diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 00000000..e7eb9261 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,28 @@ + + + +Developer's Certificate of Origin 1.1 + + By making a contribution to this project, I certify that: + + (a) The contribution was created in whole or in part by me and I + have the right to submit it under the Apache License 2.0; or + + (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + + (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + + (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. + diff --git a/.gitignore b/.gitignore index b6af165f..4e4da7a6 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,16 @@ bin/copy.sh .vagrant/ .DS_Store *.log +*.csr +*.crt +*.key lcm/coord/tmp.etcd tmp .venv/ +.idea/ +venv/ +bin/dind_scripts/config.json +bin/dind_scripts/go1.10.1.linux-amd64.tar.gz +bin/dind_scripts/helm-v2.8.2-linux-amd64.tar.gz +bin/dind_scripts/linux-amd64/ +FfDL.iml diff --git a/.helmignore b/.helmignore index 0cc12eb1..ed3db847 100644 --- a/.helmignore +++ b/.helmignore @@ -15,3 +15,16 @@ Makefile README.md .venv tmp +docs/ +metrics/ +demos/ +samples/ +cli/ +community/ +persistentvol/ +design/ +demos/ +list/ +mybucket/ +persistentvol/ +storage-plugin/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 067c7a01..e5afa1fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,14 +31,24 @@ script: # fail fast - set -e - export MAKE_ARGS=--no-print-directory + # Open SSH + # - echo travis:$sshpassword | sudo chpasswd + # - sudo sed -i 's/ChallengeResponseAuthentication no/ChallengeResponseAuthentication yes/' /etc/ssh/sshd_config + # - sudo service ssh restart + # - sudo apt-get install sshpass + # - sshpass -p $sshpassword ssh -R 9999:localhost:22 -o StrictHostKeyChecking=no travis@$bouncehostip # compile and build Docker images - glide -q install + - make $MAKE_ARGS docker-build-base + - make $MAKE_ARGS gen-certs - make $MAKE_ARGS build - make $MAKE_ARGS docker-build + - make $MAKE_ARGS docker-tag-local + - make $MAKE_ARGS create-volumes # deploy services - make $MAKE_ARGS deploy # submit a test job - - make $MAKE_ARGS test-submit + - make $MAKE_ARGS test-submit-minikube-ci notifications: email: false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e94f42f4..40f5f7ae 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,14 +1,34 @@ -# Contributing - This is an open source project, and we appreciate your help! We use the GitHub issue tracker to discuss new features and non-trivial bugs. -In addition to the issue tracker, [#journeys on -Slack](https://dwopen.slack.com) is the best way to get into contact with the -project's maintainers. - To contribute code, documentation, or tests, please submit a pull request to -the GitHub repository. Generally, we expect two maintainers to review your pull +the GitHub repository. The pull request template includes a disclaimer based +on the [Developer's Certificate of Origin 1.1](https://elinux.org/Developer_Certificate_Of_Origin) +and provides your assurance to the community that you wrote the code you are +contributing or have the right to pass on the code that you are contributing. + +Please follow the guidelines specified in [MAINTAINERS](MAINTAINERS.md) before +submitting your pull request. + +Generally, we expect two maintainers to review your pull request before it is approved for merging. For more details, see the [MAINTAINERS](MAINTAINERS.md) page. + +## Contributors + +Below is an (incomplete) list of people (in alphabetical order) who contributed to this project +via code, tests, or documentation: + +* Scott Boag +* Parijat Dube +* Benjamin Herta +* Waldemar Hummer +* Vatche Ishakian +* Michael Kalantar +* Tommy Li +* Vinod Muthusamy +* Falk Pollok +* Florian Rosenberg +* Animesh Singh +* Atin Sood diff --git a/Chart.yaml b/Chart.yaml index 251279e7..6b29a9a5 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -1,4 +1,4 @@ name: ffdl description: Fabric for Deep Learning (FfDL) -version: 0.1.0 -appVersion: 3.3 \ No newline at end of file +version: 0.1.1 +appVersion: 3.3 diff --git a/LICENSE b/LICENSE index 261eeb9e..22de1d99 100644 --- a/LICENSE +++ b/LICENSE @@ -199,3 +199,68 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + + ---------------------------------------------------------------------------- + + File : restapi/middleware/response_writer.go + Source : https://github.com/urfave/negroni/blob/master/response_writer.go + + The MIT License (MIT) + + Copyright (c) 2014 Jeremy Saenz + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + ---------------------------------------------------------------------------- + Font Awesome: dashboard/src/assets/font-awesome + + Font Awesome Free License + ------------------------- + + Font Awesome Free is free, open source, and GPL friendly. You can use it for + commercial projects, open source projects, or really almost whatever you want. + Full Font Awesome Free license: https://fontawesome.com/license. + + # Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/) + In the Font Awesome Free download, the CC BY 4.0 license applies to all icons + packaged as SVG and JS file types. + + # Fonts: SIL OFL 1.1 License (https://scripts.sil.org/OFL) + In the Font Awesome Free download, the SIL OLF license applies to all icons + packaged as web and desktop font files. + + # Code: MIT License (https://opensource.org/licenses/MIT) + In the Font Awesome Free download, the MIT license applies to all non-font and + non-icon files. + + # Attribution + Attribution is required by MIT, SIL OLF, and CC BY licenses. Downloaded Font + Awesome Free files already contain embedded comments with sufficient + attribution, so you shouldn't need to do anything additional when using these + files normally. + + We've kept attribution comments terse, so we ask that you do not actively work + to remove them from files, especially code. They're a great way for folks to + learn about Font Awesome. + + # Brand Icons + All brand icons are trademarks of their respective owners. The use of these + trademarks does not indicate endorsement of the trademark holder by Font + Awesome, nor vice versa. **Please do not use brand logos for any purpose except + to represent the company, product, or service to which they refer.** diff --git a/MAINTAINERS.md b/MAINTAINERS.md index e3413218..e936e068 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -1,12 +1,19 @@ # Maintainers Guide -This guide is intended for maintainers - anybody with commit access to one or -more Code Pattern repositories. +Following is the current list of maintainers on this project + +The maintainers are listed in alphabetical order. + +- Scott Boag ([sboagibm](https://github.com/sboagibm)) +- Waldemar Hummer ([whummer](https://github.com/whummer)) +- Tommy Li ([Tomcli](https://github.com/Tomcli)) +- Falk Pollok ([fplk](https://github.com/fplk)) +- Animesh Singh ([animeshsingh](https://github.com/animeshsingh)) ## Methodology This repository does not have a traditional release management cycle, but -should instead be maintained as as a useful, working, and polished reference at +should instead be maintained as a useful, working, and polished reference at all times. While all work can therefore be focused on the master branch, the quality of this branch should never be compromised. diff --git a/Makefile b/Makefile index 30c5f384..f5ab29ef 100644 --- a/Makefile +++ b/Makefile @@ -4,23 +4,48 @@ UNAME_SHORT = $(shell if [ "$(UNAME)" = "Darwin" ]; then echo 'osx'; else echo ' SERVICES = metrics lcm trainer restapi jobmonitor IMAGES = metrics lcm trainer restapi jobmonitor controller databroker_objectstorage databroker_s3 THIS_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) -DOCKER_REPO = docker.io -DOCKER_NAMESPACE = ffdl +HELM_DEPLOY_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))helmdeploy +DOCKER_REPO ?= docker.io +DOCKER_REPO_USER ?= user-test +DOCKER_REPO_PASS ?= test +DOCKER_REPO_DIR ?= ~/docker-registry/ +DOCKER_NAMESPACE ?= ffdl +DOCKER_PULL_POLICY ?= IfNotPresent +DLAAS_LEARNER_REGISTRY ?= ${DOCKER_REPO}/${DOCKER_NAMESPACE} INVENTORY ?= ansible/envs/local/minikube.ini IMAGE_NAME_PREFIX = ffdl- -IMAGE_TAG ?= latest +WHOAMI ?= $(shell whoami) +IMAGE_TAG ?= user-$(WHOAMI) TEST_SAMPLE ?= tf-model -# VM_TYPE is "vagrant" or "minikube" -VM_TYPE ?= vagrant +# VM_TYPE is "vagrant", "minikube" or "none" +VM_TYPE ?= minikube +HAS_STATIC_VOLUMES?=false TEST_USER = test-user SET_LOCAL_ROUTES ?= 0 MINIKUBE_RAM ?= 4096 MINIKUBE_CPUS ?= 3 -MINIKUBE_DRIVER ?= xhyve +MINIKUBE_DRIVER ?= hyperkit MINIKUBE_BRIDGE ?= $(shell (ifconfig | grep -e "^bridge100:" || ifconfig | grep -e "^bridge0:") | sed 's/\(.*\):.*/\1/') UI_REPO = git@github.com:IBM/FfDL-dashboard.git CLI_CMD = $(shell pwd)/cli/bin/ffdl-$(UNAME_SHORT) CLUSTER_NAME ?= mycluster +PUBLIC_IP ?= 127.0.0.1 +CI_MINIKUBE_VERSION ?= v0.25.1 +CI_KUBECTL_VERSION ?= v1.9.4 +NAMESPACE ?= default + +AWS_ACCESS_KEY_ID ?= test +AWS_SECRET_ACCESS_KEY ?= test +AWS_URL ?= http:\/\/s3\.default\.svc\.cluster\.local + +# This will used for "volume.beta.kubernetes.io/storage-class" for the shared volume +# Most likely "standard" in Minikube and "" in DIND, (other value is "default" or "ibmc-s3fs-standard") +# Use export SHARED_VOLUME_STORAGE_CLASS="ibmc-file-gold" for IBM Cloud deployment +ifeq ($(VM_TYPE),minikube) +SHARED_VOLUME_STORAGE_CLASS ?= "standard" +else +SHARED_VOLUME_STORAGE_CLASS ?= "" +endif IMAGE_DIR := $(IMAGE_NAME) ifneq ($(filter $(IMAGE_NAME),controller ),) @@ -33,36 +58,304 @@ ifeq ($(IMAGE_NAME),databroker_s3) IMAGE_DIR := databroker/s3 endif +TARGET ?= $(shell uname -m) +ARCHS ?= x86_64 ppc64le + +IMAGE_NAME_TARGET = -$(TARGET) # Main targets +showvars: + @echo THIS_DIR=$(THIS_DIR); \ + echo DEPLOY_DIR=$(DEPLOY_DIR) + + usage: ## Show this help @fgrep -h " ## " $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//' build: ## Build the code for all services build: $(addprefix build-, $(SERVICES)) +docker-build-images: $(addprefix docker-build-, $(IMAGES)) + docker-build: ## Build the Docker images for all services -docker-build: docker-build-base $(addprefix docker-build-, $(IMAGES)) docker-build-ui docker-build-logcollectors +docker-build: docker-build-base docker-build-images docker-build-ui docker-build-logcollectors + +docker-create-manifest: + @if [ "${DOCKER_REPO}" = "docker.io" ]; then \ + docker login --username="${DOCKER_REPO_USER}" --password="${DOCKER_REPO_PASS}"; \ + else \ + docker login --username="${DOCKER_REPO_USER}" --password="${DOCKER_REPO_PASS}" https://${DOCKER_REPO}; \ + fi \ + for image in $$(docker images --format '{{.Repository}}:{{.Tag}}' | grep -e '${DOCKER_REPO}\/${DOCKER_NAMESPACE}.*-${TARGET}:${IMAGE_TAG}' | grep -v ''); do \ + manifest_list=`echo $$image | sed -e "s/\(.*\)-${TARGET}\(:.*\)$$/\1\2/g"`; \ + echo "Creating manifest for $manifest_list"; \ + AMEND=""; \ + docker manifest inspect $$manifest_list > /dev/null 2>&1; \ + if [ $$? -eq 0 ]; then \ + AMEND="--amend"; \ + fi; \ + # lookup for other architectures \ + other_arch_images=""; \ + for arch in ${ARCHS}; do \ + if [ "$$arch" != "${TARGET}" ]; then \ + arch_image=`echo $$image | sed -e "s/\(.*\)-${TARGET}\(:.*\)$$/\1\-$$arch\2/g"`; \ + other_arch_images="$$other_arch_image $$arch_image"; \ + fi; \ + done; \ + docker manifest create $$AMEND $$manifest_list $$image $$other_arch_images ${DOCKER_CREATE_MANIFEST_OPTS}; \ + docker manifest push $$manifest_list ${DOCKER_CREATE_MANIFEST_OPTS}; \ + done + +docker-tag-local: + if [ "$(VM_TYPE)" = "minikube" ]; then \ + eval $(minikube docker-env); \ + fi; \ + for image in $$(docker images --format '{{.Repository}}:{{.Tag}}' | grep -e '${DOCKER_NAMESPACE}.*\-${TARGET}:${IMAGE_TAG}' | grep -v ''); do \ + image_name=`echo $$image | sed -e "s/\(.*\)-${TARGET}\(:.*\)$$/\1\2/g"`; \ + echo "docker tag $$image $$image_name"; \ + docker tag $$image $$image_name; \ + done \ + +docker-push: + @if [ -z "${DOCKER_REPO_USER}" ] || [ -z "${DOCKER_REPO_PASS}" ] ; then \ + echo "Please define DOCKER_REPO_USER and DOCKER_REPO_PASS."; \ + exit 1; \ + else \ + if [ "${DOCKER_REPO}" = "docker.io" ]; then \ + docker login --username="${DOCKER_REPO_USER}" --password="${DOCKER_REPO_PASS}"; \ + else \ + docker login --username="${DOCKER_REPO_USER}" --password="${DOCKER_REPO_PASS}" https://${DOCKER_REPO}; \ + fi; \ + for i in $$(docker images --format '{{.Repository}}:{{.Tag}}' | grep -e '${DOCKER_REPO}\/${DOCKER_NAMESPACE}.*\-${TARGET}:${IMAGE_TAG}' | grep -v ''); do \ + echo "docker push $$i"; \ + docker push $$i; \ + done; \ + fi + +# TODO: setup-registry + +create-registry: + @kubectl config set-context $$(kubectl config current-context) --namespace=$$NAMESPACE + @kubectl create secret docker-registry regcred --docker-server=${DOCKER_REPO} --docker-username="${DOCKER_REPO_USER}" --docker-password="${DOCKER_REPO_PASS}" --docker-email=unknown@docker.io ; \ + cd ${DOCKER_REPO_DIR} ; \ + docker-compose up -d + +# TODO Need to iterate over PVCs - currently only deletes static-volume-1 +create-volumes: + @kubectl delete --ignore-not-found=true pv/nfs pvc/static-volume-1 cm/static-volumes + @cd bin; \ + ./create_static_pv.sh; \ + ./create_static_volumes.sh; \ + ./create_static_volumes_config.sh + +deploy-plugin: + @# deploy the stack via helm + @echo Deploying services to Kubernetes. This may take a while. + @if ! helm list > /dev/null 2>&1; then \ + echo 'Installing helm/tiller'; \ + helm init > /dev/null 2>&1; \ + sleep 5; \ + echo "Waiting tiller to be ready"; \ + while ! (kubectl get pods --all-namespaces | grep tiller-deploy | grep '1/1' > /dev/null); \ + do \ + sleep 1; \ + done; \ + fi; + @existingPlugin=$$(helm list | grep ibmcloud-object-storage-plugin | awk '{print $$1}' | head -n 1); + @kubectl config set-context $$(kubectl config current-context) --namespace=$$NAMESPACE + @if [ "$(VM_TYPE)" = "dind" ]; then \ + export FFDL_PATH=$$(pwd); \ + ./bin/s3_driver.sh; \ + sleep 10; \ + (if [ -z "$$existingPlugin" ]; then \ + helm install --set dind=true,cloud=false,namespace=$$NAMESPACE storage-plugin; \ + else \ + helm upgrade --set dind=true,cloud=false,namespace=$$NAMESPACE $$existingPlugin storage-plugin; \ + fi) & pid=$$!; \ + else \ + (if [ -z "$$existingPlugin" ]; then \ + helm install --set namespace=$$NAMESPACE storage-plugin; \ + else \ + helm upgrade --set namespace=$$NAMESPACE $$existingPlugin storage-plugin; \ + fi) & pid=$$!; \ + fi; + @echo "Wait while kubectl get pvc shows static-volume-1 in state Pending" + @./bin/create_static_volumes.sh + @./bin/create_static_volumes_config.sh + @sleep 3 + +quickstart-deploy: + @echo "collecting existing pods" + @kubectl config set-context $$(kubectl config current-context) --namespace=$$NAMESPACE + @while kubectl get pods --all-namespaces | \ + grep -v RESTARTS | \ + grep -v Running | \ + grep 'alertmanager\|etcd0\|lcm\|restapi\|trainer\|trainingdata\|ui\|mongo\|prometheus\|pushgateway\|storage' > /dev/null; \ + do \ + sleep 1; \ + done + @echo "calling big command from quickstart-deploy " + @sleep 5; + @set -o verbose; \ + existing=$$(helm list | grep ffdl | awk '{print $$1}' | head -n 1); \ + (if [ -z "$$existing" ]; then \ + echo "Deploying the stack via Helm. This will take a while."; \ + helm install --set lcm.shared_volume_storage_class=$$SHARED_VOLUME_STORAGE_CLASS,namespace=$$NAMESPACE . ; \ + sleep 10; \ + else \ + echo "Upgrading existing Helm deployment ($$existing). This will take a while."; \ + helm upgrade --set lcm.shared_volume_storage_class=$$SHARED_VOLUME_STORAGE_CLASS,namespace=$$NAMESPACE $$existing . ; \ + fi) & pid=$$!; \ + sleep 5; \ + while kubectl get pods --all-namespaces | \ + grep -v RESTARTS | \ + grep -v Running | \ + grep 'alertmanager\|etcd0\|lcm\|restapi\|trainer\|trainingdata\|ui\|mongo\|prometheus\|pushgateway\|storage'; \ + do \ + sleep 5; \ + done; \ + existing=$$(helm list | grep ffdl | awk '{print $$1}' | head -n 1); \ + for i in $$(seq 1 10); do \ + status=`helm status $$existing | grep STATUS:`; \ + echo $$status; \ + if echo "$$status" | grep "DEPLOYED" > /dev/null; then \ + kill $$pid > /dev/null 2>&1; \ + exit 0; \ + fi; \ + sleep 3; \ + done; \ + exit 0 + @echo done with big command + @echo Initializing... + @# wait for pods to be ready + @while kubectl get pods --all-namespaces | \ + grep -v RESTARTS | \ + grep -v Running | \ + grep 'alertmanager\|etcd0\|lcm\|restapi\|trainer\|trainingdata\|ui\|mongo\|prometheus\|pushgateway\|storage' > /dev/null; \ + do \ + sleep 5; \ + done + @if [ "$(VM_TYPE)" = "dind" ]; then \ + ./bin/dind-port-forward.sh; \ + fi; + @echo initialize monitoring dashboards + @if [ "$$CI" != "true" ]; then bin/grafana.init.sh; fi + @echo + @echo System status: + @make status + +test-job-submit: ## Submit test training job + @# make sure the buckets with training data exist + @echo Downloading Docker images and test training data. This may take a while. + @kubectl config set-context $$(kubectl config current-context) --namespace=$$NAMESPACE + @if [ "$(VM_TYPE)" = "minikube" ]; then \ + eval $(minikube docker-env); docker images | grep tensorflow | grep latest > /dev/null || docker pull tensorflow/tensorflow > /dev/null; \ + fi + @node_ip=$$(make --no-print-directory kubernetes-ip); \ + s3_ip=$$(make --no-print-directory kubernetes-ip); \ + s3_port=$$(kubectl get service s3 -o jsonpath='{.spec.ports[0].nodePort}'); \ + s3_url=http://$$s3_ip:$$s3_port; \ + s3_raw_url=$$s3_ip:$$s3_port; \ + echo "Submitting example training job ($(TEST_SAMPLE))"; \ + restapi_port=$$(kubectl get service ffdl-restapi -o jsonpath='{.spec.ports[0].nodePort}'); \ + restapi_url=http://$$node_ip:$$restapi_port; \ + echo S3 URL: $$s3_url REST URL: $$restapi_url; \ + export DLAAS_URL=http://$$node_ip:$$restapi_port; export DLAAS_USERNAME=$(TEST_USER); export DLAAS_PASSWORD=test; \ + echo Executing in etc/examples/$(TEST_SAMPLE): DLAAS_URL=$$DLAAS_URL DLAAS_USERNAME=$$DLAAS_USERNAME DLAAS_PASSWORD=test $(CLI_CMD) train manifest.yml . ; \ + cp etc/examples/tf-model/manifest.yml etc/examples/tf-model/manifest_testrun.yml ; \ + sed -i '' -e "s/s3.default.svc.cluster.local/$$s3_raw_url/g" etc/examples/tf-model/manifest_testrun.yml ; \ + cat etc/examples/tf-model/manifest_testrun.yml ; \ + (cd etc/examples/$(TEST_SAMPLE); pwd; $(CLI_CMD) train manifest_testrun.yml .); \ + rm -f etc/examples/tf-model/manifest_testrun.yml ; \ + echo Test job submitted. Track the status via '"'DLAAS_URL=$$DLAAS_URL DLAAS_USERNAME=$(TEST_USER) DLAAS_PASSWORD=test $(CLI_CMD) list'"'. ; \ + sleep 10; \ + (for i in $$(seq 1 50); do output=$$($(CLI_CMD) list 2>&1 | grep training-); \ + if echo $$output | grep 'FAILED'; then echo 'Job failed'; exit 1; fi; \ + if echo $$output | grep 'COMPLETED'; then echo 'Job completed'; exit 0; fi; \ + echo $$output; \ + sleep 20; \ + done; exit 1) || \ + ($(CLI_CMD) list; \ + kubectl get pods | grep learner- | awk '{print $$1}' | xargs -I '{}' kubectl describe pod '{}'; \ + kubectl get pods | grep learner- | awk '{print $$1}' | xargs -I '{}' kubectl logs '{}' -c learner; \ + exit 1); + deploy: ## Deploy the services to Kubernetes + @docker images + @echo $(DOCKER_REPO) + @echo $(DOCKER_PULL_POLICY) @# deploy the stack via helm @echo Deploying services to Kubernetes. This may take a while. - @if ! helm list > /dev/null 2>&1; then echo 'Installing helm/tiller'; helm init > /dev/null 2>&1; sleep 3; fi; - @while kubectl get pods --all-namespaces | grep -v RESTARTS | grep -v Running | grep 'alertmanager\|etcd0\|lcm\|restapi\|trainer\|trainingdata\|ui\|mongo\|prometheus\|pushgateway\|storage' > /dev/null; do sleep 1; done - @while ! (kubectl get pods --all-namespaces | grep tiller-deploy | grep '1/1' > /dev/null); do sleep 1; done - @existing=$$(helm list | grep ffdl | awk '{print $$1}' | head -n 1); \ - if [ "$$CI" = "true" ]; then export helm_params='--set prometheus.deploy=false'; fi; \ - (if [ -z "$$existing" ]; then echo "Deploying the stack via Helm. This will take a while."; helm install $$helm_params . > /dev/null; sleep 10; else \ - echo "Upgrading existing Helm deployment ($$existing). This will take a while."; helm upgrade $$helm_params $$existing . > /dev/null; fi) & pid=$$!; sleep 5; \ - while kubectl get pods --all-namespaces | grep -v RESTARTS | grep -v Running | grep 'alertmanager\|etcd0\|lcm\|restapi\|trainer\|trainingdata\|ui\|mongo\|prometheus\|pushgateway\|storage'; do sleep 5; done; \ + @if ! helm list > /dev/null 2>&1; then \ + echo 'Installing helm/tiller'; \ + helm init > /dev/null 2>&1; \ + sleep 3; \ + fi; + @echo collecting existing pods + @kubectl config set-context $$(kubectl config current-context) --namespace=$$NAMESPACE + @while kubectl get pods --all-namespaces | \ + grep -v RESTARTS | \ + grep -v Running | \ + grep 'alertmanager\|etcd0\|lcm\|restapi\|trainer\|trainingdata\|ui\|mongo\|prometheus\|pushgateway\|storage' > /dev/null; \ + do \ + sleep 1; \ + done + @echo finding out which pods are running + @while ! (kubectl get pods --all-namespaces | grep tiller-deploy | grep '1/1' > /dev/null); \ + do \ + sleep 1; \ + done + @echo calling big command + @set -o verbose; \ + echo HELM_DEPLOY_DIR: ${HELM_DEPLOY_DIR}; \ + mkdir -p ${HELM_DEPLOY_DIR}; \ + cp -rf Chart.yaml values.yaml templates ${HELM_DEPLOY_DIR}; \ + existing=$$(helm list | grep ffdl | awk '{print $$1}' | head -n 1); \ + if [ "$$CI" = "true" ]; then \ + export helm_params='--set lcm.shared_volume_storage_class=${SHARED_VOLUME_STORAGE_CLASS},has_static_volumes=${HAS_STATIC_VOLUMES},namespace=${NAMESPACE},prometheus.deploy=false,learner.docker_namespace=${DOCKER_NAMESPACE},docker.namespace=${DOCKER_NAMESPACE},learner.tag=${IMAGE_TAG},docker.pullPolicy=${DOCKER_PULL_POLICY},docker.registry=${DOCKER_REPO},trainer.version=${IMAGE_TAG},restapi.version=${IMAGE_TAG},lcm.version=${IMAGE_TAG},trainingdata.version=${IMAGE_TAG},databroker.tag=${IMAGE_TAG},databroker.version=${IMAGE_TAG},webui.version=${IMAGE_TAG}'; \ + else \ + export helm_params='--set lcm.shared_volume_storage_class=${SHARED_VOLUME_STORAGE_CLASS},has_static_volumes=${HAS_STATIC_VOLUMES},namespace=${NAMESPACE},learner.docker_namespace=${DOCKER_NAMESPACE},docker.namespace=${DOCKER_NAMESPACE},learner.tag=${IMAGE_TAG},docker.pullPolicy=${DOCKER_PULL_POLICY},docker.registry=${DOCKER_REPO},trainer.version=${IMAGE_TAG},restapi.version=${IMAGE_TAG},lcm.version=${IMAGE_TAG},trainingdata.version=${IMAGE_TAG},databroker.tag=${IMAGE_TAG},databroker.version=${IMAGE_TAG},webui.version=${IMAGE_TAG}'; \ + fi; \ + (if [ -z "$$existing" ]; then \ + echo "Deploying the stack via Helm. This will take a while."; \ + helm --debug install $$helm_params ${HELM_DEPLOY_DIR} ; \ + sleep 10; \ + else \ + echo "Upgrading existing Helm deployment ($$existing). This will take a while."; \ + helm --debug upgrade $$helm_params $$existing ${HELM_DEPLOY_DIR} ; \ + fi) & pid=$$!; \ + sleep 5; \ + while kubectl get pods --all-namespaces | \ + grep -v RESTARTS | \ + grep -v Running | \ + grep 'alertmanager\|etcd0\|lcm\|restapi\|trainer\|trainingdata\|ui\|mongo\|prometheus\|pushgateway\|storage'; \ + do \ + sleep 5; \ + done; \ existing=$$(helm list | grep ffdl | awk '{print $$1}' | head -n 1); \ - for i in $$(seq 1 10); do status=`helm status $$existing | grep STATUS:`; echo $$status; if echo "$$status" | grep "DEPLOYED" > /dev/null; then kill $$pid > /dev/null 2>&1; exit 0; fi; sleep 3; done; \ + for i in $$(seq 1 10); do \ + status=`helm status $$existing | grep STATUS:`; \ + echo $$status; \ + if echo "$$status" | grep "DEPLOYED" > /dev/null; then \ + kill $$pid > /dev/null 2>&1; \ + exit 0; \ + fi; \ + sleep 3; \ + done; \ exit 0 + @echo done with big command @echo Initializing... @# wait for pods to be ready - @while kubectl get pods --all-namespaces | grep -v RESTARTS | grep -v Running | grep 'alertmanager\|etcd0\|lcm\|restapi\|trainer\|trainingdata\|ui\|mongo\|prometheus\|pushgateway\|storage' > /dev/null; do sleep 5; done - @# initialize monitoring dashboards + @while kubectl get pods --all-namespaces | \ + grep -v RESTARTS | \ + grep -v Running | \ + grep 'alertmanager\|etcd0\|lcm\|restapi\|trainer\|trainingdata\|ui\|mongo\|prometheus\|pushgateway\|storage' > /dev/null; \ + do \ + sleep 5; \ + done + @echo initialize monitoring dashboards @if [ "$$CI" != "true" ]; then bin/grafana.init.sh; fi @echo @echo System status: @@ -73,6 +366,17 @@ undeploy: ## Undeploy the services from Kubernetes @existing=$$(helm list | grep ffdl | awk '{print $$1}' | head -n 1); \ (if [ ! -z "$$existing" ]; then echo "Undeploying the stack via helm. This may take a while."; helm delete "$$existing"; echo "The stack has been undeployed."; fi) > /dev/null; +$(addprefix undeploy-, $(SERVICES)): undeploy-%: % + @SERVICE_NAME=$< make .undeploy-service + +.undeploy-service: + @echo deleting $(SERVICE_NAME) + (kubectl delete deploy,svc,statefulset --selector=service="ffdl-$(SERVICE_NAME)") + +rebuild-and-deploy-lcm: build-lcm docker-build-lcm undeploy-lcm deploy + +rebuild-and-deploy-trainer: build-trainer docker-build-trainer undeploy-trainer deploy + status: ## Print the current system status and service endpoints @tiller=s; \ status_kube=$$(kubectl config current-context) && status_kube="Running (context '$$status_kube')" || status_kube="n/a"; \ @@ -96,37 +400,57 @@ minikube: ## Configure Minikube (local Kubernetes) ifeq ($(filter $(UNAME),Linux Darwin),) @echo "Sorry, currently only supported for Mac OS and Linux"; exit 1 endif - @which minikube > /dev/null || (echo Please install Minikube; exit 1) - @minikube ip > /dev/null 2>&1 || ( \ + @which minikube || (echo Please install Minikube; exit 1) + @sudo minikube ip 2>&1 || ( \ echo "Starting up Minikube"; \ - minikube start --insecure-registry 9.0.0.0/8 --insecure-registry 10.0.0.0/8 --cpus $(MINIKUBE_CPUS) --memory $(MINIKUBE_RAM) --vm-driver=$(MINIKUBE_DRIVER) > /dev/null; \ + sudo minikube start --insecure-registry 9.0.0.0/8 --insecure-registry 10.0.0.0/8 \ + --cpus $(MINIKUBE_CPUS) \ + --memory $(MINIKUBE_RAM) \ + --vm-driver=$(MINIKUBE_DRIVER) --apiserver-ips 127.0.0.1 --apiserver-name localhost ; \ sleep 5; \ ) - @minikube ip > /dev/null 2>&1 && ( \ + @set -o verbose; \ + sudo minikube ip 2>&1 && ( \ if [ "$(SET_LOCAL_ROUTES)" == "1" ]; then \ echo "Update local network routes, using '$(MINIKUBE_BRIDGE)' as network bridge (you may be prompted for your sudo password)"; \ if [ "$(UNAME)" == "Linux" ]; then \ sudo route -n add -net 10.0.0.0/24 gw $(minikube ip); \ elif [ "$(UNAME)" == "Darwin" ]; then \ - sudo route -n delete 10.0.0.0/24 > /dev/null 2>&1; \ - sudo route -n add 10.0.0.0/24 $$(minikube ip) > /dev/null 2>&1; \ + sudo route -n delete 10.0.0.0/24 2>&1; \ + sudo route -n add 10.0.0.0/24 $$(minikube ip) 2>&1; \ member_interface=$$(ifconfig $(MINIKUBE_BRIDGE) | grep member | awk '{print $$2}' | head -1); \ if [ "$$member_interface" != "" ]; then sudo ifconfig $(MINIKUBE_BRIDGE) -hostfilter $$member_interface; fi; \ fi; \ kubectl get configmap/kube-dns --namespace kube-system -o yaml > /tmp/kube-dns.cfg; \ - grep upstreamNameservers /tmp/kube-dns.cfg > /dev/null || (echo 'data:' >> /tmp/kube-dns.cfg; \ + grep upstreamNameservers /tmp/kube-dns.cfg || (echo 'data:' >> /tmp/kube-dns.cfg; \ echo ' upstreamNameservers: '"'"'["8.8.8.8"]'"'" >> /tmp/kube-dns.cfg); \ - kubectl replace -f /tmp/kube-dns.cfg > /dev/null; \ + kubectl replace -f /tmp/kube-dns.cfg; \ fi; \ ) minikube-undo: ## Revert changes applied by the "minikube" target (e.g., local network routes) - @minikube ip > /dev/null 2>&1 && ( \ + @sudo minikube ip > /dev/null 2>&1 && ( \ sudo route -n delete 10.0.0.0/24 > /dev/null 2>&1; \ ) || true # Build targets +gen-certs: + cd commons/certs ; \ + ./generate.sh ; \ + ./install.sh + +del-certs: + rm -rf ./metrics/docker/certs; \ + rm -rf ./metrics/log_collectors/training_data_service_client/certs; \ + rm -rf ./restapi/certs; \ + rm -rf ./lcm/certs; \ + rm -rf ./jobmonitor/certs; \ + rm -rf ./trainer/docker/certs; \ + rm -f ./commons/certs/ca.*; \ + rm -f ./commons/certs/client.*; \ + rm -f ./commons/certs/server.* + $(addprefix build-, $(SERVICES)): build-%: % @SERVICE_NAME=$< BINARY_NAME=main make .build-service @@ -147,16 +471,129 @@ $(addprefix docker-build-, $(IMAGES)): docker-build-%: % docker-build-ui: mkdir -p build; test -e dashboard || (git clone $(UI_REPO) build/ffdl-ui; ln -s build/ffdl-ui dashboard) (cd dashboard && (if [ "$(VM_TYPE)" = "minikube" ]; then eval $$(minikube docker-env); fi; \ - docker build -q -t $(DOCKER_REPO)/$(DOCKER_NAMESPACE)/$(IMAGE_NAME_PREFIX)ui .; \ - (test ! `which docker-squash` || docker-squash -t $(DOCKER_REPO)/$(DOCKER_NAMESPACE)/$(IMAGE_NAME_PREFIX)ui $(DOCKER_REPO)/$(DOCKER_NAMESPACE)/$(IMAGE_NAME_PREFIX)ui))) + UI_IMAGE_NAME=$(DOCKER_REPO)/$(DOCKER_NAMESPACE)/$(IMAGE_NAME_PREFIX)ui$(IMAGE_NAME_TARGET); \ + docker build -q --build-arg ARCH=$(TARGET) -t $$UI_IMAGE_NAME:$(IMAGE_TAG) .; \ + (test ! `which docker-squash` || docker-squash -t $$UI_IMAGE_NAME:$(IMAGE_TAG) $$UI_IMAGE_NAME))) docker-build-base: - (cd etc/dlaas-service-base; make build) + if [ "$(VM_TYPE)" = "minikube" ]; then \ + eval $$(minikube docker-env); \ + fi; \ + (cd etc/dlaas-service-base; REPO=${DOCKER_REPO}/ffdl make build) docker-build-logcollectors: - cd metrics/log_collectors && IMAGE_TAG=$(IMAGE_TAG) make build-simple_log_collector build-emetrics_file build-regex_extractor build-tensorboard-all + if [ "$(VM_TYPE)" = "minikube" ]; then \ + eval $$(minikube docker-env); \ + fi; \ + cd metrics/log_collectors && IMAGE_TAG=$(IMAGE_TAG) && make build-simple_log_collector build-emetrics_file build-regex_extractor build-tensorboard-all + -# Test targets +test-push-data-s3: ## Test + @# Pushes test data to S3 buckets. + @echo Pushing test data. + @kubectl config set-context $$(kubectl config current-context) --namespace=$$NAMESPACE + @s3_ip=$$(make --no-print-directory kubernetes-ip); \ + s3_port=$$(kubectl get service s3 -o jsonpath='{.spec.ports[0].nodePort}'); \ + s3_url=http://$$s3_ip:$$s3_port; \ + export AWS_ACCESS_KEY_ID=test; export AWS_SECRET_ACCESS_KEY=test; export AWS_DEFAULT_REGION=us-east-1; \ + s3cmd="aws --endpoint-url=$$s3_url s3"; \ + $$s3cmd mb s3://tf_training_data > /dev/null; \ + $$s3cmd mb s3://tf_trained_model > /dev/null; \ + $$s3cmd mb s3://mnist_lmdb_data > /dev/null; \ + $$s3cmd mb s3://dlaas-trained-models > /dev/null; \ + for file in t10k-images-idx3-ubyte.gz t10k-labels-idx1-ubyte.gz train-images-idx3-ubyte.gz train-labels-idx1-ubyte.gz; do \ + test -e $(TMPDIR)/$$file || wget -q -O $(TMPDIR)/$$file http://yann.lecun.com/exdb/mnist/$$file; \ + $$s3cmd cp $(TMPDIR)/$$file s3://tf_training_data/$$file > /dev/null; \ + done; \ + for phase in train test; do \ + for file in data.mdb lock.mdb; do \ + tmpfile=$(TMPDIR)/$$phase.$$file; \ + test -e $$tmpfile || wget -q -O $$tmpfile https://github.com/albarji/caffe-demos/raw/master/mnist/mnist_"$$phase"_lmdb/$$file; \ + $$s3cmd cp $$tmpfile s3://mnist_lmdb_data/$$phase/$$file > /dev/null; \ + done; \ + done; + @echo "Done uploading data to S3" + +test-push-data-hostmount: ## Test + @# Pushes test data to S3 buckets. + @echo Copying test data to host mount area + @s3_ip=$$(kubectl get po/storage-0 -o=jsonpath='{.status.hostIP}'); \ + id ; \ + echo ${HOME} ; \ + sudo mkdir /cosdata; \ + sudo mkdir /cosdata/local-dlaas-ci-tf-training-data; \ + sudo mkdir /cosdata/mnist_lmdb_data; \ + sudo mkdir /cosdata/local-dlaas-ci-trained-results-tf-training-data; \ + sudo mkdir /cosdata/local-dlaas-ci-trained-results-tf-training-data/_submitted_code; \ + sudo chmod 777 -R /cosdata ; \ + sudo apt-get install zip > /dev/null; \ + rm /cosdata/local-dlaas-ci-trained-results-tf-training-data/_submitted_code/model.zip > /dev/null; \ + (cd etc/examples/$(TEST_SAMPLE); zip -r /cosdata/local-dlaas-ci-trained-results-tf-training-data/_submitted_code/model.zip .); \ + for file in t10k-images-idx3-ubyte.gz t10k-labels-idx1-ubyte.gz train-images-idx3-ubyte.gz train-labels-idx1-ubyte.gz; do \ + test -e $(TMPDIR)/$$file || wget -q -O $(TMPDIR)/$$file http://yann.lecun.com/exdb/mnist/$$file; \ + cp $(TMPDIR)/$$file /cosdata/local-dlaas-ci-tf-training-data; \ + done; \ + for phase in train test; do \ + mkdir /cosdata/mnist_lmdb_data/$$phase; \ + for file in data.mdb lock.mdb; do \ + tmpfile=$(TMPDIR)/$$phase.$$file; \ + test -e $$tmpfile || wget -q -O $$tmpfile https://github.com/albarji/caffe-demos/raw/master/mnist/mnist_"$$phase"_lmdb/$$file; \ + cp $$tmpfile /cosdata/mnist_lmdb_data/$$phase; \ + done; \ + done; + +test-submit-minikube-run-test: ## Submit test training job + @echo Downloading Docker images + @if [ "$(VM_TYPE)" = "minikube" ]; then \ + eval $(minikube docker-env); docker images | grep tensorflow | grep latest > /dev/null || docker pull tensorflow/tensorflow > /dev/null; \ + fi + @node_ip=$$(make --no-print-directory kubernetes-ip); \ + echo "Submitting example training job ($(TEST_SAMPLE))"; \ + restapi_port=$$(kubectl get service ffdl-restapi -o jsonpath='{.spec.ports[0].nodePort}'); \ + restapi_url=http://$$node_ip:$$restapi_port; \ + echo REST URL: $$restapi_url; \ + export DLAAS_URL=http://$$node_ip:$$restapi_port; export DLAAS_USERNAME=$(TEST_USER); export DLAAS_PASSWORD=test; \ + echo Executing in etc/examples/$(TEST_SAMPLE): DLAAS_URL=$$DLAAS_URL DLAAS_USERNAME=$$DLAAS_USERNAME DLAAS_PASSWORD=test $(CLI_CMD) train manifest.yml . ; \ + sudo rm -rf /cosdata/local-dlaas-ci-trained-results-tf-training-data/model; \ + sudo rm -rf /cosdata/local-dlaas-ci-trained-results-tf-training-data/learner-1; \ + (cd etc/examples/$(TEST_SAMPLE); pwd; $(CLI_CMD) train manifest-hostmount.yml . 2>&1 | tee train.log); \ + training_id=$$(cat etc/examples/$(TEST_SAMPLE)/train.log | grep "Model ID" | cut -d " " -f 3); \ + echo Training id: $${training_id} ; \ + rm -f etc/examples/$(TEST_SAMPLE)/train.log ; \ + echo Test job submitted. Track the status via '"'DLAAS_URL=$$DLAAS_URL DLAAS_USERNAME=$(TEST_USER) DLAAS_PASSWORD=test $(CLI_CMD) list'"'. ; \ + (for i in $$(seq 1 500); do output=$$($(CLI_CMD) list 2>&1 | grep $${training_id}); \ + if echo $$output | grep 'FAILED'; then echo 'Job failed'; exit 1; fi; \ + if echo $$output | grep 'COMPLETED'; then echo 'Job completed'; exit 0; fi; \ + echo "kubectl dump objects:"; \ + kubectl get pod,pvc,pv,sc,deploy,svc,statefulset,secrets --show-all -o wide ; \ + echo "kubectl dump secrets:"; \ + kubectl get secrets -o yaml ; \ + echo "Dumping Statefulsets" ; \ + kubectl get statefulsets | grep learner- | awk '{print $$1}' | xargs -I '{}' kubectl get statefulsets '{}' -o yaml; \ + echo "================:"; \ + echo "LCM:"; \ + kubectl logs --selector=service=ffdl-lcm ; \ + echo "---------------- previous:"; \ + kubectl logs -p --selector=service=ffdl-lcm ; \ + echo "---------------- Describe:"; \ + kubectl describe pods --selector=service=ffdl-lcm ; \ + echo "================:"; \ + echo "Trainer:"; \ + kubectl get pods | grep trainer- | awk '{print $$1}' | xargs -I '{}' kubectl logs '{}'; \ + echo "Jobmonitor:"; \ + kubectl get pods | grep jobmonitor- | awk '{print $$1}' | xargs -I '{}' kubectl logs '{}'; \ + echo "Learner:"; \ + kubectl get pods | grep learner- | awk '{print $$1}' | xargs -I '{}' kubectl describe pod '{}'; \ + kubectl get pods | grep learner- | awk '{print $$1}' | xargs -I '{}' kubectl logs '{}' -c learner; \ + echo $$output; \ + sleep 60; \ + done; exit 1) || \ + ($(CLI_CMD) list; \ + kubectl get pods | grep learner- | awk '{print $$1}' | xargs -I '{}' kubectl describe pod '{}'; \ + kubectl get pods | grep learner- | awk '{print $$1}' | xargs -I '{}' kubectl logs '{}' -c learner; \ + exit 1); + +test-submit-minikube-ci: test-push-data-hostmount test-submit-minikube-run-test test-submit: ## Submit test training job @# make sure the buckets with training data exist @@ -164,53 +601,94 @@ test-submit: ## Submit test training job @if [ "$(VM_TYPE)" = "minikube" ]; then \ eval $(minikube docker-env); docker images | grep tensorflow | grep latest > /dev/null || docker pull tensorflow/tensorflow > /dev/null; \ fi + @kubectl config set-context $$(kubectl config current-context) --namespace=$$NAMESPACE @node_ip=$$(make --no-print-directory kubernetes-ip); \ + s3_ip=$$(kubectl get po/storage-0 -o=jsonpath='{.status.hostIP}'); \ s3_port=$$(kubectl get service s3 -o jsonpath='{.spec.ports[0].nodePort}'); \ - s3_url=http://$$node_ip:$$s3_port; \ - export AWS_ACCESS_KEY_ID=test; export AWS_SECRET_ACCESS_KEY=test; export AWS_DEFAULT_REGION=us-east-1; \ - s3cmd="aws --endpoint-url=$$s3_url s3"; \ - $$s3cmd mb s3://tf_training_data > /dev/null; \ - $$s3cmd mb s3://tf_trained_model > /dev/null; \ - $$s3cmd mb s3://mnist_lmdb_data > /dev/null; \ - $$s3cmd mb s3://dlaas-trained-models > /dev/null; \ - for file in t10k-images-idx3-ubyte.gz t10k-labels-idx1-ubyte.gz train-images-idx3-ubyte.gz train-labels-idx1-ubyte.gz; do \ - test -e $(TMPDIR)/$$file || wget -q -O $(TMPDIR)/$$file http://yann.lecun.com/exdb/mnist/$$file; \ - $$s3cmd cp $(TMPDIR)/$$file s3://tf_training_data/$$file > /dev/null; \ - done; \ - for phase in train test; do \ - for file in data.mdb lock.mdb; do \ - tmpfile=$(TMPDIR)/$$phase.$$file; \ - test -e $$tmpfile || wget -q -O $$tmpfile https://github.com/albarji/caffe-demos/raw/master/mnist/mnist_"$$phase"_lmdb/$$file; \ - $$s3cmd cp $$tmpfile s3://mnist_lmdb_data/$$phase/$$file > /dev/null; \ - done; \ - done; \ + ./bin/escape_for_sed.sh ${AWS_URL}; \ + s3_url=$$(./bin/escape_for_sed.sh ${AWS_URL}); \ + echo "s3_url=$${s3_url}"; \ echo "Submitting example training job ($(TEST_SAMPLE))"; \ restapi_port=$$(kubectl get service ffdl-restapi -o jsonpath='{.spec.ports[0].nodePort}'); \ + restapi_url=http://$$node_ip:$$restapi_port; \ + echo S3 URL: $$s3_url REST URL: $$restapi_url; \ export DLAAS_URL=http://$$node_ip:$$restapi_port; export DLAAS_USERNAME=$(TEST_USER); export DLAAS_PASSWORD=test; \ - (cd etc/examples/$(TEST_SAMPLE); $(CLI_CMD) train manifest.yml .); \ + echo Executing in etc/examples/$(TEST_SAMPLE): DLAAS_URL=$$DLAAS_URL DLAAS_USERNAME=$$DLAAS_USERNAME DLAAS_PASSWORD=test $(CLI_CMD) train manifest-for-test.yml . ; \ + cp etc/examples/tf-model/manifest-for-test.yml etc/examples/tf-model/manifest_testrun.yml ; \ + sed -i -e "s/user_name: test/user_name: ${AWS_ACCESS_KEY_ID}/g" etc/examples/tf-model/manifest_testrun.yml ; \ + sed -i -e "s/password: test/password: ${AWS_SECRET_ACCESS_KEY}/g" etc/examples/tf-model/manifest_testrun.yml ; \ + sed -i "s/auth_url:\stest/auth_url: $${s3_url}/g" etc/examples/tf-model/manifest_testrun.yml ; \ + # cat etc/examples/tf-model/manifest_testrun.yml ; \ + (cd etc/examples/$(TEST_SAMPLE); pwd; $(CLI_CMD) train manifest_testrun.yml . 2>&1 | tee train.log); \ + training_id=$$(cat etc/examples/$(TEST_SAMPLE)/train.log | grep "Model ID" | cut -d " " -f 3); \ + echo Training id: $${training_id} ; \ + rm -f etc/examples/$(TEST_SAMPLE)/train.log ; \ + rm -f etc/examples/$(TEST_SAMPLE)/manifest_testrun.yml ; \ echo Test job submitted. Track the status via '"'DLAAS_URL=$$DLAAS_URL DLAAS_USERNAME=$(TEST_USER) DLAAS_PASSWORD=test $(CLI_CMD) list'"'. ; \ sleep 10; \ - (for i in $$(seq 1 25); do output=$$($(CLI_CMD) list 2>&1 | grep training-); \ + (for i in $$(seq 1 500); do output=$$($(CLI_CMD) list 2>&1 | grep $${training_id}); \ if echo $$output | grep 'FAILED'; then echo 'Job failed'; exit 1; fi; \ if echo $$output | grep 'COMPLETED'; then echo 'Job completed'; exit 0; fi; \ echo $$output; \ sleep 20; \ - done; exit 1) || \ - ($(CLI_CMD) list; \ - kubectl get pods | grep learner- | awk '{print $$1}' | xargs -I '{}' kubectl describe pod '{}'; \ - kubectl get pods | grep learner- | awk '{print $$1}' | xargs -I '{}' kubectl logs '{}' -c learner; \ - kubectl get pods | grep learner- | awk '{print $$1}' | xargs -I '{}' kubectl logs '{}' -c load-data; \ - exit 1); + done; exit 1) || \ + ($(CLI_CMD) list; \ + kubectl get pods | grep learner- | awk '{print $$1}' | xargs -I '{}' kubectl describe pod '{}'; \ + kubectl get pods | grep learner- | awk '{print $$1}' | xargs -I '{}' kubectl logs '{}' -c learner; \ + exit 1); + +test-localmount-submit: ## Submit test training job + @# make sure the buckets with training data exist + @echo Downloading Docker images and test training data. This may take a while. + @if [ "$(VM_TYPE)" = "minikube" ]; \ + then \ + echo "Checking if we have a tensorflow image, and maybe pulling..."; \ + eval $(minikube docker-env); \ + docker images | grep tensorflow | grep latest > /dev/null || docker pull tensorflow/tensorflow > /dev/null; \ + echo "Done checking if we have a tensorflow image"; \ + fi + @node_ip=$$(make --no-print-directory kubernetes-ip); \ + echo "Submitting example training job ($(TEST_SAMPLE))"; \ + restapi_port=$$(kubectl get service ffdl-restapi -o jsonpath='{.spec.ports[0].nodePort}'); \ + export DLAAS_URL=http://$$node_ip:$$restapi_port; export DLAAS_USERNAME=$(TEST_USER); export DLAAS_PASSWORD=test; \ + (cd etc/examples/$(TEST_SAMPLE); $(CLI_CMD) train manifest-hostmount.yml .); \ + echo Test job submitted. Track the status via '"'DLAAS_URL=$$DLAAS_URL DLAAS_USERNAME=$(TEST_USER) DLAAS_PASSWORD=test $(CLI_CMD) list'"'. ; \ + sleep 10; \ + for i in $$(seq 1 50); do output=$$($(CLI_CMD) list 2>&1 | grep training-); \ + if echo $$output | grep 'FAILED'; then echo 'Job failed'; exit 1; fi; \ + if echo $$output | grep 'COMPLETED'; then echo 'Job completed'; exit 0; fi; \ + echo $$output; \ + sleep 20; \ + done; + +# || \ +# ($(CLI_CMD) list; \ +# kubectl get pods | grep learner- | awk '{print $$1}' | xargs -I '{}' kubectl describe pod '{}'; \ +# kubectl get pods | grep learner- | awk '{print $$1}' | xargs -I '{}' kubectl logs '{}' -c learner; \ +# exit 0); # Helper targets +test-s3: + node_ip=$$(make --no-print-directory kubernetes-ip); \ + s3_port=$$(kubectl get service s3 -o jsonpath='{.spec.ports[0].nodePort}'); \ + s3_url=http://$$node_ip:$$s3_port; \ + s3_url=${AWS_URL}; \ + export AWS_DEFAULT_REGION=us-west-1; \ + s3cmd="aws --endpoint-url=${AWS_URL} s3" ; \ + $$s3cmd ls + + .build-service: (cd ./$(SERVICE_NAME)/ && (test ! -e main.go || CGO_ENABLED=0 GOOS=linux go build -ldflags "-s -w" -a -installsuffix cgo -o bin/$(BINARY_NAME))) .docker-build: - (full_img_name=$(IMAGE_NAME_PREFIX)$(IMAGE_NAME); \ - cd ./$(IMAGE_DIR)/ && (if [ "$(VM_TYPE)" = "minikube" ]; then eval $$(minikube docker-env); fi; \ - docker build -q -t $(DOCKER_REPO)/$(DOCKER_NAMESPACE)/$$full_img_name .)) + (full_img_name=$(IMAGE_NAME_PREFIX)$(IMAGE_NAME)$(IMAGE_NAME_TARGET); \ + cd ./$(IMAGE_DIR)/ && ( \ + if [ "$(VM_TYPE)" = "minikube" ]; then \ + eval $$(minikube docker-env); \ + fi; \ + docker build -q --build-arg ARCH=$(TARGET) -t $(DOCKER_REPO)/$(DOCKER_NAMESPACE)/$$full_img_name:$(IMAGE_TAG) .)) kubernetes-ip: @if [ "$$CI" = "true" ]; then kubectl get nodes -o jsonpath='{ .items[0].status.addresses[?(@.type=="InternalIP")].address }'; \ @@ -222,13 +700,17 @@ kubernetes-ip: echo $$(minikube ip); \ elif [ "$(VM_TYPE)" = "ibmcloud" ]; then \ echo $$(bx cs workers $(CLUSTER_NAME) | grep Ready | awk '{ print $$2;exit }'); \ + elif [ "$(VM_TYPE)" = "none" ]; then \ + echo "$(PUBLIC_IP)"; \ + else \ + echo "$(PUBLIC_IP)"; \ fi install-minikube-in-ci: @echo "Starting local kubernetes cluster (minikube)" - @curl -s -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v1.7.0/bin/linux/amd64/kubectl && \ + @curl -s -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/$(CI_KUBECTL_VERSION)/bin/linux/amd64/kubectl && \ chmod +x kubectl && sudo mv kubectl /usr/local/bin/ - @curl -s -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && \ + @curl -s -Lo minikube https://storage.googleapis.com/minikube/releases/$(CI_MINIKUBE_VERSION)/minikube-linux-amd64 && \ chmod +x minikube && sudo mv minikube /usr/local/bin/ @sudo minikube start --vm-driver=none @minikube update-context diff --git a/NOTICE b/NOTICE new file mode 100644 index 00000000..cd4d3faf --- /dev/null +++ b/NOTICE @@ -0,0 +1,10 @@ +FfDL - Fabric for Deep Learning +Copyright 2017-2018 IBM Corporation + +This product includes MNIST cafe2-model example +Copyright (c) 2016-present, Facebook, Inc. + +This product includes MNIST tf-summary-model example +Copyright 2015 The TensorFlow Authors. All Rights Reserved. + + diff --git a/README-cn.md b/README-cn.md new file mode 100644 index 00000000..b904bc08 --- /dev/null +++ b/README-cn.md @@ -0,0 +1,373 @@ +*阅读本文的其他语言版本:[English](README.md)。* + +[![构建状态](https://travis-ci.org/IBM/FfDL.svg?branch=master)](https://travis-ci.org/IBM/FfDL) + +# Fabric for Deep Learning (FfDL) + +该存储库包含 *FfDL* (Fabric for Deep Learning) 平台的核心服务。FfDL 是深度学习的操作系统“结构” + +FfDL 是一种协作平台,用于实现以下目的: +- 在分布式硬件上独立于框架对深度学习模型进行训练 +- 开放深度学习 API +- 提供通用度量工具 +- 运行在用户的私有云或公共云中托管的深度学习 + +![ffdl-architecture](docs/images/ffdl-architecture.png) + +要了解有关架构详情的更多信息,请阅读[此处](design/design_docs.md) + +## 前提条件 + +* `kubectl`:Kubernetes 命令行界面 (https://kubernetes.io/docs/tasks/tools/install-kubectl/) + +* `helm`:Kubernetes 软件包管理器 (https://helm.sh) + +* `docker`:Docker 命令行界面 (https://www.docker.com/) + +* `S3 CLI`:用于配置对象存储的[命令行界面](https://aws.amazon.com/cli/) + +* 一个现有的 Kubernetes 集群(例如,进行本地测试的 [Minikube](https://github.com/kubernetes/minikube))。对于 Minikube,使用 `make minikube` 命令来启动 Minikube,并设置本地网络路由。Minikube **v0.25.1** 已经过 Travis CI 的测试。 + +* 遵照相应的操作说明,使用 [IBM Cloud Public](https://github.com/IBM/container-journey-template/blob/master/README.md) 或 [IBM Cloud Private](https://github.com/IBM/deploy-ibm-cloud-private/blob/master/README.md) 支持 Kubernetes 集群 + +* FfDL 的最小推荐容量为 4GB 内存和 3 个 CPU。 + +## 使用方案 + +* 如果您已经快速入门并熟悉运用 FfDL 部署,便可跳至 [FfDL 用户指南](docs/user-guide.md),利用 FfDL 训练深度学习模型。 + +* 如果您已配置 FfDL 来使用 GPU,并且希望利用 GPU 进行训练,请遵照[此处](docs/gpu-guide.md)的这些步骤 + +* 如果您已使用 FfDL 来训练模型,并且希望使用支持 GPU 的公共云托管服务进行进一步的训练和维护,请遵照此处的[操作说明](etc/converter/ffdl-wml.md),使用 [Watson Studio 深度学习](https://www.ibm.com/cloud/deep-learning)服务来训练和维护模型 + +* 如果您刚开始学习,并且希望设置自己的 FfDL 部署,请遵照以下步骤。 + +## 步骤 + +1. [快速入门](#1-quick-start) + - 1.1 [使用 Minikube 进行安装](#11-installation-using-minikube) + - 1.2 [使用 Kubernetes 集群进行安装](#12-installation-using-kubernetes-cluster) + - 1.3 [使用 IBM Cloud Kubernetes 集群进行安装](#13-installation-using-ibm-cloud-kubernetes-cluster) +2. [测试](#2-test) +3. [监视](#3-monitoring) +4. [开发](#4-development) +5. [详细的安装说明](#5-detailed-installation-instructions) +6. [详细的测试说明](#6-detailed-testing-instructions) + - 6.1 [使用 FfDL 本地 S3 对象存储](#61-using-ffdl-local-s3-based-object-storage) + - 6.2 [使用云对象存储](#62-using-cloud-object-storage) +7. [清理](#7-clean-up) +8. [故障排除](#8-troubleshooting) +9. [参考资料](#9-references) + +## 1. 快速入门 + +可通过多种安装路径在本地(“一键式安装”)或现有的 Kubernetes 集群中安装 FfDL。 + +> 注意:如果您的 Kubernetes 集群版本是 1.7 或更低版本,请转至 [values.yaml](values.yaml),并将 `k8s_1dot8_or_above` 更改为 **false**。 + +### 1.1 使用 Minikube 进行安装 + +如果您已在机器上安装了 Minikube,请使用以下命令来部署 FfDL 平台: +``` shell +export VM_TYPE=minikube +make minikube +make deploy +``` + +### 1.2 使用 Kubernetes 集群进行安装 + +要将 FfDL 安装到合适的 Kubernetes 集群中,请确保 `kubectl` 指向正确的名称空间,然后部署平台服务: +> 注意:对于 PUBLIC_IP,请记录一个可以访问集群的 NodePort 的集群公共 IP。 + +``` shell +export VM_TYPE=none +export PUBLIC_IP= +make deploy +``` + +### 1.3 使用 IBM Cloud Kubernetes 集群进行安装 + +要将 FfDL 安装到合适的 IBM Cloud Kubernetes 集群中,请确保 `kubectl` 指向正确的名称空间,并使用 `bx login` 登录到您的机器,然后部署平台服务: +``` shell +export VM_TYPE=ibmcloud +export CLUSTER_NAME= # Replace with your IBM Cloud Cluster Name +make deploy +``` + +## 2. 测试 + +提交本存储库中包含的训练作业简单示例(请参阅 `etc/examples` 文件夹): + +``` +make test-submit +``` + +## 3. 监视 + +该平台随附简单的 Grafana 监视仪表板。在运行 `deploy` make target 时,会打印出 URL。 + +## 4. 开发 + +请参阅[开发人员指南](docs/developer-guide.md),了解更多详细信息。 + +## 5. 详细的安装说明 + +1. 首先,克隆该存储库,并在 Kubernetes 集群上安装 Helm Tiller。 +``` shell +helm init + +# Make sure the tiller pod is Running before proceeding to the next step. +kubectl get pods --all-namespaces | grep tiller-deploy +# kube-system tiller-deploy-fb8d7b69c-pcvc2 1/1 Running +``` + +2. 现在,我们使用 helm install 来安装所有必需的 FfDL 组件。 +> 注意:如果您的 Kubernetes 集群版本是 1.7 或更低版本,请转至 [values.yaml](values.yaml),并将 `k8s_1dot8_or_above` 更改为 **false**。 + +``` shell +helm install . +``` +> 注意:如果您希望升级较早版本的 FfDL,请运行 +> `helm upgrade $(helm list | grep ffdl | awk '{print $1}' | head -n 1) .` + +在进行下一步之前,确保所有的 FfDL 组件都已安装并在运行。 +``` shell +kubectl get pods +# NAME READY STATUS RESTARTS AGE +# alertmanager-7cf6b988b9-h9q6q 1/1 Running 0 5h +# etcd0 1/1 Running 0 5h +# ffdl-lcm-65bc97bcfd-qqkfc 1/1 Running 0 5h +# ffdl-restapi-8777444f6-7jfcf 1/1 Running 0 5h +# ffdl-trainer-768d7d6b9-4k8ql 1/1 Running 0 5h +# ffdl-trainingdata-866c8f48f5-ng27z 1/1 Running 0 5h +# ffdl-ui-5bf86cc7f5-zsqv5 1/1 Running 0 5h +# mongo-0 1/1 Running 0 5h +# prometheus-5f85fd7695-6dpt8 2/2 Running 0 5h +# pushgateway-7dd8f7c86d-gzr2g 2/2 Running 0 5h +# storage-0 1/1 Running 0 5h + +helm status $(helm list | grep ffdl | awk '{print $1}' | head -n 1) | grep STATUS: +# STATUS: DEPLOYED +``` + +3. 运行以下脚本,利用来自 prometheus 的日志记录信息配置 Grafana 以监控 FfDL。 +> 注意:如果您正在使用 IBM Cloud 集群,请确保自己已通过 `bx login` 进行登录。 + +``` shell +# If your Cluster is running on Minikube, replace "ibmcloud" to "minikube" +# If your Cluster is not running on Minikube or IBM Cloud, replace "ibmcloud" to "none" +export VM_TYPE=ibmcloud + +# Replace with your IBM Cloud Cluster Name if your cluster is on IBM Cloud. +# Use export PUBLIC_IP if you are using a none VM_TYPE. A Cluster Public IP that can access your Cluster's NodePorts. +export CLUSTER_NAME= +export PUBLIC_IP= + +./bin/grafana.init.sh +``` + +4. 最后,运行以下命令来获取 Grafana、FfDL Web UI 和 FfDL REST API 端点。 +``` shell +# Note: $(make --no-print-directory kubernetes-ip) simply gets the Public IP for your cluster. +node_ip=$(make --no-print-directory kubernetes-ip) + +# Obtain all the necessary NodePorts for Grafana, Web UI, and RestAPI. +grafana_port=$(kubectl get service grafana -o jsonpath='{.spec.ports[0].nodePort}') +ui_port=$(kubectl get service ffdl-ui -o jsonpath='{.spec.ports[0].nodePort}') +restapi_port=$(kubectl get service ffdl-restapi -o jsonpath='{.spec.ports[0].nodePort}') + +# Echo statements to print out Grafana and Web UI URLs. +echo "Monitoring dashboard: http://$node_ip:$grafana_port/ (login: admin/admin)" +echo "Web UI: http://$node_ip:$ui_port/#/login?endpoint=$node_ip:$restapi_port&username=test-user" +``` + +祝贺您,FfDL 现在正在您的集群上运行。现在,您可以前往[第 6 步](#6-detailed-testing-instructions)运行一些样本作业,或者前往[用户指南](docs/user-guide.md)了解如何运行和部署自定义模型。 + +## 6. 详细的测试说明 + +在本示例中,我们将运行一些简单的作业,使用 TensorFlow 和 Caffe 来训练卷积网络模型。我们将下载一系列的 MNIST 手写体数字图像,通过对象存储来存储这些图像,然后使用 FfDL CLI 训练手写体数字分类模型。 + +> 注意:对于 Minikube,请确保您通过运行 `docker pull tensorflow/tensorflow` 获得了最新的 TensorFlow Docker 镜像 + +### 6.1. 使用 FfDL 本地 S3 对象存储 + +1. 运行以下命令,从集群中获取对象存储端点。 +```shell +node_ip=$(make --no-print-directory kubernetes-ip) +s3_port=$(kubectl get service s3 -o jsonpath='{.spec.ports[0].nodePort}') +s3_url=http://$node_ip:$s3_port +``` + +2. 下一步,设置缺省的对象存储访问 ID 和 KEY。然后,创建可容纳所有必需训练数据和训练模型的存储桶。 +```shell +export AWS_ACCESS_KEY_ID=test; export AWS_SECRET_ACCESS_KEY=test; export AWS_DEFAULT_REGION=us-east-1; + +s3cmd="aws --endpoint-url=$s3_url s3" +$s3cmd mb s3://tf_training_data +$s3cmd mb s3://tf_trained_model +$s3cmd mb s3://mnist_lmdb_data +$s3cmd mb s3://dlaas-trained-models +``` + +3. 现在,创建一个临时存储库,下载用于训练和标记 TensorFlow 模型所需的图像,然后将这些图像上传到 tf_training_data 存储桶。 + +```shell +mkdir tmp +for file in t10k-images-idx3-ubyte.gz t10k-labels-idx1-ubyte.gz train-images-idx3-ubyte.gz train-labels-idx1-ubyte.gz; +do + test -e tmp/$file || wget -q -O tmp/$file http://yann.lecun.com/exdb/mnist/$file + $s3cmd cp tmp/$file s3://tf_training_data/$file +done +``` + +4. 现在,您应当在对象存储中包含了所有必需的训练数据集。我们继续为深度学习即服务设置 REST API 端点和缺省凭证。完成之后,您就可以使用 FfDL CLI(可执行的二进制文件)开始运行作业。 + +```shell +restapi_port=$(kubectl get service ffdl-restapi -o jsonpath='{.spec.ports[0].nodePort}') +export DLAAS_URL=http://$node_ip:$restapi_port; export DLAAS_USERNAME=test-user; export DLAAS_PASSWORD=test; + +# Obtain the correct CLI for your machine and run the training job with our default TensorFlow model +CLI_CMD=$(pwd)/cli/bin/ffdl-$(if [ "$(uname)" = "Darwin" ]; then echo 'osx'; else echo 'linux'; fi) +$CLI_CMD train etc/examples/tf-model/manifest.yml etc/examples/tf-model +``` + +祝贺您,您已在 FfDL 上提交了第一个作业。从 FfDL UI 或仅需运行 `$CLI_CMD list` 即可检查 FfDL 状态。 + +> 您可以通过[用户指南](docs/user-guide.md#2-create-new-models-with-ffdl),学习如何创建自己的模型定义文件和 `manifest.yaml`。 + +5. 如果您希望通过 FfDL UI 运行作业,只需运行以下命令来创建自己的模型 zip 文件。 + +```shell +# Replace tf-model with the model you want to zip +pushd etc/examples/tf-model && zip ../tf-model.zip * && popd +``` + +然后,在 `etc/examples/` 存储库中上传 `tf-model.zip` 和 `manifest.yml`(缺省的 TensorFlow 模型),如下所示。 +接着,单击 `Submit Training Job` 运行作业。 + +![ui-example](docs/images/ui-example.png) + +6. (可选)使用 FfDL 上不同的深度学习框架来提交作业非常简单,让我们来尝试运行 Caffe 作业。为 Caffe 模型下载 [LMDB 格式](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database)的所有必需训练图像和测试图像,然后将这些图像上传到 mnist_lmdb_data 存储桶。 + +```shell +for phase in train test; +do + for file in data.mdb lock.mdb; + do + tmpfile=tmp/$phase.$file + test -e $tmpfile || wget -q -O $tmpfile https://github.com/albarji/caffe-demos/raw/master/mnist/mnist_"$phase"_lmdb/$file + $s3cmd cp $tmpfile s3://mnist_lmdb_data/$phase/$file + done +done +``` + +7. 现在开始训练 Caffe 作业。 + +```shell +$CLI_CMD train etc/examples/caffe-model/manifest.yml etc/examples/caffe-model +``` + +祝贺您,现在您已掌握如何通过不同的深度学习框架来部署作业。要了解有关作业执行结果的更多信息,只需运行 `$CLI_CMD logs ` + +> 如果不再需要我们在本例中使用的任何 MNIST 数据集,只需删除 `tmp` 存储库。 + +### 6.2. 使用云对象存储 + +在本部分中,我们将演示如何通过云对象存储中存储的训练数据运行 TensorFlow 作业。 + +> 注释:这也可以通过其他云提供商的对象存储来完成,但是在本操作说明中,我们将演示如何使用 IBM Cloud Object Storage。 + +1. 配置您的云提供商提供的 S3 对象存储。记录认证端点、访问键 ID 以及密钥。 + +> 对于 IBM Cloud,您可以从 [IBM Cloud 仪表板](https://console.bluemix.net/catalog/infrastructure/cloud-object-storage?taxonomyNavigation=apps)或从 [SoftLayer 门户网站](https://control.softlayer.com/storage/objectstorage)配置对象存储。 + +2. 使用刚刚获得的对象存储凭证设置 S3 命令。 + +```shell +s3_url=http:// +export AWS_ACCESS_KEY_ID= +export AWS_SECRET_ACCESS_KEY= + +s3cmd="aws --endpoint-url=$s3_url s3" +``` + +3. 下一步,我们来创建两个存储桶,一个用于存储训练数据,另一个用于存储训练结果。 +```shell +trainingDataBucket= +trainingResultBucket= + +$s3cmd mb s3://$trainingDataBucket +$s3cmd mb s3://$trainingResultBucket +``` + +4. 现在,创建一个临时存储库,下载用于训练和标记 TensorFlow 模型所需的图像,然后将这些图像上传到训练数据存储桶。 + +```shell +mkdir tmp +for file in t10k-images-idx3-ubyte.gz t10k-labels-idx1-ubyte.gz train-images-idx3-ubyte.gz train-labels-idx1-ubyte.gz; +do + test -e tmp/$file || wget -q -O tmp/$file http://yann.lecun.com/exdb/mnist/$file + $s3cmd cp tmp/$file s3://$trainingDataBucket/$file +done +``` + +5. 接下来,我们需要利用以下 sed 命令,修改示例作业以使用云对象存储。 +```shell +if [ "$(uname)" = "Darwin" ]; then + sed -i '' s#"tf_training_data"#"$trainingDataBucket"# etc/examples/tf-model/manifest.yml + sed -i '' s#"tf_trained_model"#"$trainingResultBucket"# etc/examples/tf-model/manifest.yml + sed -i '' s#"http://s3.default.svc.cluster.local"#"$s3_url"# etc/examples/tf-model/manifest.yml + sed -i '' s#"user_name: test"#"user_name: $AWS_ACCESS_KEY_ID"# etc/examples/tf-model/manifest.yml + sed -i '' s#"password: test"#"password: $AWS_SECRET_ACCESS_KEY"# etc/examples/tf-model/manifest.yml +else + sed -i s#"tf_training_data"#"$trainingDataBucket"# etc/examples/tf-model/manifest.yml + sed -i s#"tf_trained_model"#"$trainingResultBucket"# etc/examples/tf-model/manifest.yml + sed -i s#"http://s3.default.svc.cluster.local"#"$s3_url"# etc/examples/tf-model/manifest.yml + sed -i s#"user_name: test"#"user_name: $AWS_ACCESS_KEY_ID"# etc/examples/tf-model/manifest.yml + sed -i s#"password: test"#"password: $AWS_SECRET_ACCESS_KEY"# etc/examples/tf-model/manifest.yml +fi +``` + +6. 现在,您应当在训练数据存储桶中包含了所有必需的训练数据集。我们继续为深度学习即服务设置 REST API 端点和缺省凭证。完成之后,您就可以使用 FfDL CLI(可执行的二进制文件)开始运行作业。 + +```shell +restapi_port=$(kubectl get service ffdl-restapi -o jsonpath='{.spec.ports[0].nodePort}') +export DLAAS_URL=http://$node_ip:$restapi_port; export DLAAS_USERNAME=test-user; export DLAAS_PASSWORD=test; + +# Obtain the correct CLI for your machine and run the training job with our default TensorFlow model +CLI_CMD=cli/bin/ffdl-$(if [ "$(uname)" = "Darwin" ]; then echo 'osx'; else echo 'linux'; fi) +$CLI_CMD train etc/examples/tf-model/manifest.yml etc/examples/tf-model +``` + +## 7. 清理 +如果您希望从集群中移除 FfDL,只需使用以下命令或运行 `helm delete ` +```shell +helm delete $(helm list | grep ffdl | awk '{print $1}' | head -n 1) +``` + +## 8. 故障排除 + +* FfDL 仅在 Mac OS 和 Linux 下经过测试 + +* Mac OS 中 Minikube 的缺省驱动程序是 VirtualBox,但众所周知,该驱动程序在网络方面存在问题。我们通常建议 Mac OS 用户使用 xhyve 驱动程序来安装 Minikube。 + +* 另外,在本地测试 Minikube 时,请确保将 `docker` CLI 指向 Minikube 的 Docker 守护程序: + + ``` + eval $(minikube docker-env) + ``` +* 如果您使用 Minikube 时遇到 DNS 名称解析问题,那么确保系统仅使用 `10.0.0.10` 作为单一名称服务器。使用多个名称服务器会导致各种问题,尤其是在 Mac OS 下。 + +* 如果 `glide install` 失败,出现表示路径不存在的错误(例如,“Without src, cannot continue”),请确保遵循标准的 Go 目录布局(请参见 [前提条件部分]{#Prerequisites})。 + +* 要移除集群上的 FfDL,只需运行 `make undeploy` + +* 在使用 FfDL CLI 来训练模型时,请确保目录路径末尾不含反斜杠 `/`。 + +## 9. 参考资料 + +根据 IBM 研究院在深度学习方面的工作成果 + +* B. Bhattacharjee 等人,“IBM Deep Learning Service”,IBM Journal of Research and Development,第 61 卷,第 4 号,第 10:1-10:11 页,2017 年 7 月 - 9 月 1 日。https://arxiv.org/abs/1709.05871 + +* Scott Boag 等人,Scalable Multi-Framework Multi-Tenant Lifecycle Management of Deep Learning Training Jobs,NIPS'17 会议上有关 ML 系统的研讨会成果,2017 年。http://learningsys.org/nips17/assets/papers/paper_29.pdf diff --git a/README.md b/README.md index 6e0bf29c..0459ce67 100644 --- a/README.md +++ b/README.md @@ -1,118 +1,99 @@ -[![build status](https://travis-ci.org/IBM/FfDL.svg?branch=master)](https://travis-ci.org/IBM/FfDL) +*Read this in other languages: [中文](README-cn.md).* -# FfDL Core Services +[![build status](https://travis-ci.org/IBM/FfDL.svg?branch=master)](https://travis-ci.org/IBM/FfDL) -This repository contains the core services of the *FfDL* (Fabric for Deep Learning) platform. FfDL is an operating system "fabric" for Deep Learning +# Fabric for Deep Learning (FfDL) -FfDL is a collaboration platform for: +This repository contains the core services of the *FfDL* (Fabric for Deep Learning) platform. FfDL is an operating system "fabric" for Deep Learning. It is a collaboration platform for: - Framework-independent training of Deep Learning models on distributed hardware -- Open Deep Learning APIs   -- Common instrumentation -- Inferencing in the cloud +- Open Deep Learning APIs - Running Deep Learning hosting in user's private or public cloud -**Note:** This repository is currently work in progress, it is only used for internal testing at the moment. - -## Prerequisites - -* `kubectl`: the Kubernetes command line interface (https://kubernetes.io/docs/tasks/tools/install-kubectl/) - -* `helm`: the Kubernetes package manager (https://helm.sh) - -* `docker`: the Docker command-line interface (https://www.docker.com/) - -* `aws`: the AWS command-line interface for storing test data in a local S3 mock server - -* `wget`: the command-line interface for downloading web resources - -* An existing Kubernetes cluster (e.g., [Minikube](https://github.com/kubernetes/minikube) for local testing). - Once installed, use the command `make minikube` to start Minikube and set up local network routes. Alternatively, - use the Vagrant based setup to automatically install a local Kubernetes cluster. - -Optional: - -* `go`: a working [Go](https://golang.org/) environment is required to build the code - -* `glide`: the glide package manager for Go (https://glide.sh) +![ffdl-architecture](docs/images/ffdl-architecture.png) -* `npm`: the Node.js package manager (https://www.npmjs.com) for building the Web UI +To know more about the architectural details, please read the [design document](design/design_docs.md). If you are looking for demos, slides, collaterals, blogs, webinars and other materials related to FfDL, please [find them here](demos) -Important: - -* `Go` is very specific about directory layouts. Make sure to set your `$GOPATH` and clone this repo to a directory -`$GOPATH/src/github.com/IBM/FfDL` before proceeding with the next steps. - -* Also, when testing locally with Minikube, make sure to point the `docker` CLI to Minikube's Docker daemon: - - ``` - eval $(minikube docker-env) - ``` +## Prerequisites -* FfDL has only been tested under Mac OS and Linux (we plan to add support for Windows in the near future). +* `kubectl`: The Kubernetes command line interface (https://kubernetes.io/docs/tasks/tools/install-kubectl/) +* `helm`: The Kubernetes package manager (https://helm.sh) +* `docker`: The Docker command-line interface (https://www.docker.com/) +* `S3 CLI`: The [command-line interface](https://aws.amazon.com/cli/) to configure your Object Storage +* An existing Kubernetes cluster (e.g., [Kubeadm-DIND](https://github.com/kubernetes-sigs/kubeadm-dind-cluster#using-preconfigured-scripts) for local testing). + +* Follow the appropriate instructions for standing up your Kubernetes cluster using [IBM Cloud Public](https://github.com/IBM/container-journey-template/blob/master/README.md) or [IBM Cloud Private](https://github.com/IBM/deploy-ibm-cloud-private/blob/master/README.md) +* The minimum capacity requirement for FfDL is 4GB Memory and 3 CPUs. + +## Usage Scenarios + +* If you are getting started and want to setup your own FfDL deployment, please follow the steps [below](#1-quick-start). +* If you have a FfDL deployment up and running, you can jump to [FfDL User Guide](docs/user-guide.md) to use FfDL for training your deep learning models. +* If you want to leverage Jupyter notebooks to launch training on your FfDL cluster, please follow [these instructions](etc/notebooks/art) +* If you have FfDL confiugured to use GPUs, and want to train using GPUs, follow steps [here](docs/gpu-guide.md) +* To invoke [Adversarial Robustness Toolbox](https://github.com/IBM/adversarial-robustness-toolbox) to find vulnerabilities in your models, follow the [instructions here](etc/notebooks/art) +* To deploy your trained models, follow [the integration guide with Seldon](community/FfDL-Seldon) +* If you have used FfDL to train your models, and want to use a GPU enabled public cloud hosted service for further training and serving, please follow instructions [here](etc/converter/ffdl-wml.md) to train and serve your models using [Watson Studio Deep Learning](https://www.ibm.com/cloud/deep-learning) service. ## Steps + 1. [Quick Start](#1-quick-start) - - 1.1 [Installation using Vagrant](#11-installation-using-vagrant) - - 1.2 [Installation using Minikube](#12-installation-using-minikube) - - 1.3 [Installation using Kubernetes Cluster](#13-installation-using-kubernetes-cluster) - - 1.4 [Installation using IBM Cloud Kubernetes Cluster](#14-installation-using-ibm-cloud-kubernetes-cluster) + - 1.1 [Installation using Kubeadm-DIND](#11-installation-using-kubeadm-dind) + - 1.2 [Installation using Kubernetes Cluster](#12-installation-using-kubernetes-cluster) 2. [Test](#2-test) 3. [Monitoring](#3-monitoring) 4. [Development](#4-development) -5. [Detailed Installation Instructions](#5-detailed-installation-instructions) -6. [Detailed Testing Instructions](#6-detailed-testing-instructions) -7. [Clean Up](#7-clean-up) -8. [Troubleshooting](#8-troubleshooting) +5. [Clean Up](#7-clean-up) +6. [Troubleshooting](#8-troubleshooting) +7. [References](#9-references) ## 1. Quick Start -There are multiple installation paths for installing FfDL locally ("1-click-install") or -into an existing Kubernetes cluster. +There are multiple installation paths for installing FfDL into an existing Kubernetes cluster. Below are the steps for quick install. If you want to follow more detailed step by step instructions , please visit [the detailed installation guide](docs/detailed-installation-guide.md) -### 1.1 Installation using Vagrant +> If you are using bash shell, you can modify the necessary environment variables in `env.txt` and export all of them using the following commands +> ```shell +> source env.txt +> export $(cut -d= -f1 env.txt) +> ``` -This is the simplest and recommended option for local testing. The following commands will automatically -spin up a Vagrant box with Kubernetes and the FfDL platform deployed on top of it: -``` -export VM_TYPE=vagrant -vagrant up -make deploy -``` +### 1.1 Installation using Kubeadm-DIND -### 1.2 Installation using Minikube +If you have [Kubeadm-DIND](https://github.com/kubernetes-sigs/kubeadm-dind-cluster#using-preconfigured-scripts) installed on your machine, use these commands to deploy the FfDL platform: +``` shell +export VM_TYPE=dind +export PUBLIC_IP=localhost +export SHARED_VOLUME_STORAGE_CLASS=""; +export NAMESPACE=default # If your namespace does not exist yet, please create the namespace `kubectl create namespace $NAMESPACE` before running the make commands below -If you have Minikube installed on your machine, use these commands to deploy the FfDL platform: -``` -export VM_TYPE=minikube -make minikube -make deploy +make deploy-plugin +make quickstart-deploy ``` -### 1.3 Installation using Kubernetes Cluster +### 1.2 Installation using Kubernetes Cluster -To install FfDL to a proper Kubernetes cluster, make sure `kubectl` points to the right namespace, +To install FfDL to any proper Kubernetes cluster, make sure `kubectl` points to the right namespace, then deploy the platform services: -``` +> Note: For PUBLIC_IP, put down one of your Cluster Public IP that can access your Cluster's NodePorts. For IBM Cloud, you can get your Public IP with `bx cs workers `. + +``` shell export VM_TYPE=none -make deploy -``` +export PUBLIC_IP= +export NAMESPACE=default # If your namespace does not exist yet, please create the namespace `kubectl create namespace $NAMESPACE` before running the make commands below -### 1.4 Installation using IBM Cloud Kubernetes Cluster +# Change the storage class to what's available on your Cloud Kubernetes Cluster. +export SHARED_VOLUME_STORAGE_CLASS="ibmc-file-gold"; -To install FfDL to a proper IBM Cloud Kubernetes cluster, make sure `kubectl` points to the right namespace -and your machine is logged in with `bx login`, then deploy the platform services: -``` shell -export VM_TYPE=ibmcloud -export CLUSTER_NAME=yourClusterName # Replace yourClusterName with your IBM Cloud Cluster Name -make deploy +make deploy-plugin +make quickstart-deploy ``` ## 2. Test To submit a simple example training job that is included in this repo (see `etc/examples` folder): -``` -make test-submit +``` shell +make test-push-data-s3 +make test-job-submit ``` ## 3. Monitoring @@ -121,189 +102,49 @@ The platform ships with a simple Grafana monitoring dashboard. The URL is printe ## 4. Development -Use the following instructions if you want to run a full development build, compile the code, and build the -Docker images locally. First, fetch the dependencies via: -``` -glide install -``` - -Then compile the code and build the Docker images via: -``` -make build -make docker-build -``` - -Make sure `kubectl` points to the right target context/namespace, then deploy the services to your Kubernetes -environment (using `helm`): -``` -make deploy -``` - -## 5. Detailed Installation Instructions - -1. First, clone this repository and install the helm tiller on your Kubernetes cluster. -``` shell -helm init - -# Make sure the tiller pod is Running before proceeding to the next step. -kubectl get pods --all-namespaces | grep tiller-deploy -# kube-system tiller-deploy-fb8d7b69c-pcvc2 1/1 Running -``` - -2. Now let's install all the necessary FfDL components using helm install. -``` shell -helm install . -``` -> Note: If you want to upgrade an older version of FfDL, run -> `helm upgrade $(helm list | grep ffdl | awk '{print $1}' | head -n 1) .` - -Make sure all the FfDL components are installed and running before moving to the next step. -``` shell -kubectl get pods -# NAME READY STATUS RESTARTS AGE -# alertmanager-7cf6b988b9-h9q6q 1/1 Running 0 5h -# etcd0 1/1 Running 0 5h -# ffdl-lcm-65bc97bcfd-qqkfc 1/1 Running 0 5h -# ffdl-restapi-8777444f6-7jfcf 1/1 Running 0 5h -# ffdl-trainer-768d7d6b9-4k8ql 1/1 Running 0 5h -# ffdl-trainingdata-866c8f48f5-ng27z 1/1 Running 0 5h -# ffdl-ui-5bf86cc7f5-zsqv5 1/1 Running 0 5h -# mongo-0 1/1 Running 0 5h -# prometheus-5f85fd7695-6dpt8 2/2 Running 0 5h -# pushgateway-7dd8f7c86d-gzr2g 2/2 Running 0 5h -# storage-0 1/1 Running 0 5h - -helm status $(helm list | grep ffdl | awk '{print $1}' | head -n 1) | grep STATUS: -# STATUS: DEPLOYED -``` - -3. Run the following script to configure Grafana for monitoring FfDL using the logging information from prometheus. -> Note: If you are using a IBM Cloud Cluster, make sure you are logged in with `bx login`. - -``` shell -# If your Cluster is running on Vagrant or Minikube, replace "ibmcloud" to "vagrant" | "minikube" -export VM_TYPE=ibmcloud -# Replace yourClusterName with your IBM Cloud Cluster Name if your cluster is on IBM Cloud. -export CLUSTER_NAME=yourClusterName -./bin/grafana.init.sh -``` - -4. Lastly, run the following commands to obtain your Grafana, FfDL Web UI, and FfDL restapi endpoints. -``` shell -# Note: $(make --no-print-directory kubernetes-ip) simply gets the Public IP for your cluster. -node_ip=$(make --no-print-directory kubernetes-ip) - -# Obtain all the necessary NodePorts for Grafana, Web UI, and RestAPI. -grafana_port=$(kubectl get service grafana -o jsonpath='{.spec.ports[0].nodePort}') -ui_port=$(kubectl get service ffdl-ui -o jsonpath='{.spec.ports[0].nodePort}') -restapi_port=$(kubectl get service ffdl-restapi -o jsonpath='{.spec.ports[0].nodePort}') - -# Echo statements to print out Grafana and Web UI URLs. -echo "Monitoring dashboard: http://$node_ip:$grafana_port/ (login: admin/admin)" -echo "Web UI: http://$node_ip:$ui_port/#/login?endpoint=$node_ip:$restapi_port&username=test-user" -``` - -Congratulation, FfDL is now running on your Cluster. +Please refer to the [developer guide](docs/developer-guide.md) for more details. -## 6. Detailed Testing Instructions - -In this example, we will run some simple jobs to train a convolutional network model using TensorFlow and Caffe. We will download a set of -MNIST handwritten digit images, store them in the S3 storage pod, and use the FfDL CLI to train a handwritten digit classification model. - -> Note: For Minikube, make sure you have the latest TensorFlow Docker image by running `docker pull tensorflow/tensorflow` - -1. Run the following commands to obtain the S3 storage endpoint from your cluster. -```shell -node_ip=$(make --no-print-directory kubernetes-ip) -s3_port=$(kubectl get service s3 -o jsonpath='{.spec.ports[0].nodePort}') -s3_url=http://$node_ip:$s3_port -``` - -2. Next, set up the default S3 storage access ID and KEY. Then create S3 buckets for all the necessary training data and models. +## 5. Clean Up +If you want to remove FfDL from your cluster, simply use the following commands. ```shell -export AWS_ACCESS_KEY_ID=test; export AWS_SECRET_ACCESS_KEY=test; export AWS_DEFAULT_REGION=us-east-1; - -s3cmd="aws --endpoint-url=$s3_url s3" -$s3cmd mb s3://tf_training_data -$s3cmd mb s3://tf_trained_model -$s3cmd mb s3://mnist_lmdb_data -$s3cmd mb s3://dlaas-trained-models +helm delete $(helm list | grep ffdl | awk '{print $1}' | head -n 1) ``` - -3. Now, create a temporary repository, download the necessary images for training and labeling our TensorFlow model, and upload those images -to your S3 tf_training_data bucket. - +If you want to remove the storage driver and pvc from your cluster, run: ```shell -mkdir tmp -for file in t10k-images-idx3-ubyte.gz t10k-labels-idx1-ubyte.gz train-images-idx3-ubyte.gz train-labels-idx1-ubyte.gz; -do - test -e tmp/$file || wget -q -O tmp/$file http://yann.lecun.com/exdb/mnist/$file - $s3cmd cp tmp/$file s3://tf_training_data/$file -done +kubectl delete pvc static-volume-1 +helm delete $(helm list | grep ibmcloud-object-storage-plugin | awk '{print $1}' | head -n 1) ``` - -4. Next, let's download all the necessary training and testing images in LMDB format for our Caffe model -and upload those images to your S3 mnist_lmdb_data bucket. - +For Kubeadm-DIND, you need to kill your forwarded ports. Note that the below command will kill all the ports that are created with `kubectl`. ```shell -for phase in train test; -do - for file in data.mdb lock.mdb; - do - tmpfile=tmp/$phase.$file - test -e $tmpfile || wget -q -O $tmpfile https://github.com/albarji/caffe-demos/raw/master/mnist/mnist_"$phase"_lmdb/$file - $s3cmd cp $tmpfile s3://mnist_lmdb_data/$phase/$file - done -done +kill $(lsof -i | grep kubectl | awk '{printf $2 " " }') ``` -5. Now you should have all the necessary training data set in your S3 storage. Let's go ahead to set up your restapi endpoint -and default credentials for Deep Learning as a Service. Once you done that, you can start running jobs using the FfDL CLI(executable -binary). +## 6. Troubleshooting -```shell -restapi_port=$(kubectl get service ffdl-restapi -o jsonpath='{.spec.ports[0].nodePort}') -export DLAAS_URL=http://$node_ip:$restapi_port; export DLAAS_USERNAME=test-user; export DLAAS_PASSWORD=test; - -# Obtain the correct CLI for your machine and run the training job with our default TensorFlow model -CLI_CMD=cli/bin/ffdl-$(if [ "$(uname)" = "Darwin" ]; then echo 'osx'; else echo 'linux'; fi) -$CLI_CMD train etc/examples/tf-model/manifest.yml etc/examples/tf-model -``` - -Congratulation, you had submitted your first job on FfDL. You can check your FfDL status either from the FfDL UI or simply run `$CLI_CMD list` - -6. Since it's simple and straightforward to submit jobs with different deep learning framework on FfDL, let's try to run a Caffe Job. - -```shell -$CLI_CMD train etc/examples/caffe-model/manifest.yml etc/examples/caffe-model -``` - -Congratulation, now you know how to deploy jobs with different deep learning framework. To learn more about your job execution results, -you can simply run `$CLI_CMD logs ` +* FfDL has only been tested under Mac OS and Linux + -7. (Experimental) After you done with step 4, if you want to run your job via the FfDL UI, simply upload -`tf-model.zip` and `manifest.yml` (The default TensorFlow model) in the `etc/examples/` repository as shown below. -Then, click `Submit Training Job` to run your job. +* If `glide install` fails with an error complaining about non-existing paths (e.g., "Without src, cannot continue"), + make sure to follow the standard Go directory layout (see [Prerequisites section](#prerequisites)). -![ui-example](docs/images/ui-example.png) +* To remove FfDL on your Cluster, simply run `make undeploy` -## 7. Clean Up -If you want to remove FfDL from your cluster, simply use the command below or run `helm delete ` -```shell -helm delete $(helm list | grep ffdl | awk '{print $1}' | head -n 1) -``` +* When using the FfDL CLI to train a model, make sure your directory path doesn't have slashes `/` at the end. -## 8. Troubleshooting +* If your job is stuck in pending stage, you can try to redeploy the plugin with `helm install storage-plugin --set dind=true,cloud=false` for Kubeadm-DIND and `helm install storage-plugin` for general Kubernetes Cluster. Also, double check your training job manifest file to make sure you have the correct object storage credentials. -* The default Minikube driver under Mac OS is VirtualBox, which is known for having issues with networking. - We generally recommend Mac OS users to install Minikube using the xhyve driver. +## 7. References -* If you run into DNS name resolution issues using Minikube, make sure that the system uses only `10.0.0.10` - as the single nameserver. Using multiple nameservers can result in problems, in particular under Mac OS. +Based on IBM Research work in Deep Learning. -* If `glide install` fails with an error complaining about non-existing paths (e.g., "Without src, cannot continue"), - make sure to follow the standard Go directory layout (see [Prerequisites section]{#Prerequisites}). +* B. Bhattacharjee et al., "IBM Deep Learning Service," in IBM Journal of Research and Development, vol. 61, no. 4, pp. 10:1-10:11, July-Sept. 1 2017. https://arxiv.org/abs/1709.05871 -* To remove FfDL on your Cluster, simply run `make undeploy` +* Scott Boag, et al. Scalable Multi-Framework Multi-Tenant Lifecycle Management of Deep Learning Training Jobs, In Workshop on ML Systems at NIPS'17, 2017. http://learningsys.org/nips17/assets/papers/paper_29.pdf diff --git a/bin/addnew_march_15_2018.sh b/bin/addnew_march_15_2018.sh new file mode 100755 index 00000000..fb55f053 --- /dev/null +++ b/bin/addnew_march_15_2018.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +git add lcm/lcmconfig/lcmconfig_test.go +git add lcm/service/lcm/helper/ +git add lcm/service/lcm/learner/ +git add lcm/service/lcm/nonSplitTraining.go +git add lcm/service/lcm/policies/ +git add lcm/service/lcm/splitTraining.go +git add metrics/log_collectors/tensorboard/Dockerfile +git add metrics/log_collectors/training_data_service_client/match_log_file.py +git add metrics/log_collectors/training_data_service_client/scan_log_dirs.py +git add metrics/log_collectors/training_data_service_client/states.py +git add metrics/log_collectors/training_data_service_client/training_data_buffered.py +git add trainer/glide.yaml +git add trainer/trainer/mongo.go +git add trainer/trainer/queue.go +git add trainer/trainer/queue_test.go diff --git a/bin/create_static_pv.sh b/bin/create_static_pv.sh new file mode 100755 index 00000000..efd86308 --- /dev/null +++ b/bin/create_static_pv.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +DLAAS_KUBE_CONTEXT=${DLAAS_KUBE_CONTEXT:-$(kubectl config current-context)} + +echo "Creating persistent volume." + +(kubectl --context "$DLAAS_KUBE_CONTEXT" create -f - < /dev/null; then kubectl delete configmap ${CONFIGMAP_NAME} -n ${NAMESPACE}; else echo "No need to delete ${CONFIGMAP_NAME} since it doesn't exist."; fi + +# Create new configmap +echo +echo "Using volumes with label type=$volumeType:" +kubectl get pvc --selector type=${volumeType} -n ${NAMESPACE} +echo +kubectl create configmap ${CONFIGMAP_NAME} -n ${NAMESPACE} --from-file=PVCs.yaml=<( + kubectl get pvc --selector type=${volumeType} -n ${NAMESPACE} -o yaml +) + +CONFIGMAP_NAME2=static-volumes-v2 + +# Delete configmap +#if kubectl get cm | grep static-volumes &> /dev/null; then kubectl delete configmap ${CONFIGMAP_NAME2}; else echo "No need to delete ${CONFIGMAP_NAME2} since it doesn't exist."; fi + +# Create new configmap +echo +echo "Using volumes with label type=$volumeType" +kubectl get pvc --selector type=${volumeType} -n ${NAMESPACE} +echo + +kubectl get pvc --selector type="dlaas-static-volume" -n ${NAMESPACE} -o jsonpath='{"static-volumes-v2:"}{range .items[*]}{"\n - name: "}{.metadata.name}{"\n zlabel: "}{.metadata.name}{"\n status: active\n"}' > PVCs-v2.yaml + +kubectl create configmap ${CONFIGMAP_NAME2} -n ${NAMESPACE} --from-file=PVCs-v2.yaml diff --git a/bin/dind-port-forward.sh b/bin/dind-port-forward.sh new file mode 100755 index 00000000..ab11bc3c --- /dev/null +++ b/bin/dind-port-forward.sh @@ -0,0 +1,11 @@ +grafana_port=$(kubectl get service grafana -o jsonpath='{.spec.ports[0].nodePort}') +ui_port=$(kubectl get service ffdl-ui -o jsonpath='{.spec.ports[0].nodePort}') +restapi_port=$(kubectl get service ffdl-restapi -o jsonpath='{.spec.ports[0].nodePort}') +s3_port=$(kubectl get service s3 -o jsonpath='{.spec.ports[0].nodePort}') +ui_pod=$(kubectl get pods | grep ffdl-ui | awk '{print $1}') +restapi_pod=$(kubectl get pods | grep ffdl-restapi | awk '{print $1}') +grafana_pod=$(kubectl get pods | grep prometheus | awk '{print $1}') +kubectl port-forward pod/$ui_pod $ui_port:8080 & +kubectl port-forward pod/$restapi_pod $restapi_port:8080 & +kubectl port-forward pod/$grafana_pod $grafana_port:3000 & +kubectl port-forward pod/storage-0 $s3_port:4572 & diff --git a/bin/dind_scripts/Dockerfile.compile b/bin/dind_scripts/Dockerfile.compile new file mode 100644 index 00000000..4f750eee --- /dev/null +++ b/bin/dind_scripts/Dockerfile.compile @@ -0,0 +1,47 @@ +FROM k8s.gcr.io/debian-base-amd64:0.3 + +RUN apt-get update && apt-get install -y \ + automake \ + autotools-dev \ + bash \ + build-essential \ + curl \ + git-core \ + libcurl4-openssl-dev \ + libfuse-dev \ + libssl-dev \ + libxml2-dev \ + pkg-config \ + wget vim && \ + rm -rf /var/lib/apt/lists/* + +# Install Go +RUN wget https://dl.google.com/go/go1.10.1.linux-amd64.tar.gz && \ + tar -xvf go1.10.1.linux-amd64.tar.gz && mv go /usr/local && mkdir -p ~/go/bin + +ENV GOROOT=/usr/local/go +ENV GOPATH=/root/go +ENV PATH="${GOPATH}/bin:${GOROOT}/bin:${PATH}" + +# Install glide +RUN curl https://glide.sh/get | sh && go get github.com/gin-gonic/gin + +# Compile s3fs-fuse +RUN git clone https://github.com/s3fs-fuse/s3fs-fuse.git && \ + cd s3fs-fuse && ./autogen.sh && ./configure CPPFLAGS='-I/usr/local/opt/openssl/include' && make + +# Compile storage plugin +RUN mkdir -p ${GOPATH}/bin && mkdir -p ${GOPATH}/src/github.com/IBM && \ + cd ${GOPATH}/src/github.com/IBM && git clone https://github.com/IBM/ibmcloud-object-storage-plugin.git && \ + cd ibmcloud-object-storage-plugin && make +# cd ibmcloud-object-storage-plugin && make && make provisioner && make driver + +# Note: The following lines were for Ubuntu, need to migrate to Debian if you should want to use them +#RUN apt-get update && apt-get install -y \ +# apt-transport-https \ +# software-properties-common && \ +# curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - && \ +# add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" && \ +# apt-get update && apt-get install -y docker-ce && \ +# curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose && \ +# rm -rf /var/lib/apt/lists/* diff --git a/bin/dind_scripts/build_ffdl.sh b/bin/dind_scripts/build_ffdl.sh new file mode 100755 index 00000000..4f49af7a --- /dev/null +++ b/bin/dind_scripts/build_ffdl.sh @@ -0,0 +1,11 @@ +#!/bin/bash +#mkdir -p $GOPATH/src/github.com/IBM && cd $_ +#git clone https://github.com/IBM/FfDL.git && cd FfDL +#git remote add upstream https://github.com/IBM/FfDL.git +#git fetch --all +#git checkout master && git pull upstream master +#git fetch upstream pull/79/head:pr-79 +#git checkout pr-79 +cd $GOPATH/src/github.com/IBM/FfDL +glide install +make build gen-certs docker-build-base \ No newline at end of file diff --git a/bin/dind_scripts/compile_s3fs.sh b/bin/dind_scripts/compile_s3fs.sh new file mode 100755 index 00000000..69a3655a --- /dev/null +++ b/bin/dind_scripts/compile_s3fs.sh @@ -0,0 +1,40 @@ +#!/bin/bash +sudo apt-get update -qq +#cd ~ +sudo apt-get install -y build-essential git-core libcurl4-openssl-dev libxml2-dev pkg-config autotools-dev automake libfuse-dev libssl-dev +#git clone https://github.com/s3fs-fuse/s3fs-fuse.git +#cd s3fs-fuse +#./autogen.sh +#./configure CPPFLAGS='-I/usr/local/opt/openssl/include' +#make + +# Compile s3fs and ibmc-s3fs binaries +docker build -t larva -f Dockerfile.compile . +docker run -d --name s3compiler -v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/usr/bin/docker larva tail -f /dev/null +#docker exec -i s3compiler /bin/bash <<_EOF +#cd /root/go/src/github.com/IBM/ibmcloud-object-storage-plugin/ +#make provisioner +#make driver +#_EOF +#mkdir -p binary_executables +mkdir -p ~/s3fs-fuse/src/ +docker cp s3compiler:/s3fs-fuse/src/s3fs ~/s3fs-fuse/src/s3fs +#docker cp s3compiler:/root/go/bin/ibmc-s3fs binary_executables/ibmc-s3fs +docker stop s3compiler && docker rm s3compiler +# Could save to container, i.e. docker commit s3compiler larva, or discard image, i.e. docker rmi larva + +# Push all images (ibmcloud-object-storage-plugin, deployer, optionally provisioner-builder and driver-builder) to docker registry +#docker login --username=${DOCKER_REPO_USER} --password=${DOCKER_REPO_PASS} https://${DOCKER_REPO} +#docker tag ibmcloud-object-storage-plugin:latest ${DOCKER_REPO}/ibmcloud-object-storage-plugin:latest +#docker tag deployer:latest ${DOCKER_REPO}/deployer:latest +#docker push ${DOCKER_REPO}/ibmcloud-object-storage-plugin:latest +#docker push ${DOCKER_REPO}/deployer:latest + +mkdir -p $GOPATH/src/github.com/IBM +mkdir -p $GOPATH/bin +cd $GOPATH/src/github.com/IBM/ +git clone https://github.com/IBM/ibmcloud-object-storage-plugin.git +cd ibmcloud-object-storage-plugin +make +make provisioner +make driver diff --git a/bin/dind_scripts/create_user.sh b/bin/dind_scripts/create_user.sh new file mode 100755 index 00000000..b94c0164 --- /dev/null +++ b/bin/dind_scripts/create_user.sh @@ -0,0 +1,11 @@ +#!/bin/bash +apt update && apt upgrade -y && apt install -y build-essential curl wget +useradd -m ffdlr +groupadd docker +usermod -aG docker ffdlr +usermod -aG sudo ffdlr +usermod --shell /bin/bash ffdlr +mkdir -p /home/ffdlr/go/src/github.com/IBM/ && cd $_ && git clone https://github.com/IBM/FfDL.git && chown -R ffdlr /home/ffdlr/ +if [ "$(dnsdomainname)" == "sl.cloud9.ibm.com" ]; then echo "170.225.15.112 public.dhe.ibm.com" >> /etc/hosts else echo "You do not seem to be running on SoftLayer, not modifying hosts file."; fi +passwd ffdlr +exit \ No newline at end of file diff --git a/bin/dind_scripts/experimental_master.sh b/bin/dind_scripts/experimental_master.sh new file mode 100755 index 00000000..1434d891 --- /dev/null +++ b/bin/dind_scripts/experimental_master.sh @@ -0,0 +1,44 @@ +#!/bin/bash +sudo chown -R ${USER} /home/${USER} +chmod +x build_ffdl.sh compile_s3fs.sh create_user.sh import_registry_certificates.sh install_docker.sh install_go.sh install_kubernetes.sh install_nfs.sh install_registry.sh launch_kubernetes.sh launch_registry.sh s3_driver.sh +echo "This script assumes that you have created a user, e.g. via create_user.sh, and are now logged in as that user." + +# Install dependencies +./install_docker.sh +. install_go.sh +./install_kubernetes.sh +./install_registry.sh +./install_nfs.sh + +# Compile FfDL and open source S3 driver +export VM_TYPE=none +./build_ffdl.sh +./compile_s3fs.sh + +# Launch environment and deploy S3 driver +export DOCKER_REPO=$(hostname).$(dnsdomainname) +export DOCKER_REPO_USER=$USER +export DOCKER_REPO_PASS=7312mInalM4n +./launch_registry.sh +./launch_kubernetes.sh +sudo chown -R ${USER} /home/${USER}/.kube/ +./import_registry_certificates.sh +./s3_driver.sh + +# Build FfDL containers, push them to registry and deploy +export DLAAS_IMAGE_PULL_POLICY=Always +export DOCKER_PULL_POLICY=Always +export HAS_STATIC_VOLUMES=True +export PUBLIC_IP=10.192.0.3 +export SHARED_VOLUME_STORAGE_CLASS="" +cd $GOPATH/src/github.com/IBM/FfDL +kubectl create secret docker-registry regcred --docker-server=${DOCKER_REPO} --docker-username=${DOCKER_REPO_USER} --docker-password=${DOCKER_REPO_PASS} --docker-email=unknown@docker.io +make docker-build docker-push create-volumes deploy + +echo "\nFfDL installed." +echo "You can now define your credentials and run a test job like this:" +echo " export AWS_ACCESS_KEY_ID=..." +echo " export AWS_SECRET_ACCESS_KEY=..." +echo " make test-submit" +echo "Please note that there is a good chance you need to change the input and output bucket as well as endpoint" +echo "in etc/examples/tf-model/manifest.yml to your values first." diff --git a/bin/dind_scripts/import_registry_certificates.sh b/bin/dind_scripts/import_registry_certificates.sh new file mode 100755 index 00000000..8a1eecfa --- /dev/null +++ b/bin/dind_scripts/import_registry_certificates.sh @@ -0,0 +1,34 @@ +#!/bin/bash +declare -a arrNodes=($(docker ps --format '{{.Names}}' | grep "kube-node-\|kube-master")) + +# Login to Docker Registry +#echo "docker login --username=$DOCKER_USER --password=$DOCKER_PASS https://$DOCKER_REPO" +#docker login --username=$DOCKER_USER --password=$DOCKER_PASS https://$DOCKER_REPO + +docker login -u="$USER" -p="7312mInalM4n" $(hostname).$(dnsdomainname) +DOCKER_AUTH=$(cat ~/.docker/config.json | jq ".auths.\"$DOCKER_REPO\".auth") +echo $DOCKER_AUTH +cat <<_EOF > config.json +{ + "auths": { + "$DOCKER_REPO": { + "auth": $DOCKER_AUTH + } + } +} +_EOF + +for node in "${arrNodes[@]}" +do + docker exec -d $node mkdir -p /usr/local/share/ca-certificates/docker-dev-cert/ + echo "docker cp ~/docker-registry/nginx/devdockerCA.crt $node:/usr/local/share/ca-certificates/docker-dev-cert/devdockerCA.crt" + docker cp ~/docker-registry/nginx/devdockerCA.crt $node:/usr/local/share/ca-certificates/docker-dev-cert/devdockerCA.crt + docker exec -d $node mkdir -p /root/.docker/ + docker cp config.json $node:/root/.docker/config.json + docker exec -i $node /bin/bash <<'_EOF' +apt-get update && apt-get install -y libssl1.0.2 nfs-common libfuse2 libxml2 curl libcurl3 +update-ca-certificates +service docker restart +exit +_EOF +done diff --git a/bin/dind_scripts/install_docker.sh b/bin/dind_scripts/install_docker.sh new file mode 100755 index 00000000..f045d80f --- /dev/null +++ b/bin/dind_scripts/install_docker.sh @@ -0,0 +1,17 @@ +#!/bin/bash +if ! [ -x "$(command -v docker)" ]; then + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - + sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" + sudo apt-get update && sudo apt-get install -y docker-ce + sudo systemctl status docker + sudo usermod -aG docker ${USER} +else + echo "Docker already installed." +fi + +if ! [ -x "$(command -v docker-compose)" ]; then + sudo curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose + sudo chmod +x /usr/local/bin/docker-compose +else + echo "Docker Compose already installed." +fi \ No newline at end of file diff --git a/bin/dind_scripts/install_go.sh b/bin/dind_scripts/install_go.sh new file mode 100755 index 00000000..73ecc1bc --- /dev/null +++ b/bin/dind_scripts/install_go.sh @@ -0,0 +1,25 @@ +#!/bin/bash +if ! [ -x "$(command -v go)" ]; then + wget https://dl.google.com/go/go1.10.1.linux-amd64.tar.gz + sudo tar -xvf go1.10.1.linux-amd64.tar.gz + sudo mv go /usr/local + mkdir -p ~/go/src + mkdir -p ~/go/bin + export GOROOT=/usr/local/go + echo "export GOROOT=/usr/local/go" >> ~/.profile + export GOPATH=$HOME/go + echo "export GOPATH=$HOME/go" >> ~/.profile + export PATH=${GOPATH}/bin:${GOROOT}/bin:$PATH + echo "export PATH=\$GOPATH/bin:\$GOROOT/bin:\$PATH" >> ~/.profile + source ~/.profile + go version && go env + echo "Go installed. If you did not run this script in your current shell, i.e. \". install_go.sh\", please run \"source ~/.profile\" now." +else + echo "Go already installed." +fi + +if ! [ -x "$(command -v glide)" ]; then + curl https://glide.sh/get | sh +else + echo "Glide already installed." +fi \ No newline at end of file diff --git a/bin/dind_scripts/install_kubernetes.sh b/bin/dind_scripts/install_kubernetes.sh new file mode 100755 index 00000000..13c8d2ac --- /dev/null +++ b/bin/dind_scripts/install_kubernetes.sh @@ -0,0 +1,24 @@ +#!/bin/bash +if ! [ -x "$(command -v kubectl)" ]; then + curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl + chmod +x ./kubectl + sudo mv ./kubectl /usr/local/bin/kubectl +else + echo "kubectl already installed." +fi + +if ! [ -x "$(command -v helm)" ]; then +wget https://storage.googleapis.com/kubernetes-helm/helm-v2.8.2-linux-amd64.tar.gz +tar -zxvf helm-v2.8.2-linux-amd64.tar.gz +sudo mv linux-amd64/helm /usr/local/bin/ +else + echo "helm already installed." +fi + +if [ ! -f ~/dind-cluster-v1.9.sh ]; then + cd ~ + wget https://cdn.rawgit.com/Mirantis/kubeadm-dind-cluster/master/fixed/dind-cluster-v1.9.sh + chmod +x dind-cluster-v1.9.sh +else + echo "DIND Kubernetes script already exists. Nothing to do." +fi \ No newline at end of file diff --git a/bin/dind_scripts/install_nfs.sh b/bin/dind_scripts/install_nfs.sh new file mode 100755 index 00000000..df4a2111 --- /dev/null +++ b/bin/dind_scripts/install_nfs.sh @@ -0,0 +1,7 @@ +#!/bin/bash +sudo apt install -y nfs-kernel-server +sudo mkdir -p /nfs/var/nfs/general +sudo chown nobody:nogroup /nfs/var/nfs/general +echo "/nfs/var/nfs/general *(rw,sync,no_root_squash,no_subtree_check)" | sudo tee -a /etc/exports +sudo systemctl restart nfs-kernel-server +echo "NFS installed. Please note that you need nfs-common on every Kubernetes node you wish to use NFS on." \ No newline at end of file diff --git a/bin/dind_scripts/install_registry.sh b/bin/dind_scripts/install_registry.sh new file mode 100755 index 00000000..33c3eef3 --- /dev/null +++ b/bin/dind_scripts/install_registry.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +if [ -d "/home/$USER/docker-registry" ]; then + echo "Registry seems to exist. Nothing to do." + exit 0 +fi + +sudo apt-get -y install apache2-utils + +mkdir ~/docker-registry && cd $_ +mkdir data +mkdir nginx + +SUBJECT="/C=US/ST=NY/L=Armonk/O=IBM/CN=$(hostname).$(dnsdomainname)" +VALIDITY=365 + +cat > docker-compose.yml <<'_EOF' +registry: + image: registry:2 + ports: + - 127.0.0.1:5000:5000 + environment: + REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data + volumes: + - ./data:/data +nginx: + image: "nginx:1.9" + ports: + - 443:443 + links: + - registry:registry + volumes: + - ./nginx/:/etc/nginx/conf.d:ro +_EOF + +cat > nginx/registry.conf <<'_EOF' +upstream docker-registry { + server registry:5000; +} + +server { + listen 443; + server_name myregistrydomain.com; + + # SSL + ssl on; + ssl_certificate /etc/nginx/conf.d/domain.crt; + ssl_certificate_key /etc/nginx/conf.d/domain.key; + + # disable any limits to avoid HTTP 413 for large image uploads + client_max_body_size 0; + + # required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486) + chunked_transfer_encoding on; + + location /v2/ { + # Do not allow connections from docker 1.5 and earlier + # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents + if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) { + return 404; + } + + # To add basic authentication to v2 use auth_basic setting plus add_header + auth_basic "registry.localhost"; + auth_basic_user_file /etc/nginx/conf.d/registry.password; + add_header 'Docker-Distribution-Api-Version' 'registry/2.0' always; + + proxy_pass http://docker-registry; + proxy_set_header Host $http_host; # required for docker client's sake + proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 900; + } +} +_EOF + +cd nginx/ +# echo "Enter Registry Password:" +# htpasswd -c registry.password $USER +htpasswd -b -c registry.password $USER 7312mInalM4n + +openssl genrsa -passout pass:d123gOn1337h -out devdockerCA.key 2048 +openssl req -x509 -new -nodes -days ${VALIDITY} -passin pass:d123gOn1337h -key devdockerCA.key -out devdockerCA.crt -subj ${SUBJECT} + +openssl genrsa -passout pass:d123gOn1337h -out domain.key 2048 +# NOTE: Enter your domain or IP as common name, e.g. name.sl.cloud9.ibm.com or 9.xxx.xxx.xxx !!! +openssl req -new -key domain.key -passin pass:d123gOn1337h -out dev-docker-registry.com.csr -subj ${SUBJECT} +# Self-sign certificate +openssl x509 -req -days ${VALIDITY} -in dev-docker-registry.com.csr -CA devdockerCA.crt -CAkey devdockerCA.key -CAcreateserial -passin pass:d123gOn1337h -out domain.crt + +sudo mkdir /usr/local/share/ca-certificates/docker-dev-cert +sudo cp devdockerCA.crt /usr/local/share/ca-certificates/docker-dev-cert +sudo update-ca-certificates + +echo "Registry installed." \ No newline at end of file diff --git a/bin/dind_scripts/launch_kubernetes.sh b/bin/dind_scripts/launch_kubernetes.sh new file mode 100755 index 00000000..4f51299e --- /dev/null +++ b/bin/dind_scripts/launch_kubernetes.sh @@ -0,0 +1,12 @@ +#!/bin/bash +sudo apt install -y jq +cd ~ + +wget https://cdn.rawgit.com/kubernetes-sigs/kubeadm-dind-cluster/master/fixed/dind-cluster-v1.9.sh +chmod +x dind-cluster-v1.9.sh + +sudo ./dind-cluster-v1.9.sh clean +sudo ./dind-cluster-v1.9.sh up +# cd ~/go/src/github.com/IBM/FfDL/bin +# chmod +x modify_dind_nodes.sh +# ./modify_dind_nodes.sh \ No newline at end of file diff --git a/bin/dind_scripts/launch_registry.sh b/bin/dind_scripts/launch_registry.sh new file mode 100755 index 00000000..6fa0e730 --- /dev/null +++ b/bin/dind_scripts/launch_registry.sh @@ -0,0 +1,3 @@ +#!/bin/bash +cd ~/docker-registry && docker-compose up -d +echo "Registry started. Please use \"curl https://$USER:7312mInalM4n@$(hostname).$(dnsdomainname)/v2/_catalog\" to list available images." \ No newline at end of file diff --git a/bin/dind_scripts/s3_driver.sh b/bin/dind_scripts/s3_driver.sh new file mode 100755 index 00000000..fd6f4631 --- /dev/null +++ b/bin/dind_scripts/s3_driver.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +kubectl create secret docker-registry regcred --docker-server=${DOCKER_REPO} --docker-username=${DOCKER_REPO_USER} --docker-password=${DOCKER_REPO_PASS} --docker-email=unknown@docker.io +docker pull docker.io/ffdl/ibmcloud-object-storage-plugin +docker tag ibmcloud-object-storage-plugin ${DOCKER_REPO}/ibmcloud-object-storage-plugin +docker push ${DOCKER_REPO}/ibmcloud-object-storage-plugin + +declare -a arrNodes=($(docker ps --format '{{.Names}}' | grep "kube-node-\|kube-master")) +for node in "${arrNodes[@]}" +do +docker cp $GOPATH/bin/ibmc-s3fs $node:/root/ibmc-s3fs +docker cp ~/s3fs-fuse/src/s3fs $node:/usr/local/bin/s3fs +docker exec -i $node /bin/bash <<_EOF +mkdir -p /usr/libexec/kubernetes/kubelet-plugins/volume/exec/ibm~ibmc-s3fs +cp /root/ibmc-s3fs /usr/libexec/kubernetes/kubelet-plugins/volume/exec/ibm~ibmc-s3fs +chmod +x /usr/libexec/kubernetes/kubelet-plugins/volume/exec/ibm~ibmc-s3fs/ibmc-s3fs +systemctl restart kubelet +docker pull $DOCKER_REPO/ibmcloud-object-storage-plugin:latest +_EOF +done + +cd $GOPATH/src/github.com/IBM/ibmcloud-object-storage-plugin/ +kubectl create -f deploy/provisioner-sa.yaml +cp deploy/provisioner.yaml deploy/provisioner_reg.yaml +sed -i "s/image: ibmcloud-object-storage-plugin:latest/image: $(hostname).$(dnsdomainname)\/ibmcloud-object-storage-plugin:latest/g" deploy/provisioner_reg.yaml +kubectl create -f deploy/provisioner_reg.yaml +kubectl create -f deploy/ibmc-s3fs-standard-StorageClass.yaml \ No newline at end of file diff --git a/bin/escape_for_sed.sh b/bin/escape_for_sed.sh new file mode 100755 index 00000000..7255c948 --- /dev/null +++ b/bin/escape_for_sed.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +#!/bin/bash +operating_system=$(uname) +if [[ "$operating_system" == 'Linux' ]]; then + CMD_SED=sed +elif [[ "$operating_system" == 'Darwin' ]]; then + CMD_SED=gsed +fi +replacement_string=$(echo "$AWS_URL" | $CMD_SED -r 's/\//\\\//g') + +echo $replacement_string diff --git a/bin/grafana.init.sh b/bin/grafana.init.sh index f1c35884..f5031639 100755 --- a/bin/grafana.init.sh +++ b/bin/grafana.init.sh @@ -3,6 +3,7 @@ # Note: This script should be called from the top-level working directory, i.e., bin/grafana.init.sh # get grafana service IP +echo "\$VM_TYPE == \"$VM_TYPE\"" if [ "$VM_TYPE" == "ibmcloud" ]; then node_ip=$(bx cs workers $CLUSTER_NAME | grep Ready | awk '{ print $2;exit }') elif [ "$VM_TYPE" == "minikube" ]; then @@ -10,17 +11,25 @@ elif [ "$VM_TYPE" == "minikube" ]; then elif [ "$VM_TYPE" == "vagrant" ]; then node_ip_line=$(vagrant ssh master -c 'ifconfig eth1 | grep "inet "' 2> /dev/null) node_ip=$(echo $node_ip_line | sed "s/.*inet \([^ ]*\) .*/\1/") +else + node_ip=$PUBLIC_IP fi -grafana_port=$(kubectl get service grafana -o jsonpath='{.spec.ports[0].nodePort}') + +[ -z ${node_ip} ] && echo "Can't get node_ip for grafana, \$VM_TYPE == \"$VM_TYPE\"" + +NAMESPACE=${NAMESPACE:-default} +grafana_port=$(kubectl get service grafana -o jsonpath='{.spec.ports[0].nodePort}' -n $NAMESPACE) grafana_url="http://$node_ip:$grafana_port" -# wait until the service is up +echo "wait until the grafana service is up (grafana_url=${grafana_url})" while ! curl -q $grafana_url > /dev/null 2>&1 ; do sleep 2; done; -# create data source +echo "creating data source..." curl -q -u admin:admin -H 'Content-Type: application/json' -XPOST $grafana_url/api/datasources \ -d '{"name":"prom","type":"prometheus","url":"http://localhost:9090","access":"proxy","basicAuth":false}' > /dev/null 2>&1 -# dashboards +echo "set up dashboards" curl -q -u admin:admin -H 'Content-Type: application/json' -XPOST $grafana_url/api/dashboards/db \ -d @etc/dashboards.json > /dev/null 2>&1 + +echo "Finished" diff --git a/bin/ibmc-s3fs b/bin/ibmc-s3fs new file mode 100755 index 00000000..a71035e5 Binary files /dev/null and b/bin/ibmc-s3fs differ diff --git a/bin/ibmc_scripts/experimental_master.sh b/bin/ibmc_scripts/experimental_master.sh new file mode 100644 index 00000000..038a080e --- /dev/null +++ b/bin/ibmc_scripts/experimental_master.sh @@ -0,0 +1,68 @@ +#!/bin/bash +operating_system=$(uname) +if [[ "$operating_system" == 'Linux' ]]; then + CMD_SED=sed +elif [[ "$operating_system" == 'Darwin' ]]; then + CMD_SED=gsed +fi + +# Please enter this information +export DOCKER_REPO_PASS= +export DOCKER_NAMESPACE= +export AWS_ACCESS_KEY_ID= +export AWS_SECRET_ACCESS_KEY= +export PUBLIC_IP= +export CLUSTER_NAME= +# Potentially export KUBECONFIG=... to point kubectl to your cluster + +# This information should be largely static +export DOCKER_REPO=registry.ng.bluemix.net +export DLAAS_USERID=user-$(whoami) +export DOCKER_REPO_USER=token +export SHARED_VOLUME_STORAGE_CLASS="ibmc-file-gold" +export DLAAS_IMAGE_PULL_POLICY=Always +export DOCKER_PULL_POLICY=Always +export VM_TYPE=none +export HAS_STATIC_VOLUMES=True + +# Build S3 Driver +cd $GOPATH/src/github.com/IBM/ +git clone https://github.com/IBM/ibmcloud-object-storage-plugin.git +cd ibmcloud-object-storage-plugin/deploy/binary-build-and-deploy-scripts/ +./build-all.sh + +# Push to registry +docker login --username=${DOCKER_REPO_USER} --password=${DOCKER_REPO_PASS} https://${DOCKER_REPO} +docker tag ibmcloud-object-storage-deployer:v001 $DOCKER_REPO/$DOCKER_NAMESPACE/ibmcloud-object-storage-deployer:v001 +docker tag ibmcloud-object-storage-plugin:v001 $DOCKER_REPO/$DOCKER_NAMESPACE/ibmcloud-object-storage-plugin:v001 +docker push $DOCKER_REPO/$DOCKER_NAMESPACE/ibmcloud-object-storage-deployer:v001 +docker push $DOCKER_REPO/$DOCKER_NAMESPACE/ibmcloud-object-storage-plugin:v001 + +# Deploy S3 Driver +# Replace image tag in yaml descriptors to point to registry and namespace +$CMD_SED -i "s/image: \"ibmcloud-object-storage-deployer:v001\"/image: \"$DOCKER_REPO\/$DOCKER_NAMESPACE\/ibmcloud-object-storage-deployer:v001\"/g" deploy-plugin.yaml +$CMD_SED -i "s/image: \"ibmcloud-object-storage-plugin:v001\"/image: \"$DOCKER_REPO\/$DOCKER_NAMESPACE\/ibmcloud-object-storage-plugin:v001\"/g" deploy-provisioner.yaml + +# Create secret, then deploy daemonset and plugin +kubectl create secret docker-registry regcred --docker-server=${DOCKER_REPO} --docker-username=${DOCKER_REPO_USER} --docker-password=${DOCKER_REPO_PASS} --docker-email=unknown@docker.io -n kube-system +# Note: Running deploy-plugin daemonset might only be possible once (and is also only needed once). +# Running it additional times might cause FfDL deployment to wait indefinitely. If that should happen, just delete it again. +kubectl create -f deploy-plugin.yaml +kubectl create -f deploy-provisioner.yaml + +# Create storage class +cd .. +kubectl create -f ibmc-s3fs-standard-StorageClass.yaml + +# Deploy FfDL +cd $GOPATH/src/github.com/IBM/FfDL/bin +./create_static_volumes.sh +./create_static_volumes_config.sh +cd .. +glide install +make docker-build-base +make build gen-certs docker-build docker-push deploy + +echo "" +echo "Deployment complete. You can now run a test job with:" +echo " make test-submit" \ No newline at end of file diff --git a/bin/kubecontext.sh b/bin/kubecontext.sh new file mode 100755 index 00000000..162ac763 --- /dev/null +++ b/bin/kubecontext.sh @@ -0,0 +1,101 @@ +#!/bin/bash + +# Print selected information from a Kubernetes context. +# Be sure to set the DLAAS_KUBE_CONTEXT to override the current context (i.e., kubectl config current-context) + +DLAAS_KUBE_CONTEXT=${DLAAS_KUBE_CONTEXT:-$(kubectl config current-context)} + +function printServerCertificate() { + cluster=$(kubectl config view -o jsonpath='{.contexts[?(@.name=="'$DLAAS_KUBE_CONTEXT'")].context.cluster}') + value=$(kubectl config view -o jsonpath='{.clusters[?(@.name=="'$cluster'")].cluster.certificate-authority}') + echo $value +} + +function printClientCertificate() { + user=$(kubectl config view -o jsonpath='{.contexts[?(@.name=="'$DLAAS_KUBE_CONTEXT'")].context.user}') + value=$(kubectl config view -o jsonpath='{.users[?(@.name=="'$user'")].user.client-certificate}') + echo $value +} + +function printClientKey() { + user=$(kubectl config view -o jsonpath='{.contexts[?(@.name=="'$DLAAS_KUBE_CONTEXT'")].context.user}') + value=$(kubectl config view -o jsonpath='{.users[?(@.name=="'$user'")].user.client-key}') + echo $value +} + +function printUserToken() { + user=$(kubectl config view -o jsonpath='{.contexts[?(@.name=="'$DLAAS_KUBE_CONTEXT'")].context.user}') + token=$(kubectl config view -o jsonpath='{.users[?(@.name=="'$user'")].user.token}') + echo $token +} + +function printNamespace() { + namespace=$(kubectl config view -o jsonpath='{.contexts[?(@.name=="'$DLAAS_KUBE_CONTEXT'")].context.namespace}') + if [ -z "$namespace" ]; then + namespace="default" + fi + echo $namespace +} + +function printApiServer() { + cluster=$(kubectl config view -o jsonpath='{.contexts[?(@.name=="'$DLAAS_KUBE_CONTEXT'")].context.cluster}') + server=$(kubectl config view -o jsonpath='{.clusters[?(@.name=="'$cluster'")].cluster.server}') + echo $server +} + +function printRestApiUrl() { + host=$(kubectl --context="$DLAAS_KUBE_CONTEXT" get nodes -o jsonpath='{.items[0].status.addresses[0].address}') + port=$(kubectl --context="$DLAAS_KUBE_CONTEXT" get svc/ffdl-restapi -o jsonpath='{.spec.ports[0].nodePort}' 2> /dev/null) + if [[ -z "$host" || -z "$port" ]]; then + # Assume run-services-local scenario. + url="localhost:10000" + else + url="$host:$port" + fi + echo $url +} + +function printTrainerUrl() { + host=$(kubectl --context="$DLAAS_KUBE_CONTEXT" get nodes -o jsonpath='{.items[0].status.addresses[0].address}') + port=$(kubectl --context="$DLAAS_KUBE_CONTEXT" get svc/ffdl-trainer-v2 -o jsonpath='{.spec.ports[0].nodePort}' 2> /dev/null) + if [[ -z "$host" || -z "$port" ]]; then + # Assume run-services-local scenario. + url="localhost:30005" + else + url="$host:$port" + fi + echo $url +} + + +# Parse command line args and dispatch command. +case $1 in +server-certificate) + printServerCertificate + ;; +client-certificate) + printClientCertificate + ;; +client-key) + printClientKey + ;; +user-token) + printUserToken + ;; +namespace) + printNamespace + ;; +api-server) + printApiServer + ;; +restapi-url) + printRestApiUrl + ;; +trainer-url) + printTrainerUrl + ;; +*) + echo "Usage: kubecontext.sh [server-certificate|client-certificate|client-key|user-token|namespace|api-server|restapi-url|trainer-url]" + exit 1 + ;; +esac diff --git a/bin/s3_driver.sh b/bin/s3_driver.sh new file mode 100755 index 00000000..3b51f358 --- /dev/null +++ b/bin/s3_driver.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +declare -a arrNodes=($(docker ps --format '{{.Names}}' | grep "kube-node-\|kube-master")) +for node in "${arrNodes[@]}" +do +docker cp $FFDL_PATH/bin/ibmc-s3fs $node:/root/ibmc-s3fs +docker cp $FFDL_PATH/bin/s3fs $node:/usr/local/bin/s3fs +docker exec -i $node /bin/bash <<_EOF +apt-get -y update +apt-get -y install s3fs +mkdir -p /usr/libexec/kubernetes/kubelet-plugins/volume/exec/ibm~ibmc-s3fs +cp /root/ibmc-s3fs /usr/libexec/kubernetes/kubelet-plugins/volume/exec/ibm~ibmc-s3fs +chmod +x /usr/libexec/kubernetes/kubelet-plugins/volume/exec/ibm~ibmc-s3fs/ibmc-s3fs +systemctl restart kubelet +_EOF +done diff --git a/bin/s3fs b/bin/s3fs new file mode 100755 index 00000000..c42abceb Binary files /dev/null and b/bin/s3fs differ diff --git a/bin/test-pods/nfs-pv.yaml b/bin/test-pods/nfs-pv.yaml new file mode 100644 index 00000000..40334be0 --- /dev/null +++ b/bin/test-pods/nfs-pv.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: nfs +spec: + capacity: + storage: 20Gi + accessModes: + - ReadWriteMany + nfs: + # FIXME: Do not hardcode NFS host + server: + path: "/nfs/var/nfs/general" diff --git a/bin/test-pods/nfs-test-pod.yaml b/bin/test-pods/nfs-test-pod.yaml new file mode 100644 index 00000000..26106a2e --- /dev/null +++ b/bin/test-pods/nfs-test-pod.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nfs-test-pod + namespace: default +spec: + containers: + - name: nfs-test-container + image: anaudiyal/infinite-loop + volumeMounts: + - mountPath: "/job" + name: nfs-test-volume + volumes: + - name: nfs-test-volume + persistentVolumeClaim: + claimName: static-volume-1 diff --git a/cli/bin/ffdl-linux b/cli/bin/ffdl-linux index 73c67f4e..bb1fa890 100755 Binary files a/cli/bin/ffdl-linux and b/cli/bin/ffdl-linux differ diff --git a/cli/bin/ffdl-osx b/cli/bin/ffdl-osx index ebe7aeba..f3d12c6c 100755 Binary files a/cli/bin/ffdl-osx and b/cli/bin/ffdl-osx differ diff --git a/cli/main.go b/cli/main.go index bceb4698..ed9f5aaf 100644 --- a/cli/main.go +++ b/cli/main.go @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package main import ( @@ -138,6 +139,12 @@ func (c *DlaasPlugin) Run(context plugin.PluginContext, args []string) { metadata.Logs: func(c *cli.Context) error { return cmd.NewLogsCmd(ui, context).Run(c) }, + metadata.Loglines: func(c *cli.Context) error { + return cmd.NewLoglinesCmd(ui, context).Run(c) + }, + metadata.Emetrics: func(c *cli.Context) error { + return cmd.NewEmetricsCmd(ui, context).Run(c) + }, metadata.Halt: func(c *cli.Context) error { return cmd.NewHaltCmd(ui, context).Run(c) }, @@ -153,6 +160,8 @@ func (c *DlaasPlugin) Run(context plugin.PluginContext, args []string) { metadata.ProjectInit: cmd.InitCmdCompletion, metadata.Download: cmd.DownloadCmdCompletion, metadata.Logs: cmd.TrainingLogsCompletion, + metadata.Loglines: cmd.LoglinesCompletion, + metadata.Emetrics: cmd.EMetricsCompletion, metadata.Halt: cmd.ModelIDCompletion, } diff --git a/commons/certs/copy.sh b/commons/certs/copy.sh new file mode 100755 index 00000000..ae6e1ef1 --- /dev/null +++ b/commons/certs/copy.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# This script copies the certs to each microservice directory. Each microservice +# has its own dockerfile and you cannot add anything to a dockerfile that is +# outside its build path. + +declare -a services=("lcm" "jobmonitor") +for i in ${services[@]} +do + mkdir -p ../cmd/${i}/certs + cp server.crt server.key ca.crt ../cmd/${i}/certs +done diff --git a/commons/certs/generate.sh b/commons/certs/generate.sh new file mode 100755 index 00000000..55a18d9f --- /dev/null +++ b/commons/certs/generate.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +SUBJECT="/C=US/ST=NY/L=Armonk/O=IBM/CN=dlaas.ibm.com" +VALIDITY=365 # days + +echo Generate CA key: +openssl genrsa -des3 -passout pass:w3stw0r1d -out ca.key 4096 + +echo Generate CA certificate: +openssl req -new -x509 -days ${VALIDITY} -key ca.key -passin pass:w3stw0r1d -out ca.crt -subj ${SUBJECT} + +echo Generate server key: +openssl genrsa -des3 -passout pass:w3stw0r1d -out server.key 4096 + +echo Generate server signing request: +openssl req -new -key server.key -passin pass:w3stw0r1d -out server.csr -subj ${SUBJECT} + +echo Self-sign server certificate: +openssl x509 -req -days ${VALIDITY} -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -passin pass:w3stw0r1d -out server.crt + +echo Remove passphrase from the server key: +openssl rsa -in server.key -passin pass:w3stw0r1d -out server.key + +echo Generate client key: +openssl genrsa -des3 -passout pass:w3stw0r1d -passout pass:w3stw0r1d -out client.key 4096 + +echo Generate client signing request: +openssl req -new -key client.key -passin pass:w3stw0r1d -out client.csr -subj ${SUBJECT} + +echo Self-sign client certificate: +openssl x509 -req -days ${VALIDITY} -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -passin pass:w3stw0r1d -out client.crt + +echo Remove passphrase from the client key: +openssl rsa -in client.key -passin pass:w3stw0r1d -out client.key diff --git a/commons/certs/install.sh b/commons/certs/install.sh new file mode 100755 index 00000000..afa8f737 --- /dev/null +++ b/commons/certs/install.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +staging=$GOPATH/src/github.com/IBM/FfDL + +declare -a services=( + "${staging}/metrics/docker/certs" \ + "${staging}/metrics/log_collectors/training_data_service_client/certs" \ + "${staging}/restapi/certs" \ + "${staging}/lcm/certs" \ + "${staging}/jobmonitor/certs" \ + "${staging}/trainer/docker/certs" \ + ) +for dir in ${services[@]} +do + echo "------ ${dir}" + mkdir -p ${dir} + cp ca.crt ${dir} + cp server.crt ${dir} + cp server.key ${dir} +done diff --git a/commons/config/config.go b/commons/config/config.go index e7ad2bf4..4467137e 100644 --- a/commons/config/config.go +++ b/commons/config/config.go @@ -30,6 +30,8 @@ import ( log "github.com/sirupsen/logrus" "github.com/spf13/viper" + v1core "k8s.io/api/core/v1" + "runtime" ) const ( @@ -130,7 +132,7 @@ const ( // This is temporary until we support specifying storage requirements in the manifest. VolumeSize = "external_volume_size" - // TODO this a duplication witht the storage package - needs to align + // TODO this a duplication with the storage package - needs to align UsernameKey = "user_name" PasswordKey = "password" AuthURLKey = "auth_url" @@ -146,6 +148,16 @@ const ( DlaasResourceLimit = "resource.limit" DlaasResourceLimitQuerySize = "resource.limit.query.size" + + // FfDL Change: next 5 lines + ImagePullPolicy = "image_pull_policy" + + SharedVolumeStorageClassKey = "shared_volume_storage_class" + + loadTrainingDataMemInMBKey = "load_training_data_mem_in_mb" + logCollectorMilliCPUKey = "milli_cpu" + logCollectorMemInMBKey = "mem_in_mb" + devicePlugin = "device_plugin" ) var viperInitOnce sync.Once @@ -162,6 +174,12 @@ func InitViper() { viper.SetEnvPrefix(envPrefix) // will be uppercased automatically viper.SetConfigType("yaml") + // FfDL Change: make image pull policy default + viper.SetDefault(ImagePullPolicy, v1core.PullIfNotPresent) + + // FfDL Change:Most likely be "standard" in Minikube and "ibmc-s3fs-standard" in DIND, (other value is "default" or "") + viper.SetDefault(SharedVolumeStorageClassKey, "") + // enable ENV vars and defaults viper.AutomaticEnv() viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_", ".", "_")) @@ -175,7 +193,10 @@ func InitViper() { viper.SetDefault(LearnerTagKey, "prod") viper.SetDefault(DataBrokerTagKey, "prod") viper.SetDefault(LearnerRegistryKey, "docker.io/ffdl") - viper.SetDefault(LearnerImagePullSecretKey, "bluemix-cr-ng") + + // FfDL Change: FIXME in DLaaS, this will need to be overridden with "bluemix-cr-ng" + viper.SetDefault(LearnerImagePullSecretKey, "regcred") + // viper.SetDefault(LearnerImagePullSecretKey, "bluemix-cr-ng") // TLS defaults for microservices viper.SetDefault(TLSKey, true) @@ -199,6 +220,15 @@ func InitViper() { viper.SetDefault(learnerKubeCertFileKey, path.Join(learnerKubeSecretsRoot, "client.crt")) viper.SetDefault(learnerKubeTokenFileKey, path.Join(learnerKubeSecretsRoot, "token")) + viper.SetDefault(loadTrainingDataMemInMBKey, 300) + viper.SetDefault(logCollectorMilliCPUKey, 60) + viper.SetDefault(logCollectorMemInMBKey, 300) + viper.SetDefault(devicePlugin, true) + log.Debugf("Milli CPU is: %d", GetLogCollectorMilliCPU()) + log.Debugf("Training Data Mem in MB is: %d", GetTrainingDataMemInMB()) + + viper.SetDefault(VolumeSize, "10GiB") + // config file is optional. we usually configure via ENV_VARS configFile := fmt.Sprintf("config-%s", viper.Get(EnvKey)) viper.SetConfigName(configFile) // name of config file (without extension) @@ -225,6 +255,31 @@ func InitViper() { grpclog.SetLogger(log.StandardLogger()) } +// GetInt returns the int value for the config key. +func GetInt(key string) int { + return viper.GetInt(key) +} + +// GetInt64 returns the int64 value for the config key. +func GetInt64(key string) int64 { + return viper.GetInt64(key) +} + +// GetFloat64 returns the float64 value for the config key. +func GetFloat64(key string) float64 { + return viper.GetFloat64(key) +} + +// GetString returns the string value for the config key. +func GetString(key string) string { + return viper.GetString(key) +} + +// SetDefault sets the default value for the config key. +func SetDefault(key string, value interface{}) { + viper.SetDefault(key, value) +} + // Return the contents of a file. Return an empty string if the file doesn't exist or can't be read. func GetFileContents(filename string) string { contents := "" @@ -376,10 +431,16 @@ func GetDataStoreConfig() map[string]string { if val != "" { m[DomainKey] = val } - val = viper.GetString("objectstore." + UsernameKey) + val = viper.GetString("objectstore." + RegionKey) if val != "" { - m[UsernameKey] = val + m[RegionKey] = val } + // FfDL Change: This was in the older PR, supposing not needed? + //val = viper.GetString("objectstore." + UsernameKey) + //if val != "" { + // m[UsernameKey] = val + //} + val = viper.GetString("objectstore." + ProjectKey) if val != "" { m[ProjectKey] = val @@ -496,32 +557,32 @@ func GetMongoCertLocation() string { return getFileAtLocation("/etc/certs/mongo/mongo.cert") //the file should have been mounted at this path as a part of secrets } -//Get LearnerKubeURLKey... +//GetLearnerKubeURL ... func GetLearnerKubeURL() string { return viper.GetString(learnerKubeURLKey) } -//Get LearnerKubeCAFileKey... +//GetLearnerKubeCAFile ... func GetLearnerKubeCAFile() string { return viper.GetString(learnerKubeCAFileKey) } -//Get LearnerKubetokenKey... +//GetLearnerKubeToken ... func GetLearnerKubeToken() string { return viper.GetString(learnerKubeTokenKey) } -//Get LearnerKubeTokenFileKey +//GetLearnerKubeTokenFile ... func GetLearnerKubeTokenFile() string { return viper.GetString(learnerKubeTokenFileKey) } -//Get LearnerKubeKeyFileKey +//GetLearnerKubeKeyFile ... func GetLearnerKubeKeyFile() string { return viper.GetString(learnerKubeKeyFileKey) } -//Get LearnerKubeCertFileKey +//GetLearnerKubeCertFile ... func GetLearnerKubeCertFile() string { return viper.GetString(learnerKubeCertFileKey) } @@ -545,6 +606,22 @@ func GetCurrentLearnerConfigLocation(name string, version string) string { } } +func LogStackTrace() { + pc := make([]uintptr, 30) + stackDepth := runtime.Callers(0, pc) + for i := 0; i < stackDepth; i++ { + f := runtime.FuncForPC(pc[i]) + file, line := f.FileLine(pc[i]) + // Truncate package name + funcName := f.Name() + if slash := strings.LastIndex(funcName, "."); slash >= 0 { + funcName = funcName[slash+1:] + } + locString := fmt.Sprintf("%s:%d %s -", file, line, funcName) + log.Debugf(" ---> %s", locString) + } +} + //return the location back if the file was present otherwise an empty string func getFileAtLocation(location string) string { exists := func(filename string) bool { @@ -567,3 +644,23 @@ func getFileAtLocation(location string) string { func GetPushgatewayURL() string { return fmt.Sprintf("http://pushgateway:%s", "9091") } + +func GetTrainingDataMemInMB() int { + log.Infof("GetTrainingDataMemInMB() returns %d", viper.GetInt(loadTrainingDataMemInMBKey)) + return viper.GetInt(loadTrainingDataMemInMBKey) +} + +func GetLogCollectorMilliCPU() int { + return viper.GetInt(logCollectorMilliCPUKey) +} + +func GetLogCollectorMemInMB() int { + return viper.GetInt(logCollectorMemInMBKey) +} + +func GetDevicePlugin() bool { + if viper.IsSet(devicePlugin) { + return viper.GetBool(devicePlugin) + } + return true +} diff --git a/commons/config/config_test.go b/commons/config/config_test.go index c99c51e5..17cbdc1e 100644 --- a/commons/config/config_test.go +++ b/commons/config/config_test.go @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package config import ( diff --git a/commons/framework/framework.go b/commons/framework/framework.go new file mode 100644 index 00000000..9371f8ab --- /dev/null +++ b/commons/framework/framework.go @@ -0,0 +1,86 @@ +package framework + +import ( + "encoding/json" + "io/ioutil" +) + +//Frameworks All frameworks supported and maintained by dlaas +type Frameworks struct { + Frameworks map[string]*DetailList +} + +//DetailList list of versions for a framework +type DetailList struct { + Versions []*Details +} + +//Details Specific details for a framework version +type Details struct { + Version string + External bool + Build string + PrevBuild string +} + +func readFile(location string) ([]byte, error) { + fileData, err := ioutil.ReadFile(location) + if err != nil { + return []byte(""), err + } + return fileData, nil +} + +//GetFrameworks returns the frameworks and their versions that are stored in the path to the learnerConfig +func GetFrameworks(learnerConfigPath string) (Frameworks, error) { + var frameworks Frameworks + fileData, err := readFile(learnerConfigPath) + if err != nil { + return frameworks, err + } + err = json.Unmarshal(fileData, &frameworks) + if err != nil { + return frameworks, err + } + + return frameworks, nil +} + +//GetImageBuildTagForFramework Returns the latest build tag for a specified framework and version +func GetImageBuildTagForFramework(fwName, fwVersion, learnerConfigPath string) string { + frameworks, err := GetFrameworks(learnerConfigPath) + if err != nil { + return "" + } + + frameworkVersions := frameworks.Frameworks[fwName].Versions + + for _, frameworkVersion := range frameworkVersions { + if frameworkVersion.Version == fwVersion { + return frameworkVersion.Build + } + } + + return "" +} + +//CheckIfFrameworkExists Checks if the specified framework exists +func CheckIfFrameworkExists(fwName, fwVersion, learnerConfigPath string) (bool, error) { + frameworks, err := GetFrameworks(learnerConfigPath) + if err != nil { + return false, err + } + + frameworkType := frameworks.Frameworks[fwName] + if frameworkType == nil { + return false, nil + } + frameworkVersions := frameworkType.Versions + + for _, frameworkVersion := range frameworkVersions { + if frameworkVersion.Version == fwVersion { + return true, nil + } + } + return false, nil +} diff --git a/commons/logger/logger.go b/commons/logger/logger.go index 708ede10..8b16ca4e 100644 --- a/commons/logger/logger.go +++ b/commons/logger/logger.go @@ -34,20 +34,26 @@ const ( // ======= Log field keys ======= // These keys are to be used for structured logging, and will // be visible to the Elastic Search repository for query and the like. - LogkeyCaller = "caller_info" - LogkeyTrainingID = "training_id" - LogkeyModelID = "model_id" - LogkeyModelName = "model_name" - LogkeyDBName = "db_name" - LogkeyUserID = "user_id" - LogkeyModule = "module" - LogkeyIsMetrics = "is_metrics" - LogkeyIsFollow = "is_follow" - LogkeyIsSummary = "is_summary" - LogkeyObjectstorePath = "os_path" - LogkeyTrainingDataURI = "training_data_uri" - LogkeyModelDataURI = "model_data_uri" - LogkeyModelFilename = "model_filename" + LogkeyCaller = "caller_info" + LogkeyTrainingID = "training_id" + LogkeyGpuType = "gpu_type" + LogkeyGpuUsage = "gpu_usage" + LogkeyFramework = "framework_name" + LogkeyFrameworkVersion = "framework_version" + LogkeyErrorCode = "error_code" + LogkeyErrorType = "error_type" + LogkeyModelID = "model_id" + LogkeyModelName = "model_name" + LogkeyDBName = "db_name" + LogkeyUserID = "user_id" + LogkeyModule = "module" + LogkeyIsMetrics = "is_metrics" + LogkeyIsFollow = "is_follow" + LogkeyIsSummary = "is_summary" + LogkeyObjectstorePath = "os_path" + LogkeyTrainingDataURI = "training_data_uri" + LogkeyModelDataURI = "model_data_uri" + LogkeyModelFilename = "model_filename" LogkeyDeployerService = "deployer-service" LogkeyLcmService = "lifecycle-manager-service" @@ -125,12 +131,16 @@ func FileInfoFindGood() string { if strings.Contains(file, "runtime/extern.go") { continue } - if strings.Contains(file, "dlaas-commons/logger/logger.go") { + // FfDL Change: Not sure if this can be handled in a common way. Moot point once DLaaS is based on FfDL. + if strings.Contains(file, "logger/logger.go") { continue } if strings.Contains(file, "/logging_impl.go") { continue } + if strings.Contains(file, "/logging.go") { + continue + } break } @@ -155,6 +165,23 @@ func FileInfoFindGood() string { return fmt.Sprintf("%s:%d %s -", file, line, funcName) } +// FfDL Change: Because it's useful +func LogStackTrace() { + pc := make([]uintptr, 30) + stackDepth := runtime.Callers(0, pc) + for i := 0; i < stackDepth; i++ { + f := runtime.FuncForPC(pc[i]) + file, line := f.FileLine(pc[i]) + // Truncate package name + funcName := f.Name() + if slash := strings.LastIndex(funcName, "."); slash >= 0 { + funcName = funcName[slash+1:] + } + locString := fmt.Sprintf("%s:%d %s -", file, line, funcName) + log.Debugf(" ---> %s", locString) + } +} + // NewDlaaSLogData construct log data object. func NewDlaaSLogData(serviceName string) log.Fields { f := FileInfoFindGood() @@ -213,7 +240,7 @@ func Config() { case config.ProductionEnv: log.SetFormatter(&log.JSONFormatter{}) default: // any other env will use local settings (assuming outside SL) - log.SetFormatter(&log.TextFormatter{}) + log.SetFormatter(&log.JSONFormatter{}) } } diff --git a/commons/metricsmon/metricspusher.go b/commons/metricsmon/metricspusher.go index 19d5eb3d..255cd19f 100644 --- a/commons/metricsmon/metricspusher.go +++ b/commons/metricsmon/metricspusher.go @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package metricsmon import ( @@ -5,10 +21,10 @@ import ( "github.com/IBM/FfDL/commons/config" - log "github.com/sirupsen/logrus" "github.com/go-kit/kit/metrics/statsd" stdprometheus "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/push" + log "github.com/sirupsen/logrus" "github.com/sony/gobreaker" ) @@ -65,5 +81,5 @@ func StartStatsdMetricsPusher(statsd *statsd.Statsd, pushInterval time.Duration) report := time.NewTicker(pushInterval) //TODO //defer report.Stop() - go statsd.SendLoop(report.C, "udp", "pushgateway:9125") + go statsd.SendLoop(report.C, "udp", "statsdexporter:9125") } diff --git a/commons/mock_service/lcm.go b/commons/mock_service/lcm.go index bed70161..cabe2744 100644 --- a/commons/mock_service/lcm.go +++ b/commons/mock_service/lcm.go @@ -1,6 +1,7 @@ -// Automatically generated by MockGen. DO NOT EDIT! -// Source: github.com/IBM/FfDL/commons/service (interfaces: LifecycleManager_GetTrainingLogStreamClient,LifecycleManagerClient) +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/IBM/FfDL/commons/service (interfaces: LifecycleManagerClient) +// Package mock_service is a generated GoMock package. package mock_service import ( @@ -8,220 +9,82 @@ import ( service "github.com/IBM/FfDL/commons/service" context "golang.org/x/net/context" grpc "google.golang.org/grpc" - metadata "google.golang.org/grpc/metadata" + reflect "reflect" ) -// Mock of LifecycleManager_GetTrainingLogStreamClient interface -type MockLifecycleManager_GetTrainingLogStreamClient struct { - ctrl *gomock.Controller - recorder *_MockLifecycleManager_GetTrainingLogStreamClientRecorder -} - -// Recorder for MockLifecycleManager_GetTrainingLogStreamClient (not exported) -type _MockLifecycleManager_GetTrainingLogStreamClientRecorder struct { - mock *MockLifecycleManager_GetTrainingLogStreamClient -} - -func NewMockLifecycleManager_GetTrainingLogStreamClient(ctrl *gomock.Controller) *MockLifecycleManager_GetTrainingLogStreamClient { - mock := &MockLifecycleManager_GetTrainingLogStreamClient{ctrl: ctrl} - mock.recorder = &_MockLifecycleManager_GetTrainingLogStreamClientRecorder{mock} - return mock -} - -func (_m *MockLifecycleManager_GetTrainingLogStreamClient) EXPECT() *_MockLifecycleManager_GetTrainingLogStreamClientRecorder { - return _m.recorder -} - -func (_m *MockLifecycleManager_GetTrainingLogStreamClient) CloseSend() error { - ret := _m.ctrl.Call(_m, "CloseSend") - ret0, _ := ret[0].(error) - return ret0 -} - -func (_mr *_MockLifecycleManager_GetTrainingLogStreamClientRecorder) CloseSend() *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "CloseSend") -} - -func (_m *MockLifecycleManager_GetTrainingLogStreamClient) Context() context.Context { - ret := _m.ctrl.Call(_m, "Context") - ret0, _ := ret[0].(context.Context) - return ret0 -} - -func (_mr *_MockLifecycleManager_GetTrainingLogStreamClientRecorder) Context() *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "Context") -} - -func (_m *MockLifecycleManager_GetTrainingLogStreamClient) Header() (metadata.MD, error) { - ret := _m.ctrl.Call(_m, "Header") - ret0, _ := ret[0].(metadata.MD) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -func (_mr *_MockLifecycleManager_GetTrainingLogStreamClientRecorder) Header() *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "Header") -} - -func (_m *MockLifecycleManager_GetTrainingLogStreamClient) Recv() (*service.TrainerLogStreamResponse, error) { - ret := _m.ctrl.Call(_m, "Recv") - ret0, _ := ret[0].(*service.TrainerLogStreamResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -func (_mr *_MockLifecycleManager_GetTrainingLogStreamClientRecorder) Recv() *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "Recv") -} - -func (_m *MockLifecycleManager_GetTrainingLogStreamClient) RecvMsg(_param0 interface{}) error { - ret := _m.ctrl.Call(_m, "RecvMsg", _param0) - ret0, _ := ret[0].(error) - return ret0 -} - -func (_mr *_MockLifecycleManager_GetTrainingLogStreamClientRecorder) RecvMsg(arg0 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "RecvMsg", arg0) -} - -func (_m *MockLifecycleManager_GetTrainingLogStreamClient) SendMsg(_param0 interface{}) error { - ret := _m.ctrl.Call(_m, "SendMsg", _param0) - ret0, _ := ret[0].(error) - return ret0 -} - -func (_mr *_MockLifecycleManager_GetTrainingLogStreamClientRecorder) SendMsg(arg0 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "SendMsg", arg0) -} - -func (_m *MockLifecycleManager_GetTrainingLogStreamClient) Trailer() metadata.MD { - ret := _m.ctrl.Call(_m, "Trailer") - ret0, _ := ret[0].(metadata.MD) - return ret0 -} - -func (_mr *_MockLifecycleManager_GetTrainingLogStreamClientRecorder) Trailer() *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "Trailer") -} - -// Mock of LifecycleManagerClient interface +// MockLifecycleManagerClient is a mock of LifecycleManagerClient interface type MockLifecycleManagerClient struct { ctrl *gomock.Controller - recorder *_MockLifecycleManagerClientRecorder + recorder *MockLifecycleManagerClientMockRecorder } -// Recorder for MockLifecycleManagerClient (not exported) -type _MockLifecycleManagerClientRecorder struct { +// MockLifecycleManagerClientMockRecorder is the mock recorder for MockLifecycleManagerClient +type MockLifecycleManagerClientMockRecorder struct { mock *MockLifecycleManagerClient } +// NewMockLifecycleManagerClient creates a new mock instance func NewMockLifecycleManagerClient(ctrl *gomock.Controller) *MockLifecycleManagerClient { mock := &MockLifecycleManagerClient{ctrl: ctrl} - mock.recorder = &_MockLifecycleManagerClientRecorder{mock} + mock.recorder = &MockLifecycleManagerClientMockRecorder{mock} return mock } -func (_m *MockLifecycleManagerClient) EXPECT() *_MockLifecycleManagerClientRecorder { - return _m.recorder +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockLifecycleManagerClient) EXPECT() *MockLifecycleManagerClientMockRecorder { + return m.recorder } -func (_m *MockLifecycleManagerClient) DeployTrainingJob(_param0 context.Context, _param1 *service.JobDeploymentRequest, _param2 ...grpc.CallOption) (*service.JobDeploymentResponse, error) { - _s := []interface{}{_param0, _param1} - for _, _x := range _param2 { - _s = append(_s, _x) +// DeployTrainingJob mocks base method +func (m *MockLifecycleManagerClient) DeployTrainingJob(arg0 context.Context, arg1 *service.JobDeploymentRequest, arg2 ...grpc.CallOption) (*service.JobDeploymentResponse, error) { + varargs := []interface{}{arg0, arg1} + for _, a := range arg2 { + varargs = append(varargs, a) } - ret := _m.ctrl.Call(_m, "DeployTrainingJob", _s...) + ret := m.ctrl.Call(m, "DeployTrainingJob", varargs...) ret0, _ := ret[0].(*service.JobDeploymentResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockLifecycleManagerClientRecorder) DeployTrainingJob(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { - _s := append([]interface{}{arg0, arg1}, arg2...) - return _mr.mock.ctrl.RecordCall(_mr.mock, "DeployTrainingJob", _s...) -} - -func (_m *MockLifecycleManagerClient) GetTrainingLogStream(_param0 context.Context, _param1 *service.TrainerContainerInfosRequest, _param2 ...grpc.CallOption) (service.LifecycleManager_GetTrainingLogStreamClient, error) { - _s := []interface{}{_param0, _param1} - for _, _x := range _param2 { - _s = append(_s, _x) - } - ret := _m.ctrl.Call(_m, "GetTrainingLogStream", _s...) - ret0, _ := ret[0].(service.LifecycleManager_GetTrainingLogStreamClient) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -func (_mr *_MockLifecycleManagerClientRecorder) GetTrainingLogStream(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { - _s := append([]interface{}{arg0, arg1}, arg2...) - return _mr.mock.ctrl.RecordCall(_mr.mock, "GetTrainingLogStream", _s...) +// DeployTrainingJob indicates an expected call of DeployTrainingJob +func (mr *MockLifecycleManagerClientMockRecorder) DeployTrainingJob(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { + varargs := append([]interface{}{arg0, arg1}, arg2...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeployTrainingJob", reflect.TypeOf((*MockLifecycleManagerClient)(nil).DeployTrainingJob), varargs...) } -func (_m *MockLifecycleManagerClient) HaltTrainingJob(_param0 context.Context, _param1 *service.JobHaltRequest, _param2 ...grpc.CallOption) (*service.JobHaltResponse, error) { - _s := []interface{}{_param0, _param1} - for _, _x := range _param2 { - _s = append(_s, _x) +// HaltTrainingJob mocks base method +func (m *MockLifecycleManagerClient) HaltTrainingJob(arg0 context.Context, arg1 *service.JobHaltRequest, arg2 ...grpc.CallOption) (*service.JobHaltResponse, error) { + varargs := []interface{}{arg0, arg1} + for _, a := range arg2 { + varargs = append(varargs, a) } - ret := _m.ctrl.Call(_m, "HaltTrainingJob", _s...) + ret := m.ctrl.Call(m, "HaltTrainingJob", varargs...) ret0, _ := ret[0].(*service.JobHaltResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockLifecycleManagerClientRecorder) HaltTrainingJob(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { - _s := append([]interface{}{arg0, arg1}, arg2...) - return _mr.mock.ctrl.RecordCall(_mr.mock, "HaltTrainingJob", _s...) +// HaltTrainingJob indicates an expected call of HaltTrainingJob +func (mr *MockLifecycleManagerClientMockRecorder) HaltTrainingJob(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { + varargs := append([]interface{}{arg0, arg1}, arg2...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HaltTrainingJob", reflect.TypeOf((*MockLifecycleManagerClient)(nil).HaltTrainingJob), varargs...) } -func (_m *MockLifecycleManagerClient) KillTrainingJob(_param0 context.Context, _param1 *service.JobKillRequest, _param2 ...grpc.CallOption) (*service.JobKillResponse, error) { - _s := []interface{}{_param0, _param1} - for _, _x := range _param2 { - _s = append(_s, _x) +// KillTrainingJob mocks base method +func (m *MockLifecycleManagerClient) KillTrainingJob(arg0 context.Context, arg1 *service.JobKillRequest, arg2 ...grpc.CallOption) (*service.JobKillResponse, error) { + varargs := []interface{}{arg0, arg1} + for _, a := range arg2 { + varargs = append(varargs, a) } - ret := _m.ctrl.Call(_m, "KillTrainingJob", _s...) + ret := m.ctrl.Call(m, "KillTrainingJob", varargs...) ret0, _ := ret[0].(*service.JobKillResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockLifecycleManagerClientRecorder) KillTrainingJob(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { - _s := append([]interface{}{arg0, arg1}, arg2...) - return _mr.mock.ctrl.RecordCall(_mr.mock, "KillTrainingJob", _s...) -} - -// GetMetrics(ctx context.Context, in *GetMetricsRequest, opts ...grpc.CallOption) (*GetMetricsResponse, error) -func (_m *MockLifecycleManagerClient) GetMetrics(_param0 context.Context, _param1 *service.GetMetricsRequest, _param2 ...grpc.CallOption) (*service.GetMetricsResponse, error) { - _s := []interface{}{_param0, _param1} - for _, _x := range _param2 { - _s = append(_s, _x) - } - ret := _m.ctrl.Call(_m, "GetMetrics", _s...) - ret0, _ := ret[0].(*service.GetMetricsResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -func (_mr *_MockLifecycleManagerClientRecorder) GetMetrics(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { - _s := append([]interface{}{arg0, arg1}, arg2...) - return _mr.mock.ctrl.RecordCall(_mr.mock, "GetMetrics", _s...) -} - -//CreateEventEndpoint ... mock implementation -func (_m *MockLifecycleManagerClient) CreateEventEndpoint(_param0 context.Context, _param1 *service.CreateEventEndpointRequest, _param2 ...grpc.CallOption) (*service.CreateEventEndpointResponse, error) { - return nil, nil -} - -//DeleteEventEndpoint ... mock impl -func (_m *MockLifecycleManagerClient) DeleteEventEndpoint(_param0 context.Context, _param1 *service.DeleteEventEndpointRequest, _param2 ...grpc.CallOption) (*service.DeleteEventEndpointResponse, error) { - return nil, nil -} - -//GetEventTypeEndpoints ... mock impl -func (_m *MockLifecycleManagerClient) GetEventTypeEndpoints(_param0 context.Context, _param1 *service.GetEventTypeEndpointsRequest, _param2 ...grpc.CallOption) (*service.GetEventTypeEndpointsResponse, error) { - return nil, nil -} - -//GetEventEndpoint ... mock impl -func (_m *MockLifecycleManagerClient) GetEventEndpoint(_param0 context.Context, _param1 *service.GetEventEndpointRequest, _param2 ...grpc.CallOption) (*service.GetEventEndpointResponse, error) { - return nil, nil +// KillTrainingJob indicates an expected call of KillTrainingJob +func (mr *MockLifecycleManagerClientMockRecorder) KillTrainingJob(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { + varargs := append([]interface{}{arg0, arg1}, arg2...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KillTrainingJob", reflect.TypeOf((*MockLifecycleManagerClient)(nil).KillTrainingJob), varargs...) } diff --git a/commons/service/client/lcm.go b/commons/service/client/lcm.go index e5a68efa..bdf7107b 100644 --- a/commons/service/client/lcm.go +++ b/commons/service/client/lcm.go @@ -19,12 +19,12 @@ package client import ( "fmt" + "github.com/grpc-ecosystem/go-grpc-prometheus" + log "github.com/sirupsen/logrus" + "github.com/spf13/viper" "github.com/IBM/FfDL/commons/config" "github.com/IBM/FfDL/commons/service" "github.com/IBM/FfDL/commons/util" - - log "github.com/sirupsen/logrus" - "github.com/spf13/viper" "google.golang.org/grpc" ) @@ -62,6 +62,8 @@ func NewLcm(lcm service.LifecycleManagerClient) (LcmClient, error) { return nil, err } + dialOpts = append(dialOpts, grpc.WithUnaryInterceptor(grpc_prometheus.UnaryClientInterceptor), grpc.WithStreamInterceptor(grpc_prometheus.StreamClientInterceptor)) + if lcm == nil { conn, err := grpc.Dial(address, dialOpts...) if err != nil { diff --git a/commons/service/lcm.pb.go b/commons/service/lcm.pb.go index 0ce399e5..f8444b0c 100644 --- a/commons/service/lcm.pb.go +++ b/commons/service/lcm.pb.go @@ -11,24 +11,12 @@ It has these top-level messages: ResourceRequirements User JobDeploymentRequest + ImageLocation JobDeploymentResponse JobKillRequest JobKillResponse JobHaltRequest JobHaltResponse - TrainerContainerInfosRequest - TrainerLogStreamResponse - CreateEventEndpointRequest - CreateEventEndpointResponse - GetEventTypeEndpointsRequest - GetEventTypeEndpointsResponse - DeleteEventEndpointRequest - DeleteEventEndpointResponse - GetEventEndpointRequest - GetEventEndpointResponse - GetMetricsRequest - GetMetricsResponse - Endpoint */ package service @@ -122,6 +110,7 @@ type ResourceRequirements struct { Architecture string `protobuf:"bytes,8,opt,name=architecture" json:"architecture,omitempty"` Storage float64 `protobuf:"fixed64,9,opt,name=storage" json:"storage,omitempty"` StorageUnit ResourceRequirements_MemoryUnit `protobuf:"varint,10,opt,name=storage_unit,json=storageUnit,enum=service.ResourceRequirements_MemoryUnit" json:"storage_unit,omitempty"` + GpuType string `protobuf:"bytes,11,opt,name=gpu_type,json=gpuType" json:"gpu_type,omitempty"` } func (m *ResourceRequirements) Reset() { *m = ResourceRequirements{} } @@ -199,6 +188,13 @@ func (m *ResourceRequirements) GetStorageUnit() ResourceRequirements_MemoryUnit return ResourceRequirements_MB } +func (m *ResourceRequirements) GetGpuType() string { + if m != nil { + return m.GpuType + } + return "" +} + type User struct { Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"` Roles []string `protobuf:"bytes,2,rep,name=roles" json:"roles,omitempty"` @@ -257,6 +253,8 @@ type JobDeploymentRequest struct { Framework string `protobuf:"bytes,9,opt,name=framework" json:"framework,omitempty"` Version string `protobuf:"bytes,10,opt,name=version" json:"version,omitempty"` EvaluationMetricsSpec string `protobuf:"bytes,11,opt,name=evaluation_metrics_spec,json=evaluationMetricsSpec" json:"evaluation_metrics_spec,omitempty"` + ImageTag string `protobuf:"bytes,12,opt,name=image_tag,json=imageTag" json:"image_tag,omitempty"` + ImageLocation *ImageLocation `protobuf:"bytes,13,opt,name=image_location,json=imageLocation" json:"image_location,omitempty"` } func (m *JobDeploymentRequest) Reset() { *m = JobDeploymentRequest{} } @@ -327,6 +325,60 @@ func (m *JobDeploymentRequest) GetEvaluationMetricsSpec() string { return "" } +func (m *JobDeploymentRequest) GetImageTag() string { + if m != nil { + return m.ImageTag + } + return "" +} + +func (m *JobDeploymentRequest) GetImageLocation() *ImageLocation { + if m != nil { + return m.ImageLocation + } + return nil +} + +type ImageLocation struct { + Registry string `protobuf:"bytes,1,opt,name=registry" json:"registry,omitempty"` + Namespace string `protobuf:"bytes,2,opt,name=namespace" json:"namespace,omitempty"` + AccessToken string `protobuf:"bytes,3,opt,name=access_token,json=accessToken" json:"access_token,omitempty"` + Email string `protobuf:"bytes,4,opt,name=email" json:"email,omitempty"` +} + +func (m *ImageLocation) Reset() { *m = ImageLocation{} } +func (m *ImageLocation) String() string { return proto.CompactTextString(m) } +func (*ImageLocation) ProtoMessage() {} +func (*ImageLocation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *ImageLocation) GetRegistry() string { + if m != nil { + return m.Registry + } + return "" +} + +func (m *ImageLocation) GetNamespace() string { + if m != nil { + return m.Namespace + } + return "" +} + +func (m *ImageLocation) GetAccessToken() string { + if m != nil { + return m.AccessToken + } + return "" +} + +func (m *ImageLocation) GetEmail() string { + if m != nil { + return m.Email + } + return "" +} + type JobDeploymentResponse struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Status string `protobuf:"bytes,2,opt,name=status" json:"status,omitempty"` @@ -335,7 +387,7 @@ type JobDeploymentResponse struct { func (m *JobDeploymentResponse) Reset() { *m = JobDeploymentResponse{} } func (m *JobDeploymentResponse) String() string { return proto.CompactTextString(m) } func (*JobDeploymentResponse) ProtoMessage() {} -func (*JobDeploymentResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (*JobDeploymentResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } func (m *JobDeploymentResponse) GetName() string { if m != nil { @@ -360,7 +412,7 @@ type JobKillRequest struct { func (m *JobKillRequest) Reset() { *m = JobKillRequest{} } func (m *JobKillRequest) String() string { return proto.CompactTextString(m) } func (*JobKillRequest) ProtoMessage() {} -func (*JobKillRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } +func (*JobKillRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } func (m *JobKillRequest) GetName() string { if m != nil { @@ -389,7 +441,7 @@ type JobKillResponse struct { func (m *JobKillResponse) Reset() { *m = JobKillResponse{} } func (m *JobKillResponse) String() string { return proto.CompactTextString(m) } func (*JobKillResponse) ProtoMessage() {} -func (*JobKillResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } +func (*JobKillResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } type JobHaltRequest struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` @@ -400,7 +452,7 @@ type JobHaltRequest struct { func (m *JobHaltRequest) Reset() { *m = JobHaltRequest{} } func (m *JobHaltRequest) String() string { return proto.CompactTextString(m) } func (*JobHaltRequest) ProtoMessage() {} -func (*JobHaltRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } +func (*JobHaltRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } func (m *JobHaltRequest) GetName() string { if m != nil { @@ -429,374 +481,18 @@ type JobHaltResponse struct { func (m *JobHaltResponse) Reset() { *m = JobHaltResponse{} } func (m *JobHaltResponse) String() string { return proto.CompactTextString(m) } func (*JobHaltResponse) ProtoMessage() {} -func (*JobHaltResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } - -type TrainerContainerInfosRequest struct { - TrainingId string `protobuf:"bytes,1,opt,name=training_id,json=trainingId" json:"training_id,omitempty"` - UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId" json:"user_id,omitempty"` - Follow bool `protobuf:"varint,3,opt,name=follow" json:"follow,omitempty"` - Metrics bool `protobuf:"varint,4,opt,name=metrics" json:"metrics,omitempty"` - Summary bool `protobuf:"varint,5,opt,name=summary" json:"summary,omitempty"` -} - -func (m *TrainerContainerInfosRequest) Reset() { *m = TrainerContainerInfosRequest{} } -func (m *TrainerContainerInfosRequest) String() string { return proto.CompactTextString(m) } -func (*TrainerContainerInfosRequest) ProtoMessage() {} -func (*TrainerContainerInfosRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } - -func (m *TrainerContainerInfosRequest) GetTrainingId() string { - if m != nil { - return m.TrainingId - } - return "" -} - -func (m *TrainerContainerInfosRequest) GetUserId() string { - if m != nil { - return m.UserId - } - return "" -} - -func (m *TrainerContainerInfosRequest) GetFollow() bool { - if m != nil { - return m.Follow - } - return false -} - -func (m *TrainerContainerInfosRequest) GetMetrics() bool { - if m != nil { - return m.Metrics - } - return false -} - -func (m *TrainerContainerInfosRequest) GetSummary() bool { - if m != nil { - return m.Summary - } - return false -} - -type TrainerLogStreamResponse struct { - Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` -} - -func (m *TrainerLogStreamResponse) Reset() { *m = TrainerLogStreamResponse{} } -func (m *TrainerLogStreamResponse) String() string { return proto.CompactTextString(m) } -func (*TrainerLogStreamResponse) ProtoMessage() {} -func (*TrainerLogStreamResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } - -func (m *TrainerLogStreamResponse) GetData() []byte { - if m != nil { - return m.Data - } - return nil -} - -type CreateEventEndpointRequest struct { - TrainingId string `protobuf:"bytes,1,opt,name=training_id,json=trainingId" json:"training_id,omitempty"` - UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId" json:"user_id,omitempty"` - EventType string `protobuf:"bytes,3,opt,name=event_type,json=eventType" json:"event_type,omitempty"` - EndpointUrl string `protobuf:"bytes,4,opt,name=endpoint_url,json=endpointUrl" json:"endpoint_url,omitempty"` - EndpointType string `protobuf:"bytes,5,opt,name=endpoint_type,json=endpointType" json:"endpoint_type,omitempty"` - EndpointId string `protobuf:"bytes,6,opt,name=endpoint_id,json=endpointId" json:"endpoint_id,omitempty"` -} - -func (m *CreateEventEndpointRequest) Reset() { *m = CreateEventEndpointRequest{} } -func (m *CreateEventEndpointRequest) String() string { return proto.CompactTextString(m) } -func (*CreateEventEndpointRequest) ProtoMessage() {} -func (*CreateEventEndpointRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } - -func (m *CreateEventEndpointRequest) GetTrainingId() string { - if m != nil { - return m.TrainingId - } - return "" -} - -func (m *CreateEventEndpointRequest) GetUserId() string { - if m != nil { - return m.UserId - } - return "" -} - -func (m *CreateEventEndpointRequest) GetEventType() string { - if m != nil { - return m.EventType - } - return "" -} - -func (m *CreateEventEndpointRequest) GetEndpointUrl() string { - if m != nil { - return m.EndpointUrl - } - return "" -} - -func (m *CreateEventEndpointRequest) GetEndpointType() string { - if m != nil { - return m.EndpointType - } - return "" -} - -func (m *CreateEventEndpointRequest) GetEndpointId() string { - if m != nil { - return m.EndpointId - } - return "" -} - -type CreateEventEndpointResponse struct { -} - -func (m *CreateEventEndpointResponse) Reset() { *m = CreateEventEndpointResponse{} } -func (m *CreateEventEndpointResponse) String() string { return proto.CompactTextString(m) } -func (*CreateEventEndpointResponse) ProtoMessage() {} -func (*CreateEventEndpointResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } - -type GetEventTypeEndpointsRequest struct { - TrainingId string `protobuf:"bytes,1,opt,name=training_id,json=trainingId" json:"training_id,omitempty"` - UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId" json:"user_id,omitempty"` - EventType string `protobuf:"bytes,3,opt,name=event_type,json=eventType" json:"event_type,omitempty"` -} - -func (m *GetEventTypeEndpointsRequest) Reset() { *m = GetEventTypeEndpointsRequest{} } -func (m *GetEventTypeEndpointsRequest) String() string { return proto.CompactTextString(m) } -func (*GetEventTypeEndpointsRequest) ProtoMessage() {} -func (*GetEventTypeEndpointsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } - -func (m *GetEventTypeEndpointsRequest) GetTrainingId() string { - if m != nil { - return m.TrainingId - } - return "" -} - -func (m *GetEventTypeEndpointsRequest) GetUserId() string { - if m != nil { - return m.UserId - } - return "" -} - -func (m *GetEventTypeEndpointsRequest) GetEventType() string { - if m != nil { - return m.EventType - } - return "" -} - -type GetEventTypeEndpointsResponse struct { - Endpoints []*Endpoint `protobuf:"bytes,1,rep,name=endpoints" json:"endpoints,omitempty"` -} - -func (m *GetEventTypeEndpointsResponse) Reset() { *m = GetEventTypeEndpointsResponse{} } -func (m *GetEventTypeEndpointsResponse) String() string { return proto.CompactTextString(m) } -func (*GetEventTypeEndpointsResponse) ProtoMessage() {} -func (*GetEventTypeEndpointsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } - -func (m *GetEventTypeEndpointsResponse) GetEndpoints() []*Endpoint { - if m != nil { - return m.Endpoints - } - return nil -} - -type DeleteEventEndpointRequest struct { - TrainingId string `protobuf:"bytes,1,opt,name=training_id,json=trainingId" json:"training_id,omitempty"` - UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId" json:"user_id,omitempty"` - EventType string `protobuf:"bytes,3,opt,name=event_type,json=eventType" json:"event_type,omitempty"` - EndpointId string `protobuf:"bytes,4,opt,name=endpoint_id,json=endpointId" json:"endpoint_id,omitempty"` -} - -func (m *DeleteEventEndpointRequest) Reset() { *m = DeleteEventEndpointRequest{} } -func (m *DeleteEventEndpointRequest) String() string { return proto.CompactTextString(m) } -func (*DeleteEventEndpointRequest) ProtoMessage() {} -func (*DeleteEventEndpointRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } - -func (m *DeleteEventEndpointRequest) GetTrainingId() string { - if m != nil { - return m.TrainingId - } - return "" -} - -func (m *DeleteEventEndpointRequest) GetUserId() string { - if m != nil { - return m.UserId - } - return "" -} - -func (m *DeleteEventEndpointRequest) GetEventType() string { - if m != nil { - return m.EventType - } - return "" -} - -func (m *DeleteEventEndpointRequest) GetEndpointId() string { - if m != nil { - return m.EndpointId - } - return "" -} - -type DeleteEventEndpointResponse struct { -} - -func (m *DeleteEventEndpointResponse) Reset() { *m = DeleteEventEndpointResponse{} } -func (m *DeleteEventEndpointResponse) String() string { return proto.CompactTextString(m) } -func (*DeleteEventEndpointResponse) ProtoMessage() {} -func (*DeleteEventEndpointResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } - -type GetEventEndpointRequest struct { - TrainingId string `protobuf:"bytes,1,opt,name=training_id,json=trainingId" json:"training_id,omitempty"` - UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId" json:"user_id,omitempty"` - EventType string `protobuf:"bytes,3,opt,name=event_type,json=eventType" json:"event_type,omitempty"` - EndpointId string `protobuf:"bytes,4,opt,name=endpoint_id,json=endpointId" json:"endpoint_id,omitempty"` -} - -func (m *GetEventEndpointRequest) Reset() { *m = GetEventEndpointRequest{} } -func (m *GetEventEndpointRequest) String() string { return proto.CompactTextString(m) } -func (*GetEventEndpointRequest) ProtoMessage() {} -func (*GetEventEndpointRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } - -func (m *GetEventEndpointRequest) GetTrainingId() string { - if m != nil { - return m.TrainingId - } - return "" -} - -func (m *GetEventEndpointRequest) GetUserId() string { - if m != nil { - return m.UserId - } - return "" -} - -func (m *GetEventEndpointRequest) GetEventType() string { - if m != nil { - return m.EventType - } - return "" -} - -func (m *GetEventEndpointRequest) GetEndpointId() string { - if m != nil { - return m.EndpointId - } - return "" -} - -type GetEventEndpointResponse struct { - Url string `protobuf:"bytes,1,opt,name=url" json:"url,omitempty"` - EndpointType string `protobuf:"bytes,2,opt,name=endpoint_type,json=endpointType" json:"endpoint_type,omitempty"` -} - -func (m *GetEventEndpointResponse) Reset() { *m = GetEventEndpointResponse{} } -func (m *GetEventEndpointResponse) String() string { return proto.CompactTextString(m) } -func (*GetEventEndpointResponse) ProtoMessage() {} -func (*GetEventEndpointResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } - -func (m *GetEventEndpointResponse) GetUrl() string { - if m != nil { - return m.Url - } - return "" -} - -func (m *GetEventEndpointResponse) GetEndpointType() string { - if m != nil { - return m.EndpointType - } - return "" -} - -type GetMetricsRequest struct { - TrainingId string `protobuf:"bytes,1,opt,name=training_id,json=trainingId" json:"training_id,omitempty"` -} - -func (m *GetMetricsRequest) Reset() { *m = GetMetricsRequest{} } -func (m *GetMetricsRequest) String() string { return proto.CompactTextString(m) } -func (*GetMetricsRequest) ProtoMessage() {} -func (*GetMetricsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } - -func (m *GetMetricsRequest) GetTrainingId() string { - if m != nil { - return m.TrainingId - } - return "" -} - -type GetMetricsResponse struct { - Metrics string `protobuf:"bytes,1,opt,name=metrics" json:"metrics,omitempty"` -} - -func (m *GetMetricsResponse) Reset() { *m = GetMetricsResponse{} } -func (m *GetMetricsResponse) String() string { return proto.CompactTextString(m) } -func (*GetMetricsResponse) ProtoMessage() {} -func (*GetMetricsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } - -func (m *GetMetricsResponse) GetMetrics() string { - if m != nil { - return m.Metrics - } - return "" -} - -type Endpoint struct { - Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"` - Url string `protobuf:"bytes,2,opt,name=url" json:"url,omitempty"` -} - -func (m *Endpoint) Reset() { *m = Endpoint{} } -func (m *Endpoint) String() string { return proto.CompactTextString(m) } -func (*Endpoint) ProtoMessage() {} -func (*Endpoint) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } - -func (m *Endpoint) GetId() string { - if m != nil { - return m.Id - } - return "" -} - -func (m *Endpoint) GetUrl() string { - if m != nil { - return m.Url - } - return "" -} +func (*JobHaltResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } func init() { proto.RegisterType((*ResourceRequirements)(nil), "service.ResourceRequirements") proto.RegisterType((*User)(nil), "service.User") proto.RegisterType((*JobDeploymentRequest)(nil), "service.JobDeploymentRequest") + proto.RegisterType((*ImageLocation)(nil), "service.ImageLocation") proto.RegisterType((*JobDeploymentResponse)(nil), "service.JobDeploymentResponse") proto.RegisterType((*JobKillRequest)(nil), "service.JobKillRequest") proto.RegisterType((*JobKillResponse)(nil), "service.JobKillResponse") proto.RegisterType((*JobHaltRequest)(nil), "service.JobHaltRequest") proto.RegisterType((*JobHaltResponse)(nil), "service.JobHaltResponse") - proto.RegisterType((*TrainerContainerInfosRequest)(nil), "service.TrainerContainerInfosRequest") - proto.RegisterType((*TrainerLogStreamResponse)(nil), "service.TrainerLogStreamResponse") - proto.RegisterType((*CreateEventEndpointRequest)(nil), "service.CreateEventEndpointRequest") - proto.RegisterType((*CreateEventEndpointResponse)(nil), "service.CreateEventEndpointResponse") - proto.RegisterType((*GetEventTypeEndpointsRequest)(nil), "service.GetEventTypeEndpointsRequest") - proto.RegisterType((*GetEventTypeEndpointsResponse)(nil), "service.GetEventTypeEndpointsResponse") - proto.RegisterType((*DeleteEventEndpointRequest)(nil), "service.DeleteEventEndpointRequest") - proto.RegisterType((*DeleteEventEndpointResponse)(nil), "service.DeleteEventEndpointResponse") - proto.RegisterType((*GetEventEndpointRequest)(nil), "service.GetEventEndpointRequest") - proto.RegisterType((*GetEventEndpointResponse)(nil), "service.GetEventEndpointResponse") - proto.RegisterType((*GetMetricsRequest)(nil), "service.GetMetricsRequest") - proto.RegisterType((*GetMetricsResponse)(nil), "service.GetMetricsResponse") - proto.RegisterType((*Endpoint)(nil), "service.Endpoint") proto.RegisterEnum("service.StatusMessages", StatusMessages_name, StatusMessages_value) proto.RegisterEnum("service.ResourceRequirements_MemoryUnit", ResourceRequirements_MemoryUnit_name, ResourceRequirements_MemoryUnit_value) } @@ -814,17 +510,7 @@ const _ = grpc.SupportPackageIsVersion4 type LifecycleManagerClient interface { DeployTrainingJob(ctx context.Context, in *JobDeploymentRequest, opts ...grpc.CallOption) (*JobDeploymentResponse, error) KillTrainingJob(ctx context.Context, in *JobKillRequest, opts ...grpc.CallOption) (*JobKillResponse, error) - GetTrainingLogStream(ctx context.Context, in *TrainerContainerInfosRequest, opts ...grpc.CallOption) (LifecycleManager_GetTrainingLogStreamClient, error) HaltTrainingJob(ctx context.Context, in *JobHaltRequest, opts ...grpc.CallOption) (*JobHaltResponse, error) - // creates an endpoint with a specific id for an event type - CreateEventEndpoint(ctx context.Context, in *CreateEventEndpointRequest, opts ...grpc.CallOption) (*CreateEventEndpointResponse, error) - // deletes a specific endpoint (defined by event type and endpoint id) - DeleteEventEndpoint(ctx context.Context, in *DeleteEventEndpointRequest, opts ...grpc.CallOption) (*DeleteEventEndpointResponse, error) - // gets all endpoints registered for an event type - GetEventTypeEndpoints(ctx context.Context, in *GetEventTypeEndpointsRequest, opts ...grpc.CallOption) (*GetEventTypeEndpointsResponse, error) - // gets a specific endpoint - GetEventEndpoint(ctx context.Context, in *GetEventEndpointRequest, opts ...grpc.CallOption) (*GetEventEndpointResponse, error) - GetMetrics(ctx context.Context, in *GetMetricsRequest, opts ...grpc.CallOption) (*GetMetricsResponse, error) } type lifecycleManagerClient struct { @@ -853,38 +539,6 @@ func (c *lifecycleManagerClient) KillTrainingJob(ctx context.Context, in *JobKil return out, nil } -func (c *lifecycleManagerClient) GetTrainingLogStream(ctx context.Context, in *TrainerContainerInfosRequest, opts ...grpc.CallOption) (LifecycleManager_GetTrainingLogStreamClient, error) { - stream, err := grpc.NewClientStream(ctx, &_LifecycleManager_serviceDesc.Streams[0], c.cc, "/service.LifecycleManager/GetTrainingLogStream", opts...) - if err != nil { - return nil, err - } - x := &lifecycleManagerGetTrainingLogStreamClient{stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -type LifecycleManager_GetTrainingLogStreamClient interface { - Recv() (*TrainerLogStreamResponse, error) - grpc.ClientStream -} - -type lifecycleManagerGetTrainingLogStreamClient struct { - grpc.ClientStream -} - -func (x *lifecycleManagerGetTrainingLogStreamClient) Recv() (*TrainerLogStreamResponse, error) { - m := new(TrainerLogStreamResponse) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - func (c *lifecycleManagerClient) HaltTrainingJob(ctx context.Context, in *JobHaltRequest, opts ...grpc.CallOption) (*JobHaltResponse, error) { out := new(JobHaltResponse) err := grpc.Invoke(ctx, "/service.LifecycleManager/HaltTrainingJob", in, out, c.cc, opts...) @@ -894,67 +548,12 @@ func (c *lifecycleManagerClient) HaltTrainingJob(ctx context.Context, in *JobHal return out, nil } -func (c *lifecycleManagerClient) CreateEventEndpoint(ctx context.Context, in *CreateEventEndpointRequest, opts ...grpc.CallOption) (*CreateEventEndpointResponse, error) { - out := new(CreateEventEndpointResponse) - err := grpc.Invoke(ctx, "/service.LifecycleManager/CreateEventEndpoint", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *lifecycleManagerClient) DeleteEventEndpoint(ctx context.Context, in *DeleteEventEndpointRequest, opts ...grpc.CallOption) (*DeleteEventEndpointResponse, error) { - out := new(DeleteEventEndpointResponse) - err := grpc.Invoke(ctx, "/service.LifecycleManager/DeleteEventEndpoint", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *lifecycleManagerClient) GetEventTypeEndpoints(ctx context.Context, in *GetEventTypeEndpointsRequest, opts ...grpc.CallOption) (*GetEventTypeEndpointsResponse, error) { - out := new(GetEventTypeEndpointsResponse) - err := grpc.Invoke(ctx, "/service.LifecycleManager/GetEventTypeEndpoints", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *lifecycleManagerClient) GetEventEndpoint(ctx context.Context, in *GetEventEndpointRequest, opts ...grpc.CallOption) (*GetEventEndpointResponse, error) { - out := new(GetEventEndpointResponse) - err := grpc.Invoke(ctx, "/service.LifecycleManager/GetEventEndpoint", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *lifecycleManagerClient) GetMetrics(ctx context.Context, in *GetMetricsRequest, opts ...grpc.CallOption) (*GetMetricsResponse, error) { - out := new(GetMetricsResponse) - err := grpc.Invoke(ctx, "/service.LifecycleManager/GetMetrics", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - // Server API for LifecycleManager service type LifecycleManagerServer interface { DeployTrainingJob(context.Context, *JobDeploymentRequest) (*JobDeploymentResponse, error) KillTrainingJob(context.Context, *JobKillRequest) (*JobKillResponse, error) - GetTrainingLogStream(*TrainerContainerInfosRequest, LifecycleManager_GetTrainingLogStreamServer) error HaltTrainingJob(context.Context, *JobHaltRequest) (*JobHaltResponse, error) - // creates an endpoint with a specific id for an event type - CreateEventEndpoint(context.Context, *CreateEventEndpointRequest) (*CreateEventEndpointResponse, error) - // deletes a specific endpoint (defined by event type and endpoint id) - DeleteEventEndpoint(context.Context, *DeleteEventEndpointRequest) (*DeleteEventEndpointResponse, error) - // gets all endpoints registered for an event type - GetEventTypeEndpoints(context.Context, *GetEventTypeEndpointsRequest) (*GetEventTypeEndpointsResponse, error) - // gets a specific endpoint - GetEventEndpoint(context.Context, *GetEventEndpointRequest) (*GetEventEndpointResponse, error) - GetMetrics(context.Context, *GetMetricsRequest) (*GetMetricsResponse, error) } func RegisterLifecycleManagerServer(s *grpc.Server, srv LifecycleManagerServer) { @@ -997,27 +596,6 @@ func _LifecycleManager_KillTrainingJob_Handler(srv interface{}, ctx context.Cont return interceptor(ctx, in, info, handler) } -func _LifecycleManager_GetTrainingLogStream_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(TrainerContainerInfosRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(LifecycleManagerServer).GetTrainingLogStream(m, &lifecycleManagerGetTrainingLogStreamServer{stream}) -} - -type LifecycleManager_GetTrainingLogStreamServer interface { - Send(*TrainerLogStreamResponse) error - grpc.ServerStream -} - -type lifecycleManagerGetTrainingLogStreamServer struct { - grpc.ServerStream -} - -func (x *lifecycleManagerGetTrainingLogStreamServer) Send(m *TrainerLogStreamResponse) error { - return x.ServerStream.SendMsg(m) -} - func _LifecycleManager_HaltTrainingJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(JobHaltRequest) if err := dec(in); err != nil { @@ -1036,96 +614,6 @@ func _LifecycleManager_HaltTrainingJob_Handler(srv interface{}, ctx context.Cont return interceptor(ctx, in, info, handler) } -func _LifecycleManager_CreateEventEndpoint_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CreateEventEndpointRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(LifecycleManagerServer).CreateEventEndpoint(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/service.LifecycleManager/CreateEventEndpoint", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(LifecycleManagerServer).CreateEventEndpoint(ctx, req.(*CreateEventEndpointRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _LifecycleManager_DeleteEventEndpoint_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(DeleteEventEndpointRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(LifecycleManagerServer).DeleteEventEndpoint(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/service.LifecycleManager/DeleteEventEndpoint", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(LifecycleManagerServer).DeleteEventEndpoint(ctx, req.(*DeleteEventEndpointRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _LifecycleManager_GetEventTypeEndpoints_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetEventTypeEndpointsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(LifecycleManagerServer).GetEventTypeEndpoints(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/service.LifecycleManager/GetEventTypeEndpoints", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(LifecycleManagerServer).GetEventTypeEndpoints(ctx, req.(*GetEventTypeEndpointsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _LifecycleManager_GetEventEndpoint_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetEventEndpointRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(LifecycleManagerServer).GetEventEndpoint(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/service.LifecycleManager/GetEventEndpoint", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(LifecycleManagerServer).GetEventEndpoint(ctx, req.(*GetEventEndpointRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _LifecycleManager_GetMetrics_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetMetricsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(LifecycleManagerServer).GetMetrics(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/service.LifecycleManager/GetMetrics", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(LifecycleManagerServer).GetMetrics(ctx, req.(*GetMetricsRequest)) - } - return interceptor(ctx, in, info, handler) -} - var _LifecycleManager_serviceDesc = grpc.ServiceDesc{ ServiceName: "service.LifecycleManager", HandlerType: (*LifecycleManagerServer)(nil), @@ -1142,116 +630,71 @@ var _LifecycleManager_serviceDesc = grpc.ServiceDesc{ MethodName: "HaltTrainingJob", Handler: _LifecycleManager_HaltTrainingJob_Handler, }, - { - MethodName: "CreateEventEndpoint", - Handler: _LifecycleManager_CreateEventEndpoint_Handler, - }, - { - MethodName: "DeleteEventEndpoint", - Handler: _LifecycleManager_DeleteEventEndpoint_Handler, - }, - { - MethodName: "GetEventTypeEndpoints", - Handler: _LifecycleManager_GetEventTypeEndpoints_Handler, - }, - { - MethodName: "GetEventEndpoint", - Handler: _LifecycleManager_GetEventEndpoint_Handler, - }, - { - MethodName: "GetMetrics", - Handler: _LifecycleManager_GetMetrics_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "GetTrainingLogStream", - Handler: _LifecycleManager_GetTrainingLogStream_Handler, - ServerStreams: true, - }, }, + Streams: []grpc.StreamDesc{}, Metadata: "lcm.proto", } func init() { proto.RegisterFile("lcm.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1225 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x57, 0xef, 0x6e, 0x1b, 0x45, - 0x10, 0xcf, 0xd9, 0x8e, 0xe3, 0x1b, 0x87, 0xf4, 0xb2, 0xa4, 0xc9, 0xe9, 0xda, 0xd0, 0xf4, 0x0a, - 0xc8, 0x54, 0xc8, 0xa0, 0x80, 0x10, 0x94, 0x0f, 0x28, 0x49, 0xdd, 0xe0, 0x36, 0x4e, 0xca, 0xc6, - 0xa9, 0xc4, 0x17, 0xac, 0xcb, 0x79, 0xe2, 0x9e, 0x7a, 0x7f, 0xcc, 0xee, 0xda, 0x95, 0x25, 0x9e, - 0x02, 0x24, 0x9e, 0x80, 0x47, 0xe0, 0x1d, 0x78, 0x0b, 0x9e, 0x05, 0xed, 0xde, 0xde, 0xf9, 0x62, - 0x3b, 0x86, 0x22, 0x15, 0xf1, 0x6d, 0x67, 0x66, 0x67, 0xe6, 0x37, 0x7f, 0xee, 0xb7, 0x36, 0x98, - 0xa1, 0x1f, 0x35, 0x87, 0x2c, 0x11, 0x09, 0x59, 0xe3, 0xc8, 0xc6, 0x81, 0x8f, 0xee, 0x1f, 0x65, - 0xd8, 0xa2, 0xc8, 0x93, 0x11, 0xf3, 0x91, 0xe2, 0x8f, 0xa3, 0x80, 0x61, 0x84, 0xb1, 0xe0, 0x84, - 0x40, 0xc5, 0x1f, 0x8e, 0xb8, 0x6d, 0xec, 0x19, 0x0d, 0x83, 0xaa, 0xb3, 0xd4, 0x0d, 0xa4, 0xae, - 0x94, 0xea, 0xe4, 0x99, 0x6c, 0x43, 0x35, 0xc2, 0x28, 0x61, 0x13, 0xbb, 0xac, 0xb4, 0x5a, 0x22, - 0x6d, 0xa8, 0xa7, 0xa7, 0xde, 0x28, 0x0e, 0x84, 0x5d, 0xd9, 0x33, 0x1a, 0x1b, 0xfb, 0x8d, 0xa6, - 0xce, 0xdb, 0x5c, 0x94, 0xb3, 0xd9, 0x51, 0x0e, 0x17, 0x71, 0x20, 0x28, 0x44, 0xf9, 0x99, 0x38, - 0x50, 0x0b, 0xd1, 0x63, 0x31, 0x32, 0x6e, 0xaf, 0xee, 0x19, 0x8d, 0x55, 0x9a, 0xcb, 0x64, 0x0f, - 0xea, 0xdc, 0x7f, 0x89, 0xfd, 0x61, 0x12, 0x06, 0xfe, 0xc4, 0xae, 0xee, 0x19, 0x0d, 0x93, 0x16, - 0x55, 0xd2, 0x5b, 0x24, 0xc3, 0x24, 0x4c, 0x06, 0x13, 0x7b, 0x4d, 0x99, 0x73, 0x99, 0xb8, 0xb0, - 0xee, 0x31, 0xff, 0x65, 0x20, 0xd0, 0x17, 0x23, 0x86, 0x76, 0x4d, 0xd9, 0xaf, 0xe9, 0x88, 0x0d, - 0x6b, 0x5c, 0x24, 0xcc, 0x1b, 0xa0, 0x6d, 0xaa, 0x0a, 0x33, 0x91, 0x3c, 0x83, 0x75, 0x7d, 0x4c, - 0x6b, 0x84, 0x37, 0xac, 0xb1, 0xae, 0xbd, 0xa5, 0xe0, 0x7e, 0x03, 0x30, 0x35, 0x91, 0x2a, 0x94, - 0x3a, 0x87, 0xd6, 0x0a, 0x59, 0x83, 0x72, 0x27, 0x38, 0xb4, 0x0c, 0xa9, 0x38, 0x3e, 0xb4, 0x4a, - 0x52, 0x71, 0x1c, 0x1c, 0x5a, 0x65, 0xa9, 0xe8, 0x1e, 0x5a, 0x15, 0xa9, 0xe8, 0x06, 0x87, 0xd6, - 0xaa, 0xfb, 0x13, 0x54, 0x2e, 0x38, 0x32, 0xb2, 0x01, 0xa5, 0xa0, 0xaf, 0xc6, 0x66, 0xd2, 0x52, - 0xd0, 0x27, 0x5b, 0xb0, 0xca, 0x92, 0x10, 0xe5, 0xd4, 0xca, 0x0d, 0x93, 0xa6, 0x02, 0xb9, 0x0b, - 0xe6, 0x55, 0xc0, 0xb8, 0x88, 0xbd, 0x08, 0xd5, 0xe4, 0x4c, 0x3a, 0x55, 0xa8, 0x8e, 0x7b, 0xda, - 0x58, 0x49, 0x7b, 0x96, 0xc9, 0x32, 0x1e, 0x46, 0x5e, 0x10, 0xaa, 0x51, 0x98, 0x34, 0x15, 0xdc, - 0x9f, 0x2b, 0xb0, 0xf5, 0x34, 0xb9, 0x7c, 0x8c, 0xc3, 0x30, 0x99, 0xc8, 0x4a, 0x65, 0xd1, 0xc8, - 0x85, 0xdc, 0x19, 0x15, 0x26, 0x05, 0xa4, 0xce, 0xe4, 0x6b, 0x30, 0x99, 0xee, 0x0d, 0x57, 0xf1, - 0xeb, 0xfb, 0xbb, 0x4b, 0xbb, 0x46, 0xa7, 0xf7, 0x49, 0x0b, 0x6a, 0x18, 0x8f, 0x7b, 0x63, 0x4f, - 0x6d, 0x43, 0xb9, 0x51, 0xdf, 0x7f, 0x98, 0xfb, 0x2e, 0x42, 0xd0, 0x6c, 0xc5, 0xe3, 0x17, 0x1e, - 0xe3, 0xad, 0x58, 0xb0, 0x09, 0x5d, 0xc3, 0x54, 0x22, 0x07, 0x50, 0x0d, 0xbd, 0x4b, 0x0c, 0xb9, - 0x5d, 0x55, 0x41, 0x3e, 0x5a, 0x1e, 0xe4, 0x44, 0xdd, 0x4d, 0x63, 0x68, 0x47, 0xb2, 0x03, 0x6b, - 0x23, 0x8e, 0xac, 0x17, 0xf4, 0xf5, 0x62, 0x55, 0xa5, 0xd8, 0xee, 0x93, 0x7b, 0x50, 0x17, 0xcc, - 0x0b, 0xe2, 0x20, 0x1e, 0x48, 0x63, 0xba, 0x55, 0x90, 0xa9, 0xda, 0x7d, 0xd5, 0x7d, 0xe6, 0x45, - 0xf8, 0x3a, 0x61, 0xaf, 0xd4, 0x56, 0xc9, 0xee, 0x67, 0x0a, 0xb9, 0x71, 0x63, 0x64, 0x3c, 0x48, - 0x62, 0xb5, 0x52, 0x26, 0xcd, 0x44, 0xf2, 0x05, 0xec, 0xe0, 0xd8, 0x0b, 0x47, 0x9e, 0x08, 0x92, - 0xb8, 0x17, 0xa1, 0x60, 0x81, 0xcf, 0x7b, 0x7c, 0x88, 0xbe, 0x5d, 0x57, 0x37, 0x6f, 0x4f, 0xcd, - 0x9d, 0xd4, 0x7a, 0x3e, 0x44, 0xdf, 0x79, 0x04, 0xeb, 0xc5, 0x2e, 0x10, 0x0b, 0xca, 0xaf, 0x70, - 0xa2, 0x67, 0x22, 0x8f, 0x72, 0xaa, 0xd2, 0x13, 0xd5, 0xb7, 0x6d, 0xd2, 0x54, 0x78, 0x54, 0xfa, - 0xd2, 0x70, 0xbe, 0x82, 0x7a, 0xa1, 0xf8, 0x37, 0x71, 0x75, 0x8f, 0xe0, 0xf6, 0x4c, 0x33, 0xf9, - 0x30, 0x89, 0x39, 0x2e, 0x5c, 0x8a, 0x6d, 0xa8, 0x72, 0xe1, 0x09, 0x4d, 0x2f, 0x26, 0xd5, 0x92, - 0xfb, 0x03, 0x6c, 0x3c, 0x4d, 0x2e, 0x9f, 0x05, 0x61, 0xb8, 0x6c, 0xa5, 0x66, 0x5a, 0x5e, 0x9a, - 0x6b, 0x79, 0x61, 0x58, 0xe5, 0xe2, 0xb0, 0xdc, 0x4d, 0xb8, 0x95, 0xc7, 0x4f, 0xe1, 0xe9, 0x94, - 0xdf, 0x7a, 0xa1, 0x78, 0x9b, 0x29, 0xd3, 0xf8, 0x3a, 0xe5, 0x6f, 0x06, 0xdc, 0xed, 0x4a, 0x57, - 0x64, 0x47, 0x49, 0x2c, 0xd4, 0xa1, 0x1d, 0x5f, 0x25, 0x3c, 0x43, 0x30, 0x93, 0xcd, 0x58, 0x96, - 0xad, 0x74, 0x6d, 0x1b, 0xb7, 0xa1, 0x7a, 0x95, 0x84, 0x61, 0xf2, 0x5a, 0xa1, 0xa8, 0x51, 0x2d, - 0xc9, 0x35, 0xd3, 0x1b, 0xa4, 0xbe, 0xc1, 0x1a, 0xcd, 0x44, 0x45, 0x79, 0xa3, 0x28, 0xf2, 0xd8, - 0x44, 0x7d, 0xe4, 0x35, 0x9a, 0x89, 0x6e, 0x13, 0x6c, 0x8d, 0xf2, 0x24, 0x19, 0x9c, 0x0b, 0x86, - 0x5e, 0x54, 0x1c, 0x6a, 0xdf, 0x13, 0x9e, 0x82, 0xb6, 0x4e, 0xd5, 0xd9, 0xfd, 0xd3, 0x00, 0xe7, - 0x88, 0xa1, 0x27, 0xb0, 0x35, 0xc6, 0x58, 0xb4, 0xe2, 0xfe, 0x30, 0x09, 0xa6, 0xe4, 0xf0, 0xef, - 0x8b, 0xda, 0x05, 0x40, 0x19, 0xb1, 0x27, 0x26, 0xc3, 0x9c, 0xc0, 0x94, 0xa6, 0x3b, 0x19, 0x22, - 0xb9, 0x0f, 0xeb, 0xa8, 0x73, 0xf5, 0x46, 0x2c, 0xd4, 0x24, 0x56, 0xcf, 0x74, 0x17, 0x2c, 0x24, - 0x0f, 0xe0, 0x9d, 0xfc, 0x8a, 0x0a, 0x92, 0xf2, 0x59, 0xee, 0xa7, 0xe2, 0xdc, 0x83, 0xdc, 0x47, - 0x62, 0x48, 0x9f, 0x17, 0xc8, 0x54, 0xed, 0xbe, 0xbb, 0x0b, 0x77, 0x16, 0xd6, 0xa7, 0xc7, 0xfa, - 0x1a, 0xee, 0x1e, 0xa3, 0x68, 0x65, 0xb8, 0x32, 0x3b, 0x7f, 0xdb, 0x0d, 0x70, 0x9f, 0xc3, 0xee, - 0x0d, 0x89, 0xf5, 0xb4, 0x3e, 0x01, 0x33, 0x2b, 0x43, 0x3e, 0xf2, 0x92, 0x02, 0x37, 0x73, 0x0a, - 0xcc, 0xeb, 0x98, 0xde, 0x71, 0x7f, 0x35, 0xc0, 0x79, 0x8c, 0x21, 0xfe, 0xd7, 0xa3, 0x9c, 0x19, - 0x41, 0x65, 0xd1, 0x08, 0x16, 0xe2, 0xd2, 0x23, 0xf8, 0xc5, 0x80, 0x9d, 0xac, 0x15, 0xff, 0x1f, - 0xd0, 0xdf, 0x81, 0x3d, 0x0f, 0x4a, 0x8f, 0xc6, 0x82, 0xb2, 0xdc, 0x59, 0x4d, 0xb1, 0xa3, 0x45, - 0xbb, 0x5a, 0x9a, 0xdf, 0x55, 0xf7, 0x73, 0xd8, 0x3c, 0x46, 0xa1, 0x69, 0xff, 0x9f, 0x56, 0xe8, - 0x36, 0x81, 0x14, 0xbd, 0x34, 0x84, 0x02, 0x37, 0xa4, 0x2e, 0x99, 0xe8, 0x7e, 0x0c, 0xb5, 0x0c, - 0xf0, 0xdc, 0x4f, 0x0d, 0x0d, 0xbc, 0x94, 0x03, 0x7f, 0xf8, 0x02, 0x36, 0xce, 0x15, 0x8d, 0x77, - 0x90, 0x73, 0x6f, 0x80, 0x9c, 0x6c, 0x81, 0x75, 0x7a, 0x46, 0x3b, 0x07, 0x27, 0xbd, 0xb3, 0xe7, - 0x2d, 0x7a, 0xd0, 0x6d, 0x9f, 0x9d, 0x5a, 0x2b, 0x84, 0xc0, 0x46, 0xfb, 0xb4, 0xdb, 0xa2, 0xa7, - 0x07, 0x27, 0xbd, 0x16, 0xa5, 0x67, 0xd4, 0x02, 0xe2, 0xc0, 0x76, 0xfb, 0xf4, 0xfc, 0xe2, 0xc9, - 0x93, 0xf6, 0x51, 0xbb, 0x75, 0xda, 0xed, 0xd1, 0xd6, 0xf9, 0xd9, 0x05, 0x3d, 0x6a, 0x9d, 0x5b, - 0x5b, 0xfb, 0xbf, 0x57, 0xc1, 0x3a, 0x09, 0xae, 0xd0, 0x9f, 0xf8, 0x21, 0x76, 0xbc, 0xd8, 0x1b, - 0x20, 0x23, 0x5d, 0xd8, 0x4c, 0xdf, 0x9a, 0xae, 0x2e, 0xef, 0x69, 0x72, 0x49, 0x76, 0x97, 0xbe, - 0xeb, 0xce, 0x7b, 0x37, 0x99, 0xf5, 0xf6, 0xac, 0x90, 0x27, 0x70, 0x4b, 0x3e, 0x0e, 0xc5, 0x98, - 0x3b, 0x45, 0xa7, 0xc2, 0xcb, 0xe4, 0xd8, 0xf3, 0x86, 0x3c, 0x4e, 0x1f, 0xb6, 0x8e, 0x51, 0x64, - 0x61, 0x72, 0xfa, 0x24, 0x1f, 0xe4, 0x3e, 0xcb, 0xf8, 0xdf, 0xb9, 0x3f, 0x7b, 0x6d, 0x8e, 0x80, - 0xdd, 0x95, 0x4f, 0x0d, 0x89, 0x56, 0xbe, 0x2b, 0x37, 0xa2, 0x2d, 0x3c, 0x6a, 0xd7, 0xd1, 0x5e, - 0x7b, 0x8d, 0x56, 0xc8, 0x25, 0xbc, 0xbb, 0x80, 0xd7, 0xc8, 0x83, 0xdc, 0xe5, 0x66, 0x56, 0x77, - 0xde, 0x5f, 0x7e, 0xa9, 0x98, 0x63, 0xc1, 0x87, 0x5b, 0xc8, 0x71, 0x33, 0xdd, 0x14, 0x72, 0x2c, - 0xfb, 0xf6, 0x57, 0xc8, 0x4b, 0xb8, 0xbd, 0x90, 0x07, 0x0b, 0x6d, 0x5f, 0x46, 0xd0, 0xce, 0x87, - 0x7f, 0x77, 0x2d, 0xcf, 0xf4, 0x3d, 0x58, 0xb3, 0x5f, 0x34, 0xd9, 0x9b, 0xf3, 0x9e, 0xad, 0xe3, - 0xfe, 0x92, 0x1b, 0x79, 0xe8, 0x63, 0x80, 0xe9, 0x37, 0x4a, 0x9c, 0xa2, 0xcb, 0xf5, 0xcf, 0xdd, - 0xb9, 0xb3, 0xd0, 0x96, 0x05, 0xba, 0xac, 0xaa, 0x7f, 0x7f, 0x9f, 0xfd, 0x15, 0x00, 0x00, 0xff, - 0xff, 0x3c, 0x50, 0xaf, 0x42, 0x0a, 0x0e, 0x00, 0x00, + // 919 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xc1, 0x6f, 0xdb, 0xb6, + 0x17, 0x8e, 0x6c, 0xc7, 0x8e, 0x9e, 0x13, 0x57, 0x25, 0xd2, 0x44, 0x3f, 0xff, 0xd6, 0x2d, 0xf3, + 0xc9, 0xeb, 0x21, 0x87, 0x0c, 0x18, 0xb6, 0x0e, 0xc3, 0x10, 0x67, 0x4e, 0xe7, 0x34, 0x76, 0x06, + 0x5a, 0xe9, 0x71, 0x02, 0x2d, 0xbf, 0xaa, 0x44, 0x24, 0x51, 0x23, 0x69, 0x0f, 0x06, 0x76, 0xda, + 0x9f, 0xba, 0x3f, 0x60, 0xe7, 0x1d, 0x07, 0x52, 0xb2, 0xad, 0xb4, 0x69, 0x80, 0x1e, 0x76, 0xe3, + 0xf7, 0x3d, 0xbf, 0x8f, 0xe4, 0xf7, 0x3e, 0xca, 0xe0, 0x26, 0x51, 0x7a, 0x9a, 0x4b, 0xa1, 0x05, + 0x69, 0x29, 0x94, 0x4b, 0x1e, 0x61, 0xef, 0xaf, 0x3a, 0x1c, 0x52, 0x54, 0x62, 0x21, 0x23, 0xa4, + 0xf8, 0xdb, 0x82, 0x4b, 0x4c, 0x31, 0xd3, 0x8a, 0x10, 0x68, 0x44, 0xf9, 0x42, 0xf9, 0xce, 0x89, + 0xd3, 0x77, 0xa8, 0x5d, 0x1b, 0x2e, 0x36, 0x5c, 0xad, 0xe0, 0xcc, 0x9a, 0x1c, 0x41, 0x33, 0xc5, + 0x54, 0xc8, 0x95, 0x5f, 0xb7, 0x6c, 0x89, 0xc8, 0x08, 0xda, 0xc5, 0x2a, 0x5c, 0x64, 0x5c, 0xfb, + 0x8d, 0x13, 0xa7, 0xdf, 0x39, 0xeb, 0x9f, 0x96, 0xfb, 0x9e, 0x3e, 0xb4, 0xe7, 0xe9, 0xd8, 0x36, + 0xdc, 0x66, 0x5c, 0x53, 0x48, 0x37, 0x6b, 0xd2, 0x85, 0xbd, 0x04, 0x99, 0xcc, 0x50, 0x2a, 0x7f, + 0xf7, 0xc4, 0xe9, 0xef, 0xd2, 0x0d, 0x26, 0x27, 0xd0, 0x56, 0xd1, 0x3b, 0x9c, 0xe7, 0x22, 0xe1, + 0xd1, 0xca, 0x6f, 0x9e, 0x38, 0x7d, 0x97, 0x56, 0x29, 0xd3, 0xad, 0x45, 0x2e, 0x12, 0x11, 0xaf, + 0xfc, 0x96, 0x2d, 0x6f, 0x30, 0xe9, 0xc1, 0x3e, 0x93, 0xd1, 0x3b, 0xae, 0x31, 0xd2, 0x0b, 0x89, + 0xfe, 0x9e, 0xad, 0xdf, 0xe3, 0x88, 0x0f, 0x2d, 0xa5, 0x85, 0x64, 0x31, 0xfa, 0xae, 0xbd, 0xe1, + 0x1a, 0x92, 0xd7, 0xb0, 0x5f, 0x2e, 0x8b, 0x3b, 0xc2, 0x27, 0xde, 0xb1, 0x5d, 0x76, 0xdb, 0x4b, + 0xfe, 0x0f, 0xf6, 0xe2, 0x7c, 0x11, 0xea, 0x55, 0x8e, 0x7e, 0xdb, 0x1e, 0xa3, 0x15, 0xe7, 0x8b, + 0x60, 0x95, 0x63, 0xef, 0x47, 0x80, 0x6d, 0x17, 0x69, 0x42, 0x6d, 0x3c, 0xf0, 0x76, 0x48, 0x0b, + 0xea, 0x63, 0x3e, 0xf0, 0x1c, 0x43, 0xbc, 0x1a, 0x78, 0x35, 0x43, 0xbc, 0xe2, 0x03, 0xaf, 0x6e, + 0x88, 0x60, 0xe0, 0x35, 0x0c, 0x11, 0xf0, 0x81, 0xb7, 0xdb, 0xfb, 0x03, 0x1a, 0xb7, 0x0a, 0x25, + 0xe9, 0x40, 0x8d, 0xcf, 0xed, 0x44, 0x5d, 0x5a, 0xe3, 0x73, 0x72, 0x08, 0xbb, 0x52, 0x24, 0x68, + 0x06, 0x5a, 0xef, 0xbb, 0xb4, 0x00, 0xe4, 0x33, 0x70, 0xdf, 0x72, 0xa9, 0x74, 0xc6, 0x52, 0xb4, + 0x43, 0x75, 0xe9, 0x96, 0xb0, 0xc3, 0x60, 0x65, 0xb1, 0x51, 0xd8, 0xb9, 0xc6, 0x46, 0x0f, 0x53, + 0xc6, 0x13, 0x3b, 0x25, 0x97, 0x16, 0xa0, 0xf7, 0x77, 0x03, 0x0e, 0xaf, 0xc4, 0xec, 0x27, 0xcc, + 0x13, 0xb1, 0x32, 0x26, 0x18, 0x3f, 0x50, 0x69, 0x13, 0x27, 0x2b, 0x53, 0x1c, 0xc8, 0xae, 0xc9, + 0xf7, 0xe0, 0xca, 0xd2, 0x36, 0x65, 0xf5, 0xdb, 0x67, 0xcf, 0x1f, 0x35, 0x94, 0x6e, 0x7f, 0x4f, + 0x86, 0xb0, 0x87, 0xd9, 0x32, 0x5c, 0x32, 0x1b, 0x94, 0x7a, 0xbf, 0x7d, 0xf6, 0x62, 0xd3, 0xfb, + 0xd0, 0x09, 0x4e, 0x87, 0xd9, 0xf2, 0x0d, 0x93, 0x6a, 0x98, 0x69, 0xb9, 0xa2, 0x2d, 0x2c, 0x10, + 0x39, 0x87, 0x66, 0xc2, 0x66, 0x98, 0x28, 0xbf, 0x69, 0x45, 0xbe, 0x7a, 0x5c, 0xe4, 0xda, 0xfe, + 0xb6, 0xd0, 0x28, 0x1b, 0xc9, 0x31, 0xb4, 0x16, 0x0a, 0x65, 0xc8, 0xe7, 0x65, 0xe6, 0x9a, 0x06, + 0x8e, 0xe6, 0xe4, 0x0b, 0x68, 0x6b, 0xc9, 0x78, 0xc6, 0xb3, 0xd8, 0x14, 0x8b, 0xc0, 0xc1, 0x9a, + 0x1a, 0xcd, 0xad, 0xfb, 0x92, 0xa5, 0xf8, 0xbb, 0x90, 0x77, 0x36, 0x70, 0xc6, 0xfd, 0x35, 0x61, + 0xc2, 0xb8, 0x44, 0xa9, 0xb8, 0xc8, 0x6c, 0xda, 0x5c, 0xba, 0x86, 0xe4, 0x1b, 0x38, 0xc6, 0x25, + 0x4b, 0x16, 0x4c, 0x73, 0x91, 0x85, 0x29, 0x6a, 0xc9, 0x23, 0x15, 0xaa, 0x1c, 0xa3, 0x32, 0x4e, + 0xcf, 0xb6, 0xe5, 0x71, 0x51, 0x9d, 0xe6, 0x18, 0x91, 0xff, 0x83, 0xcb, 0x53, 0x13, 0x61, 0xcd, + 0x62, 0x7f, 0xbf, 0x18, 0xa8, 0x25, 0x02, 0x16, 0x93, 0x1f, 0xa0, 0x53, 0x14, 0x13, 0x11, 0xd9, + 0x4e, 0xff, 0xc0, 0x8e, 0xe4, 0x68, 0xe3, 0xc8, 0xc8, 0x94, 0xaf, 0xcb, 0x2a, 0x3d, 0xe0, 0x55, + 0xd8, 0x7d, 0x09, 0xfb, 0x55, 0x87, 0x89, 0x07, 0xf5, 0x3b, 0x5c, 0x95, 0xf3, 0x36, 0x4b, 0x93, + 0x18, 0x73, 0x2a, 0xb4, 0x9f, 0x14, 0x97, 0x16, 0xe0, 0x65, 0xed, 0x5b, 0xa7, 0xfb, 0x1d, 0xb4, + 0x2b, 0xc6, 0x7e, 0x4a, 0x6b, 0xef, 0x4f, 0x07, 0x0e, 0xee, 0x9d, 0xcb, 0x84, 0x56, 0x62, 0xcc, + 0x95, 0x96, 0x6b, 0x89, 0x0d, 0x36, 0x86, 0x9b, 0xe4, 0xa9, 0x9c, 0x45, 0x6b, 0xad, 0x2d, 0x41, + 0xbe, 0x84, 0x7d, 0x16, 0x45, 0xa8, 0x54, 0xa8, 0xc5, 0x1d, 0x66, 0xe5, 0x7b, 0x68, 0x17, 0x5c, + 0x60, 0xa8, 0x6d, 0xea, 0x1b, 0xd5, 0xd4, 0x5f, 0xc0, 0xb3, 0xf7, 0xd2, 0xa2, 0x72, 0x91, 0x29, + 0x7c, 0x30, 0xf5, 0x47, 0xd0, 0x54, 0x9a, 0xe9, 0xf2, 0xd3, 0xea, 0xd2, 0x12, 0xf5, 0x7e, 0x85, + 0xce, 0x95, 0x98, 0xbd, 0xe6, 0x49, 0xf2, 0xd8, 0x9b, 0x79, 0x2f, 0x53, 0xb5, 0x0f, 0x32, 0x55, + 0x49, 0x63, 0xbd, 0x9a, 0xc6, 0xde, 0x53, 0x78, 0xb2, 0xd1, 0x2f, 0x8e, 0x57, 0x6e, 0xf9, 0x33, + 0x4b, 0xf4, 0x7f, 0xb9, 0x65, 0xa1, 0x5f, 0x6c, 0xf9, 0xe2, 0x0d, 0x74, 0xa6, 0xf6, 0xbe, 0x63, + 0x54, 0x8a, 0xc5, 0xa8, 0xc8, 0x21, 0x78, 0x93, 0x1b, 0x3a, 0x3e, 0xbf, 0x0e, 0x6f, 0x7e, 0x19, + 0xd2, 0xf3, 0x60, 0x74, 0x33, 0xf1, 0x76, 0x08, 0x81, 0xce, 0x68, 0x12, 0x0c, 0xe9, 0xe4, 0xfc, + 0x3a, 0x1c, 0x52, 0x7a, 0x43, 0x3d, 0x20, 0x5d, 0x38, 0x1a, 0x4d, 0xa6, 0xb7, 0x97, 0x97, 0xa3, + 0x8b, 0xd1, 0x70, 0x12, 0x84, 0x74, 0x38, 0xbd, 0xb9, 0xa5, 0x17, 0xc3, 0xa9, 0x77, 0x78, 0xf6, + 0x8f, 0x03, 0xde, 0x35, 0x7f, 0x8b, 0xd1, 0x2a, 0x4a, 0x70, 0xcc, 0x32, 0x16, 0xa3, 0x24, 0x01, + 0x3c, 0x2d, 0x86, 0x12, 0x94, 0x87, 0xbd, 0x12, 0x33, 0xf2, 0xfc, 0xd1, 0x17, 0xde, 0xfd, 0xfc, + 0x63, 0xe5, 0xd2, 0xb3, 0x1d, 0x72, 0x09, 0x4f, 0x8c, 0x8b, 0x55, 0xcd, 0xe3, 0x6a, 0x53, 0x65, + 0x84, 0x5d, 0xff, 0xc3, 0x42, 0x55, 0xc7, 0x58, 0xf3, 0x51, 0x9d, 0xca, 0x5c, 0xee, 0xeb, 0x54, + 0x0d, 0xed, 0xed, 0xcc, 0x9a, 0xf6, 0x6f, 0xfe, 0xeb, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x54, + 0x84, 0xb1, 0xe4, 0xf3, 0x07, 0x00, 0x00, } diff --git a/commons/service/lcm.proto b/commons/service/lcm.proto index bc1f1acf..133cb19b 100644 --- a/commons/service/lcm.proto +++ b/commons/service/lcm.proto @@ -21,19 +21,7 @@ package service; service LifecycleManager { rpc DeployTrainingJob (JobDeploymentRequest) returns (JobDeploymentResponse) {} rpc KillTrainingJob (JobKillRequest) returns (JobKillResponse) {} - rpc GetTrainingLogStream (TrainerContainerInfosRequest) returns (stream TrainerLogStreamResponse) {} rpc HaltTrainingJob (JobHaltRequest) returns (JobHaltResponse) {} - - // creates an endpoint with a specific id for an event type - rpc CreateEventEndpoint (CreateEventEndpointRequest) returns (CreateEventEndpointResponse) {} - // deletes a specific endpoint (defined by event type and endpoint id) - rpc DeleteEventEndpoint (DeleteEventEndpointRequest) returns (DeleteEventEndpointResponse) {} - // gets all endpoints registered for an event type - rpc GetEventTypeEndpoints (GetEventTypeEndpointsRequest) returns (GetEventTypeEndpointsResponse) {} - // gets a specific endpoint - rpc GetEventEndpoint (GetEventEndpointRequest) returns (GetEventEndpointResponse) {} - - rpc GetMetrics(GetMetricsRequest) returns (GetMetricsResponse) {} } @@ -48,6 +36,7 @@ message ResourceRequirements { string architecture = 8; double storage = 9; MemoryUnit storage_unit = 10; + string gpu_type = 11; // TODO add more fields as required @@ -87,6 +76,15 @@ message JobDeploymentRequest { string framework = 9; string version =10; string evaluation_metrics_spec = 11; + string image_tag = 12; + ImageLocation image_location = 13; // Optional: non-standard location for learner image +} + +message ImageLocation { + string registry = 1; // the server name for the docker registry + string namespace = 2; // namespace within the registry + string access_token = 3; // Token used to access images stored in the registry+namespace + string email = 4; // Email address associated with the account } message JobDeploymentResponse { @@ -113,73 +111,3 @@ message JobHaltRequest { message JobHaltResponse { // placeholder for further messages } - -message TrainerContainerInfosRequest { - string training_id = 1; - string user_id = 2; - bool follow = 3; - bool metrics = 4; - bool summary = 5; -} - -message TrainerLogStreamResponse { - bytes data = 1; -} - -message CreateEventEndpointRequest { - string training_id = 1; - string user_id = 2; - string event_type = 3; // "metrics", "status", or "all" - string endpoint_url = 4; // endpoint must accept POST request with json content type - string endpoint_type = 5; // not currently used - string endpoint_id = 6; // user-assigned id associated with the endpoint, descriptive. -} - -message CreateEventEndpointResponse { - // placeholder -} - -message GetEventTypeEndpointsRequest { - string training_id = 1; - string user_id = 2; - string event_type = 3; -} - -message GetEventTypeEndpointsResponse { - repeated Endpoint endpoints = 1; -} - -message DeleteEventEndpointRequest { - string training_id = 1; - string user_id = 2; - string event_type = 3; - string endpoint_id = 4; -} - -message DeleteEventEndpointResponse { - // placeholder -} - -message GetEventEndpointRequest { - string training_id = 1; - string user_id = 2; - string event_type = 3; - string endpoint_id = 4; -} - -message GetEventEndpointResponse { - string url = 1; - string endpoint_type = 2; // not currently used -} - -message GetMetricsRequest { - string training_id = 1; -} -message GetMetricsResponse{ - string metrics = 1; -} - -message Endpoint { - string id = 1; - string url = 2; -} diff --git a/commons/util/grpc.go b/commons/util/grpc.go index bfd2992e..b19b41e6 100644 --- a/commons/util/grpc.go +++ b/commons/util/grpc.go @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package util import ( diff --git a/commons/util/retry.go b/commons/util/retry.go index 2f312869..f234c887 100644 --- a/commons/util/retry.go +++ b/commons/util/retry.go @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package util import ( diff --git a/commons/util/stdcopynoframedebug.go b/commons/util/stdcopynoframedebug.go index 56e0620b..52dfd2e0 100644 --- a/commons/util/stdcopynoframedebug.go +++ b/commons/util/stdcopynoframedebug.go @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // Copy of copy portion of /home/sboag/git/docker/pkg/stdcopy/stdcopy.go with // frame copy debug removed. We should ask the docker folks for better control over // that debug message, and then remove this. diff --git a/community/FfDL-H2Oai/README.md b/community/FfDL-H2Oai/README.md new file mode 100644 index 00000000..7ebb9dea --- /dev/null +++ b/community/FfDL-H2Oai/README.md @@ -0,0 +1,82 @@ +# Perform Automated Machine Learning With H2O on FfDL + +[H2O.ai](https://h2o.ai) provides an open source platform for automated machine learning: [H2O-3](https://www.h2o.ai/h2o/) + +H2O is an open source, in-memory, distributed, fast, and scalable machine learning and predictive analytics platform that allows you to build machine learning models on big data and provides easy productionalization of those models in an enterprise environment. + +![ffdl-h20](images/ffdl-h203.png) + +# Deployment Steps + +1. Follow steps to deploy FfDL from the [user guide](https://github.com/IBM/FfDL/blob/master/docs/user-guide.md) +2. Add some data, either follow the user guide to store the data locally or host the data in a cloud storage bucket and pull it at runtime. +3. Change the manifest.yaml to the settings that you want + * NOTE: It is recommended that you allocate at least 4x the amount of memory as the size of the dataset you are trying to run H2O with. + * EXAMPLE: 1.5GB Dataset --> 6.0 GB Memory allocated +4. Once FfDL is deployed in your Kubernetes cluster, use the CLI or GUI to deploy H2O + +# Examples +Sample deployment scripts are hosted under: FfDL/community/FfDL-H2Oai + +If you need a sample dataset, you can pull this toy dataset: + +Train Set: +https://s3.amazonaws.com/h2o-public-test-data/smalldata/higgs/higgs_train_10k.csv + +Test Set: +https://s3.amazonaws.com/h2o-public-test-data/smalldata/higgs/higgs_test_5k.csv + +# Deploy H2O example on FfDL + +0. Deploy [FfDL](https://github.com/IBM/FfDL#5-detailed-installation-instructions) on your Kubernetes Cluster. + +1. In the main FfDL repository, run the following commands to obtain the object storage endpoint from your cluster. +```shell +node_ip=$PUBLIC_IP +s3_port=$(kubectl get service s3 -o jsonpath='{.spec.ports[0].nodePort}') +s3_url=http://$node_ip:$s3_port +``` + +2. Next, set up the default object storage access ID and KEY. Then create buckets for all the necessary training data and models. +```shell +export AWS_ACCESS_KEY_ID=test; export AWS_SECRET_ACCESS_KEY=test; export AWS_DEFAULT_REGION=us-east-1; + +s3cmd="aws --endpoint-url=$s3_url s3" +$s3cmd mb s3://h2o3_training_data +$s3cmd mb s3://h2o3_trained_model +``` + +3. Now, create a temporary repository, download the necessary data for training the H2O model, and upload those data +to your h2o3_training_data bucket. + +```shell +mkdir tmp +test -e tmp/higgs_train_10k.csv || wget -q -O tmp/higgs_train_10k.csv https://s3.amazonaws.com/h2o-public-test-data/smalldata/higgs/higgs_train_10k.csv +$s3cmd cp tmp/higgs_train_10k.csv s3://tf_training_data/higgs_train_10k.csv +``` + +4. Now you should have all the necessary training data set in your object storage. Let's go ahead to set up your restapi endpoint +and default credentials for Deep Learning as a Service. Once you done that, you can start running jobs using the FfDL CLI (executable +binary). + +```shell +restapi_port=$(kubectl get service ffdl-restapi -o jsonpath='{.spec.ports[0].nodePort}') +export DLAAS_URL=http://$node_ip:$restapi_port; export DLAAS_USERNAME=test-user; export DLAAS_PASSWORD=test; +``` + +Replace the default object storage path with your s3_url. You can skip this step if your already modified the object storage path with your s3_url. +```shell +if [ "$(uname)" = "Darwin" ]; then + sed -i '' s/s3.default.svc.cluster.local/$node_ip:$s3_port/ community/FfDL-H2Oai/h2o-model/manifest-h2o.yml +else + sed -i s/s3.default.svc.cluster.local/$node_ip:$s3_port/ community/FfDL-H2Oai/h2o-model/manifest-h2o.yml +fi +``` + +Obtain the correct CLI for your machine and run the training job with our default H2O model +```shell +CLI_CMD=$(pwd)/cli/bin/ffdl-$(if [ "$(uname)" = "Darwin" ]; then echo 'osx'; else echo 'linux'; fi) +$CLI_CMD train community/FfDL-H2Oai/h2o-model/manifest-h2o.yml community/FfDL-H2Oai/h2o-model +``` + +Congratulations, you had submitted your first H2O job on FfDL. You can check your FfDL status either from the FfDL UI or simply run `$CLI_CMD list` diff --git a/community/FfDL-H2Oai/h2o-model/Dockerfile.h2o3 b/community/FfDL-H2Oai/h2o-model/Dockerfile.h2o3 new file mode 100644 index 00000000..66230c00 --- /dev/null +++ b/community/FfDL-H2Oai/h2o-model/Dockerfile.h2o3 @@ -0,0 +1,80 @@ +######################################################################## +# Dockerfile for Oracle JDK 8 on Ubuntu 16.04 +######################################################################## + +# pull base image +FROM ubuntu:16.04 + +# maintainer details +MAINTAINER h2oai "h2o.ai" + +# add a post-invoke hook to dpkg which deletes cached deb files +# update the sources.list +# update/dist-upgrade +# clear the caches + + +RUN \ + echo 'DPkg::Post-Invoke {"/bin/rm -f /var/cache/apt/archives/*.deb || true";};' | tee /etc/apt/apt.conf.d/no-cache && \ + echo "deb http://mirror.math.princeton.edu/pub/ubuntu xenial main universe" >> /etc/apt/sources.list && \ + apt-get update -q -y && \ + apt-get dist-upgrade -y && \ + apt-get clean && \ + rm -rf /var/cache/apt/* && \ + +# Install Oracle Java 8 + DEBIAN_FRONTEND=noninteractive apt-get install -y wget curl unzip net-tools python-pip python-sklearn python-pandas python-numpy python-matplotlib software-properties-common python-software-properties && \ + add-apt-repository -y ppa:webupd8team/java && \ + apt-get update -q && \ + echo debconf shared/accepted-oracle-license-v1-1 select true | debconf-set-selections && \ + echo debconf shared/accepted-oracle-license-v1-1 seen true | debconf-set-selections && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y oracle-java8-installer && \ + apt-get clean && \ + +# Fetch h2o latest_stable + wget http://h2o-release.s3.amazonaws.com/h2o/latest_stable -O latest && \ + wget --no-check-certificate -i latest -O /opt/h2o.zip && \ + unzip -d /opt /opt/h2o.zip && \ + rm /opt/h2o.zip && \ + cd /opt && \ + cd `find . -name 'h2o.jar' | sed 's/.\///;s/\/h2o.jar//g'` && \ + cp h2o.jar /opt && \ + /usr/bin/pip install `find . -name "*.whl"` && \ + cd / && \ + wget https://raw.githubusercontent.com/h2oai/h2o-3/master/docker/start-h2o-docker.sh && \ + chmod +x start-h2o-docker.sh && \ + +# Install h2o python package + /usr/bin/pip --no-cache-dir install requests tabulate scikit-learn colorama future && \ + /usr/bin/pip --no-cache-dir --trusted-host h2o-release.s3.amazonaws.com install -f http://h2o-release.s3.amazonaws.com/h2o/latest_stable_Py.html h2o && \ + +# Get Content + wget http://s3.amazonaws.com/h2o-training/mnist/train.csv.gz && \ + gunzip train.csv.gz && \ + wget https://raw.githubusercontent.com/laurendiperna/Churn_Scripts/master/Extraction_Script.py && \ + wget https://raw.githubusercontent.com/laurendiperna/Churn_Scripts/master/Transformation_Script.py && \ + wget https://raw.githubusercontent.com/laurendiperna/Churn_Scripts/master/Modeling_Script.py + +# Install kubectl +RUN \ + curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && \ + chmod +x ./kubectl && \ + mv ./kubectl /usr/local/bin/kubectl + +# Define a mountable data directory +#VOLUME \ +# ["/data"] + +# Define the working directory +#WORKDIR \ +# /data + +EXPOSE 54321 +EXPOSE 54322 +EXPOSE 8080 + +#ENTRYPOINT ["java", "-Xmx4g", "-jar", "/opt/h2o.jar"] +# Define default command + +CMD \ + ["/bin/bash"] diff --git a/community/FfDL-H2Oai/h2o-model/h2o3-cluster.sh b/community/FfDL-H2Oai/h2o-model/h2o3-cluster.sh new file mode 100755 index 00000000..6c61f715 --- /dev/null +++ b/community/FfDL-H2Oai/h2o-model/h2o3-cluster.sh @@ -0,0 +1,8 @@ +echo $(hostname --ip-address):54321 >> $LEARNER_ID.txt +mkdir ${RESULT_DIR}/flatfiles +cp $LEARNER_ID.txt ${RESULT_DIR}/flatfiles/$LEARNER_ID.txt +lines=$(ls ${RESULT_DIR}/flatfiles/ | wc -l); +while [ "$lines" != "$NUM_LEARNERS" ]; do sleep 5; lines=$(ls ${RESULT_DIR}/flatfiles/ | wc -l); done; +cat ${RESULT_DIR}/flatfiles/* > flatfile.txt; +java -jar /opt/h2o.jar -flatfile flatfile.txt -name h2oCluster & +while [ "$nodes" != "$NUM_LEARNERS" ]; do sleep 30; nodes=$(curl -s http://$(hostname --ip-address):54321/3/Cloud.json | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["'cloud_size'"]';); done; diff --git a/community/FfDL-H2Oai/h2o-model/h2o3_baseline.py b/community/FfDL-H2Oai/h2o-model/h2o3_baseline.py new file mode 100644 index 00000000..b9f27c07 --- /dev/null +++ b/community/FfDL-H2Oai/h2o-model/h2o3_baseline.py @@ -0,0 +1,71 @@ +# +# Copyright 2017-2018 IBM Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import h2o +from h2o.automl import H2OAutoML +import os +import sys +import socket +import time + + +train_data_file = None +memory = None +target = None + + +def parse_args(argv): + if len(argv) < 6: + sys.exit("Not enough arguments provided") + + global train_data_file, memory, target + + i = 1 + while i <= 6: + arg = str(argv[i]) + if arg == "--trainDataFile": + train_data_file = str(argv[i+1]) + elif arg == "--memory": + memory = str(argv[i+1]) + elif arg == "--target": + target = str(argv[i+1]) + i += 2 + + +if __name__ == "__main__": + parse_args(sys.argv) + +h2o.init(ip=socket.gethostbyname(socket.gethostname()), port="54321", start_h2o=False) + +train = h2o.import_file(train_data_file) + +x = train.columns +y = target +x.remove(y) + +train[y] = train[y].asfactor() + +aml = H2OAutoML(max_runtime_secs=60) +aml.train(x=x, y=y, training_frame=train) + +lb = aml.leaderboard +print(lb) + +save_path = os.environ["RESULT_DIR"] +model_path = h2o.save_model(model=aml.leader, path=save_path) +print(model_path) + +h2o.cluster().shutdown() diff --git a/community/FfDL-H2Oai/h2o-model/manifest-h2o.yml b/community/FfDL-H2Oai/h2o-model/manifest-h2o.yml new file mode 100644 index 00000000..52390a74 --- /dev/null +++ b/community/FfDL-H2Oai/h2o-model/manifest-h2o.yml @@ -0,0 +1,28 @@ +name: h2o3_automl +description: H2O-3 Model Using H2O AutoML +version: "1.0" +learners: 2 +gpus: 0 +cpus: 1 +memory: 2Gb + +# Object stores that allow the system to retrieve training data +data_stores: + - id: sl-internal-os + type: mount_cos + training_data: + container: h2o3_training_data + training_results: + container: h2o3_trained_model + connection: + auth_url: http://s3.default.svc.cluster.local + user_name: test + password: test + +framework: + name: "h2o3" + version: "latest" + # h2o3-cluster.sh is the H2O entrypoint script to set up multi-node H2O cluster on FfDL + command: > + ./h2o3-cluster.sh; + if [ "$LEARNER_ID" == "1" ]; then python h2o3_baseline.py --trainDataFile ${DATA_DIR}/higgs_train_10k.csv --target response --memory 1; fi; diff --git a/community/FfDL-H2Oai/images/ffdl-h203.png b/community/FfDL-H2Oai/images/ffdl-h203.png new file mode 100644 index 00000000..d350dbb5 Binary files /dev/null and b/community/FfDL-H2Oai/images/ffdl-h203.png differ diff --git a/community/FfDL-Seldon/README.md b/community/FfDL-Seldon/README.md new file mode 100644 index 00000000..d98c4656 --- /dev/null +++ b/community/FfDL-Seldon/README.md @@ -0,0 +1,23 @@ +# Deploy FfDL Trained Models with Seldon + +[Seldon](https://github.com/SeldonIO/seldon-core) provides a deployment platform to allow machine learning models to be exposed via REST or gRPC endpoints. Runtime graphs of models, routers (e.g., AB-tests, Multi-Armed bandits) , transformers (e.g., Feature normalization) and combiners (e.g., ensemblers) can be described using a Custom Kubernetes Resource JSON/YAML and then deployed, scaled and managed. + +Any FfDL model whose runtime inference can be packaged as a Docker container can be managed by Seldon. + +# Install Seldon + +To install Seldon on your Kubernetes cluster next to FfDL see [here](https://github.com/SeldonIO/seldon-core/blob/master/docs/install.md). + +# Deployment Steps + +To deploy your models on Seldon you need to + + 1. Wrap your runtime inference components as Docker containers that follow the Seldon APIs + 1. Describe the runtime graph as a Custom Kubernetes ```SeldonDeployment``` Resource + 1. Apply the graph via the Kubernetes API, e.g. using kubectl + +# Examples + + * [Train and deploy a Tensorflow MNIST classififer.](./tf-model/README.md) + * [Train and deploy a PyTorch MNIST classififer.](./pytorch-model/README.md) + diff --git a/community/FfDL-Seldon/pytorch-model/.s2i/environment b/community/FfDL-Seldon/pytorch-model/.s2i/environment new file mode 100644 index 00000000..6b9b65b2 --- /dev/null +++ b/community/FfDL-Seldon/pytorch-model/.s2i/environment @@ -0,0 +1,4 @@ +MODEL_NAME=PyMnist +API_TYPE=REST +SERVICE_TYPE=MODEL +PERSISTENCE=0 diff --git a/community/FfDL-Seldon/pytorch-model/.s2i/environment~ b/community/FfDL-Seldon/pytorch-model/.s2i/environment~ new file mode 100644 index 00000000..4fa5c77f --- /dev/null +++ b/community/FfDL-Seldon/pytorch-model/.s2i/environment~ @@ -0,0 +1,4 @@ +MODEL_NAME=pyMnist +API_TYPE=REST +SERVICE_TYPE=MODEL +PERSISTENCE=0 diff --git a/community/FfDL-Seldon/pytorch-model/PyMnist.py b/community/FfDL-Seldon/pytorch-model/PyMnist.py new file mode 100644 index 00000000..cca33e31 --- /dev/null +++ b/community/FfDL-Seldon/pytorch-model/PyMnist.py @@ -0,0 +1,97 @@ +# +# Copyright 2017-2018 IBM Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import torch +import numpy as np +from torchvision import datasets, transforms +import torch.nn as nn +import torch.nn.functional as F +import torch.optim as optim +from torch.autograd import Variable +import boto3 +import botocore +import tarfile +import os + +class Net(nn.Module): + def __init__(self): + super(Net, self).__init__() + self.conv1 = nn.Conv2d(1, 10, kernel_size=5) + self.conv2 = nn.Conv2d(10, 20, kernel_size=5) + self.conv2_drop = nn.Dropout2d() + self.fc1 = nn.Linear(320, 50) + self.fc2 = nn.Linear(50, 10) + + def forward(self, x): + x = F.relu(F.max_pool2d(self.conv1(x), 2)) + x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2)) + x = x.view(-1, 320) + x = F.relu(self.fc1(x)) + x = F.dropout(x, training=self.training) + x = self.fc2(x) + return F.log_softmax(x) + + +class PyMnist(object): + def __init__(self): + training_id = os.environ.get("TRAINING_ID") + endpoint_url = os.environ.get("BUCKET_ENDPOINT_URL") + bucket_name = os.environ.get("BUCKET_NAME") + bucket_key = os.environ.get("BUCKET_KEY") + bucket_secret = os.environ.get("BUCKET_SECRET") + print("Training id:{} endpoint URL:{} key:{} secret:{}".format(training_id,endpoint_url,bucket_key,bucket_secret)) + + self.class_names = ["class:{}".format(str(i)) for i in range(10)] + #self.class_names = ["prediction"] + + # Define S3 resource and download the model file + client = boto3.resource( + 's3', + endpoint_url=endpoint_url, + aws_access_key_id=bucket_key, + aws_secret_access_key=bucket_secret, + ) + + KEY = training_id + '/saved_model.tar.gz' # replace with your object key + + try: + client.Bucket(bucket_name).download_file(KEY, 'saved_model.tar.gz') + except botocore.exceptions.ClientError as e: + if e.response['Error']['Code'] == "404": + print("The object does not exist.") + else: + raise + + # Untar model file + tar = tarfile.open("saved_model.tar.gz") + tar.extractall() + tar.close() + + self.model = Net() + self.model.load_state_dict(torch.load("./model.dat")) + + + def predict(self,X,feature_names): + tensor = torch.from_numpy(X).view(-1, 28, 28) + t = transforms.Normalize((0.1307,), (0.3081,)) + tensor_norm = t(tensor) + tensor_norm = tensor_norm.unsqueeze(0) + out = self.model(tensor_norm.float()) + predictions = torch.nn.functional.softmax(out) + print(predictions) + return predictions.detach().numpy() + + diff --git a/community/FfDL-Seldon/pytorch-model/README.md b/community/FfDL-Seldon/pytorch-model/README.md new file mode 100644 index 00000000..d64637c8 --- /dev/null +++ b/community/FfDL-Seldon/pytorch-model/README.md @@ -0,0 +1,53 @@ +# PyTorch MNIST Classifier + +# Assumptions + + * You have installed [seldon-core](https://github.com/SeldonIO/seldon-core/blob/master/docs/install.md) on you FfDL cluster. + + +# Train Model + +Train the [pyTorch MNIST model](https://github.com/IBM/FfDL/tree/master/etc/examples/pytorch-model) following the steps in the [user guide](https://github.com/IBM/FfDL#6-detailed-testing-instructions). + +# Wrap the Runtime Scorer +You can skip this step if you are happy to use the already packaged image ```seldonio/ffdl-pymnist``` from DockerHub. + +The runtime MNIST scrorer is contained within a standalone [python class PyMnist.py](./PyMnist.py). This needs to be packaged in a Docker container to run within Seldon. For this we use [Redhat's Source-to-image](https://github.com/openshift/source-to-image). + + * Install [S2I](https://github.com/openshift/source-to-image#installation) + * From the pytorch-model folder run the following s2i build. You will need to change *seldonio* to your Docker repo. **You will need at least 8GB for your local Docker.** +``` +s2i build . seldonio/seldon-core-s2i-python2 seldonio/ffdl-pymnist:0.1 +``` + * Push image to DockerHub or your Docker repo accessible from the FfDL cluster. + +# Deploy Model +To deploy the model you need to create the deployment resource from the template ```ffdl-mnist-deployment.json```. You will need to set: + + * TRAINING_ID : Your FfDL Training ID + * BUCKET_NAME : The name of the bucket containing your model + +You will also need to create a kubernetes secret containing your bucket endpoint url, key and secret. You can use the ```bucket-secret.yaml``` as a template, e.g.: + + * edit ```bucket-secret.yaml``` + * Enter the base64 values for endpoint url, key, secret + * On a linux system running bash shell you could do the following to get your values, ```echo -n "my key" | base64``` + * run ```kubectl create -f bucket-secret.yaml``` + +Create a deployment file by adding your settings, e.g. using sed below: + +``` +cat ffdl-mnist-deployment.json | sed 's/%TRAINING_ID%/training-84hIKJViR/' | sed 's/%BUCKET_NAME%/tf_trained_model/' > ffdl-mnist-deployment_mydeploy.json +``` + +Deploy: +``` +kubectl create -f ffdl-mnist-deployment_mydeploy.json +``` + +# Test + +To test the running model with example MNIST images you can run either of two notebooks depending on how you exposed the Seldon APIs + + * [Ambassador Example](serving_ambassador.ipynb) + * [Seldon OAuth Example](serving_oauth.ipynb) diff --git a/community/FfDL-Seldon/pytorch-model/bucket-secret.yaml b/community/FfDL-Seldon/pytorch-model/bucket-secret.yaml new file mode 100644 index 00000000..3141308e --- /dev/null +++ b/community/FfDL-Seldon/pytorch-model/bucket-secret.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +data: + endpoint: #ENDPOINT_URL_BASE64# + key: #KEY_BASE64# + secret: #SECRET_BASE64# +kind: Secret +metadata: + name: bucket-credentials +type: Opaque + diff --git a/community/FfDL-Seldon/pytorch-model/ffdl-mnist-deployment.json b/community/FfDL-Seldon/pytorch-model/ffdl-mnist-deployment.json new file mode 100644 index 00000000..f63433b8 --- /dev/null +++ b/community/FfDL-Seldon/pytorch-model/ffdl-mnist-deployment.json @@ -0,0 +1,96 @@ +{ + "apiVersion": "machinelearning.seldon.io\/v1alpha2", + "kind": "SeldonDeployment", + "metadata": { + "labels": { + "app": "seldon" + }, + "name": "ffdl-pymnist" + }, + "spec": { + "annotations": { + "project_name": "FfDL PyTorch MNIST", + "deployment_version": "v1" + }, + "name": "pymnist", + "oauth_key": "oauth-key-pymnist", + "oauth_secret": "oauth-secret", + "predictors": [ + { + "componentSpecs": [{ + "spec": { + "containers": [ + { + "image": "seldonio/ffdl-pymnist:0.1", + "imagePullPolicy": "IfNotPresent", + "name": "classifier", + "resources": { + "requests": { + "memory": "1Mi" + } + }, + "env": [ + { + "name": "TRAINING_ID", + "value": "%TRAINING_ID%" + }, + { + "name": "BUCKET_NAME", + "value": "%BUCKET_NAME%" + }, + { + "valueFrom": { + "secretKeyRef": { + "localObjectReference": { + "name" : "bucket-credentials" + }, + "key": "endpoint" + } + }, + "name": "BUCKET_ENDPOINT_URL" + }, + { + "valueFrom": { + "secretKeyRef": { + "localObjectReference": { + "name" : "bucket-credentials" + }, + "key": "key" + } + }, + "name": "BUCKET_KEY" + }, + { + "valueFrom": { + "secretKeyRef": { + "localObjectReference": { + "name" : "bucket-credentials" + }, + "key": "secret" + } + }, + "name": "BUCKET_SECRET" + } + ] + } + ], + "terminationGracePeriodSeconds": 20 + } + }], + "graph": { + "children": [], + "name": "classifier", + "endpoint": { + "type": "REST" + }, + "type": "MODEL" + }, + "name": "pytorch-model", + "replicas": 1, + "annotations": { + "predictor_version": "v1" + } + } + ] + } +} diff --git a/community/FfDL-Seldon/pytorch-model/requirements.txt b/community/FfDL-Seldon/pytorch-model/requirements.txt new file mode 100644 index 00000000..7db01131 --- /dev/null +++ b/community/FfDL-Seldon/pytorch-model/requirements.txt @@ -0,0 +1,3 @@ +torch==0.4.0 +torchvision==0.2.1 +boto3==1.7.28 diff --git a/community/FfDL-Seldon/pytorch-model/serving_ambassador.ipynb b/community/FfDL-Seldon/pytorch-model/serving_ambassador.ipynb new file mode 100644 index 00000000..2ed1a3e2 --- /dev/null +++ b/community/FfDL-Seldon/pytorch-model/serving_ambassador.ipynb @@ -0,0 +1,138 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test PyTorch MNIST Model via Ambassador\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python Dependencies\n", + "\n", + " * Requests\n", + " * Numpy\n", + " * Matplotlib\n", + " * Tensorflow" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Set up REST and gRPC methods" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Install gRPC modules for the prediction protos." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "from requests.auth import HTTPBasicAuth\n", + "from random import randint,random\n", + "import numpy as np\n", + "from tensorflow.examples.tutorials.mnist import input_data\n", + "from matplotlib import pyplot as plt\n", + "import json\n", + "\n", + "AMBASSADOR_API_IP=\"localhost:8002\"\n", + "\n", + "def rest_request(deploymentName,request):\n", + " response = requests.post(\n", + " \"http://\"+AMBASSADOR_API_IP+\"/seldon/\"+deploymentName+\"/api/v0.1/predictions\",\n", + " json=request)\n", + " return response.json() \n", + "\n", + "def gen_image(arr):\n", + " two_d = (np.reshape(arr, (28, 28)) * 255).astype(np.uint8)\n", + " plt.imshow(two_d,cmap=plt.cm.gray_r, interpolation='nearest')\n", + " return plt\n", + "\n", + "def download_mnist():\n", + " return input_data.read_data_sets(\"MNIST_data/\", one_hot = True)\n", + "\n", + "\n", + "def predict_rest_mnist(mnist):\n", + " batch_xs, batch_ys = mnist.train.next_batch(1)\n", + " chosen=0\n", + " gen_image(batch_xs[chosen]).show()\n", + " data = batch_xs[chosen].reshape((1,784))\n", + " features = [\"X\"+str(i+1) for i in range (0,784)]\n", + " request = {\"data\":{\"names\":features,\"ndarray\":data.tolist()}}\n", + " predictions = rest_request(\"ffdl-pymnist\",request)\n", + " fpreds = [ '%.2f' % elem for elem in predictions[\"data\"][\"ndarray\"][0] ]\n", + " m = dict(zip(predictions[\"data\"][\"names\"],fpreds))\n", + " print(json.dumps(m,indent=2))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Ensure you have port forwarded to the Ambassador pod:**\n", + "\n", + "```\n", + "kubectl port-forward $(kubectl get pods -n default -l service=ambassador -o jsonpath='{.items[0].metadata.name}') -n default 8002:8080\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mnist = download_mnist()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "predict_rest_mnist(mnist)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/community/FfDL-Seldon/pytorch-model/serving_oauth.ipynb b/community/FfDL-Seldon/pytorch-model/serving_oauth.ipynb new file mode 100644 index 00000000..a493d8fa --- /dev/null +++ b/community/FfDL-Seldon/pytorch-model/serving_oauth.ipynb @@ -0,0 +1,155 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test PyTorch MNIST Model via OAuth Gateway\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python Dependencies\n", + "\n", + " * Requests\n", + " * Numpy\n", + " * Matplotlib\n", + " * Tensorflow" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Set up REST and gRPC methods" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Install gRPC modules for the prediction protos." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "from requests.auth import HTTPBasicAuth\n", + "from random import randint,random\n", + "import numpy as np\n", + "from tensorflow.examples.tutorials.mnist import input_data\n", + "from matplotlib import pyplot as plt\n", + "import json\n", + "\n", + "OAUTH_API=\"localhost:8003\"\n", + "\n", + "def rest_request(deploymentName,request):\n", + " response = requests.post(\n", + " \"http://\"+OAUTH_API+\"/seldon/\"+deploymentName+\"/api/v0.1/predictions\",\n", + " json=request)\n", + " return response.json() \n", + "\n", + "def get_token():\n", + " payload = {'grant_type': 'client_credentials'}\n", + " response = requests.post(\n", + " \"http://\"+OAUTH_API+\"/oauth/token\",\n", + " auth=HTTPBasicAuth('oauth-key-pymnist', 'oauth-secret'),\n", + " data=payload)\n", + " token = response.json()[\"access_token\"]\n", + " return token\n", + "\n", + "def rest_request(request,token):\n", + " headers = {'Authorization': 'Bearer '+token}\n", + " response = requests.post(\n", + " \"http://\"+OAUTH_API+\"/api/v0.1/predictions\",\n", + " headers=headers,\n", + " json=request)\n", + " return response.json()\n", + " \n", + "def gen_image(arr):\n", + " two_d = (np.reshape(arr, (28, 28)) * 255).astype(np.uint8)\n", + " plt.imshow(two_d,cmap=plt.cm.gray_r, interpolation='nearest')\n", + " return plt\n", + "\n", + "def download_mnist():\n", + " return input_data.read_data_sets(\"MNIST_data/\", one_hot = True)\n", + "\n", + "def predict_rest_mnist(mnist):\n", + " token = get_token()\n", + " batch_xs, batch_ys = mnist.train.next_batch(1)\n", + " chosen=0\n", + " gen_image(batch_xs[chosen]).show()\n", + " data = batch_xs[chosen].reshape((1,784))\n", + " features = [\"X\"+str(i+1) for i in range (0,784)]\n", + " request = {\"data\":{\"names\":features,\"ndarray\":data.tolist()}}\n", + " predictions = rest_request(request,token)\n", + " fpreds = [ '%.2f' % elem for elem in predictions[\"data\"][\"ndarray\"][0] ]\n", + " m = dict(zip(predictions[\"data\"][\"names\"],fpreds))\n", + " print(json.dumps(m,indent=2))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Ensure you have port forwarded to the Seldon API OAUTH Gateway pod:**\n", + "\n", + "```\n", + "kubectl port-forward $(kubectl get pods -n default -l app=seldon-apiserver-container-app -o jsonpath='{.items[0].metadata.name}') -n default 8003:8080\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mnist = download_mnist()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "predict_rest_mnist(mnist)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/community/FfDL-Seldon/tf-model/.bucket_secret.yaml.tmpl.swp b/community/FfDL-Seldon/tf-model/.bucket_secret.yaml.tmpl.swp new file mode 100644 index 00000000..3fb230e8 Binary files /dev/null and b/community/FfDL-Seldon/tf-model/.bucket_secret.yaml.tmpl.swp differ diff --git a/community/FfDL-Seldon/tf-model/.s2i/environment b/community/FfDL-Seldon/tf-model/.s2i/environment new file mode 100644 index 00000000..de816076 --- /dev/null +++ b/community/FfDL-Seldon/tf-model/.s2i/environment @@ -0,0 +1,4 @@ +MODEL_NAME=TFMnist +API_TYPE=REST +SERVICE_TYPE=MODEL +PERSISTENCE=0 diff --git a/community/FfDL-Seldon/tf-model/.s2i/environment~ b/community/FfDL-Seldon/tf-model/.s2i/environment~ new file mode 100644 index 00000000..d5a1d6d6 --- /dev/null +++ b/community/FfDL-Seldon/tf-model/.s2i/environment~ @@ -0,0 +1,4 @@ +MODEL_NAME=DeepMnist +API_TYPE=REST +SERVICE_TYPE=MODEL +PERSISTENCE=0 diff --git a/community/FfDL-Seldon/tf-model/README.md b/community/FfDL-Seldon/tf-model/README.md new file mode 100644 index 00000000..87eba778 --- /dev/null +++ b/community/FfDL-Seldon/tf-model/README.md @@ -0,0 +1,52 @@ +# TensorFlow MNIST Classifier + +# Assumptions + + * You have installed [seldon-core](https://github.com/SeldonIO/seldon-core/blob/master/docs/install.md) on you FfDL cluster. + +# Train Model + +Train the [Tensorflow MNIST model](https://github.com/IBM/FfDL/tree/master/etc/examples/tf-model) following the steps in the [user guide](https://github.com/IBM/FfDL#6-detailed-testing-instructions). + +# Wrap the Runtime Scorer +You can skip this step if you are happy to use the already packaged image ```seldonio/ffdl-mnist``` from DockerHub. + +The runtime MNIST scrorer is contained within a standalone [python class TFMnist.py](./TFMnist.py). This needs to be packaged in a Docker container to run within Seldon. For this we use [Redhat's Source-to-image](https://github.com/openshift/source-to-image). + + * Install [S2I](https://github.com/openshift/source-to-image#installation) + * From the tf-model folder run, (*change seldonio to your Docker repo*) **You will need at least 8GB for your local Docker.** : +``` +s2i build . seldonio/seldon-core-s2i-python2 seldonio/ffdl-mnist:0.1 +``` + * Push image to DockerHub or your Docker repo accessible from the FfDL cluster. + +# Deploy Model +To deploy the model you need to create the deployment resource from the template ```ffdl-mnist-deployment.json```. You will need to set: + + * TRAINING_ID : Your FfDL Training ID + * BUCKET_NAME : The name of the bucket containing your model + +You will also need to create a kubernetes secret containing your bucket endpoint url, key and secret. You can use the ```bucket-secret.yaml``` as a template, e.g.: + + * edit ```bucket-secret.yaml``` + * Enter the base64 values for endpoint url, key, secret + * On a linux system running bash shell you could do the following to get your values, ```echo -n "my key" | base64``` + * run ```kubectl create -f bucket-secret.yaml``` + +Create a deployment file by adding your settings, e.g. using sed below: + +``` +cat ffdl-mnist-deployment.json | sed 's/%TRAINING_ID%/training-84hIKJViR/' | sed 's/%BUCKET_NAME%/tf_trained_model/' > ffdl-mnist-deployment_mydeploy.json +``` + +Deploy: +``` +kubectl create -f ffdl-mnist-deployment_mydeploy.json +``` + +# Test + +To test the running model with example MNIST images you can run either of two notebooks depending on how you exposed the Seldon APIs + + * [Ambassador Example](serving_ambassador.ipynb) + * [Seldon OAuth Example](serving_oauth.ipynb) diff --git a/community/FfDL-Seldon/tf-model/TFMnist.py b/community/FfDL-Seldon/tf-model/TFMnist.py new file mode 100644 index 00000000..78c2dc71 --- /dev/null +++ b/community/FfDL-Seldon/tf-model/TFMnist.py @@ -0,0 +1,75 @@ +# +# Copyright 2017-2018 IBM Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import tensorflow as tf +import boto3 +import botocore +import tarfile +import os + +class TFMnist(object): + def __init__(self): + training_id = os.environ.get("TRAINING_ID") + endpoint_url = os.environ.get("BUCKET_ENDPOINT_URL") + bucket_name = os.environ.get("BUCKET_NAME") + bucket_key = os.environ.get("BUCKET_KEY") + bucket_secret = os.environ.get("BUCKET_SECRET") + print("Training id:{} endpoint URL:{} key:{} secret:{}".format(training_id,endpoint_url,bucket_key,bucket_secret)) + + self.class_names = ["class:{}".format(str(i)) for i in range(10)] + #self.class_names = ["prediction"] + + # Define S3 resource and download the model file + client = boto3.resource( + 's3', + endpoint_url=endpoint_url, + aws_access_key_id=bucket_key, + aws_secret_access_key=bucket_secret, + ) + + KEY = training_id + '/saved_model.tar.gz' # replace with your object key + + try: + client.Bucket(bucket_name).download_file(KEY, 'saved_model.tar.gz') + except botocore.exceptions.ClientError as e: + if e.response['Error']['Code'] == "404": + print("The object does not exist.") + else: + raise + + # Untar model file + tar = tarfile.open("saved_model.tar.gz") + tar.extractall() + tar.close() + + # Load the model into tf session and run predictions. + self.sess = tf.Session() + #tf.Session(graph=tf.Graph()) as sess: + # Load saved model into tf session + tf.saved_model.loader.load(self.sess, [tf.saved_model.tag_constants.SERVING], "./") + graph = tf.get_default_graph() + self.input = graph.get_tensor_by_name("x_input:0") + #self.predictor = graph.get_tensor_by_name("predictor:0") + self.output = graph.get_tensor_by_name("y_output:0") + self.keep_prob = tf.placeholder(tf.float32) + + def predict(self,X,feature_names): + predictions = self.sess.run(self.output, feed_dict = {self.input:X, self.keep_prob:1.0}) + return predictions + + + + diff --git a/community/FfDL-Seldon/tf-model/bucket-secret.yaml b/community/FfDL-Seldon/tf-model/bucket-secret.yaml new file mode 100644 index 00000000..3141308e --- /dev/null +++ b/community/FfDL-Seldon/tf-model/bucket-secret.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +data: + endpoint: #ENDPOINT_URL_BASE64# + key: #KEY_BASE64# + secret: #SECRET_BASE64# +kind: Secret +metadata: + name: bucket-credentials +type: Opaque + diff --git a/community/FfDL-Seldon/tf-model/ffdl-mnist-deployment.json b/community/FfDL-Seldon/tf-model/ffdl-mnist-deployment.json new file mode 100644 index 00000000..43c64c53 --- /dev/null +++ b/community/FfDL-Seldon/tf-model/ffdl-mnist-deployment.json @@ -0,0 +1,96 @@ +{ + "apiVersion": "machinelearning.seldon.io\/v1alpha2", + "kind": "SeldonDeployment", + "metadata": { + "labels": { + "app": "seldon" + }, + "name": "ffdl-mnist" + }, + "spec": { + "annotations": { + "project_name": "FfDL Tensorflow MNIST", + "deployment_version": "v1" + }, + "name": "deep-mnist", + "oauth_key": "oauth-key", + "oauth_secret": "oauth-secret", + "predictors": [ + { + "componentSpecs": [{ + "spec": { + "containers": [ + { + "image": "seldonio/ffdl-mnist:0.1", + "imagePullPolicy": "IfNotPresent", + "name": "classifier", + "resources": { + "requests": { + "memory": "1Mi" + } + }, + "env": [ + { + "name": "TRAINING_ID", + "value": "%TRAINING_ID%" + }, + { + "name": "BUCKET_NAME", + "value": "%BUCKET_NAME%" + }, + { + "valueFrom": { + "secretKeyRef": { + "localObjectReference": { + "name" : "bucket-credentials" + }, + "key": "endpoint" + } + }, + "name": "BUCKET_ENDPOINT_URL" + }, + { + "valueFrom": { + "secretKeyRef": { + "localObjectReference": { + "name" : "bucket-credentials" + }, + "key": "key" + } + }, + "name": "BUCKET_KEY" + }, + { + "valueFrom": { + "secretKeyRef": { + "localObjectReference": { + "name" : "bucket-credentials" + }, + "key": "secret" + } + }, + "name": "BUCKET_SECRET" + } + ] + } + ], + "terminationGracePeriodSeconds": 20 + } + }], + "graph": { + "children": [], + "name": "classifier", + "endpoint": { + "type": "REST" + }, + "type": "MODEL" + }, + "name": "single-model", + "replicas": 1, + "annotations": { + "predictor_version": "v1" + } + } + ] + } +} diff --git a/community/FfDL-Seldon/tf-model/requirements.txt b/community/FfDL-Seldon/tf-model/requirements.txt new file mode 100644 index 00000000..71522226 --- /dev/null +++ b/community/FfDL-Seldon/tf-model/requirements.txt @@ -0,0 +1,2 @@ +tensorflow==1.6.0 +boto3==1.7.28 diff --git a/community/FfDL-Seldon/tf-model/serving_ambassador.ipynb b/community/FfDL-Seldon/tf-model/serving_ambassador.ipynb new file mode 100644 index 00000000..b36d03d9 --- /dev/null +++ b/community/FfDL-Seldon/tf-model/serving_ambassador.ipynb @@ -0,0 +1,139 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test TF MNIST Model via Ambassador\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python Dependencies\n", + "\n", + " * Requests\n", + " * Numpy\n", + " * Matplotlib\n", + " * Tensorflow" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Set up REST and gRPC methods" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Install gRPC modules for the prediction protos." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "from requests.auth import HTTPBasicAuth\n", + "from random import randint,random\n", + "import numpy as np\n", + "from tensorflow.examples.tutorials.mnist import input_data\n", + "from matplotlib import pyplot as plt\n", + "import json\n", + "\n", + "AMBASSADOR_API_IP=\"localhost:8002\"\n", + "\n", + "def rest_request(deploymentName,request):\n", + " response = requests.post(\n", + " \"http://\"+AMBASSADOR_API_IP+\"/seldon/\"+deploymentName+\"/api/v0.1/predictions\",\n", + " json=request)\n", + " return response.json() \n", + "\n", + "def gen_image(arr):\n", + " two_d = (np.reshape(arr, (28, 28)) * 255).astype(np.uint8)\n", + " plt.imshow(two_d,cmap=plt.cm.gray_r, interpolation='nearest')\n", + " return plt\n", + "\n", + "def download_mnist():\n", + " return input_data.read_data_sets(\"MNIST_data/\", one_hot = True)\n", + "\n", + "\n", + "def predict_rest_mnist(mnist):\n", + " batch_xs, batch_ys = mnist.train.next_batch(1)\n", + " chosen=0\n", + " gen_image(batch_xs[chosen]).show()\n", + " data = batch_xs[chosen].reshape((1,784))\n", + " features = [\"X\"+str(i+1) for i in range (0,784)]\n", + " request = {\"data\":{\"names\":features,\"ndarray\":data.tolist()}}\n", + " predictions = rest_request(\"ffdl-mnist\",request)\n", + " print(\"Route:\"+json.dumps(predictions[\"meta\"][\"routing\"],indent=2))\n", + " fpreds = [ '%.2f' % elem for elem in predictions[\"data\"][\"ndarray\"][0] ]\n", + " m = dict(zip(predictions[\"data\"][\"names\"],fpreds))\n", + " print(json.dumps(m,indent=2))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Ensure you have port forwarded to the Ambassador pod:**\n", + "\n", + "```\n", + "kubectl port-forward $(kubectl get pods -n default -l service=ambassador -o jsonpath='{.items[0].metadata.name}') -n default 8002:8080\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mnist = download_mnist()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "predict_rest_mnist(mnist)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/community/FfDL-Seldon/tf-model/serving_oauth.ipynb b/community/FfDL-Seldon/tf-model/serving_oauth.ipynb new file mode 100644 index 00000000..11ede1d4 --- /dev/null +++ b/community/FfDL-Seldon/tf-model/serving_oauth.ipynb @@ -0,0 +1,156 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test TF MNIST Model via Ambassador\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python Dependencies\n", + "\n", + " * Requests\n", + " * Numpy\n", + " * Matplotlib\n", + " * Tensorflow" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Set up REST and gRPC methods" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Install gRPC modules for the prediction protos." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "from requests.auth import HTTPBasicAuth\n", + "from random import randint,random\n", + "import numpy as np\n", + "from tensorflow.examples.tutorials.mnist import input_data\n", + "from matplotlib import pyplot as plt\n", + "import json\n", + "\n", + "OAUTH_API=\"localhost:8003\"\n", + "\n", + "def rest_request(deploymentName,request):\n", + " response = requests.post(\n", + " \"http://\"+OAUTH_API+\"/seldon/\"+deploymentName+\"/api/v0.1/predictions\",\n", + " json=request)\n", + " return response.json() \n", + "\n", + "def get_token():\n", + " payload = {'grant_type': 'client_credentials'}\n", + " response = requests.post(\n", + " \"http://\"+OAUTH_API+\"/oauth/token\",\n", + " auth=HTTPBasicAuth('oauth-key', 'oauth-secret'),\n", + " data=payload)\n", + " token = response.json()[\"access_token\"]\n", + " return token\n", + "\n", + "def rest_request(request,token):\n", + " headers = {'Authorization': 'Bearer '+token}\n", + " response = requests.post(\n", + " \"http://\"+OAUTH_API+\"/api/v0.1/predictions\",\n", + " headers=headers,\n", + " json=request)\n", + " return response.json()\n", + " \n", + "def gen_image(arr):\n", + " two_d = (np.reshape(arr, (28, 28)) * 255).astype(np.uint8)\n", + " plt.imshow(two_d,cmap=plt.cm.gray_r, interpolation='nearest')\n", + " return plt\n", + "\n", + "def download_mnist():\n", + " return input_data.read_data_sets(\"MNIST_data/\", one_hot = True)\n", + "\n", + "def predict_rest_mnist(mnist):\n", + " token = get_token()\n", + " batch_xs, batch_ys = mnist.train.next_batch(1)\n", + " chosen=0\n", + " gen_image(batch_xs[chosen]).show()\n", + " data = batch_xs[chosen].reshape((1,784))\n", + " features = [\"X\"+str(i+1) for i in range (0,784)]\n", + " request = {\"data\":{\"names\":features,\"ndarray\":data.tolist()}}\n", + " predictions = rest_request(request,token)\n", + " print(\"Route:\"+json.dumps(predictions[\"meta\"][\"routing\"],indent=2))\n", + " fpreds = [ '%.2f' % elem for elem in predictions[\"data\"][\"ndarray\"][0] ]\n", + " m = dict(zip(predictions[\"data\"][\"names\"],fpreds))\n", + " print(json.dumps(m,indent=2))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Ensure you have port forwarded to the Seldon API OAUTH Gateway pod:**\n", + "\n", + "```\n", + "kubectl port-forward $(kubectl get pods -n default -l app=seldon-apiserver-container-app -o jsonpath='{.items[0].metadata.name}') -n default 8003:8080\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mnist = download_mnist()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "predict_rest_mnist(mnist)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/community/collaborators.yaml b/community/collaborators.yaml new file mode 100644 index 00000000..d37b80b4 --- /dev/null +++ b/community/collaborators.yaml @@ -0,0 +1,17 @@ +- org: IBM + contacts: + - singhan@us.ibm.com + - scott_boag@us.ibm.com + - falk.pollok@ibm.com + - Tommy.Chaoping.Li@ibm.com + - whummer@ibm.com + url: https://ibm.com +- org: Seldon + contacts: + - cc@seldon.io + url: https://www.seldon.io +- org: H2O.ai + contacts: + - vinod@h2o.ai + - nicholas@h2o.ai + url: https://h2o.ai diff --git a/dashboard/Dockerfile b/dashboard/Dockerfile index 695f7e62..ddb5d366 100644 --- a/dashboard/Dockerfile +++ b/dashboard/Dockerfile @@ -1,8 +1,20 @@ -FROM node:8.5-alpine +FROM node:8-alpine -# install chromium for headless browser tests -ENV CHROME_BIN=/usr/bin/chromium-browser -RUN apk add --no-cache chromium udev ttf-freefont +ARG ARCH=x86_64 + +# install chromium/firefox for headless browser tests +ENV CHROME_BIN=/usr/bin/browser + +RUN case "${ARCH}" in \ + amd64) \ + apk add --no-cache chromium udev ttf-freefont; \ + ln -s /usr/bin/chromium-browser /usr/bin/browser \ + ;; \ + ppc64le) \ + apk add --no-cache firefox-esr udev ttf-freefont python build-base; \ + ln -s /usr/bin/firefox /usr/bin/browser \ + ;; \ + esac # set workdir WORKDIR /ffdl/ffdl-dashboard @@ -11,7 +23,8 @@ WORKDIR /ffdl/ffdl-dashboard RUN npm config set user 0 RUN npm config set unsafe-perm true # install global dependencies -RUN npm install --quiet -g @angular/cli +# RUN npm install --quiet -g @angular/cli +RUN npm install --quiet -g @angular/cli@6.0.8 RUN npm install --quiet -g http-server # set non-root user diff --git a/dashboard/e2e/app.e2e-spec.ts b/dashboard/e2e/app.e2e-spec.ts index 3516c504..90ee878b 100644 --- a/dashboard/e2e/app.e2e-spec.ts +++ b/dashboard/e2e/app.e2e-spec.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { AppPage } from './app.po'; describe('ffdl-dashboard App', () => { diff --git a/dashboard/e2e/app.po.ts b/dashboard/e2e/app.po.ts index 82ea75ba..c817f938 100644 --- a/dashboard/e2e/app.po.ts +++ b/dashboard/e2e/app.po.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { browser, by, element } from 'protractor'; export class AppPage { diff --git a/dashboard/karma.conf.js b/dashboard/karma.conf.js index af139fad..c28c2d67 100644 --- a/dashboard/karma.conf.js +++ b/dashboard/karma.conf.js @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // Karma configuration file, see link for more information // https://karma-runner.github.io/1.0/config/configuration-file.html diff --git a/dashboard/package-lock.json b/dashboard/package-lock.json index 4dbd35f5..bdd8ca6d 100644 --- a/dashboard/package-lock.json +++ b/dashboard/package-lock.json @@ -5,78 +5,104 @@ "requires": true, "dependencies": { "@angular-devkit/build-optimizer": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.0.33.tgz", - "integrity": "sha512-qdGAwI3Yd3QIJ4FJsJcAyBVThUVEGKqSm0E3njSVSQkEatjvxHXNDvexBieQDPiUhjYG2Yyobor8nW5EMxPieQ==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.3.2.tgz", + "integrity": "sha512-U0BCZtThq5rUfY08shHXpxe8ZhSsiYB/cJjUvAWRTs/ORrs8pbngS6xwseQws8d/vHoVrtqGD9GU9h8AmFRERQ==", "dev": true, "requires": { "loader-utils": "1.1.0", "source-map": "0.5.7", - "typescript": "2.4.2", - "webpack-sources": "1.0.2" + "typescript": "2.6.2", + "webpack-sources": "1.1.0" + }, + "dependencies": { + "typescript": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.2.tgz", + "integrity": "sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q=", + "dev": true + } } }, "@angular-devkit/core": { - "version": "0.0.20", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-0.0.20.tgz", - "integrity": "sha512-lg5BvMxOfbVD//SOQvpq6TPIKTXYNMj0I9N/kfXbXkUGgiBGFLyFMf2fc+qNvDoa7lulKMPT8OJWS1YlGt93eg==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-0.3.2.tgz", + "integrity": "sha512-zABk/iP7YX5SVbmK4e+IX7j2d0D37MQJQiKgWdV3JzfvVJhNJzddiirtT980pIafoq+KyvTgVwXtc+vnux0oeQ==", "dev": true, "requires": { + "ajv": "5.5.2", + "chokidar": "1.7.0", + "rxjs": "5.5.7", "source-map": "0.5.7" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + } } }, "@angular-devkit/schematics": { - "version": "0.0.36", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-0.0.36.tgz", - "integrity": "sha512-6Aj2uuSaGVWhwVDJb7wrkVdunHY1FVak7/P24NuFTUT3ThShQs2LI5UrRKbIJKIHqxtb8PYHebFsjHCHISlRMw==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-0.3.2.tgz", + "integrity": "sha512-B6zZoqvHaTJy+vVdA6EtlxnCdGMa5elCa4j9lQLC3JI8DLvMXUWkCIPVbPzJ/GSRR9nsKWpvYMYaJyfBDUqfhw==", "dev": true, "requires": { - "@angular-devkit/core": "0.0.20", - "@ngtools/json-schema": "1.1.0", - "minimist": "1.2.0", - "rxjs": "5.5.2" + "@ngtools/json-schema": "1.2.0", + "rxjs": "5.5.7" } }, "@angular/animations": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-5.0.2.tgz", - "integrity": "sha1-bTpzWk+Fw4jaa6P3ddu+YUBKwC0=", + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-5.2.8.tgz", + "integrity": "sha512-VfHN7ICR9QBaEbA02ip7ipNjD6m9ayfsliIE/ACkTVevObEdL90T3Q/NxiX+JRZSDL09M9XopIi1/WOeOn6Evw==", "requires": { "tslib": "1.8.0" } }, "@angular/cli": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-1.5.3.tgz", - "integrity": "sha512-PuMcYmnoPP/RqCVIguiJrkc+vek9eVPi+iQ+UE3W/JTDQhZsAkm4qm8zLYR/Z2bp1a5xHuP+PFMtAQysPFag+Q==", - "dev": true, - "requires": { - "@angular-devkit/build-optimizer": "0.0.33", - "@angular-devkit/schematics": "0.0.36", - "@ngtools/json-schema": "1.1.0", - "@ngtools/webpack": "1.8.3", - "@schematics/angular": "0.1.5", - "autoprefixer": "6.7.7", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-1.7.3.tgz", + "integrity": "sha512-19sh0SbjneG7/R/FvZBfHsHqfIqyj4LQuXdddJKMCDM97UoHQTjfgrpRvBf3a3lR79wdLXchWJBD9Yc6ifosEA==", + "dev": true, + "requires": { + "@angular-devkit/build-optimizer": "0.3.2", + "@angular-devkit/core": "0.3.2", + "@angular-devkit/schematics": "0.3.2", + "@ngtools/json-schema": "1.2.0", + "@ngtools/webpack": "1.10.2", + "@schematics/angular": "0.3.2", + "@schematics/package-update": "0.3.2", + "ajv": "6.2.1", + "autoprefixer": "7.2.6", + "cache-loader": "1.2.2", "chalk": "2.2.2", - "circular-dependency-plugin": "3.0.0", - "common-tags": "1.4.0", - "copy-webpack-plugin": "4.2.1", + "circular-dependency-plugin": "4.4.0", + "clean-css": "4.1.11", + "common-tags": "1.7.2", + "copy-webpack-plugin": "4.4.3", "core-object": "3.1.5", - "css-loader": "0.28.7", - "cssnano": "3.10.0", "denodeify": "1.2.1", "ember-cli-string-utils": "1.1.0", - "exports-loader": "0.6.4", - "extract-text-webpack-plugin": "3.0.0", - "file-loader": "1.1.5", - "fs-extra": "4.0.2", + "extract-text-webpack-plugin": "3.0.2", + "file-loader": "1.1.11", + "fs-extra": "4.0.3", "glob": "7.1.2", "html-webpack-plugin": "2.30.1", - "istanbul-instrumenter-loader": "2.0.0", + "istanbul-instrumenter-loader": "3.0.0", "karma-source-map-support": "1.2.0", "less": "2.7.3", - "less-loader": "4.0.5", - "license-webpack-plugin": "1.1.1", + "less-loader": "4.1.0", + "license-webpack-plugin": "1.3.0", + "loader-utils": "1.1.0", "lodash": "4.17.4", "memory-fs": "0.4.1", "minimatch": "3.0.4", @@ -85,124 +111,122 @@ "nopt": "4.0.1", "opn": "5.1.0", "portfinder": "1.0.13", - "postcss-custom-properties": "6.2.0", - "postcss-loader": "2.0.8", - "postcss-url": "7.2.1", + "postcss": "6.0.19", + "postcss-import": "11.1.0", + "postcss-loader": "2.1.1", + "postcss-url": "7.3.1", "raw-loader": "0.5.1", "resolve": "1.5.0", - "rxjs": "5.5.2", - "sass-loader": "6.0.6", + "rxjs": "5.5.7", + "sass-loader": "6.0.7", "semver": "5.4.1", "silent-error": "1.1.0", - "source-map-loader": "0.2.3", "source-map-support": "0.4.18", - "style-loader": "0.13.2", + "style-loader": "0.19.1", "stylus": "0.54.5", - "stylus-loader": "3.0.1", - "uglifyjs-webpack-plugin": "1.0.0", + "stylus-loader": "3.0.2", + "uglifyjs-webpack-plugin": "1.2.3", "url-loader": "0.6.2", - "webpack": "3.8.1", - "webpack-concat-plugin": "1.4.0", - "webpack-dev-middleware": "1.12.0", - "webpack-dev-server": "2.9.4", - "webpack-merge": "4.1.1", - "webpack-sources": "1.0.2", - "webpack-subresource-integrity": "1.0.1", - "zone.js": "0.8.18" + "webpack": "3.11.0", + "webpack-dev-middleware": "1.12.2", + "webpack-dev-server": "2.11.2", + "webpack-merge": "4.1.2", + "webpack-sources": "1.1.0", + "webpack-subresource-integrity": "1.0.4" } }, "@angular/common": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-5.0.2.tgz", - "integrity": "sha1-2AMiFT+qqazKkVUmOKPkfcI3umo=", + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-5.2.8.tgz", + "integrity": "sha512-vHODEZPDtBU5b7a2GjtQYPYmCPRq5FQsJp696pebGMJEZdvN/Du43z8V7lWEdBBLGD+oNXX6rXGD9Pr4P/Bg9w==", "requires": { "tslib": "1.8.0" } }, "@angular/compiler": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-5.0.2.tgz", - "integrity": "sha1-2GXUNyJ83RYYP4eQCjiJPY9fsTk=", + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-5.2.8.tgz", + "integrity": "sha512-xFqY7LDt/LGo6zaYzUwDRGq6Dm2Q9Z2R86ZNdy5wYRzMP+qLnwwENbU74YailKlt02WNtp83R1fdRDDlKI8N+Q==", "requires": { "tslib": "1.8.0" } }, "@angular/compiler-cli": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-5.0.2.tgz", - "integrity": "sha1-WbFnQTKF0ZX5ndHZvnP3D+2zNCk=", + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-5.2.8.tgz", + "integrity": "sha512-u0cUfpbU2VNmRfkSS/tlsAzF24/LdlXqv8RFFLReJhwZTv4mKl1DzSjvOf6kfALGHDqCdHsVWcx2YJ8f6CeCMg==", "dev": true, "requires": { "chokidar": "1.7.0", "minimist": "1.2.0", - "reflect-metadata": "0.1.10", - "tsickle": "0.24.1" + "reflect-metadata": "0.1.12", + "tsickle": "0.27.2" } }, "@angular/core": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-5.0.2.tgz", - "integrity": "sha1-+7VpHRr37GKSSAHIlDlVaTVihUo=", + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-5.2.8.tgz", + "integrity": "sha512-exvh2OY+WDm90bgzZ89Asi2nZc2zrg/OWJuKMbxNfA6nxnyjCQ7uGRjTGr+MOynG+vd54J2Evtg2eDPdbcNg5A==", "requires": { "tslib": "1.8.0" } }, "@angular/forms": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-5.0.2.tgz", - "integrity": "sha1-9Mb/JdUXkPYydi6xxQd00XyM9GU=", + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-5.2.8.tgz", + "integrity": "sha512-yxpFwZcek7259O1+4p1Zfd8FOEJs8lh6T8n2W7IBT8Q1pcAMBCYfMi/Xga69AbypFIy3P+V6DaJoq8ZZgpwefg==", "requires": { "tslib": "1.8.0" } }, "@angular/http": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@angular/http/-/http-5.0.2.tgz", - "integrity": "sha1-yzrxUh4U8ECqjKFVTij435tW/eg=", + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/@angular/http/-/http-5.2.8.tgz", + "integrity": "sha512-vtrO7RLN9v7adVrs/neWStmrCH6+4gm1gYqUYfl6BIYnazACMleqIeAagTbTD08oMblx2dU17NRNbD+2qL8q5A==", "requires": { "tslib": "1.8.0" } }, "@angular/language-service": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-5.0.2.tgz", - "integrity": "sha1-q4ZjZx+WJ4NT+18eY3agdQYZjwc=", + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-5.2.8.tgz", + "integrity": "sha512-MEEi1jB7oJgJxHmSDkwlu4Fm1bSU5TpkE3ideqO8ollxPbMgNOYNwH/9Gm634qPD+rvQaeXywKLQ0i+LQQlYiA==", "dev": true }, "@angular/platform-browser": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-5.0.2.tgz", - "integrity": "sha1-0Quv8DwkN/MIhHnBc9MK/fCxJKk=", + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-5.2.8.tgz", + "integrity": "sha512-f0tONG8+ZQOiv5/hLY76Sl1/BY6AR8Zt4buf2klz7zba5SxKLZwcsk6OfJC2PA0WtlJGiz7cSjbPr0B5sZKv8w==", "requires": { "tslib": "1.8.0" } }, "@angular/platform-browser-dynamic": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-5.0.2.tgz", - "integrity": "sha1-iYSn4vxPimdg+aBdlaK7n2sLf5o=", + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-5.2.8.tgz", + "integrity": "sha512-FzHVZf5XMty0v+hnWOU5PsXexlebvW4+EhfGG85vWCM/M9y0bF3ZSmdqZoXfGO8/Px2JbcBx0r3+GKUgsCieMA==", "requires": { "tslib": "1.8.0" } }, "@angular/router": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-5.0.2.tgz", - "integrity": "sha1-vhBPsJG87EGN09hU+K9koD5cZ50=", + "version": "5.2.8", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-5.2.8.tgz", + "integrity": "sha512-v4k1eUpauO8z/q9kcjr+vDhLvvGw5MzctJJQRoObqLhckFGBmAoITfEFsbF1ejsd/nqa9i+ivxe+LB00evbFXw==", "requires": { "tslib": "1.8.0" } }, "@ngtools/json-schema": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@ngtools/json-schema/-/json-schema-1.1.0.tgz", - "integrity": "sha1-w6DFRNYjkqzCgTpCyKDcb1j4aSI=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ngtools/json-schema/-/json-schema-1.2.0.tgz", + "integrity": "sha512-pMh+HDc6mOjUO3agRfB1tInimo7hf67u+0Cska2bfXFe6oU7rSMnr5PLVtiZVgwMoBHpx/6XjBymvcnWPo2Uzg==", "dev": true }, "@ngtools/webpack": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-1.8.3.tgz", - "integrity": "sha512-Yf6leN/IuBhhZ93qq3NRJL1NlAtn1NsowRagZ2y5gpIw64wheuaHNg52EB+HiyQ23Mejc811gKYCbs1KpcaYVw==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-1.10.2.tgz", + "integrity": "sha512-3u2zg2rarG3qNLSukBClGADWuq/iNn5SQtlSeAbfKzwBeyLGbF0gN1z1tVx1Bcr8YwFzR6NdRePQmJGcoqq1fg==", "dev": true, "requires": { "chalk": "2.2.2", @@ -211,22 +235,42 @@ "magic-string": "0.22.4", "semver": "5.4.1", "source-map": "0.5.7", - "tree-kill": "1.2.0" + "tree-kill": "1.2.0", + "webpack-sources": "1.1.0" } }, "@schematics/angular": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-0.1.5.tgz", - "integrity": "sha512-ls2mnpxVd5/la458whcPJYhEkDpvEsF8qcACMC4mNIsxqPUyn/SnjbuZExOW9+1QJGaSYTG17Kilh3N2nEl9XA==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-0.3.2.tgz", + "integrity": "sha512-Elrk0BA951s0ScFZU0AWrpUeJBYVR52DZ1QTIO5R0AhwEd1PW4olI8szPLGQlVW5Sd6H0FA/fyFLIvn2r9v6Rw==", + "dev": true, + "requires": { + "typescript": "2.6.2" + }, + "dependencies": { + "typescript": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.2.tgz", + "integrity": "sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q=", + "dev": true + } + } + }, + "@schematics/package-update": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@schematics/package-update/-/package-update-0.3.2.tgz", + "integrity": "sha512-7aVP4994Hu8vRdTTohXkfGWEwLhrdNP3EZnWyBootm5zshWqlQojUGweZe5zwewsKcixeVOiy2YtW+aI4aGSLA==", "dev": true, "requires": { - "@angular-devkit/core": "0.0.20" + "rxjs": "5.5.7", + "semver": "5.4.1", + "semver-intersect": "1.3.1" } }, "@types/chart.js": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.6.8.tgz", - "integrity": "sha512-edl/beIQzzp9Lo5BAT6ZLU+pes8UsYh22IEZJ1Et1VF+DgK1nUgT+0UR1Tk/LGvzP7M2kYLymA/QZtpWyrAugw==", + "version": "2.7.10", + "resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.7.10.tgz", + "integrity": "sha512-C3EvXLvi4XXzqyf7UKEXJ0gIZ1N74oocGOEsQuSnnjEYDs/H1giEbpEsLnZ3mLBfP2mhH+7iATBbzwvd4ErYlw==", "dev": true }, "@types/jasmine": { @@ -245,15 +289,15 @@ } }, "@types/jquery": { - "version": "3.2.16", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.2.16.tgz", - "integrity": "sha512-q2WC02YxQoX2nY1HRKlYGHpGP1saPmD7GN0pwCDlTz35a4eOtJG+aHRlXyjCuXokUukSrR2aXyBhSW3j+jPc0A==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.1.tgz", + "integrity": "sha512-N3h+rzN518yl2xKrW0o6KKdNmWZ+OwG6SoM5TBEQFF0tTv5wXPEsoOuYQ2Kt3/89XbcSZUJLdjiT/2c3BR/ApQ==", "dev": true }, "@types/node": { - "version": "6.0.92", - "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.92.tgz", - "integrity": "sha512-awEYSSTn7dauwVCYSx2CJaPTu0Z1Ht2oR1b2AD3CYao6ZRb+opb6EL43fzmD7eMFgMHzTBWSUzlWSD+S8xN0Nw==", + "version": "6.0.102", + "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.102.tgz", + "integrity": "sha512-EhNufyBoC1Kqaj+XMHGzi6mPUC8wVABOMTPE5XaSJc49LIVvXsyrV1HYMAPTUViT7E4wLUB38OdDmb+HshjGmA==", "dev": true }, "@types/q": { @@ -275,19 +319,36 @@ "dev": true }, "accepts": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", - "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "dev": true, "requires": { - "mime-types": "2.1.17", + "mime-types": "2.1.18", "negotiator": "0.6.1" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "1.33.0" + } + } } }, "acorn": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", - "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", + "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", "dev": true }, "acorn-dynamic-import": { @@ -338,21 +399,20 @@ } }, "ajv": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.4.0.tgz", - "integrity": "sha1-MtHPCNvIDEMvQm8S4QslEfa0ZHQ=", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.2.1.tgz", + "integrity": "sha1-KKarxJOiq+D7TIUHrK7bQ/pVBnE=", "dev": true, "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.0.0", + "fast-deep-equal": "1.1.0", "fast-json-stable-stringify": "2.0.0", "json-schema-traverse": "0.3.1" } }, "ajv-keywords": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.1.0.tgz", + "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74=", "dev": true }, "align-text": { @@ -366,12 +426,6 @@ "repeat-string": "1.6.1" } }, - "alphanum-sort": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", - "dev": true - }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", @@ -379,9 +433,9 @@ "dev": true }, "angular2-notifications": { - "version": "0.9.6", - "resolved": "https://registry.npmjs.org/angular2-notifications/-/angular2-notifications-0.9.6.tgz", - "integrity": "sha1-zMQrCT7DIoYLZ78Itm0gLYKXVtI=" + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/angular2-notifications/-/angular2-notifications-0.9.7.tgz", + "integrity": "sha1-IQoAfWsVyS0/2bGxo+DiIVF8CeA=" }, "ansi-html": { "version": "0.0.7", @@ -446,9 +500,9 @@ } }, "argparse": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { "sprintf-js": "1.0.3" @@ -469,6 +523,12 @@ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -488,7 +548,7 @@ "dev": true, "requires": { "define-properties": "1.1.2", - "es-abstract": "1.9.0" + "es-abstract": "1.10.0" } }, "array-slice": { @@ -544,9 +604,9 @@ "dev": true }, "asn1.js": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz", - "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "dev": true, "requires": { "bn.js": "4.11.8", @@ -569,6 +629,12 @@ "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", "dev": true }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, "async": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", @@ -597,17 +663,23 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, + "atob": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", + "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", + "dev": true + }, "autoprefixer": { - "version": "6.7.7", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", - "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.6.tgz", + "integrity": "sha512-Iq8TRIB+/9eQ8rbGhcP7ct5cYb/3qjNYAR2SnzLCEcwF6rvVOax8+9+fccgXk4bEhQGjOZd5TLhsksmAdsbGqQ==", "dev": true, "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000769", + "browserslist": "2.11.3", + "caniuse-lite": "1.0.30000814", "normalize-range": "0.1.2", "num2fraction": "1.2.2", - "postcss": "5.2.18", + "postcss": "6.0.19", "postcss-value-parser": "3.3.0" } }, @@ -662,9 +734,9 @@ } }, "babel-generator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", - "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", "dev": true, "requires": { "babel-messages": "6.23.0", @@ -700,8 +772,8 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.1", - "regenerator-runtime": "0.11.0" + "core-js": "2.5.3", + "regenerator-runtime": "0.11.1" } }, "babel-template": { @@ -730,7 +802,7 @@ "babylon": "6.18.0", "debug": "2.6.9", "globals": "9.18.0", - "invariant": "2.2.2", + "invariant": "2.2.4", "lodash": "4.17.4" } }, @@ -764,6 +836,38 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + } + } + }, "base64-arraybuffer": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", @@ -771,9 +875,9 @@ "dev": true }, "base64-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", - "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz", + "integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w==", "dev": true }, "base64id": { @@ -892,7 +996,7 @@ "deep-equal": "1.0.1", "dns-equal": "1.0.0", "dns-txt": "2.0.2", - "multicast-dns": "6.2.0", + "multicast-dns": "6.2.3", "multicast-dns-service-types": "1.1.0" } }, @@ -912,9 +1016,9 @@ } }, "bootstrap": { - "version": "4.0.0-beta.2", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.0.0-beta.2.tgz", - "integrity": "sha512-DzGtdTlKbrMoGMpz0LigKSqJ+MgtFKxA791PU/q062OlRG0HybNZcTLH7rpDAmLS66Y3esN9yzKHLLbqa5UR3w==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.0.0.tgz", + "integrity": "sha512-gulJE5dGFo6Q61V/whS6VM4WIyrlydXfCgkE+Gxe5hjrJ8rXLLZlALq7zq2RPhOc45PSwQpJkrTnc2KgD6cvmA==" }, "brace-expansion": { "version": "1.1.8", @@ -986,7 +1090,7 @@ "dev": true, "requires": { "bn.js": "4.11.8", - "randombytes": "2.0.5" + "randombytes": "2.0.6" } }, "browserify-sign": { @@ -1014,13 +1118,13 @@ } }, "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", + "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", "dev": true, "requires": { - "caniuse-db": "1.0.30000769", - "electron-to-chromium": "1.3.27" + "caniuse-lite": "1.0.30000814", + "electron-to-chromium": "1.3.37" } }, "buffer": { @@ -1029,7 +1133,7 @@ "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { - "base64-js": "1.2.1", + "base64-js": "1.2.3", "ieee754": "1.1.8", "isarray": "1.0.0" } @@ -1065,24 +1169,61 @@ "dev": true }, "cacache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.1.tgz", - "integrity": "sha512-dRHYcs9LvG9cHgdPzjiI+/eS7e1xRhULrcyOx04RZQsszNJXU2SL9CyG60yLnge282Qq5nwTv+ieK2fH+WPZmA==", + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", + "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", "dev": true, "requires": { "bluebird": "3.5.1", "chownr": "1.0.1", "glob": "7.1.2", "graceful-fs": "4.1.11", - "lru-cache": "4.1.1", - "mississippi": "1.3.0", + "lru-cache": "4.1.2", + "mississippi": "2.0.0", "mkdirp": "0.5.1", "move-concurrently": "1.0.1", "promise-inflight": "1.0.1", "rimraf": "2.6.2", - "ssri": "5.0.0", + "ssri": "5.3.0", "unique-filename": "1.1.0", - "y18n": "3.2.1" + "y18n": "4.0.0" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + }, + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + } + } + }, + "cache-loader": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cache-loader/-/cache-loader-1.2.2.tgz", + "integrity": "sha512-rsGh4SIYyB9glU+d0OcHwiXHXBoUgDhHZaQ1KAbiXqfz1CDPxtTboh1gPbJ0q2qdO8a9lfcjgC5CJ2Ms32y5bw==", + "dev": true, + "requires": { + "loader-utils": "1.1.0", + "mkdirp": "0.5.1", + "neo-async": "2.5.0", + "schema-utils": "0.4.5" } }, "callsite": { @@ -1117,22 +1258,10 @@ "map-obj": "1.0.1" } }, - "caniuse-api": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", - "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", - "dev": true, - "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000769", - "lodash.memoize": "4.1.2", - "lodash.uniq": "4.5.0" - } - }, - "caniuse-db": { - "version": "1.0.30000769", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000769.tgz", - "integrity": "sha1-wjC5wbno2z4cDYWMluaFdBuWzBA=", + "caniuse-lite": { + "version": "1.0.30000814", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000814.tgz", + "integrity": "sha512-Kt4dBhVlnTZ+jj+C8Bd4WT6RT4EJoX5/tlktHQfpqIMgLVrG1KBQlLf010ipMvuNrpQiAJ2A54e6MMbA0BaKxg==", "dev": true }, "caseless": { @@ -1149,14 +1278,6 @@ "requires": { "align-text": "0.1.4", "lazy-cache": "1.0.4" - }, - "dependencies": { - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - } } }, "chalk": { @@ -1170,16 +1291,10 @@ "supports-color": "4.5.0" } }, - "charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true - }, "chart.js": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.7.1.tgz", - "integrity": "sha512-pX1oQAY86MiuyZ2hY593Acbl4MLHKrBBhhmZ1YqSadzQbbsBE2rnd6WISoHjIsdf0WDeC0hbePYCz2ZxkV8L+g==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.7.2.tgz", + "integrity": "sha512-90wl3V9xRZ8tnMvMlpcW+0Yg13BelsGS9P9t0ClaDxv/hdypHDr/YAGf+728m11P5ljwyB0ZHfPKCapZFqSqYA==", "requires": { "chartjs-color": "2.2.0", "moment": "2.18.1" @@ -1217,6 +1332,7 @@ "requires": { "anymatch": "1.3.2", "async-each": "1.0.1", + "fsevents": "1.1.3", "glob-parent": "2.0.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", @@ -1259,51 +1375,95 @@ } }, "circular-dependency-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-3.0.0.tgz", - "integrity": "sha1-m2hpLjWw41EJmNAWS2rlARvqV2A=", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-4.4.0.tgz", + "integrity": "sha512-yEFtUNUYT4jBykEX5ZOHw+5goA3glGZr9wAXIQqoyakjz5H5TeUmScnWRc52douAhb9eYzK3s7V6bXfNnjFdzg==", "dev": true }, - "clap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", - "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { - "chalk": "1.1.3" + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" }, "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } } }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } }, "clean-css": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.9.tgz", - "integrity": "sha1-Nc7ornaHpJuYA09w3gDE7dOCYwE=", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.11.tgz", + "integrity": "sha1-Ls3xRaujj1R0DybO/Q/z4D4SXWo=", "dev": true, "requires": { "source-map": "0.5.7" @@ -1321,21 +1481,29 @@ } }, "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", "dev": true }, "clone-deep": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.3.0.tgz", - "integrity": "sha1-NIxhrpzb4O3+BT2R/0zFIdeQ7eg=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz", + "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==", "dev": true, "requires": { "for-own": "1.0.0", "is-plain-object": "2.0.4", - "kind-of": "3.2.2", - "shallow-clone": "0.1.2" + "kind-of": "6.0.2", + "shallow-clone": "1.0.0" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } } }, "co": { @@ -1344,15 +1512,6 @@ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, - "coa": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", - "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", - "dev": true, - "requires": { - "q": "1.5.1" - } - }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -1373,15 +1532,14 @@ "sprintf-js": "1.0.3" } }, - "color": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", - "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "clone": "1.0.3", - "color-convert": "1.9.1", - "color-string": "0.3.0" + "map-visit": "1.0.0", + "object-visit": "1.0.1" } }, "color-convert": { @@ -1398,26 +1556,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "color-string": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", - "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "colormin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", - "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", - "dev": true, - "requires": { - "color": "0.11.4", - "css-color-names": "0.0.4", - "has": "1.0.1" - } - }, "colors": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", @@ -1449,9 +1587,9 @@ "dev": true }, "common-tags": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.4.0.tgz", - "integrity": "sha1-EYe+Tz1M8MBCfUP3Tu8fc1AWFMA=", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.7.2.tgz", + "integrity": "sha512-joj9ZlUOjCrwdbmiLqafeUSgkUM74NqhLsZtSqDmhKudaIY197zTrb8JMl31fMnCUuxwFT23eC/oWvrZzDLRJQ==", "dev": true, "requires": { "babel-runtime": "6.26.0" @@ -1463,6 +1601,12 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, + "compare-versions": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.1.0.tgz", + "integrity": "sha512-4hAxDSBypT/yp2ySFD346So6Ragw5xmBn/e/agIGl3bZr6DLUqnoRZPusxKrXdYRZpgexO9daejmIenlq/wrIQ==", + "dev": true + }, "component-bind": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", @@ -1482,23 +1626,31 @@ "dev": true }, "compressible": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.12.tgz", - "integrity": "sha1-xZpcmdt2dn6YdlAOJx72OzSTvWY=", + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.13.tgz", + "integrity": "sha1-DRAgq5JLL9tNYnmHXH1tq6a6p6k=", "dev": true, "requires": { - "mime-db": "1.30.0" + "mime-db": "1.33.0" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + } } }, "compression": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.1.tgz", - "integrity": "sha1-7/JgPvwuIs+G810uuTWJ+YdTc9s=", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.2.tgz", + "integrity": "sha1-qv+81qr4VLROuygDU9WtFlH1mmk=", "dev": true, "requires": { - "accepts": "1.3.4", + "accepts": "1.3.5", "bytes": "3.0.0", - "compressible": "2.0.12", + "compressible": "2.0.13", "debug": "2.6.9", "on-headers": "1.0.1", "safe-buffer": "5.1.1", @@ -1512,9 +1664,9 @@ "dev": true }, "concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.1.tgz", + "integrity": "sha512-gslSSJx03QKa59cIKqeJO9HQ/WZMotvYJCuaUULrLpjj8oG40kV2Z+gz82pVxlTkOADi4PJxQPPfhl1ELYrrXw==", "dev": true, "requires": { "inherits": "2.0.3", @@ -1591,9 +1743,9 @@ "dev": true }, "convert-source-map": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", - "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", "dev": true }, "cookie": { @@ -1622,40 +1774,32 @@ "run-queue": "1.0.3" } }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, "copy-webpack-plugin": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.2.1.tgz", - "integrity": "sha512-wZIe7EAcOrCQrZF2w6/bqloylIxeuPIope3Qt7ygJMFp4TqT0OZJoYwm/Uu36QMs9U+j6rOGrY8RupGiahE+Rg==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.4.3.tgz", + "integrity": "sha512-v4THQ24Tks2NkyOvZuFDgZVfDD9YaA9rwYLZTrWg2GHIA8lrH5DboEyeoorh5Skki+PUbgSmnsCwhMWqYrQZrA==", "dev": true, "requires": { - "bluebird": "3.5.1", - "fs-extra": "4.0.2", - "glob": "7.1.2", + "cacache": "10.0.4", + "find-cache-dir": "1.0.0", + "globby": "7.1.1", "is-glob": "4.0.0", - "loader-utils": "0.2.17", - "lodash": "4.17.4", + "loader-utils": "1.1.0", "minimatch": "3.0.4", - "node-dir": "0.1.17" - }, - "dependencies": { - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" - } - } + "p-limit": "1.2.0", + "serialize-javascript": "1.4.0" } }, "core-js": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", - "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=" + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=" }, "core-object": { "version": "3.1.5", @@ -1679,7 +1823,7 @@ "dev": true, "requires": { "is-directory": "0.3.1", - "js-yaml": "3.7.0", + "js-yaml": "3.11.0", "minimist": "1.2.0", "object-assign": "4.1.1", "os-homedir": "1.0.2", @@ -1706,7 +1850,7 @@ "cipher-base": "1.0.4", "inherits": "2.0.3", "ripemd160": "2.0.1", - "sha.js": "2.4.9" + "sha.js": "2.4.10" } }, "create-hmac": { @@ -1720,7 +1864,7 @@ "inherits": "2.0.3", "ripemd160": "2.0.1", "safe-buffer": "5.1.1", - "sha.js": "2.4.9" + "sha.js": "2.4.10" } }, "cross-spawn": { @@ -1730,16 +1874,10 @@ "dev": true, "optional": true, "requires": { - "lru-cache": "4.1.1", + "lru-cache": "4.1.2", "which": "1.3.0" } }, - "crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true - }, "cryptiles": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", @@ -1764,36 +1902,8 @@ "inherits": "2.0.3", "pbkdf2": "3.0.14", "public-encrypt": "4.0.0", - "randombytes": "2.0.5", - "randomfill": "1.0.3" - } - }, - "css-color-names": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", - "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", - "dev": true - }, - "css-loader": { - "version": "0.28.7", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.7.tgz", - "integrity": "sha512-GxMpax8a/VgcfRrVy0gXD6yLd5ePYbXX/5zGgTVYp4wXtJklS8Z2VaUArJgc//f6/Dzil7BaJObdSv8eKKCPgg==", - "dev": true, - "requires": { - "babel-code-frame": "6.26.0", - "css-selector-tokenizer": "0.7.0", - "cssnano": "3.10.0", - "icss-utils": "2.1.0", - "loader-utils": "1.1.0", - "lodash.camelcase": "4.3.0", - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-modules-extract-imports": "1.1.0", - "postcss-modules-local-by-default": "1.2.0", - "postcss-modules-scope": "1.1.0", - "postcss-modules-values": "1.3.0", - "postcss-value-parser": "3.3.0", - "source-list-map": "2.0.0" + "randombytes": "2.0.6", + "randomfill": "1.0.4" } }, "css-parse": { @@ -1846,56 +1956,6 @@ "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", "dev": true }, - "cssnano": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", - "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", - "dev": true, - "requires": { - "autoprefixer": "6.7.7", - "decamelize": "1.2.0", - "defined": "1.0.0", - "has": "1.0.1", - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-calc": "5.3.1", - "postcss-colormin": "2.2.2", - "postcss-convert-values": "2.6.1", - "postcss-discard-comments": "2.0.4", - "postcss-discard-duplicates": "2.1.0", - "postcss-discard-empty": "2.1.0", - "postcss-discard-overridden": "0.1.1", - "postcss-discard-unused": "2.2.3", - "postcss-filter-plugins": "2.0.2", - "postcss-merge-idents": "2.1.7", - "postcss-merge-longhand": "2.0.2", - "postcss-merge-rules": "2.1.2", - "postcss-minify-font-values": "1.0.5", - "postcss-minify-gradients": "1.0.5", - "postcss-minify-params": "1.2.2", - "postcss-minify-selectors": "2.1.1", - "postcss-normalize-charset": "1.1.1", - "postcss-normalize-url": "3.0.8", - "postcss-ordered-values": "2.2.3", - "postcss-reduce-idents": "2.4.0", - "postcss-reduce-initial": "1.0.1", - "postcss-reduce-transforms": "1.0.4", - "postcss-svgo": "2.1.6", - "postcss-unique-selectors": "2.0.2", - "postcss-value-parser": "3.3.0", - "postcss-zindex": "2.2.0" - } - }, - "csso": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", - "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", - "dev": true, - "requires": { - "clap": "1.2.3", - "source-map": "0.5.7" - } - }, "cuint": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", @@ -1929,7 +1989,7 @@ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { - "es5-ext": "0.10.35" + "es5-ext": "0.10.40" } }, "dashdash": { @@ -1970,6 +2030,12 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, "deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", @@ -1995,11 +2061,15 @@ "object-keys": "1.0.11" } }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + } }, "del": { "version": "3.0.0", @@ -2015,6 +2085,27 @@ "rimraf": "2.6.2" }, "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", @@ -2098,7 +2189,17 @@ "requires": { "bn.js": "4.11.8", "miller-rabin": "4.0.1", - "randombytes": "2.0.5" + "randombytes": "2.0.6" + } + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "path-type": "3.0.0" } }, "dns-equal": { @@ -2108,9 +2209,9 @@ "dev": true }, "dns-packet": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.2.2.tgz", - "integrity": "sha512-kN+DjfGF7dJGUL7nWRktL9Z18t1rWP3aQlyZdY8XlpvU3Nc6GeFTQApftcjtWKxAZfiggZSGrCEoszNgvnpwDg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", "dev": true, "requires": { "ip": "1.1.5", @@ -2174,9 +2275,9 @@ } }, "domain-browser": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, "domelementtype": { @@ -2205,12 +2306,12 @@ } }, "duplexify": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", - "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.4.tgz", + "integrity": "sha512-JzYSLYMhoVVBe8+mbHQ4KgpvHpm0DZpJuL8PY93Vyv1fW7jYJ90LoXa1di/CVbJM+TgMs91rbDapE/RNIfnJsA==", "dev": true, "requires": { - "end-of-stream": "1.4.0", + "end-of-stream": "1.4.1", "inherits": "2.0.3", "readable-stream": "2.3.3", "stream-shift": "1.0.0" @@ -2239,9 +2340,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.27", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz", - "integrity": "sha1-eOy4o5kGYYe7N07t412ccFZagD0=", + "version": "1.3.37", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.37.tgz", + "integrity": "sha1-SpJzTgBEyM8LFVO+V+riGkxuX6s=", "dev": true }, "elliptic": { @@ -2278,9 +2379,9 @@ "dev": true }, "end-of-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", - "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { "once": "1.4.0" @@ -2409,12 +2510,12 @@ "dev": true }, "errno": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", - "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", "dev": true, "requires": { - "prr": "0.0.0" + "prr": "1.0.1" } }, "error-ex": { @@ -2427,9 +2528,9 @@ } }, "es-abstract": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.9.0.tgz", - "integrity": "sha512-kk3IJoKo7A3pWJc0OV8yZ/VEX2oSUytfekrJiqoxBlKJMFAJVJVpGdHClCCTdv+Fn2zHfpDHHIelMFhZVfef3Q==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", + "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", "dev": true, "requires": { "es-to-primitive": "1.1.1", @@ -2451,9 +2552,9 @@ } }, "es5-ext": { - "version": "0.10.35", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.35.tgz", - "integrity": "sha1-GO6FjOajxFx9eekcFfzKnsVoSU8=", + "version": "0.10.40", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.40.tgz", + "integrity": "sha512-S9Fh3oya5OOvYSNGvPZJ+vyrs6VYpe1IXPowVe3N1OhaiwVaGlwfn3Zf5P5klYcWOA0toIwYQW8XEv/QqhdHvQ==", "dev": true, "requires": { "es6-iterator": "2.0.3", @@ -2467,7 +2568,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.35", + "es5-ext": "0.10.40", "es6-symbol": "3.1.1" } }, @@ -2478,7 +2579,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.35", + "es5-ext": "0.10.40", "es6-iterator": "2.0.3", "es6-set": "0.1.5", "es6-symbol": "3.1.1", @@ -2492,7 +2593,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.35", + "es5-ext": "0.10.40", "es6-iterator": "2.0.3", "es6-symbol": "3.1.1", "event-emitter": "0.3.5" @@ -2505,7 +2606,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.35" + "es5-ext": "0.10.40" } }, "es6-weak-map": { @@ -2515,7 +2616,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.35", + "es5-ext": "0.10.40", "es6-iterator": "2.0.3", "es6-symbol": "3.1.1" } @@ -2540,24 +2641,23 @@ "requires": { "es6-map": "0.1.5", "es6-weak-map": "2.0.2", - "esrecurse": "4.2.0", + "esrecurse": "4.2.1", "estraverse": "4.2.0" } }, "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", "dev": true }, "esrecurse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", - "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "estraverse": "4.2.0", - "object-assign": "4.1.1" + "estraverse": "4.2.0" } }, "estraverse": { @@ -2585,7 +2685,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.35" + "es5-ext": "0.10.40" } }, "eventemitter3": { @@ -2640,7 +2740,7 @@ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "lru-cache": "4.1.1", + "lru-cache": "4.1.2", "shebang-command": "1.2.0", "which": "1.3.0" } @@ -2715,23 +2815,13 @@ "fill-range": "2.2.3" } }, - "exports-loader": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/exports-loader/-/exports-loader-0.6.4.tgz", - "integrity": "sha1-1w/GEhl1s1/BKDDPUnVL4nQPyIY=", - "dev": true, - "requires": { - "loader-utils": "1.1.0", - "source-map": "0.5.7" - } - }, "express": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", - "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", + "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", "dev": true, "requires": { - "accepts": "1.3.4", + "accepts": "1.3.5", "array-flatten": "1.1.1", "body-parser": "1.18.2", "content-disposition": "0.5.2", @@ -2739,26 +2829,26 @@ "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "1.1.1", - "encodeurl": "1.0.1", + "depd": "1.1.2", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "etag": "1.8.1", - "finalhandler": "1.1.0", + "finalhandler": "1.1.1", "fresh": "0.5.2", "merge-descriptors": "1.0.1", "methods": "1.1.2", "on-finished": "2.3.0", "parseurl": "1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.2", + "proxy-addr": "2.0.3", "qs": "6.5.1", "range-parser": "1.2.0", "safe-buffer": "5.1.1", - "send": "0.16.1", - "serve-static": "1.13.1", + "send": "0.16.2", + "serve-static": "1.13.2", "setprototypeof": "1.1.0", - "statuses": "1.3.1", - "type-is": "1.6.15", + "statuses": "1.4.0", + "type-is": "1.6.16", "utils-merge": "1.0.1", "vary": "1.1.2" }, @@ -2769,11 +2859,54 @@ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", "dev": true }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "1.33.0" + } + }, "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", "dev": true + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "dev": true + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.18" + } } } }, @@ -2783,6 +2916,27 @@ "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", "dev": true }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, "extglob": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", @@ -2801,15 +2955,38 @@ } }, "extract-text-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.0.tgz", - "integrity": "sha1-kMqnkHvESfM1AF46x1MrQbAN5hI=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz", + "integrity": "sha512-bt/LZ4m5Rqt/Crl2HiKuAl/oqg0psx1tsTLkvWbJen1CtD+fftkZhMaQ9HOtY2gWsl2Wq+sABmMVi9z3DhKWQQ==", "dev": true, "requires": { "async": "2.6.0", "loader-utils": "1.1.0", "schema-utils": "0.3.0", - "webpack-sources": "1.0.2" + "webpack-sources": "1.1.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "5.5.2" + } + } } }, "extsprintf": { @@ -2819,9 +2996,9 @@ "dev": true }, "fast-deep-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, "fast-json-stable-stringify": { @@ -2846,13 +3023,13 @@ } }, "file-loader": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.5.tgz", - "integrity": "sha512-RzGHDatcVNpGISTvCpfUfOGpYuSR7HSsSg87ki+wF6rw1Hm0RALPTiAdsxAq1UwLf0RRhbe22/eHK6nhXspiOQ==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", + "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", "dev": true, "requires": { "loader-utils": "1.1.0", - "schema-utils": "0.3.0" + "schema-utils": "0.4.5" } }, "filename-regex": { @@ -2896,18 +3073,32 @@ } }, "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "on-finished": "2.3.0", "parseurl": "1.3.2", - "statuses": "1.3.1", + "statuses": "1.4.0", "unpipe": "1.0.0" + }, + "dependencies": { + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "dev": true + } } }, "find-cache-dir": { @@ -2917,26 +3108,19 @@ "dev": true, "requires": { "commondir": "1.0.1", - "make-dir": "1.1.0", + "make-dir": "1.2.0", "pkg-dir": "2.0.0" } }, "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" + "locate-path": "2.0.0" } }, - "flatten": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", - "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", - "dev": true - }, "flush-write-stream": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.2.tgz", @@ -2997,6 +3181,15 @@ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", "dev": true }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -3023,9 +3216,9 @@ } }, "fs-extra": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", - "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", "dev": true, "requires": { "graceful-fs": "4.1.11", @@ -3051,3557 +3244,4151 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "gaze": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", - "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=", - "dev": true, - "optional": true, - "requires": { - "globule": "1.2.0" - } - }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true, - "optional": true - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", "dev": true, "optional": true, "requires": { - "is-property": "1.0.2" - } - }, - "get-caller-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", - "dev": true - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "1.0.0" + "nan": "2.9.2", + "node-pre-gyp": "0.6.39" }, "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, "dev": true - } - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" - }, - "dependencies": { - "is-extglob": { + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "bundled": true, "dev": true }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, "dev": true, "requires": { - "is-extglob": "1.0.0" + "delayed-stream": "1.0.0" } - } - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "2.0.1" - }, - "dependencies": { - "is-extglob": { + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "bundled": true, "dev": true }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, "dev": true, + "optional": true, "requires": { - "is-extglob": "1.0.0" + "jsbn": "0.1.1" } - } - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "1.0.2", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "globule": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz", - "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=", - "dev": true, - "optional": true, - "requires": { - "glob": "7.1.2", - "lodash": "4.17.4", - "minimatch": "3.0.4" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "handle-thing": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", - "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=", - "dev": true - }, - "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", - "dev": true - }, - "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", - "dev": true, - "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, "dev": true, + "optional": true, "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" } - } - } - }, - "has": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", - "dev": true, - "requires": { - "function-bind": "1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "has-binary": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.7.tgz", - "integrity": "sha1-aOYesWIQyVRaClzOBqhzkS/h5ow=", - "dev": true, - "requires": { - "isarray": "0.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, "dev": true } } }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", - "dev": true - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, - "hash-base": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", "dev": true, "requires": { + "graceful-fs": "4.1.11", "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" - } - }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" + "mkdirp": "0.5.1", + "rimraf": "2.6.2" } }, - "he": { + "function-bind": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "requires": { - "hash.js": "1.1.3", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" } }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "gaze": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", + "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=", "dev": true, + "optional": true, "requires": { - "parse-passwd": "1.0.0" + "globule": "1.2.0" } }, - "hosted-git-info": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", - "dev": true + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true, + "optional": true }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", "dev": true, + "optional": true, "requires": { - "inherits": "2.0.3", - "obuf": "1.1.1", - "readable-stream": "2.3.3", - "wbuf": "1.7.2" + "is-property": "1.0.2" } }, - "html-comment-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz", - "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=", + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", "dev": true }, - "html-entities": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", - "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true }, - "html-minifier": { - "version": "3.5.6", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.6.tgz", - "integrity": "sha512-88FjtKrlak2XjczhxrBomgzV4jmGzM3UnHRBScRkJcmcRum0kb+IwhVAETJ8AVp7j0p3xugjSaw9L+RmI5/QOA==", - "dev": true, - "requires": { - "camel-case": "3.0.0", - "clean-css": "4.1.9", - "commander": "2.11.0", - "he": "1.1.1", - "ncname": "1.0.0", - "param-case": "2.1.1", - "relateurl": "0.2.7", - "uglify-js": "3.1.10" - } - }, - "html-webpack-plugin": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-2.30.1.tgz", - "integrity": "sha1-f5xCG36pHsRg9WUn1430hO51N9U=", - "dev": true, - "requires": { - "bluebird": "3.5.1", - "html-minifier": "3.5.6", - "loader-utils": "0.2.17", - "lodash": "4.17.4", - "pretty-error": "2.1.1", - "toposort": "1.0.6" - }, - "dependencies": { - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" - } - } - } - }, - "htmlparser2": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", - "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=", - "dev": true, - "requires": { - "domelementtype": "1.3.0", - "domhandler": "2.1.0", - "domutils": "1.1.6", - "readable-stream": "1.0.34" - }, - "dependencies": { - "domutils": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", - "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=", - "dev": true, - "requires": { - "domelementtype": "1.3.0" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, - "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "requires": { - "depd": "1.1.1", - "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": "1.3.1" + "assert-plus": "1.0.0" }, - "dependencies": { - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, - "http-parser-js": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.9.tgz", - "integrity": "sha1-6hoE+2St/wJC6ZdPKX3Uw8rSceE=", - "dev": true - }, - "http-proxy": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", - "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { - "eventemitter3": "1.2.0", - "requires-port": "1.0.0" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, - "http-proxy-middleware": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz", - "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=", + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, "requires": { - "http-proxy": "1.16.2", - "is-glob": "3.1.0", - "lodash": "4.17.4", - "micromatch": "2.3.11" + "glob-parent": "2.0.0", + "is-glob": "2.0.1" }, "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "1.0.0" } } } }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" + "is-glob": "2.0.1" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } } }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", "dev": true }, - "https-proxy-agent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", - "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", "dev": true, "requires": { - "agent-base": "2.1.1", - "debug": "2.6.9", - "extend": "3.0.1" + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "glob": "7.1.2", + "ignore": "3.3.7", + "pify": "3.0.0", + "slash": "1.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "globule": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz", + "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=", + "dev": true, + "optional": true, + "requires": { + "glob": "7.1.2", + "lodash": "4.17.4", + "minimatch": "3.0.4" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true }, - "icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", + "handle-thing": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", + "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=", "dev": true }, - "icss-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", - "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", "dev": true, "requires": { - "postcss": "6.0.14" + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" }, "dependencies": { - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true, + "optional": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "dev": true, + "optional": true, "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" } }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" + "amdefine": "1.0.1" } }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "optional": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "optional": true + } + } + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true, + "optional": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } } } }, - "ieee754": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", - "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", - "dev": true - }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, - "image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", - "dev": true, - "optional": true - }, - "import-local": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-0.1.1.tgz", - "integrity": "sha1-sReVcqrNwRxqkQCftDDbyrX2aKg=", - "dev": true, - "requires": { - "pkg-dir": "2.0.0", - "resolve-cwd": "2.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", "dev": true }, - "in-publish": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", - "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", - "dev": true, - "optional": true - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", "dev": true, "requires": { - "repeating": "2.0.1" + "ajv": "4.11.8", + "har-schema": "1.0.5" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + } } }, - "indexes-of": { + "has": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "function-bind": "1.1.1" } }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", - "dev": true - }, - "internal-ip": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-1.2.0.tgz", - "integrity": "sha1-rp+/k7mEh4eF1QqN4bNWlWBYz1w=", + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "meow": "3.7.0" + "ansi-regex": "2.1.1" } }, - "interpret": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.4.tgz", - "integrity": "sha1-ggzdWIuGj/sZGoCVBtbJyPISsbA=", - "dev": true - }, - "invariant": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", - "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "has-binary": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-binary/-/has-binary-0.1.7.tgz", + "integrity": "sha1-aOYesWIQyVRaClzOBqhzkS/h5ow=", "dev": true, "requires": { - "loose-envify": "1.3.1" + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } } }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "ipaddr.js": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", - "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=", + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", "dev": true }, - "is-absolute-url": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", - "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { - "binary-extensions": "1.11.0" + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" } }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-builtin-module": { + "has-values": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "builtin-modules": "1.1.1" + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } } }, - "is-callable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", - "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", - "dev": true - }, - "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true - }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", "dev": true, "requires": { - "is-primitive": "2.0.0" + "inherits": "2.0.3" } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" } }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" } }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "parse-passwd": "1.0.0" } }, - "is-my-json-valid": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", - "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", + "hosted-git-info": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", + "dev": true + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", "dev": true, - "optional": true, "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" + "inherits": "2.0.3", + "obuf": "1.1.2", + "readable-stream": "2.3.3", + "wbuf": "1.7.3" } }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "dev": true + }, + "html-minifier": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.10.tgz", + "integrity": "sha512-5c8iAyeIGAiuFhVjJ0qy1lgvyQxxuZgjeOuMnoK/wjEyy8DF3xKUnE9pO+6H7VMir976K6SGlZV8ZEmIOea/Zg==", "dev": true, "requires": { - "kind-of": "3.2.2" + "camel-case": "3.0.0", + "clean-css": "4.1.11", + "commander": "2.14.1", + "he": "1.1.1", + "ncname": "1.0.0", + "param-case": "2.1.1", + "relateurl": "0.2.7", + "uglify-js": "3.3.14" + }, + "dependencies": { + "commander": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", + "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==", + "dev": true + } } }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "html-webpack-plugin": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-2.30.1.tgz", + "integrity": "sha1-f5xCG36pHsRg9WUn1430hO51N9U=", "dev": true, "requires": { - "is-path-inside": "1.0.0" + "bluebird": "3.5.1", + "html-minifier": "3.5.10", + "loader-utils": "0.2.17", + "lodash": "4.17.4", + "pretty-error": "2.1.1", + "toposort": "1.0.6" + }, + "dependencies": { + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1", + "object-assign": "4.1.1" + } + } } }, - "is-path-inside": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "htmlparser2": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", + "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=", "dev": true, "requires": { - "path-is-inside": "1.0.2" + "domelementtype": "1.3.0", + "domhandler": "2.1.0", + "domutils": "1.1.6", + "readable-stream": "1.0.34" + }, + "dependencies": { + "domutils": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", + "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } } }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", "dev": true }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", "dev": true, "requires": { - "isobject": "3.0.1" + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.3.1" + }, + "dependencies": { + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "dev": true + } } }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "http-parser-js": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.11.tgz", + "integrity": "sha512-QCR5O2AjjMW8Mo4HyI1ctFcv+O99j/0g367V3YoVnrNw5hkDvAWZD0lWGcc+F4yN3V55USPCVix4efb75HxFfA==", "dev": true }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "http-proxy": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", + "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", "dev": true, - "optional": true + "requires": { + "eventemitter3": "1.2.0", + "requires-port": "1.0.0" + } }, - "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "http-proxy-middleware": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz", + "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=", "dev": true, "requires": { - "has": "1.0.1" + "http-proxy": "1.16.2", + "is-glob": "3.1.0", + "lodash": "4.17.4", + "micromatch": "2.3.11" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } } }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-svg": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", - "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", "dev": true, "requires": { - "html-comment-regex": "1.1.1" + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" } }, - "is-symbol": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", - "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", - "dev": true - }, - "is-typedarray": { + "https-browserify": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "dev": true }, - "isarray": { + "https-proxy-agent": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "dev": true, + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.9", + "extend": "3.0.1" + } }, - "isbinaryfile": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", - "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", "dev": true }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", "dev": true }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", "dev": true }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "ignore": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", "dev": true }, - "istanbul-api": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.2.1.tgz", - "integrity": "sha512-oFCwXvd65amgaPCzqrR+a2XjanS1MvpXN6l/MlMUTv6uiA1NOgGX+I0uyq8Lg3GDxsxPsaP1049krz3hIJ5+KA==", + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", "dev": true, - "requires": { - "async": "2.6.0", - "fileset": "2.0.3", - "istanbul-lib-coverage": "1.1.1", - "istanbul-lib-hook": "1.1.0", - "istanbul-lib-instrument": "1.9.1", - "istanbul-lib-report": "1.1.2", - "istanbul-lib-source-maps": "1.2.2", - "istanbul-reports": "1.1.3", - "js-yaml": "3.7.0", - "mkdirp": "0.5.1", - "once": "1.4.0" - } + "optional": true }, - "istanbul-instrumenter-loader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-2.0.0.tgz", - "integrity": "sha1-5UkpAKsLuoNe+oAkywC+mz7qJwA=", + "import-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", + "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", "dev": true, "requires": { - "convert-source-map": "1.5.0", - "istanbul-lib-instrument": "1.9.1", - "loader-utils": "0.2.17", - "object-assign": "4.1.1" - }, - "dependencies": { - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" - } - } + "pkg-dir": "2.0.0", + "resolve-cwd": "2.0.0" } }, - "istanbul-lib-coverage": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz", - "integrity": "sha512-0+1vDkmzxqJIn5rcoEqapSB4DmPxE31EtI2dF2aCkV5esN9EWHxZ0dwgDClivMXJqE7zaYQxq30hj5L0nlTN5Q==", + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, - "istanbul-lib-hook": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz", - "integrity": "sha512-U3qEgwVDUerZ0bt8cfl3dSP3S6opBoOtk3ROO5f2EfBr/SRiD9FQqzwaZBqFORu8W7O0EXpai+k7kxHK13beRg==", + "in-publish": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", + "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", "dev": true, - "requires": { - "append-transform": "0.4.0" - } + "optional": true }, - "istanbul-lib-instrument": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.1.tgz", - "integrity": "sha512-RQmXeQ7sphar7k7O1wTNzVczF9igKpaeGQAG9qR2L+BS4DCJNTI9nytRmIVYevwO0bbq+2CXvJmYDuz0gMrywA==", + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, "requires": { - "babel-generator": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "istanbul-lib-coverage": "1.1.1", - "semver": "5.4.1" + "repeating": "2.0.1" } }, - "istanbul-lib-report": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.2.tgz", - "integrity": "sha512-UTv4VGx+HZivJQwAo1wnRwe1KTvFpfi/NYwN7DcsrdzMXwpRT/Yb6r4SBPoHWj4VuQPakR32g4PUUeyKkdDkBA==", + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "istanbul-lib-coverage": "1.1.1", - "mkdirp": "0.5.1", - "path-parse": "1.0.5", - "supports-color": "3.2.3" - }, - "dependencies": { - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "1.0.0" - } - } + "once": "1.4.0", + "wrappy": "1.0.2" } }, - "istanbul-lib-source-maps": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.2.tgz", - "integrity": "sha512-8BfdqSfEdtip7/wo1RnrvLpHVEd8zMZEDmOFEnpC6dg0vXflHt9nvoAyQUzig2uMSXfF2OBEYBV3CVjIL9JvaQ==", + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, + "internal-ip": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-1.2.0.tgz", + "integrity": "sha1-rp+/k7mEh4eF1QqN4bNWlWBYz1w=", "dev": true, "requires": { - "debug": "3.1.0", - "istanbul-lib-coverage": "1.1.1", - "mkdirp": "0.5.1", - "rimraf": "2.6.2", - "source-map": "0.5.7" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } + "meow": "3.7.0" } }, - "istanbul-reports": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.1.3.tgz", - "integrity": "sha512-ZEelkHh8hrZNI5xDaKwPMFwDsUf5wIEI2bXAFGp1e6deR2mnEKBPhLJEgr4ZBt8Gi6Mj38E/C8kcy9XLggVO2Q==", + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "dev": true, "requires": { - "handlebars": "4.0.11" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true, - "optional": true - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "optional": true, - "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true, - "optional": true - } - } - }, - "handlebars": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", - "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", - "dev": true, - "requires": { - "async": "1.5.2", - "optimist": "0.6.1", - "source-map": "0.4.4", - "uglify-js": "2.8.29" - } - }, - "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", - "dev": true - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "0.0.10", - "wordwrap": "0.0.3" - } - }, - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, - "optional": true, - "requires": { - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "optional": true - } - } - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "optional": true, - "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", - "window-size": "0.1.0" - } - } + "loose-envify": "1.3.1" } }, - "jasmine": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", - "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ipaddr.js": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", + "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "exit": "0.1.2", - "glob": "7.1.2", - "jasmine-core": "2.8.0" + "kind-of": "6.0.2" }, "dependencies": { - "jasmine-core": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", - "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } }, - "jasmine-core": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.6.4.tgz", - "integrity": "sha1-3skmzQqfoof7bbXHVfpIfnTOysU=", + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, - "jasmine-spec-reporter": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.1.1.tgz", - "integrity": "sha1-Wm1Yq11hvqcwn7wnkjlRF1axtYg=", + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "requires": { - "colors": "1.1.2" + "binary-extensions": "1.11.0" } }, - "jasminewd2": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", - "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=", + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, - "jquery": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz", - "integrity": "sha1-XE2d5lKvbNCncBVKYxu6ErAVx4c=" - }, - "js-base64": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.3.2.tgz", - "integrity": "sha512-Y2/+DnfJJXT1/FCwUebUhLWb3QihxiSC42+ctHLGogmW2jPY6LCapMdFZXRvVP2z6qyKW7s6qncE/9gSqZiArw==", - "dev": true + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", "dev": true }, - "js-yaml": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", - "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "argparse": "1.0.9", - "esprima": "2.7.3" + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true - }, - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", "dev": true }, - "json-loader": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", - "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==", - "dev": true + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", "dev": true }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", "dev": true }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, "requires": { - "jsonify": "0.0.0" + "is-primitive": "2.0.0" } }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", "dev": true }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "graceful-fs": "4.1.11" + "number-is-nan": "1.0.1" } }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", "dev": true, "optional": true }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "is-my-json-valid": { + "version": "2.17.2", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", + "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", "dev": true, + "optional": true, "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "is-my-ip-valid": "1.0.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" } }, - "karma": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/karma/-/karma-1.7.1.tgz", - "integrity": "sha512-k5pBjHDhmkdaUccnC7gE3mBzZjcxyxYsYVaqiL2G5AqlfLyBO5nw2VdNK+O16cveEPd/gIOWULH7gkiYYwVNHg==", + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, "requires": { - "bluebird": "3.5.1", - "body-parser": "1.18.2", - "chokidar": "1.7.0", - "colors": "1.1.2", - "combine-lists": "1.0.1", - "connect": "3.6.5", - "core-js": "2.5.1", - "di": "0.0.1", - "dom-serialize": "2.2.1", - "expand-braces": "0.1.2", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "http-proxy": "1.16.2", - "isbinaryfile": "3.0.2", - "lodash": "3.10.1", - "log4js": "0.6.38", - "mime": "1.4.1", - "minimatch": "3.0.4", - "optimist": "0.6.1", - "qjobs": "1.1.5", - "range-parser": "1.2.0", - "rimraf": "2.6.2", - "safe-buffer": "5.1.1", - "socket.io": "1.7.3", - "source-map": "0.5.7", - "tmp": "0.0.31", - "useragent": "2.2.1" + "kind-of": "3.2.2" + } + }, + "is-odd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", + "dev": true, + "requires": { + "is-number": "4.0.0" }, "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - }, - "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", "dev": true - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "0.0.10", - "wordwrap": "0.0.3" - } } } }, - "karma-chrome-launcher": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.1.1.tgz", - "integrity": "sha1-IWh5xorATY1RQOmWGboEtZr9Rs8=", + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", "dev": true, "requires": { - "fs-access": "1.0.1", - "which": "1.3.0" + "is-path-inside": "1.0.0" } }, - "karma-cli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/karma-cli/-/karma-cli-1.0.1.tgz", - "integrity": "sha1-rmw8WKMTodALRRZMRVubhs4X+WA=", + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", "dev": true, "requires": { - "resolve": "1.5.0" + "path-is-inside": "1.0.2" } }, - "karma-coverage-istanbul-reporter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.3.0.tgz", - "integrity": "sha1-0ULNnFVzHJ42Pvc3To7xoxvr+ts=", + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { - "istanbul-api": "1.2.1", - "minimatch": "3.0.4" + "isobject": "3.0.1" } }, - "karma-jasmine": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-1.1.0.tgz", - "integrity": "sha1-IuTAa/mhguUpTR9wXjczgRuBCs8=", + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", "dev": true }, - "karma-jasmine-html-reporter": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-0.2.2.tgz", - "integrity": "sha1-SKjl7xiAdhfuK14zwRlMNbQ5Ukw=", + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", "dev": true, - "requires": { - "karma-jasmine": "1.1.0" - } + "optional": true }, - "karma-source-map-support": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.2.0.tgz", - "integrity": "sha1-G/gee7SwiWJ6s1LsQXnhF8QGpUA=", + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "dev": true, "requires": { - "source-map-support": "0.4.18" + "has": "1.0.1" } }, - "killable": { + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, + "is-typedarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz", - "integrity": "sha1-2ouEvUfeU5WHj5XWTQLyRJ/gXms=", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true }, - "lazy-cache": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", - "integrity": "sha1-f+3fLctu23fRHvHRF6tf/fCrG2U=", + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, - "lcid": { + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "1.0.0" - } + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true }, - "less": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/less/-/less-2.7.3.tgz", - "integrity": "sha512-KPdIJKWcEAb02TuJtaLrhue0krtRLoRoo7x6BNJIBelO00t/CCdJQUnHW5V34OnHMWzIktSalJxRO+FvytQlCQ==", + "isbinaryfile": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", + "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul-api": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.1.tgz", + "integrity": "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g==", "dev": true, "requires": { - "errno": "0.1.4", - "graceful-fs": "4.1.11", - "image-size": "0.5.5", - "mime": "1.4.1", + "async": "2.6.0", + "compare-versions": "3.1.0", + "fileset": "2.0.3", + "istanbul-lib-coverage": "1.2.0", + "istanbul-lib-hook": "1.2.0", + "istanbul-lib-instrument": "1.10.1", + "istanbul-lib-report": "1.1.4", + "istanbul-lib-source-maps": "1.2.4", + "istanbul-reports": "1.3.0", + "js-yaml": "3.11.0", "mkdirp": "0.5.1", - "promise": "7.3.1", - "request": "2.81.0", - "source-map": "0.5.7" + "once": "1.4.0" } }, - "less-loader": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-4.0.5.tgz", - "integrity": "sha1-rhVadAbKxqzSk9eFWH/P8PR4xN0=", + "istanbul-instrumenter-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.0.tgz", + "integrity": "sha512-alLSEFX06ApU75sm5oWcaVNaiss/bgMRiWTct3g0P0ZZTKjR+6QiCcuVOKDI1kWJgwHEnIXsv/dWm783kPpmtw==", "dev": true, "requires": { - "clone": "2.1.1", + "convert-source-map": "1.5.1", + "istanbul-lib-instrument": "1.10.1", "loader-utils": "1.1.0", - "pify": "2.3.0" + "schema-utils": "0.3.0" }, "dependencies": { - "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", - "dev": true + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "5.5.2" + } } } }, - "license-webpack-plugin": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-1.1.1.tgz", - "integrity": "sha512-TjKOyiC0exqd4Idy/4M8/DETR22dXBZks387DuS5LbslxHiMRXGx/Q2F/j9IUtvEoH5uFvt72vRgk/G6f8j3Dg==", + "istanbul-lib-coverage": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", + "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.0.tgz", + "integrity": "sha512-p3En6/oGkFQV55Up8ZPC2oLxvgSxD8CzA0yBrhRZSh3pfv3OFj9aSGVC0yoerAi/O4u7jUVnOGVX1eVFM+0tmQ==", "dev": true, "requires": { - "ejs": "2.5.7" + "append-transform": "0.4.0" } }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "istanbul-lib-instrument": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz", + "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" + "babel-generator": "6.26.1", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "istanbul-lib-coverage": "1.2.0", + "semver": "5.4.1" + } + }, + "istanbul-lib-report": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz", + "integrity": "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "1.2.0", + "mkdirp": "0.5.1", + "path-parse": "1.0.5", + "supports-color": "3.2.3" + }, + "dependencies": { + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.4.tgz", + "integrity": "sha512-UzuK0g1wyQijiaYQxj/CdNycFhAd2TLtO2obKQMTZrZ1jzEMRY3rvpASEKkaxbRR6brvdovfA03znPa/pXcejg==", + "dev": true, + "requires": { + "debug": "3.1.0", + "istanbul-lib-coverage": "1.2.0", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "source-map": "0.5.7" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } } }, - "loader-runner": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", - "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", - "dev": true - }, - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "istanbul-reports": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.3.0.tgz", + "integrity": "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA==", "dev": true, "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1" + "handlebars": "4.0.11" } }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "jasmine": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", + "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", "dev": true, "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" + "exit": "0.1.2", + "glob": "7.1.2", + "jasmine-core": "2.8.0" }, "dependencies": { - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "jasmine-core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", + "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", "dev": true } } }, - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "jasmine-core": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.6.4.tgz", + "integrity": "sha1-3skmzQqfoof7bbXHVfpIfnTOysU=", "dev": true }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", + "jasmine-spec-reporter": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.1.1.tgz", + "integrity": "sha1-Wm1Yq11hvqcwn7wnkjlRF1axtYg=", "dev": true, - "optional": true - }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", - "dev": true + "requires": { + "colors": "1.1.2" + } }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "jasminewd2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", + "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=", "dev": true }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true + "jquery": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", + "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==" }, - "lodash.mergewith": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz", - "integrity": "sha1-FQzwoWeR9ZA7iJHqsVRgknS96lU=", + "js-base64": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz", + "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw==", "dev": true, "optional": true }, - "lodash.tail": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", - "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", - "dev": true - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", "dev": true }, - "log4js": { - "version": "0.6.38", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-0.6.38.tgz", - "integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=", + "js-yaml": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", + "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", "dev": true, "requires": { - "readable-stream": "1.0.34", - "semver": "4.3.6" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } + "argparse": "1.0.10", + "esprima": "4.0.0" } }, - "loglevel": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.0.tgz", - "integrity": "sha1-rgyqVhERSYxboTcj1vtjHSQAOTQ=", - "dev": true + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true }, - "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "dev": true, - "requires": { - "js-tokens": "3.0.2" - } + "json-loader": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", + "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==", + "dev": true }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "0.4.1", - "signal-exit": "3.0.2" - } + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true }, - "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", "dev": true }, - "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "jsonify": "0.0.0" } }, - "macaddress": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", - "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=", + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, - "magic-string": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.4.tgz", - "integrity": "sha512-kxBL06p6iO2qPBHsqGK2b3cRwiRGpnmSuVWNhwHcMX7qJOUr1HvricYP1LZOCdkQBUp0jiWg2d6WJwR3vYgByw==", - "dev": true, - "requires": { - "vlq": "0.2.3" - } + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true }, - "make-dir": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", - "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, "requires": { - "pify": "3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } + "graceful-fs": "4.1.11" } }, - "make-error": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.0.tgz", - "integrity": "sha1-Uq06M5zPEM5itAQLcI/nByRLi5Y=", - "dev": true - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true }, - "math-expression-evaluator": { - "version": "1.2.17", - "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", - "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", - "dev": true + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true, + "optional": true }, - "md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", "dev": true, "requires": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "1.1.6" + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } } }, - "md5.js": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", - "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "karma": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/karma/-/karma-1.7.1.tgz", + "integrity": "sha512-k5pBjHDhmkdaUccnC7gE3mBzZjcxyxYsYVaqiL2G5AqlfLyBO5nw2VdNK+O16cveEPd/gIOWULH7gkiYYwVNHg==", "dev": true, "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.3" + "bluebird": "3.5.1", + "body-parser": "1.18.2", + "chokidar": "1.7.0", + "colors": "1.1.2", + "combine-lists": "1.0.1", + "connect": "3.6.5", + "core-js": "2.5.3", + "di": "0.0.1", + "dom-serialize": "2.2.1", + "expand-braces": "0.1.2", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "http-proxy": "1.16.2", + "isbinaryfile": "3.0.2", + "lodash": "3.10.1", + "log4js": "0.6.38", + "mime": "1.4.1", + "minimatch": "3.0.4", + "optimist": "0.6.1", + "qjobs": "1.1.5", + "range-parser": "1.2.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.1", + "socket.io": "1.7.3", + "source-map": "0.5.7", + "tmp": "0.0.31", + "useragent": "2.2.1" }, "dependencies": { - "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + }, + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" + "minimist": "0.0.10", + "wordwrap": "0.0.3" } } } }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "karma-chrome-launcher": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.1.1.tgz", + "integrity": "sha1-IWh5xorATY1RQOmWGboEtZr9Rs8=", "dev": true, "requires": { - "mimic-fn": "1.1.0" + "fs-access": "1.0.1", + "which": "1.3.0" } }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "karma-cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/karma-cli/-/karma-cli-1.0.1.tgz", + "integrity": "sha1-rmw8WKMTodALRRZMRVubhs4X+WA=", "dev": true, "requires": { - "errno": "0.1.4", - "readable-stream": "2.3.3" + "resolve": "1.5.0" } }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "karma-coverage-istanbul-reporter": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.2.tgz", + "integrity": "sha512-sQHexslLF+QHzaKfK8+onTYMyvSwv+p5cDayVxhpEELGa3z0QuB+l0IMsicIkkBNMOJKQaqueiRoW7iuo7lsog==", "dev": true, "requires": { - "camelcase-keys": "2.1.0", - "decamelize": "1.2.0", - "loud-rejection": "1.6.0", - "map-obj": "1.0.1", - "minimist": "1.2.0", - "normalize-package-data": "2.4.0", - "object-assign": "4.1.1", - "read-pkg-up": "1.0.1", - "redent": "1.0.0", - "trim-newlines": "1.0.0" + "istanbul-api": "1.3.1", + "minimatch": "3.0.4" } }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "karma-jasmine": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-1.1.1.tgz", + "integrity": "sha1-b+hA51oRYAydkehLM8RY4cRqNSk=", "dev": true }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "karma-jasmine-html-reporter": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-0.2.2.tgz", + "integrity": "sha1-SKjl7xiAdhfuK14zwRlMNbQ5Ukw=", "dev": true, "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - } + "karma-jasmine": "1.1.1" } }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "karma-source-map-support": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.2.0.tgz", + "integrity": "sha1-G/gee7SwiWJ6s1LsQXnhF8QGpUA=", "dev": true, "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0" + "source-map-support": "0.4.18" } }, - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true - }, - "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "killable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz", + "integrity": "sha1-2ouEvUfeU5WHj5XWTQLyRJ/gXms=", "dev": true }, - "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "mime-db": "1.30.0" + "is-buffer": "1.1.6" } }, - "mimic-fn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", - "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", "dev": true }, - "minimalistic-assert": { + "lcid": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", - "dev": true - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { - "brace-expansion": "1.1.8" + "invert-kv": "1.0.0" } }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "mississippi": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-1.3.0.tgz", - "integrity": "sha1-0gFYPrEjJ+PFwWQqQEqcrPlONPU=", + "less": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/less/-/less-2.7.3.tgz", + "integrity": "sha512-KPdIJKWcEAb02TuJtaLrhue0krtRLoRoo7x6BNJIBelO00t/CCdJQUnHW5V34OnHMWzIktSalJxRO+FvytQlCQ==", "dev": true, "requires": { - "concat-stream": "1.6.0", - "duplexify": "3.5.1", - "end-of-stream": "1.4.0", - "flush-write-stream": "1.0.2", - "from2": "2.3.0", - "parallel-transform": "1.1.0", - "pump": "1.0.3", - "pumpify": "1.3.5", - "stream-each": "1.2.2", - "through2": "2.0.3" + "errno": "0.1.7", + "graceful-fs": "4.1.11", + "image-size": "0.5.5", + "mime": "1.4.1", + "mkdirp": "0.5.1", + "promise": "7.3.1", + "request": "2.81.0", + "source-map": "0.5.7" } }, - "mixin-object": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", - "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", + "less-loader": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-4.1.0.tgz", + "integrity": "sha512-KNTsgCE9tMOM70+ddxp9yyt9iHqgmSs0yTZc5XH5Wo+g80RWRIYNqE58QJKm/yMud5wZEvz50ugRDuzVIkyahg==", "dev": true, "requires": { - "for-in": "0.1.8", - "is-extendable": "0.1.1" + "clone": "2.1.1", + "loader-utils": "1.1.0", + "pify": "3.0.0" }, "dependencies": { - "for-in": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", - "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true } } }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "license-webpack-plugin": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-1.3.0.tgz", + "integrity": "sha512-12Spl8M5Ty7aRszGQUEfNK1W0gwcWNfAj0sMyJv7E7BglAb4YaZ6FciGncmwzxEcuzJ45RjA/Fql3Gw13la6aA==", "dev": true, "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } + "ejs": "2.5.7" } }, - "moment": { - "version": "2.18.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", - "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=" - }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { - "aproba": "1.2.0", - "copy-concurrently": "1.0.5", - "fs-write-stream-atomic": "1.0.10", - "mkdirp": "0.5.1", - "rimraf": "2.6.2", - "run-queue": "1.0.3" + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "loader-runner": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", "dev": true }, - "multicast-dns": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.0.tgz", - "integrity": "sha512-tnQqWkuWYHCOVRveiWQf+5KjHUnEmtxUycTy1esL4prQjXoT4qpndIS4fH63zObmHNxIHke3YHRnQrXYpXHf2A==", + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", "dev": true, "requires": { - "dns-packet": "1.2.2", - "thunky": "0.1.0" + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1" } }, - "multicast-dns-service-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", "dev": true }, - "nan": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", - "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", "dev": true, "optional": true }, - "ncname": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ncname/-/ncname-1.0.0.tgz", - "integrity": "sha1-W1etGLHKCShk72Kwse2BlPODtxw=", + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.mergewith": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", + "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", + "dev": true, + "optional": true + }, + "lodash.tail": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", + "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", + "dev": true + }, + "log4js": { + "version": "0.6.38", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-0.6.38.tgz", + "integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=", "dev": true, "requires": { - "xml-char-classes": "1.0.0" + "readable-stream": "1.0.34", + "semver": "4.3.6" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } } }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "loglevel": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz", + "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=", "dev": true }, - "ng2-charts": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-1.6.0.tgz", - "integrity": "sha512-9w0WH69x5/nuqC1og2WaY39NbaBqTGIP1+5gZaH7/KPN6UEPonNg/pYnsIVklLj1DWPWXKa8+XXIJZ1jy5nLxg==", + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, "requires": { - "chart.js": "2.7.1" + "js-tokens": "3.0.2" } }, - "ngx-bootstrap": { - "version": "2.0.0-beta.8", - "resolved": "https://registry.npmjs.org/ngx-bootstrap/-/ngx-bootstrap-2.0.0-beta.8.tgz", - "integrity": "sha512-e+3euXDb4nhzxn9kBO4RPWwRaI2ef7Lg+us8Yo2DBfD/Kuk/vl7ksWjoolMFLKEGpcTcKhMT/4BH5dUx+S4AtA==" + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } }, - "ngx-cookie": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ngx-cookie/-/ngx-cookie-1.0.1.tgz", - "integrity": "sha512-zE0HTC0jU/C7+33/eO3qZJUtkbGY2mKuVLXR/jpH11rOD7u7BU+zy9i2D0vf8vaxZaW+TlfUD1jGOCuIYWvv+g==" + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true }, - "ngx-webstorage": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ngx-webstorage/-/ngx-webstorage-2.0.0.tgz", - "integrity": "sha512-l+v0EHDXUro/9ZNv3jYRmDbhh1yuA8gWqlm9U2udzK/hnoQZV3sBqhGSgng1rtM2XuCsWLQPdb+suHbsTxn0WQ==" + "lru-cache": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", + "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } }, - "no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "magic-string": { + "version": "0.22.4", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.4.tgz", + "integrity": "sha512-kxBL06p6iO2qPBHsqGK2b3cRwiRGpnmSuVWNhwHcMX7qJOUr1HvricYP1LZOCdkQBUp0jiWg2d6WJwR3vYgByw==", "dev": true, "requires": { - "lower-case": "1.1.4" + "vlq": "0.2.3" } }, - "node-dir": { - "version": "0.1.17", - "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", - "integrity": "sha1-X1Zl2TNRM1yqvvjxxVRRbPXx5OU=", + "make-dir": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", + "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", "dev": true, "requires": { - "minimatch": "3.0.4" + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, - "node-forge": { - "version": "0.6.33", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.6.33.tgz", - "integrity": "sha1-RjgRh59XPUUVWtap9D3ClujoXrw=", + "make-error": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.0.tgz", + "integrity": "sha1-Uq06M5zPEM5itAQLcI/nByRLi5Y=", "dev": true }, - "node-gyp": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz", - "integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=", + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", "dev": true, - "optional": true, "requires": { - "fstream": "1.0.11", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "npmlog": "4.1.2", - "osenv": "0.1.4", - "request": "2.81.0", - "rimraf": "2.6.2", - "semver": "5.3.0", - "tar": "2.2.1", - "which": "1.3.0" + "hash-base": "3.0.4", + "inherits": "2.0.3" }, "dependencies": { - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "dev": true, - "optional": true, "requires": { - "abbrev": "1.1.1" + "inherits": "2.0.3", + "safe-buffer": "5.1.1" } - }, - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true, - "optional": true } } }, - "node-libs-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "dev": true, "requires": { - "assert": "1.4.1", - "browserify-zlib": "0.2.0", - "buffer": "4.9.1", - "console-browserify": "1.1.0", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.12.0", - "domain-browser": "1.1.7", - "events": "1.1.1", - "https-browserify": "1.0.0", - "os-browserify": "0.3.0", - "path-browserify": "0.0.0", - "process": "0.11.10", - "punycode": "1.4.1", - "querystring-es3": "0.2.1", - "readable-stream": "2.3.3", - "stream-browserify": "2.0.1", - "stream-http": "2.7.2", - "string_decoder": "1.0.3", - "timers-browserify": "2.0.4", - "tty-browserify": "0.0.0", - "url": "0.11.0", - "util": "0.10.3", - "vm-browserify": "0.0.4" + "mimic-fn": "1.2.0" } }, - "node-modules-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/node-modules-path/-/node-modules-path-1.0.1.tgz", - "integrity": "sha1-QAlrCM560OoUaAhjr0ScfHWl0cg=", - "dev": true - }, - "node-sass": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.7.2.tgz", - "integrity": "sha512-CaV+wLqZ7//Jdom5aUFCpGNoECd7BbNhjuwdsX/LkXBrHl8eb1Wjw4HvWqcFvhr5KuNgAk8i/myf/MQ1YYeroA==", + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", "dev": true, - "optional": true, "requires": { - "async-foreach": "0.1.3", - "chalk": "1.1.3", - "cross-spawn": "3.0.1", - "gaze": "1.1.2", - "get-stdin": "4.0.1", - "glob": "7.1.2", - "in-publish": "2.0.0", - "lodash.assign": "4.2.0", - "lodash.clonedeep": "4.5.0", - "lodash.mergewith": "4.6.0", - "meow": "3.7.0", - "mkdirp": "0.5.1", - "nan": "2.8.0", - "node-gyp": "3.6.2", - "npmlog": "4.1.2", - "request": "2.79.0", - "sass-graph": "2.2.4", - "stdout-stream": "1.4.0", - "true-case-path": "1.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true, - "optional": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true, - "optional": true, - "requires": { - "chalk": "1.1.3", - "commander": "2.11.0", - "is-my-json-valid": "2.16.1", - "pinkie-promise": "2.0.1" - } - }, - "qs": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", - "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", - "dev": true, - "optional": true - }, - "request": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", - "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", - "dev": true, - "optional": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.11.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "qs": "6.3.2", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", - "tunnel-agent": "0.4.3", - "uuid": "3.1.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true, - "optional": true - } + "errno": "0.1.7", + "readable-stream": "2.3.3" } }, - "nopt": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.4" + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" } }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "hosted-git-info": "2.5.0", - "is-builtin-module": "1.0.0", - "semver": "5.4.1", - "validate-npm-package-license": "3.0.1" + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } } }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "dev": true, "requires": { - "remove-trailing-separator": "1.1.0" + "bn.js": "4.11.8", + "brorand": "1.1.0" } }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", "dev": true }, - "normalize-url": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", - "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dev": true, - "requires": { - "object-assign": "4.1.1", - "prepend-http": "1.0.4", - "query-string": "4.3.4", - "sort-keys": "1.1.2" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "2.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "dev": true }, - "nth-check": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", - "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", "dev": true, "requires": { - "boolbase": "1.0.0" + "mime-db": "1.30.0" } }, - "null-check": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", - "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", "dev": true }, - "number-is-nan": { + "minimalistic-crypto-utils": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", "dev": true }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, - "object-keys": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", - "dev": true + "mississippi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", + "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "dev": true, + "requires": { + "concat-stream": "1.6.1", + "duplexify": "3.5.4", + "end-of-stream": "1.4.1", + "flush-write-stream": "1.0.2", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "2.0.1", + "pumpify": "1.4.0", + "stream-each": "1.2.2", + "through2": "2.0.3" + } }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" + "for-in": "1.0.2", + "is-extendable": "1.0.1" }, "dependencies": { - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "for-in": "1.0.2" + "is-plain-object": "2.0.4" } } } }, - "obuf": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz", - "integrity": "sha1-EEEktsYCxnlogaBCVB0220OlJk4=", - "dev": true - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "mixin-object": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", + "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", "dev": true, "requires": { - "ee-first": "1.1.1" + "for-in": "0.1.8", + "is-extendable": "0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", + "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", + "dev": true + } } }, - "on-headers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { - "wrappy": "1.0.2" + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } } }, - "opn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.1.0.tgz", - "integrity": "sha512-iPNl7SyM8L30Rm1sjGdLLheyHVw5YXVfi3SKWJzBI7efxRwHojfRFjwE/OLM6qp9xJYMgab8WicTU1cPoY+Hpg==", + "moment": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", + "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=" + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", "dev": true, "requires": { - "is-wsl": "1.1.0" + "aproba": "1.2.0", + "copy-concurrently": "1.0.5", + "fs-write-stream-atomic": "1.0.10", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" } }, - "options": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", - "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=", + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "original": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz", - "integrity": "sha1-kUf5P6FpbQS+YeAb1QuurKZWvTs=", + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", "dev": true, "requires": { - "url-parse": "1.0.5" - }, - "dependencies": { - "url-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.0.5.tgz", - "integrity": "sha1-CFSGBCKv3P7+tsllxmLUgAFpkns=", - "dev": true, - "requires": { - "querystringify": "0.0.4", - "requires-port": "1.0.0" - } - } + "dns-packet": "1.3.1", + "thunky": "1.0.2" } }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", "dev": true }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "nan": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.9.2.tgz", + "integrity": "sha512-ltW65co7f3PQWBDbqVvaU1WtFJUsNW7sWWm4HINhbMQIyVyzIeyZ8toX5TC5eeooE6piZoaEh4cZkueSKG3KYw==", "dev": true, - "requires": { - "lcid": "1.0.0" + "optional": true + }, + "nanomatch": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } } }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", - "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "ncname": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ncname/-/ncname-1.0.0.tgz", + "integrity": "sha1-W1etGLHKCShk72Kwse2BlPODtxw=", "dev": true, "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "xml-char-classes": "1.0.0" } }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", "dev": true }, - "p-limit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", - "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", + "neo-async": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.0.tgz", + "integrity": "sha512-nJmSswG4As/MkRq7QZFuH/sf/yuv8ODdMZrY4Bedjp77a5MK4A6s7YbBB64c9u79EBUOfXUXBvArmvzTD0X+6g==", "dev": true }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, + "ng2-charts": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-1.6.0.tgz", + "integrity": "sha512-9w0WH69x5/nuqC1og2WaY39NbaBqTGIP1+5gZaH7/KPN6UEPonNg/pYnsIVklLj1DWPWXKa8+XXIJZ1jy5nLxg==", "requires": { - "p-limit": "1.1.0" + "chart.js": "2.7.2" } }, - "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", - "dev": true + "ngx-bootstrap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ngx-bootstrap/-/ngx-bootstrap-2.0.3.tgz", + "integrity": "sha512-SdtOQeQrT2BW5mUbzotZF8S55QaAYOBT7orrl2Pi/U5mCVH4U7YJIaN7yNzMfjGsYINmBOSY8Zi1MBUC1UzbWg==" }, - "pako": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", - "dev": true + "ngx-cookie": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ngx-cookie/-/ngx-cookie-1.0.1.tgz", + "integrity": "sha512-zE0HTC0jU/C7+33/eO3qZJUtkbGY2mKuVLXR/jpH11rOD7u7BU+zy9i2D0vf8vaxZaW+TlfUD1jGOCuIYWvv+g==" }, - "parallel-transform": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "ngx-webstorage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ngx-webstorage/-/ngx-webstorage-2.0.1.tgz", + "integrity": "sha512-AhBkl1v5sBLYiGC1DuHxM90B8OewqyhYhm+KGtJIFxMh5dj3tlNgPokmWCtKcUZF26m8MgxDDuP5e6NeDCpYQw==" + }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", "dev": true, "requires": { - "cyclist": "0.2.2", - "inherits": "2.0.3", - "readable-stream": "2.3.3" + "lower-case": "1.1.4" } }, - "param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "node-forge": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.1.tgz", + "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=", + "dev": true + }, + "node-gyp": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz", + "integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=", "dev": true, + "optional": true, "requires": { - "no-case": "2.3.2" + "fstream": "1.0.11", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "npmlog": "4.1.2", + "osenv": "0.1.5", + "request": "2.81.0", + "rimraf": "2.6.2", + "semver": "5.3.0", + "tar": "2.2.1", + "which": "1.3.0" + }, + "dependencies": { + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.1" + } + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true, + "optional": true + } } }, - "parse-asn1": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", - "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", "dev": true, "requires": { - "asn1.js": "4.9.2", - "browserify-aes": "1.1.1", - "create-hash": "1.1.3", - "evp_bytestokey": "1.0.3", - "pbkdf2": "3.0.14" + "assert": "1.4.1", + "browserify-zlib": "0.2.0", + "buffer": "4.9.1", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "domain-browser": "1.2.0", + "events": "1.1.1", + "https-browserify": "1.0.0", + "os-browserify": "0.3.0", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "readable-stream": "2.3.3", + "stream-browserify": "2.0.1", + "stream-http": "2.8.0", + "string_decoder": "1.0.3", + "timers-browserify": "2.0.6", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4" } }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "node-modules-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/node-modules-path/-/node-modules-path-1.0.1.tgz", + "integrity": "sha1-QAlrCM560OoUaAhjr0ScfHWl0cg=", + "dev": true + }, + "node-sass": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.7.2.tgz", + "integrity": "sha512-CaV+wLqZ7//Jdom5aUFCpGNoECd7BbNhjuwdsX/LkXBrHl8eb1Wjw4HvWqcFvhr5KuNgAk8i/myf/MQ1YYeroA==", "dev": true, + "optional": true, "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" + "async-foreach": "0.1.3", + "chalk": "1.1.3", + "cross-spawn": "3.0.1", + "gaze": "1.1.2", + "get-stdin": "4.0.1", + "glob": "7.1.2", + "in-publish": "2.0.0", + "lodash.assign": "4.2.0", + "lodash.clonedeep": "4.5.0", + "lodash.mergewith": "4.6.1", + "meow": "3.7.0", + "mkdirp": "0.5.1", + "nan": "2.9.2", + "node-gyp": "3.6.2", + "npmlog": "4.1.2", + "request": "2.79.0", + "sass-graph": "2.2.4", + "stdout-stream": "1.4.0", + "true-case-path": "1.0.2" }, "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true, + "optional": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "optional": true, + "requires": { + "chalk": "1.1.3", + "commander": "2.11.0", + "is-my-json-valid": "2.17.2", + "pinkie-promise": "2.0.1" + } + }, + "qs": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "dev": true, + "optional": true + }, + "request": { + "version": "2.79.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.11.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "qs": "6.3.2", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.4.3", + "uuid": "3.1.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", "dev": true, - "requires": { - "is-extglob": "1.0.0" - } + "optional": true } } }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "requires": { - "error-ex": "1.3.1" + "abbrev": "1.1.1", + "osenv": "0.1.5" } }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parsejson": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.3.tgz", - "integrity": "sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs=", + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { - "better-assert": "1.0.2" + "hosted-git-info": "2.6.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.3" } }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "better-assert": "1.0.2" + "remove-trailing-separator": "1.1.0" } }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { - "better-assert": "1.0.2" + "path-key": "2.0.1" } }, - "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", - "dev": true - }, - "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", - "dev": true - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "requires": { - "pinkie-promise": "2.0.1" + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" } }, - "path-is-absolute": { + "nth-check": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", + "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "dev": true, + "requires": { + "boolbase": "1.0.0" + } }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "null-check": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", + "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", "dev": true }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", "dev": true }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "pbkdf2": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", - "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", - "dev": true, - "requires": { - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "ripemd160": "2.0.1", - "safe-buffer": "5.1.1", - "sha.js": "2.4.9" - } - }, - "performance-now": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", "dev": true }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", "dev": true }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "2.0.4" - } - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "find-up": "2.1.0" + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" }, "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "locate-path": "2.0.0" + "is-descriptor": "0.1.6" } - } - } - }, - "portfinder": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz", - "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=", - "dev": true, - "requires": { - "async": "1.5.2", - "debug": "2.6.9", - "mkdirp": "0.5.1" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - } - } - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "1.1.3", - "js-base64": "2.3.2", - "source-map": "0.5.7", - "supports-color": "3.2.3" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "kind-of": "3.2.2" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" }, "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + } + } + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + }, + "dependencies": { + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "dev": true, "requires": { - "has-flag": "1.0.0" + "for-in": "1.0.2" } } } }, - "postcss-calc": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", - "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-message-helpers": "2.0.0", - "reduce-css-calc": "1.3.0" + "isobject": "3.0.1" } }, - "postcss-colormin": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", - "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", "dev": true, "requires": { - "colormin": "1.1.2", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" } }, - "postcss-convert-values": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", - "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", + "opn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.1.0.tgz", + "integrity": "sha512-iPNl7SyM8L30Rm1sjGdLLheyHVw5YXVfi3SKWJzBI7efxRwHojfRFjwE/OLM6qp9xJYMgab8WicTU1cPoY+Hpg==", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "is-wsl": "1.1.0" } }, - "postcss-custom-properties": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-6.2.0.tgz", - "integrity": "sha512-eNR2h9T9ciKMoQEORrPjH33XeN/nuvVuxArOKmHtsFbGbNss631tgTrKou3/pmjAZbA4QQkhLIkPQkIk3WW+8w==", + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "balanced-match": "1.0.0", - "postcss": "6.0.14" + "minimist": "0.0.10", + "wordwrap": "0.0.3" }, "dependencies": { - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", - "dev": true, - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true } } }, - "postcss-discard-comments": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", - "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", - "dev": true, - "requires": { - "postcss": "5.2.18" - } + "options": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=", + "dev": true }, - "postcss-discard-duplicates": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", - "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", + "original": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz", + "integrity": "sha1-kUf5P6FpbQS+YeAb1QuurKZWvTs=", "dev": true, "requires": { - "postcss": "5.2.18" + "url-parse": "1.0.5" + }, + "dependencies": { + "url-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.0.5.tgz", + "integrity": "sha1-CFSGBCKv3P7+tsllxmLUgAFpkns=", + "dev": true, + "requires": { + "querystringify": "0.0.4", + "requires-port": "1.0.0" + } + } } }, - "postcss-discard-empty": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", - "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "requires": { - "postcss": "5.2.18" + "lcid": "1.0.0" } }, - "postcss-discard-overridden": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", - "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "requires": { - "postcss": "5.2.18" + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" } }, - "postcss-discard-unused": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", - "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", "dev": true, "requires": { - "postcss": "5.2.18", - "uniqs": "2.0.0" + "p-try": "1.0.0" } }, - "postcss-filter-plugins": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz", - "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=", + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "postcss": "5.2.18", - "uniqid": "4.1.1" + "p-limit": "1.2.0" } }, - "postcss-load-config": { + "p-map": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz", - "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", "dev": true, "requires": { - "cosmiconfig": "2.2.2", - "object-assign": "4.1.1", - "postcss-load-options": "1.2.0", - "postcss-load-plugins": "2.3.0" + "cyclist": "0.2.2", + "inherits": "2.0.3", + "readable-stream": "2.3.3" } }, - "postcss-load-options": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz", - "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", "dev": true, "requires": { - "cosmiconfig": "2.2.2", - "object-assign": "4.1.1" + "no-case": "2.3.2" } }, - "postcss-load-plugins": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz", - "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=", + "parse-asn1": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", "dev": true, "requires": { - "cosmiconfig": "2.2.2", - "object-assign": "4.1.1" + "asn1.js": "4.10.1", + "browserify-aes": "1.1.1", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.14" } }, - "postcss-loader": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.0.8.tgz", - "integrity": "sha512-KtXBiQ/r/WYW8LxTSJK7h8wLqvCMSub/BqmRnud/Mu8RzwflW9cmXxwsMwbn15TNv287Hcufdb3ZSs7xHKnG8Q==", + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, "requires": { - "loader-utils": "1.1.0", - "postcss": "6.0.14", - "postcss-load-config": "1.2.0", - "schema-utils": "0.3.0" + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" }, "dependencies": { - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", - "dev": true, - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } } } }, - "postcss-merge-idents": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", - "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "has": "1.0.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "error-ex": "1.3.1" } }, - "postcss-merge-longhand": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", - "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "parsejson": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/parsejson/-/parsejson-0.0.3.tgz", + "integrity": "sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs=", "dev": true, "requires": { - "postcss": "5.2.18" + "better-assert": "1.0.2" } }, - "postcss-merge-rules": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", - "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", "dev": true, "requires": { - "browserslist": "1.7.7", - "caniuse-api": "1.6.1", - "postcss": "5.2.18", - "postcss-selector-parser": "2.2.3", - "vendors": "1.0.1" + "better-assert": "1.0.2" } }, - "postcss-message-helpers": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", - "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=", + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "requires": { + "better-assert": "1.0.2" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, - "postcss-minify-font-values": { + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", - "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, - "postcss-minify-gradients": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", - "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", + "pbkdf2": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", + "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.10" } }, - "postcss-minify-params": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", - "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "alphanum-sort": "1.0.2", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0", - "uniqs": "2.0.0" + "pinkie": "2.0.4" } }, - "postcss-minify-selectors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", - "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", "dev": true, "requires": { - "alphanum-sort": "1.0.2", - "has": "1.0.1", - "postcss": "5.2.18", - "postcss-selector-parser": "2.2.3" + "find-up": "2.1.0" } }, - "postcss-modules-extract-imports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz", - "integrity": "sha1-thTJcgvmgW6u41+zpfqh26agXds=", + "portfinder": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz", + "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=", "dev": true, "requires": { - "postcss": "6.0.14" + "async": "1.5.2", + "debug": "2.6.9", + "mkdirp": "0.5.1" }, "dependencies": { - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", - "dev": true, - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true } } }, - "postcss-modules-local-by-default": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", - "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "6.0.19", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.19.tgz", + "integrity": "sha512-f13HRz0HtVwVaEuW6J6cOUCBLFtymhgyLPV7t4QEk2UD3twRI9IluDcQNdzQdBpiixkXj2OmzejhhTbSbDxNTg==", "dev": true, "requires": { - "css-selector-tokenizer": "0.7.0", - "postcss": "6.0.14" + "chalk": "2.3.2", + "source-map": "0.6.1", + "supports-color": "5.3.0" }, "dependencies": { - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" + "color-convert": "1.9.1" } }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "postcss-modules-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", - "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", - "dev": true, - "requires": { - "css-selector-tokenizer": "0.7.0", - "postcss": "6.0.14" - }, - "dependencies": { "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", "dev": true, "requires": { - "ansi-styles": "3.2.0", + "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" + "supports-color": "5.3.0" } }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", - "dev": true, - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" - } + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true - } - } - }, - "postcss-modules-values": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", - "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", - "dev": true, - "requires": { - "icss-replace-symbols": "1.1.0", - "postcss": "6.0.14" - }, - "dependencies": { - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", "dev": true, "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" + "has-flag": "3.0.0" } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true } } }, - "postcss-normalize-charset": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", - "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", - "dev": true, - "requires": { - "postcss": "5.2.18" - } - }, - "postcss-normalize-url": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", - "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", - "dev": true, - "requires": { - "is-absolute-url": "2.1.0", - "normalize-url": "1.9.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-ordered-values": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", - "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", - "dev": true, - "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-reduce-idents": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", - "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", - "dev": true, - "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-reduce-initial": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", - "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", + "postcss-import": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-11.1.0.tgz", + "integrity": "sha512-5l327iI75POonjxkXgdRCUS+AlzAdBx4pOvMEhTKTCjb1p8IEeVR9yx3cPbmN7LIWJLbfnIXxAhoB4jpD0c/Cw==", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "6.0.19", + "postcss-value-parser": "3.3.0", + "read-cache": "1.0.0", + "resolve": "1.5.0" } }, - "postcss-reduce-transforms": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", - "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", + "postcss-load-config": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz", + "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", "dev": true, "requires": { - "has": "1.0.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1", + "postcss-load-options": "1.2.0", + "postcss-load-plugins": "2.3.0" } }, - "postcss-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", - "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", + "postcss-load-options": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz", + "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", "dev": true, "requires": { - "flatten": "1.0.2", - "indexes-of": "1.0.1", - "uniq": "1.0.1" + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1" } }, - "postcss-svgo": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", - "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", + "postcss-load-plugins": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz", + "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=", "dev": true, "requires": { - "is-svg": "2.1.0", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0", - "svgo": "0.7.2" + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1" } }, - "postcss-unique-selectors": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", - "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", + "postcss-loader": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.1.1.tgz", + "integrity": "sha512-f0J/DWE/hyO9/LH0WHpXkny/ZZ238sSaG3p1SRBtVZnFWUtD7GXIEgHoBg8cnAeRbmEvUxHQptY46zWfwNYj/w==", "dev": true, "requires": { - "alphanum-sort": "1.0.2", - "postcss": "5.2.18", - "uniqs": "2.0.0" + "loader-utils": "1.1.0", + "postcss": "6.0.19", + "postcss-load-config": "1.2.0", + "schema-utils": "0.4.5" } }, "postcss-url": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-7.2.1.tgz", - "integrity": "sha512-jycW2XYgU39SpA+MJOOP7Fe7I2NxiCq8rOXiG61NBoJ4vG/WFn2IhS18vGiphla4VTN3WoHJOBMMJz1n4h1VYQ==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-7.3.1.tgz", + "integrity": "sha512-Ya5KIjGptgz0OtrVYfi2UbLxVAZ6Emc4Of+Grx4Sf1deWlRpFwLr8FrtkUxfqh+XiZIVkXbjQrddE10ESpNmdA==", "dev": true, "requires": { "mime": "1.4.1", "minimatch": "3.0.4", "mkdirp": "0.5.1", - "postcss": "6.0.14", - "xxhashjs": "0.2.1" - }, - "dependencies": { - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" - } - }, - "postcss": { - "version": "6.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", - "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", - "dev": true, - "requires": { - "chalk": "2.3.0", - "source-map": "0.6.1", - "supports-color": "4.5.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } + "postcss": "6.0.19", + "xxhashjs": "0.2.2" } }, "postcss-value-parser": { @@ -6610,23 +7397,6 @@ "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", "dev": true }, - "postcss-zindex": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", - "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", - "dev": true, - "requires": { - "has": "1.0.1", - "postcss": "5.2.18", - "uniqs": "2.0.0" - } - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", @@ -6677,7 +7447,7 @@ "integrity": "sha1-myIXQXCaTGLVzVPGqt1UpxE36V8=", "dev": true, "requires": { - "@types/node": "6.0.92", + "@types/node": "6.0.102", "@types/q": "0.0.32", "@types/selenium-webdriver": "2.53.43", "blocking-proxy": "0.0.5", @@ -6800,19 +7570,19 @@ } }, "proxy-addr": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz", - "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", + "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", "dev": true, "requires": { "forwarded": "0.1.2", - "ipaddr.js": "1.5.2" + "ipaddr.js": "1.6.0" } }, "prr": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", - "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, "pseudomap": { @@ -6831,28 +7601,28 @@ "browserify-rsa": "4.0.1", "create-hash": "1.1.3", "parse-asn1": "5.1.0", - "randombytes": "2.0.5" + "randombytes": "2.0.6" } }, "pump": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", - "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", "dev": true, "requires": { - "end-of-stream": "1.4.0", + "end-of-stream": "1.4.1", "once": "1.4.0" } }, "pumpify": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.3.5.tgz", - "integrity": "sha1-G2ccYZlAq8rqwK0OOjwWS+dgmTs=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", + "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==", "dev": true, "requires": { - "duplexify": "3.5.1", + "duplexify": "3.5.4", "inherits": "2.0.3", - "pump": "1.0.3" + "pump": "2.0.1" } }, "punycode": { @@ -6861,12 +7631,6 @@ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - }, "qjobs": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.1.5.tgz", @@ -6879,16 +7643,6 @@ "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", "dev": true }, - "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true, - "requires": { - "object-assign": "4.1.1", - "strict-uri-encode": "1.1.0" - } - }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -6949,21 +7703,21 @@ } }, "randombytes": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", - "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", "dev": true, "requires": { "safe-buffer": "5.1.1" } }, "randomfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz", - "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "dev": true, "requires": { - "randombytes": "2.0.5", + "randombytes": "2.0.6", "safe-buffer": "5.1.1" } }, @@ -6991,6 +7745,15 @@ "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=", "dev": true }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", @@ -7000,6 +7763,19 @@ "load-json-file": "1.1.0", "normalize-package-data": "2.4.0", "path-type": "1.1.0" + }, + "dependencies": { + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + } } }, "read-pkg-up": { @@ -7010,6 +7786,27 @@ "requires": { "find-up": "1.1.2", "read-pkg": "1.1.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + } } }, "readable-stream": { @@ -7049,46 +7846,10 @@ "strip-indent": "1.0.1" } }, - "reduce-css-calc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", - "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", - "dev": true, - "requires": { - "balanced-match": "0.4.2", - "math-expression-evaluator": "1.2.17", - "reduce-function-call": "1.0.2" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, - "reduce-function-call": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", - "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", - "dev": true, - "requires": { - "balanced-match": "0.4.2" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, "reflect-metadata": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.10.tgz", - "integrity": "sha1-tPg3BEFqytiZiMmxVjXUfgO5NEo=", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz", + "integrity": "sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A==", "dev": true }, "regenerate": { @@ -7098,9 +7859,9 @@ "dev": true }, "regenerator-runtime": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", - "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true }, "regex-cache": { @@ -7112,6 +7873,16 @@ "is-equal-shallow": "0.1.3" } }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, "regexpu-core": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", @@ -7283,6 +8054,18 @@ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "dev": true }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -7321,11 +8104,18 @@ } }, "rxjs": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.2.tgz", - "integrity": "sha512-oRYoIKWBU3Ic37fLA5VJu31VqQO4bWubRntcHSJ+cwaDQBwdnZ9x4zmhJfm/nFQ2E82/I4loSioHnACamrKGgA==", + "version": "5.5.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.7.tgz", + "integrity": "sha512-Hxo2ac8gRQjwjtKgukMIwBRbq5+KAeEV5hXM4obYBOAghev41bDQWgFH4svYiU9UnQ5kNww2LgfyBdevCd2HXA==", "requires": { - "symbol-observable": "1.0.4" + "symbol-observable": "1.0.1" + }, + "dependencies": { + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" + } } }, "safe-buffer": { @@ -7334,6 +8124,15 @@ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", "dev": true }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, "sass-graph": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", @@ -7348,15 +8147,15 @@ } }, "sass-loader": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-6.0.6.tgz", - "integrity": "sha512-c3/Zc+iW+qqDip6kXPYLEgsAu2lf4xz0EZDplB7EmSUMda12U1sGJPetH55B/j9eu0bTtKzKlNPWWyYC7wFNyQ==", + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-6.0.7.tgz", + "integrity": "sha512-JoiyD00Yo1o61OJsoP2s2kb19L1/Y2p3QFcCdWdF6oomBGKVYuZyqHWemRBfQ2uGYsk+CH3eCguXNfpjzlcpaA==", "dev": true, "requires": { - "async": "2.6.0", - "clone-deep": "0.3.0", + "clone-deep": "2.0.2", "loader-utils": "1.1.0", "lodash.tail": "4.1.1", + "neo-async": "2.5.0", "pify": "3.0.0" }, "dependencies": { @@ -7384,12 +8183,13 @@ "dev": true }, "schema-utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", - "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", + "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", "dev": true, "requires": { - "ajv": "5.4.0" + "ajv": "6.2.1", + "ajv-keywords": "3.1.0" } }, "scss-tokenizer": { @@ -7399,7 +8199,7 @@ "dev": true, "optional": true, "requires": { - "js-base64": "2.3.2", + "js-base64": "2.4.3", "source-map": "0.4.4" }, "dependencies": { @@ -7445,12 +8245,12 @@ } }, "selfsigned": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.1.tgz", - "integrity": "sha1-v4y3uDJWxFUeMTR8YxF3jbme7FI=", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.2.tgz", + "integrity": "sha1-tESVgNmZKbZbEKSDiTAaZZIIh1g=", "dev": true, "requires": { - "node-forge": "0.6.33" + "node-forge": "0.7.1" } }, "semver": { @@ -7468,16 +8268,25 @@ "semver": "5.4.1" } }, + "semver-intersect": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.3.1.tgz", + "integrity": "sha1-j6hKnhAovSOeRTDRo+GB5pjYhLo=", + "dev": true, + "requires": { + "semver": "5.4.1" + } + }, "send": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", - "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "dev": true, "requires": { "debug": "2.6.9", - "depd": "1.1.1", + "depd": "1.1.2", "destroy": "1.0.4", - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "etag": "1.8.1", "fresh": "0.5.2", @@ -7486,16 +8295,42 @@ "ms": "2.0.0", "on-finished": "2.3.0", "range-parser": "1.2.0", - "statuses": "1.3.1" + "statuses": "1.4.0" + }, + "dependencies": { + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "dev": true + } } }, + "serialize-javascript": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.4.0.tgz", + "integrity": "sha1-fJWFFNtqwkQ6irwGLcn3iGp/YAU=", + "dev": true + }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", "dev": true, "requires": { - "accepts": "1.3.4", + "accepts": "1.3.5", "batch": "0.6.1", "debug": "2.6.9", "escape-html": "1.0.3", @@ -7505,15 +8340,23 @@ } }, "serve-static": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", - "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "dev": true, "requires": { - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "parseurl": "1.3.2", - "send": "0.16.1" + "send": "0.16.2" + }, + "dependencies": { + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + } } }, "set-blocking": { @@ -7528,6 +8371,29 @@ "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", "dev": true }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -7541,66 +8407,192 @@ "dev": true }, "sha.js": { - "version": "2.4.9", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz", - "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==", + "version": "2.4.10", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz", + "integrity": "sha512-vnwmrFDlOExK4Nm16J2KMWHLrp14lBrjxMxBJpu++EnsuBmpiYaM/MEs46Vxxm/4FvdP5yTwuCTO9it5FSjrqA==", "dev": true, "requires": { "inherits": "2.0.3", "safe-buffer": "5.1.1" } }, - "shallow-clone": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", - "integrity": "sha1-WQnodLp3EG1zrEFM/sH/yofZcGA=", + "shallow-clone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz", + "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==", + "dev": true, + "requires": { + "is-extendable": "0.1.1", + "kind-of": "5.1.0", + "mixin-object": "2.0.1" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "silent-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/silent-error/-/silent-error-1.1.0.tgz", + "integrity": "sha1-IglwbxyFCp8dENDYQJGLRvJuG8k=", + "dev": true, + "requires": { + "debug": "2.6.9" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.1", + "use": "3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { - "is-extendable": "0.1.1", - "kind-of": "2.0.1", - "lazy-cache": "0.2.7", - "mixin-object": "2.0.1" + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" }, "dependencies": { - "kind-of": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", - "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-descriptor": "1.0.2" } } } }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "silent-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/silent-error/-/silent-error-1.1.0.tgz", - "integrity": "sha1-IglwbxyFCp8dENDYQJGLRvJuG8k=", + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { - "debug": "2.6.9" + "kind-of": "3.2.2" } }, "sntp": { @@ -7755,21 +8747,13 @@ } }, "sockjs": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.18.tgz", - "integrity": "sha1-2bKJMWyn33dZXvKZ4HXw+TfrQgc=", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", + "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", "dev": true, "requires": { "faye-websocket": "0.10.0", - "uuid": "2.0.3" - }, - "dependencies": { - "uuid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", - "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", - "dev": true - } + "uuid": "3.1.0" } }, "sockjs-client": { @@ -7797,15 +8781,6 @@ } } }, - "sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true, - "requires": { - "is-plain-obj": "1.1.0" - } - }, "source-list-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", @@ -7818,35 +8793,17 @@ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, - "source-map-loader": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.3.tgz", - "integrity": "sha512-MYbFX9DYxmTQFfy2v8FC1XZwpwHKYxg3SK8Wb7VPBKuhDjz8gi9re2819MsG4p49HDyiOSUKlmZ+nQBArW5CGw==", + "source-map-resolve": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", + "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", "dev": true, "requires": { - "async": "2.6.0", - "loader-utils": "0.2.17", - "source-map": "0.6.1" - }, - "dependencies": { - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } + "atob": "2.0.3", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" } }, "source-map-support": { @@ -7858,25 +8815,42 @@ "source-map": "0.5.7" } }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, "spdx-correct": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", "dev": true, "requires": { - "spdx-license-ids": "1.2.2" + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" } }, - "spdx-expression-parse": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", "dev": true }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, "spdx-license-ids": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", "dev": true }, "spdy": { @@ -7902,10 +8876,19 @@ "debug": "2.6.9", "detect-node": "2.0.3", "hpack.js": "2.1.6", - "obuf": "1.1.1", + "obuf": "1.1.2", "readable-stream": "2.3.3", "safe-buffer": "5.1.1", - "wbuf": "1.7.2" + "wbuf": "1.7.3" + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2" } }, "sprintf-js": { @@ -7939,14 +8922,92 @@ } }, "ssri": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.0.0.tgz", - "integrity": "sha512-728D4yoQcQm1ooZvSbywLkV1RjfITZXh0oWrhM/lnsx3nAHx7LsRGJWB/YyvoceAYRq98xqbstiN4JBv1/wNHg==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" } }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "statuses": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", @@ -7979,14 +9040,14 @@ "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==", "dev": true, "requires": { - "end-of-stream": "1.4.0", + "end-of-stream": "1.4.1", "stream-shift": "1.0.0" } }, "stream-http": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", - "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", + "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==", "dev": true, "requires": { "builtin-status-codes": "3.0.0", @@ -8002,12 +9063,6 @@ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true - }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -8074,12 +9129,36 @@ "dev": true }, "style-loader": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.13.2.tgz", - "integrity": "sha1-dFMzhM9pjHEEx5URULSXF63C87s=", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.19.1.tgz", + "integrity": "sha512-IRE+ijgojrygQi3rsqT0U4dd+UcPCqcVvauZpCnQrGAlEe+FUIyrK93bUDScamesjP08JlQNsFJU+KmPedP5Og==", "dev": true, "requires": { - "loader-utils": "1.1.0" + "loader-utils": "1.1.0", + "schema-utils": "0.3.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "5.5.2" + } + } } }, "stylus": { @@ -8128,9 +9207,9 @@ } }, "stylus-loader": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.1.tgz", - "integrity": "sha1-d/SzT9Aw0lsmF7z1UT21sHMMQIk=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz", + "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==", "dev": true, "requires": { "loader-utils": "1.1.0", @@ -8147,26 +9226,6 @@ "has-flag": "2.0.0" } }, - "svgo": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", - "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", - "dev": true, - "requires": { - "coa": "1.0.4", - "colors": "1.1.2", - "csso": "2.3.2", - "js-yaml": "3.7.0", - "mkdirp": "0.5.1", - "sax": "1.2.4", - "whet.extend": "0.9.9" - } - }, - "symbol-observable": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz", - "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=" - }, "tapable": { "version": "0.2.8", "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", @@ -8202,9 +9261,9 @@ } }, "thunky": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-0.1.0.tgz", - "integrity": "sha1-vzAUaCTituZ7Dy16Ssi+smkIaE4=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.2.tgz", + "integrity": "sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E=", "dev": true }, "time-stamp": { @@ -8214,9 +9273,9 @@ "dev": true }, "timers-browserify": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.4.tgz", - "integrity": "sha512-uZYhyU3EX8O7HQP+J9fTVYwsq90Vr68xPEFo7yrVImIxYvHgukBEgOB/SgGoorWVTzGM/3Z+wUNnboA4M8jWrg==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", + "integrity": "sha512-HQ3nbYRAowdVd0ckGFvmJPPCOH/CHleFN/Y0YQCX1DVaB7t+KFvisuyN09fuP8Jtp1CpfSh8O8bMkHbdbPe6Pw==", "dev": true, "requires": { "setimmediate": "1.0.5" @@ -8249,6 +9308,48 @@ "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", "dev": true }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + } + } + }, "toposort": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.6.tgz", @@ -8345,15 +9446,32 @@ } }, "tsickle": { - "version": "0.24.1", - "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.24.1.tgz", - "integrity": "sha512-XloFQZhVhgjpQsi3u2ORNRJvuID5sflOg6HfP093IqAbhE1+fIUXznULpdDwHgG4p+v8w78KdHruQtkWUKx5AQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.27.2.tgz", + "integrity": "sha512-KW+ZgY0t2cq2Qib1sfdgMiRnk+cr3brUtzZoVWjv+Ot3jNxVorFBUH+6In6hl8Dg7BI2AAFf69NHkwvZNMSFwA==", "dev": true, "requires": { "minimist": "1.2.0", "mkdirp": "0.5.1", - "source-map": "0.5.7", - "source-map-support": "0.4.18" + "source-map": "0.6.1", + "source-map-support": "0.5.3" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.3.tgz", + "integrity": "sha512-eKkTgWYeBOQqFGXRfKabMFdnWepo51vWqEdoeikaEPFiJC7MCU5j2h4+6Q8npkZTeLGbSyecZvRxiSoWl3rh+w==", + "dev": true, + "requires": { + "source-map": "0.6.1" + } + } } }, "tslib": { @@ -8433,15 +9551,21 @@ "dev": true }, "uglify-js": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.1.10.tgz", - "integrity": "sha512-0ul3BWx79We0mIPM1l72oqpMtWL0TVMnKZZY6FaHPy3tDzCZGXeFxw5N1ZvtkmQsLI+ECR/tUQyIYbyHUcuvEw==", + "version": "3.3.14", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.14.tgz", + "integrity": "sha512-OY8VPQU25q09gQRbC+Ekk3xgEVBmYFEfVcgS47ksjTiNht2LmLlUkWutyi38ZsDSToJHwbe76kDGwmD226Z2Fg==", "dev": true, "requires": { - "commander": "2.11.0", + "commander": "2.14.1", "source-map": "0.6.1" }, "dependencies": { + "commander": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", + "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -8458,36 +9582,41 @@ "optional": true }, "uglifyjs-webpack-plugin": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.0.0.tgz", - "integrity": "sha512-23qmtiLm1X7O0XVSZ54W7XGHykPss+2lo3RYC9zSzK3DDT5W27woZpDFDKguDCnG1RIX8cDnmy5j+dtXxJCA/Q==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.3.tgz", + "integrity": "sha512-as/50351uuJGiQbhVvE510SCqM/YOWghCzIFJeEOu5oVE0QOZ3/vu2QcnVvu0Lz+vNd0rKsiCFAlbcw0i/YH2w==", "dev": true, "requires": { - "cacache": "10.0.1", + "cacache": "10.0.4", "find-cache-dir": "1.0.0", - "schema-utils": "0.3.0", - "source-map": "0.5.7", - "uglify-es": "3.1.10", - "webpack-sources": "1.0.2", - "worker-farm": "1.5.2" + "schema-utils": "0.4.5", + "serialize-javascript": "1.4.0", + "source-map": "0.6.1", + "uglify-es": "3.3.9", + "webpack-sources": "1.1.0", + "worker-farm": "1.6.0" }, "dependencies": { + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "uglify-es": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.1.10.tgz", - "integrity": "sha512-RwBX0aOeHvO8MKKUeLCArQGb9OZ6xA+EqfVxsE9wqK0saFYFVLIFvHeeCOg61C6NO6KCuSiG9OjNjCA+OB4nzg==", + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", "dev": true, "requires": { - "commander": "2.11.0", + "commander": "2.13.0", "source-map": "0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } } } @@ -8498,27 +9627,41 @@ "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=", "dev": true }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "uniqid": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.1.tgz", - "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=", + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { - "macaddress": "0.2.8" + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } } }, - "uniqs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", - "dev": true - }, "unique-filename": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", @@ -8549,12 +9692,64 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "upath": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.0.4.tgz", + "integrity": "sha512-d4SJySNBXDaQp+DPrziv3xGS6w3d2Xt69FijJr86zMPBy23JEloMCEOUBBzuN7xCtjLCnmB9tI/z7SBCahHBOw==", + "dev": true + }, "upper-case": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", "dev": true }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", @@ -8582,6 +9777,29 @@ "loader-utils": "1.1.0", "mime": "1.4.1", "schema-utils": "0.3.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "5.5.2" + } + } } }, "url-parse": { @@ -8602,6 +9820,23 @@ } } }, + "use": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, "useragent": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", @@ -8671,13 +9906,13 @@ } }, "validate-npm-package-license": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", "dev": true, "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" } }, "vary": { @@ -8686,12 +9921,6 @@ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", "dev": true }, - "vendors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.1.tgz", - "integrity": "sha1-N61zyO5Bf7PVgOeFMSMH0nSEfyI=", - "dev": true - }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -8733,20 +9962,323 @@ "dev": true }, "watchpack": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", - "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.5.0.tgz", + "integrity": "sha512-RSlipNQB1u48cq0wH/BNfCu1tD/cJ8ydFIkNYhp9o+3d+8unClkIovpW5qpFPgmL9OE48wfAnlZydXByWP82AA==", "dev": true, "requires": { - "async": "2.6.0", - "chokidar": "1.7.0", - "graceful-fs": "4.1.11" + "chokidar": "2.0.2", + "graceful-fs": "4.1.11", + "neo-async": "2.5.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "3.1.9", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.1.tgz", + "integrity": "sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "kind-of": "6.0.2", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "chokidar": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.2.tgz", + "integrity": "sha512-l32Hw3wqB0L2kGVmSbK/a+xXLDrUEsc84pSgMkmwygHvD7ubRsP/vxxHa5BtB6oix1XLLVCHyYMsckRXxThmZw==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.1", + "fsevents": "1.1.3", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0", + "upath": "1.0.4" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.9.tgz", + "integrity": "sha512-SlIz6sv5UPaAVVFRKodKjCg48EbNoIhgetzfK/Cy0v5U52Z6zB136M8tp0UC9jM53LYbmIRihJszvvqpKkfm9g==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.1", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } } }, "wbuf": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz", - "integrity": "sha1-1pe5nx9ZUS3ydRvkJ2nBWAtYAf4=", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", "dev": true, "requires": { "minimalistic-assert": "1.0.0" @@ -8806,19 +10338,19 @@ } }, "webpack": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.8.1.tgz", - "integrity": "sha512-5ZXLWWsMqHKFr5y0N3Eo5IIisxeEeRAajNq4mELb/WELOR7srdbQk2N5XiyNy2A/AgvlR3AmeBCZJW8lHrolbw==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz", + "integrity": "sha512-3kOFejWqj5ISpJk4Qj/V7w98h9Vl52wak3CLiw/cDOfbVTq7FeoZ0SdoHHY9PYlHr50ZS42OfvzE2vB4nncKQg==", "dev": true, "requires": { - "acorn": "5.2.1", + "acorn": "5.5.3", "acorn-dynamic-import": "2.0.2", - "ajv": "5.4.0", - "ajv-keywords": "2.1.1", + "ajv": "6.2.1", + "ajv-keywords": "3.1.0", "async": "2.6.0", "enhanced-resolve": "3.4.1", "escope": "3.6.0", - "interpret": "1.0.4", + "interpret": "1.1.0", "json-loader": "0.5.7", "json5": "0.5.1", "loader-runner": "2.3.0", @@ -8830,8 +10362,8 @@ "supports-color": "4.5.0", "tapable": "0.2.8", "uglifyjs-webpack-plugin": "0.4.6", - "watchpack": "1.4.0", - "webpack-sources": "1.0.2", + "watchpack": "1.5.0", + "webpack-sources": "1.1.0", "yargs": "8.0.2" }, "dependencies": { @@ -8858,15 +10390,6 @@ "wordwrap": "0.0.2" } }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "2.0.0" - } - }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -8986,7 +10509,7 @@ "requires": { "source-map": "0.5.7", "uglify-js": "2.8.29", - "webpack-sources": "1.0.2" + "webpack-sources": "1.1.0" } }, "which-module": { @@ -9001,6 +10524,12 @@ "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", "dev": true }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, "yargs": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", @@ -9073,64 +10602,6 @@ } } }, - "webpack-concat-plugin": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/webpack-concat-plugin/-/webpack-concat-plugin-1.4.0.tgz", - "integrity": "sha512-Ym9Qm5Sw9oXJYChNJk09I/yaXDaV3UDxsa07wcCvILzIeSJTnSUZjhS4y2YkULzgE8VHOv9X04KtlJPZGwXqMg==", - "dev": true, - "requires": { - "md5": "2.2.1", - "uglify-js": "2.8.29" - }, - "dependencies": { - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" - } - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, - "requires": { - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" - } - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", - "window-size": "0.1.0" - } - } - } - }, "webpack-core": { "version": "0.6.9", "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", @@ -9159,59 +10630,149 @@ } }, "webpack-dev-middleware": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.0.tgz", - "integrity": "sha1-007++y7dp+HTtdvgcolRMhllFwk=", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", + "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", "dev": true, "requires": { "memory-fs": "0.4.1", - "mime": "1.4.1", + "mime": "1.6.0", "path-is-absolute": "1.0.1", "range-parser": "1.2.0", "time-stamp": "2.0.0" + }, + "dependencies": { + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + } } }, "webpack-dev-server": { - "version": "2.9.4", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.9.4.tgz", - "integrity": "sha512-thrqC0EQEoSjXeYgP6pUXcUCZ+LNrKsDPn+mItLnn5VyyNZOJKd06hUP5vqkYwL8nWWXsii0loSF9NHNccT6ow==", + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.11.2.tgz", + "integrity": "sha512-zrPoX97bx47vZiAXfDrkw8pe9QjJ+lunQl3dypojyWwWr1M5I2h0VSrMPfTjopHQPRNn+NqfjcMmhoLcUJe2gA==", "dev": true, "requires": { "ansi-html": "0.0.7", "array-includes": "3.0.3", "bonjour": "3.5.0", - "chokidar": "1.7.0", - "compression": "1.7.1", + "chokidar": "2.0.2", + "compression": "1.7.2", "connect-history-api-fallback": "1.5.0", "debug": "3.1.0", "del": "3.0.0", - "express": "4.16.2", + "express": "4.16.3", "html-entities": "1.2.1", "http-proxy-middleware": "0.17.4", - "import-local": "0.1.1", + "import-local": "1.0.0", "internal-ip": "1.2.0", "ip": "1.1.5", "killable": "1.0.0", - "loglevel": "1.6.0", + "loglevel": "1.6.1", "opn": "5.1.0", "portfinder": "1.0.13", - "selfsigned": "1.10.1", + "selfsigned": "1.10.2", "serve-index": "1.9.1", - "sockjs": "0.3.18", + "sockjs": "0.3.19", "sockjs-client": "1.1.4", "spdy": "3.4.7", "strip-ansi": "3.0.1", - "supports-color": "4.5.0", - "webpack-dev-middleware": "1.12.0", + "supports-color": "5.3.0", + "webpack-dev-middleware": "1.12.2", "yargs": "6.6.0" }, "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "3.1.9", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.1.tgz", + "integrity": "sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "kind-of": "6.0.2", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, + "chokidar": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.2.tgz", + "integrity": "sha512-l32Hw3wqB0L2kGVmSbK/a+xXLDrUEsc84pSgMkmwygHvD7ubRsP/vxxHa5BtB6oix1XLLVCHyYMsckRXxThmZw==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.1", + "fsevents": "1.1.3", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0", + "upath": "1.0.4" + } + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -9221,6 +10782,255 @@ "ms": "2.0.0" } }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.9.tgz", + "integrity": "sha512-SlIz6sv5UPaAVVFRKodKjCg48EbNoIhgetzfK/Cy0v5U52Z6zB136M8tp0UC9jM53LYbmIRihJszvvqpKkfm9g==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.1", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, "yargs": { "version": "6.6.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", @@ -9254,18 +11064,26 @@ } }, "webpack-merge": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.1.tgz", - "integrity": "sha512-geQsZ86YkXOVOjvPC5yv3JSNnL6/X3Kzh935AQ/gJNEYXEfJDQFu/sdFuktS9OW2JcH/SJec8TGfRdrpHshH7A==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.2.tgz", + "integrity": "sha512-/0QYwW/H1N/CdXYA2PNPVbsxO3u2Fpz34vs72xm03SRfg6bMNGfMJIQEpQjKRvkG2JvT6oRJFpDtSrwbX8Jzvw==", "dev": true, "requires": { - "lodash": "4.17.4" + "lodash": "4.17.5" + }, + "dependencies": { + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "dev": true + } } }, "webpack-sources": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.0.2.tgz", - "integrity": "sha512-Y7UddMCv6dGjy81nBv6nuQeFFIt5aalHm7uyDsAsW86nZwfOVPGRr3XMjEQLaT+WKo8rlzhC9qtbJvYKLtAwaw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", "dev": true, "requires": { "source-list-map": "2.0.0", @@ -9281,9 +11099,9 @@ } }, "webpack-subresource-integrity": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.0.1.tgz", - "integrity": "sha1-H8CdRkl9pm5GdDoqUdLMOFucsO0=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.0.4.tgz", + "integrity": "sha1-j6yKfo61n8ahZ2ioXJ2U7n+dDts=", "dev": true, "requires": { "webpack-core": "0.6.9" @@ -9295,7 +11113,7 @@ "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", "dev": true, "requires": { - "http-parser-js": "0.4.9", + "http-parser-js": "0.4.11", "websocket-extensions": "0.1.3" } }, @@ -9311,12 +11129,6 @@ "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=", "dev": true }, - "whet.extend": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", - "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", - "dev": true - }, "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", @@ -9354,13 +11166,12 @@ "dev": true }, "worker-farm": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.5.2.tgz", - "integrity": "sha512-XxiQ9kZN5n6mmnW+mFJ+wXjNNI/Nx4DIdaAKLX1Bn6LYBWlN/zaBhu34DQYPZ1AJobQuu67S2OfDdNSVULvXkQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", + "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", "dev": true, "requires": { - "errno": "0.1.4", - "xtend": "4.0.1" + "errno": "0.1.7" } }, "wrap-ansi": { @@ -9430,18 +11241,18 @@ "dev": true }, "xxhashjs": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.1.tgz", - "integrity": "sha1-m76b6JYUKXbfo0wGGy0GjEPTDeA=", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz", + "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==", "dev": true, "requires": { "cuint": "0.2.2" } }, "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, "yallist": { @@ -9478,6 +11289,13 @@ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true, "optional": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true, + "optional": true } } }, @@ -9513,9 +11331,9 @@ "dev": true }, "zone.js": { - "version": "0.8.18", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.18.tgz", - "integrity": "sha512-knKOBQM0oea3/x9pdyDuDi7RhxDlJhOIkeixXSiTKWLgs4LpK37iBc+1HaHwzlciHUKT172CymJFKo8Xgh+44Q==" + "version": "0.8.20", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.20.tgz", + "integrity": "sha512-FXlA37ErSXCMy5RNBcGFgCI/Zivqzr0D19GuvDxhcYIJc7xkFp6c29DKyODJu0Zo+EMyur/WPPgcBh1EHjB9jA==" } } } diff --git a/dashboard/package.json b/dashboard/package.json index 8d43d390..0414d280 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -21,7 +21,7 @@ "@angular/platform-browser": "^5.0.0", "@angular/platform-browser-dynamic": "^5.0.0", "@angular/router": "^5.0.0", - "angular2-notifications": "^0.9.6", + "angular2-notifications": "^1.0.0", "bootstrap": "^4.0.0-beta.2", "chart.js": "^2.7.1", "core-js": "^2.4.0", @@ -35,22 +35,22 @@ "zone.js": "^0.8.14" }, "devDependencies": { - "@angular/cli": "^1.5.3", - "@angular/compiler-cli": "^5.0.0", - "@angular/language-service": "^5.0.0", - "@types/chart.js": "^2.6.8", + "@angular/cli": "^1.7.3", + "@angular/compiler-cli": "^5.2.8", + "@angular/language-service": "^5.2.8", + "@types/chart.js": "^2.7.10", "@types/jasmine": "~2.5.53", "@types/jasminewd2": "~2.0.2", - "@types/jquery": "^3.2.12", - "@types/node": "~6.0.60", + "@types/jquery": "^3.3.1", + "@types/node": "^6.0.102", "codelyzer": "~3.2.0", "jasmine-core": "~2.6.2", "jasmine-spec-reporter": "~4.1.0", "karma": "~1.7.0", "karma-chrome-launcher": "~2.1.1", "karma-cli": "~1.0.1", - "karma-coverage-istanbul-reporter": "^1.2.1", - "karma-jasmine": "~1.1.0", + "karma-coverage-istanbul-reporter": "^1.4.2", + "karma-jasmine": "^1.1.1", "karma-jasmine-html-reporter": "^0.2.2", "protractor": "~5.1.2", "ts-node": "~3.2.0", diff --git a/dashboard/protractor.conf.js b/dashboard/protractor.conf.js index 7ee3b5ee..6f968165 100644 --- a/dashboard/protractor.conf.js +++ b/dashboard/protractor.conf.js @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // Protractor configuration file, see link for more information // https://github.com/angular/protractor/blob/master/lib/config.ts diff --git a/dashboard/src/app/analytics/main.component.ts b/dashboard/src/app/analytics/main.component.ts index 3139f2f6..b99a6689 100644 --- a/dashboard/src/app/analytics/main.component.ts +++ b/dashboard/src/app/analytics/main.component.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import {Component, OnInit, ViewEncapsulation} from '@angular/core'; import * as chartjs from 'chart.js' import * as $ from 'jquery'; diff --git a/dashboard/src/app/app.component.css b/dashboard/src/app/app.component.css index 7cd8c3c4..43034e5e 100644 --- a/dashboard/src/app/app.component.css +++ b/dashboard/src/app/app.component.css @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + body { margin: 0; } diff --git a/dashboard/src/app/app.component.spec.ts b/dashboard/src/app/app.component.spec.ts index bcbdf36b..ae1e9ca9 100644 --- a/dashboard/src/app/app.component.spec.ts +++ b/dashboard/src/app/app.component.spec.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { TestBed, async } from '@angular/core/testing'; import { AppComponent } from './app.component'; describe('AppComponent', () => { diff --git a/dashboard/src/app/app.component.ts b/dashboard/src/app/app.component.ts index 430a63b2..35db2feb 100644 --- a/dashboard/src/app/app.component.ts +++ b/dashboard/src/app/app.component.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Component, ViewEncapsulation, OnInit } from '@angular/core'; import { Router, NavigationEnd } from '@angular/router'; import { AppService } from './shared/services'; diff --git a/dashboard/src/app/app.module.ts b/dashboard/src/app/app.module.ts index ffcae37c..68c7808c 100644 --- a/dashboard/src/app/app.module.ts +++ b/dashboard/src/app/app.module.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { NgModule, ApplicationRef } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { ReactiveFormsModule } from '@angular/forms'; diff --git a/dashboard/src/app/app.routes.ts b/dashboard/src/app/app.routes.ts index fad850f7..ed055f58 100644 --- a/dashboard/src/app/app.routes.ts +++ b/dashboard/src/app/app.routes.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Routes } from '@angular/router'; // import { TrainingsListComponent, TrainingsShowComponent } from './trainings'; import { TrainingsListComponent } from "./trainings/list.component"; diff --git a/dashboard/src/app/login/index.ts b/dashboard/src/app/login/index.ts index 22d615dd..a7e18043 100644 --- a/dashboard/src/app/login/index.ts +++ b/dashboard/src/app/login/index.ts @@ -1,2 +1,18 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export * from './login.component'; diff --git a/dashboard/src/app/login/login.component.ts b/dashboard/src/app/login/login.component.ts index 939bd602..2f9dd351 100644 --- a/dashboard/src/app/login/login.component.ts +++ b/dashboard/src/app/login/login.component.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Component, Input, OnInit, OnDestroy } from '@angular/core'; import { Router, ActivatedRoute, Params } from '@angular/router'; import { EmitterService } from "../shared/services/emitter.service"; diff --git a/dashboard/src/app/menu/index.ts b/dashboard/src/app/menu/index.ts index d07a1144..857a6f08 100644 --- a/dashboard/src/app/menu/index.ts +++ b/dashboard/src/app/menu/index.ts @@ -1 +1,17 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export * from './menu.component'; diff --git a/dashboard/src/app/menu/menu.component.ts b/dashboard/src/app/menu/menu.component.ts index 51806f3c..862a9e11 100644 --- a/dashboard/src/app/menu/menu.component.ts +++ b/dashboard/src/app/menu/menu.component.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Component, Input, OnInit, OnDestroy } from '@angular/core'; import { Router } from '@angular/router'; import { NotificationsService } from "angular2-notifications"; diff --git a/dashboard/src/app/models/create.component.css b/dashboard/src/app/models/create.component.css index 15aa3fd3..2f5640e5 100644 --- a/dashboard/src/app/models/create.component.css +++ b/dashboard/src/app/models/create.component.css @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #mySpinbox.spinbox { value: 1; min: 3; diff --git a/dashboard/src/app/models/create.component.ts b/dashboard/src/app/models/create.component.ts index 8959ccb0..8d95618f 100644 --- a/dashboard/src/app/models/create.component.ts +++ b/dashboard/src/app/models/create.component.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Component, OnInit, OnDestroy, ViewEncapsulation } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Subscription } from 'rxjs/Subscription'; diff --git a/dashboard/src/app/models/index.ts b/dashboard/src/app/models/index.ts index 9962dea1..82f32756 100644 --- a/dashboard/src/app/models/index.ts +++ b/dashboard/src/app/models/index.ts @@ -1,2 +1,18 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export * from './list.component'; export * from './create.component'; diff --git a/dashboard/src/app/models/list.component.ts b/dashboard/src/app/models/list.component.ts index 88db20cc..701ac95c 100644 --- a/dashboard/src/app/models/list.component.ts +++ b/dashboard/src/app/models/list.component.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Component, OnInit } from '@angular/core'; // import { AsyncPipe } from '@angular/common'; // import { ROUTER_DIRECTIVES } from '@angular/router'; diff --git a/dashboard/src/app/profile/index.ts b/dashboard/src/app/profile/index.ts index b15241ad..50d6b226 100644 --- a/dashboard/src/app/profile/index.ts +++ b/dashboard/src/app/profile/index.ts @@ -1,2 +1,18 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export * from './list.component'; export * from './show.component'; diff --git a/dashboard/src/app/profile/list.component.ts b/dashboard/src/app/profile/list.component.ts index 45ba4289..a04ba0b8 100644 --- a/dashboard/src/app/profile/list.component.ts +++ b/dashboard/src/app/profile/list.component.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Component, ChangeDetectionStrategy, ViewEncapsulation, OnInit } from '@angular/core'; // import { AsyncPipe } from '@angular/common'; // import { ROUTER_DIRECTIVES } from '@angular/router'; diff --git a/dashboard/src/app/profile/show.component.html b/dashboard/src/app/profile/show.component.html index ae21d833..0c23b01c 100644 --- a/dashboard/src/app/profile/show.component.html +++ b/dashboard/src/app/profile/show.component.html @@ -1 +1 @@ -About \ No newline at end of file +About diff --git a/dashboard/src/app/profile/show.component.ts b/dashboard/src/app/profile/show.component.ts index 358d109f..c9afd862 100644 --- a/dashboard/src/app/profile/show.component.ts +++ b/dashboard/src/app/profile/show.component.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Component, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core'; @Component({ diff --git a/dashboard/src/app/shared/directives/autofocus.ts b/dashboard/src/app/shared/directives/autofocus.ts index 145e08d4..61451a1d 100644 --- a/dashboard/src/app/shared/directives/autofocus.ts +++ b/dashboard/src/app/shared/directives/autofocus.ts @@ -1,10 +1,26 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Directive, ElementRef, Renderer } from '@angular/core'; - + @Directive({ - selector: '[autofocus]' // using [ ] means selecting attributes + selector: '[autofocus]' // using [ ] means selecting attributes }) export class Autofocus { - + constructor(private renderer: Renderer, private el: ElementRef) { } ngOnInit() { diff --git a/dashboard/src/app/shared/directives/index.ts b/dashboard/src/app/shared/directives/index.ts index db5f4a01..edda8ee3 100644 --- a/dashboard/src/app/shared/directives/index.ts +++ b/dashboard/src/app/shared/directives/index.ts @@ -1 +1,17 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export * from './autofocus'; diff --git a/dashboard/src/app/shared/interfaces/index.ts b/dashboard/src/app/shared/interfaces/index.ts index f60b387c..75c2c1eb 100644 --- a/dashboard/src/app/shared/interfaces/index.ts +++ b/dashboard/src/app/shared/interfaces/index.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // Defines a connection to a DLaaS service export interface DlaasConnection { id: string; diff --git a/dashboard/src/app/shared/models/index.ts b/dashboard/src/app/shared/models/index.ts index 00ea9218..f045991e 100644 --- a/dashboard/src/app/shared/models/index.ts +++ b/dashboard/src/app/shared/models/index.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export class LoginData { environment: string; token: string; diff --git a/dashboard/src/app/shared/services/app.service.spec.ts b/dashboard/src/app/shared/services/app.service.spec.ts index 6ff6ffff..1edb437a 100644 --- a/dashboard/src/app/shared/services/app.service.spec.ts +++ b/dashboard/src/app/shared/services/app.service.spec.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import {} from 'jasmine'; import { inject, async, ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; diff --git a/dashboard/src/app/shared/services/app.service.ts b/dashboard/src/app/shared/services/app.service.ts index 188f82e7..f7ddee8e 100644 --- a/dashboard/src/app/shared/services/app.service.ts +++ b/dashboard/src/app/shared/services/app.service.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Injectable } from '@angular/core'; import { Title } from '@angular/platform-browser'; diff --git a/dashboard/src/app/shared/services/auth-guard.service.ts b/dashboard/src/app/shared/services/auth-guard.service.ts index 81959407..b1cb323e 100644 --- a/dashboard/src/app/shared/services/auth-guard.service.ts +++ b/dashboard/src/app/shared/services/auth-guard.service.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Injectable } from '@angular/core'; import {ActivatedRouteSnapshot, Router, RouterStateSnapshot} from '@angular/router'; import { CanActivate } from '@angular/router'; diff --git a/dashboard/src/app/shared/services/auth.service.ts b/dashboard/src/app/shared/services/auth.service.ts index 37ce15b8..99e122b6 100644 --- a/dashboard/src/app/shared/services/auth.service.ts +++ b/dashboard/src/app/shared/services/auth.service.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; diff --git a/dashboard/src/app/shared/services/dlaas.service.ts b/dashboard/src/app/shared/services/dlaas.service.ts index c9b8f1a7..215b7219 100644 --- a/dashboard/src/app/shared/services/dlaas.service.ts +++ b/dashboard/src/app/shared/services/dlaas.service.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Observable } from 'rxjs/Observable'; diff --git a/dashboard/src/app/shared/services/emitter.service.ts b/dashboard/src/app/shared/services/emitter.service.ts index 8fa5cd71..4a3dcca7 100644 --- a/dashboard/src/app/shared/services/emitter.service.ts +++ b/dashboard/src/app/shared/services/emitter.service.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Injectable, EventEmitter } from '@angular/core'; @Injectable() diff --git a/dashboard/src/app/shared/services/index.ts b/dashboard/src/app/shared/services/index.ts index 0ad6cfd1..721a1590 100644 --- a/dashboard/src/app/shared/services/index.ts +++ b/dashboard/src/app/shared/services/index.ts @@ -1,2 +1,18 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export * from './app.service'; export * from './dlaas.service'; diff --git a/dashboard/src/app/trainings/emetrics.component.css b/dashboard/src/app/trainings/emetrics.component.css index b766c75b..c5dae15a 100644 --- a/dashboard/src/app/trainings/emetrics.component.css +++ b/dashboard/src/app/trainings/emetrics.component.css @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + pre { background: #303030; color: #f1f1f1; diff --git a/dashboard/src/app/trainings/emetrics.component.ts b/dashboard/src/app/trainings/emetrics.component.ts index 7375efec..6b9d9752 100644 --- a/dashboard/src/app/trainings/emetrics.component.ts +++ b/dashboard/src/app/trainings/emetrics.component.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import {Component, Input, OnInit, OnDestroy, OnChanges, ViewEncapsulation} from '@angular/core'; import {Observable} from 'rxjs/Observable'; import { Subscription } from 'rxjs/Subscription'; diff --git a/dashboard/src/app/trainings/emetricsraw.component.css b/dashboard/src/app/trainings/emetricsraw.component.css index 3bb4ef2c..a7614d29 100644 --- a/dashboard/src/app/trainings/emetricsraw.component.css +++ b/dashboard/src/app/trainings/emetricsraw.component.css @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + pre { background: #303030; color: #f1f1f1; diff --git a/dashboard/src/app/trainings/emetricsraw.component.ts b/dashboard/src/app/trainings/emetricsraw.component.ts index a08f075b..9fe54493 100644 --- a/dashboard/src/app/trainings/emetricsraw.component.ts +++ b/dashboard/src/app/trainings/emetricsraw.component.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import {Component, Input, OnChanges, OnInit} from '@angular/core'; import {DlaasService} from '../shared/services'; import {Subscription} from 'rxjs/Subscription'; diff --git a/dashboard/src/app/trainings/index.ts b/dashboard/src/app/trainings/index.ts index c3afb826..e73129d4 100644 --- a/dashboard/src/app/trainings/index.ts +++ b/dashboard/src/app/trainings/index.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export * from './list.component'; export * from './show.component'; export * from './emetrics.component'; diff --git a/dashboard/src/app/trainings/list.component.css b/dashboard/src/app/trainings/list.component.css index de1b23c0..9d299587 100644 --- a/dashboard/src/app/trainings/list.component.css +++ b/dashboard/src/app/trainings/list.component.css @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + .manifest-row { vert-align: middle; } diff --git a/dashboard/src/app/trainings/list.component.ts b/dashboard/src/app/trainings/list.component.ts index aa077cbf..f89e1826 100644 --- a/dashboard/src/app/trainings/list.component.ts +++ b/dashboard/src/app/trainings/list.component.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Component, ViewEncapsulation, OnInit, OnChanges, ElementRef, ViewChild } from '@angular/core'; import {FormBuilder, FormGroup, Validators} from "@angular/forms"; import { DlaasService } from '../shared/services'; diff --git a/dashboard/src/app/trainings/logs.component.css b/dashboard/src/app/trainings/logs.component.css index 3bb4ef2c..a7614d29 100644 --- a/dashboard/src/app/trainings/logs.component.css +++ b/dashboard/src/app/trainings/logs.component.css @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + pre { background: #303030; color: #f1f1f1; diff --git a/dashboard/src/app/trainings/logs.component.ts b/dashboard/src/app/trainings/logs.component.ts index 6c983b26..52acbe9d 100644 --- a/dashboard/src/app/trainings/logs.component.ts +++ b/dashboard/src/app/trainings/logs.component.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import {Component, HostListener, Input, OnChanges, OnInit} from '@angular/core'; import {DlaasService} from '../shared/services'; import {Subscription} from 'rxjs/Subscription'; diff --git a/dashboard/src/app/trainings/show.component.ts b/dashboard/src/app/trainings/show.component.ts index 04de0ca4..a4f9e9b5 100644 --- a/dashboard/src/app/trainings/show.component.ts +++ b/dashboard/src/app/trainings/show.component.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Component, OnInit, OnDestroy, ViewEncapsulation } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs/Observable'; diff --git a/dashboard/src/assets/font-awesome/HELP-US-OUT.txt b/dashboard/src/assets/font-awesome/HELP-US-OUT.txt new file mode 100644 index 00000000..83d083dd --- /dev/null +++ b/dashboard/src/assets/font-awesome/HELP-US-OUT.txt @@ -0,0 +1,7 @@ +I hope you love Font Awesome. If you've found it useful, please do me a favor and check out my latest project, +Fort Awesome (https://fortawesome.com). It makes it easy to put the perfect icons on your website. Choose from our awesome, +comprehensive icon sets or copy and paste your own. + +Please. Check it out. + +-Dave Gandy diff --git a/dashboard/src/assets/font-awesome/css/font-awesome.css b/dashboard/src/assets/font-awesome/css/font-awesome.css new file mode 100644 index 00000000..97816cd2 --- /dev/null +++ b/dashboard/src/assets/font-awesome/css/font-awesome.css @@ -0,0 +1,2353 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ +/* FONT PATH + * -------------------------- */ +@font-face { + font-family: 'FontAwesome'; + src: url('../fonts/fontawesome-webfont.eot?v=4.7.0'); + src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg'); + font-weight: normal; + font-style: normal; +} +.fa { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +/* makes the font 33% larger relative to the icon container */ +.fa-lg { + font-size: 1.33333333em; + line-height: 0.75em; + vertical-align: -15%; +} +.fa-2x { + font-size: 2em; +} +.fa-3x { + font-size: 3em; +} +.fa-4x { + font-size: 4em; +} +.fa-5x { + font-size: 5em; +} +.fa-fw { + width: 1.28571429em; + text-align: center; +} +.fa-ul { + padding-left: 0; + margin-left: 2.14285714em; + list-style-type: none; +} +.fa-ul > li { + position: relative; +} +.fa-li { + position: absolute; + left: -2.14285714em; + width: 2.14285714em; + top: 0.14285714em; + text-align: center; +} +.fa-li.fa-lg { + left: -1.85714286em; +} +.fa-border { + padding: .2em .25em .15em; + border: solid 0.08em #eeeeee; + border-radius: .1em; +} +.fa-pull-left { + float: left; +} +.fa-pull-right { + float: right; +} +.fa.fa-pull-left { + margin-right: .3em; +} +.fa.fa-pull-right { + margin-left: .3em; +} +/* Deprecated as of 4.4.0 */ +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.fa.pull-left { + margin-right: .3em; +} +.fa.pull-right { + margin-left: .3em; +} +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; +} +.fa-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); +} +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +.fa-rotate-90 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); +} +.fa-rotate-180 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} +.fa-rotate-270 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; + -webkit-transform: rotate(270deg); + -ms-transform: rotate(270deg); + transform: rotate(270deg); +} +.fa-flip-horizontal { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; + -webkit-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + transform: scale(-1, 1); +} +.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(1, -1); + -ms-transform: scale(1, -1); + transform: scale(1, -1); +} +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical { + filter: none; +} +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.fa-stack-1x, +.fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.fa-stack-1x { + line-height: inherit; +} +.fa-stack-2x { + font-size: 2em; +} +.fa-inverse { + color: #ffffff; +} +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ +.fa-glass:before { + content: "\f000"; +} +.fa-music:before { + content: "\f001"; +} +.fa-search:before { + content: "\f002"; +} +.fa-envelope-o:before { + content: "\f003"; +} +.fa-heart:before { + content: "\f004"; +} +.fa-star:before { + content: "\f005"; +} +.fa-star-o:before { + content: "\f006"; +} +.fa-user:before { + content: "\f007"; +} +.fa-film:before { + content: "\f008"; +} +.fa-th-large:before { + content: "\f009"; +} +.fa-th:before { + content: "\f00a"; +} +.fa-th-list:before { + content: "\f00b"; +} +.fa-check:before { + content: "\f00c"; +} +.fa-remove:before, +.fa-close:before, +.fa-times:before { + content: "\f00d"; +} +.fa-search-plus:before { + content: "\f00e"; +} +.fa-search-minus:before { + content: "\f010"; +} +.fa-power-off:before { + content: "\f011"; +} +.fa-signal:before { + content: "\f012"; +} +.fa-gear:before, +.fa-cog:before { + content: "\f013"; +} +.fa-trash-o:before { + content: "\f014"; +} +.fa-home:before { + content: "\f015"; +} +.fa-file-o:before { + content: "\f016"; +} +.fa-clock-o:before { + content: "\f017"; +} +.fa-road:before { + content: "\f018"; +} +.fa-download:before { + content: "\f019"; +} +.fa-arrow-circle-o-down:before { + content: "\f01a"; +} +.fa-arrow-circle-o-up:before { + content: "\f01b"; +} +.fa-inbox:before { + content: "\f01c"; +} +.fa-play-circle-o:before { + content: "\f01d"; +} +.fa-rotate-right:before, +.fa-repeat:before { + content: "\f01e"; +} +.fa-refresh:before { + content: "\f021"; +} +.fa-list-alt:before { + content: "\f022"; +} +.fa-lock:before { + content: "\f023"; +} +.fa-flag:before { + content: "\f024"; +} +.fa-headphones:before { + content: "\f025"; +} +.fa-volume-off:before { + content: "\f026"; +} +.fa-volume-down:before { + content: "\f027"; +} +.fa-volume-up:before { + content: "\f028"; +} +.fa-qrcode:before { + content: "\f029"; +} +.fa-barcode:before { + content: "\f02a"; +} +.fa-tag:before { + content: "\f02b"; +} +.fa-tags:before { + content: "\f02c"; +} +.fa-book:before { + content: "\f02d"; +} +.fa-bookmark:before { + content: "\f02e"; +} +.fa-print:before { + content: "\f02f"; +} +.fa-camera:before { + content: "\f030"; +} +.fa-font:before { + content: "\f031"; +} +.fa-bold:before { + content: "\f032"; +} +.fa-italic:before { + content: "\f033"; +} +.fa-text-height:before { + content: "\f034"; +} +.fa-text-width:before { + content: "\f035"; +} +.fa-align-left:before { + content: "\f036"; +} +.fa-align-center:before { + content: "\f037"; +} +.fa-align-right:before { + content: "\f038"; +} +.fa-align-justify:before { + content: "\f039"; +} +.fa-list:before { + content: "\f03a"; +} +.fa-dedent:before, +.fa-outdent:before { + content: "\f03b"; +} +.fa-indent:before { + content: "\f03c"; +} +.fa-video-camera:before { + content: "\f03d"; +} +.fa-photo:before, +.fa-image:before, +.fa-picture-o:before { + content: "\f03e"; +} +.fa-pencil:before { + content: "\f040"; +} +.fa-map-marker:before { + content: "\f041"; +} +.fa-adjust:before { + content: "\f042"; +} +.fa-tint:before { + content: "\f043"; +} +.fa-edit:before, +.fa-pencil-square-o:before { + content: "\f044"; +} +.fa-share-square-o:before { + content: "\f045"; +} +.fa-check-square-o:before { + content: "\f046"; +} +.fa-arrows:before { + content: "\f047"; +} +.fa-step-backward:before { + content: "\f048"; +} +.fa-fast-backward:before { + content: "\f049"; +} +.fa-backward:before { + content: "\f04a"; +} +.fa-play:before { + content: "\f04b"; +} +.fa-pause:before { + content: "\f04c"; +} +.fa-stop:before { + content: "\f04d"; +} +.fa-forward:before { + content: "\f04e"; +} +.fa-fast-forward:before { + content: "\f050"; +} +.fa-step-forward:before { + content: "\f051"; +} +.fa-eject:before { + content: "\f052"; +} +.fa-chevron-left:before { + content: "\f053"; +} +.fa-chevron-right:before { + content: "\f054"; +} +.fa-plus-circle:before { + content: "\f055"; +} +.fa-minus-circle:before { + content: "\f056"; +} +.fa-times-circle:before { + content: "\f057"; +} +.fa-check-circle:before { + content: "\f058"; +} +.fa-question-circle:before { + content: "\f059"; +} +.fa-info-circle:before { + content: "\f05a"; +} +.fa-crosshairs:before { + content: "\f05b"; +} +.fa-times-circle-o:before { + content: "\f05c"; +} +.fa-check-circle-o:before { + content: "\f05d"; +} +.fa-ban:before { + content: "\f05e"; +} +.fa-arrow-left:before { + content: "\f060"; +} +.fa-arrow-right:before { + content: "\f061"; +} +.fa-arrow-up:before { + content: "\f062"; +} +.fa-arrow-down:before { + content: "\f063"; +} +.fa-mail-forward:before, +.fa-share:before { + content: "\f064"; +} +.fa-expand:before { + content: "\f065"; +} +.fa-compress:before { + content: "\f066"; +} +.fa-plus:before { + content: "\f067"; +} +.fa-minus:before { + content: "\f068"; +} +.fa-asterisk:before { + content: "\f069"; +} +.fa-exclamation-circle:before { + content: "\f06a"; +} +.fa-gift:before { + content: "\f06b"; +} +.fa-leaf:before { + content: "\f06c"; +} +.fa-fire:before { + content: "\f06d"; +} +.fa-eye:before { + content: "\f06e"; +} +.fa-eye-slash:before { + content: "\f070"; +} +.fa-warning:before, +.fa-exclamation-triangle:before { + content: "\f071"; +} +.fa-plane:before { + content: "\f072"; +} +.fa-calendar:before { + content: "\f073"; +} +.fa-random:before { + content: "\f074"; +} +.fa-comment:before { + content: "\f075"; +} +.fa-magnet:before { + content: "\f076"; +} +.fa-chevron-up:before { + content: "\f077"; +} +.fa-chevron-down:before { + content: "\f078"; +} +.fa-retweet:before { + content: "\f079"; +} +.fa-shopping-cart:before { + content: "\f07a"; +} +.fa-folder:before { + content: "\f07b"; +} +.fa-folder-open:before { + content: "\f07c"; +} +.fa-arrows-v:before { + content: "\f07d"; +} +.fa-arrows-h:before { + content: "\f07e"; +} +.fa-bar-chart-o:before, +.fa-bar-chart:before { + content: "\f080"; +} +.fa-twitter-square:before { + content: "\f081"; +} +.fa-facebook-square:before { + content: "\f082"; +} +.fa-camera-retro:before { + content: "\f083"; +} +.fa-key:before { + content: "\f084"; +} +.fa-gears:before, +.fa-cogs:before { + content: "\f085"; +} +.fa-comments:before { + content: "\f086"; +} +.fa-thumbs-o-up:before { + content: "\f087"; +} +.fa-thumbs-o-down:before { + content: "\f088"; +} +.fa-star-half:before { + content: "\f089"; +} +.fa-heart-o:before { + content: "\f08a"; +} +.fa-sign-out:before { + content: "\f08b"; +} +.fa-linkedin-square:before { + content: "\f08c"; +} +.fa-thumb-tack:before { + content: "\f08d"; +} +.fa-external-link:before { + content: "\f08e"; +} +.fa-sign-in:before { + content: "\f090"; +} +.fa-trophy:before { + content: "\f091"; +} +.fa-github-square:before { + content: "\f092"; +} +.fa-upload:before { + content: "\f093"; +} +.fa-lemon-o:before { + content: "\f094"; +} +.fa-phone:before { + content: "\f095"; +} +.fa-square-o:before { + content: "\f096"; +} +.fa-bookmark-o:before { + content: "\f097"; +} +.fa-phone-square:before { + content: "\f098"; +} +.fa-twitter:before { + content: "\f099"; +} +.fa-facebook-f:before, +.fa-facebook:before { + content: "\f09a"; +} +.fa-github:before { + content: "\f09b"; +} +.fa-unlock:before { + content: "\f09c"; +} +.fa-credit-card:before { + content: "\f09d"; +} +.fa-feed:before, +.fa-rss:before { + content: "\f09e"; +} +.fa-hdd-o:before { + content: "\f0a0"; +} +.fa-bullhorn:before { + content: "\f0a1"; +} +.fa-bell:before { + content: "\f0f3"; +} +.fa-certificate:before { + content: "\f0a3"; +} +.fa-hand-o-right:before { + content: "\f0a4"; +} +.fa-hand-o-left:before { + content: "\f0a5"; +} +.fa-hand-o-up:before { + content: "\f0a6"; +} +.fa-hand-o-down:before { + content: "\f0a7"; +} +.fa-arrow-circle-left:before { + content: "\f0a8"; +} +.fa-arrow-circle-right:before { + content: "\f0a9"; +} +.fa-arrow-circle-up:before { + content: "\f0aa"; +} +.fa-arrow-circle-down:before { + content: "\f0ab"; +} +.fa-globe:before { + content: "\f0ac"; +} +.fa-wrench:before { + content: "\f0ad"; +} +.fa-tasks:before { + content: "\f0ae"; +} +.fa-filter:before { + content: "\f0b0"; +} +.fa-briefcase:before { + content: "\f0b1"; +} +.fa-arrows-alt:before { + content: "\f0b2"; +} +.fa-group:before, +.fa-users:before { + content: "\f0c0"; +} +.fa-chain:before, +.fa-link:before { + content: "\f0c1"; +} +.fa-cloud:before { + content: "\f0c2"; +} +.fa-flask:before { + content: "\f0c3"; +} +.fa-cut:before, +.fa-scissors:before { + content: "\f0c4"; +} +.fa-copy:before, +.fa-files-o:before { + content: "\f0c5"; +} +.fa-paperclip:before { + content: "\f0c6"; +} +.fa-save:before, +.fa-floppy-o:before { + content: "\f0c7"; +} +.fa-square:before { + content: "\f0c8"; +} +.fa-navicon:before, +.fa-reorder:before, +.fa-bars:before { + content: "\f0c9"; +} +.fa-list-ul:before { + content: "\f0ca"; +} +.fa-list-ol:before { + content: "\f0cb"; +} +.fa-strikethrough:before { + content: "\f0cc"; +} +.fa-underline:before { + content: "\f0cd"; +} +.fa-table:before { + content: "\f0ce"; +} +.fa-magic:before { + content: "\f0d0"; +} +.fa-truck:before { + content: "\f0d1"; +} +.fa-pinterest:before { + content: "\f0d2"; +} +.fa-pinterest-square:before { + content: "\f0d3"; +} +.fa-google-plus-square:before { + content: "\f0d4"; +} +.fa-google-plus:before { + content: "\f0d5"; +} +.fa-money:before { + content: "\f0d6"; +} +.fa-caret-down:before { + content: "\f0d7"; +} +.fa-caret-up:before { + content: "\f0d8"; +} +.fa-caret-left:before { + content: "\f0d9"; +} +.fa-caret-right:before { + content: "\f0da"; +} +.fa-columns:before { + content: "\f0db"; +} +.fa-unsorted:before, +.fa-sort:before { + content: "\f0dc"; +} +.fa-sort-down:before, +.fa-sort-desc:before { + content: "\f0dd"; +} +.fa-sort-up:before, +.fa-sort-asc:before { + content: "\f0de"; +} +.fa-envelope:before { + content: "\f0e0"; +} +.fa-linkedin:before { + content: "\f0e1"; +} +.fa-rotate-left:before, +.fa-undo:before { + content: "\f0e2"; +} +.fa-legal:before, +.fa-gavel:before { + content: "\f0e3"; +} +.fa-dashboard:before, +.fa-tachometer:before { + content: "\f0e4"; +} +.fa-comment-o:before { + content: "\f0e5"; +} +.fa-comments-o:before { + content: "\f0e6"; +} +.fa-flash:before, +.fa-bolt:before { + content: "\f0e7"; +} +.fa-sitemap:before { + content: "\f0e8"; +} +.fa-umbrella:before { + content: "\f0e9"; +} +.fa-paste:before, +.fa-clipboard:before { + content: "\f0ea"; +} +.fa-lightbulb-o:before { + content: "\f0eb"; +} +.fa-exchange:before { + content: "\f0ec"; +} +.fa-cloud-download:before { + content: "\f0ed"; +} +.fa-cloud-upload:before { + content: "\f0ee"; +} +.fa-user-md:before { + content: "\f0f0"; +} +.fa-stethoscope:before { + content: "\f0f1"; +} +.fa-suitcase:before { + content: "\f0f2"; +} +.fa-bell-o:before { + content: "\f0a2"; +} +.fa-coffee:before { + content: "\f0f4"; +} +.fa-cutlery:before { + content: "\f0f5"; +} +.fa-file-text-o:before { + content: "\f0f6"; +} +.fa-building-o:before { + content: "\f0f7"; +} +.fa-hospital-o:before { + content: "\f0f8"; +} +.fa-ambulance:before { + content: "\f0f9"; +} +.fa-medkit:before { + content: "\f0fa"; +} +.fa-fighter-jet:before { + content: "\f0fb"; +} +.fa-beer:before { + content: "\f0fc"; +} +.fa-h-square:before { + content: "\f0fd"; +} +.fa-plus-square:before { + content: "\f0fe"; +} +.fa-angle-double-left:before { + content: "\f100"; +} +.fa-angle-double-right:before { + content: "\f101"; +} +.fa-angle-double-up:before { + content: "\f102"; +} +.fa-angle-double-down:before { + content: "\f103"; +} +.fa-angle-left:before { + content: "\f104"; +} +.fa-angle-right:before { + content: "\f105"; +} +.fa-angle-up:before { + content: "\f106"; +} +.fa-angle-down:before { + content: "\f107"; +} +.fa-desktop:before { + content: "\f108"; +} +.fa-laptop:before { + content: "\f109"; +} +.fa-tablet:before { + content: "\f10a"; +} +.fa-mobile-phone:before, +.fa-mobile:before { + content: "\f10b"; +} +.fa-circle-o:before { + content: "\f10c"; +} +.fa-quote-left:before { + content: "\f10d"; +} +.fa-quote-right:before { + content: "\f10e"; +} +.fa-spinner:before { + content: "\f110"; +} +.fa-circle:before { + content: "\f111"; +} +.fa-mail-reply:before, +.fa-reply:before { + content: "\f112"; +} +.fa-github-alt:before { + content: "\f113"; +} +.fa-folder-o:before { + content: "\f114"; +} +.fa-folder-open-o:before { + content: "\f115"; +} +.fa-smile-o:before { + content: "\f118"; +} +.fa-frown-o:before { + content: "\f119"; +} +.fa-meh-o:before { + content: "\f11a"; +} +.fa-gamepad:before { + content: "\f11b"; +} +.fa-keyboard-o:before { + content: "\f11c"; +} +.fa-flag-o:before { + content: "\f11d"; +} +.fa-flag-checkered:before { + content: "\f11e"; +} +.fa-terminal:before { + content: "\f120"; +} +.fa-code:before { + content: "\f121"; +} +.fa-mail-reply-all:before, +.fa-reply-all:before { + content: "\f122"; +} +.fa-star-half-empty:before, +.fa-star-half-full:before, +.fa-star-half-o:before { + content: "\f123"; +} +.fa-location-arrow:before { + content: "\f124"; +} +.fa-crop:before { + content: "\f125"; +} +.fa-code-fork:before { + content: "\f126"; +} +.fa-unlink:before, +.fa-chain-broken:before { + content: "\f127"; +} +.fa-question:before { + content: "\f128"; +} +.fa-info:before { + content: "\f129"; +} +.fa-exclamation:before { + content: "\f12a"; +} +.fa-superscript:before { + content: "\f12b"; +} +.fa-subscript:before { + content: "\f12c"; +} +.fa-eraser:before { + content: "\f12d"; +} +.fa-puzzle-piece:before { + content: "\f12e"; +} +.fa-microphone:before { + content: "\f130"; +} +.fa-microphone-slash:before { + content: "\f131"; +} +.fa-shield:before { + content: "\f132"; +} +.fa-calendar-o:before { + content: "\f133"; +} +.fa-fire-extinguisher:before { + content: "\f134"; +} +.fa-rocket:before { + content: "\f135"; +} +.fa-maxcdn:before { + content: "\f136"; +} +.fa-chevron-circle-left:before { + content: "\f137"; +} +.fa-chevron-circle-right:before { + content: "\f138"; +} +.fa-chevron-circle-up:before { + content: "\f139"; +} +.fa-chevron-circle-down:before { + content: "\f13a"; +} +.fa-html5:before { + content: "\f13b"; +} +.fa-css3:before { + content: "\f13c"; +} +.fa-anchor:before { + content: "\f13d"; +} +.fa-unlock-alt:before { + content: "\f13e"; +} +.fa-bullseye:before { + content: "\f140"; +} +.fa-ellipsis-h:before { + content: "\f141"; +} +.fa-ellipsis-v:before { + content: "\f142"; +} +.fa-rss-square:before { + content: "\f143"; +} +.fa-play-circle:before { + content: "\f144"; +} +.fa-ticket:before { + content: "\f145"; +} +.fa-minus-square:before { + content: "\f146"; +} +.fa-minus-square-o:before { + content: "\f147"; +} +.fa-level-up:before { + content: "\f148"; +} +.fa-level-down:before { + content: "\f149"; +} +.fa-check-square:before { + content: "\f14a"; +} +.fa-pencil-square:before { + content: "\f14b"; +} +.fa-external-link-square:before { + content: "\f14c"; +} +.fa-share-square:before { + content: "\f14d"; +} +.fa-compass:before { + content: "\f14e"; +} +.fa-toggle-down:before, +.fa-caret-square-o-down:before { + content: "\f150"; +} +.fa-toggle-up:before, +.fa-caret-square-o-up:before { + content: "\f151"; +} +.fa-toggle-right:before, +.fa-caret-square-o-right:before { + content: "\f152"; +} +.fa-euro:before, +.fa-eur:before { + content: "\f153"; +} +.fa-gbp:before { + content: "\f154"; +} +.fa-dollar:before, +.fa-usd:before { + content: "\f155"; +} +.fa-rupee:before, +.fa-inr:before { + content: "\f156"; +} +.fa-cny:before, +.fa-rmb:before, +.fa-yen:before, +.fa-jpy:before { + content: "\f157"; +} +.fa-ruble:before, +.fa-rouble:before, +.fa-rub:before { + content: "\f158"; +} +.fa-won:before, +.fa-krw:before { + content: "\f159"; +} +.fa-bitcoin:before, +.fa-btc:before { + content: "\f15a"; +} +.fa-file:before { + content: "\f15b"; +} +.fa-file-text:before { + content: "\f15c"; +} +.fa-sort-alpha-asc:before { + content: "\f15d"; +} +.fa-sort-alpha-desc:before { + content: "\f15e"; +} +.fa-sort-amount-asc:before { + content: "\f160"; +} +.fa-sort-amount-desc:before { + content: "\f161"; +} +.fa-sort-numeric-asc:before { + content: "\f162"; +} +.fa-sort-numeric-desc:before { + content: "\f163"; +} +.fa-thumbs-up:before { + content: "\f164"; +} +.fa-thumbs-down:before { + content: "\f165"; +} +.fa-youtube-square:before { + content: "\f166"; +} +.fa-youtube:before { + content: "\f167"; +} +.fa-xing:before { + content: "\f168"; +} +.fa-xing-square:before { + content: "\f169"; +} +.fa-youtube-play:before { + content: "\f16a"; +} +.fa-dropbox:before { + content: "\f16b"; +} +.fa-stack-overflow:before { + content: "\f16c"; +} +.fa-instagram:before { + content: "\f16d"; +} +.fa-flickr:before { + content: "\f16e"; +} +.fa-adn:before { + content: "\f170"; +} +.fa-bitbucket:before { + content: "\f171"; +} +.fa-bitbucket-square:before { + content: "\f172"; +} +.fa-tumblr:before { + content: "\f173"; +} +.fa-tumblr-square:before { + content: "\f174"; +} +.fa-long-arrow-down:before { + content: "\f175"; +} +.fa-long-arrow-up:before { + content: "\f176"; +} +.fa-long-arrow-left:before { + content: "\f177"; +} +.fa-long-arrow-right:before { + content: "\f178"; +} +.fa-apple:before { + content: "\f179"; +} +.fa-windows:before { + content: "\f17a"; +} +.fa-android:before { + content: "\f17b"; +} +.fa-linux:before { + content: "\f17c"; +} +.fa-dribbble:before { + content: "\f17d"; +} +.fa-skype:before { + content: "\f17e"; +} +.fa-foursquare:before { + content: "\f180"; +} +.fa-trello:before { + content: "\f181"; +} +.fa-female:before { + content: "\f182"; +} +.fa-male:before { + content: "\f183"; +} +.fa-gittip:before, +.fa-gratipay:before { + content: "\f184"; +} +.fa-sun-o:before { + content: "\f185"; +} +.fa-moon-o:before { + content: "\f186"; +} +.fa-archive:before { + content: "\f187"; +} +.fa-bug:before { + content: "\f188"; +} +.fa-vk:before { + content: "\f189"; +} +.fa-weibo:before { + content: "\f18a"; +} +.fa-renren:before { + content: "\f18b"; +} +.fa-pagelines:before { + content: "\f18c"; +} +.fa-stack-exchange:before { + content: "\f18d"; +} +.fa-arrow-circle-o-right:before { + content: "\f18e"; +} +.fa-arrow-circle-o-left:before { + content: "\f190"; +} +.fa-toggle-left:before, +.fa-caret-square-o-left:before { + content: "\f191"; +} +.fa-dot-circle-o:before { + content: "\f192"; +} +.fa-wheelchair:before { + content: "\f193"; +} +.fa-vimeo-square:before { + content: "\f194"; +} +.fa-turkish-lira:before, +.fa-try:before { + content: "\f195"; +} +.fa-plus-square-o:before { + content: "\f196"; +} +.fa-space-shuttle:before { + content: "\f197"; +} +.fa-slack:before { + content: "\f198"; +} +.fa-envelope-square:before { + content: "\f199"; +} +.fa-wordpress:before { + content: "\f19a"; +} +.fa-openid:before { + content: "\f19b"; +} +.fa-institution:before, +.fa-bank:before, +.fa-university:before { + content: "\f19c"; +} +.fa-mortar-board:before, +.fa-graduation-cap:before { + content: "\f19d"; +} +.fa-yahoo:before { + content: "\f19e"; +} +.fa-google:before { + content: "\f1a0"; +} +.fa-reddit:before { + content: "\f1a1"; +} +.fa-reddit-square:before { + content: "\f1a2"; +} +.fa-stumbleupon-circle:before { + content: "\f1a3"; +} +.fa-stumbleupon:before { + content: "\f1a4"; +} +.fa-delicious:before { + content: "\f1a5"; +} +.fa-digg:before { + content: "\f1a6"; +} +.fa-pied-piper-pp:before { + content: "\f1a7"; +} +.fa-pied-piper-alt:before { + content: "\f1a8"; +} +.fa-drupal:before { + content: "\f1a9"; +} +.fa-joomla:before { + content: "\f1aa"; +} +.fa-language:before { + content: "\f1ab"; +} +.fa-fax:before { + content: "\f1ac"; +} +.fa-building:before { + content: "\f1ad"; +} +.fa-child:before { + content: "\f1ae"; +} +.fa-paw:before { + content: "\f1b0"; +} +.fa-spoon:before { + content: "\f1b1"; +} +.fa-cube:before { + content: "\f1b2"; +} +.fa-cubes:before { + content: "\f1b3"; +} +.fa-behance:before { + content: "\f1b4"; +} +.fa-behance-square:before { + content: "\f1b5"; +} +.fa-steam:before { + content: "\f1b6"; +} +.fa-steam-square:before { + content: "\f1b7"; +} +.fa-recycle:before { + content: "\f1b8"; +} +.fa-automobile:before, +.fa-car:before { + content: "\f1b9"; +} +.fa-cab:before, +.fa-taxi:before { + content: "\f1ba"; +} +.fa-tree:before { + content: "\f1bb"; +} +.fa-spotify:before { + content: "\f1bc"; +} +.fa-deviantart:before { + content: "\f1bd"; +} +.fa-soundcloud:before { + content: "\f1be"; +} +.fa-database:before { + content: "\f1c0"; +} +.fa-file-pdf-o:before { + content: "\f1c1"; +} +.fa-file-word-o:before { + content: "\f1c2"; +} +.fa-file-excel-o:before { + content: "\f1c3"; +} +.fa-file-powerpoint-o:before { + content: "\f1c4"; +} +.fa-file-photo-o:before, +.fa-file-picture-o:before, +.fa-file-image-o:before { + content: "\f1c5"; +} +.fa-file-zip-o:before, +.fa-file-archive-o:before { + content: "\f1c6"; +} +.fa-file-sound-o:before, +.fa-file-audio-o:before { + content: "\f1c7"; +} +.fa-file-movie-o:before, +.fa-file-video-o:before { + content: "\f1c8"; +} +.fa-file-code-o:before { + content: "\f1c9"; +} +.fa-vine:before { + content: "\f1ca"; +} +.fa-codepen:before { + content: "\f1cb"; +} +.fa-jsfiddle:before { + content: "\f1cc"; +} +.fa-life-bouy:before, +.fa-life-buoy:before, +.fa-life-saver:before, +.fa-support:before, +.fa-life-ring:before { + content: "\f1cd"; +} +.fa-circle-o-notch:before { + content: "\f1ce"; +} +.fa-ra:before, +.fa-resistance:before, +.fa-rebel:before { + content: "\f1d0"; +} +.fa-ge:before, +.fa-empire:before { + content: "\f1d1"; +} +.fa-git-square:before { + content: "\f1d2"; +} +.fa-git:before { + content: "\f1d3"; +} +.fa-y-combinator-square:before, +.fa-yc-square:before, +.fa-hacker-news:before { + content: "\f1d4"; +} +.fa-tencent-weibo:before { + content: "\f1d5"; +} +.fa-qq:before { + content: "\f1d6"; +} +.fa-wechat:before, +.fa-weixin:before { + content: "\f1d7"; +} +.fa-send:before, +.fa-paper-plane:before { + content: "\f1d8"; +} +.fa-send-o:before, +.fa-paper-plane-o:before { + content: "\f1d9"; +} +.fa-history:before { + content: "\f1da"; +} +.fa-circle-thin:before { + content: "\f1db"; +} +.fa-header:before { + content: "\f1dc"; +} +.fa-paragraph:before { + content: "\f1dd"; +} +.fa-sliders:before { + content: "\f1de"; +} +.fa-share-alt:before { + content: "\f1e0"; +} +.fa-share-alt-square:before { + content: "\f1e1"; +} +.fa-bomb:before { + content: "\f1e2"; +} +.fa-soccer-ball-o:before, +.fa-futbol-o:before { + content: "\f1e3"; +} +.fa-tty:before { + content: "\f1e4"; +} +.fa-binoculars:before { + content: "\f1e5"; +} +.fa-plug:before { + content: "\f1e6"; +} +.fa-slideshare:before { + content: "\f1e7"; +} +.fa-twitch:before { + content: "\f1e8"; +} +.fa-yelp:before { + content: "\f1e9"; +} +.fa-newspaper-o:before { + content: "\f1ea"; +} +.fa-wifi:before { + content: "\f1eb"; +} +.fa-calculator:before { + content: "\f1ec"; +} +.fa-paypal:before { + content: "\f1ed"; +} +.fa-google-wallet:before { + content: "\f1ee"; +} +.fa-cc-visa:before { + content: "\f1f0"; +} +.fa-cc-mastercard:before { + content: "\f1f1"; +} +.fa-cc-discover:before { + content: "\f1f2"; +} +.fa-cc-amex:before { + content: "\f1f3"; +} +.fa-cc-paypal:before { + content: "\f1f4"; +} +.fa-cc-stripe:before { + content: "\f1f5"; +} +.fa-bell-slash:before { + content: "\f1f6"; +} +.fa-bell-slash-o:before { + content: "\f1f7"; +} +.fa-trash:before { + content: "\f1f8"; +} +.fa-copyright:before { + content: "\f1f9"; +} +.fa-at:before { + content: "\f1fa"; +} +.fa-eyedropper:before { + content: "\f1fb"; +} +.fa-paint-brush:before { + content: "\f1fc"; +} +.fa-birthday-cake:before { + content: "\f1fd"; +} +.fa-area-chart:before { + content: "\f1fe"; +} +.fa-pie-chart:before { + content: "\f200"; +} +.fa-line-chart:before { + content: "\f201"; +} +.fa-lastfm:before { + content: "\f202"; +} +.fa-lastfm-square:before { + content: "\f203"; +} +.fa-toggle-off:before { + content: "\f204"; +} +.fa-toggle-on:before { + content: "\f205"; +} +.fa-bicycle:before { + content: "\f206"; +} +.fa-bus:before { + content: "\f207"; +} +.fa-ioxhost:before { + content: "\f208"; +} +.fa-angellist:before { + content: "\f209"; +} +.fa-cc:before { + content: "\f20a"; +} +.fa-shekel:before, +.fa-sheqel:before, +.fa-ils:before { + content: "\f20b"; +} +.fa-meanpath:before { + content: "\f20c"; +} +.fa-buysellads:before { + content: "\f20d"; +} +.fa-connectdevelop:before { + content: "\f20e"; +} +.fa-dashcube:before { + content: "\f210"; +} +.fa-forumbee:before { + content: "\f211"; +} +.fa-leanpub:before { + content: "\f212"; +} +.fa-sellsy:before { + content: "\f213"; +} +.fa-shirtsinbulk:before { + content: "\f214"; +} +.fa-simplybuilt:before { + content: "\f215"; +} +.fa-skyatlas:before { + content: "\f216"; +} +.fa-cart-plus:before { + content: "\f217"; +} +.fa-cart-arrow-down:before { + content: "\f218"; +} +.fa-diamond:before { + content: "\f219"; +} +.fa-ship:before { + content: "\f21a"; +} +.fa-user-secret:before { + content: "\f21b"; +} +.fa-motorcycle:before { + content: "\f21c"; +} +.fa-street-view:before { + content: "\f21d"; +} +.fa-heartbeat:before { + content: "\f21e"; +} +.fa-venus:before { + content: "\f221"; +} +.fa-mars:before { + content: "\f222"; +} +.fa-mercury:before { + content: "\f223"; +} +.fa-intersex:before, +.fa-transgender:before { + content: "\f224"; +} +.fa-transgender-alt:before { + content: "\f225"; +} +.fa-venus-double:before { + content: "\f226"; +} +.fa-mars-double:before { + content: "\f227"; +} +.fa-venus-mars:before { + content: "\f228"; +} +.fa-mars-stroke:before { + content: "\f229"; +} +.fa-mars-stroke-v:before { + content: "\f22a"; +} +.fa-mars-stroke-h:before { + content: "\f22b"; +} +.fa-neuter:before { + content: "\f22c"; +} +.fa-genderless:before { + content: "\f22d"; +} +.fa-facebook-official:before { + content: "\f230"; +} +.fa-pinterest-p:before { + content: "\f231"; +} +.fa-whatsapp:before { + content: "\f232"; +} +.fa-server:before { + content: "\f233"; +} +.fa-user-plus:before { + content: "\f234"; +} +.fa-user-times:before { + content: "\f235"; +} +.fa-hotel:before, +.fa-bed:before { + content: "\f236"; +} +.fa-viacoin:before { + content: "\f237"; +} +.fa-train:before { + content: "\f238"; +} +.fa-subway:before { + content: "\f239"; +} +.fa-medium:before { + content: "\f23a"; +} +.fa-yc:before, +.fa-y-combinator:before { + content: "\f23b"; +} +.fa-optin-monster:before { + content: "\f23c"; +} +.fa-opencart:before { + content: "\f23d"; +} +.fa-expeditedssl:before { + content: "\f23e"; +} +.fa-battery-4:before, +.fa-battery:before, +.fa-battery-full:before { + content: "\f240"; +} +.fa-battery-3:before, +.fa-battery-three-quarters:before { + content: "\f241"; +} +.fa-battery-2:before, +.fa-battery-half:before { + content: "\f242"; +} +.fa-battery-1:before, +.fa-battery-quarter:before { + content: "\f243"; +} +.fa-battery-0:before, +.fa-battery-empty:before { + content: "\f244"; +} +.fa-mouse-pointer:before { + content: "\f245"; +} +.fa-i-cursor:before { + content: "\f246"; +} +.fa-object-group:before { + content: "\f247"; +} +.fa-object-ungroup:before { + content: "\f248"; +} +.fa-sticky-note:before { + content: "\f249"; +} +.fa-sticky-note-o:before { + content: "\f24a"; +} +.fa-cc-jcb:before { + content: "\f24b"; +} +.fa-cc-diners-club:before { + content: "\f24c"; +} +.fa-clone:before { + content: "\f24d"; +} +.fa-balance-scale:before { + content: "\f24e"; +} +.fa-hourglass-o:before { + content: "\f250"; +} +.fa-hourglass-1:before, +.fa-hourglass-start:before { + content: "\f251"; +} +.fa-hourglass-2:before, +.fa-hourglass-half:before { + content: "\f252"; +} +.fa-hourglass-3:before, +.fa-hourglass-end:before { + content: "\f253"; +} +.fa-hourglass:before { + content: "\f254"; +} +.fa-hand-grab-o:before, +.fa-hand-rock-o:before { + content: "\f255"; +} +.fa-hand-stop-o:before, +.fa-hand-paper-o:before { + content: "\f256"; +} +.fa-hand-scissors-o:before { + content: "\f257"; +} +.fa-hand-lizard-o:before { + content: "\f258"; +} +.fa-hand-spock-o:before { + content: "\f259"; +} +.fa-hand-pointer-o:before { + content: "\f25a"; +} +.fa-hand-peace-o:before { + content: "\f25b"; +} +.fa-trademark:before { + content: "\f25c"; +} +.fa-registered:before { + content: "\f25d"; +} +.fa-creative-commons:before { + content: "\f25e"; +} +.fa-gg:before { + content: "\f260"; +} +.fa-gg-circle:before { + content: "\f261"; +} +.fa-tripadvisor:before { + content: "\f262"; +} +.fa-odnoklassniki:before { + content: "\f263"; +} +.fa-odnoklassniki-square:before { + content: "\f264"; +} +.fa-get-pocket:before { + content: "\f265"; +} +.fa-wikipedia-w:before { + content: "\f266"; +} +.fa-safari:before { + content: "\f267"; +} +.fa-chrome:before { + content: "\f268"; +} +.fa-firefox:before { + content: "\f269"; +} +.fa-opera:before { + content: "\f26a"; +} +.fa-internet-explorer:before { + content: "\f26b"; +} +.fa-tv:before, +.fa-television:before { + content: "\f26c"; +} +.fa-contao:before { + content: "\f26d"; +} +.fa-500px:before { + content: "\f26e"; +} +.fa-amazon:before { + content: "\f270"; +} +.fa-calendar-plus-o:before { + content: "\f271"; +} +.fa-calendar-minus-o:before { + content: "\f272"; +} +.fa-calendar-times-o:before { + content: "\f273"; +} +.fa-calendar-check-o:before { + content: "\f274"; +} +.fa-industry:before { + content: "\f275"; +} +.fa-map-pin:before { + content: "\f276"; +} +.fa-map-signs:before { + content: "\f277"; +} +.fa-map-o:before { + content: "\f278"; +} +.fa-map:before { + content: "\f279"; +} +.fa-commenting:before { + content: "\f27a"; +} +.fa-commenting-o:before { + content: "\f27b"; +} +.fa-houzz:before { + content: "\f27c"; +} +.fa-vimeo:before { + content: "\f27d"; +} +.fa-black-tie:before { + content: "\f27e"; +} +.fa-fonticons:before { + content: "\f280"; +} +.fa-reddit-alien:before { + content: "\f281"; +} +.fa-edge:before { + content: "\f282"; +} +.fa-credit-card-alt:before { + content: "\f283"; +} +.fa-codiepie:before { + content: "\f284"; +} +.fa-modx:before { + content: "\f285"; +} +.fa-fort-awesome:before { + content: "\f286"; +} +.fa-usb:before { + content: "\f287"; +} +.fa-product-hunt:before { + content: "\f288"; +} +.fa-mixcloud:before { + content: "\f289"; +} +.fa-scribd:before { + content: "\f28a"; +} +.fa-pause-circle:before { + content: "\f28b"; +} +.fa-pause-circle-o:before { + content: "\f28c"; +} +.fa-stop-circle:before { + content: "\f28d"; +} +.fa-stop-circle-o:before { + content: "\f28e"; +} +.fa-shopping-bag:before { + content: "\f290"; +} +.fa-shopping-basket:before { + content: "\f291"; +} +.fa-hashtag:before { + content: "\f292"; +} +.fa-bluetooth:before { + content: "\f293"; +} +.fa-bluetooth-b:before { + content: "\f294"; +} +.fa-percent:before { + content: "\f295"; +} +.fa-gitlab:before { + content: "\f296"; +} +.fa-wpbeginner:before { + content: "\f297"; +} +.fa-wpforms:before { + content: "\f298"; +} +.fa-envira:before { + content: "\f299"; +} +.fa-universal-access:before { + content: "\f29a"; +} +.fa-wheelchair-alt:before { + content: "\f29b"; +} +.fa-question-circle-o:before { + content: "\f29c"; +} +.fa-blind:before { + content: "\f29d"; +} +.fa-audio-description:before { + content: "\f29e"; +} +.fa-volume-control-phone:before { + content: "\f2a0"; +} +.fa-braille:before { + content: "\f2a1"; +} +.fa-assistive-listening-systems:before { + content: "\f2a2"; +} +.fa-asl-interpreting:before, +.fa-american-sign-language-interpreting:before { + content: "\f2a3"; +} +.fa-deafness:before, +.fa-hard-of-hearing:before, +.fa-deaf:before { + content: "\f2a4"; +} +.fa-glide:before { + content: "\f2a5"; +} +.fa-glide-g:before { + content: "\f2a6"; +} +.fa-signing:before, +.fa-sign-language:before { + content: "\f2a7"; +} +.fa-low-vision:before { + content: "\f2a8"; +} +.fa-viadeo:before { + content: "\f2a9"; +} +.fa-viadeo-square:before { + content: "\f2aa"; +} +.fa-snapchat:before { + content: "\f2ab"; +} +.fa-snapchat-ghost:before { + content: "\f2ac"; +} +.fa-snapchat-square:before { + content: "\f2ad"; +} +.fa-pied-piper:before { + content: "\f2ae"; +} +.fa-first-order:before { + content: "\f2b0"; +} +.fa-yoast:before { + content: "\f2b1"; +} +.fa-themeisle:before { + content: "\f2b2"; +} +.fa-google-plus-circle:before, +.fa-google-plus-official:before { + content: "\f2b3"; +} +.fa-fa:before, +.fa-font-awesome:before { + content: "\f2b4"; +} +.fa-handshake-o:before { + content: "\f2b5"; +} +.fa-envelope-open:before { + content: "\f2b6"; +} +.fa-envelope-open-o:before { + content: "\f2b7"; +} +.fa-linode:before { + content: "\f2b8"; +} +.fa-address-book:before { + content: "\f2b9"; +} +.fa-address-book-o:before { + content: "\f2ba"; +} +.fa-vcard:before, +.fa-address-card:before { + content: "\f2bb"; +} +.fa-vcard-o:before, +.fa-address-card-o:before { + content: "\f2bc"; +} +.fa-user-circle:before { + content: "\f2bd"; +} +.fa-user-circle-o:before { + content: "\f2be"; +} +.fa-user-o:before { + content: "\f2c0"; +} +.fa-id-badge:before { + content: "\f2c1"; +} +.fa-drivers-license:before, +.fa-id-card:before { + content: "\f2c2"; +} +.fa-drivers-license-o:before, +.fa-id-card-o:before { + content: "\f2c3"; +} +.fa-quora:before { + content: "\f2c4"; +} +.fa-free-code-camp:before { + content: "\f2c5"; +} +.fa-telegram:before { + content: "\f2c6"; +} +.fa-thermometer-4:before, +.fa-thermometer:before, +.fa-thermometer-full:before { + content: "\f2c7"; +} +.fa-thermometer-3:before, +.fa-thermometer-three-quarters:before { + content: "\f2c8"; +} +.fa-thermometer-2:before, +.fa-thermometer-half:before { + content: "\f2c9"; +} +.fa-thermometer-1:before, +.fa-thermometer-quarter:before { + content: "\f2ca"; +} +.fa-thermometer-0:before, +.fa-thermometer-empty:before { + content: "\f2cb"; +} +.fa-shower:before { + content: "\f2cc"; +} +.fa-bathtub:before, +.fa-s15:before, +.fa-bath:before { + content: "\f2cd"; +} +.fa-podcast:before { + content: "\f2ce"; +} +.fa-window-maximize:before { + content: "\f2d0"; +} +.fa-window-minimize:before { + content: "\f2d1"; +} +.fa-window-restore:before { + content: "\f2d2"; +} +.fa-times-rectangle:before, +.fa-window-close:before { + content: "\f2d3"; +} +.fa-times-rectangle-o:before, +.fa-window-close-o:before { + content: "\f2d4"; +} +.fa-bandcamp:before { + content: "\f2d5"; +} +.fa-grav:before { + content: "\f2d6"; +} +.fa-etsy:before { + content: "\f2d7"; +} +.fa-imdb:before { + content: "\f2d8"; +} +.fa-ravelry:before { + content: "\f2d9"; +} +.fa-eercast:before { + content: "\f2da"; +} +.fa-microchip:before { + content: "\f2db"; +} +.fa-snowflake-o:before { + content: "\f2dc"; +} +.fa-superpowers:before { + content: "\f2dd"; +} +.fa-wpexplorer:before { + content: "\f2de"; +} +.fa-meetup:before { + content: "\f2e0"; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} diff --git a/dashboard/src/assets/font-awesome/css/font-awesome.min.css b/dashboard/src/assets/font-awesome/css/font-awesome.min.css new file mode 100644 index 00000000..540440ce --- /dev/null +++ b/dashboard/src/assets/font-awesome/css/font-awesome.min.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/dashboard/src/assets/font-awesome/fonts/FontAwesome.otf b/dashboard/src/assets/font-awesome/fonts/FontAwesome.otf new file mode 100644 index 00000000..d26606bb Binary files /dev/null and b/dashboard/src/assets/font-awesome/fonts/FontAwesome.otf differ diff --git a/dashboard/src/assets/font-awesome/fonts/fontawesome-webfont.eot b/dashboard/src/assets/font-awesome/fonts/fontawesome-webfont.eot new file mode 100644 index 00000000..842237d2 Binary files /dev/null and b/dashboard/src/assets/font-awesome/fonts/fontawesome-webfont.eot differ diff --git a/dashboard/src/assets/font-awesome/fonts/fontawesome-webfont.svg b/dashboard/src/assets/font-awesome/fonts/fontawesome-webfont.svg new file mode 100644 index 00000000..855c845e --- /dev/null +++ b/dashboard/src/assets/font-awesome/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + + +Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016 + By ,,, +Copyright Dave Gandy 2016. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dashboard/src/assets/font-awesome/fonts/fontawesome-webfont.ttf b/dashboard/src/assets/font-awesome/fonts/fontawesome-webfont.ttf new file mode 100644 index 00000000..db49aab6 Binary files /dev/null and b/dashboard/src/assets/font-awesome/fonts/fontawesome-webfont.ttf differ diff --git a/dashboard/src/assets/font-awesome/fonts/fontawesome-webfont.woff b/dashboard/src/assets/font-awesome/fonts/fontawesome-webfont.woff new file mode 100644 index 00000000..bdbb569b Binary files /dev/null and b/dashboard/src/assets/font-awesome/fonts/fontawesome-webfont.woff differ diff --git a/dashboard/src/assets/font-awesome/fonts/fontawesome-webfont.woff2 b/dashboard/src/assets/font-awesome/fonts/fontawesome-webfont.woff2 new file mode 100644 index 00000000..8d830cf6 Binary files /dev/null and b/dashboard/src/assets/font-awesome/fonts/fontawesome-webfont.woff2 differ diff --git a/dashboard/src/assets/font-awesome/less/animated.less b/dashboard/src/assets/font-awesome/less/animated.less new file mode 100644 index 00000000..9ea48642 --- /dev/null +++ b/dashboard/src/assets/font-awesome/less/animated.less @@ -0,0 +1,50 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Animated Icons +// -------------------------- + +.@{fa-css-prefix}-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; +} + +.@{fa-css-prefix}-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); +} + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} diff --git a/dashboard/src/assets/font-awesome/less/bordered-pulled.less b/dashboard/src/assets/font-awesome/less/bordered-pulled.less new file mode 100644 index 00000000..360ea3d7 --- /dev/null +++ b/dashboard/src/assets/font-awesome/less/bordered-pulled.less @@ -0,0 +1,41 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Bordered & Pulled +// ------------------------- + +.@{fa-css-prefix}-border { + padding: .2em .25em .15em; + border: solid .08em @fa-border-color; + border-radius: .1em; +} + +.@{fa-css-prefix}-pull-left { float: left; } +.@{fa-css-prefix}-pull-right { float: right; } + +.@{fa-css-prefix} { + &.@{fa-css-prefix}-pull-left { margin-right: .3em; } + &.@{fa-css-prefix}-pull-right { margin-left: .3em; } +} + +/* Deprecated as of 4.4.0 */ +.pull-right { float: right; } +.pull-left { float: left; } + +.@{fa-css-prefix} { + &.pull-left { margin-right: .3em; } + &.pull-right { margin-left: .3em; } +} diff --git a/dashboard/src/assets/font-awesome/less/core.less b/dashboard/src/assets/font-awesome/less/core.less new file mode 100644 index 00000000..67dab32b --- /dev/null +++ b/dashboard/src/assets/font-awesome/less/core.less @@ -0,0 +1,28 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Base Class Definition +// ------------------------- + +.@{fa-css-prefix} { + display: inline-block; + font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration + font-size: inherit; // can't have font-size inherit on line above, so need to override + text-rendering: auto; // optimizelegibility throws things off #1094 + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + +} diff --git a/dashboard/src/assets/font-awesome/less/fixed-width.less b/dashboard/src/assets/font-awesome/less/fixed-width.less new file mode 100644 index 00000000..f7bf30dc --- /dev/null +++ b/dashboard/src/assets/font-awesome/less/fixed-width.less @@ -0,0 +1,22 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Fixed Width Icons +// ------------------------- +.@{fa-css-prefix}-fw { + width: (18em / 14); + text-align: center; +} diff --git a/dashboard/src/assets/font-awesome/less/font-awesome.less b/dashboard/src/assets/font-awesome/less/font-awesome.less new file mode 100644 index 00000000..0929a61e --- /dev/null +++ b/dashboard/src/assets/font-awesome/less/font-awesome.less @@ -0,0 +1,34 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ + +@import "variables.less"; +@import "mixins.less"; +@import "path.less"; +@import "core.less"; +@import "larger.less"; +@import "fixed-width.less"; +@import "list.less"; +@import "bordered-pulled.less"; +@import "animated.less"; +@import "rotated-flipped.less"; +@import "stacked.less"; +@import "icons.less"; +@import "screen-reader.less"; diff --git a/dashboard/src/assets/font-awesome/less/icons.less b/dashboard/src/assets/font-awesome/less/icons.less new file mode 100644 index 00000000..9c46902d --- /dev/null +++ b/dashboard/src/assets/font-awesome/less/icons.less @@ -0,0 +1,805 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ + +.@{fa-css-prefix}-glass:before { content: @fa-var-glass; } +.@{fa-css-prefix}-music:before { content: @fa-var-music; } +.@{fa-css-prefix}-search:before { content: @fa-var-search; } +.@{fa-css-prefix}-envelope-o:before { content: @fa-var-envelope-o; } +.@{fa-css-prefix}-heart:before { content: @fa-var-heart; } +.@{fa-css-prefix}-star:before { content: @fa-var-star; } +.@{fa-css-prefix}-star-o:before { content: @fa-var-star-o; } +.@{fa-css-prefix}-user:before { content: @fa-var-user; } +.@{fa-css-prefix}-film:before { content: @fa-var-film; } +.@{fa-css-prefix}-th-large:before { content: @fa-var-th-large; } +.@{fa-css-prefix}-th:before { content: @fa-var-th; } +.@{fa-css-prefix}-th-list:before { content: @fa-var-th-list; } +.@{fa-css-prefix}-check:before { content: @fa-var-check; } +.@{fa-css-prefix}-remove:before, +.@{fa-css-prefix}-close:before, +.@{fa-css-prefix}-times:before { content: @fa-var-times; } +.@{fa-css-prefix}-search-plus:before { content: @fa-var-search-plus; } +.@{fa-css-prefix}-search-minus:before { content: @fa-var-search-minus; } +.@{fa-css-prefix}-power-off:before { content: @fa-var-power-off; } +.@{fa-css-prefix}-signal:before { content: @fa-var-signal; } +.@{fa-css-prefix}-gear:before, +.@{fa-css-prefix}-cog:before { content: @fa-var-cog; } +.@{fa-css-prefix}-trash-o:before { content: @fa-var-trash-o; } +.@{fa-css-prefix}-home:before { content: @fa-var-home; } +.@{fa-css-prefix}-file-o:before { content: @fa-var-file-o; } +.@{fa-css-prefix}-clock-o:before { content: @fa-var-clock-o; } +.@{fa-css-prefix}-road:before { content: @fa-var-road; } +.@{fa-css-prefix}-download:before { content: @fa-var-download; } +.@{fa-css-prefix}-arrow-circle-o-down:before { content: @fa-var-arrow-circle-o-down; } +.@{fa-css-prefix}-arrow-circle-o-up:before { content: @fa-var-arrow-circle-o-up; } +.@{fa-css-prefix}-inbox:before { content: @fa-var-inbox; } +.@{fa-css-prefix}-play-circle-o:before { content: @fa-var-play-circle-o; } +.@{fa-css-prefix}-rotate-right:before, +.@{fa-css-prefix}-repeat:before { content: @fa-var-repeat; } +.@{fa-css-prefix}-refresh:before { content: @fa-var-refresh; } +.@{fa-css-prefix}-list-alt:before { content: @fa-var-list-alt; } +.@{fa-css-prefix}-lock:before { content: @fa-var-lock; } +.@{fa-css-prefix}-flag:before { content: @fa-var-flag; } +.@{fa-css-prefix}-headphones:before { content: @fa-var-headphones; } +.@{fa-css-prefix}-volume-off:before { content: @fa-var-volume-off; } +.@{fa-css-prefix}-volume-down:before { content: @fa-var-volume-down; } +.@{fa-css-prefix}-volume-up:before { content: @fa-var-volume-up; } +.@{fa-css-prefix}-qrcode:before { content: @fa-var-qrcode; } +.@{fa-css-prefix}-barcode:before { content: @fa-var-barcode; } +.@{fa-css-prefix}-tag:before { content: @fa-var-tag; } +.@{fa-css-prefix}-tags:before { content: @fa-var-tags; } +.@{fa-css-prefix}-book:before { content: @fa-var-book; } +.@{fa-css-prefix}-bookmark:before { content: @fa-var-bookmark; } +.@{fa-css-prefix}-print:before { content: @fa-var-print; } +.@{fa-css-prefix}-camera:before { content: @fa-var-camera; } +.@{fa-css-prefix}-font:before { content: @fa-var-font; } +.@{fa-css-prefix}-bold:before { content: @fa-var-bold; } +.@{fa-css-prefix}-italic:before { content: @fa-var-italic; } +.@{fa-css-prefix}-text-height:before { content: @fa-var-text-height; } +.@{fa-css-prefix}-text-width:before { content: @fa-var-text-width; } +.@{fa-css-prefix}-align-left:before { content: @fa-var-align-left; } +.@{fa-css-prefix}-align-center:before { content: @fa-var-align-center; } +.@{fa-css-prefix}-align-right:before { content: @fa-var-align-right; } +.@{fa-css-prefix}-align-justify:before { content: @fa-var-align-justify; } +.@{fa-css-prefix}-list:before { content: @fa-var-list; } +.@{fa-css-prefix}-dedent:before, +.@{fa-css-prefix}-outdent:before { content: @fa-var-outdent; } +.@{fa-css-prefix}-indent:before { content: @fa-var-indent; } +.@{fa-css-prefix}-video-camera:before { content: @fa-var-video-camera; } +.@{fa-css-prefix}-photo:before, +.@{fa-css-prefix}-image:before, +.@{fa-css-prefix}-picture-o:before { content: @fa-var-picture-o; } +.@{fa-css-prefix}-pencil:before { content: @fa-var-pencil; } +.@{fa-css-prefix}-map-marker:before { content: @fa-var-map-marker; } +.@{fa-css-prefix}-adjust:before { content: @fa-var-adjust; } +.@{fa-css-prefix}-tint:before { content: @fa-var-tint; } +.@{fa-css-prefix}-edit:before, +.@{fa-css-prefix}-pencil-square-o:before { content: @fa-var-pencil-square-o; } +.@{fa-css-prefix}-share-square-o:before { content: @fa-var-share-square-o; } +.@{fa-css-prefix}-check-square-o:before { content: @fa-var-check-square-o; } +.@{fa-css-prefix}-arrows:before { content: @fa-var-arrows; } +.@{fa-css-prefix}-step-backward:before { content: @fa-var-step-backward; } +.@{fa-css-prefix}-fast-backward:before { content: @fa-var-fast-backward; } +.@{fa-css-prefix}-backward:before { content: @fa-var-backward; } +.@{fa-css-prefix}-play:before { content: @fa-var-play; } +.@{fa-css-prefix}-pause:before { content: @fa-var-pause; } +.@{fa-css-prefix}-stop:before { content: @fa-var-stop; } +.@{fa-css-prefix}-forward:before { content: @fa-var-forward; } +.@{fa-css-prefix}-fast-forward:before { content: @fa-var-fast-forward; } +.@{fa-css-prefix}-step-forward:before { content: @fa-var-step-forward; } +.@{fa-css-prefix}-eject:before { content: @fa-var-eject; } +.@{fa-css-prefix}-chevron-left:before { content: @fa-var-chevron-left; } +.@{fa-css-prefix}-chevron-right:before { content: @fa-var-chevron-right; } +.@{fa-css-prefix}-plus-circle:before { content: @fa-var-plus-circle; } +.@{fa-css-prefix}-minus-circle:before { content: @fa-var-minus-circle; } +.@{fa-css-prefix}-times-circle:before { content: @fa-var-times-circle; } +.@{fa-css-prefix}-check-circle:before { content: @fa-var-check-circle; } +.@{fa-css-prefix}-question-circle:before { content: @fa-var-question-circle; } +.@{fa-css-prefix}-info-circle:before { content: @fa-var-info-circle; } +.@{fa-css-prefix}-crosshairs:before { content: @fa-var-crosshairs; } +.@{fa-css-prefix}-times-circle-o:before { content: @fa-var-times-circle-o; } +.@{fa-css-prefix}-check-circle-o:before { content: @fa-var-check-circle-o; } +.@{fa-css-prefix}-ban:before { content: @fa-var-ban; } +.@{fa-css-prefix}-arrow-left:before { content: @fa-var-arrow-left; } +.@{fa-css-prefix}-arrow-right:before { content: @fa-var-arrow-right; } +.@{fa-css-prefix}-arrow-up:before { content: @fa-var-arrow-up; } +.@{fa-css-prefix}-arrow-down:before { content: @fa-var-arrow-down; } +.@{fa-css-prefix}-mail-forward:before, +.@{fa-css-prefix}-share:before { content: @fa-var-share; } +.@{fa-css-prefix}-expand:before { content: @fa-var-expand; } +.@{fa-css-prefix}-compress:before { content: @fa-var-compress; } +.@{fa-css-prefix}-plus:before { content: @fa-var-plus; } +.@{fa-css-prefix}-minus:before { content: @fa-var-minus; } +.@{fa-css-prefix}-asterisk:before { content: @fa-var-asterisk; } +.@{fa-css-prefix}-exclamation-circle:before { content: @fa-var-exclamation-circle; } +.@{fa-css-prefix}-gift:before { content: @fa-var-gift; } +.@{fa-css-prefix}-leaf:before { content: @fa-var-leaf; } +.@{fa-css-prefix}-fire:before { content: @fa-var-fire; } +.@{fa-css-prefix}-eye:before { content: @fa-var-eye; } +.@{fa-css-prefix}-eye-slash:before { content: @fa-var-eye-slash; } +.@{fa-css-prefix}-warning:before, +.@{fa-css-prefix}-exclamation-triangle:before { content: @fa-var-exclamation-triangle; } +.@{fa-css-prefix}-plane:before { content: @fa-var-plane; } +.@{fa-css-prefix}-calendar:before { content: @fa-var-calendar; } +.@{fa-css-prefix}-random:before { content: @fa-var-random; } +.@{fa-css-prefix}-comment:before { content: @fa-var-comment; } +.@{fa-css-prefix}-magnet:before { content: @fa-var-magnet; } +.@{fa-css-prefix}-chevron-up:before { content: @fa-var-chevron-up; } +.@{fa-css-prefix}-chevron-down:before { content: @fa-var-chevron-down; } +.@{fa-css-prefix}-retweet:before { content: @fa-var-retweet; } +.@{fa-css-prefix}-shopping-cart:before { content: @fa-var-shopping-cart; } +.@{fa-css-prefix}-folder:before { content: @fa-var-folder; } +.@{fa-css-prefix}-folder-open:before { content: @fa-var-folder-open; } +.@{fa-css-prefix}-arrows-v:before { content: @fa-var-arrows-v; } +.@{fa-css-prefix}-arrows-h:before { content: @fa-var-arrows-h; } +.@{fa-css-prefix}-bar-chart-o:before, +.@{fa-css-prefix}-bar-chart:before { content: @fa-var-bar-chart; } +.@{fa-css-prefix}-twitter-square:before { content: @fa-var-twitter-square; } +.@{fa-css-prefix}-facebook-square:before { content: @fa-var-facebook-square; } +.@{fa-css-prefix}-camera-retro:before { content: @fa-var-camera-retro; } +.@{fa-css-prefix}-key:before { content: @fa-var-key; } +.@{fa-css-prefix}-gears:before, +.@{fa-css-prefix}-cogs:before { content: @fa-var-cogs; } +.@{fa-css-prefix}-comments:before { content: @fa-var-comments; } +.@{fa-css-prefix}-thumbs-o-up:before { content: @fa-var-thumbs-o-up; } +.@{fa-css-prefix}-thumbs-o-down:before { content: @fa-var-thumbs-o-down; } +.@{fa-css-prefix}-star-half:before { content: @fa-var-star-half; } +.@{fa-css-prefix}-heart-o:before { content: @fa-var-heart-o; } +.@{fa-css-prefix}-sign-out:before { content: @fa-var-sign-out; } +.@{fa-css-prefix}-linkedin-square:before { content: @fa-var-linkedin-square; } +.@{fa-css-prefix}-thumb-tack:before { content: @fa-var-thumb-tack; } +.@{fa-css-prefix}-external-link:before { content: @fa-var-external-link; } +.@{fa-css-prefix}-sign-in:before { content: @fa-var-sign-in; } +.@{fa-css-prefix}-trophy:before { content: @fa-var-trophy; } +.@{fa-css-prefix}-github-square:before { content: @fa-var-github-square; } +.@{fa-css-prefix}-upload:before { content: @fa-var-upload; } +.@{fa-css-prefix}-lemon-o:before { content: @fa-var-lemon-o; } +.@{fa-css-prefix}-phone:before { content: @fa-var-phone; } +.@{fa-css-prefix}-square-o:before { content: @fa-var-square-o; } +.@{fa-css-prefix}-bookmark-o:before { content: @fa-var-bookmark-o; } +.@{fa-css-prefix}-phone-square:before { content: @fa-var-phone-square; } +.@{fa-css-prefix}-twitter:before { content: @fa-var-twitter; } +.@{fa-css-prefix}-facebook-f:before, +.@{fa-css-prefix}-facebook:before { content: @fa-var-facebook; } +.@{fa-css-prefix}-github:before { content: @fa-var-github; } +.@{fa-css-prefix}-unlock:before { content: @fa-var-unlock; } +.@{fa-css-prefix}-credit-card:before { content: @fa-var-credit-card; } +.@{fa-css-prefix}-feed:before, +.@{fa-css-prefix}-rss:before { content: @fa-var-rss; } +.@{fa-css-prefix}-hdd-o:before { content: @fa-var-hdd-o; } +.@{fa-css-prefix}-bullhorn:before { content: @fa-var-bullhorn; } +.@{fa-css-prefix}-bell:before { content: @fa-var-bell; } +.@{fa-css-prefix}-certificate:before { content: @fa-var-certificate; } +.@{fa-css-prefix}-hand-o-right:before { content: @fa-var-hand-o-right; } +.@{fa-css-prefix}-hand-o-left:before { content: @fa-var-hand-o-left; } +.@{fa-css-prefix}-hand-o-up:before { content: @fa-var-hand-o-up; } +.@{fa-css-prefix}-hand-o-down:before { content: @fa-var-hand-o-down; } +.@{fa-css-prefix}-arrow-circle-left:before { content: @fa-var-arrow-circle-left; } +.@{fa-css-prefix}-arrow-circle-right:before { content: @fa-var-arrow-circle-right; } +.@{fa-css-prefix}-arrow-circle-up:before { content: @fa-var-arrow-circle-up; } +.@{fa-css-prefix}-arrow-circle-down:before { content: @fa-var-arrow-circle-down; } +.@{fa-css-prefix}-globe:before { content: @fa-var-globe; } +.@{fa-css-prefix}-wrench:before { content: @fa-var-wrench; } +.@{fa-css-prefix}-tasks:before { content: @fa-var-tasks; } +.@{fa-css-prefix}-filter:before { content: @fa-var-filter; } +.@{fa-css-prefix}-briefcase:before { content: @fa-var-briefcase; } +.@{fa-css-prefix}-arrows-alt:before { content: @fa-var-arrows-alt; } +.@{fa-css-prefix}-group:before, +.@{fa-css-prefix}-users:before { content: @fa-var-users; } +.@{fa-css-prefix}-chain:before, +.@{fa-css-prefix}-link:before { content: @fa-var-link; } +.@{fa-css-prefix}-cloud:before { content: @fa-var-cloud; } +.@{fa-css-prefix}-flask:before { content: @fa-var-flask; } +.@{fa-css-prefix}-cut:before, +.@{fa-css-prefix}-scissors:before { content: @fa-var-scissors; } +.@{fa-css-prefix}-copy:before, +.@{fa-css-prefix}-files-o:before { content: @fa-var-files-o; } +.@{fa-css-prefix}-paperclip:before { content: @fa-var-paperclip; } +.@{fa-css-prefix}-save:before, +.@{fa-css-prefix}-floppy-o:before { content: @fa-var-floppy-o; } +.@{fa-css-prefix}-square:before { content: @fa-var-square; } +.@{fa-css-prefix}-navicon:before, +.@{fa-css-prefix}-reorder:before, +.@{fa-css-prefix}-bars:before { content: @fa-var-bars; } +.@{fa-css-prefix}-list-ul:before { content: @fa-var-list-ul; } +.@{fa-css-prefix}-list-ol:before { content: @fa-var-list-ol; } +.@{fa-css-prefix}-strikethrough:before { content: @fa-var-strikethrough; } +.@{fa-css-prefix}-underline:before { content: @fa-var-underline; } +.@{fa-css-prefix}-table:before { content: @fa-var-table; } +.@{fa-css-prefix}-magic:before { content: @fa-var-magic; } +.@{fa-css-prefix}-truck:before { content: @fa-var-truck; } +.@{fa-css-prefix}-pinterest:before { content: @fa-var-pinterest; } +.@{fa-css-prefix}-pinterest-square:before { content: @fa-var-pinterest-square; } +.@{fa-css-prefix}-google-plus-square:before { content: @fa-var-google-plus-square; } +.@{fa-css-prefix}-google-plus:before { content: @fa-var-google-plus; } +.@{fa-css-prefix}-money:before { content: @fa-var-money; } +.@{fa-css-prefix}-caret-down:before { content: @fa-var-caret-down; } +.@{fa-css-prefix}-caret-up:before { content: @fa-var-caret-up; } +.@{fa-css-prefix}-caret-left:before { content: @fa-var-caret-left; } +.@{fa-css-prefix}-caret-right:before { content: @fa-var-caret-right; } +.@{fa-css-prefix}-columns:before { content: @fa-var-columns; } +.@{fa-css-prefix}-unsorted:before, +.@{fa-css-prefix}-sort:before { content: @fa-var-sort; } +.@{fa-css-prefix}-sort-down:before, +.@{fa-css-prefix}-sort-desc:before { content: @fa-var-sort-desc; } +.@{fa-css-prefix}-sort-up:before, +.@{fa-css-prefix}-sort-asc:before { content: @fa-var-sort-asc; } +.@{fa-css-prefix}-envelope:before { content: @fa-var-envelope; } +.@{fa-css-prefix}-linkedin:before { content: @fa-var-linkedin; } +.@{fa-css-prefix}-rotate-left:before, +.@{fa-css-prefix}-undo:before { content: @fa-var-undo; } +.@{fa-css-prefix}-legal:before, +.@{fa-css-prefix}-gavel:before { content: @fa-var-gavel; } +.@{fa-css-prefix}-dashboard:before, +.@{fa-css-prefix}-tachometer:before { content: @fa-var-tachometer; } +.@{fa-css-prefix}-comment-o:before { content: @fa-var-comment-o; } +.@{fa-css-prefix}-comments-o:before { content: @fa-var-comments-o; } +.@{fa-css-prefix}-flash:before, +.@{fa-css-prefix}-bolt:before { content: @fa-var-bolt; } +.@{fa-css-prefix}-sitemap:before { content: @fa-var-sitemap; } +.@{fa-css-prefix}-umbrella:before { content: @fa-var-umbrella; } +.@{fa-css-prefix}-paste:before, +.@{fa-css-prefix}-clipboard:before { content: @fa-var-clipboard; } +.@{fa-css-prefix}-lightbulb-o:before { content: @fa-var-lightbulb-o; } +.@{fa-css-prefix}-exchange:before { content: @fa-var-exchange; } +.@{fa-css-prefix}-cloud-download:before { content: @fa-var-cloud-download; } +.@{fa-css-prefix}-cloud-upload:before { content: @fa-var-cloud-upload; } +.@{fa-css-prefix}-user-md:before { content: @fa-var-user-md; } +.@{fa-css-prefix}-stethoscope:before { content: @fa-var-stethoscope; } +.@{fa-css-prefix}-suitcase:before { content: @fa-var-suitcase; } +.@{fa-css-prefix}-bell-o:before { content: @fa-var-bell-o; } +.@{fa-css-prefix}-coffee:before { content: @fa-var-coffee; } +.@{fa-css-prefix}-cutlery:before { content: @fa-var-cutlery; } +.@{fa-css-prefix}-file-text-o:before { content: @fa-var-file-text-o; } +.@{fa-css-prefix}-building-o:before { content: @fa-var-building-o; } +.@{fa-css-prefix}-hospital-o:before { content: @fa-var-hospital-o; } +.@{fa-css-prefix}-ambulance:before { content: @fa-var-ambulance; } +.@{fa-css-prefix}-medkit:before { content: @fa-var-medkit; } +.@{fa-css-prefix}-fighter-jet:before { content: @fa-var-fighter-jet; } +.@{fa-css-prefix}-beer:before { content: @fa-var-beer; } +.@{fa-css-prefix}-h-square:before { content: @fa-var-h-square; } +.@{fa-css-prefix}-plus-square:before { content: @fa-var-plus-square; } +.@{fa-css-prefix}-angle-double-left:before { content: @fa-var-angle-double-left; } +.@{fa-css-prefix}-angle-double-right:before { content: @fa-var-angle-double-right; } +.@{fa-css-prefix}-angle-double-up:before { content: @fa-var-angle-double-up; } +.@{fa-css-prefix}-angle-double-down:before { content: @fa-var-angle-double-down; } +.@{fa-css-prefix}-angle-left:before { content: @fa-var-angle-left; } +.@{fa-css-prefix}-angle-right:before { content: @fa-var-angle-right; } +.@{fa-css-prefix}-angle-up:before { content: @fa-var-angle-up; } +.@{fa-css-prefix}-angle-down:before { content: @fa-var-angle-down; } +.@{fa-css-prefix}-desktop:before { content: @fa-var-desktop; } +.@{fa-css-prefix}-laptop:before { content: @fa-var-laptop; } +.@{fa-css-prefix}-tablet:before { content: @fa-var-tablet; } +.@{fa-css-prefix}-mobile-phone:before, +.@{fa-css-prefix}-mobile:before { content: @fa-var-mobile; } +.@{fa-css-prefix}-circle-o:before { content: @fa-var-circle-o; } +.@{fa-css-prefix}-quote-left:before { content: @fa-var-quote-left; } +.@{fa-css-prefix}-quote-right:before { content: @fa-var-quote-right; } +.@{fa-css-prefix}-spinner:before { content: @fa-var-spinner; } +.@{fa-css-prefix}-circle:before { content: @fa-var-circle; } +.@{fa-css-prefix}-mail-reply:before, +.@{fa-css-prefix}-reply:before { content: @fa-var-reply; } +.@{fa-css-prefix}-github-alt:before { content: @fa-var-github-alt; } +.@{fa-css-prefix}-folder-o:before { content: @fa-var-folder-o; } +.@{fa-css-prefix}-folder-open-o:before { content: @fa-var-folder-open-o; } +.@{fa-css-prefix}-smile-o:before { content: @fa-var-smile-o; } +.@{fa-css-prefix}-frown-o:before { content: @fa-var-frown-o; } +.@{fa-css-prefix}-meh-o:before { content: @fa-var-meh-o; } +.@{fa-css-prefix}-gamepad:before { content: @fa-var-gamepad; } +.@{fa-css-prefix}-keyboard-o:before { content: @fa-var-keyboard-o; } +.@{fa-css-prefix}-flag-o:before { content: @fa-var-flag-o; } +.@{fa-css-prefix}-flag-checkered:before { content: @fa-var-flag-checkered; } +.@{fa-css-prefix}-terminal:before { content: @fa-var-terminal; } +.@{fa-css-prefix}-code:before { content: @fa-var-code; } +.@{fa-css-prefix}-mail-reply-all:before, +.@{fa-css-prefix}-reply-all:before { content: @fa-var-reply-all; } +.@{fa-css-prefix}-star-half-empty:before, +.@{fa-css-prefix}-star-half-full:before, +.@{fa-css-prefix}-star-half-o:before { content: @fa-var-star-half-o; } +.@{fa-css-prefix}-location-arrow:before { content: @fa-var-location-arrow; } +.@{fa-css-prefix}-crop:before { content: @fa-var-crop; } +.@{fa-css-prefix}-code-fork:before { content: @fa-var-code-fork; } +.@{fa-css-prefix}-unlink:before, +.@{fa-css-prefix}-chain-broken:before { content: @fa-var-chain-broken; } +.@{fa-css-prefix}-question:before { content: @fa-var-question; } +.@{fa-css-prefix}-info:before { content: @fa-var-info; } +.@{fa-css-prefix}-exclamation:before { content: @fa-var-exclamation; } +.@{fa-css-prefix}-superscript:before { content: @fa-var-superscript; } +.@{fa-css-prefix}-subscript:before { content: @fa-var-subscript; } +.@{fa-css-prefix}-eraser:before { content: @fa-var-eraser; } +.@{fa-css-prefix}-puzzle-piece:before { content: @fa-var-puzzle-piece; } +.@{fa-css-prefix}-microphone:before { content: @fa-var-microphone; } +.@{fa-css-prefix}-microphone-slash:before { content: @fa-var-microphone-slash; } +.@{fa-css-prefix}-shield:before { content: @fa-var-shield; } +.@{fa-css-prefix}-calendar-o:before { content: @fa-var-calendar-o; } +.@{fa-css-prefix}-fire-extinguisher:before { content: @fa-var-fire-extinguisher; } +.@{fa-css-prefix}-rocket:before { content: @fa-var-rocket; } +.@{fa-css-prefix}-maxcdn:before { content: @fa-var-maxcdn; } +.@{fa-css-prefix}-chevron-circle-left:before { content: @fa-var-chevron-circle-left; } +.@{fa-css-prefix}-chevron-circle-right:before { content: @fa-var-chevron-circle-right; } +.@{fa-css-prefix}-chevron-circle-up:before { content: @fa-var-chevron-circle-up; } +.@{fa-css-prefix}-chevron-circle-down:before { content: @fa-var-chevron-circle-down; } +.@{fa-css-prefix}-html5:before { content: @fa-var-html5; } +.@{fa-css-prefix}-css3:before { content: @fa-var-css3; } +.@{fa-css-prefix}-anchor:before { content: @fa-var-anchor; } +.@{fa-css-prefix}-unlock-alt:before { content: @fa-var-unlock-alt; } +.@{fa-css-prefix}-bullseye:before { content: @fa-var-bullseye; } +.@{fa-css-prefix}-ellipsis-h:before { content: @fa-var-ellipsis-h; } +.@{fa-css-prefix}-ellipsis-v:before { content: @fa-var-ellipsis-v; } +.@{fa-css-prefix}-rss-square:before { content: @fa-var-rss-square; } +.@{fa-css-prefix}-play-circle:before { content: @fa-var-play-circle; } +.@{fa-css-prefix}-ticket:before { content: @fa-var-ticket; } +.@{fa-css-prefix}-minus-square:before { content: @fa-var-minus-square; } +.@{fa-css-prefix}-minus-square-o:before { content: @fa-var-minus-square-o; } +.@{fa-css-prefix}-level-up:before { content: @fa-var-level-up; } +.@{fa-css-prefix}-level-down:before { content: @fa-var-level-down; } +.@{fa-css-prefix}-check-square:before { content: @fa-var-check-square; } +.@{fa-css-prefix}-pencil-square:before { content: @fa-var-pencil-square; } +.@{fa-css-prefix}-external-link-square:before { content: @fa-var-external-link-square; } +.@{fa-css-prefix}-share-square:before { content: @fa-var-share-square; } +.@{fa-css-prefix}-compass:before { content: @fa-var-compass; } +.@{fa-css-prefix}-toggle-down:before, +.@{fa-css-prefix}-caret-square-o-down:before { content: @fa-var-caret-square-o-down; } +.@{fa-css-prefix}-toggle-up:before, +.@{fa-css-prefix}-caret-square-o-up:before { content: @fa-var-caret-square-o-up; } +.@{fa-css-prefix}-toggle-right:before, +.@{fa-css-prefix}-caret-square-o-right:before { content: @fa-var-caret-square-o-right; } +.@{fa-css-prefix}-euro:before, +.@{fa-css-prefix}-eur:before { content: @fa-var-eur; } +.@{fa-css-prefix}-gbp:before { content: @fa-var-gbp; } +.@{fa-css-prefix}-dollar:before, +.@{fa-css-prefix}-usd:before { content: @fa-var-usd; } +.@{fa-css-prefix}-rupee:before, +.@{fa-css-prefix}-inr:before { content: @fa-var-inr; } +.@{fa-css-prefix}-cny:before, +.@{fa-css-prefix}-rmb:before, +.@{fa-css-prefix}-yen:before, +.@{fa-css-prefix}-jpy:before { content: @fa-var-jpy; } +.@{fa-css-prefix}-ruble:before, +.@{fa-css-prefix}-rouble:before, +.@{fa-css-prefix}-rub:before { content: @fa-var-rub; } +.@{fa-css-prefix}-won:before, +.@{fa-css-prefix}-krw:before { content: @fa-var-krw; } +.@{fa-css-prefix}-bitcoin:before, +.@{fa-css-prefix}-btc:before { content: @fa-var-btc; } +.@{fa-css-prefix}-file:before { content: @fa-var-file; } +.@{fa-css-prefix}-file-text:before { content: @fa-var-file-text; } +.@{fa-css-prefix}-sort-alpha-asc:before { content: @fa-var-sort-alpha-asc; } +.@{fa-css-prefix}-sort-alpha-desc:before { content: @fa-var-sort-alpha-desc; } +.@{fa-css-prefix}-sort-amount-asc:before { content: @fa-var-sort-amount-asc; } +.@{fa-css-prefix}-sort-amount-desc:before { content: @fa-var-sort-amount-desc; } +.@{fa-css-prefix}-sort-numeric-asc:before { content: @fa-var-sort-numeric-asc; } +.@{fa-css-prefix}-sort-numeric-desc:before { content: @fa-var-sort-numeric-desc; } +.@{fa-css-prefix}-thumbs-up:before { content: @fa-var-thumbs-up; } +.@{fa-css-prefix}-thumbs-down:before { content: @fa-var-thumbs-down; } +.@{fa-css-prefix}-youtube-square:before { content: @fa-var-youtube-square; } +.@{fa-css-prefix}-youtube:before { content: @fa-var-youtube; } +.@{fa-css-prefix}-xing:before { content: @fa-var-xing; } +.@{fa-css-prefix}-xing-square:before { content: @fa-var-xing-square; } +.@{fa-css-prefix}-youtube-play:before { content: @fa-var-youtube-play; } +.@{fa-css-prefix}-dropbox:before { content: @fa-var-dropbox; } +.@{fa-css-prefix}-stack-overflow:before { content: @fa-var-stack-overflow; } +.@{fa-css-prefix}-instagram:before { content: @fa-var-instagram; } +.@{fa-css-prefix}-flickr:before { content: @fa-var-flickr; } +.@{fa-css-prefix}-adn:before { content: @fa-var-adn; } +.@{fa-css-prefix}-bitbucket:before { content: @fa-var-bitbucket; } +.@{fa-css-prefix}-bitbucket-square:before { content: @fa-var-bitbucket-square; } +.@{fa-css-prefix}-tumblr:before { content: @fa-var-tumblr; } +.@{fa-css-prefix}-tumblr-square:before { content: @fa-var-tumblr-square; } +.@{fa-css-prefix}-long-arrow-down:before { content: @fa-var-long-arrow-down; } +.@{fa-css-prefix}-long-arrow-up:before { content: @fa-var-long-arrow-up; } +.@{fa-css-prefix}-long-arrow-left:before { content: @fa-var-long-arrow-left; } +.@{fa-css-prefix}-long-arrow-right:before { content: @fa-var-long-arrow-right; } +.@{fa-css-prefix}-apple:before { content: @fa-var-apple; } +.@{fa-css-prefix}-windows:before { content: @fa-var-windows; } +.@{fa-css-prefix}-android:before { content: @fa-var-android; } +.@{fa-css-prefix}-linux:before { content: @fa-var-linux; } +.@{fa-css-prefix}-dribbble:before { content: @fa-var-dribbble; } +.@{fa-css-prefix}-skype:before { content: @fa-var-skype; } +.@{fa-css-prefix}-foursquare:before { content: @fa-var-foursquare; } +.@{fa-css-prefix}-trello:before { content: @fa-var-trello; } +.@{fa-css-prefix}-female:before { content: @fa-var-female; } +.@{fa-css-prefix}-male:before { content: @fa-var-male; } +.@{fa-css-prefix}-gittip:before, +.@{fa-css-prefix}-gratipay:before { content: @fa-var-gratipay; } +.@{fa-css-prefix}-sun-o:before { content: @fa-var-sun-o; } +.@{fa-css-prefix}-moon-o:before { content: @fa-var-moon-o; } +.@{fa-css-prefix}-archive:before { content: @fa-var-archive; } +.@{fa-css-prefix}-bug:before { content: @fa-var-bug; } +.@{fa-css-prefix}-vk:before { content: @fa-var-vk; } +.@{fa-css-prefix}-weibo:before { content: @fa-var-weibo; } +.@{fa-css-prefix}-renren:before { content: @fa-var-renren; } +.@{fa-css-prefix}-pagelines:before { content: @fa-var-pagelines; } +.@{fa-css-prefix}-stack-exchange:before { content: @fa-var-stack-exchange; } +.@{fa-css-prefix}-arrow-circle-o-right:before { content: @fa-var-arrow-circle-o-right; } +.@{fa-css-prefix}-arrow-circle-o-left:before { content: @fa-var-arrow-circle-o-left; } +.@{fa-css-prefix}-toggle-left:before, +.@{fa-css-prefix}-caret-square-o-left:before { content: @fa-var-caret-square-o-left; } +.@{fa-css-prefix}-dot-circle-o:before { content: @fa-var-dot-circle-o; } +.@{fa-css-prefix}-wheelchair:before { content: @fa-var-wheelchair; } +.@{fa-css-prefix}-vimeo-square:before { content: @fa-var-vimeo-square; } +.@{fa-css-prefix}-turkish-lira:before, +.@{fa-css-prefix}-try:before { content: @fa-var-try; } +.@{fa-css-prefix}-plus-square-o:before { content: @fa-var-plus-square-o; } +.@{fa-css-prefix}-space-shuttle:before { content: @fa-var-space-shuttle; } +.@{fa-css-prefix}-slack:before { content: @fa-var-slack; } +.@{fa-css-prefix}-envelope-square:before { content: @fa-var-envelope-square; } +.@{fa-css-prefix}-wordpress:before { content: @fa-var-wordpress; } +.@{fa-css-prefix}-openid:before { content: @fa-var-openid; } +.@{fa-css-prefix}-institution:before, +.@{fa-css-prefix}-bank:before, +.@{fa-css-prefix}-university:before { content: @fa-var-university; } +.@{fa-css-prefix}-mortar-board:before, +.@{fa-css-prefix}-graduation-cap:before { content: @fa-var-graduation-cap; } +.@{fa-css-prefix}-yahoo:before { content: @fa-var-yahoo; } +.@{fa-css-prefix}-google:before { content: @fa-var-google; } +.@{fa-css-prefix}-reddit:before { content: @fa-var-reddit; } +.@{fa-css-prefix}-reddit-square:before { content: @fa-var-reddit-square; } +.@{fa-css-prefix}-stumbleupon-circle:before { content: @fa-var-stumbleupon-circle; } +.@{fa-css-prefix}-stumbleupon:before { content: @fa-var-stumbleupon; } +.@{fa-css-prefix}-delicious:before { content: @fa-var-delicious; } +.@{fa-css-prefix}-digg:before { content: @fa-var-digg; } +.@{fa-css-prefix}-pied-piper-pp:before { content: @fa-var-pied-piper-pp; } +.@{fa-css-prefix}-pied-piper-alt:before { content: @fa-var-pied-piper-alt; } +.@{fa-css-prefix}-drupal:before { content: @fa-var-drupal; } +.@{fa-css-prefix}-joomla:before { content: @fa-var-joomla; } +.@{fa-css-prefix}-language:before { content: @fa-var-language; } +.@{fa-css-prefix}-fax:before { content: @fa-var-fax; } +.@{fa-css-prefix}-building:before { content: @fa-var-building; } +.@{fa-css-prefix}-child:before { content: @fa-var-child; } +.@{fa-css-prefix}-paw:before { content: @fa-var-paw; } +.@{fa-css-prefix}-spoon:before { content: @fa-var-spoon; } +.@{fa-css-prefix}-cube:before { content: @fa-var-cube; } +.@{fa-css-prefix}-cubes:before { content: @fa-var-cubes; } +.@{fa-css-prefix}-behance:before { content: @fa-var-behance; } +.@{fa-css-prefix}-behance-square:before { content: @fa-var-behance-square; } +.@{fa-css-prefix}-steam:before { content: @fa-var-steam; } +.@{fa-css-prefix}-steam-square:before { content: @fa-var-steam-square; } +.@{fa-css-prefix}-recycle:before { content: @fa-var-recycle; } +.@{fa-css-prefix}-automobile:before, +.@{fa-css-prefix}-car:before { content: @fa-var-car; } +.@{fa-css-prefix}-cab:before, +.@{fa-css-prefix}-taxi:before { content: @fa-var-taxi; } +.@{fa-css-prefix}-tree:before { content: @fa-var-tree; } +.@{fa-css-prefix}-spotify:before { content: @fa-var-spotify; } +.@{fa-css-prefix}-deviantart:before { content: @fa-var-deviantart; } +.@{fa-css-prefix}-soundcloud:before { content: @fa-var-soundcloud; } +.@{fa-css-prefix}-database:before { content: @fa-var-database; } +.@{fa-css-prefix}-file-pdf-o:before { content: @fa-var-file-pdf-o; } +.@{fa-css-prefix}-file-word-o:before { content: @fa-var-file-word-o; } +.@{fa-css-prefix}-file-excel-o:before { content: @fa-var-file-excel-o; } +.@{fa-css-prefix}-file-powerpoint-o:before { content: @fa-var-file-powerpoint-o; } +.@{fa-css-prefix}-file-photo-o:before, +.@{fa-css-prefix}-file-picture-o:before, +.@{fa-css-prefix}-file-image-o:before { content: @fa-var-file-image-o; } +.@{fa-css-prefix}-file-zip-o:before, +.@{fa-css-prefix}-file-archive-o:before { content: @fa-var-file-archive-o; } +.@{fa-css-prefix}-file-sound-o:before, +.@{fa-css-prefix}-file-audio-o:before { content: @fa-var-file-audio-o; } +.@{fa-css-prefix}-file-movie-o:before, +.@{fa-css-prefix}-file-video-o:before { content: @fa-var-file-video-o; } +.@{fa-css-prefix}-file-code-o:before { content: @fa-var-file-code-o; } +.@{fa-css-prefix}-vine:before { content: @fa-var-vine; } +.@{fa-css-prefix}-codepen:before { content: @fa-var-codepen; } +.@{fa-css-prefix}-jsfiddle:before { content: @fa-var-jsfiddle; } +.@{fa-css-prefix}-life-bouy:before, +.@{fa-css-prefix}-life-buoy:before, +.@{fa-css-prefix}-life-saver:before, +.@{fa-css-prefix}-support:before, +.@{fa-css-prefix}-life-ring:before { content: @fa-var-life-ring; } +.@{fa-css-prefix}-circle-o-notch:before { content: @fa-var-circle-o-notch; } +.@{fa-css-prefix}-ra:before, +.@{fa-css-prefix}-resistance:before, +.@{fa-css-prefix}-rebel:before { content: @fa-var-rebel; } +.@{fa-css-prefix}-ge:before, +.@{fa-css-prefix}-empire:before { content: @fa-var-empire; } +.@{fa-css-prefix}-git-square:before { content: @fa-var-git-square; } +.@{fa-css-prefix}-git:before { content: @fa-var-git; } +.@{fa-css-prefix}-y-combinator-square:before, +.@{fa-css-prefix}-yc-square:before, +.@{fa-css-prefix}-hacker-news:before { content: @fa-var-hacker-news; } +.@{fa-css-prefix}-tencent-weibo:before { content: @fa-var-tencent-weibo; } +.@{fa-css-prefix}-qq:before { content: @fa-var-qq; } +.@{fa-css-prefix}-wechat:before, +.@{fa-css-prefix}-weixin:before { content: @fa-var-weixin; } +.@{fa-css-prefix}-send:before, +.@{fa-css-prefix}-paper-plane:before { content: @fa-var-paper-plane; } +.@{fa-css-prefix}-send-o:before, +.@{fa-css-prefix}-paper-plane-o:before { content: @fa-var-paper-plane-o; } +.@{fa-css-prefix}-history:before { content: @fa-var-history; } +.@{fa-css-prefix}-circle-thin:before { content: @fa-var-circle-thin; } +.@{fa-css-prefix}-header:before { content: @fa-var-header; } +.@{fa-css-prefix}-paragraph:before { content: @fa-var-paragraph; } +.@{fa-css-prefix}-sliders:before { content: @fa-var-sliders; } +.@{fa-css-prefix}-share-alt:before { content: @fa-var-share-alt; } +.@{fa-css-prefix}-share-alt-square:before { content: @fa-var-share-alt-square; } +.@{fa-css-prefix}-bomb:before { content: @fa-var-bomb; } +.@{fa-css-prefix}-soccer-ball-o:before, +.@{fa-css-prefix}-futbol-o:before { content: @fa-var-futbol-o; } +.@{fa-css-prefix}-tty:before { content: @fa-var-tty; } +.@{fa-css-prefix}-binoculars:before { content: @fa-var-binoculars; } +.@{fa-css-prefix}-plug:before { content: @fa-var-plug; } +.@{fa-css-prefix}-slideshare:before { content: @fa-var-slideshare; } +.@{fa-css-prefix}-twitch:before { content: @fa-var-twitch; } +.@{fa-css-prefix}-yelp:before { content: @fa-var-yelp; } +.@{fa-css-prefix}-newspaper-o:before { content: @fa-var-newspaper-o; } +.@{fa-css-prefix}-wifi:before { content: @fa-var-wifi; } +.@{fa-css-prefix}-calculator:before { content: @fa-var-calculator; } +.@{fa-css-prefix}-paypal:before { content: @fa-var-paypal; } +.@{fa-css-prefix}-google-wallet:before { content: @fa-var-google-wallet; } +.@{fa-css-prefix}-cc-visa:before { content: @fa-var-cc-visa; } +.@{fa-css-prefix}-cc-mastercard:before { content: @fa-var-cc-mastercard; } +.@{fa-css-prefix}-cc-discover:before { content: @fa-var-cc-discover; } +.@{fa-css-prefix}-cc-amex:before { content: @fa-var-cc-amex; } +.@{fa-css-prefix}-cc-paypal:before { content: @fa-var-cc-paypal; } +.@{fa-css-prefix}-cc-stripe:before { content: @fa-var-cc-stripe; } +.@{fa-css-prefix}-bell-slash:before { content: @fa-var-bell-slash; } +.@{fa-css-prefix}-bell-slash-o:before { content: @fa-var-bell-slash-o; } +.@{fa-css-prefix}-trash:before { content: @fa-var-trash; } +.@{fa-css-prefix}-copyright:before { content: @fa-var-copyright; } +.@{fa-css-prefix}-at:before { content: @fa-var-at; } +.@{fa-css-prefix}-eyedropper:before { content: @fa-var-eyedropper; } +.@{fa-css-prefix}-paint-brush:before { content: @fa-var-paint-brush; } +.@{fa-css-prefix}-birthday-cake:before { content: @fa-var-birthday-cake; } +.@{fa-css-prefix}-area-chart:before { content: @fa-var-area-chart; } +.@{fa-css-prefix}-pie-chart:before { content: @fa-var-pie-chart; } +.@{fa-css-prefix}-line-chart:before { content: @fa-var-line-chart; } +.@{fa-css-prefix}-lastfm:before { content: @fa-var-lastfm; } +.@{fa-css-prefix}-lastfm-square:before { content: @fa-var-lastfm-square; } +.@{fa-css-prefix}-toggle-off:before { content: @fa-var-toggle-off; } +.@{fa-css-prefix}-toggle-on:before { content: @fa-var-toggle-on; } +.@{fa-css-prefix}-bicycle:before { content: @fa-var-bicycle; } +.@{fa-css-prefix}-bus:before { content: @fa-var-bus; } +.@{fa-css-prefix}-ioxhost:before { content: @fa-var-ioxhost; } +.@{fa-css-prefix}-angellist:before { content: @fa-var-angellist; } +.@{fa-css-prefix}-cc:before { content: @fa-var-cc; } +.@{fa-css-prefix}-shekel:before, +.@{fa-css-prefix}-sheqel:before, +.@{fa-css-prefix}-ils:before { content: @fa-var-ils; } +.@{fa-css-prefix}-meanpath:before { content: @fa-var-meanpath; } +.@{fa-css-prefix}-buysellads:before { content: @fa-var-buysellads; } +.@{fa-css-prefix}-connectdevelop:before { content: @fa-var-connectdevelop; } +.@{fa-css-prefix}-dashcube:before { content: @fa-var-dashcube; } +.@{fa-css-prefix}-forumbee:before { content: @fa-var-forumbee; } +.@{fa-css-prefix}-leanpub:before { content: @fa-var-leanpub; } +.@{fa-css-prefix}-sellsy:before { content: @fa-var-sellsy; } +.@{fa-css-prefix}-shirtsinbulk:before { content: @fa-var-shirtsinbulk; } +.@{fa-css-prefix}-simplybuilt:before { content: @fa-var-simplybuilt; } +.@{fa-css-prefix}-skyatlas:before { content: @fa-var-skyatlas; } +.@{fa-css-prefix}-cart-plus:before { content: @fa-var-cart-plus; } +.@{fa-css-prefix}-cart-arrow-down:before { content: @fa-var-cart-arrow-down; } +.@{fa-css-prefix}-diamond:before { content: @fa-var-diamond; } +.@{fa-css-prefix}-ship:before { content: @fa-var-ship; } +.@{fa-css-prefix}-user-secret:before { content: @fa-var-user-secret; } +.@{fa-css-prefix}-motorcycle:before { content: @fa-var-motorcycle; } +.@{fa-css-prefix}-street-view:before { content: @fa-var-street-view; } +.@{fa-css-prefix}-heartbeat:before { content: @fa-var-heartbeat; } +.@{fa-css-prefix}-venus:before { content: @fa-var-venus; } +.@{fa-css-prefix}-mars:before { content: @fa-var-mars; } +.@{fa-css-prefix}-mercury:before { content: @fa-var-mercury; } +.@{fa-css-prefix}-intersex:before, +.@{fa-css-prefix}-transgender:before { content: @fa-var-transgender; } +.@{fa-css-prefix}-transgender-alt:before { content: @fa-var-transgender-alt; } +.@{fa-css-prefix}-venus-double:before { content: @fa-var-venus-double; } +.@{fa-css-prefix}-mars-double:before { content: @fa-var-mars-double; } +.@{fa-css-prefix}-venus-mars:before { content: @fa-var-venus-mars; } +.@{fa-css-prefix}-mars-stroke:before { content: @fa-var-mars-stroke; } +.@{fa-css-prefix}-mars-stroke-v:before { content: @fa-var-mars-stroke-v; } +.@{fa-css-prefix}-mars-stroke-h:before { content: @fa-var-mars-stroke-h; } +.@{fa-css-prefix}-neuter:before { content: @fa-var-neuter; } +.@{fa-css-prefix}-genderless:before { content: @fa-var-genderless; } +.@{fa-css-prefix}-facebook-official:before { content: @fa-var-facebook-official; } +.@{fa-css-prefix}-pinterest-p:before { content: @fa-var-pinterest-p; } +.@{fa-css-prefix}-whatsapp:before { content: @fa-var-whatsapp; } +.@{fa-css-prefix}-server:before { content: @fa-var-server; } +.@{fa-css-prefix}-user-plus:before { content: @fa-var-user-plus; } +.@{fa-css-prefix}-user-times:before { content: @fa-var-user-times; } +.@{fa-css-prefix}-hotel:before, +.@{fa-css-prefix}-bed:before { content: @fa-var-bed; } +.@{fa-css-prefix}-viacoin:before { content: @fa-var-viacoin; } +.@{fa-css-prefix}-train:before { content: @fa-var-train; } +.@{fa-css-prefix}-subway:before { content: @fa-var-subway; } +.@{fa-css-prefix}-medium:before { content: @fa-var-medium; } +.@{fa-css-prefix}-yc:before, +.@{fa-css-prefix}-y-combinator:before { content: @fa-var-y-combinator; } +.@{fa-css-prefix}-optin-monster:before { content: @fa-var-optin-monster; } +.@{fa-css-prefix}-opencart:before { content: @fa-var-opencart; } +.@{fa-css-prefix}-expeditedssl:before { content: @fa-var-expeditedssl; } +.@{fa-css-prefix}-battery-4:before, +.@{fa-css-prefix}-battery:before, +.@{fa-css-prefix}-battery-full:before { content: @fa-var-battery-full; } +.@{fa-css-prefix}-battery-3:before, +.@{fa-css-prefix}-battery-three-quarters:before { content: @fa-var-battery-three-quarters; } +.@{fa-css-prefix}-battery-2:before, +.@{fa-css-prefix}-battery-half:before { content: @fa-var-battery-half; } +.@{fa-css-prefix}-battery-1:before, +.@{fa-css-prefix}-battery-quarter:before { content: @fa-var-battery-quarter; } +.@{fa-css-prefix}-battery-0:before, +.@{fa-css-prefix}-battery-empty:before { content: @fa-var-battery-empty; } +.@{fa-css-prefix}-mouse-pointer:before { content: @fa-var-mouse-pointer; } +.@{fa-css-prefix}-i-cursor:before { content: @fa-var-i-cursor; } +.@{fa-css-prefix}-object-group:before { content: @fa-var-object-group; } +.@{fa-css-prefix}-object-ungroup:before { content: @fa-var-object-ungroup; } +.@{fa-css-prefix}-sticky-note:before { content: @fa-var-sticky-note; } +.@{fa-css-prefix}-sticky-note-o:before { content: @fa-var-sticky-note-o; } +.@{fa-css-prefix}-cc-jcb:before { content: @fa-var-cc-jcb; } +.@{fa-css-prefix}-cc-diners-club:before { content: @fa-var-cc-diners-club; } +.@{fa-css-prefix}-clone:before { content: @fa-var-clone; } +.@{fa-css-prefix}-balance-scale:before { content: @fa-var-balance-scale; } +.@{fa-css-prefix}-hourglass-o:before { content: @fa-var-hourglass-o; } +.@{fa-css-prefix}-hourglass-1:before, +.@{fa-css-prefix}-hourglass-start:before { content: @fa-var-hourglass-start; } +.@{fa-css-prefix}-hourglass-2:before, +.@{fa-css-prefix}-hourglass-half:before { content: @fa-var-hourglass-half; } +.@{fa-css-prefix}-hourglass-3:before, +.@{fa-css-prefix}-hourglass-end:before { content: @fa-var-hourglass-end; } +.@{fa-css-prefix}-hourglass:before { content: @fa-var-hourglass; } +.@{fa-css-prefix}-hand-grab-o:before, +.@{fa-css-prefix}-hand-rock-o:before { content: @fa-var-hand-rock-o; } +.@{fa-css-prefix}-hand-stop-o:before, +.@{fa-css-prefix}-hand-paper-o:before { content: @fa-var-hand-paper-o; } +.@{fa-css-prefix}-hand-scissors-o:before { content: @fa-var-hand-scissors-o; } +.@{fa-css-prefix}-hand-lizard-o:before { content: @fa-var-hand-lizard-o; } +.@{fa-css-prefix}-hand-spock-o:before { content: @fa-var-hand-spock-o; } +.@{fa-css-prefix}-hand-pointer-o:before { content: @fa-var-hand-pointer-o; } +.@{fa-css-prefix}-hand-peace-o:before { content: @fa-var-hand-peace-o; } +.@{fa-css-prefix}-trademark:before { content: @fa-var-trademark; } +.@{fa-css-prefix}-registered:before { content: @fa-var-registered; } +.@{fa-css-prefix}-creative-commons:before { content: @fa-var-creative-commons; } +.@{fa-css-prefix}-gg:before { content: @fa-var-gg; } +.@{fa-css-prefix}-gg-circle:before { content: @fa-var-gg-circle; } +.@{fa-css-prefix}-tripadvisor:before { content: @fa-var-tripadvisor; } +.@{fa-css-prefix}-odnoklassniki:before { content: @fa-var-odnoklassniki; } +.@{fa-css-prefix}-odnoklassniki-square:before { content: @fa-var-odnoklassniki-square; } +.@{fa-css-prefix}-get-pocket:before { content: @fa-var-get-pocket; } +.@{fa-css-prefix}-wikipedia-w:before { content: @fa-var-wikipedia-w; } +.@{fa-css-prefix}-safari:before { content: @fa-var-safari; } +.@{fa-css-prefix}-chrome:before { content: @fa-var-chrome; } +.@{fa-css-prefix}-firefox:before { content: @fa-var-firefox; } +.@{fa-css-prefix}-opera:before { content: @fa-var-opera; } +.@{fa-css-prefix}-internet-explorer:before { content: @fa-var-internet-explorer; } +.@{fa-css-prefix}-tv:before, +.@{fa-css-prefix}-television:before { content: @fa-var-television; } +.@{fa-css-prefix}-contao:before { content: @fa-var-contao; } +.@{fa-css-prefix}-500px:before { content: @fa-var-500px; } +.@{fa-css-prefix}-amazon:before { content: @fa-var-amazon; } +.@{fa-css-prefix}-calendar-plus-o:before { content: @fa-var-calendar-plus-o; } +.@{fa-css-prefix}-calendar-minus-o:before { content: @fa-var-calendar-minus-o; } +.@{fa-css-prefix}-calendar-times-o:before { content: @fa-var-calendar-times-o; } +.@{fa-css-prefix}-calendar-check-o:before { content: @fa-var-calendar-check-o; } +.@{fa-css-prefix}-industry:before { content: @fa-var-industry; } +.@{fa-css-prefix}-map-pin:before { content: @fa-var-map-pin; } +.@{fa-css-prefix}-map-signs:before { content: @fa-var-map-signs; } +.@{fa-css-prefix}-map-o:before { content: @fa-var-map-o; } +.@{fa-css-prefix}-map:before { content: @fa-var-map; } +.@{fa-css-prefix}-commenting:before { content: @fa-var-commenting; } +.@{fa-css-prefix}-commenting-o:before { content: @fa-var-commenting-o; } +.@{fa-css-prefix}-houzz:before { content: @fa-var-houzz; } +.@{fa-css-prefix}-vimeo:before { content: @fa-var-vimeo; } +.@{fa-css-prefix}-black-tie:before { content: @fa-var-black-tie; } +.@{fa-css-prefix}-fonticons:before { content: @fa-var-fonticons; } +.@{fa-css-prefix}-reddit-alien:before { content: @fa-var-reddit-alien; } +.@{fa-css-prefix}-edge:before { content: @fa-var-edge; } +.@{fa-css-prefix}-credit-card-alt:before { content: @fa-var-credit-card-alt; } +.@{fa-css-prefix}-codiepie:before { content: @fa-var-codiepie; } +.@{fa-css-prefix}-modx:before { content: @fa-var-modx; } +.@{fa-css-prefix}-fort-awesome:before { content: @fa-var-fort-awesome; } +.@{fa-css-prefix}-usb:before { content: @fa-var-usb; } +.@{fa-css-prefix}-product-hunt:before { content: @fa-var-product-hunt; } +.@{fa-css-prefix}-mixcloud:before { content: @fa-var-mixcloud; } +.@{fa-css-prefix}-scribd:before { content: @fa-var-scribd; } +.@{fa-css-prefix}-pause-circle:before { content: @fa-var-pause-circle; } +.@{fa-css-prefix}-pause-circle-o:before { content: @fa-var-pause-circle-o; } +.@{fa-css-prefix}-stop-circle:before { content: @fa-var-stop-circle; } +.@{fa-css-prefix}-stop-circle-o:before { content: @fa-var-stop-circle-o; } +.@{fa-css-prefix}-shopping-bag:before { content: @fa-var-shopping-bag; } +.@{fa-css-prefix}-shopping-basket:before { content: @fa-var-shopping-basket; } +.@{fa-css-prefix}-hashtag:before { content: @fa-var-hashtag; } +.@{fa-css-prefix}-bluetooth:before { content: @fa-var-bluetooth; } +.@{fa-css-prefix}-bluetooth-b:before { content: @fa-var-bluetooth-b; } +.@{fa-css-prefix}-percent:before { content: @fa-var-percent; } +.@{fa-css-prefix}-gitlab:before { content: @fa-var-gitlab; } +.@{fa-css-prefix}-wpbeginner:before { content: @fa-var-wpbeginner; } +.@{fa-css-prefix}-wpforms:before { content: @fa-var-wpforms; } +.@{fa-css-prefix}-envira:before { content: @fa-var-envira; } +.@{fa-css-prefix}-universal-access:before { content: @fa-var-universal-access; } +.@{fa-css-prefix}-wheelchair-alt:before { content: @fa-var-wheelchair-alt; } +.@{fa-css-prefix}-question-circle-o:before { content: @fa-var-question-circle-o; } +.@{fa-css-prefix}-blind:before { content: @fa-var-blind; } +.@{fa-css-prefix}-audio-description:before { content: @fa-var-audio-description; } +.@{fa-css-prefix}-volume-control-phone:before { content: @fa-var-volume-control-phone; } +.@{fa-css-prefix}-braille:before { content: @fa-var-braille; } +.@{fa-css-prefix}-assistive-listening-systems:before { content: @fa-var-assistive-listening-systems; } +.@{fa-css-prefix}-asl-interpreting:before, +.@{fa-css-prefix}-american-sign-language-interpreting:before { content: @fa-var-american-sign-language-interpreting; } +.@{fa-css-prefix}-deafness:before, +.@{fa-css-prefix}-hard-of-hearing:before, +.@{fa-css-prefix}-deaf:before { content: @fa-var-deaf; } +.@{fa-css-prefix}-glide:before { content: @fa-var-glide; } +.@{fa-css-prefix}-glide-g:before { content: @fa-var-glide-g; } +.@{fa-css-prefix}-signing:before, +.@{fa-css-prefix}-sign-language:before { content: @fa-var-sign-language; } +.@{fa-css-prefix}-low-vision:before { content: @fa-var-low-vision; } +.@{fa-css-prefix}-viadeo:before { content: @fa-var-viadeo; } +.@{fa-css-prefix}-viadeo-square:before { content: @fa-var-viadeo-square; } +.@{fa-css-prefix}-snapchat:before { content: @fa-var-snapchat; } +.@{fa-css-prefix}-snapchat-ghost:before { content: @fa-var-snapchat-ghost; } +.@{fa-css-prefix}-snapchat-square:before { content: @fa-var-snapchat-square; } +.@{fa-css-prefix}-pied-piper:before { content: @fa-var-pied-piper; } +.@{fa-css-prefix}-first-order:before { content: @fa-var-first-order; } +.@{fa-css-prefix}-yoast:before { content: @fa-var-yoast; } +.@{fa-css-prefix}-themeisle:before { content: @fa-var-themeisle; } +.@{fa-css-prefix}-google-plus-circle:before, +.@{fa-css-prefix}-google-plus-official:before { content: @fa-var-google-plus-official; } +.@{fa-css-prefix}-fa:before, +.@{fa-css-prefix}-font-awesome:before { content: @fa-var-font-awesome; } +.@{fa-css-prefix}-handshake-o:before { content: @fa-var-handshake-o; } +.@{fa-css-prefix}-envelope-open:before { content: @fa-var-envelope-open; } +.@{fa-css-prefix}-envelope-open-o:before { content: @fa-var-envelope-open-o; } +.@{fa-css-prefix}-linode:before { content: @fa-var-linode; } +.@{fa-css-prefix}-address-book:before { content: @fa-var-address-book; } +.@{fa-css-prefix}-address-book-o:before { content: @fa-var-address-book-o; } +.@{fa-css-prefix}-vcard:before, +.@{fa-css-prefix}-address-card:before { content: @fa-var-address-card; } +.@{fa-css-prefix}-vcard-o:before, +.@{fa-css-prefix}-address-card-o:before { content: @fa-var-address-card-o; } +.@{fa-css-prefix}-user-circle:before { content: @fa-var-user-circle; } +.@{fa-css-prefix}-user-circle-o:before { content: @fa-var-user-circle-o; } +.@{fa-css-prefix}-user-o:before { content: @fa-var-user-o; } +.@{fa-css-prefix}-id-badge:before { content: @fa-var-id-badge; } +.@{fa-css-prefix}-drivers-license:before, +.@{fa-css-prefix}-id-card:before { content: @fa-var-id-card; } +.@{fa-css-prefix}-drivers-license-o:before, +.@{fa-css-prefix}-id-card-o:before { content: @fa-var-id-card-o; } +.@{fa-css-prefix}-quora:before { content: @fa-var-quora; } +.@{fa-css-prefix}-free-code-camp:before { content: @fa-var-free-code-camp; } +.@{fa-css-prefix}-telegram:before { content: @fa-var-telegram; } +.@{fa-css-prefix}-thermometer-4:before, +.@{fa-css-prefix}-thermometer:before, +.@{fa-css-prefix}-thermometer-full:before { content: @fa-var-thermometer-full; } +.@{fa-css-prefix}-thermometer-3:before, +.@{fa-css-prefix}-thermometer-three-quarters:before { content: @fa-var-thermometer-three-quarters; } +.@{fa-css-prefix}-thermometer-2:before, +.@{fa-css-prefix}-thermometer-half:before { content: @fa-var-thermometer-half; } +.@{fa-css-prefix}-thermometer-1:before, +.@{fa-css-prefix}-thermometer-quarter:before { content: @fa-var-thermometer-quarter; } +.@{fa-css-prefix}-thermometer-0:before, +.@{fa-css-prefix}-thermometer-empty:before { content: @fa-var-thermometer-empty; } +.@{fa-css-prefix}-shower:before { content: @fa-var-shower; } +.@{fa-css-prefix}-bathtub:before, +.@{fa-css-prefix}-s15:before, +.@{fa-css-prefix}-bath:before { content: @fa-var-bath; } +.@{fa-css-prefix}-podcast:before { content: @fa-var-podcast; } +.@{fa-css-prefix}-window-maximize:before { content: @fa-var-window-maximize; } +.@{fa-css-prefix}-window-minimize:before { content: @fa-var-window-minimize; } +.@{fa-css-prefix}-window-restore:before { content: @fa-var-window-restore; } +.@{fa-css-prefix}-times-rectangle:before, +.@{fa-css-prefix}-window-close:before { content: @fa-var-window-close; } +.@{fa-css-prefix}-times-rectangle-o:before, +.@{fa-css-prefix}-window-close-o:before { content: @fa-var-window-close-o; } +.@{fa-css-prefix}-bandcamp:before { content: @fa-var-bandcamp; } +.@{fa-css-prefix}-grav:before { content: @fa-var-grav; } +.@{fa-css-prefix}-etsy:before { content: @fa-var-etsy; } +.@{fa-css-prefix}-imdb:before { content: @fa-var-imdb; } +.@{fa-css-prefix}-ravelry:before { content: @fa-var-ravelry; } +.@{fa-css-prefix}-eercast:before { content: @fa-var-eercast; } +.@{fa-css-prefix}-microchip:before { content: @fa-var-microchip; } +.@{fa-css-prefix}-snowflake-o:before { content: @fa-var-snowflake-o; } +.@{fa-css-prefix}-superpowers:before { content: @fa-var-superpowers; } +.@{fa-css-prefix}-wpexplorer:before { content: @fa-var-wpexplorer; } +.@{fa-css-prefix}-meetup:before { content: @fa-var-meetup; } diff --git a/dashboard/src/assets/font-awesome/less/larger.less b/dashboard/src/assets/font-awesome/less/larger.less new file mode 100644 index 00000000..d54a4ab4 --- /dev/null +++ b/dashboard/src/assets/font-awesome/less/larger.less @@ -0,0 +1,29 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Icon Sizes +// ------------------------- + +/* makes the font 33% larger relative to the icon container */ +.@{fa-css-prefix}-lg { + font-size: (4em / 3); + line-height: (3em / 4); + vertical-align: -15%; +} +.@{fa-css-prefix}-2x { font-size: 2em; } +.@{fa-css-prefix}-3x { font-size: 3em; } +.@{fa-css-prefix}-4x { font-size: 4em; } +.@{fa-css-prefix}-5x { font-size: 5em; } diff --git a/dashboard/src/assets/font-awesome/less/list.less b/dashboard/src/assets/font-awesome/less/list.less new file mode 100644 index 00000000..eb72722b --- /dev/null +++ b/dashboard/src/assets/font-awesome/less/list.less @@ -0,0 +1,35 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// List Icons +// ------------------------- + +.@{fa-css-prefix}-ul { + padding-left: 0; + margin-left: @fa-li-width; + list-style-type: none; + > li { position: relative; } +} +.@{fa-css-prefix}-li { + position: absolute; + left: -@fa-li-width; + width: @fa-li-width; + top: (2em / 14); + text-align: center; + &.@{fa-css-prefix}-lg { + left: (-@fa-li-width + (4em / 14)); + } +} diff --git a/dashboard/src/assets/font-awesome/less/mixins.less b/dashboard/src/assets/font-awesome/less/mixins.less new file mode 100644 index 00000000..9771d398 --- /dev/null +++ b/dashboard/src/assets/font-awesome/less/mixins.less @@ -0,0 +1,76 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Mixins +// -------------------------- + +.fa-icon() { + display: inline-block; + font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration + font-size: inherit; // can't have font-size inherit on line above, so need to override + text-rendering: auto; // optimizelegibility throws things off #1094 + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + +} + +.fa-icon-rotate(@degrees, @rotation) { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation})"; + -webkit-transform: rotate(@degrees); + -ms-transform: rotate(@degrees); + transform: rotate(@degrees); +} + +.fa-icon-flip(@horiz, @vert, @rotation) { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation}, mirror=1)"; + -webkit-transform: scale(@horiz, @vert); + -ms-transform: scale(@horiz, @vert); + transform: scale(@horiz, @vert); +} + + +// Only display content to screen readers. A la Bootstrap 4. +// +// See: http://a11yproject.com/posts/how-to-hide-content/ + +.sr-only() { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0,0,0,0); + border: 0; +} + +// Use in conjunction with .sr-only to only display content when it's focused. +// +// Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 +// +// Credit: HTML5 Boilerplate + +.sr-only-focusable() { + &:active, + &:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; + } +} diff --git a/dashboard/src/assets/font-awesome/less/path.less b/dashboard/src/assets/font-awesome/less/path.less new file mode 100644 index 00000000..dfe61405 --- /dev/null +++ b/dashboard/src/assets/font-awesome/less/path.less @@ -0,0 +1,31 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* FONT PATH + * -------------------------- */ + +@font-face { + font-family: 'FontAwesome'; + src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); + src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), + url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'), + url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), + url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), + url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); + // src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts + font-weight: normal; + font-style: normal; +} diff --git a/dashboard/src/assets/font-awesome/less/rotated-flipped.less b/dashboard/src/assets/font-awesome/less/rotated-flipped.less new file mode 100644 index 00000000..5ee4dc3f --- /dev/null +++ b/dashboard/src/assets/font-awesome/less/rotated-flipped.less @@ -0,0 +1,36 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Rotated & Flipped Icons +// ------------------------- + +.@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } +.@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } +.@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } + +.@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } +.@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } + +// Hook for IE8-9 +// ------------------------- + +:root .@{fa-css-prefix}-rotate-90, +:root .@{fa-css-prefix}-rotate-180, +:root .@{fa-css-prefix}-rotate-270, +:root .@{fa-css-prefix}-flip-horizontal, +:root .@{fa-css-prefix}-flip-vertical { + filter: none; +} diff --git a/dashboard/src/assets/font-awesome/less/screen-reader.less b/dashboard/src/assets/font-awesome/less/screen-reader.less new file mode 100644 index 00000000..97ef1a3f --- /dev/null +++ b/dashboard/src/assets/font-awesome/less/screen-reader.less @@ -0,0 +1,21 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Screen Readers +// ------------------------- + +.sr-only { .sr-only(); } +.sr-only-focusable { .sr-only-focusable(); } diff --git a/dashboard/src/assets/font-awesome/less/stacked.less b/dashboard/src/assets/font-awesome/less/stacked.less new file mode 100644 index 00000000..05eb9b5c --- /dev/null +++ b/dashboard/src/assets/font-awesome/less/stacked.less @@ -0,0 +1,36 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Stacked Icons +// ------------------------- + +.@{fa-css-prefix}-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.@{fa-css-prefix}-stack-1x { line-height: inherit; } +.@{fa-css-prefix}-stack-2x { font-size: 2em; } +.@{fa-css-prefix}-inverse { color: @fa-inverse; } diff --git a/dashboard/src/assets/font-awesome/less/variables.less b/dashboard/src/assets/font-awesome/less/variables.less new file mode 100644 index 00000000..1300a628 --- /dev/null +++ b/dashboard/src/assets/font-awesome/less/variables.less @@ -0,0 +1,816 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Variables +// -------------------------- + +@fa-font-path: "../fonts"; +@fa-font-size-base: 14px; +@fa-line-height-base: 1; +//@fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.7.0/fonts"; // for referencing Bootstrap CDN font files directly +@fa-css-prefix: fa; +@fa-version: "4.7.0"; +@fa-border-color: #eee; +@fa-inverse: #fff; +@fa-li-width: (30em / 14); + +@fa-var-500px: "\f26e"; +@fa-var-address-book: "\f2b9"; +@fa-var-address-book-o: "\f2ba"; +@fa-var-address-card: "\f2bb"; +@fa-var-address-card-o: "\f2bc"; +@fa-var-adjust: "\f042"; +@fa-var-adn: "\f170"; +@fa-var-align-center: "\f037"; +@fa-var-align-justify: "\f039"; +@fa-var-align-left: "\f036"; +@fa-var-align-right: "\f038"; +@fa-var-amazon: "\f270"; +@fa-var-ambulance: "\f0f9"; +@fa-var-american-sign-language-interpreting: "\f2a3"; +@fa-var-anchor: "\f13d"; +@fa-var-android: "\f17b"; +@fa-var-angellist: "\f209"; +@fa-var-angle-double-down: "\f103"; +@fa-var-angle-double-left: "\f100"; +@fa-var-angle-double-right: "\f101"; +@fa-var-angle-double-up: "\f102"; +@fa-var-angle-down: "\f107"; +@fa-var-angle-left: "\f104"; +@fa-var-angle-right: "\f105"; +@fa-var-angle-up: "\f106"; +@fa-var-apple: "\f179"; +@fa-var-archive: "\f187"; +@fa-var-area-chart: "\f1fe"; +@fa-var-arrow-circle-down: "\f0ab"; +@fa-var-arrow-circle-left: "\f0a8"; +@fa-var-arrow-circle-o-down: "\f01a"; +@fa-var-arrow-circle-o-left: "\f190"; +@fa-var-arrow-circle-o-right: "\f18e"; +@fa-var-arrow-circle-o-up: "\f01b"; +@fa-var-arrow-circle-right: "\f0a9"; +@fa-var-arrow-circle-up: "\f0aa"; +@fa-var-arrow-down: "\f063"; +@fa-var-arrow-left: "\f060"; +@fa-var-arrow-right: "\f061"; +@fa-var-arrow-up: "\f062"; +@fa-var-arrows: "\f047"; +@fa-var-arrows-alt: "\f0b2"; +@fa-var-arrows-h: "\f07e"; +@fa-var-arrows-v: "\f07d"; +@fa-var-asl-interpreting: "\f2a3"; +@fa-var-assistive-listening-systems: "\f2a2"; +@fa-var-asterisk: "\f069"; +@fa-var-at: "\f1fa"; +@fa-var-audio-description: "\f29e"; +@fa-var-automobile: "\f1b9"; +@fa-var-backward: "\f04a"; +@fa-var-balance-scale: "\f24e"; +@fa-var-ban: "\f05e"; +@fa-var-bandcamp: "\f2d5"; +@fa-var-bank: "\f19c"; +@fa-var-bar-chart: "\f080"; +@fa-var-bar-chart-o: "\f080"; +@fa-var-barcode: "\f02a"; +@fa-var-bars: "\f0c9"; +@fa-var-bath: "\f2cd"; +@fa-var-bathtub: "\f2cd"; +@fa-var-battery: "\f240"; +@fa-var-battery-0: "\f244"; +@fa-var-battery-1: "\f243"; +@fa-var-battery-2: "\f242"; +@fa-var-battery-3: "\f241"; +@fa-var-battery-4: "\f240"; +@fa-var-battery-empty: "\f244"; +@fa-var-battery-full: "\f240"; +@fa-var-battery-half: "\f242"; +@fa-var-battery-quarter: "\f243"; +@fa-var-battery-three-quarters: "\f241"; +@fa-var-bed: "\f236"; +@fa-var-beer: "\f0fc"; +@fa-var-behance: "\f1b4"; +@fa-var-behance-square: "\f1b5"; +@fa-var-bell: "\f0f3"; +@fa-var-bell-o: "\f0a2"; +@fa-var-bell-slash: "\f1f6"; +@fa-var-bell-slash-o: "\f1f7"; +@fa-var-bicycle: "\f206"; +@fa-var-binoculars: "\f1e5"; +@fa-var-birthday-cake: "\f1fd"; +@fa-var-bitbucket: "\f171"; +@fa-var-bitbucket-square: "\f172"; +@fa-var-bitcoin: "\f15a"; +@fa-var-black-tie: "\f27e"; +@fa-var-blind: "\f29d"; +@fa-var-bluetooth: "\f293"; +@fa-var-bluetooth-b: "\f294"; +@fa-var-bold: "\f032"; +@fa-var-bolt: "\f0e7"; +@fa-var-bomb: "\f1e2"; +@fa-var-book: "\f02d"; +@fa-var-bookmark: "\f02e"; +@fa-var-bookmark-o: "\f097"; +@fa-var-braille: "\f2a1"; +@fa-var-briefcase: "\f0b1"; +@fa-var-btc: "\f15a"; +@fa-var-bug: "\f188"; +@fa-var-building: "\f1ad"; +@fa-var-building-o: "\f0f7"; +@fa-var-bullhorn: "\f0a1"; +@fa-var-bullseye: "\f140"; +@fa-var-bus: "\f207"; +@fa-var-buysellads: "\f20d"; +@fa-var-cab: "\f1ba"; +@fa-var-calculator: "\f1ec"; +@fa-var-calendar: "\f073"; +@fa-var-calendar-check-o: "\f274"; +@fa-var-calendar-minus-o: "\f272"; +@fa-var-calendar-o: "\f133"; +@fa-var-calendar-plus-o: "\f271"; +@fa-var-calendar-times-o: "\f273"; +@fa-var-camera: "\f030"; +@fa-var-camera-retro: "\f083"; +@fa-var-car: "\f1b9"; +@fa-var-caret-down: "\f0d7"; +@fa-var-caret-left: "\f0d9"; +@fa-var-caret-right: "\f0da"; +@fa-var-caret-square-o-down: "\f150"; +@fa-var-caret-square-o-left: "\f191"; +@fa-var-caret-square-o-right: "\f152"; +@fa-var-caret-square-o-up: "\f151"; +@fa-var-caret-up: "\f0d8"; +@fa-var-cart-arrow-down: "\f218"; +@fa-var-cart-plus: "\f217"; +@fa-var-cc: "\f20a"; +@fa-var-cc-amex: "\f1f3"; +@fa-var-cc-diners-club: "\f24c"; +@fa-var-cc-discover: "\f1f2"; +@fa-var-cc-jcb: "\f24b"; +@fa-var-cc-mastercard: "\f1f1"; +@fa-var-cc-paypal: "\f1f4"; +@fa-var-cc-stripe: "\f1f5"; +@fa-var-cc-visa: "\f1f0"; +@fa-var-certificate: "\f0a3"; +@fa-var-chain: "\f0c1"; +@fa-var-chain-broken: "\f127"; +@fa-var-check: "\f00c"; +@fa-var-check-circle: "\f058"; +@fa-var-check-circle-o: "\f05d"; +@fa-var-check-square: "\f14a"; +@fa-var-check-square-o: "\f046"; +@fa-var-chevron-circle-down: "\f13a"; +@fa-var-chevron-circle-left: "\f137"; +@fa-var-chevron-circle-right: "\f138"; +@fa-var-chevron-circle-up: "\f139"; +@fa-var-chevron-down: "\f078"; +@fa-var-chevron-left: "\f053"; +@fa-var-chevron-right: "\f054"; +@fa-var-chevron-up: "\f077"; +@fa-var-child: "\f1ae"; +@fa-var-chrome: "\f268"; +@fa-var-circle: "\f111"; +@fa-var-circle-o: "\f10c"; +@fa-var-circle-o-notch: "\f1ce"; +@fa-var-circle-thin: "\f1db"; +@fa-var-clipboard: "\f0ea"; +@fa-var-clock-o: "\f017"; +@fa-var-clone: "\f24d"; +@fa-var-close: "\f00d"; +@fa-var-cloud: "\f0c2"; +@fa-var-cloud-download: "\f0ed"; +@fa-var-cloud-upload: "\f0ee"; +@fa-var-cny: "\f157"; +@fa-var-code: "\f121"; +@fa-var-code-fork: "\f126"; +@fa-var-codepen: "\f1cb"; +@fa-var-codiepie: "\f284"; +@fa-var-coffee: "\f0f4"; +@fa-var-cog: "\f013"; +@fa-var-cogs: "\f085"; +@fa-var-columns: "\f0db"; +@fa-var-comment: "\f075"; +@fa-var-comment-o: "\f0e5"; +@fa-var-commenting: "\f27a"; +@fa-var-commenting-o: "\f27b"; +@fa-var-comments: "\f086"; +@fa-var-comments-o: "\f0e6"; +@fa-var-compass: "\f14e"; +@fa-var-compress: "\f066"; +@fa-var-connectdevelop: "\f20e"; +@fa-var-contao: "\f26d"; +@fa-var-copy: "\f0c5"; +@fa-var-copyright: "\f1f9"; +@fa-var-creative-commons: "\f25e"; +@fa-var-credit-card: "\f09d"; +@fa-var-credit-card-alt: "\f283"; +@fa-var-crop: "\f125"; +@fa-var-crosshairs: "\f05b"; +@fa-var-css3: "\f13c"; +@fa-var-cube: "\f1b2"; +@fa-var-cubes: "\f1b3"; +@fa-var-cut: "\f0c4"; +@fa-var-cutlery: "\f0f5"; +@fa-var-dashboard: "\f0e4"; +@fa-var-dashcube: "\f210"; +@fa-var-database: "\f1c0"; +@fa-var-deaf: "\f2a4"; +@fa-var-deafness: "\f2a4"; +@fa-var-dedent: "\f03b"; +@fa-var-delicious: "\f1a5"; +@fa-var-desktop: "\f108"; +@fa-var-deviantart: "\f1bd"; +@fa-var-diamond: "\f219"; +@fa-var-digg: "\f1a6"; +@fa-var-dollar: "\f155"; +@fa-var-dot-circle-o: "\f192"; +@fa-var-download: "\f019"; +@fa-var-dribbble: "\f17d"; +@fa-var-drivers-license: "\f2c2"; +@fa-var-drivers-license-o: "\f2c3"; +@fa-var-dropbox: "\f16b"; +@fa-var-drupal: "\f1a9"; +@fa-var-edge: "\f282"; +@fa-var-edit: "\f044"; +@fa-var-eercast: "\f2da"; +@fa-var-eject: "\f052"; +@fa-var-ellipsis-h: "\f141"; +@fa-var-ellipsis-v: "\f142"; +@fa-var-empire: "\f1d1"; +@fa-var-envelope: "\f0e0"; +@fa-var-envelope-o: "\f003"; +@fa-var-envelope-open: "\f2b6"; +@fa-var-envelope-open-o: "\f2b7"; +@fa-var-envelope-square: "\f199"; +@fa-var-envira: "\f299"; +@fa-var-eraser: "\f12d"; +@fa-var-etsy: "\f2d7"; +@fa-var-eur: "\f153"; +@fa-var-euro: "\f153"; +@fa-var-exchange: "\f0ec"; +@fa-var-exclamation: "\f12a"; +@fa-var-exclamation-circle: "\f06a"; +@fa-var-exclamation-triangle: "\f071"; +@fa-var-expand: "\f065"; +@fa-var-expeditedssl: "\f23e"; +@fa-var-external-link: "\f08e"; +@fa-var-external-link-square: "\f14c"; +@fa-var-eye: "\f06e"; +@fa-var-eye-slash: "\f070"; +@fa-var-eyedropper: "\f1fb"; +@fa-var-fa: "\f2b4"; +@fa-var-facebook: "\f09a"; +@fa-var-facebook-f: "\f09a"; +@fa-var-facebook-official: "\f230"; +@fa-var-facebook-square: "\f082"; +@fa-var-fast-backward: "\f049"; +@fa-var-fast-forward: "\f050"; +@fa-var-fax: "\f1ac"; +@fa-var-feed: "\f09e"; +@fa-var-female: "\f182"; +@fa-var-fighter-jet: "\f0fb"; +@fa-var-file: "\f15b"; +@fa-var-file-archive-o: "\f1c6"; +@fa-var-file-audio-o: "\f1c7"; +@fa-var-file-code-o: "\f1c9"; +@fa-var-file-excel-o: "\f1c3"; +@fa-var-file-image-o: "\f1c5"; +@fa-var-file-movie-o: "\f1c8"; +@fa-var-file-o: "\f016"; +@fa-var-file-pdf-o: "\f1c1"; +@fa-var-file-photo-o: "\f1c5"; +@fa-var-file-picture-o: "\f1c5"; +@fa-var-file-powerpoint-o: "\f1c4"; +@fa-var-file-sound-o: "\f1c7"; +@fa-var-file-text: "\f15c"; +@fa-var-file-text-o: "\f0f6"; +@fa-var-file-video-o: "\f1c8"; +@fa-var-file-word-o: "\f1c2"; +@fa-var-file-zip-o: "\f1c6"; +@fa-var-files-o: "\f0c5"; +@fa-var-film: "\f008"; +@fa-var-filter: "\f0b0"; +@fa-var-fire: "\f06d"; +@fa-var-fire-extinguisher: "\f134"; +@fa-var-firefox: "\f269"; +@fa-var-first-order: "\f2b0"; +@fa-var-flag: "\f024"; +@fa-var-flag-checkered: "\f11e"; +@fa-var-flag-o: "\f11d"; +@fa-var-flash: "\f0e7"; +@fa-var-flask: "\f0c3"; +@fa-var-flickr: "\f16e"; +@fa-var-floppy-o: "\f0c7"; +@fa-var-folder: "\f07b"; +@fa-var-folder-o: "\f114"; +@fa-var-folder-open: "\f07c"; +@fa-var-folder-open-o: "\f115"; +@fa-var-font: "\f031"; +@fa-var-font-awesome: "\f2b4"; +@fa-var-fonticons: "\f280"; +@fa-var-fort-awesome: "\f286"; +@fa-var-forumbee: "\f211"; +@fa-var-forward: "\f04e"; +@fa-var-foursquare: "\f180"; +@fa-var-free-code-camp: "\f2c5"; +@fa-var-frown-o: "\f119"; +@fa-var-futbol-o: "\f1e3"; +@fa-var-gamepad: "\f11b"; +@fa-var-gavel: "\f0e3"; +@fa-var-gbp: "\f154"; +@fa-var-ge: "\f1d1"; +@fa-var-gear: "\f013"; +@fa-var-gears: "\f085"; +@fa-var-genderless: "\f22d"; +@fa-var-get-pocket: "\f265"; +@fa-var-gg: "\f260"; +@fa-var-gg-circle: "\f261"; +@fa-var-gift: "\f06b"; +@fa-var-git: "\f1d3"; +@fa-var-git-square: "\f1d2"; +@fa-var-github: "\f09b"; +@fa-var-github-alt: "\f113"; +@fa-var-github-square: "\f092"; +@fa-var-gitlab: "\f296"; +@fa-var-gittip: "\f184"; +@fa-var-glass: "\f000"; +@fa-var-glide: "\f2a5"; +@fa-var-glide-g: "\f2a6"; +@fa-var-globe: "\f0ac"; +@fa-var-google: "\f1a0"; +@fa-var-google-plus: "\f0d5"; +@fa-var-google-plus-circle: "\f2b3"; +@fa-var-google-plus-official: "\f2b3"; +@fa-var-google-plus-square: "\f0d4"; +@fa-var-google-wallet: "\f1ee"; +@fa-var-graduation-cap: "\f19d"; +@fa-var-gratipay: "\f184"; +@fa-var-grav: "\f2d6"; +@fa-var-group: "\f0c0"; +@fa-var-h-square: "\f0fd"; +@fa-var-hacker-news: "\f1d4"; +@fa-var-hand-grab-o: "\f255"; +@fa-var-hand-lizard-o: "\f258"; +@fa-var-hand-o-down: "\f0a7"; +@fa-var-hand-o-left: "\f0a5"; +@fa-var-hand-o-right: "\f0a4"; +@fa-var-hand-o-up: "\f0a6"; +@fa-var-hand-paper-o: "\f256"; +@fa-var-hand-peace-o: "\f25b"; +@fa-var-hand-pointer-o: "\f25a"; +@fa-var-hand-rock-o: "\f255"; +@fa-var-hand-scissors-o: "\f257"; +@fa-var-hand-spock-o: "\f259"; +@fa-var-hand-stop-o: "\f256"; +@fa-var-handshake-o: "\f2b5"; +@fa-var-hard-of-hearing: "\f2a4"; +@fa-var-hashtag: "\f292"; +@fa-var-hdd-o: "\f0a0"; +@fa-var-header: "\f1dc"; +@fa-var-headphones: "\f025"; +@fa-var-heart: "\f004"; +@fa-var-heart-o: "\f08a"; +@fa-var-heartbeat: "\f21e"; +@fa-var-history: "\f1da"; +@fa-var-home: "\f015"; +@fa-var-hospital-o: "\f0f8"; +@fa-var-hotel: "\f236"; +@fa-var-hourglass: "\f254"; +@fa-var-hourglass-1: "\f251"; +@fa-var-hourglass-2: "\f252"; +@fa-var-hourglass-3: "\f253"; +@fa-var-hourglass-end: "\f253"; +@fa-var-hourglass-half: "\f252"; +@fa-var-hourglass-o: "\f250"; +@fa-var-hourglass-start: "\f251"; +@fa-var-houzz: "\f27c"; +@fa-var-html5: "\f13b"; +@fa-var-i-cursor: "\f246"; +@fa-var-id-badge: "\f2c1"; +@fa-var-id-card: "\f2c2"; +@fa-var-id-card-o: "\f2c3"; +@fa-var-ils: "\f20b"; +@fa-var-image: "\f03e"; +@fa-var-imdb: "\f2d8"; +@fa-var-inbox: "\f01c"; +@fa-var-indent: "\f03c"; +@fa-var-industry: "\f275"; +@fa-var-info: "\f129"; +@fa-var-info-circle: "\f05a"; +@fa-var-inr: "\f156"; +@fa-var-instagram: "\f16d"; +@fa-var-institution: "\f19c"; +@fa-var-internet-explorer: "\f26b"; +@fa-var-intersex: "\f224"; +@fa-var-ioxhost: "\f208"; +@fa-var-italic: "\f033"; +@fa-var-joomla: "\f1aa"; +@fa-var-jpy: "\f157"; +@fa-var-jsfiddle: "\f1cc"; +@fa-var-key: "\f084"; +@fa-var-keyboard-o: "\f11c"; +@fa-var-krw: "\f159"; +@fa-var-language: "\f1ab"; +@fa-var-laptop: "\f109"; +@fa-var-lastfm: "\f202"; +@fa-var-lastfm-square: "\f203"; +@fa-var-leaf: "\f06c"; +@fa-var-leanpub: "\f212"; +@fa-var-legal: "\f0e3"; +@fa-var-lemon-o: "\f094"; +@fa-var-level-down: "\f149"; +@fa-var-level-up: "\f148"; +@fa-var-life-bouy: "\f1cd"; +@fa-var-life-buoy: "\f1cd"; +@fa-var-life-ring: "\f1cd"; +@fa-var-life-saver: "\f1cd"; +@fa-var-lightbulb-o: "\f0eb"; +@fa-var-line-chart: "\f201"; +@fa-var-link: "\f0c1"; +@fa-var-linkedin: "\f0e1"; +@fa-var-linkedin-square: "\f08c"; +@fa-var-linode: "\f2b8"; +@fa-var-linux: "\f17c"; +@fa-var-list: "\f03a"; +@fa-var-list-alt: "\f022"; +@fa-var-list-ol: "\f0cb"; +@fa-var-list-ul: "\f0ca"; +@fa-var-location-arrow: "\f124"; +@fa-var-lock: "\f023"; +@fa-var-long-arrow-down: "\f175"; +@fa-var-long-arrow-left: "\f177"; +@fa-var-long-arrow-right: "\f178"; +@fa-var-long-arrow-up: "\f176"; +@fa-var-low-vision: "\f2a8"; +@fa-var-magic: "\f0d0"; +@fa-var-magnet: "\f076"; +@fa-var-mail-forward: "\f064"; +@fa-var-mail-reply: "\f112"; +@fa-var-mail-reply-all: "\f122"; +@fa-var-male: "\f183"; +@fa-var-map: "\f279"; +@fa-var-map-marker: "\f041"; +@fa-var-map-o: "\f278"; +@fa-var-map-pin: "\f276"; +@fa-var-map-signs: "\f277"; +@fa-var-mars: "\f222"; +@fa-var-mars-double: "\f227"; +@fa-var-mars-stroke: "\f229"; +@fa-var-mars-stroke-h: "\f22b"; +@fa-var-mars-stroke-v: "\f22a"; +@fa-var-maxcdn: "\f136"; +@fa-var-meanpath: "\f20c"; +@fa-var-medium: "\f23a"; +@fa-var-medkit: "\f0fa"; +@fa-var-meetup: "\f2e0"; +@fa-var-meh-o: "\f11a"; +@fa-var-mercury: "\f223"; +@fa-var-microchip: "\f2db"; +@fa-var-microphone: "\f130"; +@fa-var-microphone-slash: "\f131"; +@fa-var-minus: "\f068"; +@fa-var-minus-circle: "\f056"; +@fa-var-minus-square: "\f146"; +@fa-var-minus-square-o: "\f147"; +@fa-var-mixcloud: "\f289"; +@fa-var-mobile: "\f10b"; +@fa-var-mobile-phone: "\f10b"; +@fa-var-modx: "\f285"; +@fa-var-money: "\f0d6"; +@fa-var-moon-o: "\f186"; +@fa-var-mortar-board: "\f19d"; +@fa-var-motorcycle: "\f21c"; +@fa-var-mouse-pointer: "\f245"; +@fa-var-music: "\f001"; +@fa-var-navicon: "\f0c9"; +@fa-var-neuter: "\f22c"; +@fa-var-newspaper-o: "\f1ea"; +@fa-var-object-group: "\f247"; +@fa-var-object-ungroup: "\f248"; +@fa-var-odnoklassniki: "\f263"; +@fa-var-odnoklassniki-square: "\f264"; +@fa-var-opencart: "\f23d"; +@fa-var-openid: "\f19b"; +@fa-var-opera: "\f26a"; +@fa-var-optin-monster: "\f23c"; +@fa-var-outdent: "\f03b"; +@fa-var-pagelines: "\f18c"; +@fa-var-paint-brush: "\f1fc"; +@fa-var-paper-plane: "\f1d8"; +@fa-var-paper-plane-o: "\f1d9"; +@fa-var-paperclip: "\f0c6"; +@fa-var-paragraph: "\f1dd"; +@fa-var-paste: "\f0ea"; +@fa-var-pause: "\f04c"; +@fa-var-pause-circle: "\f28b"; +@fa-var-pause-circle-o: "\f28c"; +@fa-var-paw: "\f1b0"; +@fa-var-paypal: "\f1ed"; +@fa-var-pencil: "\f040"; +@fa-var-pencil-square: "\f14b"; +@fa-var-pencil-square-o: "\f044"; +@fa-var-percent: "\f295"; +@fa-var-phone: "\f095"; +@fa-var-phone-square: "\f098"; +@fa-var-photo: "\f03e"; +@fa-var-picture-o: "\f03e"; +@fa-var-pie-chart: "\f200"; +@fa-var-pied-piper: "\f2ae"; +@fa-var-pied-piper-alt: "\f1a8"; +@fa-var-pied-piper-pp: "\f1a7"; +@fa-var-pinterest: "\f0d2"; +@fa-var-pinterest-p: "\f231"; +@fa-var-pinterest-square: "\f0d3"; +@fa-var-plane: "\f072"; +@fa-var-play: "\f04b"; +@fa-var-play-circle: "\f144"; +@fa-var-play-circle-o: "\f01d"; +@fa-var-plug: "\f1e6"; +@fa-var-plus: "\f067"; +@fa-var-plus-circle: "\f055"; +@fa-var-plus-square: "\f0fe"; +@fa-var-plus-square-o: "\f196"; +@fa-var-podcast: "\f2ce"; +@fa-var-power-off: "\f011"; +@fa-var-print: "\f02f"; +@fa-var-product-hunt: "\f288"; +@fa-var-puzzle-piece: "\f12e"; +@fa-var-qq: "\f1d6"; +@fa-var-qrcode: "\f029"; +@fa-var-question: "\f128"; +@fa-var-question-circle: "\f059"; +@fa-var-question-circle-o: "\f29c"; +@fa-var-quora: "\f2c4"; +@fa-var-quote-left: "\f10d"; +@fa-var-quote-right: "\f10e"; +@fa-var-ra: "\f1d0"; +@fa-var-random: "\f074"; +@fa-var-ravelry: "\f2d9"; +@fa-var-rebel: "\f1d0"; +@fa-var-recycle: "\f1b8"; +@fa-var-reddit: "\f1a1"; +@fa-var-reddit-alien: "\f281"; +@fa-var-reddit-square: "\f1a2"; +@fa-var-refresh: "\f021"; +@fa-var-registered: "\f25d"; +@fa-var-remove: "\f00d"; +@fa-var-renren: "\f18b"; +@fa-var-reorder: "\f0c9"; +@fa-var-repeat: "\f01e"; +@fa-var-reply: "\f112"; +@fa-var-reply-all: "\f122"; +@fa-var-resistance: "\f1d0"; +@fa-var-retweet: "\f079"; +@fa-var-rmb: "\f157"; +@fa-var-road: "\f018"; +@fa-var-rocket: "\f135"; +@fa-var-rotate-left: "\f0e2"; +@fa-var-rotate-right: "\f01e"; +@fa-var-rouble: "\f158"; +@fa-var-rss: "\f09e"; +@fa-var-rss-square: "\f143"; +@fa-var-rub: "\f158"; +@fa-var-ruble: "\f158"; +@fa-var-rupee: "\f156"; +@fa-var-s15: "\f2cd"; +@fa-var-safari: "\f267"; +@fa-var-save: "\f0c7"; +@fa-var-scissors: "\f0c4"; +@fa-var-scribd: "\f28a"; +@fa-var-search: "\f002"; +@fa-var-search-minus: "\f010"; +@fa-var-search-plus: "\f00e"; +@fa-var-sellsy: "\f213"; +@fa-var-send: "\f1d8"; +@fa-var-send-o: "\f1d9"; +@fa-var-server: "\f233"; +@fa-var-share: "\f064"; +@fa-var-share-alt: "\f1e0"; +@fa-var-share-alt-square: "\f1e1"; +@fa-var-share-square: "\f14d"; +@fa-var-share-square-o: "\f045"; +@fa-var-shekel: "\f20b"; +@fa-var-sheqel: "\f20b"; +@fa-var-shield: "\f132"; +@fa-var-ship: "\f21a"; +@fa-var-shirtsinbulk: "\f214"; +@fa-var-shopping-bag: "\f290"; +@fa-var-shopping-basket: "\f291"; +@fa-var-shopping-cart: "\f07a"; +@fa-var-shower: "\f2cc"; +@fa-var-sign-in: "\f090"; +@fa-var-sign-language: "\f2a7"; +@fa-var-sign-out: "\f08b"; +@fa-var-signal: "\f012"; +@fa-var-signing: "\f2a7"; +@fa-var-simplybuilt: "\f215"; +@fa-var-sitemap: "\f0e8"; +@fa-var-skyatlas: "\f216"; +@fa-var-skype: "\f17e"; +@fa-var-slack: "\f198"; +@fa-var-sliders: "\f1de"; +@fa-var-slideshare: "\f1e7"; +@fa-var-smile-o: "\f118"; +@fa-var-snapchat: "\f2ab"; +@fa-var-snapchat-ghost: "\f2ac"; +@fa-var-snapchat-square: "\f2ad"; +@fa-var-snowflake-o: "\f2dc"; +@fa-var-soccer-ball-o: "\f1e3"; +@fa-var-sort: "\f0dc"; +@fa-var-sort-alpha-asc: "\f15d"; +@fa-var-sort-alpha-desc: "\f15e"; +@fa-var-sort-amount-asc: "\f160"; +@fa-var-sort-amount-desc: "\f161"; +@fa-var-sort-asc: "\f0de"; +@fa-var-sort-desc: "\f0dd"; +@fa-var-sort-down: "\f0dd"; +@fa-var-sort-numeric-asc: "\f162"; +@fa-var-sort-numeric-desc: "\f163"; +@fa-var-sort-up: "\f0de"; +@fa-var-soundcloud: "\f1be"; +@fa-var-space-shuttle: "\f197"; +@fa-var-spinner: "\f110"; +@fa-var-spoon: "\f1b1"; +@fa-var-spotify: "\f1bc"; +@fa-var-square: "\f0c8"; +@fa-var-square-o: "\f096"; +@fa-var-stack-exchange: "\f18d"; +@fa-var-stack-overflow: "\f16c"; +@fa-var-star: "\f005"; +@fa-var-star-half: "\f089"; +@fa-var-star-half-empty: "\f123"; +@fa-var-star-half-full: "\f123"; +@fa-var-star-half-o: "\f123"; +@fa-var-star-o: "\f006"; +@fa-var-steam: "\f1b6"; +@fa-var-steam-square: "\f1b7"; +@fa-var-step-backward: "\f048"; +@fa-var-step-forward: "\f051"; +@fa-var-stethoscope: "\f0f1"; +@fa-var-sticky-note: "\f249"; +@fa-var-sticky-note-o: "\f24a"; +@fa-var-stop: "\f04d"; +@fa-var-stop-circle: "\f28d"; +@fa-var-stop-circle-o: "\f28e"; +@fa-var-street-view: "\f21d"; +@fa-var-strikethrough: "\f0cc"; +@fa-var-stumbleupon: "\f1a4"; +@fa-var-stumbleupon-circle: "\f1a3"; +@fa-var-subscript: "\f12c"; +@fa-var-subway: "\f239"; +@fa-var-suitcase: "\f0f2"; +@fa-var-sun-o: "\f185"; +@fa-var-superpowers: "\f2dd"; +@fa-var-superscript: "\f12b"; +@fa-var-support: "\f1cd"; +@fa-var-table: "\f0ce"; +@fa-var-tablet: "\f10a"; +@fa-var-tachometer: "\f0e4"; +@fa-var-tag: "\f02b"; +@fa-var-tags: "\f02c"; +@fa-var-tasks: "\f0ae"; +@fa-var-taxi: "\f1ba"; +@fa-var-telegram: "\f2c6"; +@fa-var-television: "\f26c"; +@fa-var-tencent-weibo: "\f1d5"; +@fa-var-terminal: "\f120"; +@fa-var-text-height: "\f034"; +@fa-var-text-width: "\f035"; +@fa-var-th: "\f00a"; +@fa-var-th-large: "\f009"; +@fa-var-th-list: "\f00b"; +@fa-var-themeisle: "\f2b2"; +@fa-var-thermometer: "\f2c7"; +@fa-var-thermometer-0: "\f2cb"; +@fa-var-thermometer-1: "\f2ca"; +@fa-var-thermometer-2: "\f2c9"; +@fa-var-thermometer-3: "\f2c8"; +@fa-var-thermometer-4: "\f2c7"; +@fa-var-thermometer-empty: "\f2cb"; +@fa-var-thermometer-full: "\f2c7"; +@fa-var-thermometer-half: "\f2c9"; +@fa-var-thermometer-quarter: "\f2ca"; +@fa-var-thermometer-three-quarters: "\f2c8"; +@fa-var-thumb-tack: "\f08d"; +@fa-var-thumbs-down: "\f165"; +@fa-var-thumbs-o-down: "\f088"; +@fa-var-thumbs-o-up: "\f087"; +@fa-var-thumbs-up: "\f164"; +@fa-var-ticket: "\f145"; +@fa-var-times: "\f00d"; +@fa-var-times-circle: "\f057"; +@fa-var-times-circle-o: "\f05c"; +@fa-var-times-rectangle: "\f2d3"; +@fa-var-times-rectangle-o: "\f2d4"; +@fa-var-tint: "\f043"; +@fa-var-toggle-down: "\f150"; +@fa-var-toggle-left: "\f191"; +@fa-var-toggle-off: "\f204"; +@fa-var-toggle-on: "\f205"; +@fa-var-toggle-right: "\f152"; +@fa-var-toggle-up: "\f151"; +@fa-var-trademark: "\f25c"; +@fa-var-train: "\f238"; +@fa-var-transgender: "\f224"; +@fa-var-transgender-alt: "\f225"; +@fa-var-trash: "\f1f8"; +@fa-var-trash-o: "\f014"; +@fa-var-tree: "\f1bb"; +@fa-var-trello: "\f181"; +@fa-var-tripadvisor: "\f262"; +@fa-var-trophy: "\f091"; +@fa-var-truck: "\f0d1"; +@fa-var-try: "\f195"; +@fa-var-tty: "\f1e4"; +@fa-var-tumblr: "\f173"; +@fa-var-tumblr-square: "\f174"; +@fa-var-turkish-lira: "\f195"; +@fa-var-tv: "\f26c"; +@fa-var-twitch: "\f1e8"; +@fa-var-twitter: "\f099"; +@fa-var-twitter-square: "\f081"; +@fa-var-umbrella: "\f0e9"; +@fa-var-underline: "\f0cd"; +@fa-var-undo: "\f0e2"; +@fa-var-universal-access: "\f29a"; +@fa-var-university: "\f19c"; +@fa-var-unlink: "\f127"; +@fa-var-unlock: "\f09c"; +@fa-var-unlock-alt: "\f13e"; +@fa-var-unsorted: "\f0dc"; +@fa-var-upload: "\f093"; +@fa-var-usb: "\f287"; +@fa-var-usd: "\f155"; +@fa-var-user: "\f007"; +@fa-var-user-circle: "\f2bd"; +@fa-var-user-circle-o: "\f2be"; +@fa-var-user-md: "\f0f0"; +@fa-var-user-o: "\f2c0"; +@fa-var-user-plus: "\f234"; +@fa-var-user-secret: "\f21b"; +@fa-var-user-times: "\f235"; +@fa-var-users: "\f0c0"; +@fa-var-vcard: "\f2bb"; +@fa-var-vcard-o: "\f2bc"; +@fa-var-venus: "\f221"; +@fa-var-venus-double: "\f226"; +@fa-var-venus-mars: "\f228"; +@fa-var-viacoin: "\f237"; +@fa-var-viadeo: "\f2a9"; +@fa-var-viadeo-square: "\f2aa"; +@fa-var-video-camera: "\f03d"; +@fa-var-vimeo: "\f27d"; +@fa-var-vimeo-square: "\f194"; +@fa-var-vine: "\f1ca"; +@fa-var-vk: "\f189"; +@fa-var-volume-control-phone: "\f2a0"; +@fa-var-volume-down: "\f027"; +@fa-var-volume-off: "\f026"; +@fa-var-volume-up: "\f028"; +@fa-var-warning: "\f071"; +@fa-var-wechat: "\f1d7"; +@fa-var-weibo: "\f18a"; +@fa-var-weixin: "\f1d7"; +@fa-var-whatsapp: "\f232"; +@fa-var-wheelchair: "\f193"; +@fa-var-wheelchair-alt: "\f29b"; +@fa-var-wifi: "\f1eb"; +@fa-var-wikipedia-w: "\f266"; +@fa-var-window-close: "\f2d3"; +@fa-var-window-close-o: "\f2d4"; +@fa-var-window-maximize: "\f2d0"; +@fa-var-window-minimize: "\f2d1"; +@fa-var-window-restore: "\f2d2"; +@fa-var-windows: "\f17a"; +@fa-var-won: "\f159"; +@fa-var-wordpress: "\f19a"; +@fa-var-wpbeginner: "\f297"; +@fa-var-wpexplorer: "\f2de"; +@fa-var-wpforms: "\f298"; +@fa-var-wrench: "\f0ad"; +@fa-var-xing: "\f168"; +@fa-var-xing-square: "\f169"; +@fa-var-y-combinator: "\f23b"; +@fa-var-y-combinator-square: "\f1d4"; +@fa-var-yahoo: "\f19e"; +@fa-var-yc: "\f23b"; +@fa-var-yc-square: "\f1d4"; +@fa-var-yelp: "\f1e9"; +@fa-var-yen: "\f157"; +@fa-var-yoast: "\f2b1"; +@fa-var-youtube: "\f167"; +@fa-var-youtube-play: "\f16a"; +@fa-var-youtube-square: "\f166"; + diff --git a/dashboard/src/assets/font-awesome/scss/_animated.scss b/dashboard/src/assets/font-awesome/scss/_animated.scss new file mode 100644 index 00000000..284de1ce --- /dev/null +++ b/dashboard/src/assets/font-awesome/scss/_animated.scss @@ -0,0 +1,50 @@ +/*! + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Spinning Icons +// -------------------------- + +.#{$fa-css-prefix}-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; +} + +.#{$fa-css-prefix}-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); +} + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} diff --git a/dashboard/src/assets/font-awesome/scss/_bordered-pulled.scss b/dashboard/src/assets/font-awesome/scss/_bordered-pulled.scss new file mode 100644 index 00000000..44b4dda3 --- /dev/null +++ b/dashboard/src/assets/font-awesome/scss/_bordered-pulled.scss @@ -0,0 +1,41 @@ +/*! + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Bordered & Pulled +// ------------------------- + +.#{$fa-css-prefix}-border { + padding: .2em .25em .15em; + border: solid .08em $fa-border-color; + border-radius: .1em; +} + +.#{$fa-css-prefix}-pull-left { float: left; } +.#{$fa-css-prefix}-pull-right { float: right; } + +.#{$fa-css-prefix} { + &.#{$fa-css-prefix}-pull-left { margin-right: .3em; } + &.#{$fa-css-prefix}-pull-right { margin-left: .3em; } +} + +/* Deprecated as of 4.4.0 */ +.pull-right { float: right; } +.pull-left { float: left; } + +.#{$fa-css-prefix} { + &.pull-left { margin-right: .3em; } + &.pull-right { margin-left: .3em; } +} diff --git a/dashboard/src/assets/font-awesome/scss/_core.scss b/dashboard/src/assets/font-awesome/scss/_core.scss new file mode 100644 index 00000000..1b7d9383 --- /dev/null +++ b/dashboard/src/assets/font-awesome/scss/_core.scss @@ -0,0 +1,28 @@ +/*! + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Base Class Definition +// ------------------------- + +.#{$fa-css-prefix} { + display: inline-block; + font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration + font-size: inherit; // can't have font-size inherit on line above, so need to override + text-rendering: auto; // optimizelegibility throws things off #1094 + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + +} diff --git a/dashboard/src/assets/font-awesome/scss/_fixed-width.scss b/dashboard/src/assets/font-awesome/scss/_fixed-width.scss new file mode 100644 index 00000000..bdcd3323 --- /dev/null +++ b/dashboard/src/assets/font-awesome/scss/_fixed-width.scss @@ -0,0 +1,22 @@ +/*! + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Fixed Width Icons +// ------------------------- +.#{$fa-css-prefix}-fw { + width: (18em / 14); + text-align: center; +} diff --git a/dashboard/src/assets/font-awesome/scss/_icons.scss b/dashboard/src/assets/font-awesome/scss/_icons.scss new file mode 100644 index 00000000..5ebcbc69 --- /dev/null +++ b/dashboard/src/assets/font-awesome/scss/_icons.scss @@ -0,0 +1,805 @@ +/*! + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ + +.#{$fa-css-prefix}-glass:before { content: $fa-var-glass; } +.#{$fa-css-prefix}-music:before { content: $fa-var-music; } +.#{$fa-css-prefix}-search:before { content: $fa-var-search; } +.#{$fa-css-prefix}-envelope-o:before { content: $fa-var-envelope-o; } +.#{$fa-css-prefix}-heart:before { content: $fa-var-heart; } +.#{$fa-css-prefix}-star:before { content: $fa-var-star; } +.#{$fa-css-prefix}-star-o:before { content: $fa-var-star-o; } +.#{$fa-css-prefix}-user:before { content: $fa-var-user; } +.#{$fa-css-prefix}-film:before { content: $fa-var-film; } +.#{$fa-css-prefix}-th-large:before { content: $fa-var-th-large; } +.#{$fa-css-prefix}-th:before { content: $fa-var-th; } +.#{$fa-css-prefix}-th-list:before { content: $fa-var-th-list; } +.#{$fa-css-prefix}-check:before { content: $fa-var-check; } +.#{$fa-css-prefix}-remove:before, +.#{$fa-css-prefix}-close:before, +.#{$fa-css-prefix}-times:before { content: $fa-var-times; } +.#{$fa-css-prefix}-search-plus:before { content: $fa-var-search-plus; } +.#{$fa-css-prefix}-search-minus:before { content: $fa-var-search-minus; } +.#{$fa-css-prefix}-power-off:before { content: $fa-var-power-off; } +.#{$fa-css-prefix}-signal:before { content: $fa-var-signal; } +.#{$fa-css-prefix}-gear:before, +.#{$fa-css-prefix}-cog:before { content: $fa-var-cog; } +.#{$fa-css-prefix}-trash-o:before { content: $fa-var-trash-o; } +.#{$fa-css-prefix}-home:before { content: $fa-var-home; } +.#{$fa-css-prefix}-file-o:before { content: $fa-var-file-o; } +.#{$fa-css-prefix}-clock-o:before { content: $fa-var-clock-o; } +.#{$fa-css-prefix}-road:before { content: $fa-var-road; } +.#{$fa-css-prefix}-download:before { content: $fa-var-download; } +.#{$fa-css-prefix}-arrow-circle-o-down:before { content: $fa-var-arrow-circle-o-down; } +.#{$fa-css-prefix}-arrow-circle-o-up:before { content: $fa-var-arrow-circle-o-up; } +.#{$fa-css-prefix}-inbox:before { content: $fa-var-inbox; } +.#{$fa-css-prefix}-play-circle-o:before { content: $fa-var-play-circle-o; } +.#{$fa-css-prefix}-rotate-right:before, +.#{$fa-css-prefix}-repeat:before { content: $fa-var-repeat; } +.#{$fa-css-prefix}-refresh:before { content: $fa-var-refresh; } +.#{$fa-css-prefix}-list-alt:before { content: $fa-var-list-alt; } +.#{$fa-css-prefix}-lock:before { content: $fa-var-lock; } +.#{$fa-css-prefix}-flag:before { content: $fa-var-flag; } +.#{$fa-css-prefix}-headphones:before { content: $fa-var-headphones; } +.#{$fa-css-prefix}-volume-off:before { content: $fa-var-volume-off; } +.#{$fa-css-prefix}-volume-down:before { content: $fa-var-volume-down; } +.#{$fa-css-prefix}-volume-up:before { content: $fa-var-volume-up; } +.#{$fa-css-prefix}-qrcode:before { content: $fa-var-qrcode; } +.#{$fa-css-prefix}-barcode:before { content: $fa-var-barcode; } +.#{$fa-css-prefix}-tag:before { content: $fa-var-tag; } +.#{$fa-css-prefix}-tags:before { content: $fa-var-tags; } +.#{$fa-css-prefix}-book:before { content: $fa-var-book; } +.#{$fa-css-prefix}-bookmark:before { content: $fa-var-bookmark; } +.#{$fa-css-prefix}-print:before { content: $fa-var-print; } +.#{$fa-css-prefix}-camera:before { content: $fa-var-camera; } +.#{$fa-css-prefix}-font:before { content: $fa-var-font; } +.#{$fa-css-prefix}-bold:before { content: $fa-var-bold; } +.#{$fa-css-prefix}-italic:before { content: $fa-var-italic; } +.#{$fa-css-prefix}-text-height:before { content: $fa-var-text-height; } +.#{$fa-css-prefix}-text-width:before { content: $fa-var-text-width; } +.#{$fa-css-prefix}-align-left:before { content: $fa-var-align-left; } +.#{$fa-css-prefix}-align-center:before { content: $fa-var-align-center; } +.#{$fa-css-prefix}-align-right:before { content: $fa-var-align-right; } +.#{$fa-css-prefix}-align-justify:before { content: $fa-var-align-justify; } +.#{$fa-css-prefix}-list:before { content: $fa-var-list; } +.#{$fa-css-prefix}-dedent:before, +.#{$fa-css-prefix}-outdent:before { content: $fa-var-outdent; } +.#{$fa-css-prefix}-indent:before { content: $fa-var-indent; } +.#{$fa-css-prefix}-video-camera:before { content: $fa-var-video-camera; } +.#{$fa-css-prefix}-photo:before, +.#{$fa-css-prefix}-image:before, +.#{$fa-css-prefix}-picture-o:before { content: $fa-var-picture-o; } +.#{$fa-css-prefix}-pencil:before { content: $fa-var-pencil; } +.#{$fa-css-prefix}-map-marker:before { content: $fa-var-map-marker; } +.#{$fa-css-prefix}-adjust:before { content: $fa-var-adjust; } +.#{$fa-css-prefix}-tint:before { content: $fa-var-tint; } +.#{$fa-css-prefix}-edit:before, +.#{$fa-css-prefix}-pencil-square-o:before { content: $fa-var-pencil-square-o; } +.#{$fa-css-prefix}-share-square-o:before { content: $fa-var-share-square-o; } +.#{$fa-css-prefix}-check-square-o:before { content: $fa-var-check-square-o; } +.#{$fa-css-prefix}-arrows:before { content: $fa-var-arrows; } +.#{$fa-css-prefix}-step-backward:before { content: $fa-var-step-backward; } +.#{$fa-css-prefix}-fast-backward:before { content: $fa-var-fast-backward; } +.#{$fa-css-prefix}-backward:before { content: $fa-var-backward; } +.#{$fa-css-prefix}-play:before { content: $fa-var-play; } +.#{$fa-css-prefix}-pause:before { content: $fa-var-pause; } +.#{$fa-css-prefix}-stop:before { content: $fa-var-stop; } +.#{$fa-css-prefix}-forward:before { content: $fa-var-forward; } +.#{$fa-css-prefix}-fast-forward:before { content: $fa-var-fast-forward; } +.#{$fa-css-prefix}-step-forward:before { content: $fa-var-step-forward; } +.#{$fa-css-prefix}-eject:before { content: $fa-var-eject; } +.#{$fa-css-prefix}-chevron-left:before { content: $fa-var-chevron-left; } +.#{$fa-css-prefix}-chevron-right:before { content: $fa-var-chevron-right; } +.#{$fa-css-prefix}-plus-circle:before { content: $fa-var-plus-circle; } +.#{$fa-css-prefix}-minus-circle:before { content: $fa-var-minus-circle; } +.#{$fa-css-prefix}-times-circle:before { content: $fa-var-times-circle; } +.#{$fa-css-prefix}-check-circle:before { content: $fa-var-check-circle; } +.#{$fa-css-prefix}-question-circle:before { content: $fa-var-question-circle; } +.#{$fa-css-prefix}-info-circle:before { content: $fa-var-info-circle; } +.#{$fa-css-prefix}-crosshairs:before { content: $fa-var-crosshairs; } +.#{$fa-css-prefix}-times-circle-o:before { content: $fa-var-times-circle-o; } +.#{$fa-css-prefix}-check-circle-o:before { content: $fa-var-check-circle-o; } +.#{$fa-css-prefix}-ban:before { content: $fa-var-ban; } +.#{$fa-css-prefix}-arrow-left:before { content: $fa-var-arrow-left; } +.#{$fa-css-prefix}-arrow-right:before { content: $fa-var-arrow-right; } +.#{$fa-css-prefix}-arrow-up:before { content: $fa-var-arrow-up; } +.#{$fa-css-prefix}-arrow-down:before { content: $fa-var-arrow-down; } +.#{$fa-css-prefix}-mail-forward:before, +.#{$fa-css-prefix}-share:before { content: $fa-var-share; } +.#{$fa-css-prefix}-expand:before { content: $fa-var-expand; } +.#{$fa-css-prefix}-compress:before { content: $fa-var-compress; } +.#{$fa-css-prefix}-plus:before { content: $fa-var-plus; } +.#{$fa-css-prefix}-minus:before { content: $fa-var-minus; } +.#{$fa-css-prefix}-asterisk:before { content: $fa-var-asterisk; } +.#{$fa-css-prefix}-exclamation-circle:before { content: $fa-var-exclamation-circle; } +.#{$fa-css-prefix}-gift:before { content: $fa-var-gift; } +.#{$fa-css-prefix}-leaf:before { content: $fa-var-leaf; } +.#{$fa-css-prefix}-fire:before { content: $fa-var-fire; } +.#{$fa-css-prefix}-eye:before { content: $fa-var-eye; } +.#{$fa-css-prefix}-eye-slash:before { content: $fa-var-eye-slash; } +.#{$fa-css-prefix}-warning:before, +.#{$fa-css-prefix}-exclamation-triangle:before { content: $fa-var-exclamation-triangle; } +.#{$fa-css-prefix}-plane:before { content: $fa-var-plane; } +.#{$fa-css-prefix}-calendar:before { content: $fa-var-calendar; } +.#{$fa-css-prefix}-random:before { content: $fa-var-random; } +.#{$fa-css-prefix}-comment:before { content: $fa-var-comment; } +.#{$fa-css-prefix}-magnet:before { content: $fa-var-magnet; } +.#{$fa-css-prefix}-chevron-up:before { content: $fa-var-chevron-up; } +.#{$fa-css-prefix}-chevron-down:before { content: $fa-var-chevron-down; } +.#{$fa-css-prefix}-retweet:before { content: $fa-var-retweet; } +.#{$fa-css-prefix}-shopping-cart:before { content: $fa-var-shopping-cart; } +.#{$fa-css-prefix}-folder:before { content: $fa-var-folder; } +.#{$fa-css-prefix}-folder-open:before { content: $fa-var-folder-open; } +.#{$fa-css-prefix}-arrows-v:before { content: $fa-var-arrows-v; } +.#{$fa-css-prefix}-arrows-h:before { content: $fa-var-arrows-h; } +.#{$fa-css-prefix}-bar-chart-o:before, +.#{$fa-css-prefix}-bar-chart:before { content: $fa-var-bar-chart; } +.#{$fa-css-prefix}-twitter-square:before { content: $fa-var-twitter-square; } +.#{$fa-css-prefix}-facebook-square:before { content: $fa-var-facebook-square; } +.#{$fa-css-prefix}-camera-retro:before { content: $fa-var-camera-retro; } +.#{$fa-css-prefix}-key:before { content: $fa-var-key; } +.#{$fa-css-prefix}-gears:before, +.#{$fa-css-prefix}-cogs:before { content: $fa-var-cogs; } +.#{$fa-css-prefix}-comments:before { content: $fa-var-comments; } +.#{$fa-css-prefix}-thumbs-o-up:before { content: $fa-var-thumbs-o-up; } +.#{$fa-css-prefix}-thumbs-o-down:before { content: $fa-var-thumbs-o-down; } +.#{$fa-css-prefix}-star-half:before { content: $fa-var-star-half; } +.#{$fa-css-prefix}-heart-o:before { content: $fa-var-heart-o; } +.#{$fa-css-prefix}-sign-out:before { content: $fa-var-sign-out; } +.#{$fa-css-prefix}-linkedin-square:before { content: $fa-var-linkedin-square; } +.#{$fa-css-prefix}-thumb-tack:before { content: $fa-var-thumb-tack; } +.#{$fa-css-prefix}-external-link:before { content: $fa-var-external-link; } +.#{$fa-css-prefix}-sign-in:before { content: $fa-var-sign-in; } +.#{$fa-css-prefix}-trophy:before { content: $fa-var-trophy; } +.#{$fa-css-prefix}-github-square:before { content: $fa-var-github-square; } +.#{$fa-css-prefix}-upload:before { content: $fa-var-upload; } +.#{$fa-css-prefix}-lemon-o:before { content: $fa-var-lemon-o; } +.#{$fa-css-prefix}-phone:before { content: $fa-var-phone; } +.#{$fa-css-prefix}-square-o:before { content: $fa-var-square-o; } +.#{$fa-css-prefix}-bookmark-o:before { content: $fa-var-bookmark-o; } +.#{$fa-css-prefix}-phone-square:before { content: $fa-var-phone-square; } +.#{$fa-css-prefix}-twitter:before { content: $fa-var-twitter; } +.#{$fa-css-prefix}-facebook-f:before, +.#{$fa-css-prefix}-facebook:before { content: $fa-var-facebook; } +.#{$fa-css-prefix}-github:before { content: $fa-var-github; } +.#{$fa-css-prefix}-unlock:before { content: $fa-var-unlock; } +.#{$fa-css-prefix}-credit-card:before { content: $fa-var-credit-card; } +.#{$fa-css-prefix}-feed:before, +.#{$fa-css-prefix}-rss:before { content: $fa-var-rss; } +.#{$fa-css-prefix}-hdd-o:before { content: $fa-var-hdd-o; } +.#{$fa-css-prefix}-bullhorn:before { content: $fa-var-bullhorn; } +.#{$fa-css-prefix}-bell:before { content: $fa-var-bell; } +.#{$fa-css-prefix}-certificate:before { content: $fa-var-certificate; } +.#{$fa-css-prefix}-hand-o-right:before { content: $fa-var-hand-o-right; } +.#{$fa-css-prefix}-hand-o-left:before { content: $fa-var-hand-o-left; } +.#{$fa-css-prefix}-hand-o-up:before { content: $fa-var-hand-o-up; } +.#{$fa-css-prefix}-hand-o-down:before { content: $fa-var-hand-o-down; } +.#{$fa-css-prefix}-arrow-circle-left:before { content: $fa-var-arrow-circle-left; } +.#{$fa-css-prefix}-arrow-circle-right:before { content: $fa-var-arrow-circle-right; } +.#{$fa-css-prefix}-arrow-circle-up:before { content: $fa-var-arrow-circle-up; } +.#{$fa-css-prefix}-arrow-circle-down:before { content: $fa-var-arrow-circle-down; } +.#{$fa-css-prefix}-globe:before { content: $fa-var-globe; } +.#{$fa-css-prefix}-wrench:before { content: $fa-var-wrench; } +.#{$fa-css-prefix}-tasks:before { content: $fa-var-tasks; } +.#{$fa-css-prefix}-filter:before { content: $fa-var-filter; } +.#{$fa-css-prefix}-briefcase:before { content: $fa-var-briefcase; } +.#{$fa-css-prefix}-arrows-alt:before { content: $fa-var-arrows-alt; } +.#{$fa-css-prefix}-group:before, +.#{$fa-css-prefix}-users:before { content: $fa-var-users; } +.#{$fa-css-prefix}-chain:before, +.#{$fa-css-prefix}-link:before { content: $fa-var-link; } +.#{$fa-css-prefix}-cloud:before { content: $fa-var-cloud; } +.#{$fa-css-prefix}-flask:before { content: $fa-var-flask; } +.#{$fa-css-prefix}-cut:before, +.#{$fa-css-prefix}-scissors:before { content: $fa-var-scissors; } +.#{$fa-css-prefix}-copy:before, +.#{$fa-css-prefix}-files-o:before { content: $fa-var-files-o; } +.#{$fa-css-prefix}-paperclip:before { content: $fa-var-paperclip; } +.#{$fa-css-prefix}-save:before, +.#{$fa-css-prefix}-floppy-o:before { content: $fa-var-floppy-o; } +.#{$fa-css-prefix}-square:before { content: $fa-var-square; } +.#{$fa-css-prefix}-navicon:before, +.#{$fa-css-prefix}-reorder:before, +.#{$fa-css-prefix}-bars:before { content: $fa-var-bars; } +.#{$fa-css-prefix}-list-ul:before { content: $fa-var-list-ul; } +.#{$fa-css-prefix}-list-ol:before { content: $fa-var-list-ol; } +.#{$fa-css-prefix}-strikethrough:before { content: $fa-var-strikethrough; } +.#{$fa-css-prefix}-underline:before { content: $fa-var-underline; } +.#{$fa-css-prefix}-table:before { content: $fa-var-table; } +.#{$fa-css-prefix}-magic:before { content: $fa-var-magic; } +.#{$fa-css-prefix}-truck:before { content: $fa-var-truck; } +.#{$fa-css-prefix}-pinterest:before { content: $fa-var-pinterest; } +.#{$fa-css-prefix}-pinterest-square:before { content: $fa-var-pinterest-square; } +.#{$fa-css-prefix}-google-plus-square:before { content: $fa-var-google-plus-square; } +.#{$fa-css-prefix}-google-plus:before { content: $fa-var-google-plus; } +.#{$fa-css-prefix}-money:before { content: $fa-var-money; } +.#{$fa-css-prefix}-caret-down:before { content: $fa-var-caret-down; } +.#{$fa-css-prefix}-caret-up:before { content: $fa-var-caret-up; } +.#{$fa-css-prefix}-caret-left:before { content: $fa-var-caret-left; } +.#{$fa-css-prefix}-caret-right:before { content: $fa-var-caret-right; } +.#{$fa-css-prefix}-columns:before { content: $fa-var-columns; } +.#{$fa-css-prefix}-unsorted:before, +.#{$fa-css-prefix}-sort:before { content: $fa-var-sort; } +.#{$fa-css-prefix}-sort-down:before, +.#{$fa-css-prefix}-sort-desc:before { content: $fa-var-sort-desc; } +.#{$fa-css-prefix}-sort-up:before, +.#{$fa-css-prefix}-sort-asc:before { content: $fa-var-sort-asc; } +.#{$fa-css-prefix}-envelope:before { content: $fa-var-envelope; } +.#{$fa-css-prefix}-linkedin:before { content: $fa-var-linkedin; } +.#{$fa-css-prefix}-rotate-left:before, +.#{$fa-css-prefix}-undo:before { content: $fa-var-undo; } +.#{$fa-css-prefix}-legal:before, +.#{$fa-css-prefix}-gavel:before { content: $fa-var-gavel; } +.#{$fa-css-prefix}-dashboard:before, +.#{$fa-css-prefix}-tachometer:before { content: $fa-var-tachometer; } +.#{$fa-css-prefix}-comment-o:before { content: $fa-var-comment-o; } +.#{$fa-css-prefix}-comments-o:before { content: $fa-var-comments-o; } +.#{$fa-css-prefix}-flash:before, +.#{$fa-css-prefix}-bolt:before { content: $fa-var-bolt; } +.#{$fa-css-prefix}-sitemap:before { content: $fa-var-sitemap; } +.#{$fa-css-prefix}-umbrella:before { content: $fa-var-umbrella; } +.#{$fa-css-prefix}-paste:before, +.#{$fa-css-prefix}-clipboard:before { content: $fa-var-clipboard; } +.#{$fa-css-prefix}-lightbulb-o:before { content: $fa-var-lightbulb-o; } +.#{$fa-css-prefix}-exchange:before { content: $fa-var-exchange; } +.#{$fa-css-prefix}-cloud-download:before { content: $fa-var-cloud-download; } +.#{$fa-css-prefix}-cloud-upload:before { content: $fa-var-cloud-upload; } +.#{$fa-css-prefix}-user-md:before { content: $fa-var-user-md; } +.#{$fa-css-prefix}-stethoscope:before { content: $fa-var-stethoscope; } +.#{$fa-css-prefix}-suitcase:before { content: $fa-var-suitcase; } +.#{$fa-css-prefix}-bell-o:before { content: $fa-var-bell-o; } +.#{$fa-css-prefix}-coffee:before { content: $fa-var-coffee; } +.#{$fa-css-prefix}-cutlery:before { content: $fa-var-cutlery; } +.#{$fa-css-prefix}-file-text-o:before { content: $fa-var-file-text-o; } +.#{$fa-css-prefix}-building-o:before { content: $fa-var-building-o; } +.#{$fa-css-prefix}-hospital-o:before { content: $fa-var-hospital-o; } +.#{$fa-css-prefix}-ambulance:before { content: $fa-var-ambulance; } +.#{$fa-css-prefix}-medkit:before { content: $fa-var-medkit; } +.#{$fa-css-prefix}-fighter-jet:before { content: $fa-var-fighter-jet; } +.#{$fa-css-prefix}-beer:before { content: $fa-var-beer; } +.#{$fa-css-prefix}-h-square:before { content: $fa-var-h-square; } +.#{$fa-css-prefix}-plus-square:before { content: $fa-var-plus-square; } +.#{$fa-css-prefix}-angle-double-left:before { content: $fa-var-angle-double-left; } +.#{$fa-css-prefix}-angle-double-right:before { content: $fa-var-angle-double-right; } +.#{$fa-css-prefix}-angle-double-up:before { content: $fa-var-angle-double-up; } +.#{$fa-css-prefix}-angle-double-down:before { content: $fa-var-angle-double-down; } +.#{$fa-css-prefix}-angle-left:before { content: $fa-var-angle-left; } +.#{$fa-css-prefix}-angle-right:before { content: $fa-var-angle-right; } +.#{$fa-css-prefix}-angle-up:before { content: $fa-var-angle-up; } +.#{$fa-css-prefix}-angle-down:before { content: $fa-var-angle-down; } +.#{$fa-css-prefix}-desktop:before { content: $fa-var-desktop; } +.#{$fa-css-prefix}-laptop:before { content: $fa-var-laptop; } +.#{$fa-css-prefix}-tablet:before { content: $fa-var-tablet; } +.#{$fa-css-prefix}-mobile-phone:before, +.#{$fa-css-prefix}-mobile:before { content: $fa-var-mobile; } +.#{$fa-css-prefix}-circle-o:before { content: $fa-var-circle-o; } +.#{$fa-css-prefix}-quote-left:before { content: $fa-var-quote-left; } +.#{$fa-css-prefix}-quote-right:before { content: $fa-var-quote-right; } +.#{$fa-css-prefix}-spinner:before { content: $fa-var-spinner; } +.#{$fa-css-prefix}-circle:before { content: $fa-var-circle; } +.#{$fa-css-prefix}-mail-reply:before, +.#{$fa-css-prefix}-reply:before { content: $fa-var-reply; } +.#{$fa-css-prefix}-github-alt:before { content: $fa-var-github-alt; } +.#{$fa-css-prefix}-folder-o:before { content: $fa-var-folder-o; } +.#{$fa-css-prefix}-folder-open-o:before { content: $fa-var-folder-open-o; } +.#{$fa-css-prefix}-smile-o:before { content: $fa-var-smile-o; } +.#{$fa-css-prefix}-frown-o:before { content: $fa-var-frown-o; } +.#{$fa-css-prefix}-meh-o:before { content: $fa-var-meh-o; } +.#{$fa-css-prefix}-gamepad:before { content: $fa-var-gamepad; } +.#{$fa-css-prefix}-keyboard-o:before { content: $fa-var-keyboard-o; } +.#{$fa-css-prefix}-flag-o:before { content: $fa-var-flag-o; } +.#{$fa-css-prefix}-flag-checkered:before { content: $fa-var-flag-checkered; } +.#{$fa-css-prefix}-terminal:before { content: $fa-var-terminal; } +.#{$fa-css-prefix}-code:before { content: $fa-var-code; } +.#{$fa-css-prefix}-mail-reply-all:before, +.#{$fa-css-prefix}-reply-all:before { content: $fa-var-reply-all; } +.#{$fa-css-prefix}-star-half-empty:before, +.#{$fa-css-prefix}-star-half-full:before, +.#{$fa-css-prefix}-star-half-o:before { content: $fa-var-star-half-o; } +.#{$fa-css-prefix}-location-arrow:before { content: $fa-var-location-arrow; } +.#{$fa-css-prefix}-crop:before { content: $fa-var-crop; } +.#{$fa-css-prefix}-code-fork:before { content: $fa-var-code-fork; } +.#{$fa-css-prefix}-unlink:before, +.#{$fa-css-prefix}-chain-broken:before { content: $fa-var-chain-broken; } +.#{$fa-css-prefix}-question:before { content: $fa-var-question; } +.#{$fa-css-prefix}-info:before { content: $fa-var-info; } +.#{$fa-css-prefix}-exclamation:before { content: $fa-var-exclamation; } +.#{$fa-css-prefix}-superscript:before { content: $fa-var-superscript; } +.#{$fa-css-prefix}-subscript:before { content: $fa-var-subscript; } +.#{$fa-css-prefix}-eraser:before { content: $fa-var-eraser; } +.#{$fa-css-prefix}-puzzle-piece:before { content: $fa-var-puzzle-piece; } +.#{$fa-css-prefix}-microphone:before { content: $fa-var-microphone; } +.#{$fa-css-prefix}-microphone-slash:before { content: $fa-var-microphone-slash; } +.#{$fa-css-prefix}-shield:before { content: $fa-var-shield; } +.#{$fa-css-prefix}-calendar-o:before { content: $fa-var-calendar-o; } +.#{$fa-css-prefix}-fire-extinguisher:before { content: $fa-var-fire-extinguisher; } +.#{$fa-css-prefix}-rocket:before { content: $fa-var-rocket; } +.#{$fa-css-prefix}-maxcdn:before { content: $fa-var-maxcdn; } +.#{$fa-css-prefix}-chevron-circle-left:before { content: $fa-var-chevron-circle-left; } +.#{$fa-css-prefix}-chevron-circle-right:before { content: $fa-var-chevron-circle-right; } +.#{$fa-css-prefix}-chevron-circle-up:before { content: $fa-var-chevron-circle-up; } +.#{$fa-css-prefix}-chevron-circle-down:before { content: $fa-var-chevron-circle-down; } +.#{$fa-css-prefix}-html5:before { content: $fa-var-html5; } +.#{$fa-css-prefix}-css3:before { content: $fa-var-css3; } +.#{$fa-css-prefix}-anchor:before { content: $fa-var-anchor; } +.#{$fa-css-prefix}-unlock-alt:before { content: $fa-var-unlock-alt; } +.#{$fa-css-prefix}-bullseye:before { content: $fa-var-bullseye; } +.#{$fa-css-prefix}-ellipsis-h:before { content: $fa-var-ellipsis-h; } +.#{$fa-css-prefix}-ellipsis-v:before { content: $fa-var-ellipsis-v; } +.#{$fa-css-prefix}-rss-square:before { content: $fa-var-rss-square; } +.#{$fa-css-prefix}-play-circle:before { content: $fa-var-play-circle; } +.#{$fa-css-prefix}-ticket:before { content: $fa-var-ticket; } +.#{$fa-css-prefix}-minus-square:before { content: $fa-var-minus-square; } +.#{$fa-css-prefix}-minus-square-o:before { content: $fa-var-minus-square-o; } +.#{$fa-css-prefix}-level-up:before { content: $fa-var-level-up; } +.#{$fa-css-prefix}-level-down:before { content: $fa-var-level-down; } +.#{$fa-css-prefix}-check-square:before { content: $fa-var-check-square; } +.#{$fa-css-prefix}-pencil-square:before { content: $fa-var-pencil-square; } +.#{$fa-css-prefix}-external-link-square:before { content: $fa-var-external-link-square; } +.#{$fa-css-prefix}-share-square:before { content: $fa-var-share-square; } +.#{$fa-css-prefix}-compass:before { content: $fa-var-compass; } +.#{$fa-css-prefix}-toggle-down:before, +.#{$fa-css-prefix}-caret-square-o-down:before { content: $fa-var-caret-square-o-down; } +.#{$fa-css-prefix}-toggle-up:before, +.#{$fa-css-prefix}-caret-square-o-up:before { content: $fa-var-caret-square-o-up; } +.#{$fa-css-prefix}-toggle-right:before, +.#{$fa-css-prefix}-caret-square-o-right:before { content: $fa-var-caret-square-o-right; } +.#{$fa-css-prefix}-euro:before, +.#{$fa-css-prefix}-eur:before { content: $fa-var-eur; } +.#{$fa-css-prefix}-gbp:before { content: $fa-var-gbp; } +.#{$fa-css-prefix}-dollar:before, +.#{$fa-css-prefix}-usd:before { content: $fa-var-usd; } +.#{$fa-css-prefix}-rupee:before, +.#{$fa-css-prefix}-inr:before { content: $fa-var-inr; } +.#{$fa-css-prefix}-cny:before, +.#{$fa-css-prefix}-rmb:before, +.#{$fa-css-prefix}-yen:before, +.#{$fa-css-prefix}-jpy:before { content: $fa-var-jpy; } +.#{$fa-css-prefix}-ruble:before, +.#{$fa-css-prefix}-rouble:before, +.#{$fa-css-prefix}-rub:before { content: $fa-var-rub; } +.#{$fa-css-prefix}-won:before, +.#{$fa-css-prefix}-krw:before { content: $fa-var-krw; } +.#{$fa-css-prefix}-bitcoin:before, +.#{$fa-css-prefix}-btc:before { content: $fa-var-btc; } +.#{$fa-css-prefix}-file:before { content: $fa-var-file; } +.#{$fa-css-prefix}-file-text:before { content: $fa-var-file-text; } +.#{$fa-css-prefix}-sort-alpha-asc:before { content: $fa-var-sort-alpha-asc; } +.#{$fa-css-prefix}-sort-alpha-desc:before { content: $fa-var-sort-alpha-desc; } +.#{$fa-css-prefix}-sort-amount-asc:before { content: $fa-var-sort-amount-asc; } +.#{$fa-css-prefix}-sort-amount-desc:before { content: $fa-var-sort-amount-desc; } +.#{$fa-css-prefix}-sort-numeric-asc:before { content: $fa-var-sort-numeric-asc; } +.#{$fa-css-prefix}-sort-numeric-desc:before { content: $fa-var-sort-numeric-desc; } +.#{$fa-css-prefix}-thumbs-up:before { content: $fa-var-thumbs-up; } +.#{$fa-css-prefix}-thumbs-down:before { content: $fa-var-thumbs-down; } +.#{$fa-css-prefix}-youtube-square:before { content: $fa-var-youtube-square; } +.#{$fa-css-prefix}-youtube:before { content: $fa-var-youtube; } +.#{$fa-css-prefix}-xing:before { content: $fa-var-xing; } +.#{$fa-css-prefix}-xing-square:before { content: $fa-var-xing-square; } +.#{$fa-css-prefix}-youtube-play:before { content: $fa-var-youtube-play; } +.#{$fa-css-prefix}-dropbox:before { content: $fa-var-dropbox; } +.#{$fa-css-prefix}-stack-overflow:before { content: $fa-var-stack-overflow; } +.#{$fa-css-prefix}-instagram:before { content: $fa-var-instagram; } +.#{$fa-css-prefix}-flickr:before { content: $fa-var-flickr; } +.#{$fa-css-prefix}-adn:before { content: $fa-var-adn; } +.#{$fa-css-prefix}-bitbucket:before { content: $fa-var-bitbucket; } +.#{$fa-css-prefix}-bitbucket-square:before { content: $fa-var-bitbucket-square; } +.#{$fa-css-prefix}-tumblr:before { content: $fa-var-tumblr; } +.#{$fa-css-prefix}-tumblr-square:before { content: $fa-var-tumblr-square; } +.#{$fa-css-prefix}-long-arrow-down:before { content: $fa-var-long-arrow-down; } +.#{$fa-css-prefix}-long-arrow-up:before { content: $fa-var-long-arrow-up; } +.#{$fa-css-prefix}-long-arrow-left:before { content: $fa-var-long-arrow-left; } +.#{$fa-css-prefix}-long-arrow-right:before { content: $fa-var-long-arrow-right; } +.#{$fa-css-prefix}-apple:before { content: $fa-var-apple; } +.#{$fa-css-prefix}-windows:before { content: $fa-var-windows; } +.#{$fa-css-prefix}-android:before { content: $fa-var-android; } +.#{$fa-css-prefix}-linux:before { content: $fa-var-linux; } +.#{$fa-css-prefix}-dribbble:before { content: $fa-var-dribbble; } +.#{$fa-css-prefix}-skype:before { content: $fa-var-skype; } +.#{$fa-css-prefix}-foursquare:before { content: $fa-var-foursquare; } +.#{$fa-css-prefix}-trello:before { content: $fa-var-trello; } +.#{$fa-css-prefix}-female:before { content: $fa-var-female; } +.#{$fa-css-prefix}-male:before { content: $fa-var-male; } +.#{$fa-css-prefix}-gittip:before, +.#{$fa-css-prefix}-gratipay:before { content: $fa-var-gratipay; } +.#{$fa-css-prefix}-sun-o:before { content: $fa-var-sun-o; } +.#{$fa-css-prefix}-moon-o:before { content: $fa-var-moon-o; } +.#{$fa-css-prefix}-archive:before { content: $fa-var-archive; } +.#{$fa-css-prefix}-bug:before { content: $fa-var-bug; } +.#{$fa-css-prefix}-vk:before { content: $fa-var-vk; } +.#{$fa-css-prefix}-weibo:before { content: $fa-var-weibo; } +.#{$fa-css-prefix}-renren:before { content: $fa-var-renren; } +.#{$fa-css-prefix}-pagelines:before { content: $fa-var-pagelines; } +.#{$fa-css-prefix}-stack-exchange:before { content: $fa-var-stack-exchange; } +.#{$fa-css-prefix}-arrow-circle-o-right:before { content: $fa-var-arrow-circle-o-right; } +.#{$fa-css-prefix}-arrow-circle-o-left:before { content: $fa-var-arrow-circle-o-left; } +.#{$fa-css-prefix}-toggle-left:before, +.#{$fa-css-prefix}-caret-square-o-left:before { content: $fa-var-caret-square-o-left; } +.#{$fa-css-prefix}-dot-circle-o:before { content: $fa-var-dot-circle-o; } +.#{$fa-css-prefix}-wheelchair:before { content: $fa-var-wheelchair; } +.#{$fa-css-prefix}-vimeo-square:before { content: $fa-var-vimeo-square; } +.#{$fa-css-prefix}-turkish-lira:before, +.#{$fa-css-prefix}-try:before { content: $fa-var-try; } +.#{$fa-css-prefix}-plus-square-o:before { content: $fa-var-plus-square-o; } +.#{$fa-css-prefix}-space-shuttle:before { content: $fa-var-space-shuttle; } +.#{$fa-css-prefix}-slack:before { content: $fa-var-slack; } +.#{$fa-css-prefix}-envelope-square:before { content: $fa-var-envelope-square; } +.#{$fa-css-prefix}-wordpress:before { content: $fa-var-wordpress; } +.#{$fa-css-prefix}-openid:before { content: $fa-var-openid; } +.#{$fa-css-prefix}-institution:before, +.#{$fa-css-prefix}-bank:before, +.#{$fa-css-prefix}-university:before { content: $fa-var-university; } +.#{$fa-css-prefix}-mortar-board:before, +.#{$fa-css-prefix}-graduation-cap:before { content: $fa-var-graduation-cap; } +.#{$fa-css-prefix}-yahoo:before { content: $fa-var-yahoo; } +.#{$fa-css-prefix}-google:before { content: $fa-var-google; } +.#{$fa-css-prefix}-reddit:before { content: $fa-var-reddit; } +.#{$fa-css-prefix}-reddit-square:before { content: $fa-var-reddit-square; } +.#{$fa-css-prefix}-stumbleupon-circle:before { content: $fa-var-stumbleupon-circle; } +.#{$fa-css-prefix}-stumbleupon:before { content: $fa-var-stumbleupon; } +.#{$fa-css-prefix}-delicious:before { content: $fa-var-delicious; } +.#{$fa-css-prefix}-digg:before { content: $fa-var-digg; } +.#{$fa-css-prefix}-pied-piper-pp:before { content: $fa-var-pied-piper-pp; } +.#{$fa-css-prefix}-pied-piper-alt:before { content: $fa-var-pied-piper-alt; } +.#{$fa-css-prefix}-drupal:before { content: $fa-var-drupal; } +.#{$fa-css-prefix}-joomla:before { content: $fa-var-joomla; } +.#{$fa-css-prefix}-language:before { content: $fa-var-language; } +.#{$fa-css-prefix}-fax:before { content: $fa-var-fax; } +.#{$fa-css-prefix}-building:before { content: $fa-var-building; } +.#{$fa-css-prefix}-child:before { content: $fa-var-child; } +.#{$fa-css-prefix}-paw:before { content: $fa-var-paw; } +.#{$fa-css-prefix}-spoon:before { content: $fa-var-spoon; } +.#{$fa-css-prefix}-cube:before { content: $fa-var-cube; } +.#{$fa-css-prefix}-cubes:before { content: $fa-var-cubes; } +.#{$fa-css-prefix}-behance:before { content: $fa-var-behance; } +.#{$fa-css-prefix}-behance-square:before { content: $fa-var-behance-square; } +.#{$fa-css-prefix}-steam:before { content: $fa-var-steam; } +.#{$fa-css-prefix}-steam-square:before { content: $fa-var-steam-square; } +.#{$fa-css-prefix}-recycle:before { content: $fa-var-recycle; } +.#{$fa-css-prefix}-automobile:before, +.#{$fa-css-prefix}-car:before { content: $fa-var-car; } +.#{$fa-css-prefix}-cab:before, +.#{$fa-css-prefix}-taxi:before { content: $fa-var-taxi; } +.#{$fa-css-prefix}-tree:before { content: $fa-var-tree; } +.#{$fa-css-prefix}-spotify:before { content: $fa-var-spotify; } +.#{$fa-css-prefix}-deviantart:before { content: $fa-var-deviantart; } +.#{$fa-css-prefix}-soundcloud:before { content: $fa-var-soundcloud; } +.#{$fa-css-prefix}-database:before { content: $fa-var-database; } +.#{$fa-css-prefix}-file-pdf-o:before { content: $fa-var-file-pdf-o; } +.#{$fa-css-prefix}-file-word-o:before { content: $fa-var-file-word-o; } +.#{$fa-css-prefix}-file-excel-o:before { content: $fa-var-file-excel-o; } +.#{$fa-css-prefix}-file-powerpoint-o:before { content: $fa-var-file-powerpoint-o; } +.#{$fa-css-prefix}-file-photo-o:before, +.#{$fa-css-prefix}-file-picture-o:before, +.#{$fa-css-prefix}-file-image-o:before { content: $fa-var-file-image-o; } +.#{$fa-css-prefix}-file-zip-o:before, +.#{$fa-css-prefix}-file-archive-o:before { content: $fa-var-file-archive-o; } +.#{$fa-css-prefix}-file-sound-o:before, +.#{$fa-css-prefix}-file-audio-o:before { content: $fa-var-file-audio-o; } +.#{$fa-css-prefix}-file-movie-o:before, +.#{$fa-css-prefix}-file-video-o:before { content: $fa-var-file-video-o; } +.#{$fa-css-prefix}-file-code-o:before { content: $fa-var-file-code-o; } +.#{$fa-css-prefix}-vine:before { content: $fa-var-vine; } +.#{$fa-css-prefix}-codepen:before { content: $fa-var-codepen; } +.#{$fa-css-prefix}-jsfiddle:before { content: $fa-var-jsfiddle; } +.#{$fa-css-prefix}-life-bouy:before, +.#{$fa-css-prefix}-life-buoy:before, +.#{$fa-css-prefix}-life-saver:before, +.#{$fa-css-prefix}-support:before, +.#{$fa-css-prefix}-life-ring:before { content: $fa-var-life-ring; } +.#{$fa-css-prefix}-circle-o-notch:before { content: $fa-var-circle-o-notch; } +.#{$fa-css-prefix}-ra:before, +.#{$fa-css-prefix}-resistance:before, +.#{$fa-css-prefix}-rebel:before { content: $fa-var-rebel; } +.#{$fa-css-prefix}-ge:before, +.#{$fa-css-prefix}-empire:before { content: $fa-var-empire; } +.#{$fa-css-prefix}-git-square:before { content: $fa-var-git-square; } +.#{$fa-css-prefix}-git:before { content: $fa-var-git; } +.#{$fa-css-prefix}-y-combinator-square:before, +.#{$fa-css-prefix}-yc-square:before, +.#{$fa-css-prefix}-hacker-news:before { content: $fa-var-hacker-news; } +.#{$fa-css-prefix}-tencent-weibo:before { content: $fa-var-tencent-weibo; } +.#{$fa-css-prefix}-qq:before { content: $fa-var-qq; } +.#{$fa-css-prefix}-wechat:before, +.#{$fa-css-prefix}-weixin:before { content: $fa-var-weixin; } +.#{$fa-css-prefix}-send:before, +.#{$fa-css-prefix}-paper-plane:before { content: $fa-var-paper-plane; } +.#{$fa-css-prefix}-send-o:before, +.#{$fa-css-prefix}-paper-plane-o:before { content: $fa-var-paper-plane-o; } +.#{$fa-css-prefix}-history:before { content: $fa-var-history; } +.#{$fa-css-prefix}-circle-thin:before { content: $fa-var-circle-thin; } +.#{$fa-css-prefix}-header:before { content: $fa-var-header; } +.#{$fa-css-prefix}-paragraph:before { content: $fa-var-paragraph; } +.#{$fa-css-prefix}-sliders:before { content: $fa-var-sliders; } +.#{$fa-css-prefix}-share-alt:before { content: $fa-var-share-alt; } +.#{$fa-css-prefix}-share-alt-square:before { content: $fa-var-share-alt-square; } +.#{$fa-css-prefix}-bomb:before { content: $fa-var-bomb; } +.#{$fa-css-prefix}-soccer-ball-o:before, +.#{$fa-css-prefix}-futbol-o:before { content: $fa-var-futbol-o; } +.#{$fa-css-prefix}-tty:before { content: $fa-var-tty; } +.#{$fa-css-prefix}-binoculars:before { content: $fa-var-binoculars; } +.#{$fa-css-prefix}-plug:before { content: $fa-var-plug; } +.#{$fa-css-prefix}-slideshare:before { content: $fa-var-slideshare; } +.#{$fa-css-prefix}-twitch:before { content: $fa-var-twitch; } +.#{$fa-css-prefix}-yelp:before { content: $fa-var-yelp; } +.#{$fa-css-prefix}-newspaper-o:before { content: $fa-var-newspaper-o; } +.#{$fa-css-prefix}-wifi:before { content: $fa-var-wifi; } +.#{$fa-css-prefix}-calculator:before { content: $fa-var-calculator; } +.#{$fa-css-prefix}-paypal:before { content: $fa-var-paypal; } +.#{$fa-css-prefix}-google-wallet:before { content: $fa-var-google-wallet; } +.#{$fa-css-prefix}-cc-visa:before { content: $fa-var-cc-visa; } +.#{$fa-css-prefix}-cc-mastercard:before { content: $fa-var-cc-mastercard; } +.#{$fa-css-prefix}-cc-discover:before { content: $fa-var-cc-discover; } +.#{$fa-css-prefix}-cc-amex:before { content: $fa-var-cc-amex; } +.#{$fa-css-prefix}-cc-paypal:before { content: $fa-var-cc-paypal; } +.#{$fa-css-prefix}-cc-stripe:before { content: $fa-var-cc-stripe; } +.#{$fa-css-prefix}-bell-slash:before { content: $fa-var-bell-slash; } +.#{$fa-css-prefix}-bell-slash-o:before { content: $fa-var-bell-slash-o; } +.#{$fa-css-prefix}-trash:before { content: $fa-var-trash; } +.#{$fa-css-prefix}-copyright:before { content: $fa-var-copyright; } +.#{$fa-css-prefix}-at:before { content: $fa-var-at; } +.#{$fa-css-prefix}-eyedropper:before { content: $fa-var-eyedropper; } +.#{$fa-css-prefix}-paint-brush:before { content: $fa-var-paint-brush; } +.#{$fa-css-prefix}-birthday-cake:before { content: $fa-var-birthday-cake; } +.#{$fa-css-prefix}-area-chart:before { content: $fa-var-area-chart; } +.#{$fa-css-prefix}-pie-chart:before { content: $fa-var-pie-chart; } +.#{$fa-css-prefix}-line-chart:before { content: $fa-var-line-chart; } +.#{$fa-css-prefix}-lastfm:before { content: $fa-var-lastfm; } +.#{$fa-css-prefix}-lastfm-square:before { content: $fa-var-lastfm-square; } +.#{$fa-css-prefix}-toggle-off:before { content: $fa-var-toggle-off; } +.#{$fa-css-prefix}-toggle-on:before { content: $fa-var-toggle-on; } +.#{$fa-css-prefix}-bicycle:before { content: $fa-var-bicycle; } +.#{$fa-css-prefix}-bus:before { content: $fa-var-bus; } +.#{$fa-css-prefix}-ioxhost:before { content: $fa-var-ioxhost; } +.#{$fa-css-prefix}-angellist:before { content: $fa-var-angellist; } +.#{$fa-css-prefix}-cc:before { content: $fa-var-cc; } +.#{$fa-css-prefix}-shekel:before, +.#{$fa-css-prefix}-sheqel:before, +.#{$fa-css-prefix}-ils:before { content: $fa-var-ils; } +.#{$fa-css-prefix}-meanpath:before { content: $fa-var-meanpath; } +.#{$fa-css-prefix}-buysellads:before { content: $fa-var-buysellads; } +.#{$fa-css-prefix}-connectdevelop:before { content: $fa-var-connectdevelop; } +.#{$fa-css-prefix}-dashcube:before { content: $fa-var-dashcube; } +.#{$fa-css-prefix}-forumbee:before { content: $fa-var-forumbee; } +.#{$fa-css-prefix}-leanpub:before { content: $fa-var-leanpub; } +.#{$fa-css-prefix}-sellsy:before { content: $fa-var-sellsy; } +.#{$fa-css-prefix}-shirtsinbulk:before { content: $fa-var-shirtsinbulk; } +.#{$fa-css-prefix}-simplybuilt:before { content: $fa-var-simplybuilt; } +.#{$fa-css-prefix}-skyatlas:before { content: $fa-var-skyatlas; } +.#{$fa-css-prefix}-cart-plus:before { content: $fa-var-cart-plus; } +.#{$fa-css-prefix}-cart-arrow-down:before { content: $fa-var-cart-arrow-down; } +.#{$fa-css-prefix}-diamond:before { content: $fa-var-diamond; } +.#{$fa-css-prefix}-ship:before { content: $fa-var-ship; } +.#{$fa-css-prefix}-user-secret:before { content: $fa-var-user-secret; } +.#{$fa-css-prefix}-motorcycle:before { content: $fa-var-motorcycle; } +.#{$fa-css-prefix}-street-view:before { content: $fa-var-street-view; } +.#{$fa-css-prefix}-heartbeat:before { content: $fa-var-heartbeat; } +.#{$fa-css-prefix}-venus:before { content: $fa-var-venus; } +.#{$fa-css-prefix}-mars:before { content: $fa-var-mars; } +.#{$fa-css-prefix}-mercury:before { content: $fa-var-mercury; } +.#{$fa-css-prefix}-intersex:before, +.#{$fa-css-prefix}-transgender:before { content: $fa-var-transgender; } +.#{$fa-css-prefix}-transgender-alt:before { content: $fa-var-transgender-alt; } +.#{$fa-css-prefix}-venus-double:before { content: $fa-var-venus-double; } +.#{$fa-css-prefix}-mars-double:before { content: $fa-var-mars-double; } +.#{$fa-css-prefix}-venus-mars:before { content: $fa-var-venus-mars; } +.#{$fa-css-prefix}-mars-stroke:before { content: $fa-var-mars-stroke; } +.#{$fa-css-prefix}-mars-stroke-v:before { content: $fa-var-mars-stroke-v; } +.#{$fa-css-prefix}-mars-stroke-h:before { content: $fa-var-mars-stroke-h; } +.#{$fa-css-prefix}-neuter:before { content: $fa-var-neuter; } +.#{$fa-css-prefix}-genderless:before { content: $fa-var-genderless; } +.#{$fa-css-prefix}-facebook-official:before { content: $fa-var-facebook-official; } +.#{$fa-css-prefix}-pinterest-p:before { content: $fa-var-pinterest-p; } +.#{$fa-css-prefix}-whatsapp:before { content: $fa-var-whatsapp; } +.#{$fa-css-prefix}-server:before { content: $fa-var-server; } +.#{$fa-css-prefix}-user-plus:before { content: $fa-var-user-plus; } +.#{$fa-css-prefix}-user-times:before { content: $fa-var-user-times; } +.#{$fa-css-prefix}-hotel:before, +.#{$fa-css-prefix}-bed:before { content: $fa-var-bed; } +.#{$fa-css-prefix}-viacoin:before { content: $fa-var-viacoin; } +.#{$fa-css-prefix}-train:before { content: $fa-var-train; } +.#{$fa-css-prefix}-subway:before { content: $fa-var-subway; } +.#{$fa-css-prefix}-medium:before { content: $fa-var-medium; } +.#{$fa-css-prefix}-yc:before, +.#{$fa-css-prefix}-y-combinator:before { content: $fa-var-y-combinator; } +.#{$fa-css-prefix}-optin-monster:before { content: $fa-var-optin-monster; } +.#{$fa-css-prefix}-opencart:before { content: $fa-var-opencart; } +.#{$fa-css-prefix}-expeditedssl:before { content: $fa-var-expeditedssl; } +.#{$fa-css-prefix}-battery-4:before, +.#{$fa-css-prefix}-battery:before, +.#{$fa-css-prefix}-battery-full:before { content: $fa-var-battery-full; } +.#{$fa-css-prefix}-battery-3:before, +.#{$fa-css-prefix}-battery-three-quarters:before { content: $fa-var-battery-three-quarters; } +.#{$fa-css-prefix}-battery-2:before, +.#{$fa-css-prefix}-battery-half:before { content: $fa-var-battery-half; } +.#{$fa-css-prefix}-battery-1:before, +.#{$fa-css-prefix}-battery-quarter:before { content: $fa-var-battery-quarter; } +.#{$fa-css-prefix}-battery-0:before, +.#{$fa-css-prefix}-battery-empty:before { content: $fa-var-battery-empty; } +.#{$fa-css-prefix}-mouse-pointer:before { content: $fa-var-mouse-pointer; } +.#{$fa-css-prefix}-i-cursor:before { content: $fa-var-i-cursor; } +.#{$fa-css-prefix}-object-group:before { content: $fa-var-object-group; } +.#{$fa-css-prefix}-object-ungroup:before { content: $fa-var-object-ungroup; } +.#{$fa-css-prefix}-sticky-note:before { content: $fa-var-sticky-note; } +.#{$fa-css-prefix}-sticky-note-o:before { content: $fa-var-sticky-note-o; } +.#{$fa-css-prefix}-cc-jcb:before { content: $fa-var-cc-jcb; } +.#{$fa-css-prefix}-cc-diners-club:before { content: $fa-var-cc-diners-club; } +.#{$fa-css-prefix}-clone:before { content: $fa-var-clone; } +.#{$fa-css-prefix}-balance-scale:before { content: $fa-var-balance-scale; } +.#{$fa-css-prefix}-hourglass-o:before { content: $fa-var-hourglass-o; } +.#{$fa-css-prefix}-hourglass-1:before, +.#{$fa-css-prefix}-hourglass-start:before { content: $fa-var-hourglass-start; } +.#{$fa-css-prefix}-hourglass-2:before, +.#{$fa-css-prefix}-hourglass-half:before { content: $fa-var-hourglass-half; } +.#{$fa-css-prefix}-hourglass-3:before, +.#{$fa-css-prefix}-hourglass-end:before { content: $fa-var-hourglass-end; } +.#{$fa-css-prefix}-hourglass:before { content: $fa-var-hourglass; } +.#{$fa-css-prefix}-hand-grab-o:before, +.#{$fa-css-prefix}-hand-rock-o:before { content: $fa-var-hand-rock-o; } +.#{$fa-css-prefix}-hand-stop-o:before, +.#{$fa-css-prefix}-hand-paper-o:before { content: $fa-var-hand-paper-o; } +.#{$fa-css-prefix}-hand-scissors-o:before { content: $fa-var-hand-scissors-o; } +.#{$fa-css-prefix}-hand-lizard-o:before { content: $fa-var-hand-lizard-o; } +.#{$fa-css-prefix}-hand-spock-o:before { content: $fa-var-hand-spock-o; } +.#{$fa-css-prefix}-hand-pointer-o:before { content: $fa-var-hand-pointer-o; } +.#{$fa-css-prefix}-hand-peace-o:before { content: $fa-var-hand-peace-o; } +.#{$fa-css-prefix}-trademark:before { content: $fa-var-trademark; } +.#{$fa-css-prefix}-registered:before { content: $fa-var-registered; } +.#{$fa-css-prefix}-creative-commons:before { content: $fa-var-creative-commons; } +.#{$fa-css-prefix}-gg:before { content: $fa-var-gg; } +.#{$fa-css-prefix}-gg-circle:before { content: $fa-var-gg-circle; } +.#{$fa-css-prefix}-tripadvisor:before { content: $fa-var-tripadvisor; } +.#{$fa-css-prefix}-odnoklassniki:before { content: $fa-var-odnoklassniki; } +.#{$fa-css-prefix}-odnoklassniki-square:before { content: $fa-var-odnoklassniki-square; } +.#{$fa-css-prefix}-get-pocket:before { content: $fa-var-get-pocket; } +.#{$fa-css-prefix}-wikipedia-w:before { content: $fa-var-wikipedia-w; } +.#{$fa-css-prefix}-safari:before { content: $fa-var-safari; } +.#{$fa-css-prefix}-chrome:before { content: $fa-var-chrome; } +.#{$fa-css-prefix}-firefox:before { content: $fa-var-firefox; } +.#{$fa-css-prefix}-opera:before { content: $fa-var-opera; } +.#{$fa-css-prefix}-internet-explorer:before { content: $fa-var-internet-explorer; } +.#{$fa-css-prefix}-tv:before, +.#{$fa-css-prefix}-television:before { content: $fa-var-television; } +.#{$fa-css-prefix}-contao:before { content: $fa-var-contao; } +.#{$fa-css-prefix}-500px:before { content: $fa-var-500px; } +.#{$fa-css-prefix}-amazon:before { content: $fa-var-amazon; } +.#{$fa-css-prefix}-calendar-plus-o:before { content: $fa-var-calendar-plus-o; } +.#{$fa-css-prefix}-calendar-minus-o:before { content: $fa-var-calendar-minus-o; } +.#{$fa-css-prefix}-calendar-times-o:before { content: $fa-var-calendar-times-o; } +.#{$fa-css-prefix}-calendar-check-o:before { content: $fa-var-calendar-check-o; } +.#{$fa-css-prefix}-industry:before { content: $fa-var-industry; } +.#{$fa-css-prefix}-map-pin:before { content: $fa-var-map-pin; } +.#{$fa-css-prefix}-map-signs:before { content: $fa-var-map-signs; } +.#{$fa-css-prefix}-map-o:before { content: $fa-var-map-o; } +.#{$fa-css-prefix}-map:before { content: $fa-var-map; } +.#{$fa-css-prefix}-commenting:before { content: $fa-var-commenting; } +.#{$fa-css-prefix}-commenting-o:before { content: $fa-var-commenting-o; } +.#{$fa-css-prefix}-houzz:before { content: $fa-var-houzz; } +.#{$fa-css-prefix}-vimeo:before { content: $fa-var-vimeo; } +.#{$fa-css-prefix}-black-tie:before { content: $fa-var-black-tie; } +.#{$fa-css-prefix}-fonticons:before { content: $fa-var-fonticons; } +.#{$fa-css-prefix}-reddit-alien:before { content: $fa-var-reddit-alien; } +.#{$fa-css-prefix}-edge:before { content: $fa-var-edge; } +.#{$fa-css-prefix}-credit-card-alt:before { content: $fa-var-credit-card-alt; } +.#{$fa-css-prefix}-codiepie:before { content: $fa-var-codiepie; } +.#{$fa-css-prefix}-modx:before { content: $fa-var-modx; } +.#{$fa-css-prefix}-fort-awesome:before { content: $fa-var-fort-awesome; } +.#{$fa-css-prefix}-usb:before { content: $fa-var-usb; } +.#{$fa-css-prefix}-product-hunt:before { content: $fa-var-product-hunt; } +.#{$fa-css-prefix}-mixcloud:before { content: $fa-var-mixcloud; } +.#{$fa-css-prefix}-scribd:before { content: $fa-var-scribd; } +.#{$fa-css-prefix}-pause-circle:before { content: $fa-var-pause-circle; } +.#{$fa-css-prefix}-pause-circle-o:before { content: $fa-var-pause-circle-o; } +.#{$fa-css-prefix}-stop-circle:before { content: $fa-var-stop-circle; } +.#{$fa-css-prefix}-stop-circle-o:before { content: $fa-var-stop-circle-o; } +.#{$fa-css-prefix}-shopping-bag:before { content: $fa-var-shopping-bag; } +.#{$fa-css-prefix}-shopping-basket:before { content: $fa-var-shopping-basket; } +.#{$fa-css-prefix}-hashtag:before { content: $fa-var-hashtag; } +.#{$fa-css-prefix}-bluetooth:before { content: $fa-var-bluetooth; } +.#{$fa-css-prefix}-bluetooth-b:before { content: $fa-var-bluetooth-b; } +.#{$fa-css-prefix}-percent:before { content: $fa-var-percent; } +.#{$fa-css-prefix}-gitlab:before { content: $fa-var-gitlab; } +.#{$fa-css-prefix}-wpbeginner:before { content: $fa-var-wpbeginner; } +.#{$fa-css-prefix}-wpforms:before { content: $fa-var-wpforms; } +.#{$fa-css-prefix}-envira:before { content: $fa-var-envira; } +.#{$fa-css-prefix}-universal-access:before { content: $fa-var-universal-access; } +.#{$fa-css-prefix}-wheelchair-alt:before { content: $fa-var-wheelchair-alt; } +.#{$fa-css-prefix}-question-circle-o:before { content: $fa-var-question-circle-o; } +.#{$fa-css-prefix}-blind:before { content: $fa-var-blind; } +.#{$fa-css-prefix}-audio-description:before { content: $fa-var-audio-description; } +.#{$fa-css-prefix}-volume-control-phone:before { content: $fa-var-volume-control-phone; } +.#{$fa-css-prefix}-braille:before { content: $fa-var-braille; } +.#{$fa-css-prefix}-assistive-listening-systems:before { content: $fa-var-assistive-listening-systems; } +.#{$fa-css-prefix}-asl-interpreting:before, +.#{$fa-css-prefix}-american-sign-language-interpreting:before { content: $fa-var-american-sign-language-interpreting; } +.#{$fa-css-prefix}-deafness:before, +.#{$fa-css-prefix}-hard-of-hearing:before, +.#{$fa-css-prefix}-deaf:before { content: $fa-var-deaf; } +.#{$fa-css-prefix}-glide:before { content: $fa-var-glide; } +.#{$fa-css-prefix}-glide-g:before { content: $fa-var-glide-g; } +.#{$fa-css-prefix}-signing:before, +.#{$fa-css-prefix}-sign-language:before { content: $fa-var-sign-language; } +.#{$fa-css-prefix}-low-vision:before { content: $fa-var-low-vision; } +.#{$fa-css-prefix}-viadeo:before { content: $fa-var-viadeo; } +.#{$fa-css-prefix}-viadeo-square:before { content: $fa-var-viadeo-square; } +.#{$fa-css-prefix}-snapchat:before { content: $fa-var-snapchat; } +.#{$fa-css-prefix}-snapchat-ghost:before { content: $fa-var-snapchat-ghost; } +.#{$fa-css-prefix}-snapchat-square:before { content: $fa-var-snapchat-square; } +.#{$fa-css-prefix}-pied-piper:before { content: $fa-var-pied-piper; } +.#{$fa-css-prefix}-first-order:before { content: $fa-var-first-order; } +.#{$fa-css-prefix}-yoast:before { content: $fa-var-yoast; } +.#{$fa-css-prefix}-themeisle:before { content: $fa-var-themeisle; } +.#{$fa-css-prefix}-google-plus-circle:before, +.#{$fa-css-prefix}-google-plus-official:before { content: $fa-var-google-plus-official; } +.#{$fa-css-prefix}-fa:before, +.#{$fa-css-prefix}-font-awesome:before { content: $fa-var-font-awesome; } +.#{$fa-css-prefix}-handshake-o:before { content: $fa-var-handshake-o; } +.#{$fa-css-prefix}-envelope-open:before { content: $fa-var-envelope-open; } +.#{$fa-css-prefix}-envelope-open-o:before { content: $fa-var-envelope-open-o; } +.#{$fa-css-prefix}-linode:before { content: $fa-var-linode; } +.#{$fa-css-prefix}-address-book:before { content: $fa-var-address-book; } +.#{$fa-css-prefix}-address-book-o:before { content: $fa-var-address-book-o; } +.#{$fa-css-prefix}-vcard:before, +.#{$fa-css-prefix}-address-card:before { content: $fa-var-address-card; } +.#{$fa-css-prefix}-vcard-o:before, +.#{$fa-css-prefix}-address-card-o:before { content: $fa-var-address-card-o; } +.#{$fa-css-prefix}-user-circle:before { content: $fa-var-user-circle; } +.#{$fa-css-prefix}-user-circle-o:before { content: $fa-var-user-circle-o; } +.#{$fa-css-prefix}-user-o:before { content: $fa-var-user-o; } +.#{$fa-css-prefix}-id-badge:before { content: $fa-var-id-badge; } +.#{$fa-css-prefix}-drivers-license:before, +.#{$fa-css-prefix}-id-card:before { content: $fa-var-id-card; } +.#{$fa-css-prefix}-drivers-license-o:before, +.#{$fa-css-prefix}-id-card-o:before { content: $fa-var-id-card-o; } +.#{$fa-css-prefix}-quora:before { content: $fa-var-quora; } +.#{$fa-css-prefix}-free-code-camp:before { content: $fa-var-free-code-camp; } +.#{$fa-css-prefix}-telegram:before { content: $fa-var-telegram; } +.#{$fa-css-prefix}-thermometer-4:before, +.#{$fa-css-prefix}-thermometer:before, +.#{$fa-css-prefix}-thermometer-full:before { content: $fa-var-thermometer-full; } +.#{$fa-css-prefix}-thermometer-3:before, +.#{$fa-css-prefix}-thermometer-three-quarters:before { content: $fa-var-thermometer-three-quarters; } +.#{$fa-css-prefix}-thermometer-2:before, +.#{$fa-css-prefix}-thermometer-half:before { content: $fa-var-thermometer-half; } +.#{$fa-css-prefix}-thermometer-1:before, +.#{$fa-css-prefix}-thermometer-quarter:before { content: $fa-var-thermometer-quarter; } +.#{$fa-css-prefix}-thermometer-0:before, +.#{$fa-css-prefix}-thermometer-empty:before { content: $fa-var-thermometer-empty; } +.#{$fa-css-prefix}-shower:before { content: $fa-var-shower; } +.#{$fa-css-prefix}-bathtub:before, +.#{$fa-css-prefix}-s15:before, +.#{$fa-css-prefix}-bath:before { content: $fa-var-bath; } +.#{$fa-css-prefix}-podcast:before { content: $fa-var-podcast; } +.#{$fa-css-prefix}-window-maximize:before { content: $fa-var-window-maximize; } +.#{$fa-css-prefix}-window-minimize:before { content: $fa-var-window-minimize; } +.#{$fa-css-prefix}-window-restore:before { content: $fa-var-window-restore; } +.#{$fa-css-prefix}-times-rectangle:before, +.#{$fa-css-prefix}-window-close:before { content: $fa-var-window-close; } +.#{$fa-css-prefix}-times-rectangle-o:before, +.#{$fa-css-prefix}-window-close-o:before { content: $fa-var-window-close-o; } +.#{$fa-css-prefix}-bandcamp:before { content: $fa-var-bandcamp; } +.#{$fa-css-prefix}-grav:before { content: $fa-var-grav; } +.#{$fa-css-prefix}-etsy:before { content: $fa-var-etsy; } +.#{$fa-css-prefix}-imdb:before { content: $fa-var-imdb; } +.#{$fa-css-prefix}-ravelry:before { content: $fa-var-ravelry; } +.#{$fa-css-prefix}-eercast:before { content: $fa-var-eercast; } +.#{$fa-css-prefix}-microchip:before { content: $fa-var-microchip; } +.#{$fa-css-prefix}-snowflake-o:before { content: $fa-var-snowflake-o; } +.#{$fa-css-prefix}-superpowers:before { content: $fa-var-superpowers; } +.#{$fa-css-prefix}-wpexplorer:before { content: $fa-var-wpexplorer; } +.#{$fa-css-prefix}-meetup:before { content: $fa-var-meetup; } diff --git a/dashboard/src/assets/font-awesome/scss/_larger.scss b/dashboard/src/assets/font-awesome/scss/_larger.scss new file mode 100644 index 00000000..2b1cdc07 --- /dev/null +++ b/dashboard/src/assets/font-awesome/scss/_larger.scss @@ -0,0 +1,29 @@ +/*! + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Icon Sizes +// ------------------------- + +/* makes the font 33% larger relative to the icon container */ +.#{$fa-css-prefix}-lg { + font-size: (4em / 3); + line-height: (3em / 4); + vertical-align: -15%; +} +.#{$fa-css-prefix}-2x { font-size: 2em; } +.#{$fa-css-prefix}-3x { font-size: 3em; } +.#{$fa-css-prefix}-4x { font-size: 4em; } +.#{$fa-css-prefix}-5x { font-size: 5em; } diff --git a/dashboard/src/assets/font-awesome/scss/_list.scss b/dashboard/src/assets/font-awesome/scss/_list.scss new file mode 100644 index 00000000..a8b822ee --- /dev/null +++ b/dashboard/src/assets/font-awesome/scss/_list.scss @@ -0,0 +1,35 @@ +/*! + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// List Icons +// ------------------------- + +.#{$fa-css-prefix}-ul { + padding-left: 0; + margin-left: $fa-li-width; + list-style-type: none; + > li { position: relative; } +} +.#{$fa-css-prefix}-li { + position: absolute; + left: -$fa-li-width; + width: $fa-li-width; + top: (2em / 14); + text-align: center; + &.#{$fa-css-prefix}-lg { + left: -$fa-li-width + (4em / 14); + } +} diff --git a/dashboard/src/assets/font-awesome/scss/_mixins.scss b/dashboard/src/assets/font-awesome/scss/_mixins.scss new file mode 100644 index 00000000..cecc823f --- /dev/null +++ b/dashboard/src/assets/font-awesome/scss/_mixins.scss @@ -0,0 +1,76 @@ +/*! + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Mixins +// -------------------------- + +@mixin fa-icon() { + display: inline-block; + font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration + font-size: inherit; // can't have font-size inherit on line above, so need to override + text-rendering: auto; // optimizelegibility throws things off #1094 + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + +} + +@mixin fa-icon-rotate($degrees, $rotation) { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})"; + -webkit-transform: rotate($degrees); + -ms-transform: rotate($degrees); + transform: rotate($degrees); +} + +@mixin fa-icon-flip($horiz, $vert, $rotation) { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)"; + -webkit-transform: scale($horiz, $vert); + -ms-transform: scale($horiz, $vert); + transform: scale($horiz, $vert); +} + + +// Only display content to screen readers. A la Bootstrap 4. +// +// See: http://a11yproject.com/posts/how-to-hide-content/ + +@mixin sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0,0,0,0); + border: 0; +} + +// Use in conjunction with .sr-only to only display content when it's focused. +// +// Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 +// +// Credit: HTML5 Boilerplate + +@mixin sr-only-focusable { + &:active, + &:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; + } +} diff --git a/dashboard/src/assets/font-awesome/scss/_path.scss b/dashboard/src/assets/font-awesome/scss/_path.scss new file mode 100644 index 00000000..dc07dcf5 --- /dev/null +++ b/dashboard/src/assets/font-awesome/scss/_path.scss @@ -0,0 +1,31 @@ +/*! + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* FONT PATH + * -------------------------- */ + +@font-face { + font-family: 'FontAwesome'; + src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); + src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), + url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'), + url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), + url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), + url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); +// src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts + font-weight: normal; + font-style: normal; +} diff --git a/dashboard/src/assets/font-awesome/scss/_rotated-flipped.scss b/dashboard/src/assets/font-awesome/scss/_rotated-flipped.scss new file mode 100644 index 00000000..47d4872f --- /dev/null +++ b/dashboard/src/assets/font-awesome/scss/_rotated-flipped.scss @@ -0,0 +1,36 @@ +/*! + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Rotated & Flipped Icons +// ------------------------- + +.#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } +.#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } +.#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } + +.#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } +.#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } + +// Hook for IE8-9 +// ------------------------- + +:root .#{$fa-css-prefix}-rotate-90, +:root .#{$fa-css-prefix}-rotate-180, +:root .#{$fa-css-prefix}-rotate-270, +:root .#{$fa-css-prefix}-flip-horizontal, +:root .#{$fa-css-prefix}-flip-vertical { + filter: none; +} diff --git a/dashboard/src/assets/font-awesome/scss/_screen-reader.scss b/dashboard/src/assets/font-awesome/scss/_screen-reader.scss new file mode 100644 index 00000000..207f941f --- /dev/null +++ b/dashboard/src/assets/font-awesome/scss/_screen-reader.scss @@ -0,0 +1,21 @@ +/*! + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Screen Readers +// ------------------------- + +.sr-only { @include sr-only(); } +.sr-only-focusable { @include sr-only-focusable(); } diff --git a/dashboard/src/assets/font-awesome/scss/_stacked.scss b/dashboard/src/assets/font-awesome/scss/_stacked.scss new file mode 100644 index 00000000..df1345b5 --- /dev/null +++ b/dashboard/src/assets/font-awesome/scss/_stacked.scss @@ -0,0 +1,36 @@ +/*! + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Stacked Icons +// ------------------------- + +.#{$fa-css-prefix}-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.#{$fa-css-prefix}-stack-1x { line-height: inherit; } +.#{$fa-css-prefix}-stack-2x { font-size: 2em; } +.#{$fa-css-prefix}-inverse { color: $fa-inverse; } diff --git a/dashboard/src/assets/font-awesome/scss/_variables.scss b/dashboard/src/assets/font-awesome/scss/_variables.scss new file mode 100644 index 00000000..7f2613bf --- /dev/null +++ b/dashboard/src/assets/font-awesome/scss/_variables.scss @@ -0,0 +1,816 @@ +/*! + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Variables +// -------------------------- + +$fa-font-path: "../fonts" !default; +$fa-font-size-base: 14px !default; +$fa-line-height-base: 1 !default; +//$fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.7.0/fonts" !default; // for referencing Bootstrap CDN font files directly +$fa-css-prefix: fa !default; +$fa-version: "4.7.0" !default; +$fa-border-color: #eee !default; +$fa-inverse: #fff !default; +$fa-li-width: (30em / 14) !default; + +$fa-var-500px: "\f26e"; +$fa-var-address-book: "\f2b9"; +$fa-var-address-book-o: "\f2ba"; +$fa-var-address-card: "\f2bb"; +$fa-var-address-card-o: "\f2bc"; +$fa-var-adjust: "\f042"; +$fa-var-adn: "\f170"; +$fa-var-align-center: "\f037"; +$fa-var-align-justify: "\f039"; +$fa-var-align-left: "\f036"; +$fa-var-align-right: "\f038"; +$fa-var-amazon: "\f270"; +$fa-var-ambulance: "\f0f9"; +$fa-var-american-sign-language-interpreting: "\f2a3"; +$fa-var-anchor: "\f13d"; +$fa-var-android: "\f17b"; +$fa-var-angellist: "\f209"; +$fa-var-angle-double-down: "\f103"; +$fa-var-angle-double-left: "\f100"; +$fa-var-angle-double-right: "\f101"; +$fa-var-angle-double-up: "\f102"; +$fa-var-angle-down: "\f107"; +$fa-var-angle-left: "\f104"; +$fa-var-angle-right: "\f105"; +$fa-var-angle-up: "\f106"; +$fa-var-apple: "\f179"; +$fa-var-archive: "\f187"; +$fa-var-area-chart: "\f1fe"; +$fa-var-arrow-circle-down: "\f0ab"; +$fa-var-arrow-circle-left: "\f0a8"; +$fa-var-arrow-circle-o-down: "\f01a"; +$fa-var-arrow-circle-o-left: "\f190"; +$fa-var-arrow-circle-o-right: "\f18e"; +$fa-var-arrow-circle-o-up: "\f01b"; +$fa-var-arrow-circle-right: "\f0a9"; +$fa-var-arrow-circle-up: "\f0aa"; +$fa-var-arrow-down: "\f063"; +$fa-var-arrow-left: "\f060"; +$fa-var-arrow-right: "\f061"; +$fa-var-arrow-up: "\f062"; +$fa-var-arrows: "\f047"; +$fa-var-arrows-alt: "\f0b2"; +$fa-var-arrows-h: "\f07e"; +$fa-var-arrows-v: "\f07d"; +$fa-var-asl-interpreting: "\f2a3"; +$fa-var-assistive-listening-systems: "\f2a2"; +$fa-var-asterisk: "\f069"; +$fa-var-at: "\f1fa"; +$fa-var-audio-description: "\f29e"; +$fa-var-automobile: "\f1b9"; +$fa-var-backward: "\f04a"; +$fa-var-balance-scale: "\f24e"; +$fa-var-ban: "\f05e"; +$fa-var-bandcamp: "\f2d5"; +$fa-var-bank: "\f19c"; +$fa-var-bar-chart: "\f080"; +$fa-var-bar-chart-o: "\f080"; +$fa-var-barcode: "\f02a"; +$fa-var-bars: "\f0c9"; +$fa-var-bath: "\f2cd"; +$fa-var-bathtub: "\f2cd"; +$fa-var-battery: "\f240"; +$fa-var-battery-0: "\f244"; +$fa-var-battery-1: "\f243"; +$fa-var-battery-2: "\f242"; +$fa-var-battery-3: "\f241"; +$fa-var-battery-4: "\f240"; +$fa-var-battery-empty: "\f244"; +$fa-var-battery-full: "\f240"; +$fa-var-battery-half: "\f242"; +$fa-var-battery-quarter: "\f243"; +$fa-var-battery-three-quarters: "\f241"; +$fa-var-bed: "\f236"; +$fa-var-beer: "\f0fc"; +$fa-var-behance: "\f1b4"; +$fa-var-behance-square: "\f1b5"; +$fa-var-bell: "\f0f3"; +$fa-var-bell-o: "\f0a2"; +$fa-var-bell-slash: "\f1f6"; +$fa-var-bell-slash-o: "\f1f7"; +$fa-var-bicycle: "\f206"; +$fa-var-binoculars: "\f1e5"; +$fa-var-birthday-cake: "\f1fd"; +$fa-var-bitbucket: "\f171"; +$fa-var-bitbucket-square: "\f172"; +$fa-var-bitcoin: "\f15a"; +$fa-var-black-tie: "\f27e"; +$fa-var-blind: "\f29d"; +$fa-var-bluetooth: "\f293"; +$fa-var-bluetooth-b: "\f294"; +$fa-var-bold: "\f032"; +$fa-var-bolt: "\f0e7"; +$fa-var-bomb: "\f1e2"; +$fa-var-book: "\f02d"; +$fa-var-bookmark: "\f02e"; +$fa-var-bookmark-o: "\f097"; +$fa-var-braille: "\f2a1"; +$fa-var-briefcase: "\f0b1"; +$fa-var-btc: "\f15a"; +$fa-var-bug: "\f188"; +$fa-var-building: "\f1ad"; +$fa-var-building-o: "\f0f7"; +$fa-var-bullhorn: "\f0a1"; +$fa-var-bullseye: "\f140"; +$fa-var-bus: "\f207"; +$fa-var-buysellads: "\f20d"; +$fa-var-cab: "\f1ba"; +$fa-var-calculator: "\f1ec"; +$fa-var-calendar: "\f073"; +$fa-var-calendar-check-o: "\f274"; +$fa-var-calendar-minus-o: "\f272"; +$fa-var-calendar-o: "\f133"; +$fa-var-calendar-plus-o: "\f271"; +$fa-var-calendar-times-o: "\f273"; +$fa-var-camera: "\f030"; +$fa-var-camera-retro: "\f083"; +$fa-var-car: "\f1b9"; +$fa-var-caret-down: "\f0d7"; +$fa-var-caret-left: "\f0d9"; +$fa-var-caret-right: "\f0da"; +$fa-var-caret-square-o-down: "\f150"; +$fa-var-caret-square-o-left: "\f191"; +$fa-var-caret-square-o-right: "\f152"; +$fa-var-caret-square-o-up: "\f151"; +$fa-var-caret-up: "\f0d8"; +$fa-var-cart-arrow-down: "\f218"; +$fa-var-cart-plus: "\f217"; +$fa-var-cc: "\f20a"; +$fa-var-cc-amex: "\f1f3"; +$fa-var-cc-diners-club: "\f24c"; +$fa-var-cc-discover: "\f1f2"; +$fa-var-cc-jcb: "\f24b"; +$fa-var-cc-mastercard: "\f1f1"; +$fa-var-cc-paypal: "\f1f4"; +$fa-var-cc-stripe: "\f1f5"; +$fa-var-cc-visa: "\f1f0"; +$fa-var-certificate: "\f0a3"; +$fa-var-chain: "\f0c1"; +$fa-var-chain-broken: "\f127"; +$fa-var-check: "\f00c"; +$fa-var-check-circle: "\f058"; +$fa-var-check-circle-o: "\f05d"; +$fa-var-check-square: "\f14a"; +$fa-var-check-square-o: "\f046"; +$fa-var-chevron-circle-down: "\f13a"; +$fa-var-chevron-circle-left: "\f137"; +$fa-var-chevron-circle-right: "\f138"; +$fa-var-chevron-circle-up: "\f139"; +$fa-var-chevron-down: "\f078"; +$fa-var-chevron-left: "\f053"; +$fa-var-chevron-right: "\f054"; +$fa-var-chevron-up: "\f077"; +$fa-var-child: "\f1ae"; +$fa-var-chrome: "\f268"; +$fa-var-circle: "\f111"; +$fa-var-circle-o: "\f10c"; +$fa-var-circle-o-notch: "\f1ce"; +$fa-var-circle-thin: "\f1db"; +$fa-var-clipboard: "\f0ea"; +$fa-var-clock-o: "\f017"; +$fa-var-clone: "\f24d"; +$fa-var-close: "\f00d"; +$fa-var-cloud: "\f0c2"; +$fa-var-cloud-download: "\f0ed"; +$fa-var-cloud-upload: "\f0ee"; +$fa-var-cny: "\f157"; +$fa-var-code: "\f121"; +$fa-var-code-fork: "\f126"; +$fa-var-codepen: "\f1cb"; +$fa-var-codiepie: "\f284"; +$fa-var-coffee: "\f0f4"; +$fa-var-cog: "\f013"; +$fa-var-cogs: "\f085"; +$fa-var-columns: "\f0db"; +$fa-var-comment: "\f075"; +$fa-var-comment-o: "\f0e5"; +$fa-var-commenting: "\f27a"; +$fa-var-commenting-o: "\f27b"; +$fa-var-comments: "\f086"; +$fa-var-comments-o: "\f0e6"; +$fa-var-compass: "\f14e"; +$fa-var-compress: "\f066"; +$fa-var-connectdevelop: "\f20e"; +$fa-var-contao: "\f26d"; +$fa-var-copy: "\f0c5"; +$fa-var-copyright: "\f1f9"; +$fa-var-creative-commons: "\f25e"; +$fa-var-credit-card: "\f09d"; +$fa-var-credit-card-alt: "\f283"; +$fa-var-crop: "\f125"; +$fa-var-crosshairs: "\f05b"; +$fa-var-css3: "\f13c"; +$fa-var-cube: "\f1b2"; +$fa-var-cubes: "\f1b3"; +$fa-var-cut: "\f0c4"; +$fa-var-cutlery: "\f0f5"; +$fa-var-dashboard: "\f0e4"; +$fa-var-dashcube: "\f210"; +$fa-var-database: "\f1c0"; +$fa-var-deaf: "\f2a4"; +$fa-var-deafness: "\f2a4"; +$fa-var-dedent: "\f03b"; +$fa-var-delicious: "\f1a5"; +$fa-var-desktop: "\f108"; +$fa-var-deviantart: "\f1bd"; +$fa-var-diamond: "\f219"; +$fa-var-digg: "\f1a6"; +$fa-var-dollar: "\f155"; +$fa-var-dot-circle-o: "\f192"; +$fa-var-download: "\f019"; +$fa-var-dribbble: "\f17d"; +$fa-var-drivers-license: "\f2c2"; +$fa-var-drivers-license-o: "\f2c3"; +$fa-var-dropbox: "\f16b"; +$fa-var-drupal: "\f1a9"; +$fa-var-edge: "\f282"; +$fa-var-edit: "\f044"; +$fa-var-eercast: "\f2da"; +$fa-var-eject: "\f052"; +$fa-var-ellipsis-h: "\f141"; +$fa-var-ellipsis-v: "\f142"; +$fa-var-empire: "\f1d1"; +$fa-var-envelope: "\f0e0"; +$fa-var-envelope-o: "\f003"; +$fa-var-envelope-open: "\f2b6"; +$fa-var-envelope-open-o: "\f2b7"; +$fa-var-envelope-square: "\f199"; +$fa-var-envira: "\f299"; +$fa-var-eraser: "\f12d"; +$fa-var-etsy: "\f2d7"; +$fa-var-eur: "\f153"; +$fa-var-euro: "\f153"; +$fa-var-exchange: "\f0ec"; +$fa-var-exclamation: "\f12a"; +$fa-var-exclamation-circle: "\f06a"; +$fa-var-exclamation-triangle: "\f071"; +$fa-var-expand: "\f065"; +$fa-var-expeditedssl: "\f23e"; +$fa-var-external-link: "\f08e"; +$fa-var-external-link-square: "\f14c"; +$fa-var-eye: "\f06e"; +$fa-var-eye-slash: "\f070"; +$fa-var-eyedropper: "\f1fb"; +$fa-var-fa: "\f2b4"; +$fa-var-facebook: "\f09a"; +$fa-var-facebook-f: "\f09a"; +$fa-var-facebook-official: "\f230"; +$fa-var-facebook-square: "\f082"; +$fa-var-fast-backward: "\f049"; +$fa-var-fast-forward: "\f050"; +$fa-var-fax: "\f1ac"; +$fa-var-feed: "\f09e"; +$fa-var-female: "\f182"; +$fa-var-fighter-jet: "\f0fb"; +$fa-var-file: "\f15b"; +$fa-var-file-archive-o: "\f1c6"; +$fa-var-file-audio-o: "\f1c7"; +$fa-var-file-code-o: "\f1c9"; +$fa-var-file-excel-o: "\f1c3"; +$fa-var-file-image-o: "\f1c5"; +$fa-var-file-movie-o: "\f1c8"; +$fa-var-file-o: "\f016"; +$fa-var-file-pdf-o: "\f1c1"; +$fa-var-file-photo-o: "\f1c5"; +$fa-var-file-picture-o: "\f1c5"; +$fa-var-file-powerpoint-o: "\f1c4"; +$fa-var-file-sound-o: "\f1c7"; +$fa-var-file-text: "\f15c"; +$fa-var-file-text-o: "\f0f6"; +$fa-var-file-video-o: "\f1c8"; +$fa-var-file-word-o: "\f1c2"; +$fa-var-file-zip-o: "\f1c6"; +$fa-var-files-o: "\f0c5"; +$fa-var-film: "\f008"; +$fa-var-filter: "\f0b0"; +$fa-var-fire: "\f06d"; +$fa-var-fire-extinguisher: "\f134"; +$fa-var-firefox: "\f269"; +$fa-var-first-order: "\f2b0"; +$fa-var-flag: "\f024"; +$fa-var-flag-checkered: "\f11e"; +$fa-var-flag-o: "\f11d"; +$fa-var-flash: "\f0e7"; +$fa-var-flask: "\f0c3"; +$fa-var-flickr: "\f16e"; +$fa-var-floppy-o: "\f0c7"; +$fa-var-folder: "\f07b"; +$fa-var-folder-o: "\f114"; +$fa-var-folder-open: "\f07c"; +$fa-var-folder-open-o: "\f115"; +$fa-var-font: "\f031"; +$fa-var-font-awesome: "\f2b4"; +$fa-var-fonticons: "\f280"; +$fa-var-fort-awesome: "\f286"; +$fa-var-forumbee: "\f211"; +$fa-var-forward: "\f04e"; +$fa-var-foursquare: "\f180"; +$fa-var-free-code-camp: "\f2c5"; +$fa-var-frown-o: "\f119"; +$fa-var-futbol-o: "\f1e3"; +$fa-var-gamepad: "\f11b"; +$fa-var-gavel: "\f0e3"; +$fa-var-gbp: "\f154"; +$fa-var-ge: "\f1d1"; +$fa-var-gear: "\f013"; +$fa-var-gears: "\f085"; +$fa-var-genderless: "\f22d"; +$fa-var-get-pocket: "\f265"; +$fa-var-gg: "\f260"; +$fa-var-gg-circle: "\f261"; +$fa-var-gift: "\f06b"; +$fa-var-git: "\f1d3"; +$fa-var-git-square: "\f1d2"; +$fa-var-github: "\f09b"; +$fa-var-github-alt: "\f113"; +$fa-var-github-square: "\f092"; +$fa-var-gitlab: "\f296"; +$fa-var-gittip: "\f184"; +$fa-var-glass: "\f000"; +$fa-var-glide: "\f2a5"; +$fa-var-glide-g: "\f2a6"; +$fa-var-globe: "\f0ac"; +$fa-var-google: "\f1a0"; +$fa-var-google-plus: "\f0d5"; +$fa-var-google-plus-circle: "\f2b3"; +$fa-var-google-plus-official: "\f2b3"; +$fa-var-google-plus-square: "\f0d4"; +$fa-var-google-wallet: "\f1ee"; +$fa-var-graduation-cap: "\f19d"; +$fa-var-gratipay: "\f184"; +$fa-var-grav: "\f2d6"; +$fa-var-group: "\f0c0"; +$fa-var-h-square: "\f0fd"; +$fa-var-hacker-news: "\f1d4"; +$fa-var-hand-grab-o: "\f255"; +$fa-var-hand-lizard-o: "\f258"; +$fa-var-hand-o-down: "\f0a7"; +$fa-var-hand-o-left: "\f0a5"; +$fa-var-hand-o-right: "\f0a4"; +$fa-var-hand-o-up: "\f0a6"; +$fa-var-hand-paper-o: "\f256"; +$fa-var-hand-peace-o: "\f25b"; +$fa-var-hand-pointer-o: "\f25a"; +$fa-var-hand-rock-o: "\f255"; +$fa-var-hand-scissors-o: "\f257"; +$fa-var-hand-spock-o: "\f259"; +$fa-var-hand-stop-o: "\f256"; +$fa-var-handshake-o: "\f2b5"; +$fa-var-hard-of-hearing: "\f2a4"; +$fa-var-hashtag: "\f292"; +$fa-var-hdd-o: "\f0a0"; +$fa-var-header: "\f1dc"; +$fa-var-headphones: "\f025"; +$fa-var-heart: "\f004"; +$fa-var-heart-o: "\f08a"; +$fa-var-heartbeat: "\f21e"; +$fa-var-history: "\f1da"; +$fa-var-home: "\f015"; +$fa-var-hospital-o: "\f0f8"; +$fa-var-hotel: "\f236"; +$fa-var-hourglass: "\f254"; +$fa-var-hourglass-1: "\f251"; +$fa-var-hourglass-2: "\f252"; +$fa-var-hourglass-3: "\f253"; +$fa-var-hourglass-end: "\f253"; +$fa-var-hourglass-half: "\f252"; +$fa-var-hourglass-o: "\f250"; +$fa-var-hourglass-start: "\f251"; +$fa-var-houzz: "\f27c"; +$fa-var-html5: "\f13b"; +$fa-var-i-cursor: "\f246"; +$fa-var-id-badge: "\f2c1"; +$fa-var-id-card: "\f2c2"; +$fa-var-id-card-o: "\f2c3"; +$fa-var-ils: "\f20b"; +$fa-var-image: "\f03e"; +$fa-var-imdb: "\f2d8"; +$fa-var-inbox: "\f01c"; +$fa-var-indent: "\f03c"; +$fa-var-industry: "\f275"; +$fa-var-info: "\f129"; +$fa-var-info-circle: "\f05a"; +$fa-var-inr: "\f156"; +$fa-var-instagram: "\f16d"; +$fa-var-institution: "\f19c"; +$fa-var-internet-explorer: "\f26b"; +$fa-var-intersex: "\f224"; +$fa-var-ioxhost: "\f208"; +$fa-var-italic: "\f033"; +$fa-var-joomla: "\f1aa"; +$fa-var-jpy: "\f157"; +$fa-var-jsfiddle: "\f1cc"; +$fa-var-key: "\f084"; +$fa-var-keyboard-o: "\f11c"; +$fa-var-krw: "\f159"; +$fa-var-language: "\f1ab"; +$fa-var-laptop: "\f109"; +$fa-var-lastfm: "\f202"; +$fa-var-lastfm-square: "\f203"; +$fa-var-leaf: "\f06c"; +$fa-var-leanpub: "\f212"; +$fa-var-legal: "\f0e3"; +$fa-var-lemon-o: "\f094"; +$fa-var-level-down: "\f149"; +$fa-var-level-up: "\f148"; +$fa-var-life-bouy: "\f1cd"; +$fa-var-life-buoy: "\f1cd"; +$fa-var-life-ring: "\f1cd"; +$fa-var-life-saver: "\f1cd"; +$fa-var-lightbulb-o: "\f0eb"; +$fa-var-line-chart: "\f201"; +$fa-var-link: "\f0c1"; +$fa-var-linkedin: "\f0e1"; +$fa-var-linkedin-square: "\f08c"; +$fa-var-linode: "\f2b8"; +$fa-var-linux: "\f17c"; +$fa-var-list: "\f03a"; +$fa-var-list-alt: "\f022"; +$fa-var-list-ol: "\f0cb"; +$fa-var-list-ul: "\f0ca"; +$fa-var-location-arrow: "\f124"; +$fa-var-lock: "\f023"; +$fa-var-long-arrow-down: "\f175"; +$fa-var-long-arrow-left: "\f177"; +$fa-var-long-arrow-right: "\f178"; +$fa-var-long-arrow-up: "\f176"; +$fa-var-low-vision: "\f2a8"; +$fa-var-magic: "\f0d0"; +$fa-var-magnet: "\f076"; +$fa-var-mail-forward: "\f064"; +$fa-var-mail-reply: "\f112"; +$fa-var-mail-reply-all: "\f122"; +$fa-var-male: "\f183"; +$fa-var-map: "\f279"; +$fa-var-map-marker: "\f041"; +$fa-var-map-o: "\f278"; +$fa-var-map-pin: "\f276"; +$fa-var-map-signs: "\f277"; +$fa-var-mars: "\f222"; +$fa-var-mars-double: "\f227"; +$fa-var-mars-stroke: "\f229"; +$fa-var-mars-stroke-h: "\f22b"; +$fa-var-mars-stroke-v: "\f22a"; +$fa-var-maxcdn: "\f136"; +$fa-var-meanpath: "\f20c"; +$fa-var-medium: "\f23a"; +$fa-var-medkit: "\f0fa"; +$fa-var-meetup: "\f2e0"; +$fa-var-meh-o: "\f11a"; +$fa-var-mercury: "\f223"; +$fa-var-microchip: "\f2db"; +$fa-var-microphone: "\f130"; +$fa-var-microphone-slash: "\f131"; +$fa-var-minus: "\f068"; +$fa-var-minus-circle: "\f056"; +$fa-var-minus-square: "\f146"; +$fa-var-minus-square-o: "\f147"; +$fa-var-mixcloud: "\f289"; +$fa-var-mobile: "\f10b"; +$fa-var-mobile-phone: "\f10b"; +$fa-var-modx: "\f285"; +$fa-var-money: "\f0d6"; +$fa-var-moon-o: "\f186"; +$fa-var-mortar-board: "\f19d"; +$fa-var-motorcycle: "\f21c"; +$fa-var-mouse-pointer: "\f245"; +$fa-var-music: "\f001"; +$fa-var-navicon: "\f0c9"; +$fa-var-neuter: "\f22c"; +$fa-var-newspaper-o: "\f1ea"; +$fa-var-object-group: "\f247"; +$fa-var-object-ungroup: "\f248"; +$fa-var-odnoklassniki: "\f263"; +$fa-var-odnoklassniki-square: "\f264"; +$fa-var-opencart: "\f23d"; +$fa-var-openid: "\f19b"; +$fa-var-opera: "\f26a"; +$fa-var-optin-monster: "\f23c"; +$fa-var-outdent: "\f03b"; +$fa-var-pagelines: "\f18c"; +$fa-var-paint-brush: "\f1fc"; +$fa-var-paper-plane: "\f1d8"; +$fa-var-paper-plane-o: "\f1d9"; +$fa-var-paperclip: "\f0c6"; +$fa-var-paragraph: "\f1dd"; +$fa-var-paste: "\f0ea"; +$fa-var-pause: "\f04c"; +$fa-var-pause-circle: "\f28b"; +$fa-var-pause-circle-o: "\f28c"; +$fa-var-paw: "\f1b0"; +$fa-var-paypal: "\f1ed"; +$fa-var-pencil: "\f040"; +$fa-var-pencil-square: "\f14b"; +$fa-var-pencil-square-o: "\f044"; +$fa-var-percent: "\f295"; +$fa-var-phone: "\f095"; +$fa-var-phone-square: "\f098"; +$fa-var-photo: "\f03e"; +$fa-var-picture-o: "\f03e"; +$fa-var-pie-chart: "\f200"; +$fa-var-pied-piper: "\f2ae"; +$fa-var-pied-piper-alt: "\f1a8"; +$fa-var-pied-piper-pp: "\f1a7"; +$fa-var-pinterest: "\f0d2"; +$fa-var-pinterest-p: "\f231"; +$fa-var-pinterest-square: "\f0d3"; +$fa-var-plane: "\f072"; +$fa-var-play: "\f04b"; +$fa-var-play-circle: "\f144"; +$fa-var-play-circle-o: "\f01d"; +$fa-var-plug: "\f1e6"; +$fa-var-plus: "\f067"; +$fa-var-plus-circle: "\f055"; +$fa-var-plus-square: "\f0fe"; +$fa-var-plus-square-o: "\f196"; +$fa-var-podcast: "\f2ce"; +$fa-var-power-off: "\f011"; +$fa-var-print: "\f02f"; +$fa-var-product-hunt: "\f288"; +$fa-var-puzzle-piece: "\f12e"; +$fa-var-qq: "\f1d6"; +$fa-var-qrcode: "\f029"; +$fa-var-question: "\f128"; +$fa-var-question-circle: "\f059"; +$fa-var-question-circle-o: "\f29c"; +$fa-var-quora: "\f2c4"; +$fa-var-quote-left: "\f10d"; +$fa-var-quote-right: "\f10e"; +$fa-var-ra: "\f1d0"; +$fa-var-random: "\f074"; +$fa-var-ravelry: "\f2d9"; +$fa-var-rebel: "\f1d0"; +$fa-var-recycle: "\f1b8"; +$fa-var-reddit: "\f1a1"; +$fa-var-reddit-alien: "\f281"; +$fa-var-reddit-square: "\f1a2"; +$fa-var-refresh: "\f021"; +$fa-var-registered: "\f25d"; +$fa-var-remove: "\f00d"; +$fa-var-renren: "\f18b"; +$fa-var-reorder: "\f0c9"; +$fa-var-repeat: "\f01e"; +$fa-var-reply: "\f112"; +$fa-var-reply-all: "\f122"; +$fa-var-resistance: "\f1d0"; +$fa-var-retweet: "\f079"; +$fa-var-rmb: "\f157"; +$fa-var-road: "\f018"; +$fa-var-rocket: "\f135"; +$fa-var-rotate-left: "\f0e2"; +$fa-var-rotate-right: "\f01e"; +$fa-var-rouble: "\f158"; +$fa-var-rss: "\f09e"; +$fa-var-rss-square: "\f143"; +$fa-var-rub: "\f158"; +$fa-var-ruble: "\f158"; +$fa-var-rupee: "\f156"; +$fa-var-s15: "\f2cd"; +$fa-var-safari: "\f267"; +$fa-var-save: "\f0c7"; +$fa-var-scissors: "\f0c4"; +$fa-var-scribd: "\f28a"; +$fa-var-search: "\f002"; +$fa-var-search-minus: "\f010"; +$fa-var-search-plus: "\f00e"; +$fa-var-sellsy: "\f213"; +$fa-var-send: "\f1d8"; +$fa-var-send-o: "\f1d9"; +$fa-var-server: "\f233"; +$fa-var-share: "\f064"; +$fa-var-share-alt: "\f1e0"; +$fa-var-share-alt-square: "\f1e1"; +$fa-var-share-square: "\f14d"; +$fa-var-share-square-o: "\f045"; +$fa-var-shekel: "\f20b"; +$fa-var-sheqel: "\f20b"; +$fa-var-shield: "\f132"; +$fa-var-ship: "\f21a"; +$fa-var-shirtsinbulk: "\f214"; +$fa-var-shopping-bag: "\f290"; +$fa-var-shopping-basket: "\f291"; +$fa-var-shopping-cart: "\f07a"; +$fa-var-shower: "\f2cc"; +$fa-var-sign-in: "\f090"; +$fa-var-sign-language: "\f2a7"; +$fa-var-sign-out: "\f08b"; +$fa-var-signal: "\f012"; +$fa-var-signing: "\f2a7"; +$fa-var-simplybuilt: "\f215"; +$fa-var-sitemap: "\f0e8"; +$fa-var-skyatlas: "\f216"; +$fa-var-skype: "\f17e"; +$fa-var-slack: "\f198"; +$fa-var-sliders: "\f1de"; +$fa-var-slideshare: "\f1e7"; +$fa-var-smile-o: "\f118"; +$fa-var-snapchat: "\f2ab"; +$fa-var-snapchat-ghost: "\f2ac"; +$fa-var-snapchat-square: "\f2ad"; +$fa-var-snowflake-o: "\f2dc"; +$fa-var-soccer-ball-o: "\f1e3"; +$fa-var-sort: "\f0dc"; +$fa-var-sort-alpha-asc: "\f15d"; +$fa-var-sort-alpha-desc: "\f15e"; +$fa-var-sort-amount-asc: "\f160"; +$fa-var-sort-amount-desc: "\f161"; +$fa-var-sort-asc: "\f0de"; +$fa-var-sort-desc: "\f0dd"; +$fa-var-sort-down: "\f0dd"; +$fa-var-sort-numeric-asc: "\f162"; +$fa-var-sort-numeric-desc: "\f163"; +$fa-var-sort-up: "\f0de"; +$fa-var-soundcloud: "\f1be"; +$fa-var-space-shuttle: "\f197"; +$fa-var-spinner: "\f110"; +$fa-var-spoon: "\f1b1"; +$fa-var-spotify: "\f1bc"; +$fa-var-square: "\f0c8"; +$fa-var-square-o: "\f096"; +$fa-var-stack-exchange: "\f18d"; +$fa-var-stack-overflow: "\f16c"; +$fa-var-star: "\f005"; +$fa-var-star-half: "\f089"; +$fa-var-star-half-empty: "\f123"; +$fa-var-star-half-full: "\f123"; +$fa-var-star-half-o: "\f123"; +$fa-var-star-o: "\f006"; +$fa-var-steam: "\f1b6"; +$fa-var-steam-square: "\f1b7"; +$fa-var-step-backward: "\f048"; +$fa-var-step-forward: "\f051"; +$fa-var-stethoscope: "\f0f1"; +$fa-var-sticky-note: "\f249"; +$fa-var-sticky-note-o: "\f24a"; +$fa-var-stop: "\f04d"; +$fa-var-stop-circle: "\f28d"; +$fa-var-stop-circle-o: "\f28e"; +$fa-var-street-view: "\f21d"; +$fa-var-strikethrough: "\f0cc"; +$fa-var-stumbleupon: "\f1a4"; +$fa-var-stumbleupon-circle: "\f1a3"; +$fa-var-subscript: "\f12c"; +$fa-var-subway: "\f239"; +$fa-var-suitcase: "\f0f2"; +$fa-var-sun-o: "\f185"; +$fa-var-superpowers: "\f2dd"; +$fa-var-superscript: "\f12b"; +$fa-var-support: "\f1cd"; +$fa-var-table: "\f0ce"; +$fa-var-tablet: "\f10a"; +$fa-var-tachometer: "\f0e4"; +$fa-var-tag: "\f02b"; +$fa-var-tags: "\f02c"; +$fa-var-tasks: "\f0ae"; +$fa-var-taxi: "\f1ba"; +$fa-var-telegram: "\f2c6"; +$fa-var-television: "\f26c"; +$fa-var-tencent-weibo: "\f1d5"; +$fa-var-terminal: "\f120"; +$fa-var-text-height: "\f034"; +$fa-var-text-width: "\f035"; +$fa-var-th: "\f00a"; +$fa-var-th-large: "\f009"; +$fa-var-th-list: "\f00b"; +$fa-var-themeisle: "\f2b2"; +$fa-var-thermometer: "\f2c7"; +$fa-var-thermometer-0: "\f2cb"; +$fa-var-thermometer-1: "\f2ca"; +$fa-var-thermometer-2: "\f2c9"; +$fa-var-thermometer-3: "\f2c8"; +$fa-var-thermometer-4: "\f2c7"; +$fa-var-thermometer-empty: "\f2cb"; +$fa-var-thermometer-full: "\f2c7"; +$fa-var-thermometer-half: "\f2c9"; +$fa-var-thermometer-quarter: "\f2ca"; +$fa-var-thermometer-three-quarters: "\f2c8"; +$fa-var-thumb-tack: "\f08d"; +$fa-var-thumbs-down: "\f165"; +$fa-var-thumbs-o-down: "\f088"; +$fa-var-thumbs-o-up: "\f087"; +$fa-var-thumbs-up: "\f164"; +$fa-var-ticket: "\f145"; +$fa-var-times: "\f00d"; +$fa-var-times-circle: "\f057"; +$fa-var-times-circle-o: "\f05c"; +$fa-var-times-rectangle: "\f2d3"; +$fa-var-times-rectangle-o: "\f2d4"; +$fa-var-tint: "\f043"; +$fa-var-toggle-down: "\f150"; +$fa-var-toggle-left: "\f191"; +$fa-var-toggle-off: "\f204"; +$fa-var-toggle-on: "\f205"; +$fa-var-toggle-right: "\f152"; +$fa-var-toggle-up: "\f151"; +$fa-var-trademark: "\f25c"; +$fa-var-train: "\f238"; +$fa-var-transgender: "\f224"; +$fa-var-transgender-alt: "\f225"; +$fa-var-trash: "\f1f8"; +$fa-var-trash-o: "\f014"; +$fa-var-tree: "\f1bb"; +$fa-var-trello: "\f181"; +$fa-var-tripadvisor: "\f262"; +$fa-var-trophy: "\f091"; +$fa-var-truck: "\f0d1"; +$fa-var-try: "\f195"; +$fa-var-tty: "\f1e4"; +$fa-var-tumblr: "\f173"; +$fa-var-tumblr-square: "\f174"; +$fa-var-turkish-lira: "\f195"; +$fa-var-tv: "\f26c"; +$fa-var-twitch: "\f1e8"; +$fa-var-twitter: "\f099"; +$fa-var-twitter-square: "\f081"; +$fa-var-umbrella: "\f0e9"; +$fa-var-underline: "\f0cd"; +$fa-var-undo: "\f0e2"; +$fa-var-universal-access: "\f29a"; +$fa-var-university: "\f19c"; +$fa-var-unlink: "\f127"; +$fa-var-unlock: "\f09c"; +$fa-var-unlock-alt: "\f13e"; +$fa-var-unsorted: "\f0dc"; +$fa-var-upload: "\f093"; +$fa-var-usb: "\f287"; +$fa-var-usd: "\f155"; +$fa-var-user: "\f007"; +$fa-var-user-circle: "\f2bd"; +$fa-var-user-circle-o: "\f2be"; +$fa-var-user-md: "\f0f0"; +$fa-var-user-o: "\f2c0"; +$fa-var-user-plus: "\f234"; +$fa-var-user-secret: "\f21b"; +$fa-var-user-times: "\f235"; +$fa-var-users: "\f0c0"; +$fa-var-vcard: "\f2bb"; +$fa-var-vcard-o: "\f2bc"; +$fa-var-venus: "\f221"; +$fa-var-venus-double: "\f226"; +$fa-var-venus-mars: "\f228"; +$fa-var-viacoin: "\f237"; +$fa-var-viadeo: "\f2a9"; +$fa-var-viadeo-square: "\f2aa"; +$fa-var-video-camera: "\f03d"; +$fa-var-vimeo: "\f27d"; +$fa-var-vimeo-square: "\f194"; +$fa-var-vine: "\f1ca"; +$fa-var-vk: "\f189"; +$fa-var-volume-control-phone: "\f2a0"; +$fa-var-volume-down: "\f027"; +$fa-var-volume-off: "\f026"; +$fa-var-volume-up: "\f028"; +$fa-var-warning: "\f071"; +$fa-var-wechat: "\f1d7"; +$fa-var-weibo: "\f18a"; +$fa-var-weixin: "\f1d7"; +$fa-var-whatsapp: "\f232"; +$fa-var-wheelchair: "\f193"; +$fa-var-wheelchair-alt: "\f29b"; +$fa-var-wifi: "\f1eb"; +$fa-var-wikipedia-w: "\f266"; +$fa-var-window-close: "\f2d3"; +$fa-var-window-close-o: "\f2d4"; +$fa-var-window-maximize: "\f2d0"; +$fa-var-window-minimize: "\f2d1"; +$fa-var-window-restore: "\f2d2"; +$fa-var-windows: "\f17a"; +$fa-var-won: "\f159"; +$fa-var-wordpress: "\f19a"; +$fa-var-wpbeginner: "\f297"; +$fa-var-wpexplorer: "\f2de"; +$fa-var-wpforms: "\f298"; +$fa-var-wrench: "\f0ad"; +$fa-var-xing: "\f168"; +$fa-var-xing-square: "\f169"; +$fa-var-y-combinator: "\f23b"; +$fa-var-y-combinator-square: "\f1d4"; +$fa-var-yahoo: "\f19e"; +$fa-var-yc: "\f23b"; +$fa-var-yc-square: "\f1d4"; +$fa-var-yelp: "\f1e9"; +$fa-var-yen: "\f157"; +$fa-var-yoast: "\f2b1"; +$fa-var-youtube: "\f167"; +$fa-var-youtube-play: "\f16a"; +$fa-var-youtube-square: "\f166"; + diff --git a/dashboard/src/assets/font-awesome/scss/font-awesome.scss b/dashboard/src/assets/font-awesome/scss/font-awesome.scss new file mode 100644 index 00000000..112b0830 --- /dev/null +++ b/dashboard/src/assets/font-awesome/scss/font-awesome.scss @@ -0,0 +1,34 @@ +/*! + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ + +@import "variables"; +@import "mixins"; +@import "path"; +@import "core"; +@import "larger"; +@import "fixed-width"; +@import "list"; +@import "bordered-pulled"; +@import "animated"; +@import "rotated-flipped"; +@import "stacked"; +@import "icons"; +@import "screen-reader"; diff --git a/dashboard/src/assets/img/ffdl-blue.png b/dashboard/src/assets/img/ffdl-blue.png index 97039c87..ddde1e04 100644 Binary files a/dashboard/src/assets/img/ffdl-blue.png and b/dashboard/src/assets/img/ffdl-blue.png differ diff --git a/dashboard/src/assets/img/ffdl-text.png b/dashboard/src/assets/img/ffdl-text.png index 26f545dc..ffae33da 100644 Binary files a/dashboard/src/assets/img/ffdl-text.png and b/dashboard/src/assets/img/ffdl-text.png differ diff --git a/dashboard/src/assets/img/ffdl.png b/dashboard/src/assets/img/ffdl.png index 25960deb..dbe9ac1e 100644 Binary files a/dashboard/src/assets/img/ffdl.png and b/dashboard/src/assets/img/ffdl.png differ diff --git a/dashboard/src/environments/environment.prod.ts b/dashboard/src/environments/environment.prod.ts index 3612073b..c50aa17f 100644 --- a/dashboard/src/environments/environment.prod.ts +++ b/dashboard/src/environments/environment.prod.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export const environment = { production: true }; diff --git a/dashboard/src/environments/environment.ts b/dashboard/src/environments/environment.ts index b7f639ae..a02430b1 100644 --- a/dashboard/src/environments/environment.ts +++ b/dashboard/src/environments/environment.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // The file contents for the current environment will overwrite these during build. // The build system defaults to the dev environment which uses `environment.ts`, but if you do // `ng build --env=prod` then `environment.prod.ts` will be used instead. diff --git a/dashboard/src/favicon.ico b/dashboard/src/favicon.ico index 97039c87..ddde1e04 100644 Binary files a/dashboard/src/favicon.ico and b/dashboard/src/favicon.ico differ diff --git a/dashboard/src/index.html b/dashboard/src/index.html index ba66b2e6..64e61b41 100644 --- a/dashboard/src/index.html +++ b/dashboard/src/index.html @@ -9,7 +9,7 @@ - + Loading... diff --git a/dashboard/src/main.ts b/dashboard/src/main.ts index 91ec6da5..07c94ace 100644 --- a/dashboard/src/main.ts +++ b/dashboard/src/main.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; diff --git a/dashboard/src/polyfills.ts b/dashboard/src/polyfills.ts index 20d40751..25a0bca0 100644 --- a/dashboard/src/polyfills.ts +++ b/dashboard/src/polyfills.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /** * This file includes polyfills needed by Angular and is loaded before the app. * You can add your own extra polyfills to this file. diff --git a/dashboard/src/styles.css b/dashboard/src/styles.css index 90d4ee00..11f0ef35 100644 --- a/dashboard/src/styles.css +++ b/dashboard/src/styles.css @@ -1 +1,17 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /* You can add global styles to this file, and also import other style files */ diff --git a/dashboard/src/test.ts b/dashboard/src/test.ts index cd612eeb..5845b12a 100644 --- a/dashboard/src/test.ts +++ b/dashboard/src/test.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'zone.js/dist/long-stack-trace-zone'; diff --git a/dashboard/src/typings.d.ts b/dashboard/src/typings.d.ts index ef5c7bd6..1fe96738 100644 --- a/dashboard/src/typings.d.ts +++ b/dashboard/src/typings.d.ts @@ -1,3 +1,19 @@ +/* + * Copyright 2017-2018 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /* SystemJS module definition */ declare var module: NodeModule; interface NodeModule { diff --git a/databroker/objectstorage/src/utility.sh b/databroker/objectstorage/src/utility.sh index 35430f6b..b64079f1 100644 --- a/databroker/objectstorage/src/utility.sh +++ b/databroker/objectstorage/src/utility.sh @@ -114,4 +114,4 @@ function pushMetrics() { # Close UDP socket exec 3<&- exec 3>&- -} \ No newline at end of file +} diff --git a/databroker/s3/src/utility.sh b/databroker/s3/src/utility.sh index bb897f99..02f70360 100644 --- a/databroker/s3/src/utility.sh +++ b/databroker/s3/src/utility.sh @@ -87,4 +87,4 @@ function pushMetrics() { # Close UDP socket exec 3<&- exec 3>&- -} \ No newline at end of file +} diff --git a/demos/README.md b/demos/README.md new file mode 100644 index 00000000..ad9d69a4 --- /dev/null +++ b/demos/README.md @@ -0,0 +1,51 @@ + +# Fabric for Deep Learning related demos, talks, videos, publications and more. + +This is a running list of FfDL demos to be used for conference talks and presentations. + +## Demos to show +1. [Train and Depploy your Fashion MNIST model with FfDL](fashion-mnist-training/README.md) +2. [Launch adversarial attack on Fashion MNIST model ](fashion-mnist-adversarial/README.md) + +# FfDL Publications + +## Slides +- [Fabric for Deep Learning](https://www.slideshare.net/AnimeshSingh/fabric-for-deep-learning-94941117) + +## Videos +- [Introduction to Fabric for Deep Learning (FfDL)](https://www.youtube.com/watch?v=aKOqFL7VWhI) +- [Fabric for Deep Learning](https://www.youtube.com/watch?v=nQsYWmkfLP4) +- [FfDL at IEEE Computer Society Silicon Valley](https://youtu.be/wPKin0mN9LA?t=743) + +## Articles +### IBM-Affiliated +- [FfDL IBM Code Open Project Page](https://developer.ibm.com/code/open/projects/fabric-for-deep-learning-ffdl/) +- [developerWorks: Fabric for Deep Learning](https://developer.ibm.com/code/2018/03/20/fabric-for-deep-learning/) +- [developerWorks: Democratize AI with Fabric for Deep Learning (FfDL)](https://developer.ibm.com/code/2018/03/20/democratize-ai-with-fabric-for-deep-learning/) +- [Introducing Fabric for Deep Learning (FfDL) on medium.com](https://medium.com/ibm-watson/introducing-fabric-for-deep-learning-ffdl-542522774775) +- [developerWorks: Serve it hot! Deploy your FfDL trained models using Seldon](https://developer.ibm.com/code/2018/06/12/serve-it-hot-deploy-your-ffdl-trained-models-using-seldon/) +- [Deep Learning Advances from IBM Research](https://www.ibm.com/blogs/research/2018/03/deep-learning-advances/) +### Independent +- [Q&A on IBM's Fabric for Deep Learning with Chief Architect of Watson (InfoQ)](https://www.infoq.com/news/2018/04/ffdl-ruchir-puri) +- [IBM wants to open up the deep learning expertise bottleneck (IT World)](https://www.itworld.com/article/3263454/cloud-computing/ibm-wants-to-open-up-the-deep-learning-expertise-bottleneck.html) +- [IBM launches deep learning as a service inside its Watson Studio (Tech Crunch)](https://techcrunch.com/2018/03/19/ibm-launches-deep-learning-as-a-service-inside-its-watson-studio/) + +# FfDL Ecosystem and Related Projects +- [Adversarial Robustness Toolbox](https://developer.ibm.com/code/open/projects/adversarial-robustness-toolbox/), [Github](https://github.com/IBM/adversarial-robustness-toolbox) +- [IBM Code Model Asset Exchange (MAX)](https://developer.ibm.com/code/exchanges/models/) +- [H2O.ai Integration](https://github.com/IBM/FfDL/tree/master/community/FfDL-H2Oai) +- [Seldon Integration](https://github.com/IBM/FfDL/tree/master/community/FfDL-Seldon) + +## Papers +- [IBM Deep Learning Service](https://arxiv.org/abs/1709.05871) +- [Scalable Multi-Framework Multi-Tenant Lifecycle Management of Deep Learning Training Jobs](http://learningsys.org/nips17/assets/papers/paper_29.pdf) +- [Dependability in a Multi-tenant Multi-framework Deep Learning as-a-Service Platform](https://arxiv.org/abs/1805.06801) + +# IBM Products +## Watson Machine Learning and Watson Studio +- [IBM Watson Machine Learning](https://www.ibm.com/cloud/machine-learning) +- [IBM Watson Studio](https://www.ibm.com/cloud/watson-studio) +- [IBM Watson Studio Workshop](https://github.com/PubChimps/DLaaSWorkshop) +- [IBM Watson Studio: Deep Learning as a Service](https://www.ibm.com/cloud/deep-learning) +- [IBM Cloud Container Service](https://www.ibm.com/cloud/container-service) +- [IBM Cloud Object Storage](https://www.ibm.com/cloud/object-storage) diff --git a/demos/fashion-mnist-adversarial/.gitignore b/demos/fashion-mnist-adversarial/.gitignore new file mode 100644 index 00000000..1decd3ec --- /dev/null +++ b/demos/fashion-mnist-adversarial/.gitignore @@ -0,0 +1,7 @@ +.ipynb_checkpoints/ +manifest.yml +*sample* +*model* +*.py +*.npz +report.txt diff --git a/demos/fashion-mnist-adversarial/ART_with_FfDL.ipynb b/demos/fashion-mnist-adversarial/ART_with_FfDL.ipynb new file mode 100644 index 00000000..0c6d5529 --- /dev/null +++ b/demos/fashion-mnist-adversarial/ART_with_FfDL.ipynb @@ -0,0 +1,1464 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Generate Adversarial Samples for Deep Learning Models with the Adversarial Robustness Toolbox (ART)\n", + "\n", + "This notebook shows how to use adversarial attack techniques from the [Adversarial Robustness Toolbox (ART)](https://developer.ibm.com/code/open/projects/adversarial-robustness-toolbox/) on Deep Learning models trained with [Fabric for Deep Learning (FfDL)](https://github.com/IBM/ffdl/). The ART library supports crafting and analyzing various attack and defense methods for deep learning models. \n", + "\n", + "In this notebook, you will learn how to incorporate one of the attack methods supported by ART, the *Fast Gradient Method (FGM)*, into your training pipeline to generate adversarial samples to evaluate the robustness of the trained model. The model is a *Convolutional Neural Network (CNN)* trained on the [Fashion-MNIST](https://github.com/zalandoresearch/fashion-mnist) dataset using the [Keras](https://keras.io/) deep learning framework with a [TensorFlow](https://www.tensorflow.org/) backend.\n", + "\n", + "The Github repository for the ART library can be found here: https://github.com/IBM/adversarial-robustness-toolbox\n", + "\n", + "This notebook uses Python 3.\n", + "\n", + "\n", + "## Contents\n", + "\n", + "1.\t[Set up the environment](#setup)\n", + "2.\t[Create a Keras model](#model)\n", + "3. [Train the model](#train)\n", + "4.\t[Generate adversarial samples for a robustness check](#art)\n", + "5.\t[Summary and next steps](#summary)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 1. Setup\n", + "\n", + "It is recommended that you run this notebook inside a Python 3 virtual environment. Make sure you have all required libraries installed.\n", + "\n", + "To store model and training data, this notebook requires access to a Cloud Object Storage (COS) instance. [BlueMix Cloud Object Storage](https://console.bluemix.net/catalog/services/cloud-object-storage) offers a free *lite plan*. Follow [these instructions](https://dataplatform.ibm.com/docs/content/analyze-data/ml_dlaas_object_store.html) to create your COS instance and generate [service credentials](https://console.bluemix.net/docs/services/cloud-object-storage/iam/service-credentials.html#service-credentials) with [HMAC keys](https://console.bluemix.net/docs/services/cloud-object-storage/hmac/credentials.html#using-hmac-credentials).\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Enter your cluster and object storage information:**" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "env = dict(os.environ)\n", + "\n", + "user_data = {\n", + " \"public_ip\" : env.get(\"PUBLIC_IP\"), # Public IP of your Kubernetes cluster with FfDL deployed on it \n", + " \"kubeconfig_file\" : env.get(\"KUBECONFIG\"), # Path pointing to your Kubernetes cluster configuration file \n", + " \"cos_hmac_access_key_id\" : env.get(\"AWS_ACCESS_KEY_ID\"), # Cloud Object Storage (AWS) Access Key ID \n", + " \"cos_hmac_secret_access_key\" : env.get(\"AWS_SECRET_ACCESS_KEY\"), # Cloud Object Storage (AWS) Secret Access Key \n", + " \"cos_service_endpoint\" : env.get(\"AWS_ENDPOINT_URL\"), # Cloud Object Storage endpoint, i.e. 'https://s3-api.us-geo.objectstorage.softlayer.net' \n", + " \"cos_region_name\" : env.get(\"AWS_DEFAULT_REGION\"), # Cloud Object Storage default region, i.e. 'us-east-1' \n", + " \"ffdl_dir\" : env.get(\"FFDL_DIR\", os.getcwd().replace(\"/demos/fashion-mnist-adversarial\", \"\"))\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "unset_vars = [key for (key, value) in user_data.items() if not value]\n", + "\n", + "for var in unset_vars:\n", + " print(\"Dictionary 'user_data' is missing '%s'\" % var)\n", + " \n", + "assert not unset_vars, \"Enter 'user_data' to run this notebook!\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.1. Verify or Install Required Python Libraries" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Using TensorFlow backend.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "All required libraries are installed.\n", + "keras>=2.1.6\r\n", + "tensorflow>=1.8\r\n", + "ipython>=5.0.0\r\n", + "jupyter>=1.0.0\r\n", + "requests>=2.12.0,<=2.18.4\r\n", + "wget\r\n", + "boto3\r\n", + "git+git://github.com/IBM/adversarial-robustness-toolbox@master\r\n" + ] + } + ], + "source": [ + "import sys\n", + "\n", + "def is_venv():\n", + " return (hasattr(sys, 'real_prefix') or (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix))\n", + "\n", + "try:\n", + " import keras, tensorflow, requests, wget, boto3, art\n", + " print(\"All required libraries are installed.\")\n", + " !cat requirements.txt\n", + "except ModuleNotFoundError:\n", + " if is_venv:\n", + " print(\"Installing required libraries into virtual environment.\")\n", + " !python -m pip install -r requirements.txt\n", + " else:\n", + " print(\"Please install the required libraries.\")\n", + " !cat requirements.txt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2. Connect to Cloud Object Storage (COS)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a `boto3.resource` to interact with the COS instance. The `boto3` library allows Python developers to manage Cloud Object Storage (COS)." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "cos = boto3.resource(\"s3\", \n", + " aws_access_key_id = user_data[\"cos_hmac_access_key_id\"],\n", + " aws_secret_access_key = user_data[\"cos_hmac_secret_access_key\"],\n", + " endpoint_url = user_data[\"cos_service_endpoint\"],\n", + " region_name = user_data[\"cos_region_name\"]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "# for bucket in cos.buckets.all():\n", + "# print(bucket.name)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create two buckets, which you will use to store training data and training results.\n", + "\n", + "**Note:** The bucket names must be unique." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Creating bucket \"training-data-b467af13-ab67-4b5d-b0ca-c522fa0f4802\" ...\n", + "Creating bucket \"training-results-b467af13-ab67-4b5d-b0ca-c522fa0f4802\" ...\n" + ] + } + ], + "source": [ + "from uuid import uuid4\n", + "\n", + "bucket_uid = str(uuid4())\n", + "training_data_bucket = 'training-data-' + bucket_uid\n", + "training_result_bucket = 'training-results-' + bucket_uid\n", + "\n", + "def create_buckets(bucket_names):\n", + " for bucket in bucket_names:\n", + " print('Creating bucket \"{}\" ...'.format(bucket))\n", + " try:\n", + " cos.create_bucket(Bucket=bucket)\n", + " except boto3.exceptions.botocore.client.ClientError as e:\n", + " print('Error: {}.'.format(e.response['Error']['Message']))\n", + "\n", + "buckets = [training_data_bucket, training_result_bucket]\n", + "\n", + "create_buckets(buckets)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now you should have 2 buckets." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.3. Download MNIST Training Data and Upload it to the COS Buckets" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Select a data set (https://keras.io/datasets/):\n", + "- `mnist.npz`\n", + "- `fashion_mnist.npz`" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "datasets = [\"mnist.npz\", \"fashion_mnist.npz\"]\n", + "\n", + "dataset_filename = datasets[1] # 'fashion_mnist.npz'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Download the training data and upload it to the `training-data` bucket." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Uploading files to training-data-b467af13-ab67-4b5d-b0ca-c522fa0f4802:\n", + "- fashion_mnist.npz was uploaded\n" + ] + } + ], + "source": [ + "from keras.datasets import mnist, fashion_mnist\n", + "import numpy as np\n", + "\n", + "if \"fashion\" in dataset_filename:\n", + " (x_train, y_train), (x_test, y_test) = fashion_mnist.load_data() \n", + "else:\n", + " (x_train, y_train), (x_test, y_test) = mnist.load_data()\n", + " \n", + "np.savez_compressed(dataset_filename, x_train=x_train , y_train=y_train, x_test=x_test, y_test=y_test)\n", + "\n", + "bucket_obj = cos.Bucket(training_data_bucket)\n", + "print(\"Uploading files to {}:\".format(training_data_bucket))\n", + "\n", + "bucket_obj.upload_file(dataset_filename, dataset_filename)\n", + "print('- {} was uploaded'.format(dataset_filename)) " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Have a look at the list of the created buckets and their contents." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "training-data-b467af13-ab67-4b5d-b0ca-c522fa0f4802\n", + " File: fashion_mnist.npz, 30146.33kB\n", + "training-results-b467af13-ab67-4b5d-b0ca-c522fa0f4802\n" + ] + } + ], + "source": [ + "def print_bucket_contents(buckets):\n", + " for bucket_name in buckets:\n", + " print(bucket_name)\n", + " bucket_obj = cos.Bucket(bucket_name)\n", + " for obj in bucket_obj.objects.all():\n", + " print(\" File: {}, {:4.2f}kB\".format(obj.key, obj.size/1024))\n", + "\n", + "print_bucket_contents(buckets)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You are done with COS, and you are ready to train your model!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## 2. Create the Keras model\n", + "\n", + "In this section we:\n", + "\n", + "- [2.1 Package the model definition](#zip)\n", + "- [2.2 Prepare the training definition metadata](#manifest)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1. Create the Model Zip File \n", + "\n", + "Let's create the model [`convolutional_keras.py`](../edit/convolutional_keras.py) and add it to a zip file." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "script_filename = \"convolutional_keras.py\"\n", + "archive_filename = 'model.zip'" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing convolutional_keras.py\n" + ] + } + ], + "source": [ + "%%writefile $script_filename\n", + "\n", + "from __future__ import print_function\n", + "from keras.models import Sequential\n", + "from keras.layers import Dense, Dropout, Flatten\n", + "from keras.layers import Conv2D, MaxPooling2D\n", + "from keras import backend as K\n", + "\n", + "import keras\n", + "import numpy as np\n", + "import sys\n", + "import os\n", + "\n", + "batch_size = 128\n", + "num_classes = 10\n", + "epochs = 1\n", + "\n", + "img_rows, img_cols = 28, 28\n", + "\n", + "\n", + "def main(argv):\n", + " if len(argv) < 2:\n", + " sys.exit(\"Not enough arguments provided.\")\n", + " global image_path\n", + " i = 1\n", + " while i <= 2:\n", + " arg = str(argv[i])\n", + " if arg == \"--data\":\n", + " image_path = os.path.join(os.environ[\"DATA_DIR\"], str(argv[i+1]))\n", + " i += 2\n", + "\n", + "\n", + "if __name__ == \"__main__\":\n", + " main(sys.argv)\n", + "\n", + "\n", + "# load training and test data from npz file\n", + "f = np.load(image_path)\n", + "x_train = f['x_train']\n", + "y_train = f['y_train']\n", + "x_test = f['x_test']\n", + "y_test = f['y_test']\n", + "f.close()\n", + "\n", + "if K.image_data_format() == 'channels_first':\n", + " x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)\n", + " x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)\n", + " input_shape = (1, img_rows, img_cols)\n", + "else:\n", + " x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)\n", + " x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)\n", + " input_shape = (img_rows, img_cols, 1)\n", + "\n", + "x_train = x_train.astype('float32')\n", + "x_test = x_test.astype('float32')\n", + "x_train /= 255\n", + "x_test /= 255\n", + "\n", + "# convert class vectors to binary class matrices\n", + "y_train = keras.utils.to_categorical(y_train, num_classes)\n", + "y_test = keras.utils.to_categorical(y_test, num_classes)\n", + "\n", + "# model\n", + "model = Sequential()\n", + "model.add(Conv2D(32, kernel_size=(3, 3),\n", + " activation='relu',\n", + " input_shape=input_shape))\n", + "model.add(Conv2D(64, (3, 3), activation='relu'))\n", + "model.add(MaxPooling2D(pool_size=(2, 2)))\n", + "model.add(Dropout(0.25))\n", + "model.add(Flatten())\n", + "model.add(Dense(128, activation='relu'))\n", + "model.add(Dropout(0.5))\n", + "model.add(Dense(num_classes, activation='softmax'))\n", + "\n", + "model.compile(loss=keras.losses.categorical_crossentropy,\n", + " optimizer=keras.optimizers.Adadelta(),\n", + " metrics=['accuracy'])\n", + "model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_split=0.1)\n", + "\n", + "score = model.evaluate(x_test, y_test, verbose=0)\n", + "\n", + "print('Test loss:', score[0])\n", + "print('Test accuracy:', score[1])\n", + "\n", + "model_wt_path = os.environ[\"RESULT_DIR\"] + \"/keras_original_model.hdf5\"\n", + "model.save(model_wt_path)\n", + "print(\"Model saved to file: %s\" % model_wt_path)\n", + "\n", + "model_def_path = os.environ[\"RESULT_DIR\"] + \"/keras_original_model.json\"\n", + "model_json = model.to_json()\n", + "with open(model_def_path, \"w\") as json_file:\n", + " json_file.write(model_json)\n", + "print(\"Model definition saved to file: %s\" % model_def_path)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "import zipfile\n", + "\n", + "zipfile.ZipFile(archive_filename, mode='w').write(script_filename)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2. Prepare the Training Definition Metadata \n", + "- *FfDL* does not have a *Keras* community image so we need to `pip`-install *Keras* prior to running the `training_command` \n", + "- Your COS credentials are referenced in the `data_stores` > `connection` data." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "import yaml\n", + "\n", + "training_command = \"pip3 install keras; python3 %s --data ${DATA_DIR}/%s\" % (script_filename, dataset_filename)\n", + "\n", + "manifest = {\n", + " \"name\": \"keras_digit_recognition\",\n", + " \"description\": \"Hand-written Digit Recognition Training\",\n", + " \"version\": \"1.0\",\n", + " \"memory\": \"2Gb\",\n", + " \"gpus\": 0,\n", + " \"cpus\": 2,\n", + " \"data_stores\": [\n", + " {\n", + " \"id\": \"s3-art-notebook-files\",\n", + " \"type\": \"mount_cos\",\n", + " \"training_data\": {\n", + " \"container\": training_data_bucket\n", + " },\n", + " \"training_results\": {\n", + " \"container\": training_result_bucket\n", + " },\n", + " \"connection\": {\n", + " \"auth_url\": user_data[\"cos_service_endpoint\"],\n", + " \"user_name\": user_data[\"cos_hmac_access_key_id\"],\n", + " \"password\": user_data[\"cos_hmac_secret_access_key\"]\n", + " }\n", + " }\n", + " ],\n", + " \"framework\": {\n", + " \"name\": \"tensorflow\",\n", + " \"version\": \"1.5.0-py3\",\n", + " \"command\": training_command\n", + " },\n", + " \"evaluation_metrics\": {\n", + " \"type\": \"tensorboard\",\n", + " \"in\": \"$JOB_STATE_DIR/logs/tb\"\n", + " }\n", + "}\n", + "\n", + "yaml.dump(manifest, open(\"manifest.yml\", \"w\"), default_flow_style=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. Train the Model\n", + "\n", + "In this section, learn how to:\n", + "- [3.1. Setup the command line environment](#cmd_setup)\n", + "- [3.2. Train the model with FfDL](#train_ffdl)\n", + "- [3.3. Monitor the training log](#log)\n", + "- [3.4. Cancel the training](#cancel)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.1. Setup the Command Line Environment " + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "env: PUBLIC_IP=169.60.36.238\n", + "env: KUBECONFIG=~/.bluemix/plugins/container-service/clusters/my-ffdl-cluster/kube-config-dal12-my-ffdl-cluster.yml\n" + ] + } + ], + "source": [ + "%env PUBLIC_IP {user_data[\"public_ip\"]}\n", + "%env KUBECONFIG {user_data[\"kubeconfig_file\"]}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Setup the DLaaS URL, username and password" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "env: DLAAS_URL=http://169.60.36.238:30154\n", + "env: DLAAS_USERNAME=test-user\n", + "env: DLAAS_PASSWORD=test\n" + ] + } + ], + "source": [ + "restapi_port = !kubectl get service ffdl-restapi -o jsonpath='{.spec.ports[0].nodePort}'\n", + "dlaas_url = \"http://%s:%s\" % (user_data[\"public_ip\"], restapi_port[0])\n", + "\n", + "%env DLAAS_URL $dlaas_url\n", + "%env DLAAS_USERNAME = test-user\n", + "%env DLAAS_PASSWORD = test" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Obtain the correct FfDL CLI for your machine" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "import platform\n", + "\n", + "ffdl = \"%s/cli/bin/ffdl-%s\" % (user_data[\"ffdl_dir\"], \"osx\" if platform.system() == \"Darwin\" else \"linux\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.2. Start the Training Job \n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[\"Deploying model with manifest 'manifest.yml' and model file 'model.zip'...\",\n", + " 'Model ID: training-lh276tdmR',\n", + " 'OK']" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "out = !{ffdl} train \"manifest.yml\" \"model.zip\"\n", + "out" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.3. Monitor the Training Logs" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Getting model training logs for '\u001b[1;36mtraining-lh276tdmR\u001b[0m'...\n", + "Training with training/test data at:\n", + " DATA_DIR: /mnt/data/training-data-b467af13-ab67-4b5d-b0ca-c522fa0f4802\n", + " MODEL_DIR: /job/model-code\n", + " TRAINING_JOB: \n", + " TRAINING_COMMAND: pip3 install keras; python3 convolutional_keras.py --data ${DATA_DIR}/fashion_mnist.npz\n", + "Storing trained model at:\n", + " RESULT_DIR: /mnt/results/training-results-b467af13-ab67-4b5d-b0ca-c522fa0f4802/training-lh276tdmR\n", + "Contents of $MODEL_DIR\n", + "total 12\n", + "drwxrwxrwx 2 6342627 4294967294 4096 Jul 14 01:37 .\n", + "drwxrwxrwx 4 nobody 4294967294 4096 Jul 14 01:37 ..\n", + "-rwxrwxrwx 1 6342627 4294967294 2673 Jul 13 18:23 convolutional_keras.py\n", + "Contents of $DATA_DIR\n", + "total 30151\n", + "drwxrwxr-x 1 root root 0 Jan 1 1970 .\n", + "drwxr-xr-x 3 root root 4096 Jul 14 01:36 ..\n", + "---------- 1 root root 30869845 Jul 14 01:23 fashion_mnist.npz\n", + "CHECKPOINT_DIR=/mnt/results/training-results-b467af13-ab67-4b5d-b0ca-c522fa0f4802/_wml_checkpoints\n", + "DATA_DIR=/mnt/data/training-data-b467af13-ab67-4b5d-b0ca-c522fa0f4802\n", + "DOWNWARD_API_POD_NAME=learner-a2b0c40c-9975-415a-46d9-4f1c89ce7dcc-0\n", + "DOWNWARD_API_POD_NAMESPACE=default\n", + "ELASTICSEARCH_PORT=tcp://172.21.204.56:9200\n", + "ELASTICSEARCH_PORT_9200_TCP=tcp://172.21.204.56:9200\n", + "ELASTICSEARCH_PORT_9200_TCP_ADDR=172.21.204.56\n", + "ELASTICSEARCH_PORT_9200_TCP_PORT=9200\n", + "ELASTICSEARCH_PORT_9200_TCP_PROTO=tcp\n", + "ELASTICSEARCH_SERVICE_HOST=172.21.204.56\n", + "ELASTICSEARCH_SERVICE_PORT=9200\n", + "ELASTICSEARCH_SERVICE_PORT_HTTP=9200\n", + "FFDL_LCM_PORT=tcp://172.21.37.214:80\n", + "FFDL_LCM_PORT_80_TCP=tcp://172.21.37.214:80\n", + "FFDL_LCM_PORT_80_TCP_ADDR=172.21.37.214\n", + "FFDL_LCM_PORT_80_TCP_PORT=80\n", + "FFDL_LCM_PORT_80_TCP_PROTO=tcp\n", + "FFDL_LCM_SERVICE_HOST=172.21.37.214\n", + "FFDL_LCM_SERVICE_PORT=80\n", + "FFDL_LCM_SERVICE_PORT_GRPC=80\n", + "FFDL_RESTAPI_PORT=tcp://172.21.137.113:80\n", + "FFDL_RESTAPI_PORT_80_TCP=tcp://172.21.137.113:80\n", + "FFDL_RESTAPI_PORT_80_TCP_ADDR=172.21.137.113\n", + "FFDL_RESTAPI_PORT_80_TCP_PORT=80\n", + "FFDL_RESTAPI_PORT_80_TCP_PROTO=tcp\n", + "FFDL_RESTAPI_SERVICE_HOST=172.21.137.113\n", + "FFDL_RESTAPI_SERVICE_PORT=80\n", + "FFDL_RESTAPI_SERVICE_PORT_FFDL=80\n", + "FFDL_TRAINER_PORT=tcp://172.21.146.32:80\n", + "FFDL_TRAINER_PORT_80_TCP=tcp://172.21.146.32:80\n", + "FFDL_TRAINER_PORT_80_TCP_ADDR=172.21.146.32\n", + "FFDL_TRAINER_PORT_80_TCP_PORT=80\n", + "FFDL_TRAINER_PORT_80_TCP_PROTO=tcp\n", + "FFDL_TRAINER_SERVICE_HOST=172.21.146.32\n", + "FFDL_TRAINER_SERVICE_PORT=80\n", + "FFDL_TRAINER_SERVICE_PORT_GRPC=80\n", + "FFDL_TRAININGDATA_PORT=tcp://172.21.180.242:80\n", + "FFDL_TRAININGDATA_PORT_80_TCP=tcp://172.21.180.242:80\n", + "FFDL_TRAININGDATA_PORT_80_TCP_ADDR=172.21.180.242\n", + "FFDL_TRAININGDATA_PORT_80_TCP_PORT=80\n", + "FFDL_TRAININGDATA_PORT_80_TCP_PROTO=tcp\n", + "FFDL_TRAININGDATA_SERVICE_HOST=172.21.180.242\n", + "FFDL_TRAININGDATA_SERVICE_PORT=80\n", + "FFDL_TRAININGDATA_SERVICE_PORT_GRPC=80\n", + "FFDL_UI_PORT=tcp://172.21.53.228:80\n", + "FFDL_UI_PORT_80_TCP=tcp://172.21.53.228:80\n", + "FFDL_UI_PORT_80_TCP_ADDR=172.21.53.228\n", + "FFDL_UI_PORT_80_TCP_PORT=80\n", + "FFDL_UI_PORT_80_TCP_PROTO=tcp\n", + "FFDL_UI_SERVICE_HOST=172.21.53.228\n", + "FFDL_UI_SERVICE_PORT=80\n", + "FFDL_UI_SERVICE_PORT_HTTP=80\n", + "GPU_COUNT=0.000000\n", + "HOME=/root\n", + "JOB_STATE_DIR=/job\n", + "LEARNER_ID=1\n", + "LEARNER_NAME_PREFIX=learner-a2b0c40c-9975-415a-46d9-4f1c89ce7dcc\n", + "LOG_DIR=/job/logs\n", + "MODEL_DIR=/job/model-code\n", + "NUM_LEARNERS=1\n", + "OLDPWD=/notebooks\n", + "PATH=/usr/local/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n", + "PROMETHEUS_PORT=tcp://172.21.74.212:9090\n", + "PROMETHEUS_PORT_9090_TCP=tcp://172.21.74.212:9090\n", + "PROMETHEUS_PORT_9090_TCP_ADDR=172.21.74.212\n", + "PROMETHEUS_PORT_9090_TCP_PORT=9090\n", + "PROMETHEUS_PORT_9090_TCP_PROTO=tcp\n", + "PROMETHEUS_SERVICE_HOST=172.21.74.212\n", + "PROMETHEUS_SERVICE_PORT=9090\n", + "PROMETHEUS_SERVICE_PORT_PROMETHEUS=9090\n", + "PWD=/job/model-code\n", + "PYTHONPATH=:/job/model-code\n", + "RESULT_DIR=/mnt/results/training-results-b467af13-ab67-4b5d-b0ca-c522fa0f4802/training-lh276tdmR\n", + "S3_PORT=tcp://172.21.46.129:80\n", + "S3_PORT_80_TCP=tcp://172.21.46.129:80\n", + "S3_PORT_80_TCP_ADDR=172.21.46.129\n", + "S3_PORT_80_TCP_PORT=80\n", + "S3_PORT_80_TCP_PROTO=tcp\n", + "S3_SERVICE_HOST=172.21.46.129\n", + "S3_SERVICE_PORT=80\n", + "SHLVL=3\n", + "TRAINING_COMMAND=pip3 install keras; python3 convolutional_keras.py --data ${DATA_DIR}/fashion_mnist.npz\n", + "TRAINING_ID=training-lh276tdmR\n", + "_=/usr/bin/env\n", + "Sat Jul 14 01:37:35 UTC 2018: Running training job\n", + "Collecting keras\n", + " Downloading https://files.pythonhosted.org/packages/68/12/4cabc5c01451eb3b413d19ea151f36e33026fc0efb932bf51bcaf54acbf5/Keras-2.2.0-py2.py3-none-any.whl (300kB)\n", + "Requirement already satisfied: numpy>=1.9.1 in /usr/local/lib/python3.5/dist-packages (from keras)\n", + "Collecting pyyaml (from keras)\n", + " Downloading https://files.pythonhosted.org/packages/9e/a3/1d13970c3f36777c583f136c136f804d70f500168edc1edea6daa7200769/PyYAML-3.13.tar.gz (270kB)\n", + "Requirement already satisfied: scipy>=0.14 in /usr/local/lib/python3.5/dist-packages (from keras)\n", + "Requirement already satisfied: h5py in /usr/local/lib/python3.5/dist-packages (from keras)\n", + "Requirement already satisfied: six>=1.9.0 in /usr/local/lib/python3.5/dist-packages (from keras)\n", + "Collecting keras-preprocessing==1.0.1 (from keras)\n", + " Downloading https://files.pythonhosted.org/packages/f8/33/275506afe1d96b221f66f95adba94d1b73f6b6087cfb6132a5655b6fe338/Keras_Preprocessing-1.0.1-py2.py3-none-any.whl\n", + "Collecting keras-applications==1.0.2 (from keras)\n", + " Downloading https://files.pythonhosted.org/packages/e2/60/c557075e586e968d7a9c314aa38c236b37cb3ee6b37e8d57152b1a5e0b47/Keras_Applications-1.0.2-py2.py3-none-any.whl (43kB)\n", + "Building wheels for collected packages: pyyaml\n", + " Running setup.py bdist_wheel for pyyaml: started\n", + " Running setup.py bdist_wheel for pyyaml: finished with status 'done'\n", + " Stored in directory: /root/.cache/pip/wheels/ad/da/0c/74eb680767247273e2cf2723482cb9c924fe70af57c334513f\n", + "Successfully built pyyaml\n", + "Installing collected packages: pyyaml, keras-preprocessing, keras-applications, keras\n", + "Successfully installed keras-2.2.0 keras-applications-1.0.2 keras-preprocessing-1.0.1 pyyaml-3.13\n", + "You are using pip version 9.0.1, however version 10.0.1 is available.\n", + "You should consider upgrading via the 'pip install --upgrade pip' command.\n", + "2018-07-14 01:37:43.291928: I tensorflow/core/platform/cpu_feature_guard.cc:137] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA\n", + "Train on 54000 samples, validate on 6000 samples\n", + "Epoch 1/1\n", + "\n", + " 128/54000 [..............................] - ETA: 5:28 - loss: 2.3091 - acc: 0.1250\n", + " 256/54000 [..............................] - ETA: 4:38 - loss: 2.2554 - acc: 0.1211\n", + " 384/54000 [..............................] - ETA: 4:25 - loss: 2.1936 - acc: 0.1589\n", + " 512/54000 [..............................] - ETA: 4:20 - loss: 2.1520 - acc: 0.1895\n", + " 640/54000 [..............................] - ETA: 4:17 - loss: 2.1030 - acc: 0.2188\n", + " 768/54000 [..............................] - ETA: 4:15 - loss: 2.0351 - acc: 0.2565\n", + " 896/54000 [..............................] - ETA: 4:13 - loss: 2.0135 - acc: 0.2667\n", + " 1024/54000 [..............................] - ETA: 4:11 - loss: 1.9821 - acc: 0.2852\n", + " 1152/54000 [..............................] - ETA: 4:08 - loss: 1.9363 - acc: 0.3099\n", + " 1280/54000 [..............................] - ETA: 4:07 - loss: 1.8913 - acc: 0.3305\n", + " 1408/54000 [..............................] - ETA: 4:06 - loss: 1.8613 - acc: 0.3438\n", + " 1536/54000 [..............................] - ETA: 4:05 - loss: 1.8418 - acc: 0.3503\n", + " 1664/54000 [..............................] - ETA: 4:04 - loss: 1.8098 - acc: 0.3666\n", + " 1792/54000 [..............................] - ETA: 4:03 - loss: 1.7659 - acc: 0.3823\n", + " 1920/54000 [>.............................] - ETA: 4:01 - loss: 1.7355 - acc: 0.3885\n", + " 2048/54000 [>.............................] - ETA: 4:01 - loss: 1.7017 - acc: 0.4009\n", + " 2176/54000 [>.............................] - ETA: 4:00 - loss: 1.6676 - acc: 0.4127\n", + " 2304/54000 [>.............................] - ETA: 4:00 - loss: 1.6366 - acc: 0.4249\n", + " 2432/54000 [>.............................] - ETA: 3:59 - loss: 1.6042 - acc: 0.4375\n", + " 2560/54000 [>.............................] - ETA: 3:59 - loss: 1.5827 - acc: 0.4449\n", + " 2688/54000 [>.............................] - ETA: 3:58 - loss: 1.5640 - acc: 0.4513\n", + " 2816/54000 [>.............................] - ETA: 3:57 - loss: 1.5430 - acc: 0.4585\n", + " 2944/54000 [>.............................] - ETA: 3:57 - loss: 1.5205 - acc: 0.4671\n", + " 3072/54000 [>.............................] - ETA: 3:55 - loss: 1.4985 - acc: 0.4749\n", + " 3200/54000 [>.............................] - ETA: 3:55 - loss: 1.4744 - acc: 0.4828\n", + " 3328/54000 [>.............................] - ETA: 3:54 - loss: 1.4552 - acc: 0.4904\n", + " 3456/54000 [>.............................] - ETA: 3:53 - loss: 1.4363 - acc: 0.4977\n", + " 3584/54000 [>.............................] - ETA: 3:53 - loss: 1.4161 - acc: 0.5067\n", + " 3712/54000 [=>............................] - ETA: 3:52 - loss: 1.3991 - acc: 0.5132\n", + " 3840/54000 [=>............................] - ETA: 3:52 - loss: 1.3832 - acc: 0.5167\n", + " 3968/54000 [=>............................] - ETA: 3:51 - loss: 1.3695 - acc: 0.5217\n", + " 4096/54000 [=>............................] - ETA: 3:51 - loss: 1.3520 - acc: 0.5286\n", + " 4224/54000 [=>... \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " ... ===========>.] - ETA: 4s - loss: 0.5864 - acc: 0.7932\n", + "53120/54000 [============================>.] - ETA: 4s - loss: 0.5858 - acc: 0.7935\n", + "53248/54000 [============================>.] - ETA: 3s - loss: 0.5855 - acc: 0.7935\n", + "53376/54000 [============================>.] - ETA: 2s - loss: 0.5853 - acc: 0.7935\n", + "53504/54000 [============================>.] - ETA: 2s - loss: 0.5850 - acc: 0.7937\n", + "53632/54000 [============================>.] - ETA: 1s - loss: 0.5844 - acc: 0.7939\n", + "53760/54000 [============================>.] - ETA: 1s - loss: 0.5844 - acc: 0.7939\n", + "53888/54000 [============================>.] - ETA: 0s - loss: 0.5842 - acc: 0.7939\n", + "54000/54000 [==============================] - 254s 5ms/step - loss: 0.5841 - acc: 0.7939 - val_loss: 0.3561 - val_acc: 0.8700\n", + "/usr/local/lib/python3.5/dist-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n", + " from ._conv import register_converters as _register_converters\n", + "Using TensorFlow backend.\n", + "Test loss: 0.3804996592760086\n", + "Test accuracy: 0.8649\n", + "Model saved to file: /mnt/results/training-results-b467af13-ab67-4b5d-b0ca-c522fa0f4802/training-lh276tdmR/keras_original_model.hdf5\n", + "Model definition saved to file: /mnt/results/training-results-b467af13-ab67-4b5d-b0ca-c522fa0f4802/training-lh276tdmR/keras_original_model.json\n", + "Training process finished. Exit code: 0\n", + "\n" + ] + } + ], + "source": [ + "if \"Model ID\" in out[1]:\n", + " model_id = out.fields()[1][-1]\n", + " !{ffdl} logs --follow {model_id}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.4. Cancel the Training Job (Optional)\n", + "Interrupt the execution of the cell above which should be following the training logs, then uncomment the code in the cell below and run it." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "# !{ffdl} halt {model_id}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4. Generate Adversarial Samples for a Model Robustness Check" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "After successfully training our model, we can now use the Fast Gradient Method (FGM) to generate adversarial samples for the trained model. The adversarial samples are then used to check the robustness of the trained model. Both the trained model as well as the dataset used to train the model are required inputs to the robustness check." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- [4.1. Download and evaluate the trained model](#eval_model)\n", + "- [4.2. Craft adversarial samples](#craft_adv_samples)\n", + "- [4.3. Generate robustness metrics](#robustness_check)\n", + "- [4.4. Show model predictions on adversarial samples](#show_adv_samples)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.1. Download and Evaluate the Trained Model " + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "weights_filename = \"keras_original_model.hdf5\"\n", + "network_definition_filename = \"keras_original_model.json\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print contents of the `training_result_bucket`" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "training-results-b467af13-ab67-4b5d-b0ca-c522fa0f4802\n", + " File: _wml_checkpoints/, 0.00kB\n", + " File: training-lh276tdmR/_submitted_code/model.zip, 2.75kB\n", + " File: training-lh276tdmR/keras_original_model.hdf5, 14092.55kB\n", + " File: training-lh276tdmR/keras_original_model.json, 2.75kB\n", + " File: training-lh276tdmR/learner-1/, 0.00kB\n", + " File: training-lh276tdmR/learner-1/.log-copy-complete, 0.00kB\n", + " File: training-lh276tdmR/learner-1/training-log.txt, 42.02kB\n" + ] + } + ], + "source": [ + "print_bucket_contents([training_result_bucket])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Download network definition and weights to current working directory" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Downloaded keras_original_model.hdf5\n", + "Downloaded keras_original_model.json\n" + ] + } + ], + "source": [ + "weights_file_in_cos_bucket = os.path.join(model_id, weights_filename)\n", + "network_definition_file_in_cos_bucket = os.path.join(model_id, network_definition_filename)\n", + "\n", + "bucket_obj = cos.Bucket(training_result_bucket)\n", + "\n", + "bucket_obj.download_file(weights_file_in_cos_bucket, weights_filename)\n", + "print('Downloaded', weights_filename)\n", + "\n", + "bucket_obj.download_file(network_definition_file_in_cos_bucket, network_definition_filename)\n", + "print('Downloaded', network_definition_filename)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load & compile the model that we created using `convolutional_keras.py`" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Network Definition: keras_original_model.json\n", + "Weights: keras_original_model.hdf5\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "import tensorflow as tf\n", + "from keras import backend as K\n", + "from keras.models import model_from_json\n", + "\n", + "print('Network Definition:', network_definition_filename)\n", + "print('Weights: ', weights_filename)\n", + "\n", + "# load model\n", + "json_file = open(network_definition_filename, 'r')\n", + "model_json = json_file.read()\n", + "json_file.close()\n", + "\n", + "model = model_from_json(model_json)\n", + "model.load_weights(weights_filename)\n", + "comp_params = {'loss': 'categorical_crossentropy',\n", + " 'optimizer': 'adam',\n", + " 'metrics': ['accuracy']}\n", + "model.compile(**comp_params)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load the test data and labels from `.npz` file" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "from keras.utils import np_utils\n", + "\n", + "f = np.load(dataset_filename)\n", + "x_original = f['x_test']\n", + "y = f['y_test']\n", + "f.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Visualize an original (non-adversarial) sample" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAJIAAACPCAYAAAARM4LLAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAC15JREFUeJztnVtoVtkVx//LeL/H2xgv6ETjJQgqDFKxSMUqVhBftEweah8G8mCLFfrQGfsgiII+2LcKBqujUKYWWhjRUbFiLIOXRGW0jpKLxXEyqDEq3q/j7kM+073+yfed77K/y9H1A/H8z/m+c3bCyt7rrL322uKcg2HkSq9iN8B4NzBDMoJghmQEwQzJCIIZkhEEMyQjCGZIRhDMkIwg5GRIIrJMRJpEpFVEPg3VKCN+SLaRbREpA9AMYAmANgCNAGqcc1dSfKdkw+i9eum/qUGDBin96NGjrO89cOBApX/88UelX7x4kfW9C0CHc2501Id65/CAeQBanXP/BQAR+RuAlQCSGlIpw4Yzb948pY8fP571vWfMmKH048ePlW5ubs763gXgu3Q+lMvQNh7A955uS5xTiEitiJwTkXM5PMsocXLpkdLCOVcHoA4o7aHNyI1cDOkHABM9PSFxriTo37+/0uvXr1e6pqZG6fLycqVHj9ZuwdOnT5UeMWJE2m15/vy50s+ePVOafaaTJ08qvWvXLqWPHDmS9rMLRS5DWyOAKhH5UET6AvgYwIEwzTLiRtY9knPutYj8FsBRAGUAdjvnvg3WMiNW5OQjOee+AvBVoLYYMSbrOFJWD8ujs71t2zala2trlR4yZIjS7KewfvXqldIDBgxQuk+fPl3HZWVl6trLly+VZv+KY1b9+vVL+Sy+/+nTp5VeuHAh8sh559xHUR+yKRIjCGZIRhDMkIwgxNZHYh9o586dSt+6dUvp169fZ3T/vn37Ks2xHh/+Hb5580Zp359K5/vcVn72hAkTlD58+LDSK1asSPm8DDEfySgcZkhGEMyQjCDE1ke6ffu20jy3xqkaHLsZO3Zsyvvfv39fac4Z8v0YTkHhtty9e1dpjguxD8RxJRFRmuNUgwcPVnrKlCldxx0dHcgR85GMwmGGZAQh7/lI+WLYsGFK89ATNZTt2LFD6bq6OqXPnz+v9M2bN5X2X8E5DffGjRtKjxkzRmkemioqKpRua2tTmn+2oUOHKs1TKpWVlV3HAYa2tLAeyQiCGZIRBDMkIwix9ZH4FZnTWfmVmdmwYYPSDx48UJpf0XlJUX19fdfxokWLUj7ryhW9sGbmzJlKs8+zbt06pTdv3qz0nTt3lGZ/cMGCBV3HDQ0NKdsWCuuRjCCYIRlBMEMyghCrKRI/tYNjKzylwT7S8OHDlT5wQC94WblypdJRvxf//ps2bVLXHj58qPSxY8eU5qVM7e3tSvPP1tLSojRPuXAa8f79+7uO16xZ063tGWJTJEbhMEMygmCGZAQhVnGkcePGJb3G6a08/8SMH9+t3kVKVq9enfTavn37lOaYFsekLl68qDTPtXEKTKZUVVXl9P1ssB7JCIIZkhEEMyQjCLHykUaNGpX2Z3kJEC/BZh+J56sYLjXjc/ToUaX9fCCge9xn+fLlSp84cUJp9qGi0oZ5+VJUGnE+sB7JCEKkIYnIbhFpF5HL3rkRInJMRFoS/5enuofx7pNOj/Q5gGV07lMAx51zVQCOJ7TxHhPpIznn/i0ik+n0SgA/SxzvBVAP4A8B29UjvFTZJyr/iEvLsB/BcSi+3/Tp05XeunVr17G//Kcnrl69qjRXuZ00aZLSa9euVXr+/PlK37t3T2nOAc80RhaCbH2kD5xzb7PhbwH4IFB7jJiS81ubc86lmtUXkVoAtcmuG+8G2fZIt0WkAgAS/7cn+6Bzrs4591E6qQhGfMm2RzoA4NcAtib+/zJYi1LAJYt92Mfh+S3WHJvZsmWL0hyHWrp0qdKzZ8/uOp41a5a6xvlB7BP5/hWg84cAYM6cOUgF/yyZltHJB+m8/n8B4DSA6SLSJiKfoNOAlohIC4CfJ7TxHpPOW1tNkkuLA7fFiDEW2TaCEKu5Ns7b8WE/geej2G/gdWy8zo3hz/tldaqrq1N+l8sQsq/H+UsM549H+UipPpuqhGEuWI9kBMEMyQiCGZIRhFj5SKniSAzPP/EOkLztAtckYl+CyyX37v3/X13UNqXsn7HPxKUC+X7sn3GcifOdfCZPnqz0tWvXUrY1W6xHMoJghmQEIVZDGy+79uHKrjxU7d27V2lOd+U0E4bDCX6aiT/M9QS/vvNQxyV6OHV2z549SkdNofhwerINbUZJY4ZkBMEMyQhCrHwkvxwM+x1cmo/L43HZG4bDBezH5FL+J2qKg69zqOHs2bMZ3d/fDTMqBTkU1iMZQTBDMoJghmQEIVY+kh9H4vJ4UbsjcUliJmpKhMnEZ2I/hb/LmuNlmZQhBHTMK5NppVywHskIghmSEQQzJCMIsfKR/PhLlN/Q1NSkdNSyar4fz63x9UziM1FxJPb3eAsxLp/M8P38tmVSCigXrEcygmCGZATBDMkIQqx8JD/vJ2pZTXNzs9KcWpvq3j3BPpGvc4nzAN3zjxjOrWI9cuTIpN/l5eP5wnokIwhmSEYQzJCMIMTKR/LzbKJ8JF7GzKVluFxyVHnkTIiKQXHbon6WqVOnKs3LmbiMoZ9bxXla+cJ6JCMI6dRHmigiJ0Tkioh8KyK/S5y3EslGF+n0SK8B/N45Vw3gJwB+IyLVsBLJhkc6hbZuAriZOH4kIlcBjEcRSiT7vgTPLzEcF+JYC69ji7pfKjLN544qU8jwNqnXr19Xeu7cuUnvX15emIEiIx8pUW97LoCzsBLJhkfab20iMhjAPwCsd849pMhu0hLJVh75/SCtHklE+qDTiP7qnPtn4nRaJZKtPPL7QWSPJJ1dz18AXHXO/cm7VPASyb6PxDnaDOdocw425wCxTxW1pUSqa1E52kyUj8SlaS5duqT0qlWrkn63UKWS0xnaFgD4FYD/iMg3iXMb0GlAf0+US/4OwC/z00QjDqTz1vY1gGR/jlYi2QBgkW0jELGaa/PnkKJypjl+wtu381r/VCWGo65HrVOLyvdmzaX+eJstzrVK1Z6obetDYT2SEQQzJCMIZkhGEGLlI/k5RH5uEtC9huT27duVXrxYv2Cy75Dp1gq+H5LpmreobR2GDh2qdH19vdIHDx5UeuPGjUnvF1XDIBTWIxlBMEMyghCroc1PG+XhgFNnuUvv6OhQuqqqSmkuG5xJ6m3UUMbXOZTAy5H8EodA9yXb/LMw/u+Gd/DOF9YjGUEwQzKCYIZkBCFWPtKpU6e6jnnagHdh5GmEadOm5a9hBaayslJp3k3J35KisbGxIG2yHskIghmSEQQzJCMIsfKRGhoauo55KXKmaSFxJmqbLj+GxmWi84X1SEYQzJCMIJghGUGIlY/kl7y7cOGCusZxpCdPnqS8Fy8/4rm7Qm1P1RP8bG5ba2ur0ocOHVLaL6985syZwK3rGeuRjCCYIRlBMEMygiC5bLGZ8cNE7qBzVe4oAKmTaopHqbatWO2a5JyL3KuroIbU9VCRc6VaVKJU21aq7XqLDW1GEMyQjCAUy5DqivTcdCjVtpVquwAUyUcy3j1saDOCUFBDEpFlItIkIq0iUtRyyiKyW0TaReSyd64kaofHsbZ5wQxJRMoA/BnALwBUA6hJ1OsuFp8DWEbnSqV2ePxqmzvnCvIPwHwARz39GYDPCvX8JG2aDOCyp5sAVCSOKwA0FbN9Xru+BLCkVNvnnCvo0DYewPeebkucKyVKrnZ4XGqbm7OdBNf5Z1/UV1qube5fK4X2+RTSkH4AMNHTExLnSom0aocXglxqmxeDQhpSI4AqEflQRPoC+BidtbpLibe1w4EC1Q7viTRqmwNFbF+PFNhpXA6gGcA1AH8ssgP7BTo363mFTn/tEwAj0fk21ALgXwBGFKltP0XnsHUJwDeJf8tLpX09/bPIthEEc7aNIJghGUEwQzKCYIZkBMEMyQiCGZIRBDMkIwhmSEYQ/ge/lt3UHfc3WgAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%matplotlib inline\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "plt.figure(figsize=(2, 2))\n", + "plt.imshow(x_original[1], cmap='gray')\n", + "print(y[1])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Standardize the Numpy array" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "x_original = np.expand_dims(x_original, axis=3)\n", + "x_original = x_original.astype('float32') / 255\n", + "y = np_utils.to_categorical(y, 10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Evaluate the model and calculated test accuracy" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "model test loss: 38.04996589422226\n", + "model test accuracy: 86.49\n" + ] + } + ], + "source": [ + "scores = model.evaluate(x_original, y, verbose=0)\n", + "print('model test loss: ', scores[0]*100)\n", + "print('model test accuracy:', scores[1]*100)\n", + "model_accuracy = scores[1]*100" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2. Craft Adversarial Samples " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "After loading & compiling the model, we can create a `KerasClassifier` from the ART library." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [], + "source": [ + "from art.classifiers.keras import KerasClassifier\n", + "\n", + "classifier = KerasClassifier((0, 1), model)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "ART exposes many attacks like FGM, NewtonFool, DeepFool, Carlini etc. Let's use the Fast Gradient Method (FGM) to craft adversarial samples based on the test data (`x_test`)." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of adversarial samples crafted: 10000\n", + "adversarial samples saved to: adv_samples.npz\n" + ] + } + ], + "source": [ + "from art.attacks.fast_gradient import FastGradientMethod\n", + "\n", + "# configuration\n", + "epsilon = 0.2\n", + "\n", + "# create crafter object\n", + "crafter = FastGradientMethod(classifier, eps=epsilon)\n", + "\n", + "# craft samples on x_test (stored in variable x_original)\n", + "x_adv_samples = crafter.generate(x_original)\n", + "\n", + "# save the adversarial samples\n", + "adv_samples_filename = \"adv_samples.npz\"\n", + "np.savez(adv_samples_filename, x_original=x_original, x_adversarial=x_adv_samples, y=y)\n", + "\n", + "print(\"Number of adversarial samples crafted:\", len(x_adv_samples))\n", + "print(\"adversarial samples saved to:\", adv_samples_filename)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.3. Generate Model Robustness Metrics " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following functions can be used for gathering metrics like model robustness, confidence metric, perturbation metric" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy.linalg as la\n", + "import json\n", + "\n", + "\n", + "def get_metrics(model, x_original, x_adv_samples, y):\n", + " scores = model.evaluate(x_original, y, verbose=0)\n", + " model_accuracy_on_non_adversarial_samples = scores[1] * 100\n", + "\n", + " y_pred = model.predict(x_original, verbose=0)\n", + " y_pred_adv = model.predict(x_adv_samples, verbose=0)\n", + "\n", + " scores = model.evaluate(x_adv_samples, y, verbose=0)\n", + " model_accuracy_on_adversarial_samples = scores[1] * 100\n", + "\n", + " pert_metric = get_perturbation_metric(x_original, x_adv_samples, y_pred, y_pred_adv, ord=2)\n", + " conf_metric = get_confidence_metric(y_pred, y_pred_adv)\n", + "\n", + " data = {\n", + " \"model accuracy on test data:\": model_accuracy_on_non_adversarial_samples,\n", + " \"model accuracy on adversarial samples\": model_accuracy_on_adversarial_samples,\n", + " \"reduction in confidence\": conf_metric * 100,\n", + " \"average perturbation\": pert_metric * 100\n", + " }\n", + " return data\n", + "\n", + "\n", + "def get_perturbation_metric(x_original, x_adv, y_pred, y_pred_adv, ord=2):\n", + "\n", + " idxs = (np.argmax(y_pred_adv, axis=1) != np.argmax(y_pred, axis=1))\n", + "\n", + " if np.sum(idxs) == 0.0:\n", + " return 0\n", + "\n", + " perts_norm = la.norm((x_adv - x_original).reshape(x_original.shape[0], -1), ord, axis=1)\n", + " perts_norm = perts_norm[idxs]\n", + "\n", + " return np.mean(perts_norm / la.norm(x_original[idxs].reshape(np.sum(idxs), -1), ord, axis=1))\n", + "\n", + "\n", + "# This computes the change in confidence for all images in the test set\n", + "def get_confidence_metric(y_pred, y_pred_adv):\n", + "\n", + " y_classidx = np.argmax(y_pred, axis=1)\n", + " y_classconf = y_pred[np.arange(y_pred.shape[0]), y_classidx]\n", + "\n", + " y_adv_classidx = np.argmax(y_pred_adv, axis=1)\n", + " y_adv_classconf = y_pred_adv[np.arange(y_pred_adv.shape[0]), y_adv_classidx]\n", + "\n", + " idxs = (y_classidx == y_adv_classidx)\n", + "\n", + " if np.sum(idxs) == 0.0:\n", + " return 0\n", + "\n", + " idxnonzero = y_classconf != 0\n", + " idxs = idxs & idxnonzero\n", + "\n", + " return np.mean((y_classconf[idxs] - y_adv_classconf[idxs]) / y_classconf[idxs])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Display the robustness check metrics\n", + "\n", + "1. Model accuracy on test data\n", + "2. Model robustness on adversarial samples\n", + "3. Reduction in confidence\n", + "4. Perturbation metric" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"model accuracy on test data:\": 86.49,\n", + " \"model accuracy on adversarial samples\": 13.71,\n", + " \"reduction in confidence\": 49.82583820819855,\n", + " \"average perturbation\": 43.59939992427826\n", + "}\n" + ] + } + ], + "source": [ + "result = get_metrics(model, x_original, x_adv_samples, y)\n", + "\n", + "print(json.dumps(result, indent=4, sort_keys=False))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.4. Show Model Predictions on Adversarial Samples " + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "# https://keras.io/datasets/#fashion-mnist-database-of-fashion-articles\n", + "\n", + "fashion_labels = {\n", + " 0: \"T-shirt/top\",\n", + " 1: \"Trouser\",\n", + " 2: \"Pullover\",\n", + " 3: \"Dress\",\n", + " 4: \"Coat\",\n", + " 5: \"Sandal\",\n", + " 6: \"Shirt\",\n", + " 7: \"Sneaker\",\n", + " 8: \"Bag\",\n", + " 9: \"Ankle boot\"\n", + "}\n", + "\n", + "def get_label(y):\n", + " if \"fashion\" in dataset_filename:\n", + " return fashion_labels[y]\n", + " else:\n", + " return \"Predict: %i\" % y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Compare original images in the top row with the adversarial samples in the second row and test model predictions" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1oAAAC/CAYAAADnw60yAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAIABJREFUeJzsnXeYJFXV/z9tQtGXDAZyRsISlxwkg0jOKBkTKuKrIiLaDEGEnyKCCVSigUUEiQKSJEcJu8CScwbBV8EI9fuj53v7W9t3untmume6d8/neXi2ONNdXXXq3ltV93zvOZWiKAiCIAiCIAiCIAg6x9vG+wCCIAiCIAiCIAimN+JFKwiCIAiCIAiCoMPEi1YQBEEQBEEQBEGHiRetIAiCIAiCIAiCDhMvWkEQBEEQBEEQBB0mXrSCIAiCIAiCIAg6TLxoBUEQBEEQBEEQdJh40QqCIAiCIAiCIOgw8aIVBEEQBEEQBEHQYd4xnA9XKpWiWwcyHfByURRzD/dLY+HTt72t/j793ve+F4C//e1vbX9/5plnBuDNN99Mtn/9618dOrqm9KxP/+d//idtzzPPPAD84x//SLZ3vKPWtdxPb3/72xu2i6J+qDPNNBMAjzzySBeOONFzPpWv5pprrmRTW3P/TPu3af9eqVRK/wL897//BcrtPbfPUdJzPs2hvu/jQc5njuzyI8Df//73bh2i07M+XWKJJRpsb731VtqWf73vu8/f+c53AuV2nPP/ww8/PPqDLdOzPnU0Nrp/NDZqrIByP5b///nPf47FIToj8imM3/PUnHPOmbY1JuTGTKj785VXXhmjo6tRFEV+QGpBPKM2pS/6f5/Rlk+H9aIVNOWJ8T6AodBgCrDqqqsCcOWVV7b9/aWWWgooP2A9+OCDHTq6pvSET/0mpJu7/AhwwAEHAHDXXXcl2wc+8AGg/LD0vve9L23PPvvsAPznP/9JtkUWWQSAbbfdtmPHnqEnfOrIF/vuu2+y/fWvfwXKL6/T/g3KD1t6QHvXu96VbC+++CIA11xzTbL9+9//7sBRl+iKT/Vw7g/xuQfydl8cl1tuOaA8HshXPgng6AH3pZdeSrZrr722rd8bJT3XTsXJJ5+ctvVQ6i9V7373uwF4/PHHG2wA73//+4HyeCr/+wvZFlts0cGjBnrEp7nx1JllllkAePXVV5NtvvnmA/KTMVB/IZgyZUpnD7Y1PeFTyE+guI+Et6s11lgDKL/Aut/vv/9+AE499dSG/bS6jsP9XNB1eqatTke05dOQDgZBEARBEARBEHSYynBmGCKE2JQ7iqJYZbhf6pRPNWN64IEHJtuuu+4K1CMGAHPPXYtyvvHGG8k2xxxzNN23Zgs9uqCZsj/96U/J9vOf/xyASy+9dPgnkGdcfSp8plDRheuuuy7Z1l577SG/+3//939pWxJMqM8g+nXQ37fccstku+iii0Z62EPREz51PvvZzwLw/e9/P9n+8pe/APDcc88lmyJ+Tz/9dLI99NBDafvDH/4wUJYPXXHFFQDcc889yXbmmWd27NgH6YpPh5LzQX5m2OWsG2ywAQArrbRSsm2++eYAPPDAAw378WirS4tefvllAN7znvckm6IvF154YbJdcMEFADz55JNDHvMw6bl2qkiLS3sVMXXUj33c8DapsdP7viKHvr8NN9ywE4ftjKtPc5JAtXGPCEpa6f5R+3vttdcaPgf1yOLPfvazZDvooIM6cditGJFPYeyfpyZMmADA3XffnWw33ngjUI6au3RQ9zaPyOaiZLqOnYpYhXSwK/TcmDod0JZPI6IVBEEQBEEQBEHQYWKNVh9zzDHHpO1PfepTQHlWWxEoj0QpUuAz1For4Os0fB2LZhZ9hlYzsB/72MeSbeuttwbgpptuSrZ11113eCfVg/hsn1hhhRXStnyq2X+oz2q79t0XFGvW0KMWiy22GFBfEwddiWj1HEom4mtacrOmim55O/XoiyIOHkX80Ic+BMDUqVM7d8BjhGaHW61xUN/3JA3ykZ/3pEmTgHLbVSTB26lHvORLjy4oKr7gggsm23HHHdfwuYMPPhiAZ599dshz7Cc0q+/XQH7z8VLbvtbF26zaqe9HbT+3JnF6Idend955ZwAOP/zwZFPkZYcddki27373uwCsuOKKybbRRhulbUWuf/zjHyebro1HaDodeelVdA/RekCAF154AYDVVlst2QYGBoB6m4RyH95vv/2A8n1cUS5//ujCutcgmG6IiFYQBEEQBEEQBEGHiRetIAiCIAiCIAiCDhPSwT5EUiFf7Pv8888DrWvcKJ2zL87Wdq4uCZQXHU/7Hf89SUPWXHPNZNOCeU/wMD3gyQMkGXT5Ra6WjsuHJL3M1SObf/75O3uwPY7kf55CXIkvJMuEuizW29xss82WtiULcvms2vHkyZM7fdhdp5nMSQlEoO4/l16qbIDLfZVowRPYqJSAxg8ot0n9tvtPSTW8xINS7ruc8MgjjwRgn332GeoU+4rtt98eKCcPeuqpp4Cy9LJVHS1JEP07s846KwAf/OAHk23llVcG4I477ujMCfQgkvU988wzyaZ2c8kllyTbZpttBsDCCy+c3Y/6g/eBHNOjZFDtZJtttkk2taMbbrgh2TRWuoRdMmHJt6EsHVTiDC+ZITmxP3+ofIZLlV1KHwQzMhHRCoIgCIIgCIIg6DAR0epDjjjiCKC86F8z9z5LqqK5jhZo59K5eiFTT+eqGTCPyCh6pcgM1GfgtegW6otovdBkP890+eJioeiBz5ZqBtt95ouy5X//jq6nzy7OCDzxRK3m3/LLL59s8o+3U820+sJrjxQoKuMRB/29H5Nh5CJainYusMACyfboo48C5SireP3119O22q6nJ9d3F1988WTzGe9bb70VKC+GV/TBxwgl1/FkDhp/dt9992RTav1+LGKqgtpeckBRWO+z6ucqsgvlKIHatKsK9B0fX1QUvV8iWrlr6pEQlRrwKLTuH0oEBLDMMssA8NGPfjTZlNbdfe/JX8SSSy7ZsG9PxiJ1ht+jcsmOeh1PRHHllVcC5fuqxrt777032RZaaCEA9thjj2RT2/IEON6vt9pqKwAuu+yyZFMR49VXXz3ZNt54Y6BeABngvPPOA+Dhhx9u/8SCYDokIlpBEARBEARBEAQdJl60giAIgiAIgiAIOkxIB/sQLZzOLbZ2uaBqipx88snJJqmASzAkcfnb3/6WbE8++WTalizGJVtabPv0008nm47Hk0JIUqTkBtDf0sFll122wSbpoNcmk7TSa8e4zE24tFD+c5nljICkO/fcc0+ySfLmcqRFF10UgNlnnz3Z/O8PPfRQw74ljXPZZr+QkzRJYuXnI7mwJwmRbMrbl/7u0i0lHPj2t7+dbC7/075dkizZlUuN1eddKqb27LWPJB3sF7mgI1maS/nU5z1hkPq5yzbdL0IJRHzbr7lqwPULuWu69NJLp+2JEycCZZma+qySLkD9fuRJbZTo4c4770w2Hyd1HdznShLjskSN1foX+ut+pPuPJH0AX/va14ByIhCNDxr//O8+fp566qlA+f7s9zHV3LvllluSTTUiXZIpObHX6Pvyl78MlBP3BMGMSES0giAIgiAIgiAIOkxEtPoQzVb7Ymqf2ReHHHIIUJ451Qy3ZqWgnpp1/fXXz/7efffdB8CHP/zhZNMM9gEHHJBsSsvrabo1u7vWWmslmxbY9yMTJkwAytE9XQf3qa6RR/c8Vbnw66bv+KzsjIBmwj06qjbn7LDDDkB9phrqC+cBrr32WqAccdBMq0cUPDFBv6Hz9b7vCWmE2lAugY23SUW2L7/88mTzaJm+4wva1WY9eq6Ily+kF4pk9COebl3nqDT5UI/2ezRHY4OXafDrpciiR8G0b/9crvRDv+HRE7Uhj4TKl94mlYzFI02rrLIKUE8QAjBlypS0PffccwPlKJgSP3lyF0UMPWrTT8gPSncPsPfeewPl9O7ynScBUkTWo2HyuxJlQDmxixKOeJuXTQoDqPvYx+2LL764/RMLgumYiGgFQRAEQRAEQRB0mHjRCoIgCIIgCIIg6DAzlHTQZTS5OkbCpTiSb/iC2vGoC5FbTO0Lp3PyoTPOOAOArbfeuuFvXmtIksHDDz882bxG16677trwHdXxmTRpUrJJOuhJHyQ98gXx/YykK+57SQZdcqWEJX/+85+TzRcKS9bi8iDt56mnnur0Yfc0qsuy4YYbNtjcP5KluPT0pJNOStvym0sQ5WdP8NDPKFGAy4FzfV9SH5ezSp7msldJET0RifdzLXj3xAxKpuE1nyRBdCnnY489BpQlsxrH/Bh6GT/HnKRXMkpvX5K23n777cnmSXQknfPkQxozfQxxGWG/oZpuLuVTW/L70eTJk4G85NSTu0hm6ZI/T2gh//n9XBJhlwqrP3i/6Cc22GADoN63oJ5IxO/Z8p3LKxdccEGgnAhLNbj8+cYlrcsttxxQXg6gPuG1yDxZjtBYNb3U0AyCkRIRrSAIgiAIgiAIgg7TdxEtzSB6EgGPLsw777xAuUL5H/7wB6D9JAO5Rcjbb7992vaq7GNFLtWvn3duca98kWPHHXdssCkCBuXZVEUCPQWvFon7rGMzFl988bY+1+soIYjPpuo6aBYX6rOGq6++erL5bKtmYD36p1nBXNKM6RnNLnv/VKIFRaQcnz31aI586W1XEQKfMe+3JAMeVRHe1pRwwKNSap8exRc+bsgXnrTAo+caZ93n6vvuR33HU8cLb+NKJuPRnl5GCQSg3pZy9xHv2/KPRwk8LbmSCXgJDV0vLwfRb+3UUTvw/qkIiLdnJV5wn8rP3o8V/fNx158BNGZ6pCc3xipakxtD+sHfSl7hiVbUlzxSpXN67bXXkk3XxKOmUudIgQHl6Kzaqicr0Zjs1+dPf/oTUH5OUvv35EUR0QpyeF/Wdq68SSvWXXfdtK3kWJ1CSoSRJCuLiFYQBEEQBEEQBEGHiRetIAiCIAiCIAiCDtN30kExVFhxnXXWAWC11VZLNsnuTjjhhLb27XUkNt10U6C80HQ88AWlOSSJcGmFpIMunRAK9TuXXXZZ2vZK8aqR8dGPfjTZrr76aqAsJ5SM0H9PMgWvudPPSGLh8oucdPDcc89tuh9JulwqJHKJT6ZnFIr3BeryqUtmJfdxGZZLtiSf9cXc8rP3i35j4YUXTtvqYy7JkqTBfaGEFu6LXMIB9VVvhz62qj6Ro992+ZWunSd40Oe8r+hc+kU6uNRSS6VttVOvA6VzczlcTh518803p+3ll18eyCczytXj6kc0Tvo5SMbmcmCdt8ul1SbdP2q7Lmtz6Zr+7hJ6JcHw+7narCeTkSzOEz70KvKhS30333xzoNzu5AdPWKG+5zWztO01Mr3umJ4DfvGLXySbxmS1Y4D11lsPgDXXXDPZ5P9csp4gcHzcyyWoE/4Mr4RsANdddx1QTqglGXGr5GIaE/w+Jb761a+mbS23UUIaaH/pTES0giAIgiAIgiAIOkzfRbQ0Q+1vn6qWDvWZGZ/JUSKG8847L9k0g+YzYE888QRQXryp2S5PGT0eKFWq4wsIhaeyVRTJZwb1HV/k/Z3vfAcoV3p3lGrbZ3eVKnb//fdPNiUg8dlJzWg2S8zRT2h21P2cm4H5zW9+02DzxdaKOPjsoejX1MMjRb70dpqbKZLtrrvuyu5HfdlnuuXzfo5o+cydzi0XpfbPaSzziILGTk+QIZ/6eOr7yY238mkuQYb3C/ncfa/F9f2CJ7RQFMQjzvKLR15PO+20hv14ROAzn/kMkE9U4n7ORbv7BfVFb386H7/nSqmhcgRQH09z46r7x/2n/uBjbC6pRs6n/ZRG/4477gDg9NNPTzZFkTzyrWcY9UuoR8FceaEEGZ6G3/2q6+PPH3qe8siuIt8eqVb0bUZL7hTkyZVgaBa9clWVSrr4c5WXzlG/9uepE088EYBtttmm6XHlIlm77747ADvvvHOyqY/4c3C7yoyIaAVBEARBEARBEHSYeNEKgiAIgiAIgiDoMH0hHcwlV/CwtdeEknTAF34r5OdSO+3TbcssswxQXjynhbu5yudjSW5RukutmsmCjjrqqGTT4vhNNtkk2bSoddlll002lxIoVCqJIcCkSZMAWGGFFRqOy49Bx+iL8vsZyfpc2pZrG0oW4tx0001pWzLLnHwoJyecnlEbcYlZTj6UkxP64nhJunI1efpZhuWyNJ2HJ+fRYnOvdSOfetvUd73Nyb++YN3/ruQWvvheUiuXgOl4PGmPpEM+fufGi17Gfaq25m1S/vXx7fjjj2/Yj0tMdG1y97Wc1K4f0f3Xz0HtxhOHqF15cgrJ3nISTd+f+yrnU7VJJWqAeiIdv4Y5CX4v4fflXXbZBShLqHT83gblTx8zc9JXbQ91f9a9yOtxNbsWl156abJp6cL666+fbGeeeWb2d3oNtUGXY+qZ06XVkydPBuDTn/50sukcn3322WTz9p2rDZlLAJND17qZ5G6syR1TzpY7N7U/T5YmSeAPfvCDZDv22GOBcq1IT+qia3Pfffcl28YbbwyUpatHH300UF5GpPa81lprJZuWxLisUInfnnnmmYbzaEVEtIIgCIIgCIIgCDrMmIVpfNZIb7k++5SbwW6WAlsLigGef/75tK1ZM3/b1eyaJ8jQvv0tWzPhPlOmGc1cOuWRVIgeKb6oVfixy5e5Wa1DDjmk4bs+wyK/LL300tnfln89qpZbQKxrl4toOc2uaz8in+cSBjiPP/542l577bWB/GyqX5sZAaUl9r6v9uyzr7k25zO28qV/TrNPI6ky3yv44nWNTT4rqhnW888/v+E77lNFDH0s07aPGx5ZVMTGFQLypft56tSpAGy11VbJpt/28TSXYr6XcV9ovHefKsLt96BHH3206T4VJfC+r+vpEcF+85WjduXJUXS+HiWU35SUAer+9T6r65B7ZvC/59QFO+ywQ9p+8MEHgXK0odf97P1fM/977bVXsqnsysDAQLLpPP2ZR33cE1NJZeH3Yk9zr2jAww8/3PB3j3IrQuBp4qWUUQIPGJuI1rT31Fz0x59RdO4eeTvggAOAcoIw9XUfzx555BGgHJFR6ZzPf/7zybbRRhulbY2RXvKhWbTHf6+XIlkid0w5m555HLVZ74/77bcfUL6O888/PwCrrrpq9hikrvDvXHzxxUD5eUrvDXvvvXey6RnCk+BJ1eYqJP22j1/PPfdc9nimJSJaQRAEQRAEQRAEHSZetIIgCIIgCIIgCDpMV6SDOZlgLpTYTFYGeWnZrrvuCuQXz0E9PO5SBEk1fFGcJBpD1Y8Qkip4bSPVkRiqnk83yCXDcBRevvLKK5Nt3XXXBco1wORTl2RJbqGF79Min7o8RnIL/45CtL7gPZfYQbJOhd37EW/P8k+r8/HrkKspMaOi8Lu3SeH9Lrdg26VCknZ5oohcn+43XOqnhAwuU9V46wuB11lnHSCfQMTHVY2TLkX0NqnfcQldTu4qqZJfL33OZbQ+LvcDfs/ItT/JujwJQCs0jvr9LyfH6ue2q77s7SpXw1HyU5ehqg3lzn8oWbrG01x733bbbdP29773PaAsx3JpXi/i/VrLAC6//PJkU9vZfvvtk033Yr/nyF+77bZbsknm6jWLPPmOxhG/jpJx+bOTxoxLLrkk2ZQQyo9/LGmWYMLHwJVWWgmAL33pS8n2wAMPAPWkX1BPaONSNMk2ldwK6tI3b4su4Tz33HMBeOyxx5LtmGOOAeCCCy5INm+j/YbqD/p4r2d3r0N15JFHAuXkdnq2d5vu8z5O5OrouQxYY9DZZ5+dbPKvj0GShz755JPJpudoTwKz0047AfllIa2IiFYQBEEQBEEQBEGH6UpEKzdL74tYte2zCvpOLorlC9f0Juop2H0BsWbNPPWwFsT7DIxmOXyxrt6GcxE5Z9NNNwXGNqKVmwn2mTjNXHnFeM22+DkKvx4636FS2MsHPqOrWXafWT/11FOB1imcdb36OaLlM/yaeZkyZUrT72hxJsBBBx0ElK/DjIrap7dTRafcP3PMMUfDdz0hjdqkz3r1c6p89UeP9OVm+dUWfUFxLuqkMdHHWLVd95OPedrORbT8WB566CGgHNHStfNxRb/nY1cuCtEreMRe0SY/H82GfvnLX274rrddn1XXTLYnJVBCGN/3fPPNN6pj7wVyZQg8Zbb+7jPR2vY2J/+5H3PPCrnkG67EkM89TXSvj8FS0AAsscQSQPnc55lnHqDcH7Xtz0H6jiJSUE+A5UksPIKeSx2v5Ds+Ht97771AOXKj454wYUKyud+7RbNnyRxK1uHJEDyS3Qw9b/lzl/CEbIceemja1vORP49+/etfB8p9Q0oP97Ouh7dZXWsf83W9rrrqqmRz5ddwmGmmmVKbUVTqxRdfTH9Xf/Xz0e+7H6+55hqgXOpCCSa8X2tM8GdLna8ru1zVpvuJt3e1Y7fpeUERS4Drr78eKEdt5XOPhutcvNyCJzhrRm+PMEEQBEEQBEEQBH1IvGgFQRAEQRAEQRB0mFFLB3Nh91yFaA8NNqtp4wsxt9tuO6Ac+pNExaUnHupW+DdXe8BlLcLDy1rk5jaFGv2YvYL0WOHh49z5aEFsruq4+0Ih3eEkYcjVx5LNZU233HLLkN/VIn7Iy5r6jZyEyxe35nDZhPyWW2A/lvXZegH1N5eQ5WRnXt9FaDyA+jjhbbLXa+Q0QxLbnJTZ/aL+7TZtu/xC46TLOSS18nbo460kIj4m6njcJplLTq7jfV/H77IPr9HTa+RqgPm9R+00t+B/qMQNklnlJHQujcmN5b2M9zX5xReOe/0ZISmpS/5yCVjUp/1z3t5zNdskE/QalDk5Zj9JByWL9v6qRfoHH3xwsqmN+WJ+naf78Ne//jUAK664YsNvQL2N/uEPf0g21RbyZ5Lvf//7DfvR84lfRy2B8OPqJO985zt5//vfD9T95uOPtn2cOv7444Hyc+Saa64JwKyzzppsat9+f5FPV1tttWTT2OayWZeqXXHFFUD53qWlH9tss02yKRGJ70d9w9us+oHb5OfbbruN0TL33HOz//77A3UZaC4hhPtUCUN8PJMvXXaoe76PhZLmubRa5+P3Jh9vcstedIx+/SUTnThxYrKp3pkfv8Zzf07W30dyv+rtESYIgiAIgiAIgqAPiRetIAiCIAiCIAiCDjNs6aDkEAqjNZMBQl6ipnDiggsumGzKre9hfskAPHSqEKLLEHLZ8Py49Dv+OYWuc5mNPASrsKPLQJSJaplllkk2heq7hWcdVEjUQ6cKwXr2IOEh0VytolYyQkmFctnI/Lhy+8llyWlVE6yXUYjfZZs6b8/6lsNlXCInQZzRpIPC+2cuw1tOSuWSLcmCfGzIZdzsF9S33AeS9Xi/UwZWz5AnSZZnXMtJTDQ2+FiSy1TmbVf7cQmdtl0WovHUj1+/rUxp0NvSQZf7KkOWS4wk/3E/i6Hujco++oUvfCHZdL0ke4L+y5iZG8v83u0SOKH7q0uR1Ea8fakdDpXJMSc1VrbhXCY8JyeNbzdj3Viw8sorp23Jfj1DnjIxex9df/31gXp9O6j7c7311ku2O++8E6hnM4Ty2KLfufbaa5NNNaNcpqkaRC4dlP89K7S2uyUdfOutt9KzkMY0f87UPcKvr/r4vvvu27A/7+s6X5e4a7zzWk1aQiA59XA46aST0rbuY7mx19EzVm5JRif8/Oqrr3LOOecA9fbnmSt1r/asg3qO91pYysLodcgkGfTP6XxzUkSXAfrYrIyG3i+09GiTTTZpen467tzSIn8W0/UfSd29iGgFQRAEQRAEQRB0mGFHtKad6fEZOM0c+Nuptn2WVG+x/gapyFJuQbwvSNR+/C3f96MZbJ8hUxTHZxi0T/+uZsz9jVVv6/5mq8WO/vbcbXKJKBwttlRdF8c/L5/mEpYMRW7GT/71a+Oz2dMet/+Gz3D1G5oddT/rHH1WMEeu0ntu5jQ3szIj4P1JkQLVgoPybJ/w2iCKOCjqCPlZ9n5B/c7HRPU7b2tTp05t+Fyz6KlHDvUbvgDeZw01K5xLGOCL4TU+Tp48Odk0U+iRSEUhRjIrOB74TPU+++wDlPusZp032GCDZLv88suBocdVjdXeTnNqilzyiH4hV6dSkRm/9+jv/nyg77raJDdOehvXd3I+93u3oj9OLhrWSxGtG2+8MW0r4ZTX8snVAdLfva/rPN1HuQQZrjjJ+Ub79PuZxh5vs4o4uC2X0KiTvPnmmymK4wk8+hGPBo8n//znP5Ni64knngDy0Tq/1+q+scgiiySbVAybb755sp122mlAOTqlSH7ueWk4XHjhhQBsttlmyXb33XcD+Xp8fv9UH/F3GT33u63demsR0QqCIAiCIAiCIOgw8aIVBEEQBEEQBEHQYUZcR2ujjTYCynWvFOr3hc4KPXuoTp/zxduSknh9FYXvfEGiwuMusXAZisKXLhfQ7/giPD/GaclJXVzaICliTp7TLVrJGrTodd111236XeHygVyyi9xn3ee5c5cUxiUxOXmlL5rsN1SXwpOOSM61/PLLD3t/3ran3d+Mhi/SljTTZQa77757w3emTJmStiVlU10MqEsSVD+jn1Df8b6mccgXrOscXfKT62MaB7zNaZz0McXHav2ey0I0fvvnFlhgAQAeeeSRZFMtGh87JXPsF1mc+0Xn7fcbXRtvm5IODnV/ePnll4G87N737XLOfiAnU/N7ivqn33sk13E5ju6v3uZyteIcXSdva7penlQk9/1mssNewBNMqH+tsMIKyaakE7l6YZ6kRWOC+irUkxp4HSOvNSZ/elvV992vev7wNqDjcp9rKYY/iwW9zZtvvpmul8btDTfcMP1d19elvpJv+v1ZbemHP/xhsj366KNAOUmblpbk7mFD1dHSeONjrtqfP0+pNpkkhFBvs/5djT25ZVDtygWdiGgFQRAEQRAEQRB0mGFFtGaZZRZWX311oJ4KUzOUUF8g54v49GboC9tyC9QVdfI3W81S+eynZp1yi2eh/nbqkTHNxng6dn2uVXptJSbw2UX9PZf8oVv4AvVcREs+UJp8qM8w5Bayt8K/o1nJ3AJCZ7HFFgPKs2i6Dn79+znZg9I8Zn4nAAAgAElEQVTc7r333skmP6+00kpt70f+y7W/XlqIPRaoT7svlIbZU3/nZvh9FkqJWVZbbbVk8xnWfkPtyce63AyzIvCrrLJKsmlxu/dZbeciBW7zbY0DPiuobfe9ork+U60xy2ceNSvox6rUwb2Ook1+PdQmlYhlOLhfdK39/ue/0w/4sasN5aKxHuVSe/H2rL97dE/7zpUYgXo/9/uWnkO8TXpaaqFjHMl9cizYYost0rbGyi9+8YvJdtlllwHlqL36uicL0rnfeuutyaYkB37u7i9FKzwCoKiUK3+kEDruuOOSTYlH5p133mQ7+uijAXj88cfzJxv0NColon8dPf9BfWxzm9qN91u1EVdZqP15hEzf8Wdzb39qpx6V1rOnJ2DR/S4XvfbkTsLfZRTJctVGu/TmyBIEQRAEQRAEQdDHxItWEARBEARBEARBhxmWdPD1119PYWdJCJdbbrn097XWWqvhOwrLe+ILheB8UZnChS4/UHgvVwXd5WcuLVSI0RMTaLG4h6uVzMNDlrlkEDp+LayDejhxLGvBuJwsJzdT6NR9JflQu7WEhkqGIVyGlNvn1ltvDZT9rIW8/l2FkPsR1TRxGZvayHCkpOoPuRB2P9d+GglqdznZVKvEIC4NVB/w2m5DLZ7vBySTcImZZDi+UPiuu+4CygvktRg5J9P1Nqfxz9ucjzU6Bpf+qr17n15ooYUAuOCCC5LtlFNOAcq1qLS/XB2WXueGG24AYLfddks2JQTwGiztopo0UJeteB/oVSnbUHi7yt1LlKzB5cD6nLc5tS+XHeak1rmx09ukuP/++9N2ro5Wr0sHv/KVr6Ttm2++GSg/e0jK5AlyNO75fUpjgkv79Vzj5+5JNTSW+vWUbMzHJbXbn//858mm+l6+b9mC6Q/v1zk8McaMRm+OLEEQBEEQBEEQBH3MsKZ7ver24Ycf3vB3zbL4YvQlllgCqKf6hfrs54QJE5JNi6Rzs2I+S6Uo2OTJk5Ptj3/8Y9pWNfBWqXE18+qpTpV216Nv2vbZNc2yP/TQQ01/o5P4jJ/PJAmlG/cZUR2nz+o3S2WbS/kO+dnJXNRF19WrfO+www4Nn+vnBAWahfZFkooK+HVRRXSlL50WLfTMRVxmtIiW8KiJotS++DVHbtbb25fP3vYbp556aoNNY6zaF9Tb2Pbbb59sWijsM9+aWdYYDvVUuu4zj/KrLXpiBo0HvshYCoeTTjop2ZRu3qM9/Zay3FFaYh/TNJ56NKFV3xd+n1GE0vu+L/buB/yekYss6V7r5T/0HR87NTbm0jf7vSiXsCmXQMT9rPE2F8Ht1ei3Sl1A/Z7ux//AAw8A5ZTb2223HQArr7xysqkUz5577plsarf+HOSlS3QNPMollYonD9AzmJeYUIITfyZRhMzHjiCY3omIVhAEQRAEQRAEQYeJF60gCIIgCIIgCIIO09FYuSQiV155ZbJp+yc/+Uknf2rUbLXVVuN9CMPCZVU52Z8STLh0Qt/JyThytqFqlGg7Jy30mhtrrLEGUK8SP9S++60+TI6cvMolEq3kQ0oGILkl1GWxvboou9t4rThJVlpJzXL9wv3ntTimBzTGujxXsjNPhKO25HKoF154ASj3P33H+7b7VP3W23suQYmSbngSIsm4pxeUOMCll5K8e99XTa1W0kH3o8Zv34/7vN/w8xBqdy65l2wv18/9HpVLmOM0qz2opFB+DJ4kRvLjofY93qiNQV2a5xK922+/HSjXzNI9WAlcoL5Uw8fZSZMmAeUao74fjaW/+c1vkk31ulw6eOmllzbsR8ft8uV+rqEZBCNlxnyiC4IgCIIgCIIg6CK9ufozaMBn5jUj5TNF3/ve94DygljN3jWb7YP6bKFHnVqlHdc+PbX+NddcA8BFF12UbNVqteEYenXmcChyiUHOO++8ZFO6Z4+krL322gBcccUV2X3mkjzod3zGfEZCldyh3tZaRfc80YJmwL2d+uxtv+LtT/7w/qS2love+fnru4sttliyPfbYYw3f0SJ2/21PTKAIge9b0Z711lsv2RTRapVYp5fJHfvll1+ebEqM4VFAlbk466yzmu7bxwBdG2/vuTG4l/E2krvnKHqvEhkACy+8MFBOtqDolicDySWx8GitkrnkElp4O1UyBt+PJ9TpRbyUw3zzzQeU+7D646abbppsOj/3h3zs6e7Vpj3q59FyJeLwe5LKmPg4oX174pEFF1wQKD+n5BJ5BcH0TkS0giAIgiAIgiAIOky8aAVBEARBEARBEHSYkA72Cb6IVLIMlwpJjqdaYACLL744UK8cD82lWENJVWT3xcmSW/iCWEkK/BimPWaoSwr6hZx86Pzzz0+2PfbYAyhfD9U0Ouyww7L7lKQjl3Skn2sNjQYlawCYZ555gNayHpcXqY15EgG1yX7G20hOkrXkkksC5cQ0Gg/886pp+Pjjjyeb5GuqsQP5+kWeQEP9weVy2nb5Z+749d1+kRD6eClfXnLJJcm24447AmV5muRdrchdLyUxgXJyk37AZWoaw1yip3al5A2Qb0vyuRKEQL2d+ljsSSIkT/N2pd/z5A6qq+fXSIkjerW+o9cMvfnmm4F6n4f6fcclhrJJKgn1Wnd+f954442Bsi89iYtqonqtUvnOEznJh9dee22yLb300kC55qQ/iwTBjEJEtIIgCIIgCIIgCDpMRLT6BF9ArDTqHvnQjJJmrccTpTaH+uJYjzLcdtttY35Mo8FntRXV89TViqr4OebS5ztTpkwBYLnllks2zYp7dGFGwiMFq6yyCtDaj774WjOnHpHx6M30gCIEuQixJ5lRCm333wMPPACUoyaadfbP+cy+fsf9rEhMLhW5R95l8zTm/RbRyrU/T5mtJCAeOVBUz1Pd33333Q378Zl++c0juB6t7Qdy0Xkfy9RezjnnnI7/9iuvvDLk3zyCpsiNJ43SWOxRnV7iiSeeSNsbbLABAAsssECyqY16e3v22WeBcn9U4pGcCsD7vH9HY6lHy+Sn+eefP9nUr72vK1mG+si0vx0EMwoR0QqCIAiCIAiCIOgw8aIVBEEQBEEQBEHQYUI62CfceuutaVuhfV9A3EpiNZa4DEHyIZcZee2jfqBVHbInn3wSqC82hrq8Ys0110w2l39KAuYyN/ltrrnmGuUR9ycuhZVfWvneUcIGlwC5bGV6ICe5O+SQQwD46le/mmybb745ALPNNluyqWaWJ22Rz1566aVk8yQEkgx50htJgjyZgxbYn3jiicnmMiLRS+NUO7SSOKrvb7nllskm+Z8SDUBeOuhyLE82IrxOUT/gcjZJKV1SecQRR4z5MU3LCSecAJTrx0nq6RLxXpK4SdoIcMABBwAwceLEhs+dccYZaVv3Ih8/lTDEZZaS+btk1aWDGku93+pe7j6aOnUqABMmTEg2yeJdvt0vkuEg6CQR0QqCIAiCIAiCIOgwEdHqE55++um0rXS1HgFQ+ltH6XZ9VmuoFO4jxfen33n44YeT7eKLLwbKM5tKUdsvtJqFO/nkk4H6rB7AWWedBZSjWM6ZZ54JlP2ihAPXXXfdyA+2j5FPANZZZx2gnHSkFRdccEGDzVMjTw/kIkJKonL44Yc3/M2jDEp84ZGSWWaZBRi67IOi5j7jrSiOJ4Xotyh1pzjqqKOAetpwqPvsmmuuafrdSZMmpW2VNnjttdeS7corr+zUYY4Jfg9S1MOTqDTzR66ERjf43e9+B5TVIJ6CvhfxvnfuuecC8NxzzzV8ziNfvi1OOeUUAO64445kU+TbI/8egdLv3HfffQ1/v/DCCxt+w/etseqpp55KtohoBTMiEdEKgiAIgiAIgiDoMPGiFQRBEARBEARB0GEqwwnlViqVl4AnWn5wxmTBoijmHu6XwqdNCZ92nvBp5wmfdp7waecJn3aeEfkUwq9NCJ92h+j/nactnw7rRSsIgiAIgiAIgiBoTUgHgyAIgiAIgiAIOky8aAVBEARBEARBEHSYeNEKgiAIgiAIgiDoMF2ro1UZqGwDnAd8uKgWU9v4/OPAKkW1eHka+9+LavG+YfzusD7fZD97AZcX1eLZ0e6rm1QGKm8Ck6ldy/uBPYtq8UaTz58GXFRUi3MqA5VrgK8U1eL2sTjWfqEyUJkTUBGbDwBvAi8N/v+qRbX4d/aLwZCET8ePykDlG8Bu1Hz+FvBpYBL58XYrYOmiWnwns5+PAP8uqkW+ONx0QrTV8aEyUPkAcDwwEXgNeAE4sKgWDw5jH7MBuxXV4sfdOcr+Ivr+6Mj5r6gWt4xyn9fQ4rlreno264YPbd8foeanj3Vif92imwWLdwWuH/y32sXf6RZ7AVOAnn7RAv5RVIsVACoDlV8BnwGOG99DqlEZqLy9qBZvtv5kb1FUi1cA+fQw4O9Ftfiuf6YyUKkAlaJaNFaQ7QKVgco7imrx39af7E3Cp+NDZaCyBvAxYKWiWvyrMlCZC3jXUJ8vqsUFQEPl58pA5R3AR4C/A9P1w1a01bFn0J/nAacX1WKXQdvywPuBtl+0gNmA/YEZ/kUr+v7oGK7/gkZ62YdjOaZ25UWrMlB5H7A2sD5wIYMvWoNvn4cBLwPLAncAnyiq9dSHlYHKe4BzgXOLavGzafb7VWAnYCbgvKJaZF/gKgOV7wObAM8DuxTV4qXKQGUF4KfAzMAjwD5FtXg1Zwc2BFYBflUZqPwDWKOoFv8YpVvGguuACZWBykLUolbLAlQGKl8B3ldUi8OG+mJloLIrcAhQAS4uqsXXKgOVzwCLFtXiq4Of2YvaTNjnKwOVTwAHUOs0twD7F9XizcpA5e/AScBGwOeovWxPF1QGKotRuxHdCawIbFwZqKwPfI2a3y4oqsUhgzeml4tqMdvg93YBNiqqxX6D24dSm935S1Et1h/8/LHU+sy7gROKavHzykBlo8HP/h1YFPjwWJ7vWBA+7TofpOa3fwFoFrsyUAH4QmWgsiXwTmDHolpMnaaPnwb8k9p1eQZYE3hzsO9/oagW1431yYwn0Va7yvrAf4pq8VMZimpxd2WgUqkMVP4fsDlQAEcW1WLS4DPG+cDs1NrvoUW1OB/4DrBoZaByF/BH3btmUKLvj46h/PctYEvgPdRePD9dVItiMAp1C7W2PBuwb1Etrht8pj0VWB6YOvg9Bvf1E2oR3PcA5wz1TNvHDOXDx4HTqfnR2+B7gROpvR+8EzisqBbnDz7Tngm8d3C/n582uloZqEwETgZ2oPbsn9vPXsB2wPuAtwPrdeWsp6Fba7S2Bi4dDPm/UhmorGx/WxE4EFgaWARYy/72PmovZr/JvGRtAiwOrEpttnHlykBl3cxvvxe4vagWywB/oh5NOwP4WlEtJlCT2g1pL6rFOcDtwMeLarFCP7xkDd6sN6d2DsP97oeAY4ANqPl24qD083fAtvbRnYGzKgOVDw9urzUYTXsT+PjgZ94L3FJUi+WLajHdvGQZSwHfL6rF0tQero6kNrCuCKxVGai0CmFXgQ2LarE8dd9+CnixqBarUht0P1cZqCww+LdVqL3ETs8PWeHT7nE5MH9loPJgZaDy48pAxW8sLxfVYiXgJ8BXhvj+fMCaRbXYjtqE1PcHx8QZ4UErR7TV7qCJ12nZjto9aXlqk3f/rzJQ+SC1l4BtB9vv+sD3BqNiBwOPDLbRGfklC6Lvj5ah/PfDolpMHJzIfg+1iI14x2A/PpD6M+ZngTcG+3AV8OfhbxTVYhVgArBeZaAyoZsnNA4Mtw1+A7hq0IfrU+vv7wVeBDYe/PzOwAn+I5WByprU2ujWRbV4pMl+AFYCdiiqxZi8ZEH3XrR2Bc4a3D5r8P/FrUW1eHpQcnEXsJD97Xzg1KJanJHZ5yaD/90J/JnaDW/xzOfeoqZBBvglsHZloDIrMFtRLf40aD8dWHcoe9tn2Ru8Z3D27nbgSeAXI9jHROCaolq8NBhK/RWwblEtXgIerQxUVq/U1i0sBdxALeK3MnDb4G9vSO2lGWovXb8b1Rn1No8Udd30atQ688tFtfgP8Gtat58bgDMqA5X9qPe/TYC9B315C7XZMLXtm4pq8WRHz6D3CJ92iaJa/J1aX/0UtXVGkwZn9aCmHIDaA+5CQ+zit0Ufyn+7SLTVsWVtahOvbxbV4gVqk6cTqb3kfrsyULkHuAKYl5rMMBgk+v7oaOK/9SsDlVsqA5XJ1Canl7Gv5fy6LrVnUYpqcQ9wj31+p8pA5c/UnmuXoRaAmG4YQRvcBDh4cCy8hlqEfwFqUamfDfr8t5T99GFqkawtbawcaj9Qi3T/pWMn2QYdlw5WBipzUGt8y1UGKgW18FwxKPsD+Jd9/M1pjuEGYLPKQOXXRbWhknIFOLqoFicN85Cm94rMaY2WqAxU/kv5Jfrdo9j/WdTkmlOpyTWLwZnD04tq8fXM5/85nQ/Or7fxmbeotVfh/v8ktQe0jwF/rgxUVhz87P5FtbjSPsegdKid3+t3wqddZLA/XgNcM3ij2nPwTxqLpx2HnRnKV20QbbU73EtN8tMuHwfmBlYuqsV/BqVIo7nPTZdE3x8dGf99mlr0aZWiWjxVqa3h9HbXjl8BqAxUFqYWyZlY1JaxnMZ02IaH2QYrwPZFtXjA9zHo5xeoRbbfRi2iLZ6j5rcVqedUGGo/qzEO7bobEa0dgDOLarFgUS0WKqrF/MBjwDptfPdbwKvAjzJ/uwzYZ1CbTWWgMm9loDJP5nNvoz5g7wZcX1SLvwKvVgYqOobdgT8NZR/c/hvwP20ccy/yAjBPZaAyZ2WgMhPl0HaOW6mFreeqDFTeTi0CKT+cR00K6lHKK4Ed5P/KQGWOykBlwU6fRB9wC7XZrTkHpZu7UGtXb1FrV4tXBipvoyy/XKSoFjcD36TW1uel1rb3H9wHlYHKkoO67hmR8GkHGTxvj/yvADwxwt3185jYDaKtdo6rgJkqA5VPyTAoo3oN2LkyUHl7ZaAyN7XowK3ArNTklv+p1NbJ6f4TbXSQ6PujYwj/6cH95cFn0XYmB66l9ixKZaCyLLUXNYBZqD30/7UyUHk/taUf0xUjaIOXUVs/WBn8/oqD9lmB5wbH1t2pBXDEa8AWwNGVWh6IZvsZF7rxorUrtYdz53eU5YPN+CI1OdyxbiyqxeXUpBk3Db4Vn0O+478OrFoZqEyhFlk7fNC+JzWd5j3ULnYr+2nATysDlbv67aY3KGM5nNoN6Y/UolHNPv8cNW371cDdwB2DC4spqsWr1NLGL1hUi1sHbfdRW6R9+aDf/kht0eMMRVEtnqb2wHQNNRnszUW1uHjwz1+j1tlvBJ62r31/sP1OBq4uqsUUaslDHgLuGmy3P6G7GUF7lvBpx3kfcHploHLfYF9dmlpCopFwIbDt4JjYzsTZdE201c4xqGDZFtioMlB5pDJQuRc4mto9/x5q96WrgIOKavE8NXn7KoO+3IPBe1xRyxh5Q2WgMqVSS6IxIxN9f3QM5b+fUctIfRlwWxv7+QnwvspA5X5qz2V3QC3ZCzXJ4FRq7fyGTp9ADzDcNngENZngPYNjwBGD9h8De1YGKndTW8JSikoNyoo/BvxoMGo11H7GhUrRoNALgiAIgiAIgiAIRkO3kmEEQRAEQRAEQRDMsMSLVhAEQRAEQRAEQYeJF60gCIIgCIIgCIIOEy9aQRAEQRAEQRAEHWZYmY0qlUpHM2fMPPPMDbY33nijkz/R8vdGwzTH+nJRFHMPdx/t+rRTvnr722tZMd98s17qSvvuBd932qejuebN/CE/AswzzzwNn3/nO98JwL/+VS8b97a31ec13vGOWtfzZDQzzTQTAM8991zT4xruOY23T/33c9+VLxy1z7feemvIv2WOsfQvwH/+85+m32l2XM0Yy76fYyTt+r3vfS8Af/lLvVZjzmeO2rb8CPD3v/992L8thjHGjFk7bXZMuX3MMcccaVv91/uxfPnvf/+7wQb1sSHXtueeu37KDz/88JDHN5bj6Tve8Y5CY1MbvzEkzY65U/eesX6mYIQ+hbJfh9sGW51TM1/POeecafsf//gHUG6fs88+e9r+5z9r5Ypefvnlpr83XFodf1EU+QGpBe361Gn2/ON+7HI7avi9TjBe9/6x8FWP0JZPxzWF7Ic//OEG2x133DGmvzcapjnWkdanaItO+ep//qeWEf+1115r2Hcv+L7TPh3NNW/mD/kR4JOf/CQAd911V7J94AMfAOChhx7Kfkc3M38YW3TRRQE48sgjmx7XcM9pvH3qv5/7rh4u/WH1r3/9K1C/0Tvedh29/OpBFuCll14C4JVXXml6jOPt0+Gy9NJLp+12M8euscYaAPzyl79Mtne9611AeeLA+dznPgfU/Qhw7bXXDu9gjWGMMWPWTpsdU24fu+22W9r+73//C5QnVN797lrN0ccee6zBBvWxwV9Y5f/PfOYzybbFFlsMeXxjOZ7ONNNMTX+v3WuqffhDvdpuu/vwdpqbPBnrZwpG0U7dr8Ntg63OadlllwXyPtpjjz3S9uTJk4HyZNeOO+6YtqdOrVWGOeWUUxr2k7uOOUZzvYdLuz51mn3efd/ldtTwe51gvO79Y+GrHqEtn4Z0MAiCIAiCIAiCoMPMUEUR+4WVV155xN/daKON0rZmXl0KMNdccwF1yQDAxhtvDAw9C6HPenRBM2V/+tOfku3nP/85UJ79Hu65+OfHY1Yk95urrLJK2taMnM8KrrXWWgBstdVWDd/9v//7v7TtYXfNIOZkdb/4xS+SLScj1DGOpp0Ml5lnnnm0UZ8hefXVVwE47rjjkk3yNj//RRZZBIBnnnkm2R588MG0vdRSSwHl6MIVV1wBwD333JNs991335DHOt4+beUztcXbb7892XTMHjHdYIMNAFhxxRWT7amnngJgzz33TDa1Z8kKoT5GAGy33XYAvOc99ZrthxxyCAAXXXRRsl1wwQUAPPnkk22fS7+h8znqqKOS7cUXX2z4nPrxYostlmy5sdP7vuROZ5xxRsPvNTsW6H6bfeONNzpyLXOydUU7brrppmRbffXVAbjuuuuSTe3Po9mKxkJd2urRk4MOOgjI+6fX2mYnrqHvIxfJmjBhAgAHHHBAsp144olAOSI1ceLEtK1x5PTTT2/Yd04um4ts9Uut1tyzR6fayXg/13ST6e18ukFEtIIgCIIgCIIgCDrMsCJaPgM73LfYVjM2ndpfbj/tzha1ewzdmkEc7nHutNNOyTZp0qQhP3/ppZem7bXXXnvUv+9suummafvb3/42AMcff3yyfelLXxrxvrtNq7aiv+dm5JZffvm0reiLIoNDcc4556Rtre3YZZddGj7nkZ3vfve7Qx7reM1qN/utkcxuKYLy+OOPJ5uisT/72c+SbcMNN2z4rq9zed/73geUZ3PV3q+66qpkU8SwX3zqNJsd1tofgPXWWw+ABx54INk0RqywwgrJpuifr33x72id0euvv55sSpDh48qSSy4JwPzzz59szdrCeEcZRnOf8GugyLSvtdx+++0B+PGPf5xsn/3sZ9P2WWed1bAftX1XGkwPtIqy7LzzzgAMDAwk249+9CMA1llnnWRT//X9uVLjmGOOAeDggw9OttVWWw2oj7VQj7x0+nlkrGg3yvnxj38cqPdVqCtN9t9//2T70Ic+BMCss86abH7/PvvsswHYbLPNkk1j6jbbbDP8E2iCrsn999/f0f12mnbbzlCfk73V/adTx9Ntmp3PaPaXo1P357Hu3xHRCoIgCIIgCIIg6DDxohUEQRAEQRAEQdBhRp0Mo9Uiv9GE95rJS4YKIebCmJ2WOeY+14lQZLOQc+58tdi3FS5rGQ2XXHJJ2lYNmI997GMNn1tzzTXT9mGHHVb6F5qHmrsVBu90SF4yNajXGPHkAJJieWKGHXbYIW1feOGFQFlOuPDCCwMw33zzNT2WTkkORkunpLaSDnoSFeH1e5RwwROMfOITn2j4jsvgTjrpJCCfJr4V3W6f7Uqxc78pWRTUJVQuvZT8z32x7bbbAmWfKpnD888/n2w+Xkjedu+99yab5IGe/OXMM88EYMEFF0w2yeVuvfXWIc/N6dZ42ilWXXVVoFxHSwlGcrXgvO97+1PiBv+OpFvVajXZlCTm5JNPbnpcY9n3Oz12Sybo0jVJ4v1+oyQr3p59DHbJoLjlllsajqvdxAydlkONBS7l+8pXvgLAXnvtlWyStHodPSUTcomhJ2mZMmUKUE4gpKQaLidUUqxW0tfxlrnl6PQ1Hq/nx27RbiKs3Pm0sg2XTrWfsZauR0QrCIIgCIIgCIKgw3QlvXunZy16+W1/PDjiiCOA9hdlzjvvvE0/d/755wPlFM9eYFMzYG97W/29XAubfUG8Zrg08wvlRfTTHlezYx5r2m2zPvMnNEPt0b0//OEPwNCFYBUR9BlWRWp8JleMRZKX8UKRGE8wIjyN/m9+8xug7u9pUXmB/fbbr+FvKrw5HMZy9rXdGXRFk7xdKWGFz/CraLMnC3n/+98PwMMPP5xsjz76KFBORe6R19tuuw0oJyZ49tlngfIYofTbPqP9rW99CyhHeg888EAgXzKhWzPLndrvvvvuC5Sjf4oSekp8FYT2yPRvf/vbtK2x033lCRuExtHRHP9Y9H35OVeY1ouH63OzzTZbsv3ud78D6qUboF6m4KMf/WiyHXvssUC53MOuu+7a1vG5DzRG+zUcbvrxbkQihju+eyKsK6+8EqiXYgC4+uqrAbj77ruTTffx3//+9w2/6+OJp83XPd33rWQVnuBF3/nb3/7WcAydjmp0gm4mQxnrpGrdVl6MJGlT7nNjcc1H44tutomIaAVBEARBEARBEHSYeNEKgiAIgiAIgiDoMB2VDnZrkVurhWsjCRcONww4lvV1WuELh5shOcrqq6+ebDmZhCQuHvbX4mOoy+V8kfwHP/hBAJ555pmmxyBJkcsOJZsbSzol91huueUabLmEIJIH5WrHQF1m45KN9Y4qL9YAACAASURBVNdfHyjXOcrJL3qFTkto1lhjjbStJA0uR9K2189xXnvttQabZHVDyQ2npRf97Eji5/I/JVVQ7THHEy5IRujSrQUWWAAo1+CS9A1gmWWWadjPCy+8AJSlxlp8f9pppyXbiSeeCNTldVD373DlWqOh3UXarVhqqaUAuP3225Ntgw02aPic+rTLpl2OJV/+9a9/TTbfFqpx1C/4NZVPJbcEuPPOO4FynTYl/HBp79e//nWgLiGEeqIHv0e1Qj7345KM1es/KplRu4yVFDvXVpXc4tRTT002jYuSq0NeirrEEksAcOONNyab+qtLN3XPhvq9yO9J1113HVCXEEM9UdEss8ySbJJw67qPNcMdy3PPeK2e+zpdO6qbUtRO0im5Yjdllp2+l4/mGkVEKwiCIAiCIAiCoMN0JRnGSBhueuNu0uqNdbwXdHp65mZoZjA3e+spXhXxUkRlWjSD637RDPYBBxzQ9Bi0b19Mr1SwOToRJWk3HanT7gyNUgYfc8wxTfenRAFDXSulxj7vvPOSTdEr/duKXk9yIVrNCirqp1TZUE+a8MlPfjLZ1GbnnHPO7O9sueWWQNl/Tz/9NFCOQrRbeb4XUYRp8uTJyaaZe088oBTNHkn+yU9+AtR9C/WkAJdffnmy7bPPPmlbs/2PPPJIsmkGXck1oB6l8QQZwpPjNGMs+36rEgk6FkXuoe5LRVuHQpF/JS4B2HDDDRs+98Mf/jBtt0oPP+0xtlsCpFu0m+DAk4Cobfzv//5vsn3jG98AyhG/o48+GqinI4d6n/c27vcw8aUvfSltK8Lt0R9x2WWXZc9lvGh3tjyXeERJhJQwBOCVV14Byj5ccsklgXJ0atKkSQB84QtfSDZP+KQomLd52RZddNFk23rrrYGy/y+++GJg/CKz3UrgMNp7RC+0t5EymkRmw70O3YjudcL3I7lPRUQrCIIgCIIgCIKgw8SLVhAEQRAEQRAEQYfpGelgMzoVQhyqplGv0alQ5xlnnAGUK8aLOeaYI21LMnj44Ycnm2o6QV1K5JItLaI/++yzk80XvU+LyxWaSQc7ca1HUvehGTnJZCtU0+jPf/5zsrl8UvhC7ZlnnhkoS+hyx9AunQ7BdxI/JtUg8vYlyd/BBx+cbFpwfeutt2b3+c1vfhMo+y+XIKOXadVeVRPP243kqS6/UsIKtSmAvffeGygnBpEUUfWMoF6nD+oL3g877LBkUzINlw6qvtHCCy+cbEpEIhkT1KVf7SYnGS6d7vueJERyzBye9EbJBFyumpMOuszSJZ7in//855C/10t9upmfPaGF2tKKK67Y8Dlvz5/+9KeBen09qLdxT9TgCS283YmcZFCSbU/kovp8js6pGzWzRoOSr/jxq1bWmWeemWxKGnLvvfcmm2peqm4mwPXXXw/Axz/+8WT73Oc+l7aV/MkThqjf+/OCf0dorPJxvduybe//zfbbD/K9XpG4t5Jjt3ssw10eNNpr1Eoe3qnfaYeIaAVBEARBEARBEHSYMYtojfVs0A477JC2lfbU0+0OF5+RVCX2TpyTzxYMdybWF7BvsskmDX+/5JJLGmza93e+852Gv/mM2D/+8Y+0rdnWe+65J9m0SFwpo1uhtNSt6NYMYqf21W6SDc3wn3LKKcm22mqrpW2dp89ka0F8bpH3SOiFGdh2UNTF+6ciCUr/7AwVmZYvPRKQS3M8GroVJWw20+aL04UvOldU+Qc/+EGyKTFIzldKigH1mWhP+e4JB4RHB5QIRunboT4j7vsR3sa1cN+jPd1mNNdKC/+hPsZeeOGFDZ/ziIzGxp133jnZvva1rzV8x8tl5CJ8uWQY/YKSI3jSFvnII6GKwrovdO/xfiyFhfvJE0IoappLk+/3xlzimHbppkKg3X0qfbonWlFqfI86f/GLXwTKEX352JOwCE924SoCRQ2XXnrpZNOY7AlytttuOwBWWWWVZFt88cUbfqdZKn359/777x/yM60YzfNUjrEu6zOaxB3dut+3UgmMpl/kkruIkZQAcQVHToEwmmuoKPJI3iMiohUEQRAEQRAEQdBh4kUrCIIgCIIgCIKgw4xYOjiWC/X8txRiHEp6IonaWmutlWyq47DnnnsO+7ePP/54oLyoV9LBsSQXWm2Fzjv33VxCCl8U7NdQsozf//73ybbrrrsCZTmc9unyDi1i/vznP59sqtkxlgtSOyVJnHXWWdv6XE424Uj26YvohSc1EK2Ov1cWzo4EheI97L/ffvsB5UXfklZq8fe0aKG81y5rlgBnND7tBLmF247+5n1HvvJzVOIVR8luXCKl5Au+P8n6lIAA4LTTTkvbknnpevhv+74lO15qqaWSTf3c5ZtKWjCW0sFWNJO++PmoJpS3SfVfr4MleZS3n9tuuy1tazx+6623ki3X511O129onMydg8uBVYfxu9/9brJJMuRjo9qcS9pdWqi27ckyhEtvdZ1cUrfZZpsB8NJLLyXbeNfKHAodt8v7JOv147/qqquAsuSvWq0C5eQ0Qs85UF5WsMgiiwDw4IMPJpueK/xeuNBCCwHl5y5Jtzot326Xdu+JzT7XKklDu/fWTskXO73vdmglxxzu80XueNuVCZ5wwglpWwnZAK677jqgLGdVcqxW/tGYkGunkuoC7LTTTgCcddZZbR2rExGtIAiCIAiCIAiCDtPT6d1zb6K5GWqP2GgGR+mNoR5dOPTQQ5NNszo+i/7EE08A5XSkW2yxBVBPN+3H1c3I3bTMN998DbZWUS4tyvbZAi1W9UXemsHyhax+brnZ6qOOOgqA/fffP9mUztWTObQ7KzseUZeRzATlEhPkyM16+OJ2LdDOpRb2Npkj1/56MYVtu7+vmU+f4f/e974HwJe//OVkU+KVO++8M9k81btms33WezQJBcZyVrvZ4mZf+K5Z/Fw6cP9cLsmAxs5f/OIXySZfeRTa9/OZz3wGKM/2yacecdBY84lPfCLZnn/+eQB+9KMfJdt666035Hl2i9zsa7vX1JP43HDDDUA5+pSbBfVkD8Ij/4putSo3kot290vJhokTJwL58d+jTirt0C7eTq+55pq0rdIiuaQirZLj6O+t0kF3cxxo97rq76effnqy3XfffUA9+gQw++yzA/V+6TYfEzWb71Hxb3zjG2lbzz0+Nut5yhOdKIK+0korJZuib4qutTqnbtHNa9jNNjHctOmtjmU8kovl1GhOLpKV2/dll13WsI9PfepTaXu33XYDytFaRbRySeGc3Jiw++67A+WxSqo2fw5uVqrIiYhWEARBEARBEARBh4kXrSAIgiAIgiAIgg4zLOlgq8Xbww2jtvt5Dxfmwnw77rhj2lZYXItjoR7y8wXfqgXjNi1ydomhFu76Yudukwt1ezhfNoVTh0JSK8n8oL5wdqONNko21ba55ZZbks0lbVoIqdpQUK88v8IKKySbFuO6JMYlB9PSLclAq0rmown3S9an2mxQb3PbbLNNsl199dUN373pppvS9pprrgnk5UO5RdkjoZP+7aZPJZHKyX5cWpCr2eayIEm6vM5FbrzoFdlVuzVfvG7TZz/7WaBeVwjqiQJ84a76nY9bOSmaklz45y644IK0rX4u2RHUfe59W8fjY7VqGvmx+hgzHgx34bsnQZLM0ttk7r7giQWEf0d+c/mnbN4H1HZH0l671cbblSnp/ptrcy6t9HYl5FNPtqL9+P7WXnvttC3/5iS1yy67bNr2WlMjpVu1HodiueWWS9u77LILUL4/65y9LarPqf9CvT+69FXbbnPpda4+mdqlt2m120svvTTZVAvxoYceSjZJscar5tNwkzn4eHbggQcCsOCCCybblClTAPjkJz+ZbL/85S8BePbZZ5PN/ZerDanfaTcpRLv327FY3pI79pxtuDLBXIIW+RvK10HPUZLRAmy88cZAOfHSpEmTgHJiN7VdT+Si/fnzg5JwPfPMMw3H3IqIaAVBEARBEARBEHSYUYdpRpL+st1q0HqrzM2K+aJqT3yh2VZfxKbZtSOOOKJh3z4rq5lwn1XUTI+nU1bkayxmtrTfb33rWw1/axYtgnqSAU/g8NWvfhUoz7CI66+/Pm37gnhFsuaee+5k08JwR+k2fYFgq2McDzqd5EAziT5bn0vC8Pjjj6dtfdb7gI7HZyH7heH6NNd3vK1oltZnWj16JTxaIl/655SQYTR0azF1TiGQG0d8ofrPf/5zAHbeeedkU7/zSNQaa6wB5GedHS2q/9znPpdsPt6qbfv4p+vkfp46dSpQHne1H0+IkEu/PZYJHobbTn1GU/cH96kSBXnSgUcffbRhP/57ihK4mkKz5U6rpDi9jEoE5PqsR16b9c9c281FrPzvuQijJ2dqxlhHqtrFywmoH+61117JpoQVHq1bf/31gXJZAY2l3qb1jOD3c1dUSO1y8803J5uet/x+p3HJFS76u6fSl6JmLND9oN2kap6uXiUwFl100WRTf/Sxd2BgAIA///nPyabx2MdUHxO22moroO5byEd7Vl99dSA/brfLWLRpRYz8t3Lns8466wBw0kknJduxxx4LlKN/Ull4X1cyOE/Y5px77rlA+RpedNFFQPlZd8KECUA9yR3UlTJK/ARw3HHHAWUV0qqrrgqUVQ7tEhGtIAiCIAiCIAiCDhMvWkEQBEEQBEEQBB1mxNLBZtKLnBwqRy686CHdnGRw1113BcoL3LyujqQDs802W7JJqvHiiy8mm+p3uNRAv+35+RUSd2mH6kjcddddQ5xZ+7RKMCJctpdDIU6vpaFQt9cAk09dkiVcjqmwK9QXJbtEsxkudcpVoZ8e8LYrX3pV8hx+HRQW90Qu/cxwJXW5Nu/yNI0hkmZBXl7lC+Yl7XI5YTPalVWMhfyi2cLtAw44INkkw/F+JV89+OCDySZf5hKIeNuV1MLlfS7hlMzI5UY/+9nPgLK07SMf+QhQTkKksdNltC7t6AatkrYMF5edeZIAIYmRL4ZvJU+UXM79rHuTX9ehZHL9gNqfy8aE38ty0kKRk3f5/TonNT7//POTTf7/wQ9+kGwnnHBCy2MfT3Jtxhf4/7//9/8AuPzyy5NN7WmHHXZINsml/FkmJ/mVpM1lbJ58R+OrJ8+SjMvHDI0pXrOomUzY6daYqjaRW76Qe7b84he/mLb1LOSSQPlcsliAj370o0D5HCSH87HXn50kc3vssccavqMEIjA6yWC3aHat/G+SV/pzuBK5fOhDH0q2I488EijLY5Usx58jNRZ42/WxQPcYv1eqr/z2t79NNsnrl1xyyWSTPPSQQw5JtiuvvBIoyw532mknoFy7s136dyQPgiAIgiAIgiDoUbqSszwXqfIoVy7Jhb6Tm2nw2VQtsPTFc1//+tcbfsdnU6rVKlBexKbf0WJQgDPOOAOArbfeOtl8plJsuummQGciWu1y9tlnp20tdPc3ftk0MwJw0EEHAeVU5KLVbKnPFujatEpxr9kdTzqSQ9ffF86OZXX40XwnNyOn5B+eejTHxRdfnLZ1bc4555xk04ykz0JqFj2XkKHVOfVykoEc3hc1G+jtdI455mj4jqdy1yx6s1ny0dJJn7aKvqy22mpAOWqnvqNoEcCee+7Z8N1coiFFoPbZZ59kU5v0Wd9cSt7c7KpHHHLR3Fzaac1c+tiVi7p1knavVa6PeWIaJSA45ZRTkk0JhM4777yG7/o1cJ9qJtuv4csvvwzAww8/nGyKHIyEbvf9Vgli2k1TLf96G1ZU1Ntc7vkg96zg5PqAEkO5ukW0O953ilapyIUUNABLLLEEUD73hRdeGCiXe1HfzCWn8YjiMsssA5TvxVr0D/DHP/4RKI9BSuHuiSIUdfMol45bCQgA7rnnnobz61ZbbdU+hBKGTJw4seGYWqFkQo7Siuu6QDlaooiIP48efPDBQDniryRkft+TmsATN+hae3vXGHXNNde0dR7NmGmmmdK1VP/xhCnqr1/+8peTTWO+p7LfbbfdgPLYL5/7/Udjgj/36xylRINy9E/79FIISuXuqhg9LzzwwAPJpjHcj1VlJ7xkj9QN6jNQfn5rRkS0giAIgiAIgiAIOky8aAVBEARBEARBEHSYYUkHXeoymjBvs7CsL5TbbrvtgLqkD+pVxv/3f/832Tyxw5xzzgnkF2rm6pJ4eFnyBV+Q/P3vfx8oh+APPfTQIY+/Wyi07Pj5KMyaqzruEgyFdNuVdvhnc4uTndwiwdzvSFI0lpK2Vn9r1iZbyQgUsvfFrTkkBYN6m3VJhnA5XO74m1W371bihnaTtoym5pSfd0525nIFofEA6n3UfaoFrL/61a+GdSxjQSvpkGQSLgn56U9/CpT7oo91QtKRbbfdNtnU5lyqJ7mm17dxaZH27eOkro3bJOV2mYZwKafGA5d9uFyuk3Si/btvJZGR7Bdg8uTJAKy99trJpqQ33nZ9DL733nuBsrRIchmX0OTG8hzdlLe1Q87PzaTp/nndw7zv617mvs+Nkzl5u+PPEkJyzJx00BkLn7Z6ntIxuHRQiT2eeeaZZNOzkMtXlYTE65RpHPH+L8mVJ3jw/qo26ssPcseqOp+qIaXzg3Lb73QNy2ZssMEGQFmSrm1vL8cff3zDd9dcc02gvGRD/d/rY2kc9oRs8oUnZfJERerrfu86+eSTgXKdKEnUfD9KFOFJX9QPvM+pzay44orJpmfZ4TLPPPPw2c9+FqjXU8vVCXXJqZJIfO9730s2JaDQcz3U/edjoe57Lp3WdcjVx4W6D2688cZk073PpYpqf+5nJTTy+5mksN5O9PeR3K8iohUEQRAEQRAEQdBh4kUrCIIgCIIgCIKgwww766BCfaPJFCNpykILLZRsCit+8IMfTLYf/vCHQDmUrawsygoCZemgMo+5BEPhbP+cQuse1tZ3PASrrG8u1VHo17OPdFsG5/UIckgOkMti5tlbJMHYbLPN2v5tSQ48jHrVVVcB9fC8/91lAV7vQ+j6e+bIXqGZVG8o1G5anY9fB5GTY7YK8edkF81sYyHRbJdmx+JSIGVacptngBNeY2beeecFypmbPLOTaNd/440yAs4yyyzJJsmGn+NTTz0FlOvgSWLh4+AvfvELALbffvtkkxzCZRguSdb3c2OI+1bZBF2Spe96G9fYquxVUJdijEW9smbkfl/SQKhLYzzTmHzgEi2Rq98D9RqFXvNF10vSIGheg7AX22srdB/xY5cv/R6vtpTLEjxUnc2cVFHyOpd/SVLl9ZGES5+07262w1ZybP1N9YCgfj/1THSf/vSngXImNdWz8mcU+dXbpaR0ymYI5WcNLcW49tprk21gYAAoSzuffPJJoFwvaosttgDqdaNaoXZx//33t/X5VmhMczmj5Gjug8MPPxwoPxNJ1rf66qsnm87XswfrfFWPDOrPlsoa2A46d68P69vTsv7666ftq6++uuV+R8ODDz6YMinqec99qmdxl/fqOd4l4t/+9reBcm0qSQZd2q8Mtssuu2yy6Ttey/Duu+9O28r87P1C98Mf/ehHyaY+lcsWufnmmzfYXHaq3xgJEdEKgiAIgiAIgiDoMMOOaDWrTaBZJV98plkUr7qtt1ifOVVk6bjjjks2zdR4JEqJMfw4fCG3Znx9Jlxv1T7rqBnhX/7yl8m24447Nhz/IossAtRrAPj+NNvTTTQjkYt8+GyF6ovpeB2PROkaqRYG5KNbuRowfgy5xZCqM+Dkjvsb3/gGUK5Hk2MsZ7Wb/VarWSGdo88K+uJYkatFlOtPBx54YNref//92zqGbtPpRDi5fXh/UiIAn2WaOnVqw3d8UavarM8kDhVVaIexXLjdDB97DjvsMKDc1jRzp4XKkE8eoHbqf1Pf9v7ss3iaFfZ+rNqCV1xxRbJpFtojQIpIeFKH/fbbDyjXlRkP2q1L57Vh9t57b6DcZxVt9AXSUmrk6jhB3deKAkD9OnhkxiOZ0x5rr5NLTpE79hNPPBGAfffdN9nkXx8vW9XXbNbPPdGGlDM5csmccoxV5FW/c9NNNyWb6lr5WHnkkUcC9UgK1KMM/uykPuzXRrXc/LnhqKOOStu5pEQaPzyiJUWNt1mNBSuttFKyPfHEE0A5wUO3UFTPaXa9PELSLrpGXr9pOJGskdIsiuV0on0WRZGutT83TotHfHTf8CQXUur4PV1JR1RH0NG9AlqPe2rv3rY1XvvzrSJtPp5o7PBxQmO3v6PssssuAJx11llNjyVHRLSCIAiCIAiCIAg6TLxoBUEQBEEQBEEQdJhhSwfFRhttBJQXsSqUL2kY1MPVHqrT53xxu+R6vnjuggsuAOALX/hCsuUSVrjUT5JADwMqrL3zzjsnWy70qloGe+21V7JpQbL/nhJu5JIbDBeXZIlcuNdD9wrR+uJ31WlYd911G/bj3xUjSYbhPsid+yabbAKUazzk5JV+vcaTXDi6VTKM2267DYCJEycmm6RAyy+/fLLlpIM51JYcl3G1e4xjKSlqJrUazXF4e/74xz8OlGUGX//61xu+M2XKlLT9kY98BCDV/ID6Ymb17aEYb5/mfl+yH5dFSYLtn//Od74DlBNMKLmCSyk0Dnib23333YFyf/7973/fsB/v+5J0ubRDtaN8IbtkIV77JFfzZywk2NPSKiFK7nrovCXnhbqv5EeA6667Dmh9f/B7neSGPjb6wu9mx9Xtdpq7Rzm5Y8rJJiXvyX1eiVqgvmQgVysudy+DvLRQv+NJRYb6/nAY60QtOUnjhAkT0raSfnh70rOV1xKTlNclmfPPPz9QTkzmiQ5UF8+TtEg+5kl19Ntex0i/s+CCCyabnrvGK/FNs/tpN/tRu+fY7jGMd4IrTzqhPuX3b8lYTzrppGRTvSoluYO8ZDCHpPIu5fP7isYbH3N/8pOflL4LsM466wDwta99renv7bHHHkB96RPAr3/967aONUdEtIIgCIIgCIIgCDrMsKZ3ZplllhS10AzSoosumv6u9NZeDVpvmlqYBvXZUZ8l1QyMUoIC/PSnPwXKSSw0S6JFnFCeEdVCTZ/d+eY3v9lwLlqUmUsL69W07733XqCeOhrqEbJW1eU7iUcOc7N3mvX22SMtysydYys23XTTtK2Usj6znjsGtQW/Xn4dhM9KdJtc9KXdWaPcdz/xiU8A5VS6apO+6Pe0005ruu9cumKhdj/t7/QDrWbamvnefaE0zJ5kwPuA8NlZRbNXW221ZPNrMtxjHUtybU3H7qnXlQzI/agkPh7F13fdf7mkNrlIgW/rsx5l1faPf/zjZNMMu8++KyLjiZC0QN2TmDz22GN0g2aR15Fce0WbPJmI2qSnBldEqxV+XXW9fLwcy3FyNMjPHlG95557Gj6n88mNAZ7qXu3Uo3u5si2Orok/PygNt6eTVgRnNHQqGtMqwZBsnuZ72223Bcp96rLLLgPKKeulvPCkEzp3HyeUkMWfEfxaaCzwSIFSn3ukQCVbPKnJDTfcAJSjB1IW9OLYO1a/0YkI2niXwsglPnv88cfTtkebhMoG+LPjoYceCpRVFmqzfm9XdErPX1COVP/mN78Z8lhfeumltO0JXKbFE8co4YUnotI44veuZin4nYhoBUEQBEEQBEEQdJh40QqCIAiCIAiCIOgww5IOvv7660kaojCbJwBYa621Gr6zzz77AGU5ocKOHn7U4jlPfDHXXHMB5UrcCul5/Suv3eASxWnRgm2oywM9ZCnJghbt+uckS4K6bNEr13cbD93n5GaSTnjtiFwNnGa0qq3lsg3t08PW22yzDVCXfUE9bOuV5d2/40EudN+uvEhJRxxdm+FISSWVzS0aH6r+TjPGO5lDu0k7muHnLelBrl6b4/1XMhfvq7l6Uu0yHj71/aueleSCUJfn+tijMfPoo49ONo2nOQmH+1n+cym271syaZdcSCLmyTCUlMRlm1pQfPbZZyeb+orLi8dD+tKq7+eus6RQG2+8cbKpfcpPw8GlNhoT/dq0K/kebxlW7vc9CYOoVqtD7sPvLWojfs/Tdqt7me9H11AL4KGesEkJN8aTN954o636jQcddFCyKfmKyyo33HBDoCzB1bjncmuNCbkEBN4WJUWG+vOWy0KVoMivj54HfRy5/vrrgXI7fvTRR4c8z063404nuWg2TrSqy+fH0C+18IaLy9RzqN7bSM5f46wnzWmX008/PW3rt3Pjv9dCE14XUt/J1QhsRUS0giAIgiAIgiAIOsywIlp/+9vfuPLKK0s2n8XXLItX2FZUas8990w2LZz0SNSvfvUrALbaaqtkU8TLZ6lOPfVUAKZOnZpsXtV87bXXBvIL552PfexjQDmVqWZ6LrroomRT5MGrQevtOhfdGC6tZrWELyD0RdRiqaWWAspRQh2nL24fajExDC+SkptZVIpYXwg933zzAeVZgNFEGUZKNxeeyr9+XdQmczN4UF/omUs37OmjNRvT6fSwnaDTv5VrI75wO4cvmFUfcZ965GSkjHea91xigRyemOjVV18FytEp9W/NbEN9fPbEC96O5Uv3qfx81FFHJZuiaZ5G30sgjCedun5KS+wRLY2nWugNrfu+8ChYruSFrmG7dCKqnCN3j2rl09x9RvdaT9AgPDKtCIhHY2XzMcLvQbLn7o0jiTY2Y6wjiP58o8iRn7sSJimyBXWlkaflV5TRE7dIxfKHP/wh2VQuAuDYY48F4JRTTkm2FVZYASin+P7jH/8IlJ8/lITMkwzkGI+IbKd+s10lzEiScY13pFq0W4Ko0z4dq3T7Y3F/j4hWEARBEARBEARBh4kXrSAIgiAIgiAIgg4zLOlgqwrxCtG7hEW1VrzmisiFGpsls4B8mO+uu+5q+p0cAwMDw/5OO8fSCXL79cXokgC5/xTG1wJ6/05OxuFSAS1udXmiJ8aQLMOlhdr2GiU67pyk0iUfzerDjEW4vN1Fre0iGYfLX1rJh1TjTHLL3P5yxzfUMXY7/O3yodFIlJp9TnWXoO5Lo0YstQAAEuNJREFUt+XI9Qv3n0sLh8t4LFpu9ZvN/OdSHkl4XKb7wgsvAOX+p++4jNt9qrHD27YkdEcccUSyaZ9eR6vdGnad7PPtttPR+Dk3lrk8StKsVtJB93NOTu2LuJvR7Xbaqt5TjpxcTFJA1WGCugzzhBNOSDb5d8stt0w2JV4ZyieemGFaWsmPc4yFvKvdOlpeM0tJKbT8Auq1fLyO1i233AKUpYOS/B1//PHJpuukRC9QrhOk5AMuHf7kJz8JlOuXSha67LLLJtuvf/1rAL70pS81nFsv0a1kHNMzoxk/W90P2rW1u+/xThQGEdEKgiAIguD/t3fuQXZUdR7/fCUuYHgWz6gsYhLkVTFBQngoATY8lochLo/UohgCywKKhSusUJTe7awVoXBBQJQFRETZKAQoAgETAwyBQEJ45DGQLLVIACEhhAV20Q2F4ewffU7PuTM9d+6d2/cxM79PVSo9vz59+vTv/rr79Pn9zu8YhmEYhVOTRyuPVk3Sb/ZktlYTj8yHUf6JEydmspDi+brrrstkjzzyCFDuqcojTGSNR63yEmPEnoJQ55FHHpnJQvr8OJlIGP2K29DX5Nh66c/k7UrEugj1xCuCh+uJy4WkLAsWLMits9Io6xVXXJFtv/rqq2XnbQfqmaxaaZQp9rQEW+wrnXM80T14X+Jjwr3S1yhZO49m9pWkJoxyX3/99ZnsmGOOAco93Oeddx5QbpMh3XW89MWuu+6abYckBHGSgaDTa665JpONGDECKE+lPXv27IrtDjTKy1WEBzaP+fPnZ9vB1mLv1OTJk4HyBEp5xLYb9Bdz7rnnAnDvvfdmsoEy+p73zgn3d1jyA7rePbvvvnsmC/YV21xIghV7/uL3VYjQOPnkk3ucN/aKd3R0VH8RbUKc0CYklxo1alQme+KJJwB45ZVXMllY4iLW0Zw5c4DyVO0hGihOxx8vsbPHHnuUlYuJf4tgv3Gik+DlmjdvXiYLz5O8NPytimbp3o5Gt6XaNtSjl3Z+TjSyL5P3G7ZD38k8WoZhGIZhGIZhGAVjH1qGYRiGYRiGYRgFU1PoYN5E42rdrdWG+vUV5lFP/v5qJ9m1Y1hiHFYVwjIWL16cyYIbPw5XGT16NAAvvfRSJotXae9ObyFKQR67+0OIRqyrUC5v5fk4lCQOE2k0tf5+1ZaPw3lCmFYc3vn2229XPD6EdOStMh7WP6u3je1Cte2NQ3xCOGalSe5QvtZQsLE4cUMcEldNG9sp1KLa0Ic999wTKF8f69ZbbwXgrLPOymQhlPjYY4/NZGGdwBBqBOX6C/d0HMYVfps4XC5sx2GH1V5To3RexNp5eeHSDzzwQCY7+OCDgXLbDeFdfdUdJxKKdR4IiUrqmRzeKiqtYxmHXQfiZ154R8XJFk4//XQAbr755kw2fPjwHvXE4WzBZuMkESHpy7Rp0zJZuFfyaORE+rz+VF7fY+XKlZls++23B+DJJ5/MZOHei0MMw7soXt9twoQJQPlaVyHEPdblmjVrsu2DDjoI6AohhK5EWXEip3DuWBYSbEydOjWTTZo0Cch/P4brXbVqVY999dAOz/T+JI+op93tcM3dqSfBTNH99Gava2YeLcMwDMMwDMMwjIIpNL17taPCtY4S1ZNKspZ2VXu+as9bJGHCK3SNHsWjhiGl+tVXX93j2EaMfobV4/N0cMopp2TbYcQ8HhFfunRp4e2phVr1EY9qBw9LnB4/pHOOR6XzUurHdHZ2AuXpcAOlUinbDul1Y1qVgKbIc+V5NGKdhgnbfekx2Bd0eQhiW4sniHen6OdU0VR7ruAhjpPMhCQ1sacgPCPGjBmTyR577LEe9cVegeDFiRM3BI91XC7Yfux5P+SQQ3q0IXjIYk9uM72Jtf5+cbr6PMKE/9gjGJIOxHpesWJFth2uc/z48ZkspD6Pib217UZfv1Wepz4QJ0mp9HvEXptAnAQi9opUWlok9qAdf/zxQHkSpzyPVrXROfWQ15/K00dIiARdSwbEKdjDuyROhhPeIfH9uNtuuwHldhXebfGzI04nH1Lxx8s/BO9XqA+6vJCxl3uXXXYByp/RsTetO63ywlSKHGh2wqS+3jm1vvtbpdOi+9D9eVfXc2zR+jOPlmEYhmEYhmEYRsHYh5ZhGIZhGIZhGEbB1L2O1kCi3ScQV2pfHMJy4oknAuVu+rlz5zauYTVy5513ZtthVfg4NGHmzJlA/oTEdlzbKE7kkRdmEMLTwsR46ArZCOFTUB7+GUI28kKGdtxxxx6ydgwXjKl1zYq83z4OhQ2TtGO77+scQefxxO5qk2FUS6ttMoQMxaFZwf4uvvjiTBbsLp4Mv3r1agBOOumkTBbWvZkyZUomi+/fcL6QmAFg+vTpAJx22mmZLIQT3nTTTZksL6lLpZCyVt/7/QljOfTQQ4GuZzJ0hReHNcqgPHQwECcvyHsOhNCrVoew5q1LmEccPhls8dJLL81ks2bNKr5xNRKeMS+//HKLW1I9cTKMO+64AygPiQ7JWW677bZMFkJ9Q3noCieMw/dGjhwJlPcl4nDDsB0nuArv8riesB2HywZ7iJ8dlWhUMoxqz1utrN53ca3JHlr9zhmKFK1z82gZhmEYhmEYhmEUTL/TuxdNq1bibjXxhNhKI/avv/56th3S1VZKoRvTW9r2ZhA8bfFo55IlS3qUa9Qq3kX/9nntCymHJ06cmMnuuusuoNyLFRNGsMOoNXR5HPISFFRLM2296KUW4hHZvLTDlVIgQ35q8Xg0uN2o9t6PyfMIhdTiM2bM6LEvJGsAePzxx3vIFi5cCMA+++yTyeJlI4ItnnnmmZls7dq1AJx66qmZLE6W0V+Ktt1m3AvXXnstAOvWrctkIbV2fG/HhN84TjAQmDx5cra9YMGCXs/bju+0OOlB8JTGdHR09Hps/I6q5PWsl/Bcjj04lWi1lxXKl7i4++67gXwPaUiKAbBs2bIe+2+55RYAXnvttUwWEtrE/Ys4Oiaka49TvgdGjBjRQxbraNy4cUB5ev1G/rb9pR36tO387Gtkv3+oYB4twzAMwzAMwzCMgrEPLcMwDMMwDMMwjIJRLa5cSW8BvS9MM7TZ3Tm3U60HmU4rYjotHtNp8ZhOi8d0Wjym0+Lpl07B9FoB02ljsPu/eKrSaU0fWoZhGIZhGIZhGEbfWOigYRiGYRiGYRhGwdiHlmEYhmEYhmEYRsHYh5ZhGIZhGIZhGEbBNPdDS7oM6XmkFUjLkCYUWPfhSPcXVt9gIk/v0hqkHXPKfhnpkl7qORzpkEY3t9Uo0Q5KtMz/W6dEr0d//1Wr2zeokDZ5m3weaTnSd5BsAChG2sHraBnSOqTXo78r22Ol56J0M9I+vey7EOkT3WSXIJ2OdFKvxw1mzFYrY3bafki7Iv0G6SWkZ5AeQNqzxjq2Qzq/QS1sL6yP2ngaoWOpA+mAuss0iJoWLK4L6WDgBGB/nPvAd/Lbo9MqDcO5v/RdcABSq96dmwPMyalnGHA48D6QvwrvIMGV3NvAWAAl+hfgfVdyP4rLKJEAuZL7qBltUqJhrjQobfT/cG4sANLOwH8A2wClslKD+R7tC9dljyi1R1y5Pfaz3rNz5dJmwIXAr4E/R3uOAU4FrgTuB16ouw0DC7PVSpidthfpKtD3AL/Euale9nlgF+DFGmraDjgf+GnRTWwrrI/aeNpZxw2kmaNxI4ANOPcBAM5twLk3vGclQXoWaSXSXgBIw5FuQXoK6TmkyV7+GaTHfPlncz0s0nh/zMgK9UxDmoP0MPBQMxTQIvL1nnJBjt6nIf3Eb9+KdAPSEuAO4Fzg234U4kvNvpBWo0SjlOgFJbodeB4YoURfVaKVStSpRDN9uWFK9G503FQlujna7lSi5Ur0SFT+KiV6SolWKNHZXj5JiTqU6H5gZdMvuNk4tx44B/gmknLvUelipKV+NCzxsuFIc72XoRPpNC+/HOkFX7b+Dl+7I02MPAjPIW3t92yFNBtpNdLtvgNWPsInvY/0b0jLgcuATwKPoNRGkbYhfSGOBr4MXOnPMxJpLNJir+d7kLaP6r/Gl+tEOrB5ymgwZqv9x+y0WRwBfIhzN2QS55YDjyNd6a91ZWSDWyE9FPUJJvujLgdGev1c2eyLaCLWR208ven4+/5Z2Yl0Y7d7/wqvmxcJ/U5pS1JP7Sqke4AtszNIP0N6mtRrljT7AvNonkcL5gPfR3oRWAD8Fuce9fs24Nz+pO7pi4CzSR+iD+PcdKTtgKeQFgDrgaNwbiPSaGAW0OUOTI36OmAyzr2KNLOXegD2B8bg3H83+uJbSK16786ngUNwbhNFjlIOXPYCznAl97QSfRr4Aan9vQcsUKITgN9VOL4EHO5K7k0l2s7LzgHWu5I7UIk2BxYr0Xy/7wBgH1dyrzbkatoN5/5AOlK9s5d03aPS0aQdqAMBAXOQDgN2At7AueMBkLZF2gGYAuyFc87f+4Odi4Bv4NwipK2AjV4+DtgXeANYBBwKPN7t2OHAEpz7DgDSdOAInNvg908CHsK5J5DmAPfj3GxfdgVwAc49ijSD1MYv9Md9AufG+t/pFmC/oi+6ZZit9hez0+awH/BMjvwrpJ7HzwM7AkuRFgJvAVNw7n9IPQ2LvQ4vAfbLvLmDF+ujNp7edPwTnJsBgPQrUq/Xff6YYTh3INJxpPfsJOA84M84tzfSGODZ6ByX+WfwZsBDSGNwbkVTrq4XmufRcu594Aukncq3gN8iTfN77/b/PwN8xm8fDVyCtAzoALYA/hr4OHAT0krgTiCOwd4buBE4EZd1THurB+D3g8iA86ld7925E+c2NbKJA4yXXMk97bcnAA+7ktvgSu5D0lCiw/o4fhFwm/dahfvvaOBMJVoGLCEN1Rjt9z05ZD6y8onv0aP9v+dIH6x7keppJXCUH/n6Es69R/rhuxH4OdJXKA8tGqwsAq5C+hawXRRq8hTO/RHnPgKWkX+vbwLuqlD3scCDPaTStv5coUPyS8rvgVkAOLcQ2GaQf0SYrVaH2Wlr+SIwC+c24dybwKPAeNIBgZn+g3QB8CnSMMOhgfVRG0/vOj4CaYnX2ZGkAy6BPN0fRhoyjP+Iij+kTkV6lvTZuy/l+m8JzfRo4TvsHUCHV+jX/Z4P/P+bojYJ+Duc+8+yOlKvypukozEfo2s0DGAtqZGOIx0Vq1TPBOBPdV7RwKA2vXdnaOioeqrRx0ekdhfYItr+B9IPtBOAZ5VonC97viu5svAAJZpU5fkGD9JnSe1xvZfE1y/ghzj37znH7Q8cB/wA6SGcm0EaAvQ3wMnAN0kf4IMH6Ruk9gRwHM5djjSXVA+LkI7x+z6IjurtXt/Yx4DKgaSjiLXi+vh74GK2Wh1mp63ieVJ7qpbTST2uX8C5D5HWUP7uGvxYH7Xx9NTxPwJjgANw7jWvv9juqumnpkh7kHocx+PcO0i30gY23DyPlvQ570YNjAVeqXDEPNI5RCFWc5yXbwus9aNeXwM2i455Fzge+CHS4X3UMzSoXe+V+F9g6z5LDR2WAEf4LIXDgKnAoz5BxjtKNFqJPkYaFhT4rCu5xcD3gHdIRw3nAef7OlCizynRlgw1pJ2AG0jDCPI6OvOA6T7cCKRPIe2M9EnSMIJfk06A39+X2RbnHgC+TfrSG1w4dz3OjfX/3kAaiXMrce4KYCmpF6W/dN3r0r7A6qiD27Uv9ci8Q9ecza+RjpAHwvyPLwLv+fIDH7PV6jE7bRUPA5sjnZNJ0jCrd4HTkDbzdnwY8BRp32q9/8g6AtjdHzU03vvWR208+ToOH5gb/LOwmsGBhcDf+zr3I/1QgzQ50Z+A95B2Af62iGbXSzM9WlsB13mX/F+A/yJ1H57QS/l/BX4MrCBNofuyL/tT4C6kM0jnwpR/8Tv3JtIJwIM+fru3eoYKteq9EvcBs0kna16Ac48V18yBhyu5PyrR90hHZwTc50purt/9XdIH6HpSl/fmXn61Eu3hy893JdepRKtIQwWWKRH+mMkMDbb0IRMfJ7XPXwFX5ZZ0bj7S3sCTpO+k94GvAqNIJ71/BHxIOqK9NXAv0hakuv6nBl9HO3Ch7yB9RDqa/SBwcD/ruhH4HdIbwFzK5x3+hjQ05lukL8WvAzeQptn+A3BmVHYj0nOkv+/0fralXTBbLQaz02aQzvebAvwY6buknpU1pPPStgKWk3ru/hnn1iHdDtznvQxPA6t9PW8jLULqBB7EuYubfzFNwfqojac3Hb8LdALrSAdf+uJnwC+QVgGrCHMRnVvu7+PVwGukYcotR/mDcYZhGIYBSL8HzsC5tTUe1wFchMvmNBpG4zA7NQyjDWnuHC3DMAxjYOHcUa1ugmH0idmpYRhtiHm0DMMwDMMwDMMwCqaZCxYbhmEYhmEYhmEMCexDyzAMwzAMwzAMo2DsQ8swDMMwDMMwDKNg7EPLMAzDMAzDMAyjYOxDyzAMwzAMwzAMo2D+H4JH3iXyxG6HAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "x_orig = ((x_original ) * 255).astype('int')[:, :, :, 0]\n", + "x_adv = ((x_adv_samples) * 255).astype('int')[:, :, :, 0]\n", + "\n", + "y_pred_orig = model.predict(x_original, verbose=0)\n", + "y_pred_adv = model.predict(x_adv_samples, verbose=0)\n", + "\n", + "fig = plt.figure(figsize=(15, 3))\n", + "cols = 10\n", + "rows = 2\n", + "images = list(x_orig[:cols]) + list(x_adv[:cols])\n", + "preds = list(y_pred_orig[:cols]) + list(y_pred_adv[:cols])\n", + "labels = list(y[:cols]) + list(y[:cols])\n", + "\n", + "for i in range(0, len(images)):\n", + " ax = fig.add_subplot(rows, cols, i+1)\n", + " y_pred = np.argmax(preds[i])\n", + " y_orig = np.argmax(labels[i])\n", + " ax.set_xlabel(get_label(y_pred),\n", + " color = \"green\" if y_pred == y_orig else \"red\")\n", + " ax.tick_params(axis='both', which='both',\n", + " bottom=False, top=False,\n", + " right=False, left=False,\n", + " labelbottom=False, labelleft=False)\n", + " plt.imshow(images[i], cmap='gray')\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5. Summary and Next Steps \n", + "\n", + "This notebook only looked at one adversarial robustness technique (FGM). The *ART* library contains many more attacks, metrics and defenses to help you understand and improve your model's robustness. You can use this notebook as a template to experiment with all aspects of *ART*. Find more state-of-the-art methods for attacking and defending classifiers here:\n", + "\n", + "https://github.com/IBM/adversarial-robustness-toolbox" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Acknowledgements\n", + "\n", + "Special thanks to [Anupama-Murthi](https://github.ibm.com/Anupama-Murthi) and [Vijay Arya](https://github.ibm.com/vijay-arya) who created the original notebook which we modified here to showcase how to use *ART* with *FfDL*. If you would like to try *[Watson Machine Learning (WML) Service](https://console.bluemix.net/catalog/services/machine-learning)* with *ART* check out Anupama and Vijay's notebook here:\n", + "\n", + "[https://github.ibm.com/robust-dlaas/ART-in-WML/Use ART to check robustness of deep learning models.ipynb](https://github.ibm.com/robust-dlaas/ART-in-WML/blob/master/Use%20ART%20to%20check%20robustness%20of%20deep%20learning%20models.ipynb)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Copyright © 2018 IBM. This notebook and its source code are released under the terms of the MIT License." + ] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/demos/fashion-mnist-adversarial/README.md b/demos/fashion-mnist-adversarial/README.md new file mode 100644 index 00000000..4866eaf8 --- /dev/null +++ b/demos/fashion-mnist-adversarial/README.md @@ -0,0 +1,146 @@ +# Jupyter Notebook using FfDL with Adversarial Robustness Toolbox to test the robustness of Deep Learning Models + +The [Adversarial Robustness Toolbox (ART)](https://github.com/IBM/adversarial-robustness-toolbox), an open source software library, supports both researchers and developers in defending deep neural networks against adversarial attacks, making AI systems more secure. Its purpose is to allow rapid crafting and analysis of attack and defense methods for machine learning models. + +[Fabric for Deep Learning (FfDL, pronounced “fiddle”)](https://github.com/IBM/FfDL) provides a consistent way to run deep-learning frameworks such as TensorFlow, PyTorch, Caffe, Keras etc. as a service on Kubernetes. + +This [Jupyter](http://jupyter.org/install) notebook trains a [Fashion MNIST](#dataset) model with +[Fabric for Deep Learning (FfDL)](https://github.com/IBM/FfDL) on a Kubernetes Cluster and uses the +[Adversarial Robustness Toolbox (ART)](https://github.com/IBM/adversarial-robustness-toolbox) to generate adversarial +samples and test the robustness of the model against adversarial attacks. + +![FfDL](images/ffdl-art-jupyter.png) + +The [notebook](ART_with_FfDL.ipynb) is structured into sections which can be run as a whole or in individual pieces like +the model training or adversarial attacks on a trained model. + +## Notebook Contents + +1. **Set up the environment** - Configure access to FfDL cluster, to cloud object storage. Upload the training data to + cloud object storage. + +2. **Create a Keras model** - Create a Convolutional Neural Network (CNN) training script based on + [keras/examples/mnist_cnn.py](https://github.com/keras-team/keras/blob/master/examples/mnist_cnn.py) and upload it to + cloud object storage. Create a FfDL `manifest.yml` to describing the model, the deep learning framework, the object + store information, resource requirements, and hyperparameters required for training and testing. + +3. **Train the model** - Setup the FfDL command line environment, start the training job with FfDL on your Kubernetes + cluster. While the training job is running you can monitor the training logs, or, optionally cancel the training job. + +4. **Generate adversarial samples for a robustness check** - Once the training job is completed, download the generated + model artifacts and load the model in the notebook. Use one of ART's attack methods, the Fast Gradient Method (FGM), + to craft adversarial samples which can be used to measure the model's robustness against adversarial attacks. Show + robustness metrics and compare model predictions on adversarial samples to predictions on the original test images. + + ![model predictions on adversarial samples](images/adv_sample_predictions.png) + +5. **Summary and next steps** - This notebook showed how to use Jupyter notebooks to interact with a FfDL cluster and + how the Adversarial Robustness Toolbox can be integrated into a deep learning pipeline. To learn more about ART go to + https://github.com/IBM/adversarial-robustness-toolbox + +Follow the [Prerequisites](#prerequisites) and the [Setup](#setup) steps below before [Running the Notebook](#running-the-notebook). + + +## Prerequisites + +### Kubernetes Cluster with FfDL +You need to have [Fabric for Deep Learning](https://github.com/IBM/FfDL/) deployed on a Kubernetes Cluster with at least +2 CPUs and 4 Gb Memory. + +### Cloud Object Storage +To store model and training data, this notebook requires access to a Cloud Object Storage (COS) instance. +[BlueMix Cloud Object Storage](https://console.bluemix.net/catalog/services/cloud-object-storage) offers a free +*lite plan*. +Follow [these instructions](https://dataplatform.ibm.com/docs/content/analyze-data/ml_dlaas_object_store.html) +to create your COS instance and generate [service credentials](https://console.bluemix.net/docs/services/cloud-object-storage/iam/service-credentials.html#service-credentials) +with [HMAC keys](https://console.bluemix.net/docs/services/cloud-object-storage/hmac/credentials.html#using-hmac-credentials). +Then go to the COS dashboard: +- Get the `cos_service_endpoint` from the **Endpoint** tab +- In the **Service credentials** tab, click **New Credential +** + - Add the "[HMAC](https://console.bluemix.net/docs/services/cloud-object-storage/hmac/credentials.html#using-hmac-credentials)" + **inline configuration parameter**: `{"HMAC":true}`, click **Add** + - Get the `access_key_id` (*AWS_ACCESS_KEY_ID*) and `secret_access_key` (*AWS_SECRET_ACCESS_KEY*) + from the `cos_hmac_keys` section of the instance credentials: + ``` + "cos_hmac_keys": { + "access_key_id": "1234567890abcdefghijklmnopqrtsuv", + "secret_access_key": "0987654321zxywvutsrqponmlkjihgfedcba1234567890ab" + } + ``` + + +## Setup + +### Environment Variables + +Optional, this step can be done in the notebook itself. + +```bash +export FFDL_DIR="" # Path to local clone of FfDL repository +export PUBLIC_IP="" # Public IP of FfDL cluster +export KUBECONFIG="" # Path to Kubernetes cluster configuration file +export AWS_ACCESS_KEY_ID="" # Cloud Object Storage (AWS) Access Key ID +export AWS_SECRET_ACCESS_KEY="" # Cloud Object Storage (AWS) Secret Access Key +export AWS_DEFAULT_REGION="" # Cloud Object Storage region name, i.e. 'us-east-1' +export AWS_ENDPOINT_URL="" # Cloud Object Storage endpoint, i.e. 'https://s3-api.us-geo.objectstorage.softlayer.net' +``` + +### Virtual Environment + +Before running this notebook for the first time we recommend creating a Python 3 *virtual environment* using either +[virtualenv](https://pypi.org/project/virtualenv/), [venv](https://docs.python.org/3/library/venv.html) (since Python 3.3), +or [Conda](https://conda.io/docs/user-guide/tasks/manage-environments.html). +```bash +# assuming present working directory to be the FfDL project root +pip3 install virtualenv +virtualenv .venv/art +.venv/art/bin/pip install -r demos/fashion-mnist-adversarial/requirements.txt --upgrade +``` + +## Running the Notebook + +Activate the Python virtual environment +```bash +source .venv/art/bin/activate +``` + +Start the Jupyter notebook server +```bash +jupyter-notebook --notebook-dir demos/fashion-mnist-adversarial +# ... use Control-C to stop the notebook server +``` + +Deactivate the virtual environment after stopping the Jupyter notebook server +```bash +deactivate +``` + +To delete the Python virtual environment run the following command +```bash +rm -rf .venv/art +``` + + +## Dataset + +Fashion-MNIST is a [dataset of clothing images](https://github.com/zalandoresearch/fashion-mnist) provided by +[Zalando Research](https://research.zalando.com/). It is intended to serve as a direct drop-in replacement for the +original MNIST dataset of hand-written digits for benchmarking Machine Learning algorithms. The Fashion-MNIST dataset +is split into 60,000 training examples and 10,000 test examples. Each example is a 28x28 grayscale image, associated +with a label from 10 classes. + +![Fashion-MNIST](https://github.com/IBM/Fashion-MNIST-using-FfDL/blob/master/fashion-mnist-webapp/static/img/p1.png) + + +## Acknowledgements + +Special thanks to [Anupama-Murthi](https://github.ibm.com/Anupama-Murthi) and [Vijay Arya](https://github.ibm.com/vijay-arya) +who created the original notebook which we modified here to showcase how to use *ART* with *FfDL*. +If you would like to try *[Watson Machine Learning (WML) Service](https://console.bluemix.net/catalog/services/machine-learning)* +with *ART* check out Anupama and Vijay's notebook here: + +[https://github.ibm.com/robust-dlaas/ART-in-WML/Use ART to check robustness of deep learning models.ipynb](https://github.ibm.com/robust-dlaas/ART-in-WML/blob/master/Use%20ART%20to%20check%20robustness%20of%20deep%20learning%20models.ipynb) + + +## License +[Apache 2.0](LICENSE) diff --git a/demos/fashion-mnist-adversarial/images/adv_sample_predictions.png b/demos/fashion-mnist-adversarial/images/adv_sample_predictions.png new file mode 100644 index 00000000..10df8054 Binary files /dev/null and b/demos/fashion-mnist-adversarial/images/adv_sample_predictions.png differ diff --git a/demos/fashion-mnist-adversarial/images/ffdl-art-jupyter.png b/demos/fashion-mnist-adversarial/images/ffdl-art-jupyter.png new file mode 100644 index 00000000..367b1500 Binary files /dev/null and b/demos/fashion-mnist-adversarial/images/ffdl-art-jupyter.png differ diff --git a/demos/fashion-mnist-adversarial/images/ffdl.png b/demos/fashion-mnist-adversarial/images/ffdl.png new file mode 100644 index 00000000..3c095141 Binary files /dev/null and b/demos/fashion-mnist-adversarial/images/ffdl.png differ diff --git a/demos/fashion-mnist-adversarial/requirements.txt b/demos/fashion-mnist-adversarial/requirements.txt new file mode 100644 index 00000000..d39b4cae --- /dev/null +++ b/demos/fashion-mnist-adversarial/requirements.txt @@ -0,0 +1,8 @@ +keras>=2.1.6 +tensorflow>=1.8 +ipython>=5.0.0 +jupyter>=1.0.0 +requests>=2.12.0,<=2.18.4 +wget +boto3 +git+git://github.com/IBM/adversarial-robustness-toolbox@master diff --git a/demos/fashion-mnist-training/README.md b/demos/fashion-mnist-training/README.md new file mode 100644 index 00000000..2efd731a --- /dev/null +++ b/demos/fashion-mnist-training/README.md @@ -0,0 +1,32 @@ +# Fashion MNIST using FfDL + +Train your Fashion MNIST model with [Fabric for Deep Learning (FfDL)](https://github.com/IBM/FfDL) on Kubernetes Cluster configured with GPU. This model is defined in Keras and trained using TensorFlow using Fabric for Deep Learning which is deployed on Kubernetes GPU cluster running on IBM Cloud. + +On the open source side, to complete the FfDL trained model deployment story we’ve worked together with [Seldon](https://github.com/SeldonIO/seldon-core) to provide a FfDL integration. + +In this code, we will show end to end example how to train, deploy, and write an application to consume to deployed model on Fashion MNISH dataset on Kubernetes + + + +## Prerequisites +You need to have [Fabric for Deep Learning](https://github.com/IBM/FfDL) deployed on a Kubernetes Cluster with at least 4 CPUs and 8Gb Memory. + +## Steps +1. [Train your Fashion MNIST model with FfDL](fashion-train) +2. [Deploy your Fashion MNIST model with Seldon](seldon-deployment) +3. [Build the FfDL Fashion MNIST Web App and push it on Kubernetes](fashion-mnist-webapp) + +## Dataset +Fashion-MNIST is a [dataset provided by Zalando of clothing images](https://github.com/zalandoresearch/fashion-mnist). It is intended to serve as a direct drop-in replacement for the original MNIST dataset for benchmarking ML algorithms. It shares the same image size and structure of training and testing splits, consisting of a training set of 60,000 examples and a test set of 10,000 examples. Each example is a 28x28 grayscale image, associated with a label from 10 classes + + + +## Appropriate Test Data + +The model will expect to receive a file path to a picture. Over 30 different file types are supported although only the two (.png and .jpg) have been tested extensively. These file types are listed at (http://pillow.readthedocs.io/en/5.1.x/handbook/image-file-formats.html) + +The models trained on the Fashion MNIST data will work best when there is only one object in the picture and the background of the picture is pure black. Additionally, the object in the picture should be centered and completely in frame. Any image the model receives will be compressed into a 28x28 grayscaled image to match the original Fashion MNIST training set. Due to this, the model works best when the object in the picture takes up a majority of the frame. + +## License + +[Apache 2.0](LICENSE) diff --git a/demos/fashion-mnist-training/demo.md b/demos/fashion-mnist-training/demo.md new file mode 100644 index 00000000..5a389712 --- /dev/null +++ b/demos/fashion-mnist-training/demo.md @@ -0,0 +1,47 @@ +# DEMO FLOW + +## Prerequisites +This demo assumes the Kubernetes Cluster has FfDL, Seldon, and Webapp built and deployed, and you have access to that cluster. + +## Steps +1. Go to the FfDL GUI. You can obtain your FfDL GUI in the FfDL repository by running `make status`. + +2. Submit a training job using either the FfDL GUI or command line. The model definition file is at `fashion-train/fashion-training.zip` and the manifest is at `fashion-train/manifest.yml` + + **GUI instructions** + + Upload your model definition file and manifest file. Then click **Submit Training Job** + + ![ui-example](fashion-mnist-webapp/static/img/ui-example.png) + + **Command line instructions** + ```shell + # Setup commands + git clone https://github.com/IBM/Fashion-MNIST-using-FfDL + cd FfDL-Fashion-MNIST/fashion-train + export node_ip= + export restapi_port=$(kubectl get service ffdl-restapi -o jsonpath='{.spec.ports[0].nodePort}') + export DLAAS_URL=http://$node_ip:$restapi_port; export DLAAS_USERNAME=test-user; export DLAAS_PASSWORD=test; + CLI_CMD=/cli/bin/ffdl-$(if [ "$(uname)" = "Darwin" ]; then echo 'osx'; else echo 'linux'; fi) + ``` + + ```shell + # training command + $CLI_CMD train manifest.yml fashion-training + ``` + +3. Then the job will start running, with k80 usually takes 5 minutes. Meanwhile, we can talk about how FfDL can take advantage of GPU resources. + * Explain some background about this training job: + * The dataset we are using is Fashion-MNIST. It has a training set of 60,000 examples and a test set of 10,000 examples. + * This is a CNN model with 3 Convolutional layers followed by 2 dense layers. + * This job will run for 30 epochs and our batch size is 128. + * The validated accuracy rate and loss rate may look strange because our model is using the Adam optimizer with 0.4 dropout rate. The great thing about FfDL is it will plot out these Scalar graphs for you, so you can use it to tell your model may have some issues. + * Click on the info icon for the `Fashion-MNIST keras model with k80 GPU` and `Fashion-MNIST keras model with 30 CPU` respectively. Then, show k80 GPU can train this job within 5 minutes, while with pure CPU it will cost more than 9 minutes even with 30 CPUs. + * After the training job is finished, your model will be stored in the Cloud Object Storage and ready to be served. + +4. We use Seldon to serve our model that are stored in the Cloud Object Storage. + +5. Use the Sample Web-app at http://:8088 to demo your ML Web-app. + * The demo works the best if you use fashion images with black background. + * Sample demo images are avaliable at the `sample-test-data` directory. These images are not part of the default images on the demo website. + * If you want to delete all your uploaded images, go to http://:8088/cleanup and click **Delete User Uploaded Image**. Then click the FfDL icon to return to the main demo page. diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/.travis.yml b/demos/fashion-mnist-training/fashion-mnist-webapp/.travis.yml new file mode 100644 index 00000000..2dab8283 --- /dev/null +++ b/demos/fashion-mnist-training/fashion-mnist-webapp/.travis.yml @@ -0,0 +1,6 @@ +language: python +python: + - "2.7" + - "3.6" +script: + - flake8 \ No newline at end of file diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/Dockerfile b/demos/fashion-mnist-training/fashion-mnist-webapp/Dockerfile new file mode 100644 index 00000000..36d2acf9 --- /dev/null +++ b/demos/fashion-mnist-training/fashion-mnist-webapp/Dockerfile @@ -0,0 +1,25 @@ +# +# Copyright 2018 IBM Corp. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +FROM python:3 + +COPY . /app +WORKDIR /app +RUN pip install --upgrade pip +RUN pip install -r requirements.txt + +EXPOSE 8088 +CMD python app.py diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/README.md b/demos/fashion-mnist-training/fashion-mnist-webapp/README.md new file mode 100644 index 00000000..ab431d62 --- /dev/null +++ b/demos/fashion-mnist-training/fashion-mnist-webapp/README.md @@ -0,0 +1,23 @@ +# Build the FfDL Fashion MNIST Web App and push it on Kubernetes + +The webapp is designed to take images that are uploaded, display them on the webpage, and show the names of the classes with the top 3 confidences. There is an accompanying word cloud where the size of the word is correlated to the frequency of the class being the number one choice for a picture. + +1. Go to the `fashion-mnist-webapp` directory, run the following commands to containerize your web application and push it to DockerHub. + ```shell + cd fashion-mnist-webapp + docker build -t . + docker push + ``` + +2. Modify deployment resource from the template `fashion-mnist-webapp.yaml`. You need to set: + * `MODEL_ENDPOINT`: Your Seldon model endpoint. (e.g. http:///seldon//api/v0.1/predictions) The `AMBASSADOR_API_IP` is your `seldon-core-ambassador`'s service endpoint which by default is exposed with NodePort. + * `image` : Your web app image at DockerHub + +3. Congratulations, your web app should be running now. You can use the following commands to check where your web app is hosted. + ```shell + kubectl get svc fashion-mnist-webapp + # Your web app link is http://:8088 + ``` + +## Reference +This web-app example is based on the Model Asset Exchange web-app example. (https://github.com/IBM/MAX-Image-Caption-Generator-Web-App) diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/app.py b/demos/fashion-mnist-training/fashion-mnist-webapp/app.py new file mode 100755 index 00000000..b823d419 --- /dev/null +++ b/demos/fashion-mnist-training/fashion-mnist-webapp/app.py @@ -0,0 +1,304 @@ +#!/usr/bin/env python + +# +# Copyright 2018 IBM Corp. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import collections +import json +import logging +import os +import requests +import signal +import time +import threading +from tornado import httpserver, ioloop, web +from tornado.options import define, options, parse_command_line +import numpy +from PIL import Image +import io + +modelEndpoint = os.environ.get("MODEL_ENDPOINT") +# Command Line Options +define("port", default=8088, help="Port the web app will run on") +# define("ml-endpoint", default="http://0.0.0.0:5000/predict", +# help="The Image Caption Generator REST endpoint") +define("ml-endpoint", default=modelEndpoint, + help="The Image Caption Generator REST endpoint") + +# Setup Logging +logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO"), + format='%(levelname)s: %(message)s') + +# Global variables +static_img_path = "static/img/images/" +temp_img_prefix = "MAX-" +image_captions = collections.OrderedDict() +VALID_EXT = ['png', 'jpg', 'jpeg', 'gif'] +FASHION_LIST = ['T-shirt/top','Trouser','Pullover','Dress','Coat','Sandal','Shirt','Sneaker','Bag','Ankle boot'] + + +class MainHandler(web.RequestHandler): + def get(self): + self.render("index.html", image_captions=image_captions) + + +class DetailHandler(web.RequestHandler): + def get(self): + image = self.get_argument('image', None) + if not image: + self.set_status(400) + return self.finish("400: Missing image parameter") + if image not in image_captions: + self.set_status(404) + return self.finish("404: Image not found") + self.render("detail-snippet.html", image=image, + predictions=image_captions[image]) + + +class CleanupHandler(web.RequestHandler): + def get(self): + self.render("cleanup.html") + + def delete(self): + clean_up() + + +class UploadHandler(web.RequestHandler): + def post(self): + finish_ret = [] + new_files = self.request.files['file'] + for file_des in new_files: + file_name = temp_img_prefix + file_des['filename'] + if valid_file_ext(file_name): + rel_path = static_img_path + file_name + output_file = open(rel_path, 'wb') + output_file.write(file_des['body']) + output_file.close() + caption = run_ml(rel_path) + finish_ret.append({ + "file_name": rel_path, + "caption": caption[0]['caption'] + }) + if not finish_ret: + self.send_error(400) + return + sort_image_captions() + self.finish(json.dumps(finish_ret)) + + +def valid_file_ext(filename): + return '.' in filename and filename.split('.', 1)[1].lower() in VALID_EXT + + +# Runs ML on given image +def run_ml(img_path): + img_file = {'image': open(img_path, 'rb')} + image = preprocess_object(img_path) + # Run curl command to send json to seldon + features = [str(i+1) for i in range(0,784)] + req = {"data": {"names": features, "ndarray": image}} + results = requests.post(ml_endpoint, json=req) + request_results = results.json() + # Run postprocessing and retrieve results from returned json + return_json = request_results['data']['ndarray'] + results = postprocess(return_json) + cap_json = postpostprocess(results) + print(cap_json) + caption = cap_json['predictions'] + image_captions[img_path] = caption + return caption + +# preprocess and post processing images +def preprocess_object(image_path, target_shape=(28,28)): + """ + + image_path: File path to image + target_shape: Shape that the model is expecting images to be in + by default the expected shape is (28,28) + returns: An array containing the raw data from the image at + 'image_path' resized to 'target_shape' + """ + + image = read_image(image_path, target_shape) + + # Changes the image from a 1d array of size 784 to 2d of 28x28 + feature_list = [] + row = [] + for x in range(0,28): + range1 = 28 * x + row = [] + for vals in range(0,28): + pixel = image[range1 + vals] + row.append([pixel]) + feature_list.append(row) + + return [feature_list] + +def read_image(image_path, target_shape): + """ + + image_path: File path to image + target_shape: Shape that the model is expecting images to be in + by default the expected shape is (28,28) + returns: Returns a list of pixel values stored in 'L' mode + (black and white 8bit pixels) + """ + image = Image.open(image_path) + image = image.resize(target_shape) + # Force image to be stored in 'L' mode (Black and White 8bit pixels) + image = image.convert('L') + raw = list(image.getdata()) + return raw + +def postprocess(results): + """ + + results: List of results where each result is a list of confidences + in the image being predicted being of a certain class + returns: A list of 2-tuples where each 2-tuple corresponds to a result + and is a 2-tuple where the second element is a list of sorted + confidence values (from max to min) and the first element is + the argsorted list of classes corresponding to the confidences + """ + + post_results = [] + for result in results: + argsort_rev = numpy.argsort(result)[::-1] + result_rev_sort = sorted(result)[::-1] + post_results.append((argsort_rev, result_rev_sort)) + return post_results + +def postpostprocess(post_results): + """ + + post_results: An array of confidences that the image is of the class + with the same key as the index of the confidence value + """ + + FASHION_LIST = ['T-shirt/top','Trouser','Pullover','Dress','Coat','Sandal','Shirt','Sneaker','Bag','Ankle boot'] + + cap_array = [] + for i in range(0,3): + cap_array.append({"index": i, "caption": FASHION_LIST[post_results[0][0][i]],"probability": str(round(post_results[0][1][i]*100, 4))}) + cap_json = {'predictions': cap_array} + return cap_json + + +def sort_image_captions(): + global image_captions + image_captions = collections.OrderedDict( + sorted(image_captions.items(), key=lambda t: t[0].lower())) + + +# Gets list of images with relative paths from static dir +def get_image_list(): + image_list = sorted(os.listdir(static_img_path)) + rel_img_list = [static_img_path + s for s in image_list] + return rel_img_list + + +# Run all static images through ML +def prepare_metadata(): + threads = [] + + rel_img_list = get_image_list() + for img in rel_img_list: + t = threading.Thread(target=run_ml, args=(img,)) + threads.append(t) + + for t in threads: + t.start() + + for t in threads: + t.join() + + sort_image_captions() + + +# Deletes all files uploaded through the GUI and removes them from the dict +def clean_up(): + img_list = get_image_list() + for img_file in img_list: + if img_file.startswith(static_img_path + temp_img_prefix): + os.remove(img_file) + image_captions.pop(img_file) + + +def signal_handler(sig, frame): + ioloop.IOLoop.current().add_callback_from_signal(shutdown) + + +def shutdown(): + logging.info("Cleaning up image files") + clean_up() + logging.info("Stopping web server") + server.stop() + ioloop.IOLoop.current().stop() + + +def make_app(): + handlers = [ + (r"/", MainHandler), + (r"/upload", UploadHandler), + (r"/cleanup", CleanupHandler), + (r"/detail", DetailHandler) + ] + + configs = { + 'static_path': 'static', + 'template_path': 'templates' + } + + return web.Application(handlers, **configs) + + +def main(): + parse_command_line() + + global ml_endpoint + ml_endpoint = options.ml_endpoint + # if '/model/predict' not in options.ml_endpoint: + # ml_endpoint = options.ml_endpoint + "/model/predict" + + logging.info("Connecting to ML endpoint at %s", ml_endpoint) + + # try: + # requests.get(ml_endpoint) + # except requests.exceptions.ConnectionError: + # logging.error( + # "Cannot connect to the Image Caption Generator REST endpoint at " + + # options.ml_endpoint) + # raise SystemExit + + logging.info("Starting web server") + app = make_app() + global server + server = httpserver.HTTPServer(app) + server.listen(options.port) + signal.signal(signal.SIGINT, signal_handler) + + logging.info("Preparing ML metadata (this may take some time)") + start = time.time() + prepare_metadata() + end = time.time() + logging.info("Metadata prepared in %s seconds", end - start) + + logging.info("Use Ctrl+C to stop web server") + ioloop.IOLoop.current().start() + + +if __name__ == "__main__": + main() diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/fashion-mnist-webapp.yaml b/demos/fashion-mnist-training/fashion-mnist-webapp/fashion-mnist-webapp.yaml new file mode 100644 index 00000000..ee44ab29 --- /dev/null +++ b/demos/fashion-mnist-training/fashion-mnist-webapp/fashion-mnist-webapp.yaml @@ -0,0 +1,40 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: fashion-mnist-webapp + labels: + service: fashion-mnist-webapp +spec: + replicas: 1 + template: + metadata: + name: fashion-mnist-webapp + labels: + service: fashion-mnist-webapp + spec: + containers: + - name: fashion-mnist-webapp + # You can use your own webapp image below + image: journeycode/ffdl-webapp-demo:latest + imagePullPolicy: Always + env: + - name: MODEL_ENDPOINT + # Put down your Seldon model endpoint + value: http:///seldon//api/v0.1/predictions + ports: + - containerPort: 8088 +--- +apiVersion: v1 +kind: Service +metadata: + name: fashion-mnist-webapp + labels: + service: fashion-mnist-webapp +spec: + ports: + - name: http + port: 8088 + targetPort: 8088 + type: LoadBalancer + selector: + service: fashion-mnist-webapp diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/requirements.txt b/demos/fashion-mnist-training/fashion-mnist-webapp/requirements.txt new file mode 100644 index 00000000..d3cabc79 --- /dev/null +++ b/demos/fashion-mnist-training/fashion-mnist-webapp/requirements.txt @@ -0,0 +1,5 @@ +numpy +requests +tornado +flake8 +Pillow diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/css/bootstrap.min.css b/demos/fashion-mnist-training/fashion-mnist-webapp/static/css/bootstrap.min.css new file mode 100644 index 00000000..a9558eb0 --- /dev/null +++ b/demos/fashion-mnist-training/fashion-mnist-webapp/static/css/bootstrap.min.css @@ -0,0 +1,5 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} \ No newline at end of file diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/css/featherlight.min.css b/demos/fashion-mnist-training/fashion-mnist-webapp/static/css/featherlight.min.css new file mode 100755 index 00000000..058487f9 --- /dev/null +++ b/demos/fashion-mnist-training/fashion-mnist-webapp/static/css/featherlight.min.css @@ -0,0 +1,8 @@ +/** + * Featherlight - ultra slim jQuery lightbox + * Version 1.7.13 - http://noelboss.github.io/featherlight/ + * + * Copyright 2018, Noël Raoul Bossart (http://www.noelboss.com) + * MIT Licensed. +**/ +html.with-featherlight{overflow:hidden}.featherlight{display:none;position:fixed;top:0;right:0;bottom:0;left:0;z-index:2147483647;text-align:center;white-space:nowrap;cursor:pointer;background:#333;background:rgba(0,0,0,0)}.featherlight:last-of-type{background:rgba(0,0,0,.8)}.featherlight:before{content:'';display:inline-block;height:100%;vertical-align:middle}.featherlight .featherlight-content{position:relative;text-align:left;vertical-align:middle;display:inline-block;overflow:auto;padding:25px 25px 0;border-bottom:25px solid transparent;margin-left:5%;margin-right:5%;max-height:95%;background:#fff;cursor:auto;white-space:normal}.featherlight .featherlight-inner{display:block}.featherlight link.featherlight-inner,.featherlight script.featherlight-inner,.featherlight style.featherlight-inner{display:none}.featherlight .featherlight-close-icon{position:absolute;z-index:9999;top:0;right:0;line-height:25px;width:25px;cursor:pointer;text-align:center;font-family:Arial,sans-serif;background:#fff;background:rgba(255,255,255,.3);color:#000;border:0;padding:0}.featherlight .featherlight-close-icon::-moz-focus-inner{border:0;padding:0}.featherlight .featherlight-image{width:100%}.featherlight-iframe .featherlight-content{border-bottom:0;padding:0;-webkit-overflow-scrolling:touch}.featherlight iframe{border:0}.featherlight *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@media only screen and (max-width:1024px){.featherlight .featherlight-content{margin-left:0;margin-right:0;max-height:98%;padding:10px 10px 0;border-bottom:10px solid transparent}}@media print{html.with-featherlight>*>:not(.featherlight){display:none}} \ No newline at end of file diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/css/image-picker.css b/demos/fashion-mnist-training/fashion-mnist-webapp/static/css/image-picker.css new file mode 100755 index 00000000..c13e50ac --- /dev/null +++ b/demos/fashion-mnist-training/fashion-mnist-webapp/static/css/image-picker.css @@ -0,0 +1,30 @@ +ul.thumbnails.image_picker_selector { + overflow: auto; + list-style-image: none; + list-style-position: outside; + list-style-type: none; + padding: 0px; + margin: 0px; } + ul.thumbnails.image_picker_selector ul { + overflow: auto; + list-style-image: none; + list-style-position: outside; + list-style-type: none; + padding: 0px; + margin: 0px; } + ul.thumbnails.image_picker_selector li.group {width:100%;} + ul.thumbnails.image_picker_selector li.group_title { + float: none; } + ul.thumbnails.image_picker_selector li { + margin: 0px 12px 12px 0px; + float: left; } + ul.thumbnails.image_picker_selector li .thumbnail { + padding: 6px; + border: 1px solid #dddddd; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; } + ul.thumbnails.image_picker_selector li .thumbnail img { + -webkit-user-drag: none; } + ul.thumbnails.image_picker_selector li .thumbnail.selected { + background: #0088cc; } diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/css/webapp.css b/demos/fashion-mnist-training/fashion-mnist-webapp/static/css/webapp.css new file mode 100644 index 00000000..42f51ab0 --- /dev/null +++ b/demos/fashion-mnist-training/fashion-mnist-webapp/static/css/webapp.css @@ -0,0 +1,117 @@ +/* + * Copyright 2018 IBM Corp. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Style sheet for MAX Image Caption Generator Web App */ + +body { + font-family: 'IBM Plex Sans', 'Helvetica Neue', Arial, sans-serif; +} + +.container-fluid { + padding: 1% 2%; +} + +#codait-logo { + min-width: 162px; + min-height: 150px; +} + +#codait-logo img { + width: 162px; + height: 150px; +} + +.title-section h1 { + margin-top: 10px; +} + +.panel-title { + font-size: 18px; +} + +#word-cloud { + text-align: center; +} + +#thumbnails .select-buttons button { + margin: 0px 12px 12px 0px; +} + +.thumbnails li { + width: 30%; +} + +#thumbnails .image-scroller { + max-height: 65vh; + width: 100%; + overflow: auto; +} + +.ibm-code .btn-primary { + background-color: #26A8A2; + border-color: #32A8A3; + white-space: normal; +} + +.ibm-code .btn-primary:hover { + background-color: #1E8B87; + border-color: #24D8B89; +} + +.ibm-code ul.thumbnails.image_picker_selector li { + float: none; + display:inline-block; + vertical-align: top; +} + +.ibm-code ul.thumbnails.image_picker_selector li .thumbnail.selected { + background: #5FBFBB; +} + +.ibm-code .thumbnail { + display: inline-block; + position: relative; +} + +.thumbnails .more-info-icon { + position: absolute; + top: 0; + right: 0; + padding: 6px; + background: #FFFFFF; + border-radius: 4px; + font-size: 1.2em; +} + +a.more-info-icon { + color: inherit; + text-decoration: inherit; +} + +.thumbnails .selected .more-info-icon { + background: #5FBFBB; +} + +.featherlight .featherlight-content { + border-radius: 4px; + background: #5FBFBB; + border-bottom: 0; + max-width: 100vh; +} + +.featherlight .featherlight-close-icon { + background: #5FBFBB; +} diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/favicon.ico b/demos/fashion-mnist-training/fashion-mnist-webapp/static/favicon.ico new file mode 100644 index 00000000..e53fa154 Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/favicon.ico differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/fonts/glyphicons-halflings-regular.eot b/demos/fashion-mnist-training/fashion-mnist-webapp/static/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 00000000..b93a4953 Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/fonts/glyphicons-halflings-regular.eot differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/fonts/glyphicons-halflings-regular.svg b/demos/fashion-mnist-training/fashion-mnist-webapp/static/fonts/glyphicons-halflings-regular.svg new file mode 100644 index 00000000..94fb5490 --- /dev/null +++ b/demos/fashion-mnist-training/fashion-mnist-webapp/static/fonts/glyphicons-halflings-regular.svg @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/fonts/glyphicons-halflings-regular.ttf b/demos/fashion-mnist-training/fashion-mnist-webapp/static/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 00000000..1413fc60 Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/fonts/glyphicons-halflings-regular.ttf differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/fonts/glyphicons-halflings-regular.woff b/demos/fashion-mnist-training/fashion-mnist-webapp/static/fonts/glyphicons-halflings-regular.woff new file mode 100644 index 00000000..9e612858 Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/fonts/glyphicons-halflings-regular.woff differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/fonts/glyphicons-halflings-regular.woff2 b/demos/fashion-mnist-training/fashion-mnist-webapp/static/fonts/glyphicons-halflings-regular.woff2 new file mode 100644 index 00000000..64539b54 Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/fonts/glyphicons-halflings-regular.woff2 differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/codait-logo.jpg b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/codait-logo.jpg new file mode 100644 index 00000000..f60f6a8d Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/codait-logo.jpg differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/fashion-arch.png b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/fashion-arch.png new file mode 100644 index 00000000..dd19ee72 Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/fashion-arch.png differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/ffdl-blue.png b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/ffdl-blue.png new file mode 100644 index 00000000..97039c87 Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/ffdl-blue.png differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/ffdl-fashion.png b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/ffdl-fashion.png new file mode 100644 index 00000000..e234ba17 Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/ffdl-fashion.png differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/0.jpg b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/0.jpg new file mode 100644 index 00000000..36e068f9 Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/0.jpg differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/1.jpg b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/1.jpg new file mode 100644 index 00000000..bb30c09d Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/1.jpg differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/2.jpg b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/2.jpg new file mode 100644 index 00000000..a1c09109 Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/2.jpg differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/3.png b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/3.png new file mode 100644 index 00000000..4281279c Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/3.png differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/4.jpg b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/4.jpg new file mode 100644 index 00000000..bc611e09 Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/4.jpg differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/5.jpg b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/5.jpg new file mode 100644 index 00000000..4d8a4cd0 Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/5.jpg differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/6.jpg b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/6.jpg new file mode 100644 index 00000000..3ac4f73c Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/6.jpg differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/7.jpg b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/7.jpg new file mode 100644 index 00000000..44c99474 Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/7.jpg differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/8.jpg b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/8.jpg new file mode 100644 index 00000000..d3e22626 Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/8.jpg differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/9.jpg b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/9.jpg new file mode 100644 index 00000000..508d17c7 Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/images/9.jpg differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/p1.png b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/p1.png new file mode 100644 index 00000000..1ecde6f1 Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/p1.png differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/ui-example.png b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/ui-example.png new file mode 100644 index 00000000..905d926b Binary files /dev/null and b/demos/fashion-mnist-training/fashion-mnist-webapp/static/img/ui-example.png differ diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/js/d3.layout.cloud.js b/demos/fashion-mnist-training/fashion-mnist-webapp/static/js/d3.layout.cloud.js new file mode 100644 index 00000000..14b01e22 --- /dev/null +++ b/demos/fashion-mnist-training/fashion-mnist-webapp/static/js/d3.layout.cloud.js @@ -0,0 +1,500 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g=(g.d3||(g.d3 = {}));g=(g.layout||(g.layout = {}));g.cloud = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 5, + ch = 1 << 11; + +module.exports = function() { + var size = [256, 256], + text = cloudText, + font = cloudFont, + fontSize = cloudFontSize, + fontStyle = cloudFontNormal, + fontWeight = cloudFontNormal, + rotate = cloudRotate, + padding = cloudPadding, + spiral = archimedeanSpiral, + words = [], + timeInterval = Infinity, + event = dispatch("word", "end"), + timer = null, + random = Math.random, + cloud = {}, + canvas = cloudCanvas; + + cloud.canvas = function(_) { + return arguments.length ? (canvas = functor(_), cloud) : canvas; + }; + + cloud.start = function() { + var contextAndRatio = getContext(canvas()), + board = zeroArray((size[0] >> 5) * size[1]), + bounds = null, + n = words.length, + i = -1, + tags = [], + data = words.map(function(d, i) { + d.text = text.call(this, d, i); + d.font = font.call(this, d, i); + d.style = fontStyle.call(this, d, i); + d.weight = fontWeight.call(this, d, i); + d.rotate = rotate.call(this, d, i); + d.size = ~~fontSize.call(this, d, i); + d.padding = padding.call(this, d, i); + return d; + }).sort(function(a, b) { return b.size - a.size; }); + + if (timer) clearInterval(timer); + timer = setInterval(step, 0); + step(); + + return cloud; + + function step() { + var start = Date.now(); + while (Date.now() - start < timeInterval && ++i < n && timer) { + var d = data[i]; + d.x = (size[0] * (random() + .5)) >> 1; + d.y = (size[1] * (random() + .5)) >> 1; + cloudSprite(contextAndRatio, d, data, i); + if (d.hasText && place(board, d, bounds)) { + tags.push(d); + event.call("word", cloud, d); + if (bounds) cloudBounds(bounds, d); + else bounds = [{x: d.x + d.x0, y: d.y + d.y0}, {x: d.x + d.x1, y: d.y + d.y1}]; + // Temporary hack + d.x -= size[0] >> 1; + d.y -= size[1] >> 1; + } + } + if (i >= n) { + cloud.stop(); + event.call("end", cloud, tags, bounds); + } + } + } + + cloud.stop = function() { + if (timer) { + clearInterval(timer); + timer = null; + } + return cloud; + }; + + function getContext(canvas) { + canvas.width = canvas.height = 1; + var ratio = Math.sqrt(canvas.getContext("2d").getImageData(0, 0, 1, 1).data.length >> 2); + canvas.width = (cw << 5) / ratio; + canvas.height = ch / ratio; + + var context = canvas.getContext("2d"); + context.fillStyle = context.strokeStyle = "red"; + context.textAlign = "center"; + + return {context: context, ratio: ratio}; + } + + function place(board, tag, bounds) { + var perimeter = [{x: 0, y: 0}, {x: size[0], y: size[1]}], + startX = tag.x, + startY = tag.y, + maxDelta = Math.sqrt(size[0] * size[0] + size[1] * size[1]), + s = spiral(size), + dt = random() < .5 ? 1 : -1, + t = -dt, + dxdy, + dx, + dy; + + while (dxdy = s(t += dt)) { + dx = ~~dxdy[0]; + dy = ~~dxdy[1]; + + if (Math.min(Math.abs(dx), Math.abs(dy)) >= maxDelta) break; + + tag.x = startX + dx; + tag.y = startY + dy; + + if (tag.x + tag.x0 < 0 || tag.y + tag.y0 < 0 || + tag.x + tag.x1 > size[0] || tag.y + tag.y1 > size[1]) continue; + // TODO only check for collisions within current bounds. + if (!bounds || !cloudCollide(tag, board, size[0])) { + if (!bounds || collideRects(tag, bounds)) { + var sprite = tag.sprite, + w = tag.width >> 5, + sw = size[0] >> 5, + lx = tag.x - (w << 4), + sx = lx & 0x7f, + msx = 32 - sx, + h = tag.y1 - tag.y0, + x = (tag.y + tag.y0) * sw + (lx >> 5), + last; + for (var j = 0; j < h; j++) { + last = 0; + for (var i = 0; i <= w; i++) { + board[x + i] |= (last << msx) | (i < w ? (last = sprite[j * w + i]) >>> sx : 0); + } + x += sw; + } + delete tag.sprite; + return true; + } + } + } + return false; + } + + cloud.timeInterval = function(_) { + return arguments.length ? (timeInterval = _ == null ? Infinity : _, cloud) : timeInterval; + }; + + cloud.words = function(_) { + return arguments.length ? (words = _, cloud) : words; + }; + + cloud.size = function(_) { + return arguments.length ? (size = [+_[0], +_[1]], cloud) : size; + }; + + cloud.font = function(_) { + return arguments.length ? (font = functor(_), cloud) : font; + }; + + cloud.fontStyle = function(_) { + return arguments.length ? (fontStyle = functor(_), cloud) : fontStyle; + }; + + cloud.fontWeight = function(_) { + return arguments.length ? (fontWeight = functor(_), cloud) : fontWeight; + }; + + cloud.rotate = function(_) { + return arguments.length ? (rotate = functor(_), cloud) : rotate; + }; + + cloud.text = function(_) { + return arguments.length ? (text = functor(_), cloud) : text; + }; + + cloud.spiral = function(_) { + return arguments.length ? (spiral = spirals[_] || _, cloud) : spiral; + }; + + cloud.fontSize = function(_) { + return arguments.length ? (fontSize = functor(_), cloud) : fontSize; + }; + + cloud.padding = function(_) { + return arguments.length ? (padding = functor(_), cloud) : padding; + }; + + cloud.random = function(_) { + return arguments.length ? (random = _, cloud) : random; + }; + + cloud.on = function() { + var value = event.on.apply(event, arguments); + return value === event ? cloud : value; + }; + + return cloud; +}; + +function cloudText(d) { + return d.text; +} + +function cloudFont() { + return "serif"; +} + +function cloudFontNormal() { + return "normal"; +} + +function cloudFontSize(d) { + return Math.sqrt(d.value); +} + +function cloudRotate() { + return (~~(Math.random() * 6) - 3) * 30; +} + +function cloudPadding() { + return 1; +} + +// Fetches a monochrome sprite bitmap for the specified text. +// Load in batches for speed. +function cloudSprite(contextAndRatio, d, data, di) { + if (d.sprite) return; + var c = contextAndRatio.context, + ratio = contextAndRatio.ratio; + + c.clearRect(0, 0, (cw << 5) / ratio, ch / ratio); + var x = 0, + y = 0, + maxh = 0, + n = data.length; + --di; + while (++di < n) { + d = data[di]; + c.save(); + c.font = d.style + " " + d.weight + " " + ~~((d.size + 1) / ratio) + "px " + d.font; + var w = c.measureText(d.text + "m").width * ratio, + h = d.size << 1; + if (d.rotate) { + var sr = Math.sin(d.rotate * cloudRadians), + cr = Math.cos(d.rotate * cloudRadians), + wcr = w * cr, + wsr = w * sr, + hcr = h * cr, + hsr = h * sr; + w = (Math.max(Math.abs(wcr + hsr), Math.abs(wcr - hsr)) + 0x1f) >> 5 << 5; + h = ~~Math.max(Math.abs(wsr + hcr), Math.abs(wsr - hcr)); + } else { + w = (w + 0x1f) >> 5 << 5; + } + if (h > maxh) maxh = h; + if (x + w >= (cw << 5)) { + x = 0; + y += maxh; + maxh = 0; + } + if (y + h >= ch) break; + c.translate((x + (w >> 1)) / ratio, (y + (h >> 1)) / ratio); + if (d.rotate) c.rotate(d.rotate * cloudRadians); + c.fillText(d.text, 0, 0); + if (d.padding) c.lineWidth = 2 * d.padding, c.strokeText(d.text, 0, 0); + c.restore(); + d.width = w; + d.height = h; + d.xoff = x; + d.yoff = y; + d.x1 = w >> 1; + d.y1 = h >> 1; + d.x0 = -d.x1; + d.y0 = -d.y1; + d.hasText = true; + x += w; + } + var pixels = c.getImageData(0, 0, (cw << 5) / ratio, ch / ratio).data, + sprite = []; + while (--di >= 0) { + d = data[di]; + if (!d.hasText) continue; + var w = d.width, + w32 = w >> 5, + h = d.y1 - d.y0; + // Zero the buffer + for (var i = 0; i < h * w32; i++) sprite[i] = 0; + x = d.xoff; + if (x == null) return; + y = d.yoff; + var seen = 0, + seenRow = -1; + for (var j = 0; j < h; j++) { + for (var i = 0; i < w; i++) { + var k = w32 * j + (i >> 5), + m = pixels[((y + j) * (cw << 5) + (x + i)) << 2] ? 1 << (31 - (i % 32)) : 0; + sprite[k] |= m; + seen |= m; + } + if (seen) seenRow = j; + else { + d.y0++; + h--; + j--; + y++; + } + } + d.y1 = d.y0 + seenRow; + d.sprite = sprite.slice(0, (d.y1 - d.y0) * w32); + } +} + +// Use mask-based collision detection. +function cloudCollide(tag, board, sw) { + sw >>= 5; + var sprite = tag.sprite, + w = tag.width >> 5, + lx = tag.x - (w << 4), + sx = lx & 0x7f, + msx = 32 - sx, + h = tag.y1 - tag.y0, + x = (tag.y + tag.y0) * sw + (lx >> 5), + last; + for (var j = 0; j < h; j++) { + last = 0; + for (var i = 0; i <= w; i++) { + if (((last << msx) | (i < w ? (last = sprite[j * w + i]) >>> sx : 0)) + & board[x + i]) return true; + } + x += sw; + } + return false; +} + +function cloudBounds(bounds, d) { + var b0 = bounds[0], + b1 = bounds[1]; + if (d.x + d.x0 < b0.x) b0.x = d.x + d.x0; + if (d.y + d.y0 < b0.y) b0.y = d.y + d.y0; + if (d.x + d.x1 > b1.x) b1.x = d.x + d.x1; + if (d.y + d.y1 > b1.y) b1.y = d.y + d.y1; +} + +function collideRects(a, b) { + return a.x + a.x1 > b[0].x && a.x + a.x0 < b[1].x && a.y + a.y1 > b[0].y && a.y + a.y0 < b[1].y; +} + +function archimedeanSpiral(size) { + var e = size[0] / size[1]; + return function(t) { + return [e * (t *= .1) * Math.cos(t), t * Math.sin(t)]; + }; +} + +function rectangularSpiral(size) { + var dy = 4, + dx = dy * size[0] / size[1], + x = 0, + y = 0; + return function(t) { + var sign = t < 0 ? -1 : 1; + // See triangular numbers: T_n = n * (n + 1) / 2. + switch ((Math.sqrt(1 + 4 * sign * t) - sign) & 3) { + case 0: x += dx; break; + case 1: y += dy; break; + case 2: x -= dx; break; + default: y -= dy; break; + } + return [x, y]; + }; +} + +// TODO reuse arrays? +function zeroArray(n) { + var a = [], + i = -1; + while (++i < n) a[i] = 0; + return a; +} + +function cloudCanvas() { + return document.createElement("canvas"); +} + +function functor(d) { + return typeof d === "function" ? d : function() { return d; }; +} + +var spirals = { + archimedean: archimedeanSpiral, + rectangular: rectangularSpiral +}; + +},{"d3-dispatch":2}],2:[function(require,module,exports){ +// https://d3js.org/d3-dispatch/ Version 1.0.3. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var noop = {value: function() {}}; + +function dispatch() { + for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { + if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t); + _[t] = []; + } + return new Dispatch(_); +} + +function Dispatch(_) { + this._ = _; +} + +function parseTypenames(typenames, types) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); + if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t); + return {type: t, name: name}; + }); +} + +Dispatch.prototype = dispatch.prototype = { + constructor: Dispatch, + on: function(typename, callback) { + var _ = this._, + T = parseTypenames(typename + "", _), + t, + i = -1, + n = T.length; + + // If no callback was specified, return the callback of the given type and name. + if (arguments.length < 2) { + while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t; + return; + } + + // If a type was specified, set the callback for the given type and name. + // Otherwise, if a null callback was specified, remove callbacks of the given name. + if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback); + while (++i < n) { + if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback); + else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null); + } + + return this; + }, + copy: function() { + var copy = {}, _ = this._; + for (var t in _) copy[t] = _[t].slice(); + return new Dispatch(copy); + }, + call: function(type, that) { + if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2]; + if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); + for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); + }, + apply: function(type, that, args) { + if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); + for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); + } +}; + +function get(type, name) { + for (var i = 0, n = type.length, c; i < n; ++i) { + if ((c = type[i]).name === name) { + return c.value; + } + } +} + +function set(type, name, callback) { + for (var i = 0, n = type.length; i < n; ++i) { + if (type[i].name === name) { + type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1)); + break; + } + } + if (callback != null) type.push({name: name, value: callback}); + return type; +} + +exports.dispatch = dispatch; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}]},{},[1])(1) +}); \ No newline at end of file diff --git a/demos/fashion-mnist-training/fashion-mnist-webapp/static/js/d3.min.js b/demos/fashion-mnist-training/fashion-mnist-webapp/static/js/d3.min.js new file mode 100644 index 00000000..a75674c5 --- /dev/null +++ b/demos/fashion-mnist-training/fashion-mnist-webapp/static/js/d3.min.js @@ -0,0 +1,2 @@ +// https://d3js.org Version 5.1.0. Copyright 2018 Mike Bostock. +(function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(t.d3=t.d3||{})})(this,function(t){"use strict";function n(t,n){return tn?1:t>=n?0:NaN}function e(t){return 1===t.length&&(t=function(t){return function(e,r){return n(t(e),r)}}(t)),{left:function(n,e,r,i){for(null==r&&(r=0),null==i&&(i=n.length);r>>1;t(n[o],e)<0?r=o+1:i=o}return r},right:function(n,e,r,i){for(null==r&&(r=0),null==i&&(i=n.length);r>>1;t(n[o],e)>0?i=o:r=o+1}return r}}}function r(t,n){return[t,n]}function i(t){return null===t?NaN:+t}function o(t,n){var e,r,o=t.length,a=0,u=-1,f=0,c=0;if(null==n)for(;++u1)return c/(a-1)}function a(t,n){var e=o(t,n);return e?Math.sqrt(e):e}function u(t,n){var e,r,i,o=t.length,a=-1;if(null==n){for(;++a=e)for(r=i=e;++ae&&(r=e),i=e)for(r=i=e;++ae&&(r=e),i0)return[t];if((r=n0)for(t=Math.ceil(t/a),n=Math.floor(n/a),o=new Array(i=Math.ceil(n-t+1));++u=0?(o>=es?10:o>=rs?5:o>=is?2:1)*Math.pow(10,i):-Math.pow(10,-i)/(o>=es?10:o>=rs?5:o>=is?2:1)}function d(t,n,e){var r=Math.abs(n-t)/Math.max(0,e),i=Math.pow(10,Math.floor(Math.log(r)/Math.LN10)),o=r/i;return o>=es?i*=10:o>=rs?i*=5:o>=is&&(i*=2),n=1)return+e(t[r-1],r-1,t);var r,o=(r-1)*n,a=Math.floor(o),u=+e(t[a],a,t);return u+(+e(t[a+1],a+1,t)-u)*(o-a)}}function g(t,n){var e,r,i=t.length,o=-1;if(null==n){for(;++o=e)for(r=e;++or&&(r=e)}else for(;++o=e)for(r=e;++or&&(r=e);return r}function y(t){for(var n,e,r,i=t.length,o=-1,a=0;++o=0;)for(n=(r=t[i]).length;--n>=0;)e[--a]=r[n];return e}function _(t,n){var e,r,i=t.length,o=-1;if(null==n){for(;++o=e)for(r=e;++oe&&(r=e)}else for(;++o=e)for(r=e;++oe&&(r=e);return r}function b(t){if(!(i=t.length))return[];for(var n=-1,e=_(t,m),r=new Array(e);++n=0&&"xmlns"!==(n=t.slice(0,e))&&(t=t.slice(e+1)),ds.hasOwnProperty(n)?{space:ds[n],local:t}:t}function C(t){var n=k(t);return(n.local?function(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}:function(t){return function(){var n=this.ownerDocument,e=this.namespaceURI;return e===hs&&n.documentElement.namespaceURI===hs?n.createElement(t):n.createElementNS(e,t)}})(n)}function P(){}function z(t){return null==t?P:function(){return this.querySelector(t)}}function R(){return[]}function L(t){return null==t?R:function(){return this.querySelectorAll(t)}}function D(t){return new Array(t.length)}function U(t,n){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=n}function q(t,n,e,r,i,o){for(var a,u=0,f=n.length,c=o.length;un?1:t>=n?0:NaN}function B(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function F(t,n){return t.style.getPropertyValue(n)||B(t).getComputedStyle(t,null).getPropertyValue(n)}function I(t){return t.trim().split(/^|\s+/)}function j(t){return t.classList||new H(t)}function H(t){this._node=t,this._names=I(t.getAttribute("class")||"")}function X(t,n){for(var e=j(t),r=-1,i=n.length;++r>8&15|n>>4&240,n>>4&15|240&n,(15&n)<<4|15&n,1)):(n=Ns.exec(t))?Ct(parseInt(n[1],16)):(n=Ss.exec(t))?new Lt(n[1],n[2],n[3],1):(n=Es.exec(t))?new Lt(255*n[1]/100,255*n[2]/100,255*n[3]/100,1):(n=ks.exec(t))?Pt(n[1],n[2],n[3],n[4]):(n=Cs.exec(t))?Pt(255*n[1]/100,255*n[2]/100,255*n[3]/100,n[4]):(n=Ps.exec(t))?Dt(n[1],n[2]/100,n[3]/100,1):(n=zs.exec(t))?Dt(n[1],n[2]/100,n[3]/100,n[4]):Rs.hasOwnProperty(t)?Ct(Rs[t]):"transparent"===t?new Lt(NaN,NaN,NaN,0):null}function Ct(t){return new Lt(t>>16&255,t>>8&255,255&t,1)}function Pt(t,n,e,r){return r<=0&&(t=n=e=NaN),new Lt(t,n,e,r)}function zt(t){return t instanceof Et||(t=kt(t)),t?(t=t.rgb(),new Lt(t.r,t.g,t.b,t.opacity)):new Lt}function Rt(t,n,e,r){return 1===arguments.length?zt(t):new Lt(t,n,e,null==r?1:r)}function Lt(t,n,e,r){this.r=+t,this.g=+n,this.b=+e,this.opacity=+r}function Dt(t,n,e,r){return r<=0?t=n=e=NaN:e<=0||e>=1?t=n=NaN:n<=0&&(t=NaN),new qt(t,n,e,r)}function Ut(t,n,e,r){return 1===arguments.length?function(t){if(t instanceof qt)return new qt(t.h,t.s,t.l,t.opacity);if(t instanceof Et||(t=kt(t)),!t)return new qt;if(t instanceof qt)return t;var n=(t=t.rgb()).r/255,e=t.g/255,r=t.b/255,i=Math.min(n,e,r),o=Math.max(n,e,r),a=NaN,u=o-i,f=(o+i)/2;return u?(a=n===o?(e-r)/u+6*(e0&&f<1?0:a,new qt(a,u,f,t.opacity)}(t):new qt(t,n,e,null==r?1:r)}function qt(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function Ot(t,n,e){return 255*(t<60?n+(e-n)*t/60:t<180?e:t<240?n+(e-n)*(240-t)/60:n)}function Yt(t){if(t instanceof Ft)return new Ft(t.l,t.a,t.b,t.opacity);if(t instanceof $t){if(isNaN(t.h))return new Ft(t.l,0,0,t.opacity);var n=t.h*Ls;return new Ft(t.l,Math.cos(n)*t.c,Math.sin(n)*t.c,t.opacity)}t instanceof Lt||(t=zt(t));var e,r,i=Xt(t.r),o=Xt(t.g),a=Xt(t.b),u=It((.2225045*i+.7168786*o+.0606169*a)/qs);return i===o&&o===a?e=r=u:(e=It((.4360747*i+.3850649*o+.1430804*a)/Us),r=It((.0139322*i+.0971045*o+.7141733*a)/Os)),new Ft(116*u-16,500*(e-u),200*(u-r),t.opacity)}function Bt(t,n,e,r){return 1===arguments.length?Yt(t):new Ft(t,n,e,null==r?1:r)}function Ft(t,n,e,r){this.l=+t,this.a=+n,this.b=+e,this.opacity=+r}function It(t){return t>Is?Math.pow(t,1/3):t/Fs+Ys}function jt(t){return t>Bs?t*t*t:Fs*(t-Ys)}function Ht(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function Xt(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Gt(t){if(t instanceof $t)return new $t(t.h,t.c,t.l,t.opacity);if(t instanceof Ft||(t=Yt(t)),0===t.a&&0===t.b)return new $t(NaN,0,t.l,t.opacity);var n=Math.atan2(t.b,t.a)*Ds;return new $t(n<0?n+360:n,Math.sqrt(t.a*t.a+t.b*t.b),t.l,t.opacity)}function Vt(t,n,e,r){return 1===arguments.length?Gt(t):new $t(t,n,e,null==r?1:r)}function $t(t,n,e,r){this.h=+t,this.c=+n,this.l=+e,this.opacity=+r}function Wt(t,n,e,r){return 1===arguments.length?function(t){if(t instanceof Zt)return new Zt(t.h,t.s,t.l,t.opacity);t instanceof Lt||(t=zt(t));var n=t.r/255,e=t.g/255,r=t.b/255,i=($s*r+Gs*n-Vs*e)/($s+Gs-Vs),o=r-i,a=(Xs*(e-i)-js*o)/Hs,u=Math.sqrt(a*a+o*o)/(Xs*i*(1-i)),f=u?Math.atan2(a,o)*Ds-120:NaN;return new Zt(f<0?f+360:f,u,i,t.opacity)}(t):new Zt(t,n,e,null==r?1:r)}function Zt(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function Qt(t,n,e,r,i){var o=t*t,a=o*t;return((1-3*t+3*o-a)*n+(4-6*o+3*a)*e+(1+3*t+3*o-3*a)*r+a*i)/6}function Jt(t){var n=t.length-1;return function(e){var r=e<=0?e=0:e>=1?(e=1,n-1):Math.floor(e*n),i=t[r],o=t[r+1],a=r>0?t[r-1]:2*i-o,u=r180||e<-180?e-360*Math.round(e/360):e):tn(isNaN(t)?n:t)}function rn(t){return 1==(t=+t)?on:function(n,e){return e-n?function(t,n,e){return t=Math.pow(t,e),n=Math.pow(n,e)-t,e=1/e,function(r){return Math.pow(t+r*n,e)}}(n,e,t):tn(isNaN(n)?e:n)}}function on(t,n){var e=n-t;return e?nn(t,e):tn(isNaN(t)?n:t)}function an(t){return function(n){var e,r,i=n.length,o=new Array(i),a=new Array(i),u=new Array(i);for(e=0;eo&&(i=n.slice(o,i),u[a]?u[a]+=i:u[++a]=i),(e=e[0])===(r=r[0])?u[a]?u[a]+=r:u[++a]=r:(u[++a]=null,f.push({i:a,x:cn(e,r)})),o=ol.lastIndex;return o180?n+=360:n-t>180&&(t+=360),o.push({i:e.push(i(e)+"rotate(",null,r)-2,x:cn(t,n)})):n&&e.push(i(e)+"rotate("+n+r)}(o.rotate,a.rotate,u,f),function(t,n,e,o){t!==n?o.push({i:e.push(i(e)+"skewX(",null,r)-2,x:cn(t,n)}):n&&e.push(i(e)+"skewX("+n+r)}(o.skewX,a.skewX,u,f),function(t,n,e,r,o,a){if(t!==e||n!==r){var u=o.push(i(o)+"scale(",null,",",null,")");a.push({i:u-4,x:cn(t,e)},{i:u-2,x:cn(n,r)})}else 1===e&&1===r||o.push(i(o)+"scale("+e+","+r+")")}(o.scaleX,o.scaleY,a.scaleX,a.scaleY,u,f),o=a=null,function(t){for(var n,e=-1,r=f.length;++e=0&&n._call.call(null,t),n=n._next;--ml}function Nn(){Tl=(Al=Sl.now())+Nl,ml=xl=0;try{Tn()}finally{ml=0,function(){var t,n,e=Ks,r=1/0;for(;e;)e._call?(r>e._time&&(r=e._time),t=e,e=e._next):(n=e._next,e._next=null,e=t?t._next=n:Ks=n);tl=t,En(r)}(),Tl=0}}function Sn(){var t=Sl.now(),n=t-Al;n>Ml&&(Nl-=n,Al=t)}function En(t){if(!ml){xl&&(xl=clearTimeout(xl));t-Tl>24?(t<1/0&&(xl=setTimeout(Nn,t-Sl.now()-Nl)),wl&&(wl=clearInterval(wl))):(wl||(Al=Sl.now(),wl=setInterval(Sn,Ml)),ml=1,El(Nn))}}function kn(t,n,e){var r=new Mn;return n=null==n?0:+n,r.restart(function(e){r.stop(),t(e+n)},n,e),r}function Cn(t,n,e,r,i,o){var a=t.__transition;if(a){if(e in a)return}else t.__transition={};(function(t,n,e){function r(f){var c,s,l,h;if(e.state!==zl)return o();for(c in u)if((h=u[c]).name===e.name){if(h.state===Ll)return kn(r);h.state===Dl?(h.state=ql,h.timer.stop(),h.on.call("interrupt",t,t.__data__,h.index,h.group),delete u[c]):+cPl)throw new Error("too late; already scheduled");return e}function zn(t,n){var e=Rn(t,n);if(e.state>Rl)throw new Error("too late; already started");return e}function Rn(t,n){var e=t.__transition;if(!e||!(e=e[n]))throw new Error("transition not found");return e}function Ln(t,n){var e,r,i,o=t.__transition,a=!0;if(o){n=null==n?null:n+"";for(i in o)(e=o[i]).name===n?(r=e.state>Rl&&e.stateMath.abs(t[1]-U[1])?x=!0:m=!0),U=t,b=!0,Wn(),o()}function o(){var t;switch(y=U[0]-D[0],_=U[1]-D[1],A){case hh:case lh:T&&(y=Math.max(C-u,Math.min(z-d,y)),c=u+y,p=d+y),N&&(_=Math.max(P-l,Math.min(R-v,_)),h=l+_,g=v+_);break;case dh:T<0?(y=Math.max(C-u,Math.min(z-u,y)),c=u+y,p=d):T>0&&(y=Math.max(C-d,Math.min(z-d,y)),c=u,p=d+y),N<0?(_=Math.max(P-l,Math.min(R-l,_)),h=l+_,g=v):N>0&&(_=Math.max(P-v,Math.min(R-v,_)),h=l,g=v+_);break;case ph:T&&(c=Math.max(C,Math.min(z,u-y*T)),p=Math.max(C,Math.min(z,d+y*T))),N&&(h=Math.max(P,Math.min(R,l-_*N)),g=Math.max(P,Math.min(R,v+_*N)))}p0&&(u=c-y),N<0?v=g-_:N>0&&(l=h-_),A=hh,Y.attr("cursor",_h.selection),o());break;default:return}Wn()},!0).on("keyup.brush",function(){switch(t.event.keyCode){case 16:L&&(m=x=L=!1,o());break;case 18:A===ph&&(T<0?d=p:T>0&&(u=c),N<0?v=g:N>0&&(l=h),A=dh,o());break;case 32:A===hh&&(t.event.altKey?(T&&(d=p-y*T,u=c+y*T),N&&(v=g-_*N,l=h+_*N),A=ph):(T<0?d=p:T>0&&(u=c),N<0?v=g:N>0&&(l=h),A=dh),Y.attr("cursor",_h[M]),o());break;default:return}Wn()},!0).on("mousemove.brush",e,!0).on("mouseup.brush",a,!0);_t(t.event.view)}$n(),Ln(w),r.call(w),q.start()}}function u(){var t=this.__brush||{selection:null};return t.extent=c.apply(this,arguments),t.dim=n,t}var f,c=Jn,s=Qn,l=N(e,"start","brush","end"),h=6;return e.move=function(t,e){t.selection?t.on("start.brush",function(){i(this,arguments).beforestart().start()}).on("interrupt.brush end.brush",function(){i(this,arguments).end()}).tween("brush",function(){function t(t){a.selection=1===t&&te(c)?null:s(t),r.call(o),u.brush()}var o=this,a=o.__brush,u=i(o,arguments),f=a.selection,c=n.input("function"==typeof e?e.apply(this,arguments):e,a.extent),s=hn(f,c);return f&&c?t:t(1)}):t.each(function(){var t=arguments,o=this.__brush,a=n.input("function"==typeof e?e.apply(this,t):e,o.extent),u=i(this,t).beforestart();Ln(this),o.selection=null==a||te(a)?null:a,r.call(this),u.start().brush().end()})},o.prototype={beforestart:function(){return 1==++this.active&&(this.state.emitter=this,this.starting=!0),this},start:function(){return this.starting&&(this.starting=!1,this.emit("start")),this},brush:function(){return this.emit("brush"),this},end:function(){return 0==--this.active&&(delete this.state.emitter,this.emit("end")),this},emit:function(t){ot(new function(t,n,e){this.target=t,this.type=n,this.selection=e}(e,t,n.output(this.state.selection)),l.apply,l,[t,this.that,this.args])}},e.extent=function(t){return arguments.length?(c="function"==typeof t?t:Vn([[+t[0][0],+t[0][1]],[+t[1][0],+t[1][1]]]),e):c},e.filter=function(t){return arguments.length?(s="function"==typeof t?t:Vn(!!t),e):s},e.handleSize=function(t){return arguments.length?(h=+t,e):h},e.on=function(){var t=l.on.apply(l,arguments);return t===l?e:t},e}function ee(t){return function(){return t}}function re(){this._x0=this._y0=this._x1=this._y1=null,this._=""}function ie(){return new re}function oe(t){return t.source}function ae(t){return t.target}function ue(t){return t.radius}function fe(t){return t.startAngle}function ce(t){return t.endAngle}function se(){}function le(t,n){var e=new se;if(t instanceof se)t.each(function(t,n){e.set(n,t)});else if(Array.isArray(t)){var r,i=-1,o=t.length;if(null==n)for(;++ir!=d>r&&e<(h-c)*(r-s)/(d-s)+c&&(i=-i)}return i}(t,n[r]))return e;return 0}function xe(){}function we(){function t(t){var e=a(t);if(Array.isArray(e))e=e.slice().sort(_e);else{var r=u(t),i=r[0],o=r[1];e=d(i,o,e),e=s(Math.floor(i/e)*e,Math.floor(o/e)*e,e)}return e.map(function(e){return n(t,e)})}function n(t,n){var r=[],a=[];return function(t,n,r){function a(t){var n,i,o=[t[0][0]+u,t[0][1]+f],a=[t[1][0]+u,t[1][1]+f],c=e(o),s=e(a);(n=p[c])?(i=d[s])?(delete p[n.end],delete d[i.start],n===i?(n.ring.push(a),r(n.ring)):d[n.start]=p[i.end]={start:n.start,end:i.end,ring:n.ring.concat(i.ring)}):(delete p[n.end],n.ring.push(a),p[n.end=s]=n):(n=d[s])?(i=p[c])?(delete d[n.start],delete p[i.end],n===i?(n.ring.push(a),r(n.ring)):d[i.start]=p[n.end]={start:i.start,end:n.end,ring:i.ring.concat(n.ring)}):(delete d[n.start],n.ring.unshift(o),d[n.start=c]=n):d[c]=p[s]={start:c,end:s,ring:[o,a]}}var u,f,c,s,l,h,d=new Array,p=new Array;u=f=-1,s=t[0]>=n,Dh[s<<1].forEach(a);for(;++u=n,Dh[c|s<<1].forEach(a);Dh[s<<0].forEach(a);for(;++f=n,l=t[f*i]>=n,Dh[s<<1|l<<2].forEach(a);++u=n,h=l,l=t[f*i+u+1]>=n,Dh[c|s<<1|l<<2|h<<3].forEach(a);Dh[s|l<<3].forEach(a)}u=-1,l=t[f*i]>=n,Dh[l<<2].forEach(a);for(;++u=n,Dh[l<<2|h<<3].forEach(a);Dh[l<<3].forEach(a)}(t,n,function(e){f(e,t,n),function(t){for(var n=0,e=t.length,r=t[e-1][1]*t[0][0]-t[e-1][0]*t[0][1];++n0?r.push([e]):a.push(e)}),a.forEach(function(t){for(var n,e=0,i=r.length;e0&&a0&&u0&&r>0))throw new Error("invalid size");return i=e,o=r,t},t.thresholds=function(n){return arguments.length?(a="function"==typeof n?n:Array.isArray(n)?be(Lh.call(n)):be(n),t):a},t.smooth=function(n){return arguments.length?(f=n?r:xe,t):f===r},t}function Me(t,n,e){for(var r=t.width,i=t.height,o=1+(e<<1),a=0;a=e&&(u>=o&&(f-=t.data[u-o+a*r]),n.data[u-e+a*r]=f/Math.min(u+1,r-1+o-u,o))}function Ae(t,n,e){for(var r=t.width,i=t.height,o=1+(e<<1),a=0;a=e&&(u>=o&&(f-=t.data[a+(u-o)*r]),n.data[a+(u-e)*r]=f/Math.min(u+1,i-1+o-u,o))}function Te(t){return t[0]}function Ne(t){return t[1]}function Se(t){return new Function("d","return {"+t.map(function(t,n){return JSON.stringify(t)+": d["+n+"]"}).join(",")+"}")}function Ee(t){function n(t,n){function e(){if(c)return qh;if(s)return s=!1,Uh;var n,e,r=u;if(t.charCodeAt(r)===Oh){for(;u++=a?c=!0:(e=t.charCodeAt(u++))===Yh?s=!0:e===Bh&&(s=!0,t.charCodeAt(u)===Yh&&++u),t.slice(r+1,n-1).replace(/""/g,'"')}for(;u=(o=(v+y)/2))?v=o:y=o,(s=e>=(a=(g+_)/2))?g=a:_=a,i=d,!(d=d[l=s<<1|c]))return i[l]=p,t;if(u=+t._x.call(null,d.data),f=+t._y.call(null,d.data),n===u&&e===f)return p.next=d,i?i[l]=p:t._root=p,t;do{i=i?i[l]=new Array(4):t._root=new Array(4),(c=n>=(o=(v+y)/2))?v=o:y=o,(s=e>=(a=(g+_)/2))?g=a:_=a}while((l=s<<1|c)==(h=(f>=a)<<1|u>=o));return i[h]=d,i[l]=p,t}function Ye(t,n,e,r,i){this.node=t,this.x0=n,this.y0=e,this.x1=r,this.y1=i}function Be(t){return t[0]}function Fe(t){return t[1]}function Ie(t,n,e){var r=new je(null==n?Be:n,null==e?Fe:e,NaN,NaN,NaN,NaN);return null==t?r:r.addAll(t)}function je(t,n,e,r,i,o){this._x=t,this._y=n,this._x0=e,this._y0=r,this._x1=i,this._y1=o,this._root=void 0}function He(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.data};return n}function Xe(t){return t.x+t.vx}function Ge(t){return t.y+t.vy}function Ve(t){return t.index}function $e(t,n){var e=t.get(n);if(!e)throw new Error("missing: "+n);return e}function We(t){return t.x}function Ze(t){return t.y}function Qe(t,n){if((e=(t=n?t.toExponential(n-1):t.toExponential()).indexOf("e"))<0)return null;var e,r=t.slice(0,e);return[r.length>1?r[0]+r.slice(2):r,+t.slice(e+1)]}function Je(t){return(t=Qe(Math.abs(t)))?t[1]:NaN}function Ke(t,n){var e=Qe(t,n);if(!e)return t+"";var r=e[0],i=e[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}function tr(t){return new nr(t)}function nr(t){if(!(n=ud.exec(t)))throw new Error("invalid format: "+t);var n,e=n[1]||" ",r=n[2]||">",i=n[3]||"-",o=n[4]||"",a=!!n[5],u=n[6]&&+n[6],f=!!n[7],c=n[8]&&+n[8].slice(1),s=n[9]||"";"n"===s?(f=!0,s="g"):ad[s]||(s=""),(a||"0"===e&&"="===r)&&(a=!0,e="0",r="="),this.fill=e,this.align=r,this.sign=i,this.symbol=o,this.zero=a,this.width=u,this.comma=f,this.precision=c,this.type=s}function er(t){return t}function rr(t){function n(t){function n(t){var n,r,a,s=g,m=y;if("c"===v)m=_(t)+m,t="";else{var x=(t=+t)<0;if(t=_(Math.abs(t),p),x&&0==+t&&(x=!1),s=(x?"("===c?c:"-":"-"===c||"("===c?"":c)+s,m=("s"===v?cd[8+rd/3]:"")+m+(x&&"("===c?")":""),b)for(n=-1,r=t.length;++n(a=t.charCodeAt(n))||a>57){m=(46===a?i+t.slice(n+1):t.slice(n))+m,t=t.slice(0,n);break}}d&&!l&&(t=e(t,1/0));var w=s.length+t.length+m.length,M=w>1)+s+t+m+M.slice(w);break;default:t=M+s+t+m}return o(t)}var u=(t=tr(t)).fill,f=t.align,c=t.sign,s=t.symbol,l=t.zero,h=t.width,d=t.comma,p=t.precision,v=t.type,g="$"===s?r[0]:"#"===s&&/[boxX]/.test(v)?"0"+v.toLowerCase():"",y="$"===s?r[1]:/[%p]/.test(v)?a:"",_=ad[v],b=!v||/[defgprs%]/.test(v);return p=null==p?v?6:12:/[gprs]/.test(v)?Math.max(1,Math.min(21,p)):Math.max(0,Math.min(20,p)),n.toString=function(){return t+""},n}var e=t.grouping&&t.thousands?function(t,n){return function(e,r){for(var i=e.length,o=[],a=0,u=t[0],f=0;i>0&&u>0&&(f+u+1>r&&(u=Math.max(1,r-f)),o.push(e.substring(i-=u,i+u)),!((f+=u+1)>r));)u=t[a=(a+1)%t.length];return o.reverse().join(n)}}(t.grouping,t.thousands):er,r=t.currency,i=t.decimal,o=t.numerals?function(t){return function(n){return n.replace(/[0-9]/g,function(n){return t[+n]})}}(t.numerals):er,a=t.percent||"%";return{format:n,formatPrefix:function(t,e){var r=n((t=tr(t),t.type="f",t)),i=3*Math.max(-8,Math.min(8,Math.floor(Je(e)/3))),o=Math.pow(10,-i),a=cd[8+i/3];return function(t){return r(o*t)+a}}}}function ir(n){return fd=rr(n),t.format=fd.format,t.formatPrefix=fd.formatPrefix,fd}function or(t){return Math.max(0,-Je(Math.abs(t)))}function ar(t,n){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(Je(n)/3)))-Je(Math.abs(t)))}function ur(t,n){return t=Math.abs(t),n=Math.abs(n)-t,Math.max(0,Je(n)-Je(t))+1}function fr(){return new cr}function cr(){this.reset()}function sr(t,n,e){var r=t.s=n+e,i=r-n,o=r-i;t.t=n-o+(e-i)}function lr(t){return t>1?0:t<-1?Hd:Math.acos(t)}function hr(t){return t>1?Xd:t<-1?-Xd:Math.asin(t)}function dr(t){return(t=ip(t/2))*t}function pr(){}function vr(t,n){t&&cp.hasOwnProperty(t.type)&&cp[t.type](t,n)}function gr(t,n,e){var r,i=-1,o=t.length-e;for(n.lineStart();++i=0?1:-1,i=r*e,o=Kd(n),a=ip(n),u=pd*a,f=dd*o+u*Kd(i),c=u*r*ip(i);sp.add(Jd(c,f)),hd=t,dd=o,pd=a}function Mr(t){return[Jd(t[1],t[0]),hr(t[2])]}function Ar(t){var n=t[0],e=t[1],r=Kd(e);return[r*Kd(n),r*ip(n),ip(e)]}function Tr(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function Nr(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1]-t[1]*n[0]]}function Sr(t,n){t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]}function Er(t,n){return[t[0]*n,t[1]*n,t[2]*n]}function kr(t){var n=ap(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=n,t[1]/=n,t[2]/=n}function Cr(t,n){Md.push(Ad=[vd=t,yd=t]),n_d&&(_d=n)}function Pr(t,n){var e=Ar([t*Wd,n*Wd]);if(wd){var r=Nr(wd,e),i=Nr([r[1],-r[0],0],r);kr(i),i=Mr(i);var o,a=t-bd,u=a>0?1:-1,f=i[0]*$d*u,c=Zd(a)>180;c^(u*bd_d&&(_d=o):(f=(f+360)%360-180,c^(u*bd_d&&(_d=n))),c?tqr(vd,yd)&&(yd=t):qr(t,yd)>qr(vd,yd)&&(vd=t):yd>=vd?(tyd&&(yd=t)):t>bd?qr(vd,t)>qr(vd,yd)&&(yd=t):qr(t,yd)>qr(vd,yd)&&(vd=t)}else Md.push(Ad=[vd=t,yd=t]);n_d&&(_d=n),wd=e,bd=t}function zr(){pp.point=Pr}function Rr(){Ad[0]=vd,Ad[1]=yd,pp.point=Cr,wd=null}function Lr(t,n){if(wd){var e=t-bd;dp.add(Zd(e)>180?e+(e>0?360:-360):e)}else md=t,xd=n;hp.point(t,n),Pr(t,n)}function Dr(){hp.lineStart()}function Ur(){Lr(md,xd),hp.lineEnd(),Zd(dp)>Id&&(vd=-(yd=180)),Ad[0]=vd,Ad[1]=yd,wd=null}function qr(t,n){return(n-=t)<0?n+360:n}function Or(t,n){return t[0]-n[0]}function Yr(t,n){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:nHd?t-Vd:t<-Hd?t+Vd:t,n]}function Kr(t,n,e){return(t%=Vd)?n||e?Qr(ni(t),ei(n,e)):ni(t):n||e?ei(n,e):Jr}function ti(t){return function(n,e){return n+=t,[n>Hd?n-Vd:n<-Hd?n+Vd:n,e]}}function ni(t){var n=ti(t);return n.invert=ti(-t),n}function ei(t,n){function e(t,n){var e=Kd(n),u=Kd(t)*e,f=ip(t)*e,c=ip(n),s=c*r+u*i;return[Jd(f*o-s*a,u*r-c*i),hr(s*o+f*a)]}var r=Kd(t),i=ip(t),o=Kd(n),a=ip(n);return e.invert=function(t,n){var e=Kd(n),u=Kd(t)*e,f=ip(t)*e,c=ip(n),s=c*o-f*a;return[Jd(f*o+c*a,u*r+s*i),hr(s*r-u*i)]},e}function ri(t){function n(n){return n=t(n[0]*Wd,n[1]*Wd),n[0]*=$d,n[1]*=$d,n}return t=Kr(t[0]*Wd,t[1]*Wd,t.length>2?t[2]*Wd:0),n.invert=function(n){return n=t.invert(n[0]*Wd,n[1]*Wd),n[0]*=$d,n[1]*=$d,n},n}function ii(t,n,e,r,i,o){if(e){var a=Kd(n),u=ip(n),f=r*e;null==i?(i=n+r*Vd,o=n-f/2):(i=oi(a,i),o=oi(a,o),(r>0?io)&&(i+=r*Vd));for(var c,s=i;r>0?s>o:s1&&n.push(n.pop().concat(n.shift()))},result:function(){var e=n;return n=[],t=null,e}}}function ui(t,n){return Zd(t[0]-n[0])=0;--o)i.point((s=c[o])[0],s[1]);else r(h.x,h.p.x,-1,i);h=h.p}c=(h=h.o).z,d=!d}while(!h.v);i.lineEnd()}}}function si(t){if(n=t.length){for(var n,e,r=0,i=t[0];++r=0?1:-1,T=A*M,N=T>Hd,S=v*x;if(Sp.add(Jd(S*A*ip(T),g*w+S*Kd(T))),a+=N?M+A*Vd:M,N^d>=e^b>=e){var E=Nr(Ar(h),Ar(_));kr(E);var k=Nr(o,E);kr(k);var C=(N^M>=0?-1:1)*hr(k[2]);(r>C||r===C&&(E[0]||E[1]))&&(u+=N^M>=0?1:-1)}}return(a<-Id||a0){for(b||(i.polygonStart(),b=!0),i.lineStart(),t=0;t1&&2&o&&a.push(a.pop().concat(a.shift())),d.push(a.filter(di))}var h,d,p,v=n(i),g=ai(),_=n(g),b=!1,m={point:o,lineStart:u,lineEnd:f,polygonStart:function(){m.point=c,m.lineStart=s,m.lineEnd=l,d=[],h=[]},polygonEnd:function(){m.point=o,m.lineStart=u,m.lineEnd=f,d=y(d);var t=li(h,r);d.length?(b||(i.polygonStart(),b=!0),ci(d,pi,t,e,i)):t&&(b||(i.polygonStart(),b=!0),i.lineStart(),e(null,null,1,i),i.lineEnd()),b&&(i.polygonEnd(),b=!1),d=h=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}};return m}}function di(t){return t.length>1}function pi(t,n){return((t=t.x)[0]<0?t[1]-Xd-Id:Xd-t[1])-((n=n.x)[0]<0?n[1]-Xd-Id:Xd-n[1])}function vi(t){function n(t,n){return Kd(t)*Kd(n)>i}function e(t,n,e){var r=[1,0,0],o=Nr(Ar(t),Ar(n)),a=Tr(o,o),u=o[0],f=a-u*u;if(!f)return!e&&t;var c=i*a/f,s=-i*u/f,l=Nr(r,o),h=Er(r,c);Sr(h,Er(o,s));var d=l,p=Tr(h,d),v=Tr(d,d),g=p*p-v*(Tr(h,h)-1);if(!(g<0)){var y=ap(g),_=Er(d,(-p-y)/v);if(Sr(_,h),_=Mr(_),!e)return _;var b,m=t[0],x=n[0],w=t[1],M=n[1];x0^_[1]<(Zd(_[0]-m)Hd^(m<=_[0]&&_[0]<=x)){var N=Er(d,(-p+y)/v);return Sr(N,h),[_,Mr(N)]}}}function r(n,e){var r=a?t:Hd-t,i=0;return n<-r?i|=1:n>r&&(i|=2),e<-r?i|=4:e>r&&(i|=8),i}var i=Kd(t),o=6*Wd,a=i>0,u=Zd(i)>Id;return hi(n,function(t){var i,o,f,c,s;return{lineStart:function(){c=f=!1,s=1},point:function(l,h){var d,p=[l,h],v=n(l,h),g=a?v?0:r(l,h):v?r(l+(l<0?Hd:-Hd),h):0;if(!i&&(c=f=v)&&t.lineStart(),v!==f&&(!(d=e(i,p))||ui(i,d)||ui(p,d))&&(p[0]+=Id,p[1]+=Id,v=n(p[0],p[1])),v!==f)s=0,v?(t.lineStart(),d=e(p,i),t.point(d[0],d[1])):(d=e(i,p),t.point(d[0],d[1]),t.lineEnd()),i=d;else if(u&&i&&a^v){var y;g&o||!(y=e(p,i,!0))||(s=0,a?(t.lineStart(),t.point(y[0][0],y[0][1]),t.point(y[1][0],y[1][1]),t.lineEnd()):(t.point(y[1][0],y[1][1]),t.lineEnd(),t.lineStart(),t.point(y[0][0],y[0][1])))}!v||i&&ui(i,p)||t.point(p[0],p[1]),i=p,f=v,o=g},lineEnd:function(){f&&t.lineEnd(),i=null},clean:function(){return s|(c&&f)<<1}}},function(n,e,r,i){ii(i,t,o,r,n,e)},a?[0,-t]:[-Hd,t-Hd])}function gi(t,n,e,r){function i(i,o){return t<=i&&i<=e&&n<=o&&o<=r}function o(i,o,u,c){var s=0,l=0;if(null==i||(s=a(i,u))!==(l=a(o,u))||f(i,o)<0^u>0)do{c.point(0===s||3===s?t:e,s>1?r:n)}while((s=(s+u+4)%4)!==l);else c.point(o[0],o[1])}function a(r,i){return Zd(r[0]-t)0?0:3:Zd(r[0]-e)0?2:1:Zd(r[1]-n)0?1:0:i>0?3:2}function u(t,n){return f(t.x,n.x)}function f(t,n){var e=a(t,1),r=a(n,1);return e!==r?e-r:0===e?n[1]-t[1]:1===e?t[0]-n[0]:2===e?t[1]-n[1]:n[0]-t[0]}return function(a){function f(t,n){i(t,n)&&w.point(t,n)}function c(o,a){var u=i(o,a);if(l&&h.push([o,a]),m)d=o,p=a,v=u,m=!1,u&&(w.lineStart(),w.point(o,a));else if(u&&b)w.point(o,a);else{var f=[g=Math.max(Cp,Math.min(kp,g)),_=Math.max(Cp,Math.min(kp,_))],c=[o=Math.max(Cp,Math.min(kp,o)),a=Math.max(Cp,Math.min(kp,a))];!function(t,n,e,r,i,o){var a,u=t[0],f=t[1],c=0,s=1,l=n[0]-u,h=n[1]-f;if(a=e-u,l||!(a>0)){if(a/=l,l<0){if(a0){if(a>s)return;a>c&&(c=a)}if(a=i-u,l||!(a<0)){if(a/=l,l<0){if(a>s)return;a>c&&(c=a)}else if(l>0){if(a0)){if(a/=h,h<0){if(a0){if(a>s)return;a>c&&(c=a)}if(a=o-f,h||!(a<0)){if(a/=h,h<0){if(a>s)return;a>c&&(c=a)}else if(h>0){if(a0&&(t[0]=u+c*l,t[1]=f+c*h),s<1&&(n[0]=u+s*l,n[1]=f+s*h),!0}}}}}(f,c,t,n,e,r)?u&&(w.lineStart(),w.point(o,a),x=!1):(b||(w.lineStart(),w.point(f[0],f[1])),w.point(c[0],c[1]),u||w.lineEnd(),x=!1)}g=o,_=a,b=u}var s,l,h,d,p,v,g,_,b,m,x,w=a,M=ai(),A={point:f,lineStart:function(){A.point=c,l&&l.push(h=[]),m=!0,b=!1,g=_=NaN},lineEnd:function(){s&&(c(d,p),v&&b&&M.rejoin(),s.push(M.result())),A.point=f,b&&w.lineEnd()},polygonStart:function(){w=M,s=[],l=[],x=!0},polygonEnd:function(){var n=function(){for(var n=0,e=0,i=l.length;er&&(h-o)*(r-a)>(d-a)*(t-o)&&++n:d<=r&&(h-o)*(r-a)<(d-a)*(t-o)&&--n;return n}(),e=x&&n,i=(s=y(s)).length;(e||i)&&(a.polygonStart(),e&&(a.lineStart(),o(null,null,1,a),a.lineEnd()),i&&ci(s,u,n,o,a),a.polygonEnd()),w=a,s=l=h=null}};return A}}function yi(){zp.point=zp.lineEnd=pr}function _i(t,n){gp=t*=Wd,yp=ip(n*=Wd),_p=Kd(n),zp.point=bi}function bi(t,n){t*=Wd;var e=ip(n*=Wd),r=Kd(n),i=Zd(t-gp),o=Kd(i),a=r*ip(i),u=_p*e-yp*r*o,f=yp*e+_p*r*o;Pp.add(Jd(ap(a*a+u*u),f)),gp=t,yp=e,_p=r}function mi(t){return Pp.reset(),_r(t,zp),+Pp}function xi(t,n){return Rp[0]=t,Rp[1]=n,mi(Lp)}function wi(t,n){return!(!t||!Up.hasOwnProperty(t.type))&&Up[t.type](t,n)}function Mi(t,n){return 0===xi(t,n)}function Ai(t,n){var e=xi(t[0],t[1]);return xi(t[0],n)+xi(n,t[1])<=e+Id}function Ti(t,n){return!!li(t.map(Ni),Si(n))}function Ni(t){return(t=t.map(Si)).pop(),t}function Si(t){return[t[0]*Wd,t[1]*Wd]}function Ei(t,n,e){var r=s(t,n-Id,e).concat(n);return function(t){return r.map(function(n){return[t,n]})}}function ki(t,n,e){var r=s(t,n-Id,e).concat(n);return function(t){return r.map(function(n){return[n,t]})}}function Ci(){function t(){return{type:"MultiLineString",coordinates:n()}}function n(){return s(tp(o/y)*y,i,y).map(d).concat(s(tp(c/_)*_,f,_).map(p)).concat(s(tp(r/v)*v,e,v).filter(function(t){return Zd(t%y)>Id}).map(l)).concat(s(tp(u/g)*g,a,g).filter(function(t){return Zd(t%_)>Id}).map(h))}var e,r,i,o,a,u,f,c,l,h,d,p,v=10,g=v,y=90,_=360,b=2.5;return t.lines=function(){return n().map(function(t){return{type:"LineString",coordinates:t}})},t.outline=function(){return{type:"Polygon",coordinates:[d(o).concat(p(f).slice(1),d(i).reverse().slice(1),p(c).reverse().slice(1))]}},t.extent=function(n){return arguments.length?t.extentMajor(n).extentMinor(n):t.extentMinor()},t.extentMajor=function(n){return arguments.length?(o=+n[0][0],i=+n[1][0],c=+n[0][1],f=+n[1][1],o>i&&(n=o,o=i,i=n),c>f&&(n=c,c=f,f=n),t.precision(b)):[[o,c],[i,f]]},t.extentMinor=function(n){return arguments.length?(r=+n[0][0],e=+n[1][0],u=+n[0][1],a=+n[1][1],r>e&&(n=r,r=e,e=n),u>a&&(n=u,u=a,a=n),t.precision(b)):[[r,u],[e,a]]},t.step=function(n){return arguments.length?t.stepMajor(n).stepMinor(n):t.stepMinor()},t.stepMajor=function(n){return arguments.length?(y=+n[0],_=+n[1],t):[y,_]},t.stepMinor=function(n){return arguments.length?(v=+n[0],g=+n[1],t):[v,g]},t.precision=function(n){return arguments.length?(b=+n,l=Ei(u,a,90),h=ki(r,e,b),d=Ei(c,f,90),p=ki(o,i,b),t):b},t.extentMajor([[-180,-90+Id],[180,90-Id]]).extentMinor([[-180,-80-Id],[180,80+Id]])}function Pi(t){return t}function zi(){Yp.point=Ri}function Ri(t,n){Yp.point=Li,bp=xp=t,mp=wp=n}function Li(t,n){Op.add(wp*t-xp*n),xp=t,wp=n}function Di(){Li(bp,mp)}function Ui(t,n){Xp+=t,Gp+=n,++Vp}function qi(){tv.point=Oi}function Oi(t,n){tv.point=Yi,Ui(Tp=t,Np=n)}function Yi(t,n){var e=t-Tp,r=n-Np,i=ap(e*e+r*r);$p+=i*(Tp+t)/2,Wp+=i*(Np+n)/2,Zp+=i,Ui(Tp=t,Np=n)}function Bi(){tv.point=Ui}function Fi(){tv.point=ji}function Ii(){Hi(Mp,Ap)}function ji(t,n){tv.point=Hi,Ui(Mp=Tp=t,Ap=Np=n)}function Hi(t,n){var e=t-Tp,r=n-Np,i=ap(e*e+r*r);$p+=i*(Tp+t)/2,Wp+=i*(Np+n)/2,Zp+=i,Qp+=(i=Np*t-Tp*n)*(Tp+t),Jp+=i*(Np+n),Kp+=3*i,Ui(Tp=t,Np=n)}function Xi(t){this._context=t}function Gi(t,n){uv.point=Vi,ev=iv=t,rv=ov=n}function Vi(t,n){iv-=t,ov-=n,av.add(ap(iv*iv+ov*ov)),iv=t,ov=n}function $i(){this._string=[]}function Wi(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" 0 1,1 0,"+2*t+"z"}function Zi(t){return function(n){var e=new Qi;for(var r in t)e[r]=t[r];return e.stream=n,e}}function Qi(){}function Ji(t,n,e){var r=t.clipExtent&&t.clipExtent();return t.scale(150).translate([0,0]),null!=r&&t.clipExtent(null),_r(e,t.stream(Hp)),n(Hp.result()),null!=r&&t.clipExtent(r),t}function Ki(t,n,e){return Ji(t,function(e){var r=n[1][0]-n[0][0],i=n[1][1]-n[0][1],o=Math.min(r/(e[1][0]-e[0][0]),i/(e[1][1]-e[0][1])),a=+n[0][0]+(r-o*(e[1][0]+e[0][0]))/2,u=+n[0][1]+(i-o*(e[1][1]+e[0][1]))/2;t.scale(150*o).translate([a,u])},e)}function to(t,n,e){return Ki(t,[[0,0],n],e)}function no(t,n,e){return Ji(t,function(e){var r=+n,i=r/(e[1][0]-e[0][0]),o=(r-i*(e[1][0]+e[0][0]))/2,a=-i*e[0][1];t.scale(150*i).translate([o,a])},e)}function eo(t,n,e){return Ji(t,function(e){var r=+n,i=r/(e[1][1]-e[0][1]),o=-i*e[0][0],a=(r-i*(e[1][1]+e[0][1]))/2;t.scale(150*i).translate([o,a])},e)}function ro(t,n){return+n?function(t,n){function e(r,i,o,a,u,f,c,s,l,h,d,p,v,g){var y=c-r,_=s-i,b=y*y+_*_;if(b>4*n&&v--){var m=a+h,x=u+d,w=f+p,M=ap(m*m+x*x+w*w),A=hr(w/=M),T=Zd(Zd(w)-1)n||Zd((y*k+_*C)/b-.5)>.3||a*h+u*d+f*p2?t[2]%360*Wd:0,e()):[b*$d,m*$d,x*$d]},n.angle=function(t){return arguments.length?(w=t%360*Wd,e()):w*$d},n.precision=function(t){return arguments.length?(c=ro(s,S=t*t),r()):ap(S)},n.fitExtent=function(t,e){return Ki(n,t,e)},n.fitSize=function(t,e){return to(n,t,e)},n.fitWidth=function(t,e){return no(n,t,e)},n.fitHeight=function(t,e){return eo(n,t,e)},function(){return i=t.apply(this,arguments),n.invert=i.invert&&function(t){return(t=l.invert(t[0],t[1]))&&[t[0]*$d,t[1]*$d]},e()}}function uo(t){var n=0,e=Hd/3,r=ao(t),i=r(n,e);return i.parallels=function(t){return arguments.length?r(n=t[0]*Wd,e=t[1]*Wd):[n*$d,e*$d]},i}function fo(t,n){function e(t,n){var e=ap(o-2*i*ip(n))/i;return[e*ip(t*=i),a-e*Kd(t)]}var r=ip(t),i=(r+ip(n))/2;if(Zd(i)0?n<-Xd+Id&&(n=-Xd+Id):n>Xd-Id&&(n=Xd-Id);var e=o/rp(go(n),i);return[e*ip(i*t),o-e*Kd(i*t)]}var r=Kd(t),i=t===n?ip(t):ep(r/Kd(n))/ep(go(n)/go(t)),o=r*rp(go(t),i)/i;return i?(e.invert=function(t,n){var e=o-n,r=op(i)*ap(t*t+e*e);return[Jd(t,Zd(e))/i*op(e),2*Qd(rp(o/r,1/i))-Xd]},e):po}function _o(t,n){return[t,n]}function bo(t,n){function e(t,n){var e=o-n,r=i*t;return[e*ip(r),o-e*Kd(r)]}var r=Kd(t),i=t===n?ip(t):(r-Kd(n))/(n-t),o=r/i+t;return Zd(i)=0;)n+=e[r].value;else n=1;t.value=n}function Co(t,n){var e,r,i,o,a,u=new Lo(t),f=+t.value&&(u.value=t.value),c=[u];for(null==n&&(n=Po);e=c.pop();)if(f&&(e.value=+e.data.value),(i=n(e.data))&&(a=i.length))for(e.children=new Array(a),o=a-1;o>=0;--o)c.push(r=e.children[o]=new Lo(i[o])),r.parent=e,r.depth=e.depth+1;return u.eachBefore(Ro)}function Po(t){return t.children}function zo(t){t.data=t.data.data}function Ro(t){var n=0;do{t.height=n}while((t=t.parent)&&t.height<++n)}function Lo(t){this.data=t,this.depth=this.height=0,this.parent=null}function Do(t){for(var n,e,r=0,i=(t=function(t){for(var n,e,r=t.length;r;)e=Math.random()*r--|0,n=t[r],t[r]=t[e],t[e]=n;return t}(dv.call(t))).length,o=[];r0&&e*e>r*r+i*i}function Oo(t,n){for(var e=0;e(a*=a)?(r=(c+a-i)/(2*c),o=Math.sqrt(Math.max(0,a/c-r*r)),e.x=t.x-r*u-o*f,e.y=t.y-r*f+o*u):(r=(c+i-a)/(2*c),o=Math.sqrt(Math.max(0,i/c-r*r)),e.x=n.x+r*u-o*f,e.y=n.y+r*f+o*u)):(e.x=n.x+e.r,e.y=n.y)}function Io(t,n){var e=t.r+n.r-1e-6,r=n.x-t.x,i=n.y-t.y;return e>0&&e*e>r*r+i*i}function jo(t){var n=t._,e=t.next._,r=n.r+e.r,i=(n.x*e.r+e.x*n.r)/r,o=(n.y*e.r+e.y*n.r)/r;return i*i+o*o}function Ho(t){this._=t,this.next=null,this.previous=null}function Xo(t){if(!(i=t.length))return 0;var n,e,r,i,o,a,u,f,c,s,l;if(n=t[0],n.x=0,n.y=0,!(i>1))return n.r;if(e=t[1],n.x=-e.r,e.x=n.r,e.y=0,!(i>2))return n.r+e.r;Fo(e,n,r=t[2]),n=new Ho(n),e=new Ho(e),r=new Ho(r),n.next=r.previous=e,e.next=n.previous=r,r.next=e.previous=n;t:for(u=3;uh&&(h=u),g=s*s*v,(d=Math.max(h/g,g/l))>p){s-=u;break}p=d}y.push(a={value:s,dice:f1&&la(t[e[r-2]],t[e[r-1]],t[i])<=0;)--r;e[r++]=i}return e.slice(0,r)}function pa(){return Math.random()}function va(t){function n(n){var o=n+"",a=e.get(o);if(!a){if(i!==kv)return i;e.set(o,a=r.push(n))}return t[(a-1)%t.length]}var e=le(),r=[],i=kv;return t=null==t?[]:Ev.call(t),n.domain=function(t){if(!arguments.length)return r.slice();r=[],e=le();for(var i,o,a=-1,u=t.length;++a2?wa:xa,o=a=null,r}function r(n){return(o||(o=i(u,f,s?function(t){return function(n,e){var r=t(n=+n,e=+e);return function(t){return t<=n?0:t>=e?1:r(t)}}}(t):t,c)))(+n)}var i,o,a,u=Cv,f=Cv,c=hn,s=!1;return r.invert=function(t){return(a||(a=i(f,u,ma,s?function(t){return function(n,e){var r=t(n=+n,e=+e);return function(t){return t<=0?n:t>=1?e:r(t)}}}(n):n)))(+t)},r.domain=function(t){return arguments.length?(u=Sv.call(t,ba),e()):u.slice()},r.range=function(t){return arguments.length?(f=Ev.call(t),e()):f.slice()},r.rangeRound=function(t){return f=Ev.call(t),c=dn,e()},r.clamp=function(t){return arguments.length?(s=!!t,e()):s},r.interpolate=function(t){return arguments.length?(c=t,e()):c},e()}function Ta(n){var e=n.domain;return n.ticks=function(t){var n=e();return l(n[0],n[n.length-1],null==t?10:t)},n.tickFormat=function(n,r){return function(n,e,r){var i,o=n[0],a=n[n.length-1],u=d(o,a,null==e?10:e);switch((r=tr(null==r?",f":r)).type){case"s":var f=Math.max(Math.abs(o),Math.abs(a));return null!=r.precision||isNaN(i=ar(u,f))||(r.precision=i),t.formatPrefix(r,f);case"":case"e":case"g":case"p":case"r":null!=r.precision||isNaN(i=ur(u,Math.max(Math.abs(o),Math.abs(a))))||(r.precision=i-("e"===r.type));break;case"f":case"%":null!=r.precision||isNaN(i=or(u))||(r.precision=i-2*("%"===r.type))}return t.format(r)}(e(),n,r)},n.nice=function(t){null==t&&(t=10);var r,i=e(),o=0,a=i.length-1,u=i[o],f=i[a];return f0?r=h(u=Math.floor(u/r)*r,f=Math.ceil(f/r)*r,t):r<0&&(r=h(u=Math.ceil(u*r)/r,f=Math.floor(f*r)/r,t)),r>0?(i[o]=Math.floor(u/r)*r,i[a]=Math.ceil(f/r)*r,e(i)):r<0&&(i[o]=Math.ceil(u*r)/r,i[a]=Math.floor(f*r)/r,e(i)),n},n}function Na(){var t=Aa(ma,cn);return t.copy=function(){return Ma(t,Na())},Ta(t)}function Sa(){function t(t){return+t}var n=[0,1];return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=Sv.call(e,ba),t):n.slice()},t.copy=function(){return Sa().domain(n)},Ta(t)}function Ea(t,n){var e,r=0,i=(t=t.slice()).length-1,o=t[r],a=t[i];return a0){for(;df)break;g.push(h)}}else for(;d=1;--s)if(!((h=c*s)f)break;g.push(h)}}else g=l(d,p,Math.min(p-d,v)).map(a);return n?g.reverse():g},e.tickFormat=function(n,r){if(null==r&&(r=10===i?".0e":","),"function"!=typeof r&&(r=t.format(r)),n===1/0)return r;null==n&&(n=10);var u=Math.max(1,i*n/e.ticks().length);return function(t){var n=t/a(Math.round(o(t)));return n*i0?o[n-1]:r[0],n=i?[o[i-1],r]:[o[n-1],o[n]]},t.copy=function(){return Ya().domain([e,r]).range(a)},Ta(t)}function Ba(){function t(t){if(t<=t)return e[Qc(n,t,0,r)]}var n=[.5],e=[0,1],r=1;return t.domain=function(i){return arguments.length?(n=Ev.call(i),r=Math.min(n.length,e.length-1),t):n.slice()},t.range=function(i){return arguments.length?(e=Ev.call(i),r=Math.min(n.length,e.length-1),t):e.slice()},t.invertExtent=function(t){var r=e.indexOf(t);return[n[r-1],n[r]]},t.copy=function(){return Ba().domain(n).range(e)},t}function Fa(t,n,e,r){function i(n){return t(n=new Date(+n)),n}return i.floor=i,i.ceil=function(e){return t(e=new Date(e-1)),n(e,1),t(e),e},i.round=function(t){var n=i(t),e=i.ceil(t);return t-n0))return u;do{u.push(a=new Date(+e)),n(e,o),t(e)}while(a=n)for(;t(n),!e(n);)n.setTime(n-1)},function(t,r){if(t>=t)if(r<0)for(;++r<=0;)for(;n(t,-1),!e(t););else for(;--r>=0;)for(;n(t,1),!e(t););})},e&&(i.count=function(n,r){return Pv.setTime(+n),zv.setTime(+r),t(Pv),t(zv),Math.floor(e(Pv,zv))},i.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?function(n){return r(n)%t==0}:function(n){return i.count(0,n)%t==0}):i:null}),i}function Ia(t){return Fa(function(n){n.setDate(n.getDate()-(n.getDay()+7-t)%7),n.setHours(0,0,0,0)},function(t,n){t.setDate(t.getDate()+7*n)},function(t,n){return(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*Dv)/Uv})}function ja(t){return Fa(function(n){n.setUTCDate(n.getUTCDate()-(n.getUTCDay()+7-t)%7),n.setUTCHours(0,0,0,0)},function(t,n){t.setUTCDate(t.getUTCDate()+7*n)},function(t,n){return(n-t)/Uv})}function Ha(t){if(0<=t.y&&t.y<100){var n=new Date(-1,t.m,t.d,t.H,t.M,t.S,t.L);return n.setFullYear(t.y),n}return new Date(t.y,t.m,t.d,t.H,t.M,t.S,t.L)}function Xa(t){if(0<=t.y&&t.y<100){var n=new Date(Date.UTC(-1,t.m,t.d,t.H,t.M,t.S,t.L));return n.setUTCFullYear(t.y),n}return new Date(Date.UTC(t.y,t.m,t.d,t.H,t.M,t.S,t.L))}function Ga(t){return{y:t,m:0,d:1,H:0,M:0,S:0,L:0}}function Va(t){function n(t,n){return function(e){var r,i,o,a=[],u=-1,f=0,c=t.length;for(e instanceof Date||(e=new Date(+e));++u53)return null;"w"in a||(a.w=1),"Z"in a?(i=(o=(i=Xa(Ga(a.y))).getUTCDay())>4||0===o?gg.ceil(i):gg(i),i=dg.offset(i,7*(a.V-1)),a.y=i.getUTCFullYear(),a.m=i.getUTCMonth(),a.d=i.getUTCDate()+(a.w+6)%7):(i=(o=(i=n(Ga(a.y))).getDay())>4||0===o?Gv.ceil(i):Gv(i),i=jv.offset(i,7*(a.V-1)),a.y=i.getFullYear(),a.m=i.getMonth(),a.d=i.getDate()+(a.w+6)%7)}else("W"in a||"U"in a)&&("w"in a||(a.w="u"in a?a.u%7:"W"in a?1:0),o="Z"in a?Xa(Ga(a.y)).getUTCDay():n(Ga(a.y)).getDay(),a.m=0,a.d="W"in a?(a.w+6)%7+7*a.W-(o+5)%7:a.w+7*a.U-(o+6)%7);return"Z"in a?(a.H+=a.Z/100|0,a.M+=a.Z%100,Xa(a)):n(a)}}function r(t,n,e,r){for(var i,o,a=0,u=n.length,f=e.length;a=f)return-1;if(37===(i=n.charCodeAt(a++))){if(i=n.charAt(a++),!(o=A[i in Lg?n.charAt(a++):i])||(r=o(t,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}var i=t.dateTime,o=t.date,a=t.time,u=t.periods,f=t.days,c=t.shortDays,s=t.months,l=t.shortMonths,h=Za(u),d=Qa(u),p=Za(f),v=Qa(f),g=Za(c),y=Qa(c),_=Za(s),b=Qa(s),m=Za(l),x=Qa(l),w={a:function(t){return c[t.getDay()]},A:function(t){return f[t.getDay()]},b:function(t){return l[t.getMonth()]},B:function(t){return s[t.getMonth()]},c:null,d:yu,e:yu,f:wu,H:_u,I:bu,j:mu,L:xu,m:Mu,M:Au,p:function(t){return u[+(t.getHours()>=12)]},Q:Ju,s:Ku,S:Tu,u:Nu,U:Su,V:Eu,w:ku,W:Cu,x:null,X:null,y:Pu,Y:zu,Z:Ru,"%":Qu},M={a:function(t){return c[t.getUTCDay()]},A:function(t){return f[t.getUTCDay()]},b:function(t){return l[t.getUTCMonth()]},B:function(t){return s[t.getUTCMonth()]},c:null,d:Lu,e:Lu,f:Yu,H:Du,I:Uu,j:qu,L:Ou,m:Bu,M:Fu,p:function(t){return u[+(t.getUTCHours()>=12)]},Q:Ju,s:Ku,S:Iu,u:ju,U:Hu,V:Xu,w:Gu,W:Vu,x:null,X:null,y:$u,Y:Wu,Z:Zu,"%":Qu},A={a:function(t,n,e){var r=g.exec(n.slice(e));return r?(t.w=y[r[0].toLowerCase()],e+r[0].length):-1},A:function(t,n,e){var r=p.exec(n.slice(e));return r?(t.w=v[r[0].toLowerCase()],e+r[0].length):-1},b:function(t,n,e){var r=m.exec(n.slice(e));return r?(t.m=x[r[0].toLowerCase()],e+r[0].length):-1},B:function(t,n,e){var r=_.exec(n.slice(e));return r?(t.m=b[r[0].toLowerCase()],e+r[0].length):-1},c:function(t,n,e){return r(t,i,n,e)},d:uu,e:uu,f:du,H:cu,I:cu,j:fu,L:hu,m:au,M:su,p:function(t,n,e){var r=h.exec(n.slice(e));return r?(t.p=d[r[0].toLowerCase()],e+r[0].length):-1},Q:vu,s:gu,S:lu,u:Ka,U:tu,V:nu,w:Ja,W:eu,x:function(t,n,e){return r(t,o,n,e)},X:function(t,n,e){return r(t,a,n,e)},y:iu,Y:ru,Z:ou,"%":pu};return w.x=n(o,w),w.X=n(a,w),w.c=n(i,w),M.x=n(o,M),M.X=n(a,M),M.c=n(i,M),{format:function(t){var e=n(t+="",w);return e.toString=function(){return t},e},parse:function(t){var n=e(t+="",Ha);return n.toString=function(){return t},n},utcFormat:function(t){var e=n(t+="",M);return e.toString=function(){return t},e},utcParse:function(t){var n=e(t,Xa);return n.toString=function(){return t},n}}}function $a(t,n,e){var r=t<0?"-":"",i=(r?-t:t)+"",o=i.length;return r+(o68?1900:2e3),e+r[0].length):-1}function ou(t,n,e){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(n.slice(e,e+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),e+r[0].length):-1}function au(t,n,e){var r=Dg.exec(n.slice(e,e+2));return r?(t.m=r[0]-1,e+r[0].length):-1}function uu(t,n,e){var r=Dg.exec(n.slice(e,e+2));return r?(t.d=+r[0],e+r[0].length):-1}function fu(t,n,e){var r=Dg.exec(n.slice(e,e+3));return r?(t.m=0,t.d=+r[0],e+r[0].length):-1}function cu(t,n,e){var r=Dg.exec(n.slice(e,e+2));return r?(t.H=+r[0],e+r[0].length):-1}function su(t,n,e){var r=Dg.exec(n.slice(e,e+2));return r?(t.M=+r[0],e+r[0].length):-1}function lu(t,n,e){var r=Dg.exec(n.slice(e,e+2));return r?(t.S=+r[0],e+r[0].length):-1}function hu(t,n,e){var r=Dg.exec(n.slice(e,e+3));return r?(t.L=+r[0],e+r[0].length):-1}function du(t,n,e){var r=Dg.exec(n.slice(e,e+6));return r?(t.L=Math.floor(r[0]/1e3),e+r[0].length):-1}function pu(t,n,e){var r=Ug.exec(n.slice(e,e+1));return r?e+r[0].length:-1}function vu(t,n,e){var r=Dg.exec(n.slice(e));return r?(t.Q=+r[0],e+r[0].length):-1}function gu(t,n,e){var r=Dg.exec(n.slice(e));return r?(t.Q=1e3*+r[0],e+r[0].length):-1}function yu(t,n){return $a(t.getDate(),n,2)}function _u(t,n){return $a(t.getHours(),n,2)}function bu(t,n){return $a(t.getHours()%12||12,n,2)}function mu(t,n){return $a(1+jv.count(ug(t),t),n,3)}function xu(t,n){return $a(t.getMilliseconds(),n,3)}function wu(t,n){return xu(t,n)+"000"}function Mu(t,n){return $a(t.getMonth()+1,n,2)}function Au(t,n){return $a(t.getMinutes(),n,2)}function Tu(t,n){return $a(t.getSeconds(),n,2)}function Nu(t){var n=t.getDay();return 0===n?7:n}function Su(t,n){return $a(Xv.count(ug(t),t),n,2)}function Eu(t,n){var e=t.getDay();return t=e>=4||0===e?Wv(t):Wv.ceil(t),$a(Wv.count(ug(t),t)+(4===ug(t).getDay()),n,2)}function ku(t){return t.getDay()}function Cu(t,n){return $a(Gv.count(ug(t),t),n,2)}function Pu(t,n){return $a(t.getFullYear()%100,n,2)}function zu(t,n){return $a(t.getFullYear()%1e4,n,4)}function Ru(t){var n=t.getTimezoneOffset();return(n>0?"-":(n*=-1,"+"))+$a(n/60|0,"0",2)+$a(n%60,"0",2)}function Lu(t,n){return $a(t.getUTCDate(),n,2)}function Du(t,n){return $a(t.getUTCHours(),n,2)}function Uu(t,n){return $a(t.getUTCHours()%12||12,n,2)}function qu(t,n){return $a(1+dg.count(Pg(t),t),n,3)}function Ou(t,n){return $a(t.getUTCMilliseconds(),n,3)}function Yu(t,n){return Ou(t,n)+"000"}function Bu(t,n){return $a(t.getUTCMonth()+1,n,2)}function Fu(t,n){return $a(t.getUTCMinutes(),n,2)}function Iu(t,n){return $a(t.getUTCSeconds(),n,2)}function ju(t){var n=t.getUTCDay();return 0===n?7:n}function Hu(t,n){return $a(vg.count(Pg(t),t),n,2)}function Xu(t,n){var e=t.getUTCDay();return t=e>=4||0===e?bg(t):bg.ceil(t),$a(bg.count(Pg(t),t)+(4===Pg(t).getUTCDay()),n,2)}function Gu(t){return t.getUTCDay()}function Vu(t,n){return $a(gg.count(Pg(t),t),n,2)}function $u(t,n){return $a(t.getUTCFullYear()%100,n,2)}function Wu(t,n){return $a(t.getUTCFullYear()%1e4,n,4)}function Zu(){return"+0000"}function Qu(){return"%"}function Ju(t){return+t}function Ku(t){return Math.floor(+t/1e3)}function tf(n){return zg=Va(n),t.timeFormat=zg.format,t.timeParse=zg.parse,t.utcFormat=zg.utcFormat,t.utcParse=zg.utcParse,zg}function nf(t){return new Date(t)}function ef(t){return t instanceof Date?+t:+new Date(+t)}function rf(t,n,r,i,o,a,u,f,c){function s(e){return(u(e)=1?m_:t<=-1?-m_:Math.asin(t)}function lf(t){return t.innerRadius}function hf(t){return t.outerRadius}function df(t){return t.startAngle}function pf(t){return t.endAngle}function vf(t){return t&&t.padAngle}function gf(t,n,e,r,i,o,a){var u=t-e,f=n-r,c=(a?o:-o)/y_(u*u+f*f),s=c*f,l=-c*u,h=t+s,d=n+l,p=e+s,v=r+l,g=(h+p)/2,y=(d+v)/2,_=p-h,b=v-d,m=_*_+b*b,x=i-o,w=h*v-p*d,M=(b<0?-1:1)*y_(p_(0,x*x*m-w*w)),A=(w*b-_*M)/m,T=(-w*_-b*M)/m,N=(w*b+_*M)/m,S=(-w*_+b*M)/m,E=A-g,k=T-y,C=N-g,P=S-y;return E*E+k*k>C*C+P*P&&(A=N,T=S),{cx:A,cy:T,x01:-s,y01:-l,x11:A*(i/x-1),y11:T*(i/x-1)}}function yf(t){this._context=t}function _f(t){return new yf(t)}function bf(t){return t[0]}function mf(t){return t[1]}function xf(){function t(t){var u,f,c,s=t.length,l=!1;for(null==i&&(a=o(c=ie())),u=0;u<=s;++u)!(u=s;--l)c.point(g[l],y[l]);c.lineEnd(),c.areaEnd()}v&&(g[n]=+e(h,n,t),y[n]=+i(h,n,t),c.point(r?+r(h,n,t):g[n],o?+o(h,n,t):y[n]))}if(d)return c=null,d+""||null}function n(){return xf().defined(a).curve(f).context(u)}var e=bf,r=null,i=cf(0),o=mf,a=cf(!0),u=null,f=_f,c=null;return t.x=function(n){return arguments.length?(e="function"==typeof n?n:cf(+n),r=null,t):e},t.x0=function(n){return arguments.length?(e="function"==typeof n?n:cf(+n),t):e},t.x1=function(n){return arguments.length?(r=null==n?null:"function"==typeof n?n:cf(+n),t):r},t.y=function(n){return arguments.length?(i="function"==typeof n?n:cf(+n),o=null,t):i},t.y0=function(n){return arguments.length?(i="function"==typeof n?n:cf(+n),t):i},t.y1=function(n){return arguments.length?(o=null==n?null:"function"==typeof n?n:cf(+n),t):o},t.lineX0=t.lineY0=function(){return n().x(e).y(i)},t.lineY1=function(){return n().x(e).y(o)},t.lineX1=function(){return n().x(r).y(i)},t.defined=function(n){return arguments.length?(a="function"==typeof n?n:cf(!!n),t):a},t.curve=function(n){return arguments.length?(f=n,null!=u&&(c=f(u)),t):f},t.context=function(n){return arguments.length?(null==n?u=c=null:c=f(u=n),t):u},t}function Mf(t,n){return nt?1:n>=t?0:NaN}function Af(t){return t}function Tf(t){this._curve=t}function Nf(t){function n(n){return new Tf(t(n))}return n._curve=t,n}function Sf(t){var n=t.curve;return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t.curve=function(t){return arguments.length?n(Nf(t)):n()._curve},t}function Ef(){return Sf(xf().curve(w_))}function kf(){var t=wf().curve(w_),n=t.curve,e=t.lineX0,r=t.lineX1,i=t.lineY0,o=t.lineY1;return t.angle=t.x,delete t.x,t.startAngle=t.x0,delete t.x0,t.endAngle=t.x1,delete t.x1,t.radius=t.y,delete t.y,t.innerRadius=t.y0,delete t.y0,t.outerRadius=t.y1,delete t.y1,t.lineStartAngle=function(){return Sf(e())},delete t.lineX0,t.lineEndAngle=function(){return Sf(r())},delete t.lineX1,t.lineInnerRadius=function(){return Sf(i())},delete t.lineY0,t.lineOuterRadius=function(){return Sf(o())},delete t.lineY1,t.curve=function(t){return arguments.length?n(Nf(t)):n()._curve},t}function Cf(t,n){return[(n=+n)*Math.cos(t-=Math.PI/2),n*Math.sin(t)]}function Pf(t){return t.source}function zf(t){return t.target}function Rf(t){function n(){var n,u=M_.call(arguments),f=e.apply(this,u),c=r.apply(this,u);if(a||(a=n=ie()),t(a,+i.apply(this,(u[0]=f,u)),+o.apply(this,u),+i.apply(this,(u[0]=c,u)),+o.apply(this,u)),n)return a=null,n+""||null}var e=Pf,r=zf,i=bf,o=mf,a=null;return n.source=function(t){return arguments.length?(e=t,n):e},n.target=function(t){return arguments.length?(r=t,n):r},n.x=function(t){return arguments.length?(i="function"==typeof t?t:cf(+t),n):i},n.y=function(t){return arguments.length?(o="function"==typeof t?t:cf(+t),n):o},n.context=function(t){return arguments.length?(a=null==t?null:t,n):a},n}function Lf(t,n,e,r,i){t.moveTo(n,e),t.bezierCurveTo(n=(n+r)/2,e,n,i,r,i)}function Df(t,n,e,r,i){t.moveTo(n,e),t.bezierCurveTo(n,e=(e+i)/2,r,e,r,i)}function Uf(t,n,e,r,i){var o=Cf(n,e),a=Cf(n,e=(e+i)/2),u=Cf(r,e),f=Cf(r,i);t.moveTo(o[0],o[1]),t.bezierCurveTo(a[0],a[1],u[0],u[1],f[0],f[1])}function qf(){}function Of(t,n,e){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+n)/6,(t._y0+4*t._y1+e)/6)}function Yf(t){this._context=t}function Bf(t){this._context=t}function Ff(t){this._context=t}function If(t,n){this._basis=new Yf(t),this._beta=n}function jf(t,n,e){t._context.bezierCurveTo(t._x1+t._k*(t._x2-t._x0),t._y1+t._k*(t._y2-t._y0),t._x2+t._k*(t._x1-n),t._y2+t._k*(t._y1-e),t._x2,t._y2)}function Hf(t,n){this._context=t,this._k=(1-n)/6}function Xf(t,n){this._context=t,this._k=(1-n)/6}function Gf(t,n){this._context=t,this._k=(1-n)/6}function Vf(t,n,e){var r=t._x1,i=t._y1,o=t._x2,a=t._y2;if(t._l01_a>__){var u=2*t._l01_2a+3*t._l01_a*t._l12_a+t._l12_2a,f=3*t._l01_a*(t._l01_a+t._l12_a);r=(r*u-t._x0*t._l12_2a+t._x2*t._l01_2a)/f,i=(i*u-t._y0*t._l12_2a+t._y2*t._l01_2a)/f}if(t._l23_a>__){var c=2*t._l23_2a+3*t._l23_a*t._l12_a+t._l12_2a,s=3*t._l23_a*(t._l23_a+t._l12_a);o=(o*c+t._x1*t._l23_2a-n*t._l12_2a)/s,a=(a*c+t._y1*t._l23_2a-e*t._l12_2a)/s}t._context.bezierCurveTo(r,i,o,a,t._x2,t._y2)}function $f(t,n){this._context=t,this._alpha=n}function Wf(t,n){this._context=t,this._alpha=n}function Zf(t,n){this._context=t,this._alpha=n}function Qf(t){this._context=t}function Jf(t){return t<0?-1:1}function Kf(t,n,e){var r=t._x1-t._x0,i=n-t._x1,o=(t._y1-t._y0)/(r||i<0&&-0),a=(e-t._y1)/(i||r<0&&-0),u=(o*i+a*r)/(r+i);return(Jf(o)+Jf(a))*Math.min(Math.abs(o),Math.abs(a),.5*Math.abs(u))||0}function tc(t,n){var e=t._x1-t._x0;return e?(3*(t._y1-t._y0)/e-n)/2:n}function nc(t,n,e){var r=t._x0,i=t._y0,o=t._x1,a=t._y1,u=(o-r)/3;t._context.bezierCurveTo(r+u,i+u*n,o-u,a-u*e,o,a)}function ec(t){this._context=t}function rc(t){this._context=new ic(t)}function ic(t){this._context=t}function oc(t){this._context=t}function ac(t){var n,e,r=t.length-1,i=new Array(r),o=new Array(r),a=new Array(r);for(i[0]=0,o[0]=2,a[0]=t[0]+2*t[1],n=1;n=0;--n)i[n]=(a[n]-i[n+1])/o[n];for(o[r-1]=(t[r]+i[r-1])/2,n=0;n1)for(var e,r,i,o=1,a=t[n[0]],u=a.length;o=0;)e[n]=n;return e}function sc(t,n){return t[n]}function lc(t){var n=t.map(hc);return cc(t).sort(function(t,e){return n[t]-n[e]})}function hc(t){for(var n,e=0,r=-1,i=t.length;++r0)){if(o/=h,h<0){if(o0){if(o>l)return;o>s&&(s=o)}if(o=r-f,h||!(o<0)){if(o/=h,h<0){if(o>l)return;o>s&&(s=o)}else if(h>0){if(o0)){if(o/=d,d<0){if(o0){if(o>l)return;o>s&&(s=o)}if(o=i-c,d||!(o<0)){if(o/=d,d<0){if(o>l)return;o>s&&(s=o)}else if(d>0){if(o0||l<1)||(s>0&&(t[0]=[f+s*h,c+s*d]),l<1&&(t[1]=[f+l*h,c+l*d]),!0)}}}}}function Tc(t,n,e,r,i){var o=t[1];if(o)return!0;var a,u,f=t[0],c=t.left,s=t.right,l=c[0],h=c[1],d=s[0],p=s[1],v=(l+d)/2,g=(h+p)/2;if(p===h){if(v=r)return;if(l>d){if(f){if(f[1]>=i)return}else f=[v,e];o=[v,i]}else{if(f){if(f[1]1)if(l>d){if(f){if(f[1]>=i)return}else f=[(e-u)/a,e];o=[(i-u)/a,i]}else{if(f){if(f[1]=r)return}else f=[n,a*n+u];o=[r,a*r+u]}else{if(f){if(f[0]=-eb)){var d=f*f+c*c,p=s*s+l*l,v=(l*d-c*p)/h,g=(f*p-s*d)/h,y=K_.pop()||new function(){yc(this),this.x=this.y=this.arc=this.site=this.cy=null};y.arc=t,y.site=i,y.x=v+a,y.y=(y.cy=g+u)+Math.sqrt(v*v+g*g),t.circle=y;for(var _=null,b=Q_._;b;)if(y.ynb)u=u.L;else{if(!((i=o-function(t,n){var e=t.N;if(e)return Dc(e,n);var r=t.site;return r[1]===n?r[0]:1/0}(u,a))>nb)){r>-nb?(n=u.P,e=u):i>-nb?(n=u,e=u.N):n=e=u;break}if(!u.R){n=u;break}u=u.R}(function(t){Z_[t.index]={site:t,halfedges:[]}})(t);var f=Pc(t);if(W_.insert(n,f),n||e){if(n===e)return Cc(n),e=Pc(n.site),W_.insert(f,e),f.edge=e.edge=xc(n.site,f.site),kc(n),void kc(e);if(e){Cc(n),Cc(e);var c=n.site,s=c[0],l=c[1],h=t[0]-s,d=t[1]-l,p=e.site,v=p[0]-s,g=p[1]-l,y=2*(h*g-d*v),_=h*h+d*d,b=v*v+g*g,m=[(g*_-d*b)/y+s,(h*b-v*_)/y+l];Mc(e.edge,c,p,m),f.edge=xc(c,t,null,m),e.edge=xc(t,p,null,m),kc(n),kc(e)}else f.edge=xc(n.site,f.site)}}function Dc(t,n){var e=t.site,r=e[0],i=e[1],o=i-n;if(!o)return r;var a=t.P;if(!a)return-1/0;var u=(e=a.site)[0],f=e[1],c=f-n;if(!c)return u;var s=u-r,l=1/o-1/c,h=s/c;return l?(-h+Math.sqrt(h*h-2*l*(s*s/(-2*c)-f+c/2+i-o/2)))/l+r:(r+u)/2}function Uc(t,n,e){return(t[0]-e[0])*(n[1]-t[1])-(t[0]-n[0])*(e[1]-t[1])}function qc(t,n){return n[1]-t[1]||n[0]-t[0]}function Oc(t,n){var e,r,i,o=t.sort(qc).pop();for(J_=[],Z_=new Array(t.length),W_=new gc,Q_=new gc;;)if(i=$_,o&&(!i||o[1]nb||Math.abs(i[0][1]-i[1][1])>nb)||delete J_[o]})(a,u,f,c),function(t,n,e,r){var i,o,a,u,f,c,s,l,h,d,p,v,g=Z_.length,y=!0;for(i=0;inb||Math.abs(v-h)>nb)&&(f.splice(u,0,J_.push(wc(a,d,Math.abs(p-t)nb?[t,Math.abs(l-t)nb?[Math.abs(h-r)nb?[e,Math.abs(l-e)nb?[Math.abs(h-n)r?(r+i)/2:Math.min(0,r)||Math.max(0,i),a>o?(o+a)/2:Math.min(0,o)||Math.max(0,a))}var Zc=e(n),Qc=Zc.right,Jc=Zc.left,Kc=Array.prototype,ts=Kc.slice,ns=Kc.map,es=Math.sqrt(50),rs=Math.sqrt(10),is=Math.sqrt(2),os=Array.prototype.slice,as=1,us=2,fs=3,cs=4,ss=1e-6,ls={value:function(){}};S.prototype=N.prototype={constructor:S,on:function(t,n){var e,r=this._,i=function(t,n){return t.trim().split(/^|\s+/).map(function(t){var e="",r=t.indexOf(".");if(r>=0&&(e=t.slice(r+1),t=t.slice(0,r)),t&&!n.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:e}})}(t+"",r),o=-1,a=i.length;{if(!(arguments.length<2)){if(null!=n&&"function"!=typeof n)throw new Error("invalid callback: "+n);for(;++o0)for(var e,r,i=new Array(e),o=0;o=0&&(this._names.splice(n,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var bs={};if(t.event=null,"undefined"!=typeof document){"onmouseenter"in document.documentElement||(bs={mouseenter:"mouseover",mouseleave:"mouseout"})}var ms=[null];ut.prototype=ft.prototype={constructor:ut,select:function(t){"function"!=typeof t&&(t=z(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i=m&&(m=b+1);!(_=g[m])&&++m=0;)(r=i[o])&&(a&&a!==r.nextSibling&&a.parentNode.insertBefore(r,a),a=r);return this},sort:function(t){function n(n,e){return n&&e?t(n.__data__,e.__data__):!n-!e}t||(t=Y);for(var e=this._groups,r=e.length,i=new Array(r),o=0;o1?this.each((null==n?function(t){return function(){this.style.removeProperty(t)}}:"function"==typeof n?function(t,n,e){return function(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}}:function(t,n,e){return function(){this.style.setProperty(t,n,e)}})(t,n,null==e?"":e)):F(this.node(),t)},property:function(t,n){return arguments.length>1?this.each((null==n?function(t){return function(){delete this[t]}}:"function"==typeof n?function(t,n){return function(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}}:function(t,n){return function(){this[t]=n}})(t,n)):this.node()[t]},classed:function(t,n){var e=I(t+"");if(arguments.length<2){for(var r=j(this.node()),i=-1,o=e.length;++i=0&&(n=t.slice(e+1),t=t.slice(0,e)),{type:t,name:n}})}(t+""),a=o.length;if(!(arguments.length<2)){for(u=n?it:rt,null==e&&(e=!1),r=0;r=240?t-240:t+120,i,r),Ot(t,i,r),Ot(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1}}));var Ls=Math.PI/180,Ds=180/Math.PI,Us=.96422,qs=1,Os=.82521,Ys=4/29,Bs=6/29,Fs=3*Bs*Bs,Is=Bs*Bs*Bs;Nt(Ft,Bt,St(Et,{brighter:function(t){return new Ft(this.l+18*(null==t?1:t),this.a,this.b,this.opacity)},darker:function(t){return new Ft(this.l-18*(null==t?1:t),this.a,this.b,this.opacity)},rgb:function(){var t=(this.l+16)/116,n=isNaN(this.a)?t:t+this.a/500,e=isNaN(this.b)?t:t-this.b/200;return n=Us*jt(n),t=qs*jt(t),e=Os*jt(e),new Lt(Ht(3.1338561*n-1.6168667*t-.4906146*e),Ht(-.9787684*n+1.9161415*t+.033454*e),Ht(.0719453*n-.2289914*t+1.4052427*e),this.opacity)}})),Nt($t,Vt,St(Et,{brighter:function(t){return new $t(this.h,this.c,this.l+18*(null==t?1:t),this.opacity)},darker:function(t){return new $t(this.h,this.c,this.l-18*(null==t?1:t),this.opacity)},rgb:function(){return Yt(this).rgb()}}));var js=-.29227,Hs=-.90649,Xs=1.97294,Gs=Xs*Hs,Vs=1.78277*Xs,$s=1.78277*js- -.14861*Hs;Nt(Zt,Wt,St(Et,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new Zt(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new Zt(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=isNaN(this.h)?0:(this.h+120)*Ls,n=+this.l,e=isNaN(this.s)?0:this.s*n*(1-n),r=Math.cos(t),i=Math.sin(t);return new Lt(255*(n+e*(-.14861*r+1.78277*i)),255*(n+e*(js*r+Hs*i)),255*(n+e*(Xs*r)),this.opacity)}}));var Ws,Zs,Qs,Js,Ks,tl,nl=function t(n){function e(t,n){var e=r((t=Rt(t)).r,(n=Rt(n)).r),i=r(t.g,n.g),o=r(t.b,n.b),a=on(t.opacity,n.opacity);return function(n){return t.r=e(n),t.g=i(n),t.b=o(n),t.opacity=a(n),t+""}}var r=rn(n);return e.gamma=t,e}(1),el=an(Jt),rl=an(Kt),il=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,ol=new RegExp(il.source,"g"),al=180/Math.PI,ul={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1},fl=vn(function(t){return"none"===t?ul:(Ws||(Ws=document.createElement("DIV"),Zs=document.documentElement,Qs=document.defaultView),Ws.style.transform=t,t=Qs.getComputedStyle(Zs.appendChild(Ws),null).getPropertyValue("transform"),Zs.removeChild(Ws),t=t.slice(7,-1).split(","),pn(+t[0],+t[1],+t[2],+t[3],+t[4],+t[5]))},"px, ","px)","deg)"),cl=vn(function(t){return null==t?ul:(Js||(Js=document.createElementNS("http://www.w3.org/2000/svg","g")),Js.setAttribute("transform",t),(t=Js.transform.baseVal.consolidate())?(t=t.matrix,pn(t.a,t.b,t.c,t.d,t.e,t.f)):ul)},", ",")",")"),sl=Math.SQRT2,ll=2,hl=4,dl=1e-12,pl=_n(en),vl=_n(on),gl=bn(en),yl=bn(on),_l=mn(en),bl=mn(on),ml=0,xl=0,wl=0,Ml=1e3,Al=0,Tl=0,Nl=0,Sl="object"==typeof performance&&performance.now?performance:Date,El="object"==typeof window&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(t){setTimeout(t,17)};Mn.prototype=An.prototype={constructor:Mn,restart:function(t,n,e){if("function"!=typeof t)throw new TypeError("callback is not a function");e=(null==e?xn():+e)+(null==n?0:+n),this._next||tl===this||(tl?tl._next=this:Ks=this,tl=this),this._call=t,this._time=e,En()},stop:function(){this._call&&(this._call=null,this._time=1/0,En())}};var kl=N("start","end","interrupt"),Cl=[],Pl=0,zl=1,Rl=2,Ll=3,Dl=4,Ul=5,ql=6,Ol=ft.prototype.constructor,Yl=0,Bl=ft.prototype;qn.prototype=On.prototype={constructor:qn,select:function(t){var n=this._name,e=this._id;"function"!=typeof t&&(t=z(t));for(var r=this._groups,i=r.length,o=new Array(i),a=0;a=0&&(t=t.slice(0,n)),!t||"start"===t})}(n)?Pn:zn;return function(){var a=o(this,t),u=a.on;u!==r&&(i=(r=u).copy()).on(n,e),a.on=i}}(e,t,n))},attr:function(t,n){var e=k(t),r="transform"===e?cl:Un;return this.attrTween(t,"function"==typeof n?(e.local?function(t,n,e){var r,i,o;return function(){var a,u=e(this);if(null!=u)return(a=this.getAttributeNS(t.space,t.local))===u?null:a===r&&u===i?o:o=n(r=a,i=u);this.removeAttributeNS(t.space,t.local)}}:function(t,n,e){var r,i,o;return function(){var a,u=e(this);if(null!=u)return(a=this.getAttribute(t))===u?null:a===r&&u===i?o:o=n(r=a,i=u);this.removeAttribute(t)}})(e,r,Dn(this,"attr."+t,n)):null==n?(e.local?function(t){return function(){this.removeAttributeNS(t.space,t.local)}}:function(t){return function(){this.removeAttribute(t)}})(e):(e.local?function(t,n,e){var r,i;return function(){var o=this.getAttributeNS(t.space,t.local);return o===e?null:o===r?i:i=n(r=o,e)}}:function(t,n,e){var r,i;return function(){var o=this.getAttribute(t);return o===e?null:o===r?i:i=n(r=o,e)}})(e,r,n+""))},attrTween:function(t,n){var e="attr."+t;if(arguments.length<2)return(e=this.tween(e))&&e._value;if(null==n)return this.tween(e,null);if("function"!=typeof n)throw new Error;var r=k(t);return this.tween(e,(r.local?function(t,n){function e(){var e=this,r=n.apply(e,arguments);return r&&function(n){e.setAttributeNS(t.space,t.local,r(n))}}return e._value=n,e}:function(t,n){function e(){var e=this,r=n.apply(e,arguments);return r&&function(n){e.setAttribute(t,r(n))}}return e._value=n,e})(r,n))},style:function(t,n,e){var r="transform"==(t+="")?fl:Un;return null==n?this.styleTween(t,function(t,n){var e,r,i;return function(){var o=F(this,t),a=(this.style.removeProperty(t),F(this,t));return o===a?null:o===e&&a===r?i:i=n(e=o,r=a)}}(t,r)).on("end.style."+t,function(t){return function(){this.style.removeProperty(t)}}(t)):this.styleTween(t,"function"==typeof n?function(t,n,e){var r,i,o;return function(){var a=F(this,t),u=e(this);return null==u&&(this.style.removeProperty(t),u=F(this,t)),a===u?null:a===r&&u===i?o:o=n(r=a,i=u)}}(t,r,Dn(this,"style."+t,n)):function(t,n,e){var r,i;return function(){var o=F(this,t);return o===e?null:o===r?i:i=n(r=o,e)}}(t,r,n+""),e)},styleTween:function(t,n,e){var r="style."+(t+="");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==n)return this.tween(r,null);if("function"!=typeof n)throw new Error;return this.tween(r,function(t,n,e){function r(){var r=this,i=n.apply(r,arguments);return i&&function(n){r.style.setProperty(t,i(n),e)}}return r._value=n,r}(t,n,null==e?"":e))},text:function(t){return this.tween("text","function"==typeof t?function(t){return function(){var n=t(this);this.textContent=null==n?"":n}}(Dn(this,"text",t)):function(t){return function(){this.textContent=t}}(null==t?"":t+""))},remove:function(){return this.on("end.remove",function(t){return function(){var n=this.parentNode;for(var e in this.__transition)if(+e!==t)return;n&&n.removeChild(this)}}(this._id))},tween:function(t,n){var e=this._id;if(t+="",arguments.length<2){for(var r,i=Rn(this.node(),e).tween,o=0,a=i.length;o1e-6)if(Math.abs(s*u-f*c)>1e-6&&i){var h=e-o,d=r-a,p=u*u+f*f,v=h*h+d*d,g=Math.sqrt(p),y=Math.sqrt(l),_=i*Math.tan((Ch-Math.acos((p+l-v)/(2*g*y)))/2),b=_/y,m=_/g;Math.abs(b-1)>1e-6&&(this._+="L"+(t+b*c)+","+(n+b*s)),this._+="A"+i+","+i+",0,0,"+ +(s*h>c*d)+","+(this._x1=t+m*u)+","+(this._y1=n+m*f)}else this._+="L"+(this._x1=t)+","+(this._y1=n);else;},arc:function(t,n,e,r,i,o){t=+t,n=+n;var a=(e=+e)*Math.cos(r),u=e*Math.sin(r),f=t+a,c=n+u,s=1^o,l=o?r-i:i-r;if(e<0)throw new Error("negative radius: "+e);null===this._x1?this._+="M"+f+","+c:(Math.abs(this._x1-f)>1e-6||Math.abs(this._y1-c)>1e-6)&&(this._+="L"+f+","+c),e&&(l<0&&(l=l%Ph+Ph),l>zh?this._+="A"+e+","+e+",0,1,"+s+","+(t-a)+","+(n-u)+"A"+e+","+e+",0,1,"+s+","+(this._x1=f)+","+(this._y1=c):l>1e-6&&(this._+="A"+e+","+e+",0,"+ +(l>=Ch)+","+s+","+(this._x1=t+e*Math.cos(i))+","+(this._y1=n+e*Math.sin(i))))},rect:function(t,n,e,r){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+n)+"h"+ +e+"v"+ +r+"h"+-e+"Z"},toString:function(){return this._}};se.prototype=le.prototype={constructor:se,has:function(t){return"$"+t in this},get:function(t){return this["$"+t]},set:function(t,n){return this["$"+t]=n,this},remove:function(t){var n="$"+t;return n in this&&delete this[n]},clear:function(){for(var t in this)"$"===t[0]&&delete this[t]},keys:function(){var t=[];for(var n in this)"$"===n[0]&&t.push(n.slice(1));return t},values:function(){var t=[];for(var n in this)"$"===n[0]&&t.push(this[n]);return t},entries:function(){var t=[];for(var n in this)"$"===n[0]&&t.push({key:n.slice(1),value:this[n]});return t},size:function(){var t=0;for(var n in this)"$"===n[0]&&++t;return t},empty:function(){for(var t in this)if("$"===t[0])return!1;return!0},each:function(t){for(var n in this)"$"===n[0]&&t(this[n],n.slice(1),this)}};var Rh=le.prototype;ge.prototype=ye.prototype={constructor:ge,has:Rh.has,add:function(t){return t+="",this["$"+t]=t,this},remove:Rh.remove,clear:Rh.clear,values:Rh.keys,size:Rh.size,empty:Rh.empty,each:Rh.each};var Lh=Array.prototype.slice,Dh=[[],[[[1,1.5],[.5,1]]],[[[1.5,1],[1,1.5]]],[[[1.5,1],[.5,1]]],[[[1,.5],[1.5,1]]],[[[1,1.5],[.5,1]],[[1,.5],[1.5,1]]],[[[1,.5],[1,1.5]]],[[[1,.5],[.5,1]]],[[[.5,1],[1,.5]]],[[[1,1.5],[1,.5]]],[[[.5,1],[1,.5]],[[1.5,1],[1,1.5]]],[[[1.5,1],[1,.5]]],[[[.5,1],[1.5,1]]],[[[1,1.5],[1.5,1]]],[[[.5,1],[1,1.5]]],[]],Uh={},qh={},Oh=34,Yh=10,Bh=13,Fh=Ee(","),Ih=Fh.parse,jh=Fh.parseRows,Hh=Fh.format,Xh=Fh.formatRows,Gh=Ee("\t"),Vh=Gh.parse,$h=Gh.parseRows,Wh=Gh.format,Zh=Gh.formatRows,Qh=Re(Ih),Jh=Re(Vh),Kh=De("application/xml"),td=De("text/html"),nd=De("image/svg+xml"),ed=Ie.prototype=je.prototype;ed.copy=function(){var t,n,e=new je(this._x,this._y,this._x0,this._y0,this._x1,this._y1),r=this._root;if(!r)return e;if(!r.length)return e._root=He(r),e;for(t=[{source:r,target:e._root=new Array(4)}];r=t.pop();)for(var i=0;i<4;++i)(n=r.source[i])&&(n.length?t.push({source:n,target:r.target[i]=new Array(4)}):r.target[i]=He(n));return e},ed.add=function(t){var n=+this._x.call(null,t),e=+this._y.call(null,t);return Oe(this.cover(n,e),n,e,t)},ed.addAll=function(t){var n,e,r,i,o=t.length,a=new Array(o),u=new Array(o),f=1/0,c=1/0,s=-1/0,l=-1/0;for(e=0;es&&(s=r),il&&(l=i));for(st||t>i||r>n||n>o))return this;var a,u,f=i-e,c=this._root;switch(u=(n<(r+o)/2)<<1|t<(e+i)/2){case 0:do{a=new Array(4),a[u]=c,c=a}while(f*=2,i=e+f,o=r+f,t>i||n>o);break;case 1:do{a=new Array(4),a[u]=c,c=a}while(f*=2,e=i-f,o=r+f,e>t||n>o);break;case 2:do{a=new Array(4),a[u]=c,c=a}while(f*=2,i=e+f,r=o-f,t>i||r>n);break;case 3:do{a=new Array(4),a[u]=c,c=a}while(f*=2,e=i-f,r=o-f,e>t||r>n)}this._root&&this._root.length&&(this._root=c)}return this._x0=e,this._y0=r,this._x1=i,this._y1=o,this},ed.data=function(){var t=[];return this.visit(function(n){if(!n.length)do{t.push(n.data)}while(n=n.next)}),t},ed.extent=function(t){return arguments.length?this.cover(+t[0][0],+t[0][1]).cover(+t[1][0],+t[1][1]):isNaN(this._x0)?void 0:[[this._x0,this._y0],[this._x1,this._y1]]},ed.find=function(t,n,e){var r,i,o,a,u,f,c,s=this._x0,l=this._y0,h=this._x1,d=this._y1,p=[],v=this._root;for(v&&p.push(new Ye(v,s,l,h,d)),null==e?e=1/0:(s=t-e,l=n-e,h=t+e,d=n+e,e*=e);f=p.pop();)if(!(!(v=f.node)||(i=f.x0)>h||(o=f.y0)>d||(a=f.x1)=y)<<1|t>=g)&&(f=p[p.length-1],p[p.length-1]=p[p.length-1-c],p[p.length-1-c]=f)}else{var _=t-+this._x.call(null,v.data),b=n-+this._y.call(null,v.data),m=_*_+b*b;if(m=(u=(p+g)/2))?p=u:g=u,(s=a>=(f=(v+y)/2))?v=f:y=f,n=d,!(d=d[l=s<<1|c]))return this;if(!d.length)break;(n[l+1&3]||n[l+2&3]||n[l+3&3])&&(e=n,h=l)}for(;d.data!==t;)if(r=d,!(d=d.next))return this;return(i=d.next)&&delete d.next,r?(i?r.next=i:delete r.next,this):n?(i?n[l]=i:delete n[l],(d=n[0]||n[1]||n[2]||n[3])&&d===(n[3]||n[2]||n[1]||n[0])&&!d.length&&(e?e[h]=d:this._root=d),this):(this._root=i,this)},ed.removeAll=function(t){for(var n=0,e=t.length;n0&&(o=0)}return o>0?t.slice(0,o)+t.slice(e+1):t},"%":function(t,n){return(100*t).toFixed(n)},b:function(t){return Math.round(t).toString(2)},c:function(t){return t+""},d:function(t){return Math.round(t).toString(10)},e:function(t,n){return t.toExponential(n)},f:function(t,n){return t.toFixed(n)},g:function(t,n){return t.toPrecision(n)},o:function(t){return Math.round(t).toString(8)},p:function(t,n){return Ke(100*t,n)},r:Ke,s:function(t,n){var e=Qe(t,n);if(!e)return t+"";var r=e[0],i=e[1],o=i-(rd=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,a=r.length;return o===a?r:o>a?r+new Array(o-a+1).join("0"):o>0?r.slice(0,o)+"."+r.slice(o):"0."+new Array(1-o).join("0")+Qe(t,Math.max(0,n+o-1))[0]},X:function(t){return Math.round(t).toString(16).toUpperCase()},x:function(t){return Math.round(t).toString(16)}},ud=/^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;tr.prototype=nr.prototype,nr.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(null==this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(null==this.precision?"":"."+Math.max(0,0|this.precision))+this.type};var fd,cd=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];ir({decimal:".",thousands:",",grouping:[3],currency:["$",""]}),cr.prototype={constructor:cr,reset:function(){this.s=this.t=0},add:function(t){sr(Fd,t,this.t),sr(this,Fd.s,this.s),this.s?this.t+=Fd.t:this.s=Fd.t},valueOf:function(){return this.s}};var sd,ld,hd,dd,pd,vd,gd,yd,_d,bd,md,xd,wd,Md,Ad,Td,Nd,Sd,Ed,kd,Cd,Pd,zd,Rd,Ld,Dd,Ud,qd,Od,Yd,Bd,Fd=new cr,Id=1e-6,jd=1e-12,Hd=Math.PI,Xd=Hd/2,Gd=Hd/4,Vd=2*Hd,$d=180/Hd,Wd=Hd/180,Zd=Math.abs,Qd=Math.atan,Jd=Math.atan2,Kd=Math.cos,tp=Math.ceil,np=Math.exp,ep=Math.log,rp=Math.pow,ip=Math.sin,op=Math.sign||function(t){return t>0?1:t<0?-1:0},ap=Math.sqrt,up=Math.tan,fp={Feature:function(t,n){vr(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,i=e.length;++rId?_d=90:dp<-Id&&(gd=-90),Ad[0]=vd,Ad[1]=yd}},vp={sphere:pr,point:Br,lineStart:Ir,lineEnd:Xr,polygonStart:function(){vp.lineStart=Gr,vp.lineEnd=Vr},polygonEnd:function(){vp.lineStart=Ir,vp.lineEnd=Xr}};Jr.invert=Jr;var gp,yp,_p,bp,mp,xp,wp,Mp,Ap,Tp,Np,Sp=fr(),Ep=hi(function(){return!0},function(t){var n,e=NaN,r=NaN,i=NaN;return{lineStart:function(){t.lineStart(),n=1},point:function(o,a){var u=o>0?Hd:-Hd,f=Zd(o-e);Zd(f-Hd)0?Xd:-Xd),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(u,r),t.point(o,r),n=0):i!==u&&f>=Hd&&(Zd(e-i)Id?Qd((ip(n)*(o=Kd(r))*ip(e)-ip(r)*(i=Kd(n))*ip(t))/(i*o*a)):(n+r)/2}(e,r,o,a),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(u,r),n=0),t.point(e=o,r=a),i=u},lineEnd:function(){t.lineEnd(),e=r=NaN},clean:function(){return 2-n}}},function(t,n,e,r){var i;if(null==t)i=e*Xd,r.point(-Hd,i),r.point(0,i),r.point(Hd,i),r.point(Hd,0),r.point(Hd,-i),r.point(0,-i),r.point(-Hd,-i),r.point(-Hd,0),r.point(-Hd,i);else if(Zd(t[0]-n[0])>Id){var o=t[0]Ip&&(Ip=t),njp&&(jp=n)},lineStart:pr,lineEnd:pr,polygonStart:pr,polygonEnd:pr,result:function(){var t=[[Bp,Fp],[Ip,jp]];return Ip=jp=-(Fp=Bp=1/0),t}},Xp=0,Gp=0,Vp=0,$p=0,Wp=0,Zp=0,Qp=0,Jp=0,Kp=0,tv={point:Ui,lineStart:qi,lineEnd:Bi,polygonStart:function(){tv.lineStart=Fi,tv.lineEnd=Ii},polygonEnd:function(){tv.point=Ui,tv.lineStart=qi,tv.lineEnd=Bi},result:function(){var t=Kp?[Qp/Kp,Jp/Kp]:Zp?[$p/Zp,Wp/Zp]:Vp?[Xp/Vp,Gp/Vp]:[NaN,NaN];return Xp=Gp=Vp=$p=Wp=Zp=Qp=Jp=Kp=0,t}};Xi.prototype={_radius:4.5,pointRadius:function(t){return this._radius=t,this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._context.closePath(),this._point=NaN},point:function(t,n){switch(this._point){case 0:this._context.moveTo(t,n),this._point=1;break;case 1:this._context.lineTo(t,n);break;default:this._context.moveTo(t+this._radius,n),this._context.arc(t,n,this._radius,0,Vd)}},result:pr};var nv,ev,rv,iv,ov,av=fr(),uv={point:pr,lineStart:function(){uv.point=Gi},lineEnd:function(){nv&&Vi(ev,rv),uv.point=pr},polygonStart:function(){nv=!0},polygonEnd:function(){nv=null},result:function(){var t=+av;return av.reset(),t}};$i.prototype={_radius:4.5,_circle:Wi(4.5),pointRadius:function(t){return(t=+t)!==this._radius&&(this._radius=t,this._circle=null),this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._string.push("Z"),this._point=NaN},point:function(t,n){switch(this._point){case 0:this._string.push("M",t,",",n),this._point=1;break;case 1:this._string.push("L",t,",",n);break;default:null==this._circle&&(this._circle=Wi(this._radius)),this._string.push("M",t,",",n,this._circle)}},result:function(){if(this._string.length){var t=this._string.join("");return this._string=[],t}return null}},Qi.prototype={constructor:Qi,point:function(t,n){this.stream.point(t,n)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}};var fv=16,cv=Kd(30*Wd),sv=Zi({point:function(t,n){this.stream.point(t*Wd,n*Wd)}}),lv=lo(function(t){return ap(2/(1+t))});lv.invert=ho(function(t){return 2*hr(t/2)});var hv=lo(function(t){return(t=lr(t))&&t/ip(t)});hv.invert=ho(function(t){return t}),po.invert=function(t,n){return[t,2*Qd(np(n))-Xd]},_o.invert=_o,mo.invert=ho(Qd),wo.invert=function(t,n){var e,r=n,i=25;do{var o=r*r,a=o*o;r-=e=(r*(1.007226+o*(.015085+a*(.028874*o-.044475-.005916*a)))-n)/(1.007226+o*(.045255+a*(.259866*o-.311325-.005916*11*a)))}while(Zd(e)>Id&&--i>0);return[t/(.8707+(o=r*r)*(o*(o*o*o*(.003971-.001529*o)-.013791)-.131979)),r]},Mo.invert=ho(hr),Ao.invert=ho(function(t){return 2*Qd(t)}),To.invert=function(t,n){return[-n,2*Qd(np(t))-Xd]},Lo.prototype=Co.prototype={constructor:Lo,count:function(){return this.eachAfter(ko)},each:function(t){var n,e,r,i,o=this,a=[o];do{for(n=a.reverse(),a=[];o=n.pop();)if(t(o),e=o.children)for(r=0,i=e.length;r=0;--e)i.push(n[e]);return this},sum:function(t){return this.eachAfter(function(n){for(var e=+t(n.data)||0,r=n.children,i=r&&r.length;--i>=0;)e+=r[i].value;n.value=e})},sort:function(t){return this.eachBefore(function(n){n.children&&n.children.sort(t)})},path:function(t){for(var n=this,e=function(t,n){if(t===n)return t;var e=t.ancestors(),r=n.ancestors(),i=null;for(t=e.pop(),n=r.pop();t===n;)i=t,t=e.pop(),n=r.pop();return i}(n,t),r=[n];n!==e;)n=n.parent,r.push(n);for(var i=r.length;t!==e;)r.splice(i,0,t),t=t.parent;return r},ancestors:function(){for(var t=this,n=[t];t=t.parent;)n.push(t);return n},descendants:function(){var t=[];return this.each(function(n){t.push(n)}),t},leaves:function(){var t=[];return this.eachBefore(function(n){n.children||t.push(n)}),t},links:function(){var t=this,n=[];return t.each(function(e){e!==t&&n.push({source:e.parent,target:e})}),n},copy:function(){return Co(this).eachBefore(zo)}};var dv=Array.prototype.slice,pv="$",vv={depth:-1},gv={};fa.prototype=Object.create(Lo.prototype);var yv=(1+Math.sqrt(5))/2,_v=function t(n){function e(t,e,r,i,o){sa(n,t,e,r,i,o)}return e.ratio=function(n){return t((n=+n)>1?n:1)},e}(yv),bv=function t(n){function e(t,e,r,i,o){if((a=t._squarify)&&a.ratio===n)for(var a,u,f,c,s,l=-1,h=a.length,d=t.value;++l1?n:1)},e}(yv),mv=function t(n){function e(t,e){return t=null==t?0:+t,e=null==e?1:+e,1===arguments.length?(e=t,t=0):e-=t,function(){return n()*e+t}}return e.source=t,e}(pa),xv=function t(n){function e(t,e){var r,i;return t=null==t?0:+t,e=null==e?1:+e,function(){var o;if(null!=r)o=r,r=null;else do{r=2*n()-1,o=2*n()-1,i=r*r+o*o}while(!i||i>1);return t+e*o*Math.sqrt(-2*Math.log(i)/i)}}return e.source=t,e}(pa),wv=function t(n){function e(){var t=xv.source(n).apply(this,arguments);return function(){return Math.exp(t())}}return e.source=t,e}(pa),Mv=function t(n){function e(t){return function(){for(var e=0,r=0;r0?t>1?Fa(function(n){n.setTime(Math.floor(n/t)*t)},function(n,e){n.setTime(+n+e*t)},function(n,e){return(e-n)/t}):Rv:null};var Lv=Rv.range,Dv=6e4,Uv=6048e5,qv=Fa(function(t){t.setTime(1e3*Math.floor(t/1e3))},function(t,n){t.setTime(+t+1e3*n)},function(t,n){return(n-t)/1e3},function(t){return t.getUTCSeconds()}),Ov=qv.range,Yv=Fa(function(t){t.setTime(Math.floor(t/Dv)*Dv)},function(t,n){t.setTime(+t+n*Dv)},function(t,n){return(n-t)/Dv},function(t){return t.getMinutes()}),Bv=Yv.range,Fv=Fa(function(t){var n=t.getTimezoneOffset()*Dv%36e5;n<0&&(n+=36e5),t.setTime(36e5*Math.floor((+t-n)/36e5)+n)},function(t,n){t.setTime(+t+36e5*n)},function(t,n){return(n-t)/36e5},function(t){return t.getHours()}),Iv=Fv.range,jv=Fa(function(t){t.setHours(0,0,0,0)},function(t,n){t.setDate(t.getDate()+n)},function(t,n){return(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*Dv)/864e5},function(t){return t.getDate()-1}),Hv=jv.range,Xv=Ia(0),Gv=Ia(1),Vv=Ia(2),$v=Ia(3),Wv=Ia(4),Zv=Ia(5),Qv=Ia(6),Jv=Xv.range,Kv=Gv.range,tg=Vv.range,ng=$v.range,eg=Wv.range,rg=Zv.range,ig=Qv.range,og=Fa(function(t){t.setDate(1),t.setHours(0,0,0,0)},function(t,n){t.setMonth(t.getMonth()+n)},function(t,n){return n.getMonth()-t.getMonth()+12*(n.getFullYear()-t.getFullYear())},function(t){return t.getMonth()}),ag=og.range,ug=Fa(function(t){t.setMonth(0,1),t.setHours(0,0,0,0)},function(t,n){t.setFullYear(t.getFullYear()+n)},function(t,n){return n.getFullYear()-t.getFullYear()},function(t){return t.getFullYear()});ug.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Fa(function(n){n.setFullYear(Math.floor(n.getFullYear()/t)*t),n.setMonth(0,1),n.setHours(0,0,0,0)},function(n,e){n.setFullYear(n.getFullYear()+e*t)}):null};var fg=ug.range,cg=Fa(function(t){t.setUTCSeconds(0,0)},function(t,n){t.setTime(+t+n*Dv)},function(t,n){return(n-t)/Dv},function(t){return t.getUTCMinutes()}),sg=cg.range,lg=Fa(function(t){t.setUTCMinutes(0,0,0)},function(t,n){t.setTime(+t+36e5*n)},function(t,n){return(n-t)/36e5},function(t){return t.getUTCHours()}),hg=lg.range,dg=Fa(function(t){t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCDate(t.getUTCDate()+n)},function(t,n){return(n-t)/864e5},function(t){return t.getUTCDate()-1}),pg=dg.range,vg=ja(0),gg=ja(1),yg=ja(2),_g=ja(3),bg=ja(4),mg=ja(5),xg=ja(6),wg=vg.range,Mg=gg.range,Ag=yg.range,Tg=_g.range,Ng=bg.range,Sg=mg.range,Eg=xg.range,kg=Fa(function(t){t.setUTCDate(1),t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCMonth(t.getUTCMonth()+n)},function(t,n){return n.getUTCMonth()-t.getUTCMonth()+12*(n.getUTCFullYear()-t.getUTCFullYear())},function(t){return t.getUTCMonth()}),Cg=kg.range,Pg=Fa(function(t){t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCFullYear(t.getUTCFullYear()+n)},function(t,n){return n.getUTCFullYear()-t.getUTCFullYear()},function(t){return t.getUTCFullYear()});Pg.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Fa(function(n){n.setUTCFullYear(Math.floor(n.getUTCFullYear()/t)*t),n.setUTCMonth(0,1),n.setUTCHours(0,0,0,0)},function(n,e){n.setUTCFullYear(n.getUTCFullYear()+e*t)}):null};var zg,Rg=Pg.range,Lg={"-":"",_:" ",0:"0"},Dg=/^\s*\d+/,Ug=/^%/,qg=/[\\^$*+?|[\]().{}]/g;tf({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});var Og="%Y-%m-%dT%H:%M:%S.%LZ",Yg=Date.prototype.toISOString?function(t){return t.toISOString()}:t.utcFormat(Og),Bg=+new Date("2000-01-01T00:00:00.000Z")?function(t){var n=new Date(t);return isNaN(n)?null:n}:t.utcParse(Og),Fg=1e3,Ig=60*Fg,jg=60*Ig,Hg=24*jg,Xg=7*Hg,Gg=30*Hg,Vg=365*Hg,$g=af("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"),Wg=af("7fc97fbeaed4fdc086ffff99386cb0f0027fbf5b17666666"),Zg=af("1b9e77d95f027570b3e7298a66a61ee6ab02a6761d666666"),Qg=af("a6cee31f78b4b2df8a33a02cfb9a99e31a1cfdbf6fff7f00cab2d66a3d9affff99b15928"),Jg=af("fbb4aeb3cde3ccebc5decbe4fed9a6ffffcce5d8bdfddaecf2f2f2"),Kg=af("b3e2cdfdcdaccbd5e8f4cae4e6f5c9fff2aef1e2cccccccc"),ty=af("e41a1c377eb84daf4a984ea3ff7f00ffff33a65628f781bf999999"),ny=af("66c2a5fc8d628da0cbe78ac3a6d854ffd92fe5c494b3b3b3"),ey=af("8dd3c7ffffb3bebadafb807280b1d3fdb462b3de69fccde5d9d9d9bc80bdccebc5ffed6f"),ry=new Array(3).concat("d8b365f5f5f55ab4ac","a6611adfc27d80cdc1018571","a6611adfc27df5f5f580cdc1018571","8c510ad8b365f6e8c3c7eae55ab4ac01665e","8c510ad8b365f6e8c3f5f5f5c7eae55ab4ac01665e","8c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e","8c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e","5430058c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e003c30","5430058c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e003c30").map(af),iy=uf(ry),oy=new Array(3).concat("af8dc3f7f7f77fbf7b","7b3294c2a5cfa6dba0008837","7b3294c2a5cff7f7f7a6dba0008837","762a83af8dc3e7d4e8d9f0d37fbf7b1b7837","762a83af8dc3e7d4e8f7f7f7d9f0d37fbf7b1b7837","762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b7837","762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b7837","40004b762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b783700441b","40004b762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b783700441b").map(af),ay=uf(oy),uy=new Array(3).concat("e9a3c9f7f7f7a1d76a","d01c8bf1b6dab8e1864dac26","d01c8bf1b6daf7f7f7b8e1864dac26","c51b7de9a3c9fde0efe6f5d0a1d76a4d9221","c51b7de9a3c9fde0eff7f7f7e6f5d0a1d76a4d9221","c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221","c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221","8e0152c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221276419","8e0152c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221276419").map(af),fy=uf(uy),cy=new Array(3).concat("998ec3f7f7f7f1a340","5e3c99b2abd2fdb863e66101","5e3c99b2abd2f7f7f7fdb863e66101","542788998ec3d8daebfee0b6f1a340b35806","542788998ec3d8daebf7f7f7fee0b6f1a340b35806","5427888073acb2abd2d8daebfee0b6fdb863e08214b35806","5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b35806","2d004b5427888073acb2abd2d8daebfee0b6fdb863e08214b358067f3b08","2d004b5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b358067f3b08").map(af),sy=uf(cy),ly=new Array(3).concat("ef8a62f7f7f767a9cf","ca0020f4a58292c5de0571b0","ca0020f4a582f7f7f792c5de0571b0","b2182bef8a62fddbc7d1e5f067a9cf2166ac","b2182bef8a62fddbc7f7f7f7d1e5f067a9cf2166ac","b2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac","b2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac","67001fb2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac053061","67001fb2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac053061").map(af),hy=uf(ly),dy=new Array(3).concat("ef8a62ffffff999999","ca0020f4a582bababa404040","ca0020f4a582ffffffbababa404040","b2182bef8a62fddbc7e0e0e09999994d4d4d","b2182bef8a62fddbc7ffffffe0e0e09999994d4d4d","b2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d","b2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d","67001fb2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d1a1a1a","67001fb2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d1a1a1a").map(af),py=uf(dy),vy=new Array(3).concat("fc8d59ffffbf91bfdb","d7191cfdae61abd9e92c7bb6","d7191cfdae61ffffbfabd9e92c7bb6","d73027fc8d59fee090e0f3f891bfdb4575b4","d73027fc8d59fee090ffffbfe0f3f891bfdb4575b4","d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4","d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4","a50026d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4313695","a50026d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4313695").map(af),gy=uf(vy),yy=new Array(3).concat("fc8d59ffffbf91cf60","d7191cfdae61a6d96a1a9641","d7191cfdae61ffffbfa6d96a1a9641","d73027fc8d59fee08bd9ef8b91cf601a9850","d73027fc8d59fee08bffffbfd9ef8b91cf601a9850","d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850","d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850","a50026d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850006837","a50026d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850006837").map(af),_y=uf(yy),by=new Array(3).concat("fc8d59ffffbf99d594","d7191cfdae61abdda42b83ba","d7191cfdae61ffffbfabdda42b83ba","d53e4ffc8d59fee08be6f59899d5943288bd","d53e4ffc8d59fee08bffffbfe6f59899d5943288bd","d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd","d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd","9e0142d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd5e4fa2","9e0142d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd5e4fa2").map(af),my=uf(by),xy=new Array(3).concat("e5f5f999d8c92ca25f","edf8fbb2e2e266c2a4238b45","edf8fbb2e2e266c2a42ca25f006d2c","edf8fbccece699d8c966c2a42ca25f006d2c","edf8fbccece699d8c966c2a441ae76238b45005824","f7fcfde5f5f9ccece699d8c966c2a441ae76238b45005824","f7fcfde5f5f9ccece699d8c966c2a441ae76238b45006d2c00441b").map(af),wy=uf(xy),My=new Array(3).concat("e0ecf49ebcda8856a7","edf8fbb3cde38c96c688419d","edf8fbb3cde38c96c68856a7810f7c","edf8fbbfd3e69ebcda8c96c68856a7810f7c","edf8fbbfd3e69ebcda8c96c68c6bb188419d6e016b","f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d6e016b","f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d810f7c4d004b").map(af),Ay=uf(My),Ty=new Array(3).concat("e0f3dba8ddb543a2ca","f0f9e8bae4bc7bccc42b8cbe","f0f9e8bae4bc7bccc443a2ca0868ac","f0f9e8ccebc5a8ddb57bccc443a2ca0868ac","f0f9e8ccebc5a8ddb57bccc44eb3d32b8cbe08589e","f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe08589e","f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe0868ac084081").map(af),Ny=uf(Ty),Sy=new Array(3).concat("fee8c8fdbb84e34a33","fef0d9fdcc8afc8d59d7301f","fef0d9fdcc8afc8d59e34a33b30000","fef0d9fdd49efdbb84fc8d59e34a33b30000","fef0d9fdd49efdbb84fc8d59ef6548d7301f990000","fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301f990000","fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301fb300007f0000").map(af),Ey=uf(Sy),ky=new Array(3).concat("ece2f0a6bddb1c9099","f6eff7bdc9e167a9cf02818a","f6eff7bdc9e167a9cf1c9099016c59","f6eff7d0d1e6a6bddb67a9cf1c9099016c59","f6eff7d0d1e6a6bddb67a9cf3690c002818a016450","fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016450","fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016c59014636").map(af),Cy=uf(ky),Py=new Array(3).concat("ece7f2a6bddb2b8cbe","f1eef6bdc9e174a9cf0570b0","f1eef6bdc9e174a9cf2b8cbe045a8d","f1eef6d0d1e6a6bddb74a9cf2b8cbe045a8d","f1eef6d0d1e6a6bddb74a9cf3690c00570b0034e7b","fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0034e7b","fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0045a8d023858").map(af),zy=uf(Py),Ry=new Array(3).concat("e7e1efc994c7dd1c77","f1eef6d7b5d8df65b0ce1256","f1eef6d7b5d8df65b0dd1c77980043","f1eef6d4b9dac994c7df65b0dd1c77980043","f1eef6d4b9dac994c7df65b0e7298ace125691003f","f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125691003f","f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125698004367001f").map(af),Ly=uf(Ry),Dy=new Array(3).concat("fde0ddfa9fb5c51b8a","feebe2fbb4b9f768a1ae017e","feebe2fbb4b9f768a1c51b8a7a0177","feebe2fcc5c0fa9fb5f768a1c51b8a7a0177","feebe2fcc5c0fa9fb5f768a1dd3497ae017e7a0177","fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a0177","fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a017749006a").map(af),Uy=uf(Dy),qy=new Array(3).concat("edf8b17fcdbb2c7fb8","ffffcca1dab441b6c4225ea8","ffffcca1dab441b6c42c7fb8253494","ffffccc7e9b47fcdbb41b6c42c7fb8253494","ffffccc7e9b47fcdbb41b6c41d91c0225ea80c2c84","ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea80c2c84","ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea8253494081d58").map(af),Oy=uf(qy),Yy=new Array(3).concat("f7fcb9addd8e31a354","ffffccc2e69978c679238443","ffffccc2e69978c67931a354006837","ffffccd9f0a3addd8e78c67931a354006837","ffffccd9f0a3addd8e78c67941ab5d238443005a32","ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443005a32","ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443006837004529").map(af),By=uf(Yy),Fy=new Array(3).concat("fff7bcfec44fd95f0e","ffffd4fed98efe9929cc4c02","ffffd4fed98efe9929d95f0e993404","ffffd4fee391fec44ffe9929d95f0e993404","ffffd4fee391fec44ffe9929ec7014cc4c028c2d04","ffffe5fff7bcfee391fec44ffe9929ec7014cc4c028c2d04","ffffe5fff7bcfee391fec44ffe9929ec7014cc4c02993404662506").map(af),Iy=uf(Fy),jy=new Array(3).concat("ffeda0feb24cf03b20","ffffb2fecc5cfd8d3ce31a1c","ffffb2fecc5cfd8d3cf03b20bd0026","ffffb2fed976feb24cfd8d3cf03b20bd0026","ffffb2fed976feb24cfd8d3cfc4e2ae31a1cb10026","ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cb10026","ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cbd0026800026").map(af),Hy=uf(jy),Xy=new Array(3).concat("deebf79ecae13182bd","eff3ffbdd7e76baed62171b5","eff3ffbdd7e76baed63182bd08519c","eff3ffc6dbef9ecae16baed63182bd08519c","eff3ffc6dbef9ecae16baed64292c62171b5084594","f7fbffdeebf7c6dbef9ecae16baed64292c62171b5084594","f7fbffdeebf7c6dbef9ecae16baed64292c62171b508519c08306b").map(af),Gy=uf(Xy),Vy=new Array(3).concat("e5f5e0a1d99b31a354","edf8e9bae4b374c476238b45","edf8e9bae4b374c47631a354006d2c","edf8e9c7e9c0a1d99b74c47631a354006d2c","edf8e9c7e9c0a1d99b74c47641ab5d238b45005a32","f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45005a32","f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45006d2c00441b").map(af),$y=uf(Vy),Wy=new Array(3).concat("f0f0f0bdbdbd636363","f7f7f7cccccc969696525252","f7f7f7cccccc969696636363252525","f7f7f7d9d9d9bdbdbd969696636363252525","f7f7f7d9d9d9bdbdbd969696737373525252252525","fffffff0f0f0d9d9d9bdbdbd969696737373525252252525","fffffff0f0f0d9d9d9bdbdbd969696737373525252252525000000").map(af),Zy=uf(Wy),Qy=new Array(3).concat("efedf5bcbddc756bb1","f2f0f7cbc9e29e9ac86a51a3","f2f0f7cbc9e29e9ac8756bb154278f","f2f0f7dadaebbcbddc9e9ac8756bb154278f","f2f0f7dadaebbcbddc9e9ac8807dba6a51a34a1486","fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a34a1486","fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a354278f3f007d").map(af),Jy=uf(Qy),Ky=new Array(3).concat("fee0d2fc9272de2d26","fee5d9fcae91fb6a4acb181d","fee5d9fcae91fb6a4ade2d26a50f15","fee5d9fcbba1fc9272fb6a4ade2d26a50f15","fee5d9fcbba1fc9272fb6a4aef3b2ccb181d99000d","fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181d99000d","fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181da50f1567000d").map(af),t_=uf(Ky),n_=new Array(3).concat("fee6cefdae6be6550d","feeddefdbe85fd8d3cd94701","feeddefdbe85fd8d3ce6550da63603","feeddefdd0a2fdae6bfd8d3ce6550da63603","feeddefdd0a2fdae6bfd8d3cf16913d948018c2d04","fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d948018c2d04","fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d94801a636037f2704").map(af),e_=uf(n_),r_=bl(Wt(300,.5,0),Wt(-240,.5,1)),i_=bl(Wt(-100,.75,.35),Wt(80,1.5,.8)),o_=bl(Wt(260,.75,.35),Wt(80,1.5,.8)),a_=Wt(),u_=ff(af("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")),f_=ff(af("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")),c_=ff(af("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")),s_=ff(af("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921")),l_=Math.abs,h_=Math.atan2,d_=Math.cos,p_=Math.max,v_=Math.min,g_=Math.sin,y_=Math.sqrt,__=1e-12,b_=Math.PI,m_=b_/2,x_=2*b_;yf.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:this._context.lineTo(t,n)}}};var w_=Nf(_f);Tf.prototype={areaStart:function(){this._curve.areaStart()},areaEnd:function(){this._curve.areaEnd()},lineStart:function(){this._curve.lineStart()},lineEnd:function(){this._curve.lineEnd()},point:function(t,n){this._curve.point(n*Math.sin(t),n*-Math.cos(t))}};var M_=Array.prototype.slice,A_={draw:function(t,n){var e=Math.sqrt(n/b_);t.moveTo(e,0),t.arc(0,0,e,0,x_)}},T_={draw:function(t,n){var e=Math.sqrt(n/5)/2;t.moveTo(-3*e,-e),t.lineTo(-e,-e),t.lineTo(-e,-3*e),t.lineTo(e,-3*e),t.lineTo(e,-e),t.lineTo(3*e,-e),t.lineTo(3*e,e),t.lineTo(e,e),t.lineTo(e,3*e),t.lineTo(-e,3*e),t.lineTo(-e,e),t.lineTo(-3*e,e),t.closePath()}},N_=Math.sqrt(1/3),S_=2*N_,E_={draw:function(t,n){var e=Math.sqrt(n/S_),r=e*N_;t.moveTo(0,-e),t.lineTo(r,0),t.lineTo(0,e),t.lineTo(-r,0),t.closePath()}},k_=Math.sin(b_/10)/Math.sin(7*b_/10),C_=Math.sin(x_/10)*k_,P_=-Math.cos(x_/10)*k_,z_={draw:function(t,n){var e=Math.sqrt(.8908130915292852*n),r=C_*e,i=P_*e;t.moveTo(0,-e),t.lineTo(r,i);for(var o=1;o<5;++o){var a=x_*o/5,u=Math.cos(a),f=Math.sin(a);t.lineTo(f*e,-u*e),t.lineTo(u*r-f*i,f*r+u*i)}t.closePath()}},R_={draw:function(t,n){var e=Math.sqrt(n),r=-e/2;t.rect(r,r,e,e)}},L_=Math.sqrt(3),D_={draw:function(t,n){var e=-Math.sqrt(n/(3*L_));t.moveTo(0,2*e),t.lineTo(-L_*e,-e),t.lineTo(L_*e,-e),t.closePath()}},U_=Math.sqrt(3)/2,q_=1/Math.sqrt(12),O_=3*(q_/2+1),Y_={draw:function(t,n){var e=Math.sqrt(n/O_),r=e/2,i=e*q_,o=r,a=e*q_+e,u=-o,f=a;t.moveTo(r,i),t.lineTo(o,a),t.lineTo(u,f),t.lineTo(-.5*r-U_*i,U_*r+-.5*i),t.lineTo(-.5*o-U_*a,U_*o+-.5*a),t.lineTo(-.5*u-U_*f,U_*u+-.5*f),t.lineTo(-.5*r+U_*i,-.5*i-U_*r),t.lineTo(-.5*o+U_*a,-.5*a-U_*o),t.lineTo(-.5*u+U_*f,-.5*f-U_*u),t.closePath()}},B_=[A_,T_,E_,R_,z_,D_,Y_];Yf.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:Of(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:Of(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}},Bf.prototype={areaStart:qf,areaEnd:qf,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._x2=t,this._y2=n;break;case 1:this._point=2,this._x3=t,this._y3=n;break;case 2:this._point=3,this._x4=t,this._y4=n,this._context.moveTo((this._x0+4*this._x1+t)/6,(this._y0+4*this._y1+n)/6);break;default:Of(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}},Ff.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var e=(this._x0+4*this._x1+t)/6,r=(this._y0+4*this._y1+n)/6;this._line?this._context.lineTo(e,r):this._context.moveTo(e,r);break;case 3:this._point=4;default:Of(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}},If.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var t=this._x,n=this._y,e=t.length-1;if(e>0)for(var r,i=t[0],o=n[0],a=t[e]-i,u=n[e]-o,f=-1;++f<=e;)r=f/e,this._basis.point(this._beta*t[f]+(1-this._beta)*(i+r*a),this._beta*n[f]+(1-this._beta)*(o+r*u));this._x=this._y=null,this._basis.lineEnd()},point:function(t,n){this._x.push(+t),this._y.push(+n)}};var F_=function t(n){function e(t){return 1===n?new Yf(t):new If(t,n)}return e.beta=function(n){return t(+n)},e}(.85);Hf.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:jf(this,this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2,this._x1=t,this._y1=n;break;case 2:this._point=3;default:jf(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var I_=function t(n){function e(t){return new Hf(t,n)}return e.tension=function(n){return t(+n)},e}(0);Xf.prototype={areaStart:qf,areaEnd:qf,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._x3=t,this._y3=n;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=n);break;case 2:this._point=3,this._x5=t,this._y5=n;break;default:jf(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var j_=function t(n){function e(t){return new Xf(t,n)}return e.tension=function(n){return t(+n)},e}(0);Gf.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:jf(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var H_=function t(n){function e(t){return new Gf(t,n)}return e.tension=function(n){return t(+n)},e}(0);$f.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:this.point(this._x2,this._y2)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3;default:Vf(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var X_=function t(n){function e(t){return n?new $f(t,n):new Hf(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);Wf.prototype={areaStart:qf,areaEnd:qf,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=t,this._y3=n;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=n);break;case 2:this._point=3,this._x5=t,this._y5=n;break;default:Vf(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var G_=function t(n){function e(t){return n?new Wf(t,n):new Xf(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);Zf.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:Vf(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var V_=function t(n){function e(t){return n?new Zf(t,n):new Gf(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);Qf.prototype={areaStart:qf,areaEnd:qf,lineStart:function(){this._point=0},lineEnd:function(){this._point&&this._context.closePath()},point:function(t,n){t=+t,n=+n,this._point?this._context.lineTo(t,n):(this._point=1,this._context.moveTo(t,n))}},ec.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:nc(this,this._t0,tc(this,this._t0))}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){var e=NaN;if(t=+t,n=+n,t!==this._x1||n!==this._y1){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3,nc(this,tc(this,e=Kf(this,t,n)),e);break;default:nc(this,this._t0,e=Kf(this,t,n))}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n,this._t0=e}}},(rc.prototype=Object.create(ec.prototype)).point=function(t,n){ec.prototype.point.call(this,n,t)},ic.prototype={moveTo:function(t,n){this._context.moveTo(n,t)},closePath:function(){this._context.closePath()},lineTo:function(t,n){this._context.lineTo(n,t)},bezierCurveTo:function(t,n,e,r,i,o){this._context.bezierCurveTo(n,t,r,e,o,i)}},oc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=[],this._y=[]},lineEnd:function(){var t=this._x,n=this._y,e=t.length;if(e)if(this._line?this._context.lineTo(t[0],n[0]):this._context.moveTo(t[0],n[0]),2===e)this._context.lineTo(t[1],n[1]);else for(var r=ac(t),i=ac(n),o=0,a=1;a=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,n),this._context.lineTo(t,n);else{var e=this._x*(1-this._t)+t*this._t;this._context.lineTo(e,this._y),this._context.lineTo(e,n)}}this._x=t,this._y=n}},gc.prototype={constructor:gc,insert:function(t,n){var e,r,i;if(t){if(n.P=t,n.N=t.N,t.N&&(t.N.P=n),t.N=n,t.R){for(t=t.R;t.L;)t=t.L;t.L=n}else t.R=n;e=t}else this._?(t=mc(this._),n.P=null,n.N=t,t.P=t.L=n,e=t):(n.P=n.N=null,this._=n,e=null);for(n.L=n.R=null,n.U=e,n.C=!0,t=n;e&&e.C;)e===(r=e.U).L?(i=r.R)&&i.C?(e.C=i.C=!1,r.C=!0,t=r):(t===e.R&&(_c(this,e),e=(t=e).U),e.C=!1,r.C=!0,bc(this,r)):(i=r.L)&&i.C?(e.C=i.C=!1,r.C=!0,t=r):(t===e.L&&(bc(this,e),e=(t=e).U),e.C=!1,r.C=!0,_c(this,r)),e=t.U;this._.C=!1},remove:function(t){t.N&&(t.N.P=t.P),t.P&&(t.P.N=t.N),t.N=t.P=null;var n,e,r,i=t.U,o=t.L,a=t.R;if(e=o?a?mc(a):o:a,i?i.L===t?i.L=e:i.R=e:this._=e,o&&a?(r=e.C,e.C=t.C,e.L=o,o.U=e,e!==a?(i=e.U,e.U=t.U,t=e.R,i.L=t,e.R=a,a.U=e):(e.U=i,i=e,t=e.R)):(r=t.C,t=e),t&&(t.U=i),!r)if(t&&t.C)t.C=!1;else{do{if(t===this._)break;if(t===i.L){if((n=i.R).C&&(n.C=!1,i.C=!0,_c(this,i),n=i.R),n.L&&n.L.C||n.R&&n.R.C){n.R&&n.R.C||(n.L.C=!1,n.C=!0,bc(this,n),n=i.R),n.C=i.C,i.C=n.R.C=!1,_c(this,i),t=this._;break}}else if((n=i.L).C&&(n.C=!1,i.C=!0,bc(this,i),n=i.L),n.L&&n.L.C||n.R&&n.R.C){n.L&&n.L.C||(n.R.C=!1,n.C=!0,_c(this,n),n=i.L),n.C=i.C,i.C=n.L.C=!1,bc(this,i),t=this._;break}n.C=!0,t=i,i=i.U}while(!t.C);t&&(t.C=!1)}}};var $_,W_,Z_,Q_,J_,K_=[],tb=[],nb=1e-6,eb=1e-12;Oc.prototype={constructor:Oc,polygons:function(){var t=this.edges;return this.cells.map(function(n){var e=n.halfedges.map(function(e){return Sc(n,t[e])});return e.data=n.site.data,e})},triangles:function(){var t=[],n=this.edges;return this.cells.forEach(function(e,r){if(o=(i=e.halfedges).length)for(var i,o,a,u=e.site,f=-1,c=n[i[o-1]],s=c.left===u?c.right:c.left;++f=u)return null;var f=t-i.site[0],c=n-i.site[1],s=f*f+c*c;do{i=o.cells[r=a],a=null,i.halfedges.forEach(function(e){var r=o.edges[e],u=r.left;if(u!==i.site&&u||(u=r.right)){var f=t-u[0],c=n-u[1],l=f*f+c*c;lt?1:n>=t?0:NaN},t.deviation=a,t.extent=u,t.histogram=function(){function t(t){var i,o,a=t.length,u=new Array(a);for(i=0;il;)h.pop(),--p;var v,g=new Array(p+1);for(i=0;i<=p;++i)(v=g[i]=[]).x0=i>0?h[i-1]:c,v.x1=i=o.length)return null!=e&&n.sort(e),null!=r?r(n):n;for(var f,c,s,l=-1,h=n.length,d=o[i++],p=le(),v=a();++lo.length)return t;var i,u=a[e-1];return null!=r&&e>=o.length?i=t.entries():(i=[],t.each(function(t,r){i.push({key:r,values:n(t,e)})})),null!=u?i.sort(function(t,n){return u(t.key,n.key)}):i}var e,r,i,o=[],a=[];return i={object:function(n){return t(n,0,he,de)},map:function(n){return t(n,0,pe,ve)},entries:function(e){return n(t(e,0,pe,ve),0)},key:function(t){return o.push(t),i},sortKeys:function(t){return a[o.length-1]=t,i},sortValues:function(t){return e=t,i},rollup:function(t){return r=t,i}}},t.set=ye,t.map=le,t.keys=function(t){var n=[];for(var e in t)n.push(e);return n},t.values=function(t){var n=[];for(var e in t)n.push(t[e]);return n},t.entries=function(t){var n=[];for(var e in t)n.push({key:e,value:t[e]});return n},t.color=kt,t.rgb=Rt,t.hsl=Ut,t.lab=Bt,t.hcl=Vt,t.lch=function(t,n,e,r){return 1===arguments.length?Gt(t):new $t(e,n,t,null==r?1:r)},t.gray=function(t,n){return new Ft(t,0,0,null==n?1:n)},t.cubehelix=Wt,t.contours=we,t.contourDensity=function(){function t(t){var e=new Float32Array(v*y),r=new Float32Array(v*y);t.forEach(function(t,n,r){var i=a(t,n,r)+p>>h,o=u(t,n,r)+p>>h;i>=0&&i=0&&o>h),Ae({width:v,height:y,data:r},{width:v,height:y,data:e},l>>h),Me({width:v,height:y,data:e},{width:v,height:y,data:r},l>>h),Ae({width:v,height:y,data:r},{width:v,height:y,data:e},l>>h),Me({width:v,height:y,data:e},{width:v,height:y,data:r},l>>h),Ae({width:v,height:y,data:r},{width:v,height:y,data:e},l>>h);var i=_(e);if(!Array.isArray(i)){var o=g(e);i=d(0,o,i),(i=s(0,Math.floor(o/i)*i,i)).shift()}return we().thresholds(i).size([v,y])(e).map(n)}function n(t){return t.value*=Math.pow(2,-2*h),t.coordinates.forEach(e),t}function e(t){t.forEach(r)}function r(t){t.forEach(i)}function i(t){t[0]=t[0]*Math.pow(2,h)-p,t[1]=t[1]*Math.pow(2,h)-p}function o(){return p=3*l,v=f+2*p>>h,y=c+2*p>>h,t}var a=Te,u=Ne,f=960,c=500,l=20,h=2,p=3*l,v=f+2*p>>h,y=c+2*p>>h,_=be(20);return t.x=function(n){return arguments.length?(a="function"==typeof n?n:be(+n),t):a},t.y=function(n){return arguments.length?(u="function"==typeof n?n:be(+n),t):u},t.size=function(t){if(!arguments.length)return[f,c];var n=Math.ceil(t[0]),e=Math.ceil(t[1]);if(!(n>=0||n>=0))throw new Error("invalid size");return f=n,c=e,o()},t.cellSize=function(t){if(!arguments.length)return 1<=1))throw new Error("invalid cell size");return h=Math.floor(Math.log(t)/Math.LN2),o()},t.thresholds=function(n){return arguments.length?(_="function"==typeof n?n:Array.isArray(n)?be(Lh.call(n)):be(n),t):_},t.bandwidth=function(t){if(!arguments.length)return Math.sqrt(l*(l+1));if(!((t=+t)>=0))throw new Error("invalid bandwidth");return l=Math.round((Math.sqrt(4*t*t+1)-1)/2),o()},t},t.dispatch=N,t.drag=function(){function n(t){t.on("mousedown.drag",e).filter(g).on("touchstart.drag",o).on("touchmove.drag",a).on("touchend.drag touchcancel.drag",u).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function e(){if(!h&&d.apply(this,arguments)){var n=f("mouse",p.apply(this,arguments),pt,this,arguments);n&&(ct(t.event.view).on("mousemove.drag",r,!0).on("mouseup.drag",i,!0),_t(t.event.view),gt(),l=!1,c=t.event.clientX,s=t.event.clientY,n("start"))}}function r(){if(yt(),!l){var n=t.event.clientX-c,e=t.event.clientY-s;l=n*n+e*e>m}y.mouse("drag")}function i(){ct(t.event.view).on("mousemove.drag mouseup.drag",null),bt(t.event.view,l),yt(),y.mouse("end")}function o(){if(d.apply(this,arguments)){var n,e,r=t.event.changedTouches,i=p.apply(this,arguments),o=r.length;for(n=0;nf+d||ic+d||or.index){var p=f-u.x-u.vx,v=c-u.y-u.vy,g=p*p+v*v;gt.r&&(t.r=t[n].r)}function r(){if(i){var n,e,r=i.length;for(o=new Array(r),n=0;n=s)){(t.data!==o||t.next)&&(0===i&&(i=qe(),d+=i*i),0===f&&(f=qe(),d+=f*f),d1?(null==n?l.remove(t):l.set(t,i(n)),o):l.get(t)},find:function(n,e,r){var i,o,a,u,f,c=0,s=t.length;for(null==r?r=1/0:r*=r,c=0;c1?(d.on(t,n),o):d.on(t)}}},t.forceX=function(t){function n(t){for(var n,e=0,a=r.length;eqr(r[0],r[1])&&(r[1]=i[1]),qr(i[0],r[1])>qr(r[0],r[1])&&(r[0]=i[0])):o.push(r=i);for(a=-1/0,n=0,r=o[e=o.length-1];n<=e;r=i,++n)i=o[n],(u=qr(r[1],i[0]))>a&&(a=u,vd=i[0],yd=r[1])}return Md=Ad=null,vd===1/0||gd===1/0?[[NaN,NaN],[NaN,NaN]]:[[vd,gd],[yd,_d]]},t.geoCentroid=function(t){Td=Nd=Sd=Ed=kd=Cd=Pd=zd=Rd=Ld=Dd=0,_r(t,vp);var n=Rd,e=Ld,r=Dd,i=n*n+e*e+r*r;return i=.12&&i<.234&&r>=-.425&&r<-.214?c:i>=.166&&i<.234&&r>=-.214&&r<-.115?s:f).invert(t)},t.stream=function(t){return e&&r===t?e:e=function(t){var n=t.length;return{point:function(e,r){for(var i=-1;++i2?t[2]+90:90]):(t=e(),[t[0],t[1],t[2]-90])},e([0,0,90]).scale(159.155)},t.geoTransverseMercatorRaw=To,t.geoRotation=ri,t.geoStream=_r,t.geoTransform=function(t){return{stream:Zi(t)}},t.cluster=function(){function t(t){var o,a=0;t.eachAfter(function(t){var e=t.children;e?(t.x=function(t){return t.reduce(So,0)/t.length}(e),t.y=function(t){return 1+t.reduce(Eo,0)}(e)):(t.x=o?a+=n(t,o):0,t.y=0,o=t)});var u=function(t){for(var n;n=t.children;)t=n[0];return t}(t),f=function(t){for(var n;n=t.children;)t=n[n.length-1];return t}(t),c=u.x-n(u,f)/2,s=f.x+n(f,u)/2;return t.eachAfter(i?function(n){n.x=(n.x-t.x)*e,n.y=(t.y-n.y)*r}:function(n){n.x=(n.x-c)/(s-c)*e,n.y=(1-(t.y?n.y/t.y:1))*r})}var n=No,e=1,r=1,i=!1;return t.separation=function(e){return arguments.length?(n=e,t):n},t.size=function(n){return arguments.length?(i=!1,e=+n[0],r=+n[1],t):i?null:[e,r]},t.nodeSize=function(n){return arguments.length?(i=!0,e=+n[0],r=+n[1],t):i?[e,r]:null},t},t.hierarchy=Co,t.pack=function(){function t(t){return t.x=e/2,t.y=r/2,n?t.eachBefore(Zo(n)).eachAfter(Qo(i,.5)).eachBefore(Jo(1)):t.eachBefore(Zo(Wo)).eachAfter(Qo(Vo,1)).eachAfter(Qo(i,t.r/Math.min(e,r))).eachBefore(Jo(Math.min(e,r)/(2*t.r))),t}var n=null,e=1,r=1,i=Vo;return t.radius=function(e){return arguments.length?(n=function(t){return null==t?null:Go(t)}(e),t):n},t.size=function(n){return arguments.length?(e=+n[0],r=+n[1],t):[e,r]},t.padding=function(n){return arguments.length?(i="function"==typeof n?n:$o(+n),t):i},t},t.packSiblings=function(t){return Xo(t),t},t.packEnclose=Do,t.partition=function(){function t(t){var o=t.height+1;return t.x0=t.y0=r,t.x1=n,t.y1=e/o,t.eachBefore(function(t,n){return function(e){e.children&&ta(e,e.x0,t*(e.depth+1)/n,e.x1,t*(e.depth+2)/n);var i=e.x0,o=e.y0,a=e.x1-r,u=e.y1-r;a0)throw new Error("cycle");return o}var n=na,e=ea;return t.id=function(e){return arguments.length?(n=Go(e),t):n},t.parentId=function(n){return arguments.length?(e=Go(n),t):e},t},t.tree=function(){function t(t){var f=function(t){for(var n,e,r,i,o,a=new fa(t,0),u=[a];n=u.pop();)if(r=n._.children)for(n.children=new Array(o=r.length),i=o-1;i>=0;--i)u.push(e=n.children[i]=new fa(r[i],i)),e.parent=n;return(a.parent=new fa(null,0)).children=[a],a}(t);if(f.eachAfter(n),f.parent.m=-f.z,f.eachBefore(e),u)t.eachBefore(r);else{var c=t,s=t,l=t;t.eachBefore(function(t){t.xs.x&&(s=t),t.depth>l.depth&&(l=t)});var h=c===s?1:i(c,s)/2,d=h-c.x,p=o/(s.x+h+d),v=a/(l.depth||1);t.eachBefore(function(t){t.x=(t.x+d)*p,t.y=t.depth*v})}return t}function n(t){var n=t.children,e=t.parent.children,r=t.i?e[t.i-1]:null;if(n){(function(t){for(var n,e=0,r=0,i=t.children,o=i.length;--o>=0;)(n=i[o]).z+=e,n.m+=e,e+=n.s+(r+=n.c)})(t);var o=(n[0].z+n[n.length-1].z)/2;r?(t.z=r.z+i(t._,r._),t.m=t.z-o):t.z=o}else r&&(t.z=r.z+i(t._,r._));t.parent.A=function(t,n,e){if(n){for(var r,o=t,a=t,u=n,f=o.parent.children[0],c=o.m,s=a.m,l=u.m,h=f.m;u=oa(u),o=ia(o),u&&o;)f=ia(f),(a=oa(a)).a=t,(r=u.z+l-o.z-c+i(u._,o._))>0&&(aa(ua(u,t,e),t,r),c+=r,s+=r),l+=u.m,c+=o.m,h+=f.m,s+=a.m;u&&!oa(a)&&(a.t=u,a.m+=l-s),o&&!ia(f)&&(f.t=o,f.m+=c-h,e=t)}return e}(t,r,t.parent.A||e[0])}function e(t){t._.x=t.z+t.parent.m,t.m+=t.parent.m}function r(t){t.x*=o,t.y=t.depth*a}var i=ra,o=1,a=1,u=null;return t.separation=function(n){return arguments.length?(i=n,t):i},t.size=function(n){return arguments.length?(u=!1,o=+n[0],a=+n[1],t):u?null:[o,a]},t.nodeSize=function(n){return arguments.length?(u=!0,o=+n[0],a=+n[1],t):u?[o,a]:null},t},t.treemap=function(){function t(t){return t.x0=t.y0=0,t.x1=i,t.y1=o,t.eachBefore(n),a=[0],r&&t.eachBefore(Ko),t}function n(t){var n=a[t.depth],r=t.x0+n,i=t.y0+n,o=t.x1-n,h=t.y1-n;o=n-1){var c=f[t];return c.x0=r,c.y0=i,c.x1=a,void(c.y1=u)}for(var l=s[t],h=e/2+l,d=t+1,p=n-1;d>>1;s[v]u-i){var _=(r*y+a*g)/e;o(t,d,g,r,i,_,u),o(d,n,y,_,i,a,u)}else{var b=(i*y+u*g)/e;o(t,d,g,r,i,a,b),o(d,n,y,r,b,a,u)}}var a,u,f=t.children,c=f.length,s=new Array(c+1);for(s[0]=u=a=0;a=0;--n)c.push(t[r[o[n]][2]]);for(n=+u;nu!=c>u&&a<(f-e)*(u-r)/(c-r)+e&&(s=!s),f=e,c=r;return s},t.polygonLength=function(t){for(var n,e,r=-1,i=t.length,o=t[i-1],a=o[0],u=o[1],f=0;++r1)&&(t-=Math.floor(t));var n=Math.abs(t-.5);return a_.h=360*t-100,a_.s=1.5-1.5*n,a_.l=.8-.9*n,a_+""},t.interpolateWarm=i_,t.interpolateCool=o_,t.interpolateViridis=u_,t.interpolateMagma=f_,t.interpolateInferno=c_,t.interpolatePlasma=s_,t.create=function(t){return ct(C(t).call(document.documentElement))},t.creator=C,t.local=st,t.matcher=ys,t.mouse=pt,t.namespace=k,t.namespaces=ds,t.clientPoint=dt,t.select=ct,t.selectAll=function(t){return"string"==typeof t?new ut([document.querySelectorAll(t)],[document.documentElement]):new ut([null==t?[]:t],ms)},t.selection=ft,t.selector=z,t.selectorAll=L,t.style=F,t.touch=vt,t.touches=function(t,n){null==n&&(n=ht().touches);for(var e=0,r=n?n.length:0,i=new Array(r);eh;if(f||(f=t=ie()),l__)if(p>x_-__)f.moveTo(l*d_(h),l*g_(h)),f.arc(0,0,l,h,d,!v),s>__&&(f.moveTo(s*d_(d),s*g_(d)),f.arc(0,0,s,d,h,v));else{var g,y,_=h,b=d,m=h,x=d,w=p,M=p,A=u.apply(this,arguments)/2,T=A>__&&(i?+i.apply(this,arguments):y_(s*s+l*l)),N=v_(l_(l-s)/2,+r.apply(this,arguments)),S=N,E=N;if(T>__){var k=sf(T/s*g_(A)),C=sf(T/l*g_(A));(w-=2*k)>__?(k*=v?1:-1,m+=k,x-=k):(w=0,m=x=(h+d)/2),(M-=2*C)>__?(C*=v?1:-1,_+=C,b-=C):(M=0,_=b=(h+d)/2)}var P=l*d_(_),z=l*g_(_),R=s*d_(x),L=s*g_(x);if(N>__){var D=l*d_(b),U=l*g_(b),q=s*d_(m),O=s*g_(m);if(p__?function(t,n,e,r,i,o,a,u){var f=e-t,c=r-n,s=a-i,l=u-o,h=(s*(n-o)-l*(t-i))/(l*f-s*c);return[t+h*f,n+h*c]}(P,z,q,O,D,U,R,L):[R,L],B=P-Y[0],F=z-Y[1],I=D-Y[0],j=U-Y[1],H=1/g_(function(t){return t>1?0:t<-1?b_:Math.acos(t)}((B*I+F*j)/(y_(B*B+F*F)*y_(I*I+j*j)))/2),X=y_(Y[0]*Y[0]+Y[1]*Y[1]);S=v_(N,(s-X)/(H-1)),E=v_(N,(l-X)/(H+1))}}M>__?E>__?(g=gf(q,O,P,z,l,E,v),y=gf(D,U,R,L,l,E,v),f.moveTo(g.cx+g.x01,g.cy+g.y01),E__&&w>__?S>__?(g=gf(R,L,D,U,s,-S,v),y=gf(P,z,q,O,s,-S,v),f.lineTo(g.cx+g.x01,g.cy+g.y01),S0&&(d+=l);for(null!=e?p.sort(function(t,n){return e(v[t],v[n])}):null!=r&&p.sort(function(n,e){return r(t[n],t[e])}),u=0,c=d?(y-h*b)/d:0;u0?l*c:0)+b,v[f]={data:t[f],index:u,value:l,startAngle:g,endAngle:s,padAngle:_};return v}var n=Af,e=Mf,r=null,i=cf(0),o=cf(x_),a=cf(0);return t.value=function(e){return arguments.length?(n="function"==typeof e?e:cf(+e),t):n},t.sortValues=function(n){return arguments.length?(e=n,r=null,t):e},t.sort=function(n){return arguments.length?(r=n,e=null,t):r},t.startAngle=function(n){return arguments.length?(i="function"==typeof n?n:cf(+n),t):i},t.endAngle=function(n){return arguments.length?(o="function"==typeof n?n:cf(+n),t):o},t.padAngle=function(n){return arguments.length?(a="function"==typeof n?n:cf(+n),t):a},t},t.areaRadial=kf,t.radialArea=kf,t.lineRadial=Ef,t.radialLine=Ef,t.pointRadial=Cf,t.linkHorizontal=function(){return Rf(Lf)},t.linkVertical=function(){return Rf(Df)},t.linkRadial=function(){var t=Rf(Uf);return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t},t.symbol=function(){function t(){var t;if(r||(r=t=ie()),n.apply(this,arguments).draw(r,+e.apply(this,arguments)),t)return r=null,t+""||null}var n=cf(A_),e=cf(64),r=null;return t.type=function(e){return arguments.length?(n="function"==typeof e?e:cf(e),t):n},t.size=function(n){return arguments.length?(e="function"==typeof n?n:cf(+n),t):e},t.context=function(n){return arguments.length?(r=null==n?null:n,t):r},t},t.symbols=B_,t.symbolCircle=A_,t.symbolCross=T_,t.symbolDiamond=E_,t.symbolSquare=R_,t.symbolStar=z_,t.symbolTriangle=D_,t.symbolWye=Y_,t.curveBasisClosed=function(t){return new Bf(t)},t.curveBasisOpen=function(t){return new Ff(t)},t.curveBasis=function(t){return new Yf(t)},t.curveBundle=F_,t.curveCardinalClosed=j_,t.curveCardinalOpen=H_,t.curveCardinal=I_,t.curveCatmullRomClosed=G_,t.curveCatmullRomOpen=V_,t.curveCatmullRom=X_,t.curveLinearClosed=function(t){return new Qf(t)},t.curveLinear=_f,t.curveMonotoneX=function(t){return new ec(t)},t.curveMonotoneY=function(t){return new rc(t)},t.curveNatural=function(t){return new oc(t)},t.curveStep=function(t){return new uc(t,.5)},t.curveStepAfter=function(t){return new uc(t,1)},t.curveStepBefore=function(t){return new uc(t,0)},t.stack=function(){function t(t){var o,a,u=n.apply(this,arguments),f=t.length,c=u.length,s=new Array(c);for(o=0;o0){for(var e,r,i,o=0,a=t[0].length;o1)for(var e,r,i,o,a,u,f=0,c=t[n[0]].length;f=0?(r[0]=o,r[1]=o+=i):i<0?(r[1]=a,r[0]=a+=i):r[0]=o},t.stackOffsetNone=fc,t.stackOffsetSilhouette=function(t,n){if((e=t.length)>0){for(var e,r=0,i=t[n[0]],o=i.length;r0&&(r=(e=t[n[0]]).length)>0){for(var e,r,i,o=0,a=1;azl&&e.name===n)return new qn([[t]],sh,n,+r)}return null},t.interrupt=Ln,t.voronoi=function(){function t(t){return new Oc(t.map(function(r,i){var o=[Math.round(n(r,i,t)/nb)*nb,Math.round(e(r,i,t)/nb)*nb];return o.index=i,o.data=r,o}),r)}var n=pc,e=vc,r=null;return t.polygons=function(n){return t(n).polygons()},t.links=function(n){return t(n).links()},t.triangles=function(n){return t(n).triangles()},t.x=function(e){return arguments.length?(n="function"==typeof e?e:dc(+e),t):n},t.y=function(n){return arguments.length?(e="function"==typeof n?n:dc(+n),t):e},t.extent=function(n){return arguments.length?(r=null==n?null:[[+n[0][0],+n[0][1]],[+n[1][0],+n[1][1]]],t):r&&[[r[0][0],r[0][1]],[r[1][0],r[1][1]]]},t.size=function(n){return arguments.length?(r=null==n?null:[[0,0],[+n[0],+n[1]]],t):r&&[r[1][0]-r[0][0],r[1][1]-r[0][1]]},t},t.zoom=function(){function n(t){t.property("__zoom",Gc).on("wheel.zoom",f).on("mousedown.zoom",c).on("dblclick.zoom",s).filter(m).on("touchstart.zoom",l).on("touchmove.zoom",h).on("touchend.zoom touchcancel.zoom",d).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function e(t,n){return(n=Math.max(x[0],Math.min(x[1],n)))===t.k?t:new Bc(n,t.x,t.y)}function r(t,n,e){var r=n[0]-e[0]*t.k,i=n[1]-e[1]*t.k;return r===t.x&&i===t.y?t:new Bc(t.k,r,i)}function i(t){return[(+t[0][0]+ +t[1][0])/2,(+t[0][1]+ +t[1][1])/2]}function o(t,n,e){t.on("start.zoom",function(){a(this,arguments).start()}).on("interrupt.zoom end.zoom",function(){a(this,arguments).end()}).tween("zoom",function(){var t=arguments,r=a(this,t),o=y.apply(this,t),u=e||i(o),f=Math.max(o[1][0]-o[0][0],o[1][1]-o[0][1]),c=this.__zoom,s="function"==typeof n?n.apply(this,t):n,l=A(c.invert(u).concat(f/c.k),s.invert(u).concat(f/s.k));return function(t){if(1===t)t=s;else{var n=l(t),e=f/n[2];t=new Bc(e,u[0]-n[0]*e,u[1]-n[1]*e)}r.zoom(null,t)}})}function a(t,n){for(var e,r=0,i=T.length;rC}n.zoom("mouse",_(r(n.that.__zoom,n.mouse[0]=pt(n.that),n.mouse[1]),n.extent,w))},!0).on("mouseup.zoom",function(){e.on("mousemove.zoom mouseup.zoom",null),bt(t.event.view,n.moved),jc(),n.end()},!0),i=pt(this),o=t.event.clientX,u=t.event.clientY;_t(t.event.view),Ic(),n.mouse=[i,this.__zoom.invert(i)],Ln(this),n.start()}}function s(){if(g.apply(this,arguments)){var i=this.__zoom,a=pt(this),u=i.invert(a),f=i.k*(t.event.shiftKey?.5:2),c=_(r(e(i,f),a,u),y.apply(this,arguments),w);jc(),M>0?ct(this).transition().duration(M).call(o,c,a):ct(this).call(n.transform,c)}}function l(){if(g.apply(this,arguments)){var n,e,r,i,o=a(this,arguments),u=t.event.changedTouches,f=u.length;for(Ic(),e=0;e0})},g={allow:1,allowfullscreen:1,frameborder:1,height:1,longdesc:1,marginheight:1,marginwidth:1,mozallowfullscreen:1,name:1,referrerpolicy:1,sandbox:1,scrolling:1,src:1,srcdoc:1,style:1,webkitallowfullscreen:1,width:1},h={keyup:"onKeyUp",resize:"onResize"},i=function(c){a.each(b.opened().reverse(),function(){return c.isDefaultPrevented()||!1!==this[h[c.type]](c)?void 0:(c.preventDefault(),c.stopPropagation(),!1)})},j=function(c){if(c!==b._globalHandlerInstalled){b._globalHandlerInstalled=c;var d=a.map(h,function(a,c){return c+"."+b.prototype.namespace}).join(" ");a(window)[c?"on":"off"](d,i)}};b.prototype={constructor:b,namespace:"featherlight",targetAttr:"data-featherlight",variant:null,resetCss:!1,background:null,openTrigger:"click",closeTrigger:"click",filter:null,root:"body",openSpeed:250,closeSpeed:250,closeOnClick:"background",closeOnEsc:!0,closeIcon:"✕",loading:"",persist:!1,otherClose:null,beforeOpen:a.noop,beforeContent:a.noop,beforeClose:a.noop,afterOpen:a.noop,afterContent:a.noop,afterClose:a.noop,onKeyUp:a.noop,onResize:a.noop,type:null,contentFilters:["jquery","image","html","ajax","iframe","text"],setup:function(b,c){"object"!=typeof b||b instanceof a!=!1||c||(c=b,b=void 0);var d=a.extend(this,c,{target:b}),e=d.resetCss?d.namespace+"-reset":d.namespace,f=a(d.background||['
','
','",'
'+d.loading+"
","
","
"].join("")),g="."+d.namespace+"-close"+(d.otherClose?","+d.otherClose:"");return d.$instance=f.clone().addClass(d.variant),d.$instance.on(d.closeTrigger+"."+d.namespace,function(b){if(!b.isDefaultPrevented()){var c=a(b.target);("background"===d.closeOnClick&&c.is("."+d.namespace)||"anywhere"===d.closeOnClick||c.closest(g).length)&&(d.close(b),b.preventDefault())}}),this},getContent:function(){if(this.persist!==!1&&this.$content)return this.$content;var b=this,c=this.constructor.contentFilters,d=function(a){return b.$currentTarget&&b.$currentTarget.attr(a)},e=d(b.targetAttr),f=b.target||e||"",g=c[b.type];if(!g&&f in c&&(g=c[f],f=b.target&&e),f=f||d("href")||"",!g)for(var h in c)b[h]&&(g=c[h],f=b[h]);if(!g){var i=f;if(f=null,a.each(b.contentFilters,function(){return g=c[this],g.test&&(f=g.test(i)),!f&&g.regex&&i.match&&i.match(g.regex)&&(f=i),!f}),!f)return"console"in window&&window.console.error("Featherlight: no content filter found "+(i?' for "'+i+'"':" (no target specified)")),!1}return g.process.call(b,f)},setContent:function(b){return this.$instance.removeClass(this.namespace+"-loading"),this.$instance.toggleClass(this.namespace+"-iframe",b.is("iframe")),this.$instance.find("."+this.namespace+"-inner").not(b).slice(1).remove().end().replaceWith(a.contains(this.$instance[0],b[0])?"":b),this.$content=b.addClass(this.namespace+"-inner"),this},open:function(b){var c=this;if(c.$instance.hide().appendTo(c.root),!(b&&b.isDefaultPrevented()||c.beforeOpen(b)===!1)){b&&b.preventDefault();var d=c.getContent();if(d)return e.push(c),j(!0),c.$instance.fadeIn(c.openSpeed),c.beforeContent(b),a.when(d).always(function(a){c.setContent(a),c.afterContent(b)}).then(c.$instance.promise()).done(function(){c.afterOpen(b)})}return c.$instance.detach(),a.Deferred().reject().promise()},close:function(b){var c=this,d=a.Deferred();return c.beforeClose(b)===!1?d.reject():(0===f(c).length&&j(!1),c.$instance.fadeOut(c.closeSpeed,function(){c.$instance.detach(),c.afterClose(b),d.resolve()})),d.promise()},resize:function(a,b){if(a&&b){this.$content.css("width","").css("height","");var c=Math.max(a/(this.$content.parent().width()-1),b/(this.$content.parent().height()-1));c>1&&(c=b/Math.floor(b/c),this.$content.css("width",""+a/c+"px").css("height",""+b/c+"px"))}},chainCallbacks:function(b){for(var c in b)this[c]=a.proxy(b[c],this,a.proxy(this[c],this))}},a.extend(b,{id:0,autoBind:"[data-featherlight]",defaults:b.prototype,contentFilters:{jquery:{regex:/^[#.]\w/,test:function(b){return b instanceof a&&b},process:function(b){return this.persist!==!1?a(b):a(b).clone(!0)}},image:{regex:/\.(png|jpg|jpeg|gif|tiff?|bmp|svg)(\?\S*)?$/i,process:function(b){var c=this,d=a.Deferred(),e=new Image,f=a('');return e.onload=function(){f.naturalWidth=e.width,f.naturalHeight=e.height,d.resolve(f)},e.onerror=function(){d.reject(f)},e.src=b,d.promise()}},html:{regex:/^\s*<[\w!][^<]*>/,process:function(b){return a(b)}},ajax:{regex:/./,process:function(b){var c=a.Deferred(),d=a("
").load(b,function(a,b){"error"!==b&&c.resolve(d.contents()),c.fail()});return c.promise()}},iframe:{process:function(b){var e=new a.Deferred,f=a("