Merge branch 'master' into feature/add-exampleservice
diff --git a/.dockerignore b/.dockerignore
index ea51f67..302c3f5 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,3 +1,4 @@
 views/
 applications/
 xos/tests/api/node_modules
+xos/configurations/cord-pod/images
diff --git a/containers/synchronizer/Dockerfile b/containers/synchronizer/Dockerfile
index c4bb737..2f1e092 100644
--- a/containers/synchronizer/Dockerfile
+++ b/containers/synchronizer/Dockerfile
@@ -1,47 +1,5 @@
 FROM       xosproject/xos
 
-RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
-    openssh-client \
-    python-crypto \
-    python-jinja2 \
-    python-paramiko \
-    python-yaml \
-    python-httplib2 \
-    rsync \
-    supervisor
-
-RUN pip install -U \
-    jinja2
-
-# Install custom Ansible
-RUN \
-    git clone -b release1.8.2 git://github.com/ansible/ansible.git /opt/ansible && \
-    git clone -b release1.8.2 git://github.com/ansible/ansible-modules-extras.git /opt/ansible/lib/ansible/modules/extras && \
-    git clone -b release1.8.2 git://github.com/ansible/ansible-modules-extras.git /opt/ansible/v2/ansible/modules/extras && \
-    git clone git://github.com/sb98052/ansible-modules-core.git /opt/ansible/lib/ansible/modules/core && \
-    git clone git://github.com/sb98052/ansible-modules-core.git /opt/ansible/v2/ansible/modules/core && \
-    # git clone uses cached copy, doesn't pick up latest
-    git -C /opt/ansible pull && \
-    git -C /opt/ansible/lib/ansible/modules/core pull && \
-    git -C /opt/ansible/v2/ansible/modules/core pull
-
-
-# For Observer
-RUN mkdir -p /usr/local/share /bin /etc/ansible
-
-COPY conf/ansible-hosts /etc/ansible/hosts
-
-ADD http://phantomjs.googlecode.com/files/phantomjs-1.7.0-linux-x86_64.tar.bz2 /usr/local/share/
-
-RUN git clone git://git.planet-lab.org/fofum.git /tmp/fofum && \
-    cd /tmp/fofum; python setup.py install && \
-    rm -rf /tmp/fofum && \
-    tar jxvf /usr/local/share/phantomjs-1.7.0-linux-x86_64.tar.bz2 -C /usr/local/share/ && \
-    rm -f /usr/local/share/phantomjs-1.7.0-linux-x86_64.tar.bz2 && \
-    ln -s /usr/local/share/phantomjs-1.7.0-linux-x86_64 /usr/local/share/phantomjs && \
-    ln -s /usr/local/share/phantomjs/bin/phantomjs /bin/phantomjs
-
-
 # Supervisor
 COPY conf/synchronizer.conf /etc/supervisor/conf.d/
 
diff --git a/containers/xos/Dockerfile b/containers/xos/Dockerfile
index e631e23..cbaad65 100644
--- a/containers/xos/Dockerfile
+++ b/containers/xos/Dockerfile
@@ -1,100 +1,26 @@
-FROM       ubuntu:14.04.3
-
-# XXX Workaround for docker bug:
-# https://github.com/docker/docker/issues/6345
-# Kernel 3.15 breaks docker, uss the line below as a workaround
-# until there is a fix
-RUN ln -s -f /bin/true /usr/bin/chfn
-# XXX End workaround
-
-# Install.
-RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
-    curl \
-    gcc \
-    geoip-database \
-    git \
-    graphviz \
-    graphviz-dev \
-    libgeoip1 \
-    libxslt1.1 \
-    libxslt1-dev \
-    libyaml-dev \
-    m4 \
-    pkg-config \
-    python-dev \
-    python-httplib2 \
-    python-pip \
-    python-psycopg2 \
-    python-pycurl \
-    python-setuptools \
-    tar \
-    wget \
-##### observer dependencies
-    python-keystoneclient \
-    python-novaclient \
-    python-neutronclient \
-    python-glanceclient \
-    python-ceilometerclient
-
-RUN pip install \
-    django==1.7 \
-    django-bitfield \
-    django-crispy-forms \
-    django-encrypted-fields \
-    django-extensions \
-    django-filter==0.11.0 \
-    django-geoposition \
-    django-ipware \
-    django_rest_swagger \
-    django-suit==0.3a1 \
-    django-timezones \
-    djangorestframework==3.3.3 \
-    dnslib \
-    jinja2 \
-    lxml \
-    markdown \
-    netaddr \
-    pyOpenSSL \
-    psycopg2 \
-    python-ceilometerclient \
-    python-dateutil \
-    python-keyczar \
-    python-logstash \
-    pygraphviz \
-    pytz \
-    pyyaml \
-    requests
-
-RUN easy_install --upgrade httplib2
-
-RUN easy_install \
-    python_gflags \
-    google_api_python_client \
-    httplib2.ca_certs_locater
-
-ADD http://code.jquery.com/jquery-1.9.1.min.js /usr/local/lib/python2.7/dist-packages/suit/static/suit/js/
+FROM xosproject/xos-base
 
 # Include certificates from Openstack
 ADD local_certs.crt /usr/local/share/ca-certificates/local_certs.crt
 RUN update-ca-certificates
 
-# Install XOS
-RUN git clone git://github.com/open-cloud/xos.git /tmp/xos && \
+# Install and boostrap XOS and Tosca
+ENV XOS_GIT_REPO git://github.com/open-cloud/xos.git
+ENV XOS_GIT_BRANCH master
+
+RUN git clone $XOS_GIT_REPO -b $XOS_GIT_BRANCH /tmp/xos && \
     mv /tmp/xos/xos /opt/ && \
     chmod +x /opt/xos/tools/xos-manage && \
     /opt/xos/tools/xos-manage genkeys
 
-# install Tosca engine
-RUN chmod +x /opt/xos/tosca/run.py
-RUN bash /opt/xos/tosca/install_tosca.sh
-
 EXPOSE 8000
 
-# Set environment variables.
+# Set environment variables
 ENV HOME /root
 
-# Define working directory.
+# Define working directory
 WORKDIR /opt/xos
 
-# Define default command.
+# Define default command
 CMD python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure --makemigrations
+
diff --git a/containers/xos/Dockerfile.base b/containers/xos/Dockerfile.base
new file mode 100644
index 0000000..e430dc8
--- /dev/null
+++ b/containers/xos/Dockerfile.base
@@ -0,0 +1,142 @@
+# Dockerfile.base
+# This image isn't used, but installs the prereqs for the other XOS images
+
+FROM       ubuntu:14.04.3
+
+# XXX Workaround for docker bug:
+# https://github.com/docker/docker/issues/6345
+# Kernel 3.15 breaks docker, uss the line below as a workaround
+# until there is a fix
+RUN ln -s -f /bin/true /usr/bin/chfn
+# XXX End workaround
+
+# Install apt packages
+RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
+    apt-transport-https \
+    curl \
+    gcc \
+    geoip-database \
+    git \
+    graphviz \
+    graphviz-dev \
+    libgeoip1 \
+    libxslt1-dev \
+    libxslt1.1 \
+    libyaml-dev \
+    m4 \
+    openssh-client \
+    pkg-config \
+    python-ceilometerclient \
+    python-crypto \
+    python-dev \
+    python-glanceclient \
+    python-httplib2 \
+    python-jinja2 \
+    python-keystoneclient \
+    python-neutronclient \
+    python-novaclient \
+    python-paramiko \
+    python-pip \
+    python-psycopg2 \
+    python-pycurl \
+    python-setuptools \
+    python-yaml \
+    rsync \
+    supervisor \
+    tar \
+    wget \
+ && rm -rf /var/lib/apt/lists/*
+
+# Install python pacakges with pip
+RUN pip install \
+    django==1.7 \
+    django-bitfield \
+    django-crispy-forms \
+    django-encrypted-fields \
+    django-extensions \
+    django-filter==0.11.0 \
+    django-geoposition \
+    django-ipware \
+    django_rest_swagger \
+    django-suit==0.3a1 \
+    django-timezones \
+    djangorestframework==3.3.3 \
+    dnslib \
+    jinja2 \
+    lxml \
+    markdown \
+    netaddr \
+    pyOpenSSL \
+    psycopg2 \
+    python-ceilometerclient \
+    python-dateutil \
+    python-keyczar \
+    python-logstash \
+    pygraphviz \
+    pytz \
+    pyyaml \
+    requests
+
+# Upgrade jinja2
+RUN pip install -U \
+    jinja2
+
+# Installs with Easy install (should be incorporated into pip?)
+RUN easy_install --upgrade httplib2
+
+RUN easy_install \
+    python_gflags \
+    google_api_python_client \
+    httplib2.ca_certs_locater
+
+# jQuery download w/checksum
+ENV JQUERY_VERSION jquery-1.9.1.min.js
+ENV JQUERY_DL_URL http://code.jquery.com/jquery-1.9.1.min.js
+ENV JQUERY_SHA256 c12f6098e641aaca96c60215800f18f5671039aecf812217fab3c0d152f6adb4
+
+RUN wget $JQUERY_DL_URL && \
+  echo "$JQUERY_SHA256  $JQUERY_VERSION" | sha256sum -c - && \
+  mv $JQUERY_VERSION /usr/local/lib/python2.7/dist-packages/suit/static/suit/js/
+
+# Install heat-translator for TOSCA support
+ENV HT_REPO_URL https://github.com/openstack/heat-translator.git
+ENV HT_REF a951b93c16e54046ed2d233d814860181c772e30
+
+RUN git clone $HT_REPO_URL /tmp/heat-translator && \
+    cd /tmp/heat-translator && \
+    git checkout $HT_REF && \
+    mkdir -p /opt/tosca && \
+    mv /tmp/heat-translator/translator /opt/tosca/translator && \
+    echo > /opt/tosca/translator/__init__.py && \
+    rm -rf /tmp/heat-translator
+
+# Install custom Ansible
+RUN \
+    git clone -b release1.8.2 git://github.com/ansible/ansible.git /opt/ansible && \
+    git clone -b release1.8.2 git://github.com/ansible/ansible-modules-extras.git /opt/ansible/lib/ansible/modules/extras && \
+    git clone -b release1.8.2 git://github.com/ansible/ansible-modules-extras.git /opt/ansible/v2/ansible/modules/extras && \
+    git clone git://github.com/sb98052/ansible-modules-core.git /opt/ansible/lib/ansible/modules/core && \
+    git clone git://github.com/sb98052/ansible-modules-core.git /opt/ansible/v2/ansible/modules/core && \
+    # git clone uses cached copy, doesn't pick up latest
+    git -C /opt/ansible pull && \
+    git -C /opt/ansible/lib/ansible/modules/core pull && \
+    git -C /opt/ansible/v2/ansible/modules/core pull && \
+    mkdir -p /usr/local/share /bin /etc/ansible
+
+COPY ansible-hosts /etc/ansible/hosts
+
+# For Synchronizer
+ENV PHANTOMJS_DL_URL http://phantomjs.googlecode.com/files/phantomjs-1.7.0-linux-x86_64.tar.bz2
+ENV PHANTOMJS_SHA256 a7658f5f2d9464f86891afdb979eb60b754d5f404801db624368ac11e16724d4
+
+RUN curl -fLsS $PHANTOMJS_DL_URL -o phantomjs.tar.bz2 && \
+  echo "$PHANTOMJS_SHA256  phantomjs.tar.bz2" | sha256sum -c - && \
+  tar -C /usr/local/share -xjf phantomjs.tar.bz2 && \
+  ln -s /usr/local/share/phantomjs-* /usr/local/share/phantomjs && \
+  ln -s /usr/local/share/phantomjs/bin/phantomjs /bin/phantomjs && \
+  rm phantomjs.tar.bz2
+
+RUN git clone git://git.planet-lab.org/fofum.git /tmp/fofum && \
+    cd /tmp/fofum; python setup.py install && \
+    rm -rf /tmp/fofum
+
diff --git a/containers/xos/Dockerfile.devel b/containers/xos/Dockerfile.devel
index 2b796e4..6d1c510 100644
--- a/containers/xos/Dockerfile.devel
+++ b/containers/xos/Dockerfile.devel
@@ -1,78 +1,4 @@
-FROM       ubuntu:14.04.3
-
-# XXX Workaround for docker bug:
-# https://github.com/docker/docker/issues/6345
-# Kernel 3.15 breaks docker, uss the line below as a workaround
-# until there is a fix
-RUN ln -s -f /bin/true /usr/bin/chfn
-# XXX End workaround
-
-# Install.
-RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
-    curl \
-    gcc \
-    geoip-database \
-    git \
-    graphviz \
-    graphviz-dev \
-    libgeoip1 \
-    libxslt1.1 \
-    libxslt1-dev \
-    libyaml-dev \
-    m4 \
-    pkg-config \
-    python-dev \
-    python-httplib2 \
-    python-pip \
-    python-psycopg2 \
-    python-pycurl \
-    python-setuptools \
-    tar \
-    wget \
-##### observer dependencies
-    python-keystoneclient \
-    python-novaclient \
-    python-neutronclient \
-    python-glanceclient \
-    python-ceilometerclient
-
-RUN pip install \
-    django==1.7 \
-    django-bitfield \
-    django-crispy-forms \
-    django-encrypted-fields \
-    django-extensions \
-    django-filter==0.11.0 \
-    django-geoposition \
-    django-ipware \
-    django_rest_swagger \
-    django-suit==0.3a1 \
-    django-timezones \
-    djangorestframework==3.3.3 \
-    dnslib \
-    jinja2 \
-    lxml \
-    markdown \
-    netaddr \
-    pyOpenSSL \
-    psycopg2 \
-    python-ceilometerclient \
-    python-dateutil \
-    python-keyczar \
-    python-logstash \
-    pygraphviz \
-    pytz \
-    pyyaml \
-    requests
-
-RUN easy_install --upgrade httplib2
-
-RUN easy_install \
-    python_gflags \
-    google_api_python_client \
-    httplib2.ca_certs_locater
-
-ADD http://code.jquery.com/jquery-1.9.1.min.js /usr/local/lib/python2.7/dist-packages/suit/static/suit/js/
+FROM xosproject/xos-base
 
 # Include certificates from Openstack
 ADD containers/xos/local_certs.crt /usr/local/share/ca-certificates/local_certs.crt
@@ -80,20 +6,18 @@
 
 # Install XOS
 ADD xos /opt/xos
-RUN chmod +x /opt/xos/tools/xos-manage
-RUN /opt/xos/tools/xos-manage genkeys
 
-# install Tosca engine
-RUN chmod +x /opt/xos/tosca/run.py
-RUN bash /opt/xos/tosca/install_tosca.sh
+RUN chmod +x /opt/xos/tools/xos-manage && sync && \
+    /opt/xos/tools/xos-manage genkeys
 
 EXPOSE 8000
 
-# Set environment variables.
+# Set environment variables
 ENV HOME /root
 
-# Define working directory.
+# Define working directory
 WORKDIR /opt/xos
 
-# Define default command.
+# Define default command
 CMD python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure --makemigrations
+
diff --git a/containers/xos/Dockerfile.templ b/containers/xos/Dockerfile.templ
deleted file mode 100644
index 95592c6..0000000
--- a/containers/xos/Dockerfile.templ
+++ /dev/null
@@ -1,93 +0,0 @@
-FROM       ubuntu:14.04.3
-
-# XXX Workaround for docker bug:
-# https://github.com/docker/docker/issues/6345
-# Kernel 3.15 breaks docker, uss the line below as a workaround
-# until there is a fix
-RUN ln -s -f /bin/true /usr/bin/chfn
-# XXX End workaround
-
-# Install.
-RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
-    curl \
-    gcc \
-    geoip-database \
-    git \
-    graphviz \
-    graphviz-dev \
-    libgeoip1 \
-    libxslt1.1 \
-    libxslt1-dev \
-    libyaml-dev \
-    m4 \
-    pkg-config \
-    python-dev \
-    python-httplib2 \
-    python-pip \
-    python-psycopg2 \
-    python-pycurl \
-    python-setuptools \
-    tar \
-    wget \
-##### observer dependencies
-    python-keystoneclient \
-    python-novaclient \
-    python-neutronclient \
-    python-glanceclient \
-    python-ceilometerclient
-
-RUN pip install -U \
-    django==1.7 \
-    django-bitfield \
-    django-crispy-forms \
-    django-encrypted-fields \
-    django_evolution \
-    django-extensions \
-    django-filter==0.11.0 \
-    django-geoposition \
-    django-ipware \
-    django_rest_swagger \
-    django-suit==0.3a1 \
-    django-timezones \
-    djangorestframework==3.3.3 \
-    dnslib \
-    google_api_python_client \
-    httplib2 \
-    httplib2.ca_certs_locater \
-    lxml \
-    markdown \
-    netaddr \
-    python-dateutil \
-    python_gflags \
-    python-keyczar \
-    python-logstash \
-    pygraphviz \
-    pytz \
-    pyyaml \
-    requests
-
-ADD http://code.jquery.com/jquery-1.9.1.min.js /usr/local/lib/python2.7/dist-packages/suit/static/suit/js/
-
-# Include certificates from Openstack
-ADD containers/xos/local_certs.crt /usr/local/share/ca-certificates/local_certs.crt
-RUN update-ca-certificates
-
-# Install XOS
-RUN git clone XOS_GIT_REPO -b XOS_GIT_BRANCH /tmp/xos && \
-    mv /tmp/xos/xos /opt/ && \
-    chmod +x /opt/xos/tools/xos-manage && \
-    /opt/xos/tools/xos-manage genkeys
-
-# install Tosca engine
-RUN bash /opt/xos/tosca/install_tosca.sh
-
-EXPOSE 8000
-
-# Set environment variables.
-ENV HOME /root
-
-# Define working directory.
-WORKDIR /root
-
-# Define default command.
-CMD python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure --makemigrations
diff --git a/containers/xos/Dockerfile.test b/containers/xos/Dockerfile.test
index 8b01b98..ac3c14c 100644
--- a/containers/xos/Dockerfile.test
+++ b/containers/xos/Dockerfile.test
@@ -1,9 +1,17 @@
 FROM       xosproject/xos
 
 # install nodejs
-RUN curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
-RUN sudo apt-get install -y nodejs
+COPY containers/xos/nodesource.gpg.key /tmp/nodesource.gpg.key
+
+RUN apt-key add /tmp/nodesource.gpg.key && \
+    echo "deb https://deb.nodesource.com/node_4.x trusty main" \
+    > /etc/apt/sources.list.d/nodesource.list
+
+RUN apt-get update && apt-get install -y --force-yes nodejs && \
+    rm -rf /var/lib/apt/lists/*
+
 RUN node -v
 
 # install node modules
-# RUN cd /opt/xos/tests/api; npm install
\ No newline at end of file
+# RUN cd /opt/xos/tests/api; npm install
+
diff --git a/containers/xos/Makefile b/containers/xos/Makefile
index cf91988..1f856b7 100644
--- a/containers/xos/Makefile
+++ b/containers/xos/Makefile
@@ -1,30 +1,63 @@
-CONTAINER_NAME:=xos-server
-IMAGE_NAME:=xosproject/xos
-TOSCA_CONFIG_PATH:=/opt/xos/configurations/opencloud/opencloud.yaml
-XOS_GIT_REPO?=git://github.com/open-cloud/xos.git
-XOS_GIT_BRANCH?=master
-NO_DOCKER_CACHE?=false
+# Docker container Makefile for XOS
+#
+# Targets:
+#
+#  `base`   - XOS prerequistie files, no XOS code, builds xosproject/xos-base
+#  `build`  - base + XOS code, git pulled in Dockerfile from main repo,
+#             builds xosproject/xos
+#  `custom` - base + XOS code, git pulled in Dockerfile from selectable repo,
+#             builds xosproject/xos
+#  `devel`  - base + XOS code from local directory, builds xosproject/xos
+#  `test`   - xosproject/xos + nodejs testing frameworks, builds
+#             xosproject/xos-test
+#
 
-.PHONY: build
-build: ; sudo docker build --no-cache=${NO_DOCKER_CACHE} --rm -t ${IMAGE_NAME} .
+NO_DOCKER_CACHE    ?= false
 
-.PHONY: custom
-custom: ; cat Dockerfile.templ | sed -e "s|XOS_GIT_REPO|${XOS_GIT_REPO}|g" -e "s|XOS_GIT_BRANCH|${XOS_GIT_BRANCH}|g" | docker build --no-cache=${NO_DOCKER_CACHE} --rm -t ${IMAGE_NAME} -
+CONTAINER_NAME     ?= xos-server
+IMAGE_NAME         ?= xosproject/xos
 
-.PHONY: devel
-devel: ; cd ../..; ls; sudo docker build -f containers/xos/Dockerfile.devel --no-cache=${NO_DOCKER_CACHE} --rm -t ${IMAGE_NAME} .
+XOS_GIT_REPO       ?= git://github.com/open-cloud/xos.git
+XOS_GIT_BRANCH     ?= master
 
-.PHONY: test
-test: ; cd ../..; ls; sudo docker build -f containers/xos/Dockerfile.test --no-cache=${NO_DOCKER_CACHE} --rm -t ${IMAGE_NAME} .
+TOSCA_CONFIG_PATH  ?= /opt/xos/configurations/opencloud/opencloud.yaml
 
-.PHONY: run
-run: ; sudo docker run -d --name ${CONTAINER_NAME} -p 80:8000 -v /usr/local/share/ca-certificates:/usr/local/share/ca-certificates:ro ${IMAGE_NAME}
+base:
+	sudo docker build --no-cache=${NO_DOCKER_CACHE} --rm \
+	-f Dockerfile.base -t xosproject/xos-base .
 
-.PHONY: runtosca
-runtosca: ; sudo docker exec -it ${CONTAINER_NAME} /usr/bin/python /opt/xos/tosca/run.py padmin@vicci.org ${TOSCA_CONFIG_PATH}
+build:
+	sudo docker build --no-cache=${NO_DOCKER_CACHE} --rm \
+	-f Dockerfile -t ${IMAGE_NAME} .
 
-.PHONY: stop
-stop: ; sudo docker stop ${CONTAINER_NAME}
+custom:
+	docker build --no-cache=${NO_DOCKER_CACHE} --rm \
+	--build-arg XOS_GIT_REPO=${XOS_GIT_REPO} \
+	--build-arg XOS_GIT_BRANCH=${XOS_GIT_BRANCH} \
+	-f Dockerfile -t ${IMAGE_NAME} .
 
-.PHONY: rm
-rm: ; sudo docker rm ${CONTAINER_NAME}
+devel:
+	sudo docker build --no-cache=${NO_DOCKER_CACHE} --rm \
+	-f Dockerfile.devel -t ${IMAGE_NAME} ../..
+
+test:
+	sudo docker build --no-cache=${NO_DOCKER_CACHE} --rm \
+	-f Dockerfile.test -t xosproject/xos-test ../..
+
+run:
+	sudo docker run -d --name ${CONTAINER_NAME} -p 80:8000 \
+	${IMAGE_NAME}
+
+runtosca:
+	sudo docker exec -it ${CONTAINER_NAME} \
+  /usr/bin/python /opt/xos/tosca/run.py padmin@vicci.org ${TOSCA_CONFIG_PATH}
+
+stop:
+	sudo docker stop ${CONTAINER_NAME}
+
+rm:
+	sudo docker rm ${CONTAINER_NAME}
+
+rmi:
+	sudo docker rmi `docker images | grep "^<none>" | awk '{print $$3}'`
+
diff --git a/containers/xos/ansible-hosts b/containers/xos/ansible-hosts
new file mode 100644
index 0000000..0dd74f1
--- /dev/null
+++ b/containers/xos/ansible-hosts
@@ -0,0 +1,2 @@
+[localhost]
+127.0.0.1
diff --git a/containers/xos/nodesource.gpg.key b/containers/xos/nodesource.gpg.key
new file mode 100644
index 0000000..1dc1d10
--- /dev/null
+++ b/containers/xos/nodesource.gpg.key
@@ -0,0 +1,52 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1
+Comment: GPGTools - https://gpgtools.org
+
+mQINBFObJLYBEADkFW8HMjsoYRJQ4nCYC/6Eh0yLWHWfCh+/9ZSIj4w/pOe2V6V+
+W6DHY3kK3a+2bxrax9EqKe7uxkSKf95gfns+I9+R+RJfRpb1qvljURr54y35IZgs
+fMG22Np+TmM2RLgdFCZa18h0+RbH9i0b+ZrB9XPZmLb/h9ou7SowGqQ3wwOtT3Vy
+qmif0A2GCcjFTqWW6TXaY8eZJ9BCEqW3k/0Cjw7K/mSy/utxYiUIvZNKgaG/P8U7
+89QyvxeRxAf93YFAVzMXhoKxu12IuH4VnSwAfb8gQyxKRyiGOUwk0YoBPpqRnMmD
+Dl7SdmY3oQHEJzBelTMjTM8AjbB9mWoPBX5G8t4u47/FZ6PgdfmRg9hsKXhkLJc7
+C1btblOHNgDx19fzASWX+xOjZiKpP6MkEEzq1bilUFul6RDtxkTWsTa5TGixgCB/
+G2fK8I9JL/yQhDc6OGY9mjPOxMb5PgUlT8ox3v8wt25erWj9z30QoEBwfSg4tzLc
+Jq6N/iepQemNfo6Is+TG+JzI6vhXjlsBm/Xmz0ZiFPPObAH/vGCY5I6886vXQ7ft
+qWHYHT8jz/R4tigMGC+tvZ/kcmYBsLCCI5uSEP6JJRQQhHrCvOX0UaytItfsQfLm
+EYRd2F72o1yGh3yvWWfDIBXRmaBuIGXGpajC0JyBGSOWb9UxMNZY/2LJEwARAQAB
+tB9Ob2RlU291cmNlIDxncGdAbm9kZXNvdXJjZS5jb20+iQI4BBMBAgAiBQJTmyS2
+AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRAWVaCraFdigHTmD/9OKhUy
+jJ+h8gMRg6ri5EQxOExccSRU0i7UHktecSs0DVC4lZG9AOzBe+Q36cym5Z1di6JQ
+kHl69q3zBdV3KTW+H1pdmnZlebYGz8paG9iQ/wS9gpnSeEyx0Enyi167Bzm0O4A1
+GK0prkLnz/yROHHEfHjsTgMvFwAnf9uaxwWgE1d1RitIWgJpAnp1DZ5O0uVlsPPm
+XAhuBJ32mU8S5BezPTuJJICwBlLYECGb1Y65Cil4OALU7T7sbUqfLCuaRKxuPtcU
+VnJ6/qiyPygvKZWhV6Od0Yxlyed1kftMJyYoL8kPHfeHJ+vIyt0s7cropfiwXoka
+1iJB5nKyt/eqMnPQ9aRpqkm9ABS/r7AauMA/9RALudQRHBdWIzfIg0Mlqb52yyTI
+IgQJHNGNX1T3z1XgZhI+Vi8SLFFSh8x9FeUZC6YJu0VXXj5iz+eZmk/nYjUt4Mtc
+pVsVYIB7oIDIbImODm8ggsgrIzqxOzQVP1zsCGek5U6QFc9GYrQ+Wv3/fG8hfkDn
+xXLww0OGaEQxfodm8cLFZ5b8JaG3+Yxfe7JkNclwvRimvlAjqIiW5OK0vvfHco+Y
+gANhQrlMnTx//IdZssaxvYytSHpPZTYw+qPEjbBJOLpoLrz8ZafN1uekpAqQjffI
+AOqW9SdIzq/kSHgl0bzWbPJPw86XzzftewjKNbkCDQRTmyS2ARAAxSSdQi+WpPQZ
+fOflkx9sYJa0cWzLl2w++FQnZ1Pn5F09D/kPMNh4qOsyvXWlekaV/SseDZtVziHJ
+Km6V8TBG3flmFlC3DWQfNNFwn5+pWSB8WHG4bTA5RyYEEYfpbekMtdoWW/Ro8Kmh
+41nuxZDSuBJhDeFIp0ccnN2Lp1o6XfIeDYPegyEPSSZqrudfqLrSZhStDlJgXjea
+JjW6UP6txPtYaaila9/Hn6vF87AQ5bR2dEWB/xRJzgNwRiax7KSU0xca6xAuf+TD
+xCjZ5pp2JwdCjquXLTmUnbIZ9LGV54UZ/MeiG8yVu6pxbiGnXo4Ekbk6xgi1ewLi
+vGmz4QRfVklV0dba3Zj0fRozfZ22qUHxCfDM7ad0eBXMFmHiN8hg3IUHTO+UdlX/
+aH3gADFAvSVDv0v8t6dGc6XE9Dr7mGEFnQMHO4zhM1HaS2Nh0TiL2tFLttLbfG5o
+QlxCfXX9/nasj3K9qnlEg9G3+4T7lpdPmZRRe1O8cHCI5imVg6cLIiBLPO16e0fK
+yHIgYswLdrJFfaHNYM/SWJxHpX795zn+iCwyvZSlLfH9mlegOeVmj9cyhN/VOmS3
+QRhlYXoA2z7WZTNoC6iAIlyIpMTcZr+ntaGVtFOLS6fwdBqDXjmSQu66mDKwU5Ek
+fNlbyrpzZMyFCDWEYo4AIR/18aGZBYUAEQEAAYkCHwQYAQIACQUCU5sktgIbDAAK
+CRAWVaCraFdigIPQEACcYh8rR19wMZZ/hgYv5so6Y1HcJNARuzmffQKozS/rxqec
+0xM3wceL1AIMuGhlXFeGd0wRv/RVzeZjnTGwhN1DnCDy1I66hUTgehONsfVanuP1
+PZKoL38EAxsMzdYgkYH6T9a4wJH/IPt+uuFTFFy3o8TKMvKaJk98+Jsp2X/QuNxh
+qpcIGaVbtQ1bn7m+k5Qe/fz+bFuUeXPivafLLlGc6KbdgMvSW9EVMO7yBy/2JE15
+ZJgl7lXKLQ31VQPAHT3an5IV2C/ie12eEqZWlnCiHV/wT+zhOkSpWdrheWfBT+ac
+hR4jDH80AS3F8jo3byQATJb3RoCYUCVc3u1ouhNZa5yLgYZ/iZkpk5gKjxHPudFb
+DdWjbGflN9k17VCf4Z9yAb9QMqHzHwIGXrb7ryFcuROMCLLVUp07PrTrRxnO9A/4
+xxECi0l/BzNxeU1gK88hEaNjIfviPR/h6Gq6KOcNKZ8rVFdwFpjbvwHMQBWhrqfu
+G3KaePvbnObKHXpfIKoAM7X2qfO+IFnLGTPyhFTcrl6vZBTMZTfZiC1XDQLuGUnd
+sckuXINIU3DFWzZGr0QrqkuE/jyr7FXeUJj9B7cLo+s/TXo+RaVfi3kOc9BoxIvy
+/qiNGs/TKy2/Ujqp/affmIMoMXSozKmga81JSwkADO1JMgUy6dApXz9kP4EE3g==
+=CLGF
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/views/ngXosLib/gulpfile.js b/views/ngXosLib/gulpfile.js
index e514d7a..e030ad9 100644
--- a/views/ngXosLib/gulpfile.js
+++ b/views/ngXosLib/gulpfile.js
@@ -2,6 +2,7 @@
 
 var gulp = require('gulp');
 var wrench = require('wrench');
+var path = require('path');
 
 var options = {
   ngXosVendor: '../../xos/core/xoslib/static/js/vendor/', //save here the minfied vendor file, this is automatically loaded in the django page
@@ -11,9 +12,9 @@
   docs: './docs'
 };
 
-wrench.readdirSyncRecursive('./gulp')
+wrench.readdirSyncRecursive(path.join(__dirname, './gulp'))
 .map(function(file) {
-  require('./gulp/' + file)(options);
+  require(path.join(__dirname, './gulp/' + file))(options);
 });
 
 gulp.task('default', function () {
diff --git a/views/ngXosLib/xosHelpers/spec/notification.test.js b/views/ngXosLib/xosHelpers/spec/notification.test.js
new file mode 100644
index 0000000..cbc1e56
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/spec/notification.test.js
@@ -0,0 +1,63 @@
+(function () {
+  'use strict';
+
+  describe('The xos.helper module', function(){
+    describe('The xosNotification service', () => {
+
+      let service, scope;
+
+      const options = {icon: 'icon', body: 'message'};
+
+      let notificationMock = {
+        requestPermission: () => {
+          return {
+            then: cb => cb('granted')
+          }
+        },
+        permission: 'granted'
+      }
+
+
+      // load the application module
+      beforeEach(module('xos.helpers', ($provide) => {
+        $provide.value('Notification', notificationMock);
+      }));
+
+      // inject the cartService
+      beforeEach(inject(function (_xosNotification_, $rootScope) {
+        // The injector unwraps the underscores (_) from around the parameter names when matching
+        service = _xosNotification_;
+        scope = $rootScope;
+        spyOn(service, 'sendNotification');
+        spyOn(service, 'checkPermission').and.callThrough();
+        spyOn(notificationMock, 'requestPermission').and.callThrough();
+      }));
+
+      it('should exist', () => {
+        expect(service).toBeDefined();
+      });
+
+      describe('when permission are granted', () => {
+        it('should send the notification', () => {
+          service.notify('Test', options);
+          expect(service.sendNotification).toHaveBeenCalledWith('Test', options);
+        });
+      });
+
+      describe('when permission are not granted', () => {
+        beforeEach(() => {
+          notificationMock.permission = false;
+        });
+
+        it('should request permission', () => {
+          service.notify('Test', options);
+          expect(service.checkPermission).toHaveBeenCalled();
+          scope.$apply(); // this resolve the promise
+          expect(service.sendNotification).toHaveBeenCalledWith('Test', options);
+        });
+      });
+
+    });
+  });
+
+})();
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/spec/services/helpers/form.helpers.test.js b/views/ngXosLib/xosHelpers/spec/services/helpers/form.helpers.test.js
index 4c90cd6..f6bfbb2 100644
--- a/views/ngXosLib/xosHelpers/spec/services/helpers/form.helpers.test.js
+++ b/views/ngXosLib/xosHelpers/spec/services/helpers/form.helpers.test.js
@@ -43,7 +43,8 @@
         custom: {
           label: 'Custom Label',
           type: 'number',
-          validators: {}
+          validators: {},
+          hint: 'Test Hint'
         }
       };
 
@@ -51,32 +52,38 @@
         id: {
           label: 'Id:',
           type: 'number',
-          validators: {}
+          validators: {},
+          hint: ''
         },
         name: {
           label: 'Name:',
           type: 'text',
-          validators: {}
+          validators: {},
+          hint: ''
         },
         mail: {
           label: 'Mail:',
           type: 'email',
-          validators: {}
+          validators: {},
+          hint: ''
         },
         active: {
           label: 'Active:',
           type: 'boolean',
-          validators: {}
+          validators: {},
+          hint: ''
         },
         created: {
           label: 'Created:',
           type: 'date',
-          validators: {}
+          validators: {},
+          hint: ''
         },
         custom: {
           label: 'Custom Label:',
           type: 'number',
-          validators: {}
+          validators: {},
+          hint: 'Test Hint'
         }
       };
 
@@ -133,8 +140,14 @@
         });
       });
 
-      it('should convert the fields array in an empty form object', () => {
-        expect(service.parseModelField(fields)).toEqual(modelField);
+      describe('the parseModelField mehtod', () => {
+        it('should convert the fields array in an empty form object', () => {
+          expect(service.parseModelField(fields)).toEqual(modelField);
+        });
+
+        xit('should handle nested config', () => {
+          
+        });
       });
 
       describe('when modelField are provided', () => {
@@ -170,7 +183,8 @@
           },
           custom: {
             label: 'Custom Label',
-            type: 'number'
+            type: 'number',
+            hint: 'Test Hint'
           }
         };
 
@@ -178,32 +192,38 @@
           id: {
             label: 'Id:',
             type: 'number',
-            validators: {}
+            validators: {},
+            hint: ''
           },
           name: {
             label: 'Name:',
             type: 'text',
-            validators: {}
+            validators: {},
+            hint: ''
           },
           mail: {
             label: 'Mail:',
             type: 'email',
-            validators: {}
+            validators: {},
+            hint: ''
           },
           active: {
             label: 'Active:',
             type: 'boolean',
-            validators: {}
+            validators: {},
+            hint: ''
           },
           created: {
             label: 'Created:',
             type: 'date',
-            validators: {}
+            validators: {},
+            hint: ''
           },
           custom: {
             label: 'Custom Label:',
             type: 'number',
-            validators: {}
+            validators: {},
+            hint: 'Test Hint'
           }
         };
 
diff --git a/views/ngXosLib/xosHelpers/spec/services/helpers/user-prefs.test.js b/views/ngXosLib/xosHelpers/spec/services/helpers/user-prefs.test.js
new file mode 100644
index 0000000..4c76484
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/spec/services/helpers/user-prefs.test.js
@@ -0,0 +1,113 @@
+/**
+ * © OpenCORD
+ *
+ * Created by teone on 5/25/16.
+ */
+
+(function () {
+  'use strict';
+  let service;
+  let cookies = {
+    xosUserPrefs: JSON.stringify({test: true})
+  };
+
+  const cookieMock = {
+    get: (name) => {
+      return cookies[name]
+    },
+    put: (name, value) => {
+      cookies[name] = value
+    }
+  };
+
+  describe('The xos.helper module', function(){
+
+    describe('The XosUserPrefs service', () => {
+
+      // load the application module
+      beforeEach(module('xos.helpers', ($provide) => {
+        $provide.value('$cookies', cookieMock);
+      }));
+
+      // inject the cartService
+      beforeEach(inject(function (_XosUserPrefs_) {
+        // The injector unwraps the underscores (_) from around the parameter names when matching
+        service = _XosUserPrefs_;
+        spyOn(cookieMock, 'put').and.callThrough();
+      }));
+
+      it('should exists and have methods', () => {
+        expect(service).toBeDefined();
+        expect(service.getAll).toBeDefined();
+        expect(service.setAll).toBeDefined();
+        expect(service.getSynchronizerNotificationStatus).toBeDefined();
+        expect(service.setSynchronizerNotificationStatus).toBeDefined();
+      });
+
+      describe('the getAll method', () => {
+        it('should return all the stored prefs', () => {
+          let prefs = service.getAll();
+          expect(prefs).toEqual(JSON.parse(cookies.xosUserPrefs));
+        });
+      });
+
+      describe('the setAll method', () => {
+        it('should override all preferences', () => {
+          service.setAll({test: true, updated: true});
+          expect(JSON.parse(cookies.xosUserPrefs)).toEqual({test: true, updated: true});
+        });
+      });
+
+      describe('the synchronizers status', () => {
+        let syncNotification;
+        beforeEach(() => {
+          syncNotification = {
+            synchronizers: {
+              notification: {
+                first: true,
+                second: false
+              }
+            }
+          }
+          cookies.xosUserPrefs = JSON.stringify(syncNotification);
+        });
+
+        describe('the getSynchronizerNotificationStatus method', () => {
+          it('should return notification status for all synchronizers', () => {
+            expect(service.getSynchronizerNotificationStatus()).toEqual(syncNotification.synchronizers.notification);
+          });
+
+          it('should return notification status for a single synchronizers', () => {
+            expect(service.getSynchronizerNotificationStatus('first')).toEqual(syncNotification.synchronizers.notification.first);
+            expect(service.getSynchronizerNotificationStatus('second')).toEqual(syncNotification.synchronizers.notification.second);
+          });
+        });
+
+        describe('the setSynchronizerNotificationStatus', () => {
+          
+          it('should throw an error if called without synchronizer name', () => {
+            function wrapper (){
+              service.setSynchronizerNotificationStatus();
+            }
+            expect(wrapper).toThrowError('[XosUserPrefs] When updating a synchronizer is mandatory to provide a name.');
+          });
+
+          it('should update a synchronizer notification status', () => {
+            service.setSynchronizerNotificationStatus('second', true);
+            expect(service.getSynchronizerNotificationStatus('second')).toEqual(true);
+            expect(service.getSynchronizerNotificationStatus('first')).toEqual(true);
+
+            // should persist the change
+            expect(cookieMock.put).toHaveBeenCalledWith('xosUserPrefs', '{"synchronizers":{"notification":{"first":true,"second":true}}}');
+          });
+
+          it('should handle empty cookies', () => {
+            cookies.xosUserPrefs = '';
+            service.setSynchronizerNotificationStatus('second', true);
+            expect(service.getSynchronizerNotificationStatus('second')).toEqual(true);
+          });
+        });
+      });
+    });
+  });
+})();
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/spec/ui/field.test.js b/views/ngXosLib/xosHelpers/spec/ui/field.test.js
index c308417..f933a01 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/field.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/field.test.js
@@ -8,13 +8,15 @@
   'use strict';
 
   let element, scope, isolatedScope, rootScope, compile;
-  const compileElement = () => {
+  const compileElement = (el) => {
+    element = el;
 
     if(!scope){
       scope = rootScope.$new();
     }
-
-    element = angular.element('<xos-field name="name" field="field" ng-model="ngModel"></xos-field>');
+    if(!angular.isDefined(element)){
+      element = angular.element('<xos-field name="name" field="field" ng-model="ngModel"></xos-field>');
+    }
     compile(element)(scope);
     scope.$digest();
     isolatedScope = element.isolateScope().vm;
@@ -67,7 +69,7 @@
             type: 'number',
             validators: {}
           };
-          compileElement();
+          compileElement(angular.element('<xos-field name="name" field="field"></xos-field>'));
         }
         expect(errorFunctionWrapper).toThrow(new Error('[xosField] Please provide an ng-model'));
       }));
@@ -173,6 +175,10 @@
           expect($(element).find('.boolean-field > button').length).toEqual(2);
         });
 
+        it('should format labels', () => {
+          expect($(element).find('input[name="foo"]').parent().find('label').text()).toBe('Foo:');
+        });
+
         describe('and the model is empty', () => {
           beforeEach(() => {
             scope.ngModel = {
@@ -181,7 +187,7 @@
           });
 
           it('should not print the panel', () => {
-            console.log($(element).find('.panel.object-field'));
+            // console.log($(element).find('.panel.object-field'));
             expect($(element).find('.panel.object-field')).not.toExist()
           });
         });
diff --git a/views/ngXosLib/xosHelpers/spec/ui/form.test.js b/views/ngXosLib/xosHelpers/spec/ui/form.test.js
index 5f73f30..cb9f9e8 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/form.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/form.test.js
@@ -7,28 +7,44 @@
 (function () {
   'use strict';
 
+  let element, scope, isolatedScope, rootScope, compile;
+
+  const compileElement = () => {
+
+    if(!scope){
+      scope = rootScope.$new();
+    }
+
+    element = angular.element(`<xos-form config="config" ng-model="model"></xos-form>`);
+    compile(element)(scope);
+    scope.$digest();
+    isolatedScope = element.isolateScope().vm;
+  }
+
   describe('The xos.helper module', function(){
 
     describe('The xos-form component', () => {
 
-      let element, scope, isolatedScope;
 
       beforeEach(module('xos.helpers'));
 
+      beforeEach(inject(($compile, $rootScope) => {
+        rootScope = $rootScope;
+        compile = $compile;
+      }));
+
       it('should throw an error if no config is specified', inject(($compile, $rootScope) => {
         function errorFunctionWrapper(){
-          $compile(angular.element('<xos-form></xos-form>'))($rootScope);
-          $rootScope.$digest();
+          compileElement();
         }
         expect(errorFunctionWrapper).toThrow(new Error('[xosForm] Please provide a configuration via the "config" attribute'));
       }));
 
       it('should throw an error if no actions is specified', inject(($compile, $rootScope) => {
         function errorFunctionWrapper(){
-          let scope = $rootScope.$new();
+          scope = $rootScope.$new();
           scope.config = 'green';
-          $compile(angular.element('<xos-form config="config"></xos-form>'))(scope);
-          $rootScope.$digest();
+          compileElement();
         }
         expect(errorFunctionWrapper).toThrow(new Error('[xosForm] Please provide an action list in the configuration'));
       }));
@@ -37,8 +53,7 @@
         
         let cb = jasmine.createSpy('callback');
 
-        beforeEach(inject(($compile, $rootScope) => {
-
+        beforeEach(inject(($rootScope) => {
 
           scope = $rootScope.$new();
 
@@ -78,10 +93,7 @@
             }
           };
 
-          element = angular.element(`<xos-form config="config" ng-model="model"></xos-form>`);
-          $compile(element)(scope);
-          scope.$digest();
-          isolatedScope = element.isolateScope().vm;
+          compileElement();
         }));
 
         it('should add excluded properties to the list', () => {
@@ -194,6 +206,53 @@
             expect(isolatedScope.testForm.age.$error.min).toBeTruthy();
           });
         });
+
+        describe('when a deep model is passed', () => {
+
+          beforeEach(inject(($rootScope) => {
+
+            scope = $rootScope.$new();
+
+            scope.config = {
+              exclude: ['excludedField'],
+              formName: 'testForm',
+              actions: [
+                {
+                  label: 'Save',
+                  icon: 'ok', // refers to bootstraps glyphicon
+                  cb: cb,
+                  class: 'success'
+                }
+              ],
+              fields: {
+                object_field: {
+                  field_one: {
+                    label: 'Custom Label'
+                  }
+                }
+              }
+            };
+
+            scope.model = {
+              object_field: {
+                field_one: 'bar',
+                number: 1,
+                email: 'teo@onlab.us'
+              }
+            };
+
+            compileElement();
+          }));
+
+          it('should print nested field', () => {
+            expect($(element).find('input').length).toBe(3);
+          });
+
+          xit('should configure nested fields', () => {
+            let custom_label = $(element).find('input[name=field_one]').parent().find('label');
+            expect(custom_label.text()).toBe('Custom Label');
+          });
+        });
       });
     });
   });
diff --git a/views/ngXosLib/xosHelpers/spec/ui/validation.test.js b/views/ngXosLib/xosHelpers/spec/ui/validation.test.js
index 782f03f..bb663fa 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/validation.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/validation.test.js
@@ -7,27 +7,46 @@
 (function () {
   'use strict';
 
+  let compile, element, scope, isolatedScope;
+
+  const compileElement = (el) => {
+    element = el;
+
+    if(!scope){
+      scope = rootScope.$new();
+    }
+    if(!angular.isDefined(element)){
+      element = angular.element('<xos-validation field="field" form="form"></xos-validation>');
+    }
+    compile(element)(scope);
+    scope.$digest();
+    isolatedScope = element.isolateScope().vm;
+  }
+
   describe('The xos.helper module', function(){
     describe('The xos-validation component', () => {
 
-      let element, scope, isolatedScope;
-
       beforeEach(module('xos.helpers'));
 
-      beforeEach(inject(($compile, $rootScope) => {
+      describe('when the form has no errors', () => {
+        beforeEach(inject(($compile, $rootScope) => {
+          compile = $compile;
+          scope = $rootScope.$new();
 
-        scope = $rootScope.$new();
+          scope.field = {
+            $error: {}
+          };
 
-        scope.errors = {};
+          scope.form = {
+            $submitted: true
+          }
 
-        element = angular.element(`<xos-validation errors="errors"></xos-validation>`);
-        $compile(element)(scope);
-        scope.$digest();
-        isolatedScope = element.isolateScope().vm;
-      }));
+          compileElement();
+        }));
 
-      it('should not show an alert', () => {
-        expect($(element).find('xos-alert > .alert')[0]).toHaveClass('ng-hide');
+        it('should not show an alert by default', () => {
+          expect($(element).find('xos-alert > .alert')[0]).toHaveClass('ng-hide');
+        });
       });
 
       let availableErrors = [
@@ -56,8 +75,8 @@
       // use a loop to generate similar test
       availableErrors.forEach((e, i) => {
         it(`should show an alert for ${e.type} errors`, () => {
-          scope.errors[e.type] = true;
-          scope.$digest();
+          scope.field.$error[e.type] = true;
+          compileElement();
           let alert = $(element).find('xos-alert > .alert')[i];
           expect(alert).not.toHaveClass('ng-hide');
           expect(alert).toHaveText(e.message);
diff --git a/views/ngXosLib/xosHelpers/src/services/helpers/ui/form.helpers.js b/views/ngXosLib/xosHelpers/src/services/helpers/ui/form.helpers.js
index c850f48..04a383a 100644
--- a/views/ngXosLib/xosHelpers/src/services/helpers/ui/form.helpers.js
+++ b/views/ngXosLib/xosHelpers/src/services/helpers/ui/form.helpers.js
@@ -21,6 +21,7 @@
     * @returns {boolean} If the string match an email format
     **/
 
+
     this._isEmail = (text) => {
       var re = /(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/;
       return re.test(text);
@@ -81,7 +82,8 @@
     *   'field-name': {
     *     label: 'Label',
     *     type: 'number', //typeof field
-    *     validators: {} // see xosForm for more details
+    *     validators: {}, // see xosForm for more details
+    *     hint: 'A Custom hint for the field'
     *   }
     * }
     * ```
@@ -97,7 +99,8 @@
         form[f] = {
           label: (customField[f] && customField[f].label) ? `${customField[f].label}:` : LabelFormatter.format(f),
           type: (customField[f] && customField[f].type) ? customField[f].type : this._getFieldFormat(model[f]),
-          validators: (customField[f] && customField[f].validators) ? customField[f].validators : {}
+          validators: (customField[f] && customField[f].validators) ? customField[f].validators : {},
+          hint: (customField[f] && customField[f].hint)? customField[f].hint : ''
         };
 
         if(form[f].type === 'date'){
diff --git a/views/ngXosLib/xosHelpers/src/services/helpers/user-prefs.service.js b/views/ngXosLib/xosHelpers/src/services/helpers/user-prefs.service.js
new file mode 100644
index 0000000..27edf7f
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/src/services/helpers/user-prefs.service.js
@@ -0,0 +1,95 @@
+(function () {
+  
+  angular.module('xos.helpers')
+
+  /**
+  * @ngdoc service
+  * @name xos.helpers.XosUserPrefs
+  * @description
+  * This service is used to store the user preferences in cookies, so that they survive to page changes.
+  * The structure of the user preference is:
+  * ```
+  * {
+  *   synchronizers: {
+  *     notification: {
+  *       'volt': boolean,
+  *       'openstack': boolean,
+  *       ...
+  *     }
+  *   }
+  * }
+  * ```
+  **/
+
+  .service('XosUserPrefs', function($cookies){
+
+    let userPrefs = $cookies.get('xosUserPrefs') ? JSON.parse($cookies.get('xosUserPrefs')) : {};
+
+    /**
+    * @ngdoc method
+    * @name xos.helpers.XosUserPrefs#getAll
+    * @methodOf xos.helpers.XosUserPrefs
+    * @description
+    * Return all the user preferences stored in cookies
+    * @returns {object} The user preferences
+    **/
+    this.getAll = () => {
+      userPrefs = $cookies.get('xosUserPrefs') ? JSON.parse($cookies.get('xosUserPrefs')) : {};
+      return userPrefs;
+    };
+
+    /**
+    * @ngdoc method
+    * @name xos.helpers.XosUserPrefs#setAll
+    * @methodOf xos.helpers.XosUserPrefs
+    * @description
+    * Override all user preferences
+    * @param {object} prefs The user preferences
+    **/
+    this.setAll = (prefs) => {
+      $cookies.put('xosUserPrefs', JSON.stringify(prefs));
+    };
+
+    /**
+    * @ngdoc method
+    * @name xos.helpers.XosUserPrefs#getSynchronizerNotificationStatus
+    * @methodOf xos.helpers.XosUserPrefs
+    * @description
+    * Return the synchronizer notification status, if name is not provided return the status for all synchronizers
+    * @param {string=} prefs The synchronizer name
+    * @returns {object | string} The synchronizer status
+    **/
+    this.getSynchronizerNotificationStatus = (name = false) => {
+      if(name){
+        return this.getAll().synchronizers.notification[name];
+      }
+      return this.getAll().synchronizers.notification;
+    };
+
+    /**
+    * @ngdoc method
+    * @name xos.helpers.XosUserPrefs#setSynchronizerNotificationStatus
+    * @methodOf xos.helpers.XosUserPrefs
+    * @description
+    * Update the notification status for a single synchronizer
+    * @param {string} name The synchronizer name
+    * @param {boolean} value The notification status (true means that it has been sent)
+    **/
+    this.setSynchronizerNotificationStatus = (name = false, value) => {
+      if(!name){
+        throw new Error('[XosUserPrefs] When updating a synchronizer is mandatory to provide a name.')
+      }
+
+      let cookies = this.getAll();
+
+      if(!cookies.synchronizers){
+        cookies.synchronizers = {
+          notification: {}
+        }
+      }
+
+      cookies.synchronizers.notification[name] = value;
+      this.setAll(cookies);
+    }
+  });
+})();
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/src/services/notification.service.js b/views/ngXosLib/xosHelpers/src/services/notification.service.js
new file mode 100644
index 0000000..e190451
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/src/services/notification.service.js
@@ -0,0 +1,61 @@
+(function() {
+  'use strict';
+
+  angular
+  .module('xos.helpers')
+  .factory('Notification', function(){
+    return window.Notification;
+  })
+  /**
+  * @ngdoc service
+  * @name xos.helpers.xosNotification
+  * @description This factory define a set of helper function to trigger desktop notification
+  **/
+  .service('xosNotification', function($q, $log, Notification) {
+
+    this.checkPermission = () => {
+      const deferred = $q.defer();
+      Notification.requestPermission()
+      .then(permission => {
+        if (permission === 'granted') {
+          deferred.resolve(permission);
+        }
+        else {
+          deferred.reject(permission);
+        }
+      });
+      return deferred.promise;
+    };
+
+    this.sendNotification = (title, options) => {
+      const notification = new Notification(title, options);
+      notification.onerror = function(err){
+        $log.error(err);
+      };
+    };
+
+    /**
+    * @ngdoc method
+    * @name xos.helpers.xosNotification#notify
+    * @methodOf xos.helpers.xosNotification
+    * @description
+    * This method will check for user permission and if granted will send a browser notification.
+    * @param {string} title The notification title
+    * @param {object} options The notification options: `{icon: 'url', body: 'Notification body'}`
+    **/
+
+    this.notify = (title, options) => {
+      if (!('Notification' in window)) {
+        $log.info('This browser does not support desktop notification');
+      }
+      else if (Notification.permission !== 'granted') {
+        this.checkPermission()
+        .then(() => this.sendNotification(title, options));
+      }
+      else if (Notification.permission === 'granted') {
+        this.sendNotification(title, options);
+      }
+    }
+
+  })
+})();
diff --git a/views/ngXosLib/xosHelpers/src/services/rest/Slices_plus.js b/views/ngXosLib/xosHelpers/src/services/rest/Slices_plus.js
index e744caa..8213b11 100644
--- a/views/ngXosLib/xosHelpers/src/services/rest/Slices_plus.js
+++ b/views/ngXosLib/xosHelpers/src/services/rest/Slices_plus.js
@@ -22,5 +22,19 @@
 
       return {$promise: deferred.promise};
     }
+
+    this.get = (id, params) => {
+      let deferred = $q.defer();
+
+      $http.get(`/api/utility/slicesplus/${id}`, {params: params})
+      .then(res => {
+        deferred.resolve(res.data);
+      })
+      .catch(res => {
+        deferred.reject(res.data);
+      });
+      return {$promise: deferred.promise};
+      
+    }
   })
 })();
diff --git a/views/ngXosLib/xosHelpers/src/styles/main.scss b/views/ngXosLib/xosHelpers/src/styles/main.scss
index 43c54f6..cc02e6f 100644
--- a/views/ngXosLib/xosHelpers/src/styles/main.scss
+++ b/views/ngXosLib/xosHelpers/src/styles/main.scss
@@ -4,6 +4,7 @@
 @import '../ui_components/dumbComponents/table/table.scss';
 @import '../ui_components/dumbComponents/alert/alert.scss';
 @import '../ui_components/dumbComponents/validation/validation.scss';
+@import '../ui_components/dumbComponents/field/field.scss';
 
 @import '../ui_components/smartComponents/smartTable/smartTable.scss';
 
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/field/field.component.js b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/field/field.component.js
index c2aa62d..20b7707 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/field/field.component.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/field/field.component.js
@@ -26,6 +26,99 @@
     * }
     * ```
     * @param {mixed} ngModel The field value
+    *
+    * @example
+    
+    # Basic Example
+    
+      <example module="sampleField1">
+        <file name="script.js">
+          angular.module('sampleField1', ['xos.uiComponents'])
+          .factory('_', function($window){
+            return $window._;
+          })
+          .controller('SampleCtrl', function(){
+            this.name = 'input-name';
+            this.field = {label: 'My String Value:', type: 'string'};
+            this.model = 'my string';
+          });
+        </file>
+        <file name="index.html">
+          <div ng-controller="SampleCtrl as vm">
+            <xos-field ng-model="vm.model" name="vm.name" field="vm.field"></xos-field>
+          </div>
+        </file>
+      </example>
+      
+      # Possible Values
+
+      <example module="sampleField2">
+        <file name="script.js">
+          angular.module('sampleField2', ['xos.uiComponents'])
+          .factory('_', function($window){
+            return $window._;
+          })
+          .controller('SampleCtrl', function(){
+            this.field1 = {
+              name: 'number-field',
+              field: {label: 'My Number Value:', type: 'number'},
+              model: 2
+            };
+
+            this.field2 = {
+              name: 'date-field',
+              field: {label: 'My Date Value:', type: 'date'},
+              model: new Date()
+            };
+
+            this.field3 = {
+              name: 'boolean-field',
+              field: {label: 'My Boolean Value:', type: 'boolean'},
+              model: true
+            };
+
+            this.field4 = {
+              name: 'email-field',
+              field: {label: 'My Email Value:', type: 'email'},
+              model: 'sample@domain.us'
+            };
+          });
+        </file>
+        <file name="index.html">
+          <div ng-controller="SampleCtrl as vm">
+            <xos-field ng-model="vm.field1.model" name="vm.field1.name" field="vm.field1.field"></xos-field>
+            <xos-field ng-model="vm.field2.model" name="vm.field2.name" field="vm.field2.field"></xos-field>
+            <xos-field ng-model="vm.field3.model" name="vm.field3.name" field="vm.field3.field"></xos-field>
+            <xos-field ng-model="vm.field4.model" name="vm.field4.name" field="vm.field4.field"></xos-field>
+          </div>
+        </file>
+      </example>
+
+      # This element is recursive
+
+      <example module="sampleField3">
+        <file name="script.js">
+          angular.module('sampleField3', ['xos.uiComponents'])
+          .factory('_', function($window){
+            return $window._;
+          })
+          .controller('SampleCtrl', function(){
+            this.name = 'input-name';
+            this.field = {label: 'My Object Value:', type: 'object'};
+            this.model = {
+              name: 'Jhon',
+              age: '25',
+              email: 'jhon@thewall.ru',
+              active: true
+            };
+          });
+        </file>
+        <file name="index.html">
+          <div ng-controller="SampleCtrl as vm">
+            <xos-field ng-model="vm.model" name="vm.name" field="vm.field"></xos-field>
+          </div>
+        </file>
+      </example>
     */
   .directive('xosField', function(RecursionHelper){
     return {
@@ -69,7 +162,7 @@
                 <div ng-repeat="(k, v) in vm.ngModel">
                   <xos-field
                     name="k"
-                    field="{label: k, type: vm.getType(v)}"
+                    field="{label: vm.formatLabel(k), type: vm.getType(v)}"
                     ng-model="v">
                   </xos-field>
                 </div>
@@ -82,7 +175,7 @@
       compile: function (element) {
         return RecursionHelper.compile(element);
       },
-      controller: function(XosFormHelpers){
+      controller: function($attrs, XosFormHelpers, LabelFormatter){
         // console.log('Field: ', this.name, this.field, this.ngModel);
         if(!this.name){
           throw new Error('[xosField] Please provide a field name');
@@ -90,11 +183,12 @@
         if(!this.field){
           throw new Error('[xosField] Please provide a field definition');
         }
-        if(!angular.isDefined(this.ngModel)){
+        if(!$attrs.ngModel){
           throw new Error('[xosField] Please provide an ng-model');
         }
 
         this.getType = XosFormHelpers._getFieldFormat;
+        this.formatLabel = LabelFormatter.format;
 
         this.isEmptyObject = o => Object.keys(o).length === 0;
       }
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/field/field.scss b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/field/field.scss
new file mode 100644
index 0000000..8dd7ca4
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/field/field.scss
@@ -0,0 +1,3 @@
+xos-field {
+  display: block;
+}
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/form/form.component.js b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/form/form.component.js
index db4a2fd..92843c2 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/form/form.component.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/form/form.component.js
@@ -9,6 +9,7 @@
 (function () {
   'use strict';
 
+
   angular.module('xos.uiComponents')
 
   /**
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/validation/validation.component.js b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/validation/validation.component.js
index 84eb91a..dbe4fbb 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/validation/validation.component.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/validation/validation.component.js
@@ -74,24 +74,24 @@
     return {
       restrict: 'E',
       scope: {
-        errors: '='
+        field: '=',
+        form: '='
       },
       template: `
         <div ng-cloak>
-          <!-- <pre>{{vm.errors.email | json}}</pre> -->
-          <xos-alert config="vm.config" show="vm.errors.required !== undefined && vm.errors.required !== false">
+          <xos-alert config="vm.config" show="vm.field.$error.required !== undefined && vm.field.$error.required !== false  && (vm.field.$touched || vm.form.$submitted)">
             Field required
           </xos-alert>
-          <xos-alert config="vm.config" show="vm.errors.email !== undefined && vm.errors.email !== false">
+          <xos-alert config="vm.config" show="vm.field.$error.email !== undefined && vm.field.$error.email !== false  && (vm.field.$touched || vm.form.$submitted)">
             This is not a valid email
           </xos-alert>
-          <xos-alert config="vm.config" show="vm.errors.minlength !== undefined && vm.errors.minlength !== false">
+          <xos-alert config="vm.config" show="vm.field.$error.minlength !== undefined && vm.field.$error.minlength !== false  && (vm.field.$touched || vm.form.$submitted)">
             Too short
           </xos-alert>
-          <xos-alert config="vm.config" show="vm.errors.maxlength !== undefined && vm.errors.maxlength !== false">
+          <xos-alert config="vm.config" show="vm.field.$error.maxlength !== undefined && vm.field.$error.maxlength !== false  && (vm.field.$touched || vm.form.$submitted)">
             Too long
           </xos-alert>
-          <xos-alert config="vm.config" show="vm.errors.custom !== undefined && vm.errors.custom !== false">
+          <xos-alert config="vm.config" show="vm.field.$error.custom !== undefined && vm.field.$error.custom !== false  && (vm.field.$touched || vm.form.$submitted)">
             Field invalid
           </xos-alert>
         </div>
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/ui-components.module.js b/views/ngXosLib/xosHelpers/src/ui_components/ui-components.module.js
index ad3dc49..d94e59d 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/ui-components.module.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/ui-components.module.js
@@ -24,6 +24,7 @@
   **/
 
   angular.module('xos.uiComponents', [
-    'chart.js'
+    'chart.js',
+    'RecursionHelper'
   ])
 })();
diff --git a/views/ngXosLib/xosHelpers/src/xosHelpers.module.js b/views/ngXosLib/xosHelpers/src/xosHelpers.module.js
index 4ffc99d..fe246a6 100644
--- a/views/ngXosLib/xosHelpers/src/xosHelpers.module.js
+++ b/views/ngXosLib/xosHelpers/src/xosHelpers.module.js
@@ -24,8 +24,7 @@
         'ngResource',
         'ngAnimate',
         'bugSnag',
-        'xos.uiComponents',
-        'RecursionHelper'
+        'xos.uiComponents'
       ])
       .config(config)
 
diff --git a/views/ngXosViews/diagnostic/mocks/data/cordsubscriber.json b/views/ngXosViews/diagnostic/mocks/data/cordsubscriber.json
index e2409a7..9f5919a 100644
--- a/views/ngXosViews/diagnostic/mocks/data/cordsubscriber.json
+++ b/views/ngXosViews/diagnostic/mocks/data/cordsubscriber.json
@@ -3,7 +3,6 @@
           "humanReadableName": "cordSubscriber-1", 
           "id": 1, 
           "service_specific_id": "123", 
-          "vlan_id": "432", 
           "s_tag": "222", 
           "c_tag": "432", 
           "vcpe_id": 4, 
diff --git a/views/ngXosViews/subscribers/karma.conf.js b/views/ngXosViews/subscribers/karma.conf.js
index 4123be9..0e9c4d8 100644
--- a/views/ngXosViews/subscribers/karma.conf.js
+++ b/views/ngXosViews/subscribers/karma.conf.js
@@ -26,6 +26,7 @@
 
     // list of files / patterns to load in the browser
     files: bowerComponents.concat([
+      'node_modules/babel-polyfill/dist/polyfill.js',
       '../../../xos/core/xoslib/static/js/vendor/ngXosVendor.js',
       '../../../xos/core/xoslib/static/js/vendor/ngXosHelpers.js',
       'src/js/**/*.js',
@@ -78,7 +79,10 @@
 
     // start these browsers
     // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
-    browsers: ['PhantomJS'],
+    browsers: [
+      'PhantomJS',
+      'Chrome'
+    ],
 
 
     // Continuous Integration mode
diff --git a/views/ngXosViews/subscribers/package.json b/views/ngXosViews/subscribers/package.json
index 3d5def5..96a2326 100644
--- a/views/ngXosViews/subscribers/package.json
+++ b/views/ngXosViews/subscribers/package.json
@@ -21,6 +21,7 @@
   "dependencies": {},
   "devDependencies": {
     "autoprefixer": "^6.3.3",
+    "babel-polyfill": "^6.9.0",
     "browser-sync": "^2.9.11",
     "css-mqpacker": "^4.0.0",
     "csswring": "^4.2.1",
@@ -48,6 +49,7 @@
     "jasmine-core": "~2.3.4",
     "karma": "^0.13.14",
     "karma-babel-preprocessor": "~5.2.2",
+    "karma-chrome-launcher": "^1.0.1",
     "karma-coverage": "^0.5.3",
     "karma-jasmine": "~0.3.6",
     "karma-mocha-reporter": "~1.1.1",
diff --git a/views/ngXosViews/subscribers/spec/sample.test.js b/views/ngXosViews/subscribers/spec/sample.test.js
index 9b06600..1b7796c 100644
--- a/views/ngXosViews/subscribers/spec/sample.test.js
+++ b/views/ngXosViews/subscribers/spec/sample.test.js
@@ -1,7 +1,17 @@
 'use strict';
 
-describe('The User List', () => {
+describe('The Subscriber View', () => {
   
+  const subscribersList = [
+    {
+      humanReadableName: 'cordSubscriber-1',
+      features: {cdn: false, uplink_speed: 1000000000, downlink_speed: 1000000000, uverse: true, status: 'enabled'},
+      id: 1,
+      identity: {account_num: '123', name: 'Stanford'},
+      related: {}
+    }
+  ];
+
   var scope, element, isolatedScope, httpBackend;
 
   beforeEach(module('xos.subscribers'));
@@ -10,28 +20,34 @@
   beforeEach(inject(function($httpBackend, $compile, $rootScope){
     
     httpBackend = $httpBackend;
-    // Setting up mock request
-    $httpBackend.expectGET('/api/core/users/?no_hyperlinks=1').respond([
-      {
-        email: 'matteo.scandolo@gmail.com',
-        firstname: 'Matteo',
-        lastname: 'Scandolo' 
-      }
-    ]);
+    
+    httpBackend.whenGET('/api/tenant/cord/subscriber/?no_hyperlinks=1').respond(subscribersList);
   
     scope = $rootScope.$new();
-    element = angular.element('<users-list></users-list>');
+    element = angular.element('<subscribers-list></subscribers-list>');
     $compile(element)(scope);
     scope.$digest();
     isolatedScope = element.isolateScope().vm;
   }));
 
-  xit('should load 1 users', () => {
+  it('should load 1 subscriber', () => {
+    // this
     httpBackend.flush();
-    expect(isolatedScope.users.length).toBe(1);
-    expect(isolatedScope.users[0].email).toEqual('matteo.scandolo@gmail.com');
-    expect(isolatedScope.users[0].firstname).toEqual('Matteo');
-    expect(isolatedScope.users[0].lastname).toEqual('Scandolo');
+    scope.$digest();
+    let table = $(element).find('table');
+    let tr = table.find('tbody:last-child tr');
+    // let tds = $(tr[1]).find('td');
+    // console.log(tr);
+    expect(tr.length).toBe(1);
+    // expect($(tds[0]).html()).toBe('cordSubscriber-1')
+  });
+
+  it('should configure xos-smart-table', () => {
+    expect(isolatedScope.smartTableConfig).toEqual({resource: 'Subscribers'});
+  });
+
+  it('should render xos-smart-table', () => {
+    expect($(element).find('xos-smart-table').length).toBe(1);
   });
 
 });
\ No newline at end of file
diff --git a/views/ngXosViews/subscribers/src/js/main.js b/views/ngXosViews/subscribers/src/js/main.js
index 838efa0..203e9ff 100644
--- a/views/ngXosViews/subscribers/src/js/main.js
+++ b/views/ngXosViews/subscribers/src/js/main.js
@@ -28,27 +28,6 @@
       this.smartTableConfig = {
         resource: 'Subscribers'
       };
-
-      this.model = {
-        label: {
-          name: 'aaa'
-        },
-        empty: {}
-      }
-      this.config = {
-        exclude: ['password', 'last_login'],
-        formName: 'sampleForm',
-        actions: [
-          {
-            label: 'Save',
-            icon: 'ok', // refers to bootstraps glyphicon
-            cb: (user) => { // receive the model
-              console.log(user);
-            },
-            class: 'success'
-          }
-        ]
-      };
     }
   };
 });
\ No newline at end of file
diff --git a/views/ngXosViews/subscribers/src/templates/subscribers-list.tpl.html b/views/ngXosViews/subscribers/src/templates/subscribers-list.tpl.html
index 2e9298b..d6e755b 100644
--- a/views/ngXosViews/subscribers/src/templates/subscribers-list.tpl.html
+++ b/views/ngXosViews/subscribers/src/templates/subscribers-list.tpl.html
@@ -1,2 +1 @@
-<!-- <xos-form ng-model="vm.model" config="vm.config"></xos-form> -->
 <xos-smart-table config="vm.smartTableConfig"></xos-smart-table>
\ No newline at end of file
diff --git a/views/ngXosViews/synchronizerNotifier/.bowerrc b/views/ngXosViews/synchronizerNotifier/.bowerrc
new file mode 100644
index 0000000..e491038
--- /dev/null
+++ b/views/ngXosViews/synchronizerNotifier/.bowerrc
@@ -0,0 +1,3 @@
+{
+  "directory": "src/vendor/"
+}
\ No newline at end of file
diff --git a/views/ngXosViews/synchronizerNotifier/.eslintrc b/views/ngXosViews/synchronizerNotifier/.eslintrc
new file mode 100644
index 0000000..c852748
--- /dev/null
+++ b/views/ngXosViews/synchronizerNotifier/.eslintrc
@@ -0,0 +1,42 @@
+{
+    "ecmaFeatures": {
+        "blockBindings": true,
+        "forOf": true,
+        "destructuring": true,
+        "arrowFunctions": true,
+        "templateStrings": true
+    },
+    "env": { 
+        "browser": true,
+        "node": true,
+        "es6": true
+    },
+    "plugins": [
+        //"angular"
+    ],
+    "rules": {
+        "quotes": [2, "single"],
+        "camelcase": [1, {"properties": "always"}],
+        "no-underscore-dangle": 1,
+        "eqeqeq": [2, "smart"],
+        "no-alert": 1,
+        "key-spacing": [1, { "beforeColon": false, "afterColon": true }],
+        "indent": [2, 2],
+        "no-irregular-whitespace": 1,
+        "eol-last": 0,
+        "max-nested-callbacks": [2, 4],
+        "comma-spacing": [1, {"before": false, "after": true}],
+        "no-trailing-spaces": [1, { skipBlankLines: true }],
+        "no-unused-vars": [1, {"vars": "all", "args": "after-used"}],
+        "new-cap": 0,
+
+        //"angular/ng_module_name": [2, '/^xos\.*[a-z]*$/'],
+        //"angular/ng_controller_name": [2, '/^[a-z].*Ctrl$/'],
+        //"angular/ng_service_name": [2, '/^[A-Z].*Service$/'],
+        //"angular/ng_directive_name": [2, '/^[a-z]+[[A-Z].*]*$/'],
+        //"angular/ng_di": [0, "function or array"]
+    },
+    "globals" :{
+        "angular": true
+    } 
+}
\ No newline at end of file
diff --git a/views/ngXosViews/synchronizerNotifier/.gitignore b/views/ngXosViews/synchronizerNotifier/.gitignore
new file mode 100644
index 0000000..567aee4
--- /dev/null
+++ b/views/ngXosViews/synchronizerNotifier/.gitignore
@@ -0,0 +1,6 @@
+dist/
+src/vendor
+.tmp
+node_modules
+npm-debug.log
+dist/
\ No newline at end of file
diff --git a/views/ngXosViews/synchronizerNotifier/bower.json b/views/ngXosViews/synchronizerNotifier/bower.json
new file mode 100644
index 0000000..8b0eb12
--- /dev/null
+++ b/views/ngXosViews/synchronizerNotifier/bower.json
@@ -0,0 +1,32 @@
+{
+  "name": "xos-synchronizerNotifier",
+  "version": "0.0.0",
+  "authors": [
+    "Matteo Scandolo <matteo.scandolo@gmail.com>"
+  ],
+  "description": "The synchronizerNotifier view",
+  "license": "MIT",
+  "ignore": [
+    "**/.*",
+    "node_modules",
+    "bower_components",
+    "static/js/vendor/",
+    "test",
+    "tests"
+  ],
+  "dependencies": {},
+  "devDependencies": {
+    "jquery": "2.1.4",
+    "angular-mocks": "1.4.7",
+    "angular": "1.4.7",
+    "angular-ui-router": "0.2.15",
+    "angular-cookies": "1.4.7",
+    "angular-animate": "1.4.7",
+    "angular-resource": "1.4.7",
+    "lodash": "~4.11.1",
+    "bootstrap-css": "3.3.6",
+    "angular-chart.js": "~0.10.2",
+    "d3": "~3.5.17",
+    "angular-recursion": "~1.0.5"
+  }
+}
diff --git a/views/ngXosViews/synchronizerNotifier/gulp/build.js b/views/ngXosViews/synchronizerNotifier/gulp/build.js
new file mode 100644
index 0000000..47cb69c
--- /dev/null
+++ b/views/ngXosViews/synchronizerNotifier/gulp/build.js
@@ -0,0 +1,164 @@
+'use strict';
+
+// BUILD
+//
+// The only purpose of this gulpfile is to build a XOS view and copy the correct files into
+// .html => dashboards
+// .js (minified and concat) => static/js
+//
+// The template are parsed and added to js with angular $templateCache
+
+var gulp = require('gulp');
+var ngAnnotate = require('gulp-ng-annotate');
+var uglify = require('gulp-uglify');
+var templateCache = require('gulp-angular-templatecache');
+var runSequence = require('run-sequence');
+var concat = require('gulp-concat-util');
+var del = require('del');
+var wiredep = require('wiredep');
+var angularFilesort = require('gulp-angular-filesort');
+var _ = require('lodash');
+var eslint = require('gulp-eslint');
+var inject = require('gulp-inject');
+var rename = require('gulp-rename');
+var replace = require('gulp-replace');
+var postcss = require('gulp-postcss');
+var autoprefixer = require('autoprefixer');
+var mqpacker = require('css-mqpacker');
+var csswring = require('csswring');
+
+const TEMPLATE_FOOTER = `
+angular.module('xos.synchronizerNotifier')
+.run(['$location', function(a){
+  a.path('/');
+}])
+`
+
+module.exports = function(options){
+  
+  // delete previous builded file
+  gulp.task('clean', function(){
+    return del(
+      [
+        options.dashboards + 'xosSynchronizerNotifier.html',
+        options.static + 'css/xosSynchronizerNotifier.css'
+      ],
+      {force: true}
+    );
+  });
+
+  // minify css
+  gulp.task('css', function () {
+    var processors = [
+      autoprefixer({browsers: ['last 1 version']}),
+      mqpacker,
+      csswring
+    ];
+
+    gulp.src([
+      `${options.css}**/*.css`,
+      `!${options.css}dev.css`
+    ])
+    .pipe(postcss(processors))
+    .pipe(gulp.dest(options.tmp + '/css/'));
+  });
+
+  // copy css in correct folder
+  gulp.task('copyCss', ['wait'], function(){
+    return gulp.src([`${options.tmp}/css/*.css`])
+    .pipe(concat('xosSynchronizerNotifier.css'))
+    .pipe(gulp.dest(options.static + 'css/'))
+  });
+
+  // compile and minify scripts
+  gulp.task('scripts', function() {
+    return gulp.src([
+      options.tmp + '**/*.js'
+    ])
+    .pipe(ngAnnotate())
+    .pipe(angularFilesort())
+    .pipe(concat('xosSynchronizerNotifier.js'))
+    .pipe(concat.header('//Autogenerated, do not edit!!!\n'))
+    .pipe(concat.footer(TEMPLATE_FOOTER))
+    .pipe(uglify())
+    .pipe(gulp.dest(options.static + 'js/'));
+  });
+
+  // set templates in cache
+  gulp.task('templates', function(){
+    return gulp.src('./src/templates/*.html')
+      .pipe(templateCache({
+        module: 'xos.synchronizerNotifier',
+        root: 'templates/'
+      }))
+      .pipe(gulp.dest(options.tmp));
+  });
+
+  // copy html index to Django Folder
+  gulp.task('copyHtml', function(){
+    return gulp.src(options.src + 'index.html')
+      // remove dev dependencies from html
+      .pipe(replace(/<!-- bower:css -->(\n^<link.*)*\n<!-- endbower -->/gmi, ''))
+      .pipe(replace(/<!-- bower:js -->(\n^<script.*)*\n<!-- endbower -->/gmi, ''))
+      // injecting minified files
+      .pipe(
+        inject(
+          gulp.src([
+            options.static + 'js/vendor/xosSynchronizerNotifierVendor.js',
+            options.static + 'js/xosSynchronizerNotifier.js',
+            options.static + 'css/xosSynchronizerNotifier.css'
+          ]),
+          {ignorePath: '/../../../xos/core/xoslib'}
+        )
+      )
+      .pipe(rename('xosSynchronizerNotifier.html'))
+      .pipe(gulp.dest(options.dashboards));
+  });
+
+  // minify vendor js files
+  gulp.task('wiredep', function(){
+    var bowerDeps = wiredep().js;
+    if(!bowerDeps){
+      return;
+    }
+
+    // remove angular (it's already loaded)
+    _.remove(bowerDeps, function(dep){
+      return dep.indexOf('angular/angular.js') !== -1;
+    });
+
+    return gulp.src(bowerDeps)
+      .pipe(concat('xosSynchronizerNotifierVendor.js'))
+      .pipe(uglify())
+      .pipe(gulp.dest(options.static + 'js/vendor/'));
+  });
+
+  gulp.task('lint', function () {
+    return gulp.src(['src/js/**/*.js'])
+      .pipe(eslint())
+      .pipe(eslint.format())
+      .pipe(eslint.failAfterError());
+  });
+
+  gulp.task('wait', function (cb) {
+    // setTimeout could be any async task
+    setTimeout(function () {
+      cb();
+    }, 1000);
+  });
+
+  gulp.task('build', function() {
+    runSequence(
+      'clean',
+      'sass',
+      'templates',
+      'babel',
+      'scripts',
+      'wiredep',
+      'css',
+      'copyCss',
+      'copyHtml',
+      'cleanTmp'
+    );
+  });
+};
\ No newline at end of file
diff --git a/views/ngXosViews/synchronizerNotifier/gulp/server.js b/views/ngXosViews/synchronizerNotifier/gulp/server.js
new file mode 100644
index 0000000..1e40a34
--- /dev/null
+++ b/views/ngXosViews/synchronizerNotifier/gulp/server.js
@@ -0,0 +1,170 @@
+'use strict';
+
+var gulp = require('gulp');
+var browserSync = require('browser-sync').create();
+var inject = require('gulp-inject');
+var runSequence = require('run-sequence');
+var angularFilesort = require('gulp-angular-filesort');
+var babel = require('gulp-babel');
+var wiredep = require('wiredep').stream;
+var httpProxy = require('http-proxy');
+var del = require('del');
+var sass = require('gulp-sass');
+var fs = require('fs');
+var path = require('path');
+
+const environment = process.env.NODE_ENV;
+
+if(!fs.existsSync(path.join(__dirname, `../../../env/${environment || 'default'}.js`))){
+  if(!environment){
+    throw new Error('You should define a default.js config in /views/env folder.');
+  }
+  else{
+    throw new Error(`Since you are loading a custom environment, you should define a ${environment}.js config in /views/env folder.`);
+  }
+}
+
+var conf = require(path.join(__dirname, `../../../env/${environment || 'default'}.js`));
+
+var proxy = httpProxy.createProxyServer({
+  target: conf.host
+});
+
+
+proxy.on('error', function(error, req, res) {
+  res.writeHead(500, {
+    'Content-Type': 'text/plain'
+  });
+
+  console.error('[Proxy]', error);
+});
+
+module.exports = function(options){
+
+  gulp.task('browser', function() {
+    browserSync.init({
+      startPath: '#/',
+      snippetOptions: {
+        rule: {
+          match: /<!-- browserSync -->/i
+        }
+      },
+      server: {
+        baseDir: options.src,
+        routes: {
+          '/xos/core/xoslib/static/js/vendor': options.helpers,
+          '/xos/core/static': options.static + '../../static/'
+        },
+        middleware: function(req, res, next){
+          if(
+            req.url.indexOf('/api/') !== -1
+          ){
+            if(conf.xoscsrftoken && conf.xossessionid){
+              req.headers.cookie = `xoscsrftoken=${conf.xoscsrftoken}; xossessionid=${conf.xossessionid}`;
+              req.headers['x-csrftoken'] = conf.xoscsrftoken;
+            }
+            proxy.web(req, res);
+          }
+          else{
+            next();
+          }
+        }
+      }
+    });
+
+    gulp.watch(options.src + 'js/**/*.js', ['js-watch']);
+    gulp.watch(options.src + 'vendor/**/*.js', ['bower'], function(){
+      browserSync.reload();
+    });
+    gulp.watch(options.src + '**/*.html', function(){
+      browserSync.reload();
+    });
+    gulp.watch(options.css + '**/*.css', function(){
+      browserSync.reload();
+    });
+    gulp.watch(`${options.sass}/**/*.scss`, ['sass'], function(){
+      browserSync.reload();
+    });
+
+    gulp.watch([
+      options.helpers + 'ngXosHelpers.js',
+      options.static + '../../static/xosNgLib.css'
+    ], function(){
+      browserSync.reload();
+    });
+  });
+
+  // compile sass
+  gulp.task('sass', function () {
+    return gulp.src(`${options.sass}/**/*.scss`)
+      .pipe(sass().on('error', sass.logError))
+      .pipe(gulp.dest(options.css));
+  });
+
+  // transpile js with sourceMaps
+  gulp.task('babel', function(){
+    return gulp.src(options.scripts + '**/*.js')
+      .pipe(babel({sourceMaps: true}))
+      .pipe(gulp.dest(options.tmp));
+  });
+
+  // inject scripts
+  gulp.task('injectScript', ['cleanTmp', 'babel'], function(){
+    return gulp.src(options.src + 'index.html')
+      .pipe(
+        inject(
+          gulp.src([
+            options.tmp + '**/*.js',
+            options.helpers + 'ngXosHelpers.js'
+          ])
+          .pipe(angularFilesort()),
+          {
+            ignorePath: [options.src, '/../../ngXosLib']
+          }
+        )
+      )
+      .pipe(gulp.dest(options.src));
+  });
+
+  // inject CSS
+  gulp.task('injectCss', function(){
+    return gulp.src(options.src + 'index.html')
+      .pipe(
+        inject(
+          gulp.src([
+            options.src + 'css/*.css',
+            options.static + '../../static/xosNgLib.css'
+          ]),
+          {
+            ignorePath: [options.src]
+          }
+          )
+        )
+      .pipe(gulp.dest(options.src));
+  });
+
+  // inject bower dependencies with wiredep
+  gulp.task('bower', function () {
+    return gulp.src(options.src + 'index.html')
+    .pipe(wiredep({devDependencies: true}))
+    .pipe(gulp.dest(options.src));
+  });
+
+  gulp.task('js-watch', ['injectScript'], function(){
+    browserSync.reload();
+  });
+
+  gulp.task('cleanTmp', function(){
+    return del([options.tmp + '**/*']);
+  });
+
+  gulp.task('serve', function() {
+    runSequence(
+      'sass',
+      'bower',
+      'injectScript',
+      'injectCss',
+      ['browser']
+    );
+  });
+};
diff --git a/views/ngXosViews/synchronizerNotifier/gulpfile.js b/views/ngXosViews/synchronizerNotifier/gulpfile.js
new file mode 100644
index 0000000..08df554
--- /dev/null
+++ b/views/ngXosViews/synchronizerNotifier/gulpfile.js
@@ -0,0 +1,26 @@
+'use strict';
+
+var gulp = require('gulp');
+var wrench = require('wrench');
+
+var options = {
+  src: 'src/',
+  css: 'src/css/',
+  sass: 'src/sass/',
+  scripts: 'src/js/',
+  tmp: 'src/.tmp',
+  dist: 'dist/',
+  api: '../../ngXosLib/api/',
+  helpers: '../../../xos/core/xoslib/static/js/vendor/',
+  static: '../../../xos/core/xoslib/static/', // this is the django static folder
+  dashboards: '../../../xos/core/xoslib/dashboards/' // this is the django html folder
+};
+
+wrench.readdirSyncRecursive('./gulp')
+.map(function(file) {
+  require('./gulp/' + file)(options);
+});
+
+gulp.task('default', function () {
+  gulp.start('build');
+});
diff --git a/views/ngXosViews/synchronizerNotifier/karma.conf.js b/views/ngXosViews/synchronizerNotifier/karma.conf.js
new file mode 100644
index 0000000..4123be9
--- /dev/null
+++ b/views/ngXosViews/synchronizerNotifier/karma.conf.js
@@ -0,0 +1,88 @@
+// Karma configuration
+// Generated on Tue Oct 06 2015 09:27:10 GMT+0000 (UTC)
+
+/* eslint indent: [2,2], quotes: [2, "single"]*/
+
+/*eslint-disable*/
+var wiredep = require('wiredep');
+var path = require('path');
+
+var bowerComponents = wiredep( {devDependencies: true} )[ 'js' ].map(function( file ){
+  return path.relative(process.cwd(), file);
+});
+
+module.exports = function(config) {
+/*eslint-enable*/
+  config.set({
+
+    // base path that will be used to resolve all patterns (eg. files, exclude)
+    basePath: '',
+
+
+    // frameworks to use
+    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+    frameworks: ['jasmine'],
+
+
+    // list of files / patterns to load in the browser
+    files: bowerComponents.concat([
+      '../../../xos/core/xoslib/static/js/vendor/ngXosVendor.js',
+      '../../../xos/core/xoslib/static/js/vendor/ngXosHelpers.js',
+      'src/js/**/*.js',
+      'spec/**/*.mock.js',
+      'spec/**/*.test.js',
+      'src/**/*.html'
+    ]),
+
+
+    // list of files to exclude
+    exclude: [
+    ],
+
+
+    // preprocess matching files before serving them to the browser
+    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+    preprocessors: {
+      'src/js/**/*.js': ['babel'],
+      'spec/**/*.test.js': ['babel'],
+      'src/**/*.html': ['ng-html2js']
+    },
+
+    ngHtml2JsPreprocessor: {
+      stripPrefix: 'src/', //strip the src path from template url (http://stackoverflow.com/questions/22869668/karma-unexpected-request-when-testing-angular-directive-even-with-ng-html2js)
+      moduleName: 'templates' // define the template module name
+    },
+
+    // test results reporter to use
+    // possible values: 'dots', 'progress'
+    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
+    reporters: ['mocha'],
+
+
+    // web server port
+    port: 9876,
+
+
+    // enable / disable colors in the output (reporters and logs)
+    colors: true,
+
+
+    // level of logging
+    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+    logLevel: config.LOG_INFO,
+
+
+    // enable / disable watching file and executing tests whenever any file changes
+    autoWatch: true,
+
+
+    // start these browsers
+    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+    browsers: ['PhantomJS'],
+
+
+    // Continuous Integration mode
+    // if true, Karma captures browsers, runs the tests and exits
+    singleRun: false
+  });
+};
diff --git a/views/ngXosViews/synchronizerNotifier/package.json b/views/ngXosViews/synchronizerNotifier/package.json
new file mode 100644
index 0000000..ad76efe
--- /dev/null
+++ b/views/ngXosViews/synchronizerNotifier/package.json
@@ -0,0 +1,63 @@
+{
+  "name": "xos-synchronizerNotifier",
+  "version": "1.0.0",
+  "description": "Angular Application for XOS, created with generator-xos",
+  "scripts": {
+    "prestart": "npm install && bower install",
+    "start": "gulp serve",
+    "prebuild": "npm install && bower install",
+    "build": "gulp",
+    "test": "karma start",
+    "test:ci": "karma start --single-run",
+    "lint": "eslint src/js/"
+  },
+  "keywords": [
+    "XOS",
+    "Angular",
+    "XOSlib"
+  ],
+  "author": "Matteo Scandolo",
+  "license": "MIT",
+  "dependencies": {},
+  "devDependencies": {
+    "autoprefixer": "^6.3.3",
+    "browser-sync": "^2.9.11",
+    "css-mqpacker": "^4.0.0",
+    "csswring": "^4.2.1",
+    "del": "^2.0.2",
+    "easy-mocker": "^1.2.0",
+    "eslint": "^1.8.0",
+    "eslint-plugin-angular": "linkmesrl/eslint-plugin-angular",
+    "gulp": "^3.9.0",
+    "gulp-angular-filesort": "^1.1.1",
+    "gulp-angular-templatecache": "^1.8.0",
+    "gulp-babel": "^5.3.0",
+    "gulp-concat": "^2.6.0",
+    "gulp-concat-util": "^0.5.5",
+    "gulp-eslint": "^1.0.0",
+    "gulp-inject": "^3.0.0",
+    "gulp-minify-html": "^1.0.4",
+    "gulp-ng-annotate": "^1.1.0",
+    "gulp-postcss": "^6.0.1",
+    "gulp-rename": "^1.2.2",
+    "gulp-replace": "^0.5.4",
+    "gulp-sass": "^2.2.0",
+    "gulp-uglify": "^1.4.2",
+    "http-proxy": "^1.12.0",
+    "ink-docstrap": "^0.5.2",
+    "jasmine-core": "~2.3.4",
+    "karma": "^0.13.14",
+    "karma-babel-preprocessor": "~5.2.2",
+    "karma-coverage": "^0.5.3",
+    "karma-jasmine": "~0.3.6",
+    "karma-mocha-reporter": "~1.1.1",
+    "karma-ng-html2js-preprocessor": "^0.2.0",
+    "karma-phantomjs-launcher": "~0.2.1",
+    "lodash": "^3.10.1",
+    "phantomjs": "^1.9.19",
+    "proxy-middleware": "^0.15.0",
+    "run-sequence": "^1.1.4",
+    "wiredep": "^3.0.0-beta",
+    "wrench": "^1.5.8"
+  }
+}
diff --git a/views/ngXosViews/synchronizerNotifier/spec/notification.test.js b/views/ngXosViews/synchronizerNotifier/spec/notification.test.js
new file mode 100644
index 0000000..265b7b9
--- /dev/null
+++ b/views/ngXosViews/synchronizerNotifier/spec/notification.test.js
@@ -0,0 +1,76 @@
+'use strict';
+
+describe('The Synchronizer Notification Panel', () => {
+  
+  var scope, element, isolatedScope, XosUserPrefs;
+  const xosNotification = {
+    notify: jasmine.createSpy('notify')
+  };
+
+  const failureEvent = {
+    name: 'test',
+    status: false
+  };
+
+  const successEvent = {
+    name: 'test',
+    status: true
+  };
+
+  beforeEach(module('xos.synchronizerNotifier', ($provide) => {
+    $provide.value('Diag', {
+      start: () => null
+    });
+
+    $provide.value('xosNotification', xosNotification);
+  }));
+  beforeEach(module('templates'));
+
+  beforeEach(inject(function($compile, $rootScope, _XosUserPrefs_){
+
+    XosUserPrefs = _XosUserPrefs_;
+    scope = $rootScope.$new();
+    element = angular.element('<sync-status></sync-status>');
+    $compile(element)(scope);
+    scope.$digest();
+    isolatedScope = element.isolateScope().vm;
+  }));
+
+  describe('when an event is received', () => {
+
+    beforeEach(() => {
+      xosNotification.notify.calls.reset()
+    });
+
+    describe('and notification have not been sent', () => {
+      
+      beforeEach(() => {
+        XosUserPrefs.setSynchronizerNotificationStatus('test', false);
+        scope.$emit('diag', failureEvent);
+      });
+
+      it('should trigger notification', () => {
+        expect(xosNotification.notify).toHaveBeenCalled();
+      });
+
+      it('should update status in the scope', () => {
+        expect(isolatedScope.synchronizers.test).toEqual(failureEvent);
+        scope.$emit('diag', successEvent);
+        expect(isolatedScope.synchronizers.test).toEqual(successEvent);
+      });
+    });
+
+    describe('and notification have been sent', () => {
+      
+      beforeEach(() => {
+        XosUserPrefs.setSynchronizerNotificationStatus('test', true);
+        scope.$emit('diag', failureEvent);
+      });
+
+      it('should not trigger multiple notification for the same synchronizer', () => {
+        expect(xosNotification.notify).not.toHaveBeenCalled();
+      });
+    });
+  });
+
+});
\ No newline at end of file
diff --git a/views/ngXosViews/synchronizerNotifier/src/css/main.css b/views/ngXosViews/synchronizerNotifier/src/css/main.css
new file mode 100644
index 0000000..88a08e7
--- /dev/null
+++ b/views/ngXosViews/synchronizerNotifier/src/css/main.css
@@ -0,0 +1,14 @@
+#xosSynchronizerNotifier {
+  float: left; }
+  #xosSynchronizerNotifier .alert {
+    margin-bottom: 0px !important; }
+  #xosSynchronizerNotifier .sync-status-container {
+    position: relative;
+    z-index: 200; }
+  #xosSynchronizerNotifier .notification-panel {
+    position: absolute;
+    width: 200px; }
+  #xosSynchronizerNotifier sync-status .badge.success {
+    background-color: #5cb85c; }
+  #xosSynchronizerNotifier sync-status .badge.warning {
+    background-color: #f0ad4e; }
diff --git a/views/ngXosViews/synchronizerNotifier/src/index.html b/views/ngXosViews/synchronizerNotifier/src/index.html
new file mode 100644
index 0000000..cb9b7b5
--- /dev/null
+++ b/views/ngXosViews/synchronizerNotifier/src/index.html
@@ -0,0 +1,35 @@
+<!-- browserSync -->
+<!-- bower:css -->
+<link rel="stylesheet" href="vendor/bootstrap-css/css/bootstrap.min.css" />
+<link rel="stylesheet" href="vendor/angular-chart.js/dist/angular-chart.css" />
+<!-- endbower -->
+<!-- endcss -->
+<!-- inject:css -->
+<link rel="stylesheet" href="/css/main.css">
+<link rel="stylesheet" href="/../../../xos/core/static/xosNgLib.css">
+<!-- endinject -->
+
+<div id="xosSynchronizerNotifier">
+  <sync-status></sync-status>
+</div>
+
+<!-- bower:js -->
+<script src="vendor/jquery/dist/jquery.js"></script>
+<script src="vendor/angular/angular.js"></script>
+<script src="vendor/angular-mocks/angular-mocks.js"></script>
+<script src="vendor/angular-ui-router/release/angular-ui-router.js"></script>
+<script src="vendor/angular-cookies/angular-cookies.js"></script>
+<script src="vendor/angular-animate/angular-animate.js"></script>
+<script src="vendor/angular-resource/angular-resource.js"></script>
+<script src="vendor/lodash/lodash.js"></script>
+<script src="vendor/bootstrap-css/js/bootstrap.min.js"></script>
+<script src="vendor/Chart.js/Chart.js"></script>
+<script src="vendor/angular-chart.js/dist/angular-chart.js"></script>
+<script src="vendor/d3/d3.js"></script>
+<script src="vendor/angular-recursion/angular-recursion.js"></script>
+<!-- endbower -->
+<!-- endjs -->
+<!-- inject:js -->
+<script src="/../../../xos/core/xoslib/static/js/vendor/ngXosHelpers.js"></script>
+<script src="/.tmp/main.js"></script>
+<!-- endinject -->
\ No newline at end of file
diff --git a/views/ngXosViews/synchronizerNotifier/src/js/main.js b/views/ngXosViews/synchronizerNotifier/src/js/main.js
new file mode 100644
index 0000000..e761fad
--- /dev/null
+++ b/views/ngXosViews/synchronizerNotifier/src/js/main.js
@@ -0,0 +1,131 @@
+'use strict';
+
+angular.module('xos.synchronizerNotifier', [
+  'ngResource',
+  'ngCookies',
+  'ui.router',
+  'xos.helpers'
+])
+.service('Diag', function($rootScope, $http, $q, $interval){
+
+  let isRunning = false;
+
+  this.getDiags = () => {
+    let d = $q.defer();
+    $http.get('/api/core/diags')
+    .then(res => {
+      d.resolve(res.data);
+    })
+    .catch(err => {
+      d.reject(err);
+    });
+
+    return d.promise;
+  };
+
+  this.sendEvents = (diags) => {
+    diags.forEach(d => {
+      let status = JSON.parse(d.backend_register);
+      status.last_run = new Date(status.last_run * 1000);
+      status.last_duration = status.last_duration * 1000;
+      status.last_synchronizer_start = new Date(status.last_synchronizer_start * 1000);
+      status.last_syncrecord_start = status.last_syncrecord_start ? new Date(status.last_syncrecord_start * 1000) : null;
+      $rootScope.$broadcast(`diag`, {
+        name: d.name,
+        updated: d.updated,
+        info: status,
+        status: this.getSyncStatus(status)
+      });
+    });
+  };
+
+  this.start = () => {
+    isRunning = true;
+    this.getDiags()
+    .then(diags => {
+      this.sendEvents(diags);
+    });
+    return isRunning;
+  };
+
+  this.stop = () => {
+    isRunning = false;
+    return isRunning;
+  };
+
+  this.getSyncStatus = (status) => {
+
+    const now = new Date();
+    const gap = 15 * 60 * 1000; /* ms */
+    // const gap = 1 * 60 * 1000; // for demo use 1 minute
+    // if all of this values are older than 15 min,
+    // probably something is wrong
+    if (
+      (now - status.last_synchronizer_start) > gap &&
+      (now - status.last_syncrecord_start) > gap &&
+      (now - status.last_run) > gap
+    ){
+      return false;
+    }
+    else{
+      return true;
+    }
+  }
+
+  $interval(() => {
+    if(isRunning){
+      this.getDiags()
+      .then(diags => {
+        this.sendEvents(diags);
+      });
+    }
+  }, 5 * 60 * 1000);
+})
+.directive('syncStatus', function() {
+  return {
+    restrict: 'E',
+    scope: {},
+    bindToController: true,
+    controllerAs: 'vm',
+    templateUrl: 'templates/sync-status.tpl.html',
+    controller: function($log, $rootScope, Diag, xosNotification, XosUserPrefs){
+      Diag.start();
+      // to debug set this to true,
+      // the panel will be opened by default
+      // this.showNotificationPanel = true;
+      this.synchronizers = {};
+
+      this.showNoSync = true;
+
+      $rootScope.$on('diag', (e, d) => {
+        this.synchronizers[d.name] = d;
+
+        // if errored
+        if(!d.status){
+          // and not already notified
+          if(!XosUserPrefs.getSynchronizerNotificationStatus(d.name)){
+            xosNotification.notify('CORD Synchronizer', {
+              icon: '/static/cord-logo.png',
+              body: `The ${d.name} synchronizer has not performed actions in the last 15 minutes.`
+            });
+          }
+          XosUserPrefs.setSynchronizerNotificationStatus(d.name, true);
+        }
+        else {
+          XosUserPrefs.setSynchronizerNotificationStatus(d.name, false);
+        }
+
+        // hide list if empty
+        this.showNoSync = false;
+        if(Object.keys(this.synchronizers).length === 0){
+          this.showNoSync = true;
+        }
+      });
+
+    }
+  }
+});
+
+angular.element(document).ready(function() {
+  angular.bootstrap('#xosSynchronizerNotifier', ['xos.synchronizerNotifier']);
+});
\ No newline at end of file
diff --git a/views/ngXosViews/synchronizerNotifier/src/sass/main.scss b/views/ngXosViews/synchronizerNotifier/src/sass/main.scss
new file mode 100644
index 0000000..d101d76
--- /dev/null
+++ b/views/ngXosViews/synchronizerNotifier/src/sass/main.scss
@@ -0,0 +1,32 @@
+@import '../../../../style/sass/lib/_variables.scss';
+
+#xosSynchronizerNotifier {
+  
+  float: left;
+
+  .alert {
+    margin-bottom: 0px !important;
+  }
+
+  .sync-status-container {
+    position: relative;
+    z-index: 200;
+  }
+
+  .notification-panel {
+    position: absolute;
+    width: 200px;
+  }
+
+  sync-status {
+    .badge {
+      &.success {
+        background-color: $brand-success;
+      }
+
+      &.warning {
+        background-color: $brand-warning;
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/views/ngXosViews/synchronizerNotifier/src/templates/sync-status.tpl.html b/views/ngXosViews/synchronizerNotifier/src/templates/sync-status.tpl.html
new file mode 100644
index 0000000..cbd794e
--- /dev/null
+++ b/views/ngXosViews/synchronizerNotifier/src/templates/sync-status.tpl.html
@@ -0,0 +1,21 @@
+<div class="sync-status-container">
+  <div class="btn btn-default" ng-click="vm.showNotificationPanel = !vm.showNotificationPanel">
+    <i class="glyphicon glyphicon-inbox"></i>
+  </div>
+  <div class="notification-panel panel panel-default" ng-show="vm.showNotificationPanel">
+    <ul class="list-group" ng-show="!vm.showNoSync">
+      <li class="list-group-item" ng-repeat="(syncName, syncStatus) in vm.synchronizers">
+        <span class="badge" ng-class="{success: syncStatus.status, warning: !syncStatus.status}">
+          <span ng-show="syncStatus.status"><i class="glyphicon glyphicon-ok"></i></span>
+          <span ng-hide="syncStatus.status"><i class="glyphicon glyphicon-time"></i></span>
+        </span>
+        <b>{{syncName}}</b>
+        <br/>
+        <small><i>{{syncStatus.info.last_run | date:'mediumTime'}}</i></small>
+      </li>
+    </ul>
+    <div class="alert alert-info" ng-show="vm.showNoSync">
+      No syncronizers are running.
+    </div>
+  </div>
+</div>
diff --git a/xos/api/utility/synchronizer.py b/xos/api/utility/synchronizer.py
new file mode 100644
index 0000000..84bae00
--- /dev/null
+++ b/xos/api/utility/synchronizer.py
@@ -0,0 +1,61 @@
+from rest_framework.decorators import api_view
+from rest_framework.response import Response
+from rest_framework.reverse import reverse
+from rest_framework import serializers
+from rest_framework import generics
+from rest_framework.exceptions import APIException
+from core.models import *
+from django.forms import widgets
+from core.xoslib.objects.sliceplus import SlicePlus
+from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
+import json
+from core.models import Slice, SlicePrivilege, SliceRole, Instance, Site, Node, User
+from operator import itemgetter, attrgetter
+from api.xosapi_helpers import PlusObjectMixin, PlusModelSerializer
+
+IdField = serializers.ReadOnlyField
+
+
+class SynchronizerSerializer(PlusModelSerializer):
+    id = IdField()
+
+    name = serializers.CharField(required=False)
+
+    class Meta:
+        model = Diag
+        fields = ('id', 'name', 'backend_status', 'backend_register')
+
+
+class SynchronizerList(XOSListCreateAPIView):
+    queryset = Diag.objects.all()
+    serializer_class = SynchronizerSerializer
+
+    method_kind = "list"
+    method_name = "synchronizer"
+
+    def get_queryset(self):
+        name = self.request.query_params.get('name', False)
+
+        if (not self.request.user.is_authenticated()):
+            raise XOSPermissionDenied("You must be authenticated in order to use this API")
+        if(name):
+            return Diag.objects.filter(name=name)
+        return Diag.objects.all()
+
+
+class SynchronizerDetail(XOSRetrieveUpdateDestroyAPIView):
+    queryset = Diag.objects.all()
+    serializer_class = SynchronizerSerializer
+
+    method_kind = "detail"
+    method_name = "synchronizer"
+
+    def get_queryset(self):
+        if (not self.request.user.is_authenticated()):
+            raise XOSPermissionDenied("You must be authenticated in order to use this API")
+
+        print "kwargs"
+        print self.request
+        print self.kwargs['pk']
+
+        return Diag.objects.filter(id=self.kwargs['pk'])
diff --git a/xos/configurations/cord-pod/Makefile b/xos/configurations/cord-pod/Makefile
index 878797c..6d5ddac 100644
--- a/xos/configurations/cord-pod/Makefile
+++ b/xos/configurations/cord-pod/Makefile
@@ -18,6 +18,7 @@
 cord: vsg_custom_images
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/mgmt-net.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/cord-vtn-vsg.yaml
+	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/cord-volt-devices.yaml
 
 exampleservice:
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/pod-exampleservice.yaml
diff --git a/xos/configurations/cord-pod/cord-volt-devices.yaml b/xos/configurations/cord-pod/cord-volt-devices.yaml
new file mode 100644
index 0000000..8b41623
--- /dev/null
+++ b/xos/configurations/cord-pod/cord-volt-devices.yaml
@@ -0,0 +1,47 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Just enough Tosca to get the vSG slice running on the CORD POD
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    service#volt:
+      type: tosca.nodes.VOLTService
+      properties:
+          no-create: True
+          no-delete: True
+          no-update: True
+
+    voltdev-1:
+      type: tosca.nodes.VOLTDevice
+      properties:
+            driver: pmc-olt
+            openflow_id: of:1000000000000001
+            access_devices: >
+              2 222,
+              3 223,
+              4 224
+      requirements:
+          - volt_service:
+              node: service#volt
+              relationship: tosca.relationships.MemberOfService
+          - access_agent:
+              node: agent-1
+              relationship: tosca.relationships.UsesAgent
+
+    agent-1:
+      type: tosca.nodes.AccessAgent
+      properties:
+          mac: AA:BB:CC:DD:EE:FF
+          port_mappings: >
+            of:0000000000000002/2 DE:AD:BE:EF:BA:11,
+            of:0000000000000002/3 BE:EF:DE:AD:BE:EF
+      requirements:
+          - volt_service:
+              node: service#volt
+              relationship: tosca.relationships.MemberOfService
+
+
+
diff --git a/xos/configurations/cord-pod/cord-vtn-vsg.yaml b/xos/configurations/cord-pod/cord-vtn-vsg.yaml
index bb603fe..8c73799 100644
--- a/xos/configurations/cord-pod/cord-vtn-vsg.yaml
+++ b/xos/configurations/cord-pod/cord-vtn-vsg.yaml
@@ -16,7 +16,7 @@
           replaces: service_vtr
 
     service#volt:
-      type: tosca.nodes.Service
+      type: tosca.nodes.VOLTService
       requirements:
           - vsg_tenant:
               node: service#vsg
@@ -75,6 +75,50 @@
           view_url: /admin/fabric/fabricservice/$id$/
           replaces: service_fabric
 
+    service#ONOS_Fabric:
+      type: tosca.nodes.ONOSService
+      requirements:
+      properties:
+          kind: onos
+          view_url: /admin/onos/onosservice/$id$/
+          no_container: true
+          rest_hostname: onos-fabric
+          replaces: service_ONOS_Fabric
+
+    service#ONOS_CORD:
+      type: tosca.nodes.ONOSService
+      properties:
+          no-delete: true
+          no-create: true
+          no-update: true
+
+    vOLT_ONOS_app:
+      type: tosca.nodes.ONOSvOLTApp
+      requirements:
+          - onos_tenant:
+              node: service#ONOS_CORD
+              relationship: tosca.relationships.TenantOfService
+          - volt_service:
+              node: service#volt
+              relationship: tosca.relationships.UsedByService
+      properties:
+          install_dependencies: onos-ext-notifier-1.0-SNAPSHOT.oar, onos-ext-volt-event-publisher-1.0-SNAPSHOT.oar
+          dependencies: org.onosproject.openflow-base, org.onosproject.olt, org.ciena.onos.ext_notifier, org.ciena.onos.volt_event_publisher
+          autogenerate: volt-network-cfg
+
+    vRouter_ONOS_app:
+      type: tosca.nodes.ONOSvRouterApp
+      requirements:
+          - onos_tenant:
+              node: service#ONOS_Fabric
+              relationship: tosca.relationships.TenantOfService
+          - vrouter_service:
+              node: service#vrouter
+              relationship: tosca.relationships.UsedByService
+      properties:
+          dependencies: org.onosproject.vrouter
+          autogenerate: vrouter-network-cfg
+
     Private:
       type: tosca.nodes.NetworkTemplate
 
diff --git a/xos/configurations/devel/Makefile b/xos/configurations/devel/Makefile
index e55f38b..cc29f53 100644
--- a/xos/configurations/devel/Makefile
+++ b/xos/configurations/devel/Makefile
@@ -1,8 +1,8 @@
 MYIP:=$(shell hostname -i)
 
-cloudlab: common_cloudlab xos
+cloudlab: common_cloudlab containers xos
 
-devstack: upgrade_pkgs common_devstack xos
+devstack: upgrade_pkgs common_devstack containers xos
 
 xos:
 	sudo MYIP=$(MYIP) docker-compose up -d
diff --git a/xos/configurations/frontend/Makefile b/xos/configurations/frontend/Makefile
index d3faad0..562578e 100644
--- a/xos/configurations/frontend/Makefile
+++ b/xos/configurations/frontend/Makefile
@@ -29,24 +29,24 @@
 django-restart:
 	sudo docker exec frontend_xos_1 touch /opt/xos/xos/settings.py
 
+clean-config-folder:
+	sudo docker exec frontend_xos_1 rm -f /opt/xos/xos_configuration/xos_mcord_config
+	sudo docker exec frontend_xos_1 rm -f /opt/xos/xos_configuration/xos_cord_config
+
 mock-cord-pod:
-	echo "make sure to add '../vtn/files/xos_vtn_config:/opt/xos/xos_configuration/xos_vtn_config:ro' to volumes section of docker-compose.yml"
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/fixtures.yaml
-	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/mocks/mcord.yaml
-	sudo docker exec frontend_xos_1 cp /opt/xos/configurations/mcord/xos_mcord_config /opt/xos/xos_configuration/
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord-pod/mgmt-net.yaml
 	sudo docker-compose run xos bash -c "echo somekey > /opt/xos/synchronizers/vcpe/vcpe_public_key; python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord-pod/cord-vtn-vsg.yaml"
-	sudo docker exec frontend_xos_1 cp /opt/xos/configurations/cord-pod/xos_cord_config /opt/xos/xos_configuration/
-	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord-pod/mgmt-net.yaml
-	sudo docker-compose run xos bash -c "echo somekey > /opt/xos/synchronizers/vcpe/vcpe_public_key; python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord-pod/cord-vtn-vsg.yaml"
+	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord-pod/cord-volt-devices.yaml
 	sudo docker exec frontend_xos_1 cp /opt/xos/configurations/cord-pod/xos_cord_config /opt/xos/xos_configuration/
 	sudo docker exec frontend_xos_1 touch /opt/xos/xos/settings.py
 
+
+
 mock-mcord:
 	# check this
-	echo "make sure to add '../vtn/files/xos_vtn_config:/opt/xos/xos_configuration/xos_vtn_config:ro' to volumes section of docker-compose.yml"
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/fixtures.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord-pod/mgmt-net.yaml
-	sudo docker-compose run xos bash -c "echo somekey > /opt/xos/synchronizers/vcpe/vcpe_public_key; python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord-pod/cord-vtn-vsg.yaml"
+	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/mocks/mcord.yaml
 	sudo docker exec frontend_xos_1 cp /opt/xos/configurations/mcord/xos_mcord_config /opt/xos/xos_configuration/
 	sudo docker exec frontend_xos_1 touch /opt/xos/xos/settings.py
diff --git a/xos/configurations/test-standalone/Makefile b/xos/configurations/test-standalone/Makefile
index 1542d07..9eafa61 100644
--- a/xos/configurations/test-standalone/Makefile
+++ b/xos/configurations/test-standalone/Makefile
@@ -46,9 +46,12 @@
 	sudo docker-compose run xos bash -c "cd /opt/xos/tosca/tests; python ./alltests.py"
 
 base-container: 
+	cd ../../../containers/xos; make base
+
+devel-container: base-container
 	cd ../../../containers/xos; make devel
 
-containers: base-container
+containers: devel-container
 	cd ../../../containers/xos; make test
 
 stop:
diff --git a/xos/core/admin.py b/xos/core/admin.py
index 6d16fc9..200bb5c 100644
--- a/xos/core/admin.py
+++ b/xos/core/admin.py
@@ -2392,6 +2392,15 @@
     def has_add_permission(self, request):
         return False
 
+class DiagAdmin(XOSBaseAdmin):
+    list_display = ("name", "backend_status", "backend_register")
+    list_display_links = ('name',)
+
+    fieldsets = [
+        (None, {'fields': ['name', 'backend_status', 'backend_register'],
+                'classes':['suit-tab suit-tab-general']}),
+    ]
+
 # Now register the new UserAdmin...
 admin.site.register(User, UserAdmin)
 # ... and, since we're not using Django's builtin permissions,
@@ -2436,3 +2445,4 @@
     admin.site.register(TenantRole, TenantRoleAdmin)
     admin.site.register(TenantAttribute, TenantAttributeAdmin)
     admin.site.register(AddressPool, AddressPoolAdmin)
+    admin.site.register(Diag, DiagAdmin)
diff --git a/xos/core/models/plcorebase.py b/xos/core/models/plcorebase.py
index 6be949d..b84b526 100644
--- a/xos/core/models/plcorebase.py
+++ b/xos/core/models/plcorebase.py
@@ -204,7 +204,7 @@
     policed = models.DateTimeField(null=True, blank=True, default=None)
 
     # This is a scratchpad used by the Observer
-    backend_register = models.CharField(max_length=140,
+    backend_register = models.CharField(max_length=1024,
                                       default="{}", null=True)
 
     backend_status = models.CharField(max_length=1024,
diff --git a/xos/core/static/xosNgLib.css b/xos/core/static/xosNgLib.css
index e6cbaf6..35cb6fa 100644
--- a/xos/core/static/xosNgLib.css
+++ b/xos/core/static/xosNgLib.css
@@ -153,6 +153,9 @@
   margin-top: 15px;
   display: block; }
 
+xos-field {
+  display: block; }
+
 [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
   display: none !important; }
 
@@ -160,4 +163,4 @@
   /* TODO move in xos.scss*/
   margin-top: 15px; }
 
-/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieG9zTmdMaWIuY3NzIiwic291cmNlcyI6WyJtYWluLnNjc3MiLCJhbmltYXRpb25zLnNjc3MiLCIuLi8uLi8uLi8uLi9zdHlsZS9zYXNzL2Jvb3RzdHJhcC9ib290c3RyYXAvX3ZhcmlhYmxlcy5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy90YWJsZS90YWJsZS5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy9hbGVydC9hbGVydC5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy92YWxpZGF0aW9uL3ZhbGlkYXRpb24uc2NzcyIsIi4uL3VpX2NvbXBvbmVudHMvc21hcnRDb21wb25lbnRzL3NtYXJ0VGFibGUvc21hcnRUYWJsZS5zY3NzIl0sInNvdXJjZXNDb250ZW50IjpbIkBpbXBvcnQgJy4vYW5pbWF0aW9ucy5zY3NzJztcbkBpbXBvcnQgJy4uLy4uLy4uLy4uLy4uL3ZpZXdzL3N0eWxlL3Nhc3MvYm9vdHN0cmFwL2Jvb3RzdHJhcC9fdmFyaWFibGVzLnNjc3MnO1xuXG5AaW1wb3J0ICcuLi91aV9jb21wb25lbnRzL2R1bWJDb21wb25lbnRzL3RhYmxlL3RhYmxlLnNjc3MnO1xuQGltcG9ydCAnLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy9hbGVydC9hbGVydC5zY3NzJztcbkBpbXBvcnQgJy4uL3VpX2NvbXBvbmVudHMvZHVtYkNvbXBvbmVudHMvdmFsaWRhdGlvbi92YWxpZGF0aW9uLnNjc3MnO1xuXG5AaW1wb3J0ICcuLi91aV9jb21wb25lbnRzL3NtYXJ0Q29tcG9uZW50cy9zbWFydFRhYmxlL3NtYXJ0VGFibGUuc2Nzcyc7XG5cbltuZ1xcOmNsb2FrXSwgW25nLWNsb2FrXSwgW2RhdGEtbmctY2xvYWtdLCBbeC1uZy1jbG9ha10sIC5uZy1jbG9haywgLngtbmctY2xvYWsge1xuICBkaXNwbGF5OiBub25lICFpbXBvcnRhbnQ7XG59XG5cbi5yb3cgKyAucm93IHtcbiAgLyogVE9ETyBtb3ZlIGluIHhvcy5zY3NzKi8gXG4gIG1hcmdpbi10b3A6ICRmb3JtLWdyb3VwLW1hcmdpbi1ib3R0b207XG59IiwiQGtleWZyYW1lcyBzbGlkZUluUmlnaHQge1xuICBmcm9tIHtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDEwMCUsIDAsIDApO1xuICAgIHZpc2liaWxpdHk6IHZpc2libGU7XG4gIH1cblxuICB0byB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAwLCAwKTtcbiAgfVxufVxuXG5Aa2V5ZnJhbWVzIHNsaWRlT3V0UmlnaHQge1xuICBmcm9tIHtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDAsIDApO1xuICB9XG5cbiAgdG8ge1xuICAgIHZpc2liaWxpdHk6IGhpZGRlbjtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDEwMCUsIDAsIDApO1xuICB9XG59XG5cbkBrZXlmcmFtZXMgZmFkZUluVXAge1xuICBmcm9tIHtcbiAgICBvcGFjaXR5OiAwO1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgMTAwJSwgMCk7XG4gIH1cblxuICB0byB7XG4gICAgb3BhY2l0eTogMTtcbiAgICB0cmFuc2Zvcm06IG5vbmU7XG4gIH1cbn1cblxuQGtleWZyYW1lcyBmYWRlT3V0RG93biB7XG4gIGZyb20ge1xuICAgIG9wYWNpdHk6IDE7XG4gIH1cblxuICB0byB7XG4gICAgb3BhY2l0eTogMDtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDEwMCUsIDApO1xuICB9XG59IiwiJGJvb3RzdHJhcC1zYXNzLWFzc2V0LWhlbHBlcjogZmFsc2UgIWRlZmF1bHQ7XG4vL1xuLy8gVmFyaWFibGVzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cbi8vPT0gQ29sb3JzXG4vL1xuLy8jIyBHcmF5IGFuZCBicmFuZCBjb2xvcnMgZm9yIHVzZSBhY3Jvc3MgQm9vdHN0cmFwLlxuXG4kZ3JheS1iYXNlOiAgICAgICAgICAgICAgIzAwMCAhZGVmYXVsdDtcbiRncmF5LWRhcmtlcjogICAgICAgICAgICBsaWdodGVuKCRncmF5LWJhc2UsIDEzLjUlKSAhZGVmYXVsdDsgLy8gIzIyMlxuJGdyYXktZGFyazogICAgICAgICAgICAgIGxpZ2h0ZW4oJGdyYXktYmFzZSwgMjAlKSAhZGVmYXVsdDsgICAvLyAjMzMzXG4kZ3JheTogICAgICAgICAgICAgICAgICAgbGlnaHRlbigkZ3JheS1iYXNlLCAzMy41JSkgIWRlZmF1bHQ7IC8vICM1NTVcbiRncmF5LWxpZ2h0OiAgICAgICAgICAgICBsaWdodGVuKCRncmF5LWJhc2UsIDQ2LjclKSAhZGVmYXVsdDsgLy8gIzc3N1xuJGdyYXktbGlnaHRlcjogICAgICAgICAgIGxpZ2h0ZW4oJGdyYXktYmFzZSwgOTMuNSUpICFkZWZhdWx0OyAvLyAjZWVlXG5cbiRicmFuZC1wcmltYXJ5OiAgICAgICAgIGRhcmtlbigjNDI4YmNhLCA2LjUlKSAhZGVmYXVsdDsgLy8gIzMzN2FiN1xuJGJyYW5kLXN1Y2Nlc3M6ICAgICAgICAgIzVjYjg1YyAhZGVmYXVsdDtcbiRicmFuZC1pbmZvOiAgICAgICAgICAgICM1YmMwZGUgIWRlZmF1bHQ7XG4kYnJhbmQtd2FybmluZzogICAgICAgICAjZjBhZDRlICFkZWZhdWx0O1xuJGJyYW5kLWRhbmdlcjogICAgICAgICAgI2Q5NTM0ZiAhZGVmYXVsdDtcblxuXG4vLz09IFNjYWZmb2xkaW5nXG4vL1xuLy8jIyBTZXR0aW5ncyBmb3Igc29tZSBvZiB0aGUgbW9zdCBnbG9iYWwgc3R5bGVzLlxuXG4vLyoqIEJhY2tncm91bmQgY29sb3IgZm9yIGA8Ym9keT5gLlxuJGJvZHktYmc6ICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogR2xvYmFsIHRleHQgY29sb3Igb24gYDxib2R5PmAuXG4kdGV4dC1jb2xvcjogICAgICAgICAgICAkZ3JheS1kYXJrICFkZWZhdWx0O1xuXG4vLyoqIEdsb2JhbCB0ZXh0dWFsIGxpbmsgY29sb3IuXG4kbGluay1jb2xvcjogICAgICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcbi8vKiogTGluayBob3ZlciBjb2xvciBzZXQgdmlhIGBkYXJrZW4oKWAgZnVuY3Rpb24uXG4kbGluay1ob3Zlci1jb2xvcjogICAgICBkYXJrZW4oJGxpbmstY29sb3IsIDE1JSkgIWRlZmF1bHQ7XG4vLyoqIExpbmsgaG92ZXIgZGVjb3JhdGlvbi5cbiRsaW5rLWhvdmVyLWRlY29yYXRpb246IHVuZGVybGluZSAhZGVmYXVsdDtcblxuXG4vLz09IFR5cG9ncmFwaHlcbi8vXG4vLyMjIEZvbnQsIGxpbmUtaGVpZ2h0LCBhbmQgY29sb3IgZm9yIGJvZHkgdGV4dCwgaGVhZGluZ3MsIGFuZCBtb3JlLlxuXG4kZm9udC1mYW1pbHktc2Fucy1zZXJpZjogIFwiSGVsdmV0aWNhIE5ldWVcIiwgSGVsdmV0aWNhLCBBcmlhbCwgc2Fucy1zZXJpZiAhZGVmYXVsdDtcbiRmb250LWZhbWlseS1zZXJpZjogICAgICAgR2VvcmdpYSwgXCJUaW1lcyBOZXcgUm9tYW5cIiwgVGltZXMsIHNlcmlmICFkZWZhdWx0O1xuLy8qKiBEZWZhdWx0IG1vbm9zcGFjZSBmb250cyBmb3IgYDxjb2RlPmAsIGA8a2JkPmAsIGFuZCBgPHByZT5gLlxuJGZvbnQtZmFtaWx5LW1vbm9zcGFjZTogICBNZW5sbywgTW9uYWNvLCBDb25zb2xhcywgXCJDb3VyaWVyIE5ld1wiLCBtb25vc3BhY2UgIWRlZmF1bHQ7XG4kZm9udC1mYW1pbHktYmFzZTogICAgICAgICRmb250LWZhbWlseS1zYW5zLXNlcmlmICFkZWZhdWx0O1xuXG4kZm9udC1zaXplLWJhc2U6ICAgICAgICAgIDE0cHggIWRlZmF1bHQ7XG4kZm9udC1zaXplLWxhcmdlOiAgICAgICAgIGNlaWwoKCRmb250LXNpemUtYmFzZSAqIDEuMjUpKSAhZGVmYXVsdDsgLy8gfjE4cHhcbiRmb250LXNpemUtc21hbGw6ICAgICAgICAgY2VpbCgoJGZvbnQtc2l6ZS1iYXNlICogMC44NSkpICFkZWZhdWx0OyAvLyB+MTJweFxuXG4kZm9udC1zaXplLWgxOiAgICAgICAgICAgIGZsb29yKCgkZm9udC1zaXplLWJhc2UgKiAyLjYpKSAhZGVmYXVsdDsgLy8gfjM2cHhcbiRmb250LXNpemUtaDI6ICAgICAgICAgICAgZmxvb3IoKCRmb250LXNpemUtYmFzZSAqIDIuMTUpKSAhZGVmYXVsdDsgLy8gfjMwcHhcbiRmb250LXNpemUtaDM6ICAgICAgICAgICAgY2VpbCgoJGZvbnQtc2l6ZS1iYXNlICogMS43KSkgIWRlZmF1bHQ7IC8vIH4yNHB4XG4kZm9udC1zaXplLWg0OiAgICAgICAgICAgIGNlaWwoKCRmb250LXNpemUtYmFzZSAqIDEuMjUpKSAhZGVmYXVsdDsgLy8gfjE4cHhcbiRmb250LXNpemUtaDU6ICAgICAgICAgICAgJGZvbnQtc2l6ZS1iYXNlICFkZWZhdWx0O1xuJGZvbnQtc2l6ZS1oNjogICAgICAgICAgICBjZWlsKCgkZm9udC1zaXplLWJhc2UgKiAwLjg1KSkgIWRlZmF1bHQ7IC8vIH4xMnB4XG5cbi8vKiogVW5pdC1sZXNzIGBsaW5lLWhlaWdodGAgZm9yIHVzZSBpbiBjb21wb25lbnRzIGxpa2UgYnV0dG9ucy5cbiRsaW5lLWhlaWdodC1iYXNlOiAgICAgICAgMS40Mjg1NzE0MjkgIWRlZmF1bHQ7IC8vIDIwLzE0XG4vLyoqIENvbXB1dGVkIFwibGluZS1oZWlnaHRcIiAoYGZvbnQtc2l6ZWAgKiBgbGluZS1oZWlnaHRgKSBmb3IgdXNlIHdpdGggYG1hcmdpbmAsIGBwYWRkaW5nYCwgZXRjLlxuJGxpbmUtaGVpZ2h0LWNvbXB1dGVkOiAgICBmbG9vcigoJGZvbnQtc2l6ZS1iYXNlICogJGxpbmUtaGVpZ2h0LWJhc2UpKSAhZGVmYXVsdDsgLy8gfjIwcHhcblxuLy8qKiBCeSBkZWZhdWx0LCB0aGlzIGluaGVyaXRzIGZyb20gdGhlIGA8Ym9keT5gLlxuJGhlYWRpbmdzLWZvbnQtZmFtaWx5OiAgICBpbmhlcml0ICFkZWZhdWx0O1xuJGhlYWRpbmdzLWZvbnQtd2VpZ2h0OiAgICA1MDAgIWRlZmF1bHQ7XG4kaGVhZGluZ3MtbGluZS1oZWlnaHQ6ICAgIDEuMSAhZGVmYXVsdDtcbiRoZWFkaW5ncy1jb2xvcjogICAgICAgICAgaW5oZXJpdCAhZGVmYXVsdDtcblxuXG4vLz09IEljb25vZ3JhcGh5XG4vL1xuLy8jIyBTcGVjaWZ5IGN1c3RvbSBsb2NhdGlvbiBhbmQgZmlsZW5hbWUgb2YgdGhlIGluY2x1ZGVkIEdseXBoaWNvbnMgaWNvbiBmb250LiBVc2VmdWwgZm9yIHRob3NlIGluY2x1ZGluZyBCb290c3RyYXAgdmlhIEJvd2VyLlxuXG4vLyoqIExvYWQgZm9udHMgZnJvbSB0aGlzIGRpcmVjdG9yeS5cblxuLy8gW2NvbnZlcnRlcl0gSWYgJGJvb3RzdHJhcC1zYXNzLWFzc2V0LWhlbHBlciBpZiB1c2VkLCBwcm92aWRlIHBhdGggcmVsYXRpdmUgdG8gdGhlIGFzc2V0cyBsb2FkIHBhdGguXG4vLyBbY29udmVydGVyXSBUaGlzIGlzIGJlY2F1c2Ugc29tZSBhc3NldCBoZWxwZXJzLCBzdWNoIGFzIFNwcm9ja2V0cywgZG8gbm90IHdvcmsgd2l0aCBmaWxlLXJlbGF0aXZlIHBhdGhzLlxuJGljb24tZm9udC1wYXRoOiBpZigkYm9vdHN0cmFwLXNhc3MtYXNzZXQtaGVscGVyLCBcImJvb3RzdHJhcC9cIiwgXCIuLi9mb250cy9ib290c3RyYXAvXCIpICFkZWZhdWx0O1xuXG4vLyoqIEZpbGUgbmFtZSBmb3IgYWxsIGZvbnQgZmlsZXMuXG4kaWNvbi1mb250LW5hbWU6ICAgICAgICAgIFwiZ2x5cGhpY29ucy1oYWxmbGluZ3MtcmVndWxhclwiICFkZWZhdWx0O1xuLy8qKiBFbGVtZW50IElEIHdpdGhpbiBTVkcgaWNvbiBmaWxlLlxuJGljb24tZm9udC1zdmctaWQ6ICAgICAgICBcImdseXBoaWNvbnNfaGFsZmxpbmdzcmVndWxhclwiICFkZWZhdWx0O1xuXG5cbi8vPT0gQ29tcG9uZW50c1xuLy9cbi8vIyMgRGVmaW5lIGNvbW1vbiBwYWRkaW5nIGFuZCBib3JkZXIgcmFkaXVzIHNpemVzIGFuZCBtb3JlLiBWYWx1ZXMgYmFzZWQgb24gMTRweCB0ZXh0IGFuZCAxLjQyOCBsaW5lLWhlaWdodCAofjIwcHggdG8gc3RhcnQpLlxuXG4kcGFkZGluZy1iYXNlLXZlcnRpY2FsOiAgICAgNnB4ICFkZWZhdWx0O1xuJHBhZGRpbmctYmFzZS1ob3Jpem9udGFsOiAgIDEycHggIWRlZmF1bHQ7XG5cbiRwYWRkaW5nLWxhcmdlLXZlcnRpY2FsOiAgICAxMHB4ICFkZWZhdWx0O1xuJHBhZGRpbmctbGFyZ2UtaG9yaXpvbnRhbDogIDE2cHggIWRlZmF1bHQ7XG5cbiRwYWRkaW5nLXNtYWxsLXZlcnRpY2FsOiAgICA1cHggIWRlZmF1bHQ7XG4kcGFkZGluZy1zbWFsbC1ob3Jpem9udGFsOiAgMTBweCAhZGVmYXVsdDtcblxuJHBhZGRpbmcteHMtdmVydGljYWw6ICAgICAgIDFweCAhZGVmYXVsdDtcbiRwYWRkaW5nLXhzLWhvcml6b250YWw6ICAgICA1cHggIWRlZmF1bHQ7XG5cbiRsaW5lLWhlaWdodC1sYXJnZTogICAgICAgICAxLjMzMzMzMzMgIWRlZmF1bHQ7IC8vIGV4dHJhIGRlY2ltYWxzIGZvciBXaW4gOC4xIENocm9tZVxuJGxpbmUtaGVpZ2h0LXNtYWxsOiAgICAgICAgIDEuNSAhZGVmYXVsdDtcblxuJGJvcmRlci1yYWRpdXMtYmFzZTogICAgICAgIDRweCAhZGVmYXVsdDtcbiRib3JkZXItcmFkaXVzLWxhcmdlOiAgICAgICA2cHggIWRlZmF1bHQ7XG4kYm9yZGVyLXJhZGl1cy1zbWFsbDogICAgICAgM3B4ICFkZWZhdWx0O1xuXG4vLyoqIEdsb2JhbCBjb2xvciBmb3IgYWN0aXZlIGl0ZW1zIChlLmcuLCBuYXZzIG9yIGRyb3Bkb3ducykuXG4kY29tcG9uZW50LWFjdGl2ZS1jb2xvcjogICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogR2xvYmFsIGJhY2tncm91bmQgY29sb3IgZm9yIGFjdGl2ZSBpdGVtcyAoZS5nLiwgbmF2cyBvciBkcm9wZG93bnMpLlxuJGNvbXBvbmVudC1hY3RpdmUtYmc6ICAgICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuXG4vLyoqIFdpZHRoIG9mIHRoZSBgYm9yZGVyYCBmb3IgZ2VuZXJhdGluZyBjYXJldHMgdGhhdCBpbmRpY2F0b3IgZHJvcGRvd25zLlxuJGNhcmV0LXdpZHRoLWJhc2U6ICAgICAgICAgIDRweCAhZGVmYXVsdDtcbi8vKiogQ2FyZXRzIGluY3JlYXNlIHNsaWdodGx5IGluIHNpemUgZm9yIGxhcmdlciBjb21wb25lbnRzLlxuJGNhcmV0LXdpZHRoLWxhcmdlOiAgICAgICAgIDVweCAhZGVmYXVsdDtcblxuXG4vLz09IFRhYmxlc1xuLy9cbi8vIyMgQ3VzdG9taXplcyB0aGUgYC50YWJsZWAgY29tcG9uZW50IHdpdGggYmFzaWMgdmFsdWVzLCBlYWNoIHVzZWQgYWNyb3NzIGFsbCB0YWJsZSB2YXJpYXRpb25zLlxuXG4vLyoqIFBhZGRpbmcgZm9yIGA8dGg+YHMgYW5kIGA8dGQ+YHMuXG4kdGFibGUtY2VsbC1wYWRkaW5nOiAgICAgICAgICAgIDhweCAhZGVmYXVsdDtcbi8vKiogUGFkZGluZyBmb3IgY2VsbHMgaW4gYC50YWJsZS1jb25kZW5zZWRgLlxuJHRhYmxlLWNvbmRlbnNlZC1jZWxsLXBhZGRpbmc6ICA1cHggIWRlZmF1bHQ7XG5cbi8vKiogRGVmYXVsdCBiYWNrZ3JvdW5kIGNvbG9yIHVzZWQgZm9yIGFsbCB0YWJsZXMuXG4kdGFibGUtYmc6ICAgICAgICAgICAgICAgICAgICAgIHRyYW5zcGFyZW50ICFkZWZhdWx0O1xuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIHVzZWQgZm9yIGAudGFibGUtc3RyaXBlZGAuXG4kdGFibGUtYmctYWNjZW50OiAgICAgICAgICAgICAgICNmOWY5ZjkgIWRlZmF1bHQ7XG4vLyoqIEJhY2tncm91bmQgY29sb3IgdXNlZCBmb3IgYC50YWJsZS1ob3ZlcmAuXG4kdGFibGUtYmctaG92ZXI6ICAgICAgICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG4kdGFibGUtYmctYWN0aXZlOiAgICAgICAgICAgICAgICR0YWJsZS1iZy1ob3ZlciAhZGVmYXVsdDtcblxuLy8qKiBCb3JkZXIgY29sb3IgZm9yIHRhYmxlIGFuZCBjZWxsIGJvcmRlcnMuXG4kdGFibGUtYm9yZGVyLWNvbG9yOiAgICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG5cblxuLy89PSBCdXR0b25zXG4vL1xuLy8jIyBGb3IgZWFjaCBvZiBCb290c3RyYXAncyBidXR0b25zLCBkZWZpbmUgdGV4dCwgYmFja2dyb3VuZCBhbmQgYm9yZGVyIGNvbG9yLlxuXG4kYnRuLWZvbnQtd2VpZ2h0OiAgICAgICAgICAgICAgICBub3JtYWwgIWRlZmF1bHQ7XG5cbiRidG4tZGVmYXVsdC1jb2xvcjogICAgICAgICAgICAgICMzMzMgIWRlZmF1bHQ7XG4kYnRuLWRlZmF1bHQtYmc6ICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGJ0bi1kZWZhdWx0LWJvcmRlcjogICAgICAgICAgICAgI2NjYyAhZGVmYXVsdDtcblxuJGJ0bi1wcmltYXJ5LWNvbG9yOiAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRidG4tcHJpbWFyeS1iZzogICAgICAgICAgICAgICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuJGJ0bi1wcmltYXJ5LWJvcmRlcjogICAgICAgICAgICAgZGFya2VuKCRidG4tcHJpbWFyeS1iZywgNSUpICFkZWZhdWx0O1xuXG4kYnRuLXN1Y2Nlc3MtY29sb3I6ICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGJ0bi1zdWNjZXNzLWJnOiAgICAgICAgICAgICAgICAgJGJyYW5kLXN1Y2Nlc3MgIWRlZmF1bHQ7XG4kYnRuLXN1Y2Nlc3MtYm9yZGVyOiAgICAgICAgICAgICBkYXJrZW4oJGJ0bi1zdWNjZXNzLWJnLCA1JSkgIWRlZmF1bHQ7XG5cbiRidG4taW5mby1jb2xvcjogICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kYnRuLWluZm8tYmc6ICAgICAgICAgICAgICAgICAgICAkYnJhbmQtaW5mbyAhZGVmYXVsdDtcbiRidG4taW5mby1ib3JkZXI6ICAgICAgICAgICAgICAgIGRhcmtlbigkYnRuLWluZm8tYmcsIDUlKSAhZGVmYXVsdDtcblxuJGJ0bi13YXJuaW5nLWNvbG9yOiAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRidG4td2FybmluZy1iZzogICAgICAgICAgICAgICAgICRicmFuZC13YXJuaW5nICFkZWZhdWx0O1xuJGJ0bi13YXJuaW5nLWJvcmRlcjogICAgICAgICAgICAgZGFya2VuKCRidG4td2FybmluZy1iZywgNSUpICFkZWZhdWx0O1xuXG4kYnRuLWRhbmdlci1jb2xvcjogICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGJ0bi1kYW5nZXItYmc6ICAgICAgICAgICAgICAgICAgJGJyYW5kLWRhbmdlciAhZGVmYXVsdDtcbiRidG4tZGFuZ2VyLWJvcmRlcjogICAgICAgICAgICAgIGRhcmtlbigkYnRuLWRhbmdlci1iZywgNSUpICFkZWZhdWx0O1xuXG4kYnRuLWxpbmstZGlzYWJsZWQtY29sb3I6ICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcblxuLy8gQWxsb3dzIGZvciBjdXN0b21pemluZyBidXR0b24gcmFkaXVzIGluZGVwZW5kZW50bHkgZnJvbSBnbG9iYWwgYm9yZGVyIHJhZGl1c1xuJGJ0bi1ib3JkZXItcmFkaXVzLWJhc2U6ICAgICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcbiRidG4tYm9yZGVyLXJhZGl1cy1sYXJnZTogICAgICAgICRib3JkZXItcmFkaXVzLWxhcmdlICFkZWZhdWx0O1xuJGJ0bi1ib3JkZXItcmFkaXVzLXNtYWxsOiAgICAgICAgJGJvcmRlci1yYWRpdXMtc21hbGwgIWRlZmF1bHQ7XG5cblxuLy89PSBGb3Jtc1xuLy9cbi8vIyNcblxuLy8qKiBgPGlucHV0PmAgYmFja2dyb3VuZCBjb2xvclxuJGlucHV0LWJnOiAgICAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogYDxpbnB1dCBkaXNhYmxlZD5gIGJhY2tncm91bmQgY29sb3JcbiRpbnB1dC1iZy1kaXNhYmxlZDogICAgICAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG5cbi8vKiogVGV4dCBjb2xvciBmb3IgYDxpbnB1dD5gc1xuJGlucHV0LWNvbG9yOiAgICAgICAgICAgICAgICAgICAgJGdyYXkgIWRlZmF1bHQ7XG4vLyoqIGA8aW5wdXQ+YCBib3JkZXIgY29sb3JcbiRpbnB1dC1ib3JkZXI6ICAgICAgICAgICAgICAgICAgICNjY2MgIWRlZmF1bHQ7XG5cbi8vIFRPRE86IFJlbmFtZSBgJGlucHV0LWJvcmRlci1yYWRpdXNgIHRvIGAkaW5wdXQtYm9yZGVyLXJhZGl1cy1iYXNlYCBpbiB2NFxuLy8qKiBEZWZhdWx0IGAuZm9ybS1jb250cm9sYCBib3JkZXIgcmFkaXVzXG4vLyBUaGlzIGhhcyBubyBlZmZlY3Qgb24gYDxzZWxlY3Q+YHMgaW4gc29tZSBicm93c2VycywgZHVlIHRvIHRoZSBsaW1pdGVkIHN0eWxhYmlsaXR5IG9mIGA8c2VsZWN0PmBzIGluIENTUy5cbiRpbnB1dC1ib3JkZXItcmFkaXVzOiAgICAgICAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG4vLyoqIExhcmdlIGAuZm9ybS1jb250cm9sYCBib3JkZXIgcmFkaXVzXG4kaW5wdXQtYm9yZGVyLXJhZGl1cy1sYXJnZTogICAgICAkYm9yZGVyLXJhZGl1cy1sYXJnZSAhZGVmYXVsdDtcbi8vKiogU21hbGwgYC5mb3JtLWNvbnRyb2xgIGJvcmRlciByYWRpdXNcbiRpbnB1dC1ib3JkZXItcmFkaXVzLXNtYWxsOiAgICAgICRib3JkZXItcmFkaXVzLXNtYWxsICFkZWZhdWx0O1xuXG4vLyoqIEJvcmRlciBjb2xvciBmb3IgaW5wdXRzIG9uIGZvY3VzXG4kaW5wdXQtYm9yZGVyLWZvY3VzOiAgICAgICAgICAgICAjNjZhZmU5ICFkZWZhdWx0O1xuXG4vLyoqIFBsYWNlaG9sZGVyIHRleHQgY29sb3JcbiRpbnB1dC1jb2xvci1wbGFjZWhvbGRlcjogICAgICAgICM5OTkgIWRlZmF1bHQ7XG5cbi8vKiogRGVmYXVsdCBgLmZvcm0tY29udHJvbGAgaGVpZ2h0XG4kaW5wdXQtaGVpZ2h0LWJhc2U6ICAgICAgICAgICAgICAoJGxpbmUtaGVpZ2h0LWNvbXB1dGVkICsgKCRwYWRkaW5nLWJhc2UtdmVydGljYWwgKiAyKSArIDIpICFkZWZhdWx0O1xuLy8qKiBMYXJnZSBgLmZvcm0tY29udHJvbGAgaGVpZ2h0XG4kaW5wdXQtaGVpZ2h0LWxhcmdlOiAgICAgICAgICAgICAoY2VpbCgkZm9udC1zaXplLWxhcmdlICogJGxpbmUtaGVpZ2h0LWxhcmdlKSArICgkcGFkZGluZy1sYXJnZS12ZXJ0aWNhbCAqIDIpICsgMikgIWRlZmF1bHQ7XG4vLyoqIFNtYWxsIGAuZm9ybS1jb250cm9sYCBoZWlnaHRcbiRpbnB1dC1oZWlnaHQtc21hbGw6ICAgICAgICAgICAgIChmbG9vcigkZm9udC1zaXplLXNtYWxsICogJGxpbmUtaGVpZ2h0LXNtYWxsKSArICgkcGFkZGluZy1zbWFsbC12ZXJ0aWNhbCAqIDIpICsgMikgIWRlZmF1bHQ7XG5cbi8vKiogYC5mb3JtLWdyb3VwYCBtYXJnaW5cbiRmb3JtLWdyb3VwLW1hcmdpbi1ib3R0b206ICAgICAgIDE1cHggIWRlZmF1bHQ7XG5cbiRsZWdlbmQtY29sb3I6ICAgICAgICAgICAgICAgICAgICRncmF5LWRhcmsgIWRlZmF1bHQ7XG4kbGVnZW5kLWJvcmRlci1jb2xvcjogICAgICAgICAgICAjZTVlNWU1ICFkZWZhdWx0O1xuXG4vLyoqIEJhY2tncm91bmQgY29sb3IgZm9yIHRleHR1YWwgaW5wdXQgYWRkb25zXG4kaW5wdXQtZ3JvdXAtYWRkb24tYmc6ICAgICAgICAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuLy8qKiBCb3JkZXIgY29sb3IgZm9yIHRleHR1YWwgaW5wdXQgYWRkb25zXG4kaW5wdXQtZ3JvdXAtYWRkb24tYm9yZGVyLWNvbG9yOiAkaW5wdXQtYm9yZGVyICFkZWZhdWx0O1xuXG4vLyoqIERpc2FibGVkIGN1cnNvciBmb3IgZm9ybSBjb250cm9scyBhbmQgYnV0dG9ucy5cbiRjdXJzb3ItZGlzYWJsZWQ6ICAgICAgICAgICAgICAgIG5vdC1hbGxvd2VkICFkZWZhdWx0O1xuXG5cbi8vPT0gRHJvcGRvd25zXG4vL1xuLy8jIyBEcm9wZG93biBtZW51IGNvbnRhaW5lciBhbmQgY29udGVudHMuXG5cbi8vKiogQmFja2dyb3VuZCBmb3IgdGhlIGRyb3Bkb3duIG1lbnUuXG4kZHJvcGRvd24tYmc6ICAgICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBEcm9wZG93biBtZW51IGBib3JkZXItY29sb3JgLlxuJGRyb3Bkb3duLWJvcmRlcjogICAgICAgICAgICAgICAgcmdiYSgwLDAsMCwuMTUpICFkZWZhdWx0O1xuLy8qKiBEcm9wZG93biBtZW51IGBib3JkZXItY29sb3JgICoqZm9yIElFOCoqLlxuJGRyb3Bkb3duLWZhbGxiYWNrLWJvcmRlcjogICAgICAgI2NjYyAhZGVmYXVsdDtcbi8vKiogRGl2aWRlciBjb2xvciBmb3IgYmV0d2VlbiBkcm9wZG93biBpdGVtcy5cbiRkcm9wZG93bi1kaXZpZGVyLWJnOiAgICAgICAgICAgICNlNWU1ZTUgIWRlZmF1bHQ7XG5cbi8vKiogRHJvcGRvd24gbGluayB0ZXh0IGNvbG9yLlxuJGRyb3Bkb3duLWxpbmstY29sb3I6ICAgICAgICAgICAgJGdyYXktZGFyayAhZGVmYXVsdDtcbi8vKiogSG92ZXIgY29sb3IgZm9yIGRyb3Bkb3duIGxpbmtzLlxuJGRyb3Bkb3duLWxpbmstaG92ZXItY29sb3I6ICAgICAgZGFya2VuKCRncmF5LWRhcmssIDUlKSAhZGVmYXVsdDtcbi8vKiogSG92ZXIgYmFja2dyb3VuZCBmb3IgZHJvcGRvd24gbGlua3MuXG4kZHJvcGRvd24tbGluay1ob3Zlci1iZzogICAgICAgICAjZjVmNWY1ICFkZWZhdWx0O1xuXG4vLyoqIEFjdGl2ZSBkcm9wZG93biBtZW51IGl0ZW0gdGV4dCBjb2xvci5cbiRkcm9wZG93bi1saW5rLWFjdGl2ZS1jb2xvcjogICAgICRjb21wb25lbnQtYWN0aXZlLWNvbG9yICFkZWZhdWx0O1xuLy8qKiBBY3RpdmUgZHJvcGRvd24gbWVudSBpdGVtIGJhY2tncm91bmQgY29sb3IuXG4kZHJvcGRvd24tbGluay1hY3RpdmUtYmc6ICAgICAgICAkY29tcG9uZW50LWFjdGl2ZS1iZyAhZGVmYXVsdDtcblxuLy8qKiBEaXNhYmxlZCBkcm9wZG93biBtZW51IGl0ZW0gYmFja2dyb3VuZCBjb2xvci5cbiRkcm9wZG93bi1saW5rLWRpc2FibGVkLWNvbG9yOiAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuXG4vLyoqIFRleHQgY29sb3IgZm9yIGhlYWRlcnMgd2l0aGluIGRyb3Bkb3duIG1lbnVzLlxuJGRyb3Bkb3duLWhlYWRlci1jb2xvcjogICAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG5cbi8vKiogRGVwcmVjYXRlZCBgJGRyb3Bkb3duLWNhcmV0LWNvbG9yYCBhcyBvZiB2My4xLjBcbiRkcm9wZG93bi1jYXJldC1jb2xvcjogICAgICAgICAgICMwMDAgIWRlZmF1bHQ7XG5cblxuLy8tLSBaLWluZGV4IG1hc3RlciBsaXN0XG4vL1xuLy8gV2FybmluZzogQXZvaWQgY3VzdG9taXppbmcgdGhlc2UgdmFsdWVzLiBUaGV5J3JlIHVzZWQgZm9yIGEgYmlyZCdzIGV5ZSB2aWV3XG4vLyBvZiBjb21wb25lbnRzIGRlcGVuZGVudCBvbiB0aGUgei1heGlzIGFuZCBhcmUgZGVzaWduZWQgdG8gYWxsIHdvcmsgdG9nZXRoZXIuXG4vL1xuLy8gTm90ZTogVGhlc2UgdmFyaWFibGVzIGFyZSBub3QgZ2VuZXJhdGVkIGludG8gdGhlIEN1c3RvbWl6ZXIuXG5cbiR6aW5kZXgtbmF2YmFyOiAgICAgICAgICAgIDEwMDAgIWRlZmF1bHQ7XG4kemluZGV4LWRyb3Bkb3duOiAgICAgICAgICAxMDAwICFkZWZhdWx0O1xuJHppbmRleC1wb3BvdmVyOiAgICAgICAgICAgMTA2MCAhZGVmYXVsdDtcbiR6aW5kZXgtdG9vbHRpcDogICAgICAgICAgIDEwNzAgIWRlZmF1bHQ7XG4kemluZGV4LW5hdmJhci1maXhlZDogICAgICAxMDMwICFkZWZhdWx0O1xuJHppbmRleC1tb2RhbC1iYWNrZ3JvdW5kOiAgMTA0MCAhZGVmYXVsdDtcbiR6aW5kZXgtbW9kYWw6ICAgICAgICAgICAgIDEwNTAgIWRlZmF1bHQ7XG5cblxuLy89PSBNZWRpYSBxdWVyaWVzIGJyZWFrcG9pbnRzXG4vL1xuLy8jIyBEZWZpbmUgdGhlIGJyZWFrcG9pbnRzIGF0IHdoaWNoIHlvdXIgbGF5b3V0IHdpbGwgY2hhbmdlLCBhZGFwdGluZyB0byBkaWZmZXJlbnQgc2NyZWVuIHNpemVzLlxuXG4vLyBFeHRyYSBzbWFsbCBzY3JlZW4gLyBwaG9uZVxuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLXhzYCBhcyBvZiB2My4wLjFcbiRzY3JlZW4teHM6ICAgICAgICAgICAgICAgICAgNDgwcHggIWRlZmF1bHQ7XG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4teHMtbWluYCBhcyBvZiB2My4yLjBcbiRzY3JlZW4teHMtbWluOiAgICAgICAgICAgICAgJHNjcmVlbi14cyAhZGVmYXVsdDtcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi1waG9uZWAgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLXBob25lOiAgICAgICAgICAgICAgICRzY3JlZW4teHMtbWluICFkZWZhdWx0O1xuXG4vLyBTbWFsbCBzY3JlZW4gLyB0YWJsZXRcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi1zbWAgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLXNtOiAgICAgICAgICAgICAgICAgIDc2OHB4ICFkZWZhdWx0O1xuJHNjcmVlbi1zbS1taW46ICAgICAgICAgICAgICAkc2NyZWVuLXNtICFkZWZhdWx0O1xuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLXRhYmxldGAgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLXRhYmxldDogICAgICAgICAgICAgICRzY3JlZW4tc20tbWluICFkZWZhdWx0O1xuXG4vLyBNZWRpdW0gc2NyZWVuIC8gZGVza3RvcFxuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLW1kYCBhcyBvZiB2My4wLjFcbiRzY3JlZW4tbWQ6ICAgICAgICAgICAgICAgICAgOTkycHggIWRlZmF1bHQ7XG4kc2NyZWVuLW1kLW1pbjogICAgICAgICAgICAgICRzY3JlZW4tbWQgIWRlZmF1bHQ7XG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4tZGVza3RvcGAgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLWRlc2t0b3A6ICAgICAgICAgICAgICRzY3JlZW4tbWQtbWluICFkZWZhdWx0O1xuXG4vLyBMYXJnZSBzY3JlZW4gLyB3aWRlIGRlc2t0b3Bcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi1sZ2AgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLWxnOiAgICAgICAgICAgICAgICAgIDEyMDBweCAhZGVmYXVsdDtcbiRzY3JlZW4tbGctbWluOiAgICAgICAgICAgICAgJHNjcmVlbi1sZyAhZGVmYXVsdDtcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi1sZy1kZXNrdG9wYCBhcyBvZiB2My4wLjFcbiRzY3JlZW4tbGctZGVza3RvcDogICAgICAgICAgJHNjcmVlbi1sZy1taW4gIWRlZmF1bHQ7XG5cbi8vIFNvIG1lZGlhIHF1ZXJpZXMgZG9uJ3Qgb3ZlcmxhcCB3aGVuIHJlcXVpcmVkLCBwcm92aWRlIGEgbWF4aW11bVxuJHNjcmVlbi14cy1tYXg6ICAgICAgICAgICAgICAoJHNjcmVlbi1zbS1taW4gLSAxKSAhZGVmYXVsdDtcbiRzY3JlZW4tc20tbWF4OiAgICAgICAgICAgICAgKCRzY3JlZW4tbWQtbWluIC0gMSkgIWRlZmF1bHQ7XG4kc2NyZWVuLW1kLW1heDogICAgICAgICAgICAgICgkc2NyZWVuLWxnLW1pbiAtIDEpICFkZWZhdWx0O1xuXG5cbi8vPT0gR3JpZCBzeXN0ZW1cbi8vXG4vLyMjIERlZmluZSB5b3VyIGN1c3RvbSByZXNwb25zaXZlIGdyaWQuXG5cbi8vKiogTnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhlIGdyaWQuXG4kZ3JpZC1jb2x1bW5zOiAgICAgICAgICAgICAgMTIgIWRlZmF1bHQ7XG4vLyoqIFBhZGRpbmcgYmV0d2VlbiBjb2x1bW5zLiBHZXRzIGRpdmlkZWQgaW4gaGFsZiBmb3IgdGhlIGxlZnQgYW5kIHJpZ2h0LlxuJGdyaWQtZ3V0dGVyLXdpZHRoOiAgICAgICAgIDMwcHggIWRlZmF1bHQ7XG4vLyBOYXZiYXIgY29sbGFwc2Vcbi8vKiogUG9pbnQgYXQgd2hpY2ggdGhlIG5hdmJhciBiZWNvbWVzIHVuY29sbGFwc2VkLlxuJGdyaWQtZmxvYXQtYnJlYWtwb2ludDogICAgICRzY3JlZW4tc20tbWluICFkZWZhdWx0O1xuLy8qKiBQb2ludCBhdCB3aGljaCB0aGUgbmF2YmFyIGJlZ2lucyBjb2xsYXBzaW5nLlxuJGdyaWQtZmxvYXQtYnJlYWtwb2ludC1tYXg6ICgkZ3JpZC1mbG9hdC1icmVha3BvaW50IC0gMSkgIWRlZmF1bHQ7XG5cblxuLy89PSBDb250YWluZXIgc2l6ZXNcbi8vXG4vLyMjIERlZmluZSB0aGUgbWF4aW11bSB3aWR0aCBvZiBgLmNvbnRhaW5lcmAgZm9yIGRpZmZlcmVudCBzY3JlZW4gc2l6ZXMuXG5cbi8vIFNtYWxsIHNjcmVlbiAvIHRhYmxldFxuJGNvbnRhaW5lci10YWJsZXQ6ICAgICAgICAgICAgICg3MjBweCArICRncmlkLWd1dHRlci13aWR0aCkgIWRlZmF1bHQ7XG4vLyoqIEZvciBgJHNjcmVlbi1zbS1taW5gIGFuZCB1cC5cbiRjb250YWluZXItc206ICAgICAgICAgICAgICAgICAkY29udGFpbmVyLXRhYmxldCAhZGVmYXVsdDtcblxuLy8gTWVkaXVtIHNjcmVlbiAvIGRlc2t0b3BcbiRjb250YWluZXItZGVza3RvcDogICAgICAgICAgICAoOTQwcHggKyAkZ3JpZC1ndXR0ZXItd2lkdGgpICFkZWZhdWx0O1xuLy8qKiBGb3IgYCRzY3JlZW4tbWQtbWluYCBhbmQgdXAuXG4kY29udGFpbmVyLW1kOiAgICAgICAgICAgICAgICAgJGNvbnRhaW5lci1kZXNrdG9wICFkZWZhdWx0O1xuXG4vLyBMYXJnZSBzY3JlZW4gLyB3aWRlIGRlc2t0b3BcbiRjb250YWluZXItbGFyZ2UtZGVza3RvcDogICAgICAoMTE0MHB4ICsgJGdyaWQtZ3V0dGVyLXdpZHRoKSAhZGVmYXVsdDtcbi8vKiogRm9yIGAkc2NyZWVuLWxnLW1pbmAgYW5kIHVwLlxuJGNvbnRhaW5lci1sZzogICAgICAgICAgICAgICAgICRjb250YWluZXItbGFyZ2UtZGVza3RvcCAhZGVmYXVsdDtcblxuXG4vLz09IE5hdmJhclxuLy9cbi8vIyNcblxuLy8gQmFzaWNzIG9mIGEgbmF2YmFyXG4kbmF2YmFyLWhlaWdodDogICAgICAgICAgICAgICAgICAgIDUwcHggIWRlZmF1bHQ7XG4kbmF2YmFyLW1hcmdpbi1ib3R0b206ICAgICAgICAgICAgICRsaW5lLWhlaWdodC1jb21wdXRlZCAhZGVmYXVsdDtcbiRuYXZiYXItYm9yZGVyLXJhZGl1czogICAgICAgICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcbiRuYXZiYXItcGFkZGluZy1ob3Jpem9udGFsOiAgICAgICAgZmxvb3IoKCRncmlkLWd1dHRlci13aWR0aCAvIDIpKSAhZGVmYXVsdDtcbiRuYXZiYXItcGFkZGluZy12ZXJ0aWNhbDogICAgICAgICAgKCgkbmF2YmFyLWhlaWdodCAtICRsaW5lLWhlaWdodC1jb21wdXRlZCkgLyAyKSAhZGVmYXVsdDtcbiRuYXZiYXItY29sbGFwc2UtbWF4LWhlaWdodDogICAgICAgMzQwcHggIWRlZmF1bHQ7XG5cbiRuYXZiYXItZGVmYXVsdC1jb2xvcjogICAgICAgICAgICAgIzc3NyAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1iZzogICAgICAgICAgICAgICAgI2Y4ZjhmOCAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1ib3JkZXI6ICAgICAgICAgICAgZGFya2VuKCRuYXZiYXItZGVmYXVsdC1iZywgNi41JSkgIWRlZmF1bHQ7XG5cbi8vIE5hdmJhciBsaW5rc1xuJG5hdmJhci1kZWZhdWx0LWxpbmstY29sb3I6ICAgICAgICAgICAgICAgICM3NzcgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtbGluay1ob3Zlci1jb2xvcjogICAgICAgICAgIzMzMyAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1saW5rLWhvdmVyLWJnOiAgICAgICAgICAgICB0cmFuc3BhcmVudCAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1saW5rLWFjdGl2ZS1jb2xvcjogICAgICAgICAjNTU1ICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWxpbmstYWN0aXZlLWJnOiAgICAgICAgICAgIGRhcmtlbigkbmF2YmFyLWRlZmF1bHQtYmcsIDYuNSUpICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWxpbmstZGlzYWJsZWQtY29sb3I6ICAgICAgICNjY2MgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtbGluay1kaXNhYmxlZC1iZzogICAgICAgICAgdHJhbnNwYXJlbnQgIWRlZmF1bHQ7XG5cbi8vIE5hdmJhciBicmFuZCBsYWJlbFxuJG5hdmJhci1kZWZhdWx0LWJyYW5kLWNvbG9yOiAgICAgICAgICAgICAgICRuYXZiYXItZGVmYXVsdC1saW5rLWNvbG9yICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWJyYW5kLWhvdmVyLWNvbG9yOiAgICAgICAgIGRhcmtlbigkbmF2YmFyLWRlZmF1bHQtYnJhbmQtY29sb3IsIDEwJSkgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtYnJhbmQtaG92ZXItYmc6ICAgICAgICAgICAgdHJhbnNwYXJlbnQgIWRlZmF1bHQ7XG5cbi8vIE5hdmJhciB0b2dnbGVcbiRuYXZiYXItZGVmYXVsdC10b2dnbGUtaG92ZXItYmc6ICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LXRvZ2dsZS1pY29uLWJhci1iZzogICAgICAgICM4ODggIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtdG9nZ2xlLWJvcmRlci1jb2xvcjogICAgICAgI2RkZCAhZGVmYXVsdDtcblxuXG4vLz09PSBJbnZlcnRlZCBuYXZiYXJcbi8vIFJlc2V0IGludmVydGVkIG5hdmJhciBiYXNpY3NcbiRuYXZiYXItaW52ZXJzZS1jb2xvcjogICAgICAgICAgICAgICAgICAgICAgbGlnaHRlbigkZ3JheS1saWdodCwgMTUlKSAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1iZzogICAgICAgICAgICAgICAgICAgICAgICAgIzIyMiAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1ib3JkZXI6ICAgICAgICAgICAgICAgICAgICAgZGFya2VuKCRuYXZiYXItaW52ZXJzZS1iZywgMTAlKSAhZGVmYXVsdDtcblxuLy8gSW52ZXJ0ZWQgbmF2YmFyIGxpbmtzXG4kbmF2YmFyLWludmVyc2UtbGluay1jb2xvcjogICAgICAgICAgICAgICAgIGxpZ2h0ZW4oJGdyYXktbGlnaHQsIDE1JSkgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtbGluay1ob3Zlci1jb2xvcjogICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtbGluay1ob3Zlci1iZzogICAgICAgICAgICAgIHRyYW5zcGFyZW50ICFkZWZhdWx0O1xuJG5hdmJhci1pbnZlcnNlLWxpbmstYWN0aXZlLWNvbG9yOiAgICAgICAgICAkbmF2YmFyLWludmVyc2UtbGluay1ob3Zlci1jb2xvciAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1saW5rLWFjdGl2ZS1iZzogICAgICAgICAgICAgZGFya2VuKCRuYXZiYXItaW52ZXJzZS1iZywgMTAlKSAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1saW5rLWRpc2FibGVkLWNvbG9yOiAgICAgICAgIzQ0NCAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1saW5rLWRpc2FibGVkLWJnOiAgICAgICAgICAgdHJhbnNwYXJlbnQgIWRlZmF1bHQ7XG5cbi8vIEludmVydGVkIG5hdmJhciBicmFuZCBsYWJlbFxuJG5hdmJhci1pbnZlcnNlLWJyYW5kLWNvbG9yOiAgICAgICAgICAgICAgICAkbmF2YmFyLWludmVyc2UtbGluay1jb2xvciAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1icmFuZC1ob3Zlci1jb2xvcjogICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1icmFuZC1ob3Zlci1iZzogICAgICAgICAgICAgdHJhbnNwYXJlbnQgIWRlZmF1bHQ7XG5cbi8vIEludmVydGVkIG5hdmJhciB0b2dnbGVcbiRuYXZiYXItaW52ZXJzZS10b2dnbGUtaG92ZXItYmc6ICAgICAgICAgICAgIzMzMyAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS10b2dnbGUtaWNvbi1iYXItYmc6ICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS10b2dnbGUtYm9yZGVyLWNvbG9yOiAgICAgICAgIzMzMyAhZGVmYXVsdDtcblxuXG4vLz09IE5hdnNcbi8vXG4vLyMjXG5cbi8vPT09IFNoYXJlZCBuYXYgc3R5bGVzXG4kbmF2LWxpbmstcGFkZGluZzogICAgICAgICAgICAgICAgICAgICAgICAgIDEwcHggMTVweCAhZGVmYXVsdDtcbiRuYXYtbGluay1ob3Zlci1iZzogICAgICAgICAgICAgICAgICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcblxuJG5hdi1kaXNhYmxlZC1saW5rLWNvbG9yOiAgICAgICAgICAgICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbiRuYXYtZGlzYWJsZWQtbGluay1ob3Zlci1jb2xvcjogICAgICAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG5cbi8vPT0gVGFic1xuJG5hdi10YWJzLWJvcmRlci1jb2xvcjogICAgICAgICAgICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuXG4kbmF2LXRhYnMtbGluay1ob3Zlci1ib3JkZXItY29sb3I6ICAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG5cbiRuYXYtdGFicy1hY3RpdmUtbGluay1ob3Zlci1iZzogICAgICAgICAgICAgJGJvZHktYmcgIWRlZmF1bHQ7XG4kbmF2LXRhYnMtYWN0aXZlLWxpbmstaG92ZXItY29sb3I6ICAgICAgICAgICRncmF5ICFkZWZhdWx0O1xuJG5hdi10YWJzLWFjdGl2ZS1saW5rLWhvdmVyLWJvcmRlci1jb2xvcjogICAjZGRkICFkZWZhdWx0O1xuXG4kbmF2LXRhYnMtanVzdGlmaWVkLWxpbmstYm9yZGVyLWNvbG9yOiAgICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG4kbmF2LXRhYnMtanVzdGlmaWVkLWFjdGl2ZS1saW5rLWJvcmRlci1jb2xvcjogICAgICRib2R5LWJnICFkZWZhdWx0O1xuXG4vLz09IFBpbGxzXG4kbmF2LXBpbGxzLWJvcmRlci1yYWRpdXM6ICAgICAgICAgICAgICAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG4kbmF2LXBpbGxzLWFjdGl2ZS1saW5rLWhvdmVyLWJnOiAgICAgICAgICAgICRjb21wb25lbnQtYWN0aXZlLWJnICFkZWZhdWx0O1xuJG5hdi1waWxscy1hY3RpdmUtbGluay1ob3Zlci1jb2xvcjogICAgICAgICAkY29tcG9uZW50LWFjdGl2ZS1jb2xvciAhZGVmYXVsdDtcblxuXG4vLz09IFBhZ2luYXRpb25cbi8vXG4vLyMjXG5cbiRwYWdpbmF0aW9uLWNvbG9yOiAgICAgICAgICAgICAgICAgICAgICRsaW5rLWNvbG9yICFkZWZhdWx0O1xuJHBhZ2luYXRpb24tYmc6ICAgICAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWJvcmRlcjogICAgICAgICAgICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG5cbiRwYWdpbmF0aW9uLWhvdmVyLWNvbG9yOiAgICAgICAgICAgICAgICRsaW5rLWhvdmVyLWNvbG9yICFkZWZhdWx0O1xuJHBhZ2luYXRpb24taG92ZXItYmc6ICAgICAgICAgICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWhvdmVyLWJvcmRlcjogICAgICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG5cbiRwYWdpbmF0aW9uLWFjdGl2ZS1jb2xvcjogICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kcGFnaW5hdGlvbi1hY3RpdmUtYmc6ICAgICAgICAgICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWFjdGl2ZS1ib3JkZXI6ICAgICAgICAgICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuXG4kcGFnaW5hdGlvbi1kaXNhYmxlZC1jb2xvcjogICAgICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWRpc2FibGVkLWJnOiAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kcGFnaW5hdGlvbi1kaXNhYmxlZC1ib3JkZXI6ICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuXG5cbi8vPT0gUGFnZXJcbi8vXG4vLyMjXG5cbiRwYWdlci1iZzogICAgICAgICAgICAgICAgICAgICAgICAgICAgICRwYWdpbmF0aW9uLWJnICFkZWZhdWx0O1xuJHBhZ2VyLWJvcmRlcjogICAgICAgICAgICAgICAgICAgICAgICAgJHBhZ2luYXRpb24tYm9yZGVyICFkZWZhdWx0O1xuJHBhZ2VyLWJvcmRlci1yYWRpdXM6ICAgICAgICAgICAgICAgICAgMTVweCAhZGVmYXVsdDtcblxuJHBhZ2VyLWhvdmVyLWJnOiAgICAgICAgICAgICAgICAgICAgICAgJHBhZ2luYXRpb24taG92ZXItYmcgIWRlZmF1bHQ7XG5cbiRwYWdlci1hY3RpdmUtYmc6ICAgICAgICAgICAgICAgICAgICAgICRwYWdpbmF0aW9uLWFjdGl2ZS1iZyAhZGVmYXVsdDtcbiRwYWdlci1hY3RpdmUtY29sb3I6ICAgICAgICAgICAgICAgICAgICRwYWdpbmF0aW9uLWFjdGl2ZS1jb2xvciAhZGVmYXVsdDtcblxuJHBhZ2VyLWRpc2FibGVkLWNvbG9yOiAgICAgICAgICAgICAgICAgJHBhZ2luYXRpb24tZGlzYWJsZWQtY29sb3IgIWRlZmF1bHQ7XG5cblxuLy89PSBKdW1ib3Ryb25cbi8vXG4vLyMjXG5cbiRqdW1ib3Ryb24tcGFkZGluZzogICAgICAgICAgICAgIDMwcHggIWRlZmF1bHQ7XG4kanVtYm90cm9uLWNvbG9yOiAgICAgICAgICAgICAgICBpbmhlcml0ICFkZWZhdWx0O1xuJGp1bWJvdHJvbi1iZzogICAgICAgICAgICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbiRqdW1ib3Ryb24taGVhZGluZy1jb2xvcjogICAgICAgIGluaGVyaXQgIWRlZmF1bHQ7XG4kanVtYm90cm9uLWZvbnQtc2l6ZTogICAgICAgICAgICBjZWlsKCgkZm9udC1zaXplLWJhc2UgKiAxLjUpKSAhZGVmYXVsdDtcbiRqdW1ib3Ryb24taGVhZGluZy1mb250LXNpemU6ICAgIGNlaWwoKCRmb250LXNpemUtYmFzZSAqIDQuNSkpICFkZWZhdWx0O1xuXG5cbi8vPT0gRm9ybSBzdGF0ZXMgYW5kIGFsZXJ0c1xuLy9cbi8vIyMgRGVmaW5lIGNvbG9ycyBmb3IgZm9ybSBmZWVkYmFjayBzdGF0ZXMgYW5kLCBieSBkZWZhdWx0LCBhbGVydHMuXG5cbiRzdGF0ZS1zdWNjZXNzLXRleHQ6ICAgICAgICAgICAgICMzYzc2M2QgIWRlZmF1bHQ7XG4kc3RhdGUtc3VjY2Vzcy1iZzogICAgICAgICAgICAgICAjZGZmMGQ4ICFkZWZhdWx0O1xuJHN0YXRlLXN1Y2Nlc3MtYm9yZGVyOiAgICAgICAgICAgZGFya2VuKGFkanVzdC1odWUoJHN0YXRlLXN1Y2Nlc3MtYmcsIC0xMCksIDUlKSAhZGVmYXVsdDtcblxuJHN0YXRlLWluZm8tdGV4dDogICAgICAgICAgICAgICAgIzMxNzA4ZiAhZGVmYXVsdDtcbiRzdGF0ZS1pbmZvLWJnOiAgICAgICAgICAgICAgICAgICNkOWVkZjcgIWRlZmF1bHQ7XG4kc3RhdGUtaW5mby1ib3JkZXI6ICAgICAgICAgICAgICBkYXJrZW4oYWRqdXN0LWh1ZSgkc3RhdGUtaW5mby1iZywgLTEwKSwgNyUpICFkZWZhdWx0O1xuXG4kc3RhdGUtd2FybmluZy10ZXh0OiAgICAgICAgICAgICAjOGE2ZDNiICFkZWZhdWx0O1xuJHN0YXRlLXdhcm5pbmctYmc6ICAgICAgICAgICAgICAgI2ZjZjhlMyAhZGVmYXVsdDtcbiRzdGF0ZS13YXJuaW5nLWJvcmRlcjogICAgICAgICAgIGRhcmtlbihhZGp1c3QtaHVlKCRzdGF0ZS13YXJuaW5nLWJnLCAtMTApLCA1JSkgIWRlZmF1bHQ7XG5cbiRzdGF0ZS1kYW5nZXItdGV4dDogICAgICAgICAgICAgICNhOTQ0NDIgIWRlZmF1bHQ7XG4kc3RhdGUtZGFuZ2VyLWJnOiAgICAgICAgICAgICAgICAjZjJkZWRlICFkZWZhdWx0O1xuJHN0YXRlLWRhbmdlci1ib3JkZXI6ICAgICAgICAgICAgZGFya2VuKGFkanVzdC1odWUoJHN0YXRlLWRhbmdlci1iZywgLTEwKSwgNSUpICFkZWZhdWx0O1xuXG5cbi8vPT0gVG9vbHRpcHNcbi8vXG4vLyMjXG5cbi8vKiogVG9vbHRpcCBtYXggd2lkdGhcbiR0b29sdGlwLW1heC13aWR0aDogICAgICAgICAgIDIwMHB4ICFkZWZhdWx0O1xuLy8qKiBUb29sdGlwIHRleHQgY29sb3JcbiR0b29sdGlwLWNvbG9yOiAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIFRvb2x0aXAgYmFja2dyb3VuZCBjb2xvclxuJHRvb2x0aXAtYmc6ICAgICAgICAgICAgICAgICAgIzAwMCAhZGVmYXVsdDtcbiR0b29sdGlwLW9wYWNpdHk6ICAgICAgICAgICAgIC45ICFkZWZhdWx0O1xuXG4vLyoqIFRvb2x0aXAgYXJyb3cgd2lkdGhcbiR0b29sdGlwLWFycm93LXdpZHRoOiAgICAgICAgIDVweCAhZGVmYXVsdDtcbi8vKiogVG9vbHRpcCBhcnJvdyBjb2xvclxuJHRvb2x0aXAtYXJyb3ctY29sb3I6ICAgICAgICAgJHRvb2x0aXAtYmcgIWRlZmF1bHQ7XG5cblxuLy89PSBQb3BvdmVyc1xuLy9cbi8vIyNcblxuLy8qKiBQb3BvdmVyIGJvZHkgYmFja2dyb3VuZCBjb2xvclxuJHBvcG92ZXItYmc6ICAgICAgICAgICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBQb3BvdmVyIG1heGltdW0gd2lkdGhcbiRwb3BvdmVyLW1heC13aWR0aDogICAgICAgICAgICAgICAgICAgMjc2cHggIWRlZmF1bHQ7XG4vLyoqIFBvcG92ZXIgYm9yZGVyIGNvbG9yXG4kcG9wb3Zlci1ib3JkZXItY29sb3I6ICAgICAgICAgICAgICAgIHJnYmEoMCwwLDAsLjIpICFkZWZhdWx0O1xuLy8qKiBQb3BvdmVyIGZhbGxiYWNrIGJvcmRlciBjb2xvclxuJHBvcG92ZXItZmFsbGJhY2stYm9yZGVyLWNvbG9yOiAgICAgICAjY2NjICFkZWZhdWx0O1xuXG4vLyoqIFBvcG92ZXIgdGl0bGUgYmFja2dyb3VuZCBjb2xvclxuJHBvcG92ZXItdGl0bGUtYmc6ICAgICAgICAgICAgICAgICAgICBkYXJrZW4oJHBvcG92ZXItYmcsIDMlKSAhZGVmYXVsdDtcblxuLy8qKiBQb3BvdmVyIGFycm93IHdpZHRoXG4kcG9wb3Zlci1hcnJvdy13aWR0aDogICAgICAgICAgICAgICAgIDEwcHggIWRlZmF1bHQ7XG4vLyoqIFBvcG92ZXIgYXJyb3cgY29sb3JcbiRwb3BvdmVyLWFycm93LWNvbG9yOiAgICAgICAgICAgICAgICAgJHBvcG92ZXItYmcgIWRlZmF1bHQ7XG5cbi8vKiogUG9wb3ZlciBvdXRlciBhcnJvdyB3aWR0aFxuJHBvcG92ZXItYXJyb3ctb3V0ZXItd2lkdGg6ICAgICAgICAgICAoJHBvcG92ZXItYXJyb3ctd2lkdGggKyAxKSAhZGVmYXVsdDtcbi8vKiogUG9wb3ZlciBvdXRlciBhcnJvdyBjb2xvclxuJHBvcG92ZXItYXJyb3ctb3V0ZXItY29sb3I6ICAgICAgICAgICBmYWRlX2luKCRwb3BvdmVyLWJvcmRlci1jb2xvciwgMC4wNSkgIWRlZmF1bHQ7XG4vLyoqIFBvcG92ZXIgb3V0ZXIgYXJyb3cgZmFsbGJhY2sgY29sb3JcbiRwb3BvdmVyLWFycm93LW91dGVyLWZhbGxiYWNrLWNvbG9yOiAgZGFya2VuKCRwb3BvdmVyLWZhbGxiYWNrLWJvcmRlci1jb2xvciwgMjAlKSAhZGVmYXVsdDtcblxuXG4vLz09IExhYmVsc1xuLy9cbi8vIyNcblxuLy8qKiBEZWZhdWx0IGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC1kZWZhdWx0LWJnOiAgICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBQcmltYXJ5IGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC1wcmltYXJ5LWJnOiAgICAgICAgICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuLy8qKiBTdWNjZXNzIGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC1zdWNjZXNzLWJnOiAgICAgICAgICAgICRicmFuZC1zdWNjZXNzICFkZWZhdWx0O1xuLy8qKiBJbmZvIGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC1pbmZvLWJnOiAgICAgICAgICAgICAgICRicmFuZC1pbmZvICFkZWZhdWx0O1xuLy8qKiBXYXJuaW5nIGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC13YXJuaW5nLWJnOiAgICAgICAgICAgICRicmFuZC13YXJuaW5nICFkZWZhdWx0O1xuLy8qKiBEYW5nZXIgbGFiZWwgYmFja2dyb3VuZCBjb2xvclxuJGxhYmVsLWRhbmdlci1iZzogICAgICAgICAgICAgJGJyYW5kLWRhbmdlciAhZGVmYXVsdDtcblxuLy8qKiBEZWZhdWx0IGxhYmVsIHRleHQgY29sb3JcbiRsYWJlbC1jb2xvcjogICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIERlZmF1bHQgdGV4dCBjb2xvciBvZiBhIGxpbmtlZCBsYWJlbFxuJGxhYmVsLWxpbmstaG92ZXItY29sb3I6ICAgICAgI2ZmZiAhZGVmYXVsdDtcblxuXG4vLz09IE1vZGFsc1xuLy9cbi8vIyNcblxuLy8qKiBQYWRkaW5nIGFwcGxpZWQgdG8gdGhlIG1vZGFsIGJvZHlcbiRtb2RhbC1pbm5lci1wYWRkaW5nOiAgICAgICAgIDE1cHggIWRlZmF1bHQ7XG5cbi8vKiogUGFkZGluZyBhcHBsaWVkIHRvIHRoZSBtb2RhbCB0aXRsZVxuJG1vZGFsLXRpdGxlLXBhZGRpbmc6ICAgICAgICAgMTVweCAhZGVmYXVsdDtcbi8vKiogTW9kYWwgdGl0bGUgbGluZS1oZWlnaHRcbiRtb2RhbC10aXRsZS1saW5lLWhlaWdodDogICAgICRsaW5lLWhlaWdodC1iYXNlICFkZWZhdWx0O1xuXG4vLyoqIEJhY2tncm91bmQgY29sb3Igb2YgbW9kYWwgY29udGVudCBhcmVhXG4kbW9kYWwtY29udGVudC1iZzogICAgICAgICAgICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIE1vZGFsIGNvbnRlbnQgYm9yZGVyIGNvbG9yXG4kbW9kYWwtY29udGVudC1ib3JkZXItY29sb3I6ICAgICAgICAgICAgICAgICAgIHJnYmEoMCwwLDAsLjIpICFkZWZhdWx0O1xuLy8qKiBNb2RhbCBjb250ZW50IGJvcmRlciBjb2xvciAqKmZvciBJRTgqKlxuJG1vZGFsLWNvbnRlbnQtZmFsbGJhY2stYm9yZGVyLWNvbG9yOiAgICAgICAgICAjOTk5ICFkZWZhdWx0O1xuXG4vLyoqIE1vZGFsIGJhY2tkcm9wIGJhY2tncm91bmQgY29sb3JcbiRtb2RhbC1iYWNrZHJvcC1iZzogICAgICAgICAgICMwMDAgIWRlZmF1bHQ7XG4vLyoqIE1vZGFsIGJhY2tkcm9wIG9wYWNpdHlcbiRtb2RhbC1iYWNrZHJvcC1vcGFjaXR5OiAgICAgIC41ICFkZWZhdWx0O1xuLy8qKiBNb2RhbCBoZWFkZXIgYm9yZGVyIGNvbG9yXG4kbW9kYWwtaGVhZGVyLWJvcmRlci1jb2xvcjogICAjZTVlNWU1ICFkZWZhdWx0O1xuLy8qKiBNb2RhbCBmb290ZXIgYm9yZGVyIGNvbG9yXG4kbW9kYWwtZm9vdGVyLWJvcmRlci1jb2xvcjogICAkbW9kYWwtaGVhZGVyLWJvcmRlci1jb2xvciAhZGVmYXVsdDtcblxuJG1vZGFsLWxnOiAgICAgICAgICAgICAgICAgICAgOTAwcHggIWRlZmF1bHQ7XG4kbW9kYWwtbWQ6ICAgICAgICAgICAgICAgICAgICA2MDBweCAhZGVmYXVsdDtcbiRtb2RhbC1zbTogICAgICAgICAgICAgICAgICAgIDMwMHB4ICFkZWZhdWx0O1xuXG5cbi8vPT0gQWxlcnRzXG4vL1xuLy8jIyBEZWZpbmUgYWxlcnQgY29sb3JzLCBib3JkZXIgcmFkaXVzLCBhbmQgcGFkZGluZy5cblxuJGFsZXJ0LXBhZGRpbmc6ICAgICAgICAgICAgICAgMTVweCAhZGVmYXVsdDtcbiRhbGVydC1ib3JkZXItcmFkaXVzOiAgICAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG4kYWxlcnQtbGluay1mb250LXdlaWdodDogICAgICBib2xkICFkZWZhdWx0O1xuXG4kYWxlcnQtc3VjY2Vzcy1iZzogICAgICAgICAgICAkc3RhdGUtc3VjY2Vzcy1iZyAhZGVmYXVsdDtcbiRhbGVydC1zdWNjZXNzLXRleHQ6ICAgICAgICAgICRzdGF0ZS1zdWNjZXNzLXRleHQgIWRlZmF1bHQ7XG4kYWxlcnQtc3VjY2Vzcy1ib3JkZXI6ICAgICAgICAkc3RhdGUtc3VjY2Vzcy1ib3JkZXIgIWRlZmF1bHQ7XG5cbiRhbGVydC1pbmZvLWJnOiAgICAgICAgICAgICAgICRzdGF0ZS1pbmZvLWJnICFkZWZhdWx0O1xuJGFsZXJ0LWluZm8tdGV4dDogICAgICAgICAgICAgJHN0YXRlLWluZm8tdGV4dCAhZGVmYXVsdDtcbiRhbGVydC1pbmZvLWJvcmRlcjogICAgICAgICAgICRzdGF0ZS1pbmZvLWJvcmRlciAhZGVmYXVsdDtcblxuJGFsZXJ0LXdhcm5pbmctYmc6ICAgICAgICAgICAgJHN0YXRlLXdhcm5pbmctYmcgIWRlZmF1bHQ7XG4kYWxlcnQtd2FybmluZy10ZXh0OiAgICAgICAgICAkc3RhdGUtd2FybmluZy10ZXh0ICFkZWZhdWx0O1xuJGFsZXJ0LXdhcm5pbmctYm9yZGVyOiAgICAgICAgJHN0YXRlLXdhcm5pbmctYm9yZGVyICFkZWZhdWx0O1xuXG4kYWxlcnQtZGFuZ2VyLWJnOiAgICAgICAgICAgICAkc3RhdGUtZGFuZ2VyLWJnICFkZWZhdWx0O1xuJGFsZXJ0LWRhbmdlci10ZXh0OiAgICAgICAgICAgJHN0YXRlLWRhbmdlci10ZXh0ICFkZWZhdWx0O1xuJGFsZXJ0LWRhbmdlci1ib3JkZXI6ICAgICAgICAgJHN0YXRlLWRhbmdlci1ib3JkZXIgIWRlZmF1bHQ7XG5cblxuLy89PSBQcm9ncmVzcyBiYXJzXG4vL1xuLy8jI1xuXG4vLyoqIEJhY2tncm91bmQgY29sb3Igb2YgdGhlIHdob2xlIHByb2dyZXNzIGNvbXBvbmVudFxuJHByb2dyZXNzLWJnOiAgICAgICAgICAgICAgICAgI2Y1ZjVmNSAhZGVmYXVsdDtcbi8vKiogUHJvZ3Jlc3MgYmFyIHRleHQgY29sb3JcbiRwcm9ncmVzcy1iYXItY29sb3I6ICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIFZhcmlhYmxlIGZvciBzZXR0aW5nIHJvdW5kZWQgY29ybmVycyBvbiBwcm9ncmVzcyBiYXIuXG4kcHJvZ3Jlc3MtYm9yZGVyLXJhZGl1czogICAgICAkYm9yZGVyLXJhZGl1cy1iYXNlICFkZWZhdWx0O1xuXG4vLyoqIERlZmF1bHQgcHJvZ3Jlc3MgYmFyIGNvbG9yXG4kcHJvZ3Jlc3MtYmFyLWJnOiAgICAgICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcbi8vKiogU3VjY2VzcyBwcm9ncmVzcyBiYXIgY29sb3JcbiRwcm9ncmVzcy1iYXItc3VjY2Vzcy1iZzogICAgICRicmFuZC1zdWNjZXNzICFkZWZhdWx0O1xuLy8qKiBXYXJuaW5nIHByb2dyZXNzIGJhciBjb2xvclxuJHByb2dyZXNzLWJhci13YXJuaW5nLWJnOiAgICAgJGJyYW5kLXdhcm5pbmcgIWRlZmF1bHQ7XG4vLyoqIERhbmdlciBwcm9ncmVzcyBiYXIgY29sb3JcbiRwcm9ncmVzcy1iYXItZGFuZ2VyLWJnOiAgICAgICRicmFuZC1kYW5nZXIgIWRlZmF1bHQ7XG4vLyoqIEluZm8gcHJvZ3Jlc3MgYmFyIGNvbG9yXG4kcHJvZ3Jlc3MtYmFyLWluZm8tYmc6ICAgICAgICAkYnJhbmQtaW5mbyAhZGVmYXVsdDtcblxuXG4vLz09IExpc3QgZ3JvdXBcbi8vXG4vLyMjXG5cbi8vKiogQmFja2dyb3VuZCBjb2xvciBvbiBgLmxpc3QtZ3JvdXAtaXRlbWBcbiRsaXN0LWdyb3VwLWJnOiAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogYC5saXN0LWdyb3VwLWl0ZW1gIGJvcmRlciBjb2xvclxuJGxpc3QtZ3JvdXAtYm9yZGVyOiAgICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuLy8qKiBMaXN0IGdyb3VwIGJvcmRlciByYWRpdXNcbiRsaXN0LWdyb3VwLWJvcmRlci1yYWRpdXM6ICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcblxuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIG9mIHNpbmdsZSBsaXN0IGl0ZW1zIG9uIGhvdmVyXG4kbGlzdC1ncm91cC1ob3Zlci1iZzogICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG4vLyoqIFRleHQgY29sb3Igb2YgYWN0aXZlIGxpc3QgaXRlbXNcbiRsaXN0LWdyb3VwLWFjdGl2ZS1jb2xvcjogICAgICAgJGNvbXBvbmVudC1hY3RpdmUtY29sb3IgIWRlZmF1bHQ7XG4vLyoqIEJhY2tncm91bmQgY29sb3Igb2YgYWN0aXZlIGxpc3QgaXRlbXNcbiRsaXN0LWdyb3VwLWFjdGl2ZS1iZzogICAgICAgICAgJGNvbXBvbmVudC1hY3RpdmUtYmcgIWRlZmF1bHQ7XG4vLyoqIEJvcmRlciBjb2xvciBvZiBhY3RpdmUgbGlzdCBlbGVtZW50c1xuJGxpc3QtZ3JvdXAtYWN0aXZlLWJvcmRlcjogICAgICAkbGlzdC1ncm91cC1hY3RpdmUtYmcgIWRlZmF1bHQ7XG4vLyoqIFRleHQgY29sb3IgZm9yIGNvbnRlbnQgd2l0aGluIGFjdGl2ZSBsaXN0IGl0ZW1zXG4kbGlzdC1ncm91cC1hY3RpdmUtdGV4dC1jb2xvcjogIGxpZ2h0ZW4oJGxpc3QtZ3JvdXAtYWN0aXZlLWJnLCA0MCUpICFkZWZhdWx0O1xuXG4vLyoqIFRleHQgY29sb3Igb2YgZGlzYWJsZWQgbGlzdCBpdGVtc1xuJGxpc3QtZ3JvdXAtZGlzYWJsZWQtY29sb3I6ICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG4vLyoqIEJhY2tncm91bmQgY29sb3Igb2YgZGlzYWJsZWQgbGlzdCBpdGVtc1xuJGxpc3QtZ3JvdXAtZGlzYWJsZWQtYmc6ICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbi8vKiogVGV4dCBjb2xvciBmb3IgY29udGVudCB3aXRoaW4gZGlzYWJsZWQgbGlzdCBpdGVtc1xuJGxpc3QtZ3JvdXAtZGlzYWJsZWQtdGV4dC1jb2xvcjogJGxpc3QtZ3JvdXAtZGlzYWJsZWQtY29sb3IgIWRlZmF1bHQ7XG5cbiRsaXN0LWdyb3VwLWxpbmstY29sb3I6ICAgICAgICAgIzU1NSAhZGVmYXVsdDtcbiRsaXN0LWdyb3VwLWxpbmstaG92ZXItY29sb3I6ICAgJGxpc3QtZ3JvdXAtbGluay1jb2xvciAhZGVmYXVsdDtcbiRsaXN0LWdyb3VwLWxpbmstaGVhZGluZy1jb2xvcjogIzMzMyAhZGVmYXVsdDtcblxuXG4vLz09IFBhbmVsc1xuLy9cbi8vIyNcblxuJHBhbmVsLWJnOiAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRwYW5lbC1ib2R5LXBhZGRpbmc6ICAgICAgICAgIDE1cHggIWRlZmF1bHQ7XG4kcGFuZWwtaGVhZGluZy1wYWRkaW5nOiAgICAgICAxMHB4IDE1cHggIWRlZmF1bHQ7XG4kcGFuZWwtZm9vdGVyLXBhZGRpbmc6ICAgICAgICAkcGFuZWwtaGVhZGluZy1wYWRkaW5nICFkZWZhdWx0O1xuJHBhbmVsLWJvcmRlci1yYWRpdXM6ICAgICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcblxuLy8qKiBCb3JkZXIgY29sb3IgZm9yIGVsZW1lbnRzIHdpdGhpbiBwYW5lbHNcbiRwYW5lbC1pbm5lci1ib3JkZXI6ICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG4kcGFuZWwtZm9vdGVyLWJnOiAgICAgICAgICAgICAjZjVmNWY1ICFkZWZhdWx0O1xuXG4kcGFuZWwtZGVmYXVsdC10ZXh0OiAgICAgICAgICAkZ3JheS1kYXJrICFkZWZhdWx0O1xuJHBhbmVsLWRlZmF1bHQtYm9yZGVyOiAgICAgICAgI2RkZCAhZGVmYXVsdDtcbiRwYW5lbC1kZWZhdWx0LWhlYWRpbmctYmc6ICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG5cbiRwYW5lbC1wcmltYXJ5LXRleHQ6ICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kcGFuZWwtcHJpbWFyeS1ib3JkZXI6ICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcbiRwYW5lbC1wcmltYXJ5LWhlYWRpbmctYmc6ICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuXG4kcGFuZWwtc3VjY2Vzcy10ZXh0OiAgICAgICAgICAkc3RhdGUtc3VjY2Vzcy10ZXh0ICFkZWZhdWx0O1xuJHBhbmVsLXN1Y2Nlc3MtYm9yZGVyOiAgICAgICAgJHN0YXRlLXN1Y2Nlc3MtYm9yZGVyICFkZWZhdWx0O1xuJHBhbmVsLXN1Y2Nlc3MtaGVhZGluZy1iZzogICAgJHN0YXRlLXN1Y2Nlc3MtYmcgIWRlZmF1bHQ7XG5cbiRwYW5lbC1pbmZvLXRleHQ6ICAgICAgICAgICAgICRzdGF0ZS1pbmZvLXRleHQgIWRlZmF1bHQ7XG4kcGFuZWwtaW5mby1ib3JkZXI6ICAgICAgICAgICAkc3RhdGUtaW5mby1ib3JkZXIgIWRlZmF1bHQ7XG4kcGFuZWwtaW5mby1oZWFkaW5nLWJnOiAgICAgICAkc3RhdGUtaW5mby1iZyAhZGVmYXVsdDtcblxuJHBhbmVsLXdhcm5pbmctdGV4dDogICAgICAgICAgJHN0YXRlLXdhcm5pbmctdGV4dCAhZGVmYXVsdDtcbiRwYW5lbC13YXJuaW5nLWJvcmRlcjogICAgICAgICRzdGF0ZS13YXJuaW5nLWJvcmRlciAhZGVmYXVsdDtcbiRwYW5lbC13YXJuaW5nLWhlYWRpbmctYmc6ICAgICRzdGF0ZS13YXJuaW5nLWJnICFkZWZhdWx0O1xuXG4kcGFuZWwtZGFuZ2VyLXRleHQ6ICAgICAgICAgICAkc3RhdGUtZGFuZ2VyLXRleHQgIWRlZmF1bHQ7XG4kcGFuZWwtZGFuZ2VyLWJvcmRlcjogICAgICAgICAkc3RhdGUtZGFuZ2VyLWJvcmRlciAhZGVmYXVsdDtcbiRwYW5lbC1kYW5nZXItaGVhZGluZy1iZzogICAgICRzdGF0ZS1kYW5nZXItYmcgIWRlZmF1bHQ7XG5cblxuLy89PSBUaHVtYm5haWxzXG4vL1xuLy8jI1xuXG4vLyoqIFBhZGRpbmcgYXJvdW5kIHRoZSB0aHVtYm5haWwgaW1hZ2VcbiR0aHVtYm5haWwtcGFkZGluZzogICAgICAgICAgIDRweCAhZGVmYXVsdDtcbi8vKiogVGh1bWJuYWlsIGJhY2tncm91bmQgY29sb3JcbiR0aHVtYm5haWwtYmc6ICAgICAgICAgICAgICAgICRib2R5LWJnICFkZWZhdWx0O1xuLy8qKiBUaHVtYm5haWwgYm9yZGVyIGNvbG9yXG4kdGh1bWJuYWlsLWJvcmRlcjogICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuLy8qKiBUaHVtYm5haWwgYm9yZGVyIHJhZGl1c1xuJHRodW1ibmFpbC1ib3JkZXItcmFkaXVzOiAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcblxuLy8qKiBDdXN0b20gdGV4dCBjb2xvciBmb3IgdGh1bWJuYWlsIGNhcHRpb25zXG4kdGh1bWJuYWlsLWNhcHRpb24tY29sb3I6ICAgICAkdGV4dC1jb2xvciAhZGVmYXVsdDtcbi8vKiogUGFkZGluZyBhcm91bmQgdGhlIHRodW1ibmFpbCBjYXB0aW9uXG4kdGh1bWJuYWlsLWNhcHRpb24tcGFkZGluZzogICA5cHggIWRlZmF1bHQ7XG5cblxuLy89PSBXZWxsc1xuLy9cbi8vIyNcblxuJHdlbGwtYmc6ICAgICAgICAgICAgICAgICAgICAgI2Y1ZjVmNSAhZGVmYXVsdDtcbiR3ZWxsLWJvcmRlcjogICAgICAgICAgICAgICAgIGRhcmtlbigkd2VsbC1iZywgNyUpICFkZWZhdWx0O1xuXG5cbi8vPT0gQmFkZ2VzXG4vL1xuLy8jI1xuXG4kYmFkZ2UtY29sb3I6ICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBMaW5rZWQgYmFkZ2UgdGV4dCBjb2xvciBvbiBob3ZlclxuJGJhZGdlLWxpbmstaG92ZXItY29sb3I6ICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRiYWRnZS1iZzogICAgICAgICAgICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuXG4vLyoqIEJhZGdlIHRleHQgY29sb3IgaW4gYWN0aXZlIG5hdiBsaW5rXG4kYmFkZ2UtYWN0aXZlLWNvbG9yOiAgICAgICAgICAkbGluay1jb2xvciAhZGVmYXVsdDtcbi8vKiogQmFkZ2UgYmFja2dyb3VuZCBjb2xvciBpbiBhY3RpdmUgbmF2IGxpbmtcbiRiYWRnZS1hY3RpdmUtYmc6ICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG5cbiRiYWRnZS1mb250LXdlaWdodDogICAgICAgICAgIGJvbGQgIWRlZmF1bHQ7XG4kYmFkZ2UtbGluZS1oZWlnaHQ6ICAgICAgICAgICAxICFkZWZhdWx0O1xuJGJhZGdlLWJvcmRlci1yYWRpdXM6ICAgICAgICAgMTBweCAhZGVmYXVsdDtcblxuXG4vLz09IEJyZWFkY3J1bWJzXG4vL1xuLy8jI1xuXG4kYnJlYWRjcnVtYi1wYWRkaW5nLXZlcnRpY2FsOiAgIDhweCAhZGVmYXVsdDtcbiRicmVhZGNydW1iLXBhZGRpbmctaG9yaXpvbnRhbDogMTVweCAhZGVmYXVsdDtcbi8vKiogQnJlYWRjcnVtYiBiYWNrZ3JvdW5kIGNvbG9yXG4kYnJlYWRjcnVtYi1iZzogICAgICAgICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG4vLyoqIEJyZWFkY3J1bWIgdGV4dCBjb2xvclxuJGJyZWFkY3J1bWItY29sb3I6ICAgICAgICAgICAgICAjY2NjICFkZWZhdWx0O1xuLy8qKiBUZXh0IGNvbG9yIG9mIGN1cnJlbnQgcGFnZSBpbiB0aGUgYnJlYWRjcnVtYlxuJGJyZWFkY3J1bWItYWN0aXZlLWNvbG9yOiAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbi8vKiogVGV4dHVhbCBzZXBhcmF0b3IgZm9yIGJldHdlZW4gYnJlYWRjcnVtYiBlbGVtZW50c1xuJGJyZWFkY3J1bWItc2VwYXJhdG9yOiAgICAgICAgICBcIi9cIiAhZGVmYXVsdDtcblxuXG4vLz09IENhcm91c2VsXG4vL1xuLy8jI1xuXG4kY2Fyb3VzZWwtdGV4dC1zaGFkb3c6ICAgICAgICAgICAgICAgICAgICAgICAgMCAxcHggMnB4IHJnYmEoMCwwLDAsLjYpICFkZWZhdWx0O1xuXG4kY2Fyb3VzZWwtY29udHJvbC1jb2xvcjogICAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRjYXJvdXNlbC1jb250cm9sLXdpZHRoOiAgICAgICAgICAgICAgICAgICAgICAxNSUgIWRlZmF1bHQ7XG4kY2Fyb3VzZWwtY29udHJvbC1vcGFjaXR5OiAgICAgICAgICAgICAgICAgICAgLjUgIWRlZmF1bHQ7XG4kY2Fyb3VzZWwtY29udHJvbC1mb250LXNpemU6ICAgICAgICAgICAgICAgICAgMjBweCAhZGVmYXVsdDtcblxuJGNhcm91c2VsLWluZGljYXRvci1hY3RpdmUtYmc6ICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kY2Fyb3VzZWwtaW5kaWNhdG9yLWJvcmRlci1jb2xvcjogICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcblxuJGNhcm91c2VsLWNhcHRpb24tY29sb3I6ICAgICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG5cblxuLy89PSBDbG9zZVxuLy9cbi8vIyNcblxuJGNsb3NlLWZvbnQtd2VpZ2h0OiAgICAgICAgICAgYm9sZCAhZGVmYXVsdDtcbiRjbG9zZS1jb2xvcjogICAgICAgICAgICAgICAgICMwMDAgIWRlZmF1bHQ7XG4kY2xvc2UtdGV4dC1zaGFkb3c6ICAgICAgICAgICAwIDFweCAwICNmZmYgIWRlZmF1bHQ7XG5cblxuLy89PSBDb2RlXG4vL1xuLy8jI1xuXG4kY29kZS1jb2xvcjogICAgICAgICAgICAgICAgICAjYzcyNTRlICFkZWZhdWx0O1xuJGNvZGUtYmc6ICAgICAgICAgICAgICAgICAgICAgI2Y5ZjJmNCAhZGVmYXVsdDtcblxuJGtiZC1jb2xvcjogICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRrYmQtYmc6ICAgICAgICAgICAgICAgICAgICAgICMzMzMgIWRlZmF1bHQ7XG5cbiRwcmUtYmc6ICAgICAgICAgICAgICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG4kcHJlLWNvbG9yOiAgICAgICAgICAgICAgICAgICAkZ3JheS1kYXJrICFkZWZhdWx0O1xuJHByZS1ib3JkZXItY29sb3I6ICAgICAgICAgICAgI2NjYyAhZGVmYXVsdDtcbiRwcmUtc2Nyb2xsYWJsZS1tYXgtaGVpZ2h0OiAgIDM0MHB4ICFkZWZhdWx0O1xuXG5cbi8vPT0gVHlwZVxuLy9cbi8vIyNcblxuLy8qKiBIb3Jpem9udGFsIG9mZnNldCBmb3IgZm9ybXMgYW5kIGxpc3RzLlxuJGNvbXBvbmVudC1vZmZzZXQtaG9yaXpvbnRhbDogMTgwcHggIWRlZmF1bHQ7XG4vLyoqIFRleHQgbXV0ZWQgY29sb3JcbiR0ZXh0LW11dGVkOiAgICAgICAgICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBBYmJyZXZpYXRpb25zIGFuZCBhY3JvbnltcyBib3JkZXIgY29sb3JcbiRhYmJyLWJvcmRlci1jb2xvcjogICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBIZWFkaW5ncyBzbWFsbCBjb2xvclxuJGhlYWRpbmdzLXNtYWxsLWNvbG9yOiAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG4vLyoqIEJsb2NrcXVvdGUgc21hbGwgY29sb3JcbiRibG9ja3F1b3RlLXNtYWxsLWNvbG9yOiAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBCbG9ja3F1b3RlIGZvbnQgc2l6ZVxuJGJsb2NrcXVvdGUtZm9udC1zaXplOiAgICAgICAgKCRmb250LXNpemUtYmFzZSAqIDEuMjUpICFkZWZhdWx0O1xuLy8qKiBCbG9ja3F1b3RlIGJvcmRlciBjb2xvclxuJGJsb2NrcXVvdGUtYm9yZGVyLWNvbG9yOiAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbi8vKiogUGFnZSBoZWFkZXIgYm9yZGVyIGNvbG9yXG4kcGFnZS1oZWFkZXItYm9yZGVyLWNvbG9yOiAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuLy8qKiBXaWR0aCBvZiBob3Jpem9udGFsIGRlc2NyaXB0aW9uIGxpc3QgdGl0bGVzXG4kZGwtaG9yaXpvbnRhbC1vZmZzZXQ6ICAgICAgICAkY29tcG9uZW50LW9mZnNldC1ob3Jpem9udGFsICFkZWZhdWx0O1xuLy8qKiBQb2ludCBhdCB3aGljaCAuZGwtaG9yaXpvbnRhbCBiZWNvbWVzIGhvcml6b250YWxcbiRkbC1ob3Jpem9udGFsLWJyZWFrcG9pbnQ6ICAgICRncmlkLWZsb2F0LWJyZWFrcG9pbnQgIWRlZmF1bHQ7XG4vLyoqIEhvcml6b250YWwgbGluZSBjb2xvci5cbiRoci1ib3JkZXI6ICAgICAgICAgICAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG4iLCJAaW1wb3J0ICcuLi8uLi8uLi9zdHlsZXMvYW5pbWF0aW9ucy5zY3NzJztcblxueG9zLXRhYmxlIHtcblxuICBkaXNwbGF5OiBibG9jaztcblxuICB0ci5uZy1tb3ZlLFxuICB0ci5uZy1lbnRlcixcbiAgdHIubmctbGVhdmUge1xuICAgIHRyYW5zaXRpb246YWxsIGxpbmVhciAwLjVzO1xuICB9XG5cbiAgdHIubmctbGVhdmUubmctbGVhdmUtYWN0aXZlLFxuICB0ci5uZy1tb3ZlLFxuICB0ci5uZy1lbnRlciB7XG4gICAgb3BhY2l0eTowO1xuICAgIGFuaW1hdGlvbjogMC41cyBzbGlkZU91dFJpZ2h0IGVhc2UtaW4tb3V0O1xuICB9XG5cbiAgdHIubmctbGVhdmUsXG4gIHRyLm5nLW1vdmUubmctbW92ZS1hY3RpdmUsXG4gIHRyLm5nLWVudGVyLm5nLWVudGVyLWFjdGl2ZSB7XG4gICAgb3BhY2l0eToxO1xuICAgIGFuaW1hdGlvbjogMC41cyBzbGlkZUluUmlnaHQgZWFzZS1pbi1vdXQ7XG4gIH1cblxuICB0ZCBkbCB7XG4gICAgbWFyZ2luLWJvdHRvbTogMDtcblxuICAgIGR0IHtcbiAgICAgIHdpZHRoOiBhdXRvICFpbXBvcnRhbnQ7XG4gICAgICBtYXJnaW4tcmlnaHQ6IDEwcHg7XG4gICAgfVxuICAgIFxuICAgIGR0OmFmdGVyIHtcbiAgICAgIC8qZGlzcGxheTogYmxvY2s7Ki9cbiAgICAgIGNvbnRlbnQ6ICc6JztcbiAgICB9XG5cbiAgICBkZCB7XG4gICAgICBtYXJnaW4tbGVmdDogMCAhaW1wb3J0YW50O1xuICAgIH1cbiAgfVxufSIsIkBpbXBvcnQgJy4uLy4uLy4uL3N0eWxlcy9hbmltYXRpb25zLnNjc3MnO1xuXG54b3MtYWxlcnQge1xuXG4gIC8qIHdoZW4gaGlkaW5nICovXG4gIC5uZy1oaWRlLWFkZCAgICAgICAgIHsgYW5pbWF0aW9uOjAuNXMgZmFkZU91dERvd24gZWFzZS1pbi1vdXQ7IH1cblxuICAvKiB3aGVuIHNob3dpbmcgKi9cbiAgLm5nLWhpZGUtcmVtb3ZlICAgICAgeyBhbmltYXRpb246MC41cyBmYWRlSW5VcCBlYXNlLWluLW91dDsgfVxufSIsIkBpbXBvcnQgJy4uLy4uLy4uL3N0eWxlcy9hbmltYXRpb25zLnNjc3MnO1xuQGltcG9ydCAnLi4vLi4vLi4vLi4vLi4vLi4vc3R5bGUvc2Fzcy9ib290c3RyYXAvYm9vdHN0cmFwL192YXJpYWJsZXMuc2Nzcyc7XG5cbmlucHV0ICsgeG9zLXZhbGlkYXRpb24ge1xuICBtYXJnaW4tdG9wOiAkZm9ybS1ncm91cC1tYXJnaW4tYm90dG9tO1xuICBkaXNwbGF5OiBibG9jaztcbn0iLCJ4b3Mtc21hcnQtdGFibGV7XG4gIFxufSJdLCJtYXBwaW5ncyI6IkFDQUEsVUFBVSxDQUFDLEFBQUEsWUFBWTtFQUNyQixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsdUJBQVc7SUFDdEIsVUFBVSxFQUFFLE9BQVE7RUFHdEIsQUFBQSxFQUFFO0lBQ0EsU0FBUyxFQUFFLG9CQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxhQUFhO0VBQ3RCLEFBQUEsSUFBSTtJQUNGLFNBQVMsRUFBRSxvQkFBVztFQUd4QixBQUFBLEVBQUU7SUFDQSxVQUFVLEVBQUUsTUFBTztJQUNuQixTQUFTLEVBQUUsdUJBQVc7O0FBSTFCLFVBQVUsQ0FBQyxBQUFBLFFBQVE7RUFDakIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsdUJBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsSUFBSzs7QUFJcEIsVUFBVSxDQUFDLEFBQUEsV0FBVztFQUNwQixBQUFBLElBQUk7SUFDRixPQUFPLEVBQUUsQ0FBRTtFQUdiLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXOztBQXpDMUIsVUFBVSxDQUFDLEFBQUEsWUFBWTtFQUNyQixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsdUJBQVc7SUFDdEIsVUFBVSxFQUFFLE9BQVE7RUFHdEIsQUFBQSxFQUFFO0lBQ0EsU0FBUyxFQUFFLG9CQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxhQUFhO0VBQ3RCLEFBQUEsSUFBSTtJQUNGLFNBQVMsRUFBRSxvQkFBVztFQUd4QixBQUFBLEVBQUU7SUFDQSxVQUFVLEVBQUUsTUFBTztJQUNuQixTQUFTLEVBQUUsdUJBQVc7O0FBSTFCLFVBQVUsQ0FBQyxBQUFBLFFBQVE7RUFDakIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsdUJBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsSUFBSzs7QUFJcEIsVUFBVSxDQUFDLEFBQUEsV0FBVztFQUNwQixBQUFBLElBQUk7SUFDRixPQUFPLEVBQUUsQ0FBRTtFQUdiLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXOztBRXZDMUIsQUFBQSxTQUFTLENBQUM7RUFFUixPQUFPLEVBQUUsS0FBTSxHQXVDaEI7RUF6Q0QsQUFJSSxTQUpLLENBSVAsRUFBRSxBQUFBLFFBQVE7RUFKWixBQUtJLFNBTEssQ0FLUCxFQUFFLEFBQUEsU0FBUztFQUxiLEFBTUksU0FOSyxDQU1QLEVBQUUsQUFBQSxTQUFTLENBQUM7SUFDVixVQUFVLEVBQUMsZUFBZ0IsR0FDNUI7RUFSSCxBQVVhLFNBVkosQ0FVUCxFQUFFLEFBQUEsU0FBUyxBQUFBLGdCQUFnQjtFQVY3QixBQVdJLFNBWEssQ0FXUCxFQUFFLEFBQUEsUUFBUTtFQVhaLEFBWUksU0FaSyxDQVlQLEVBQUUsQUFBQSxTQUFTLENBQUM7SUFDVixPQUFPLEVBQUMsQ0FBRTtJQUNWLFNBQVMsRUFBRSw4QkFBK0IsR0FDM0M7RUFmSCxBQWlCSSxTQWpCSyxDQWlCUCxFQUFFLEFBQUEsU0FBUztFQWpCYixBQWtCWSxTQWxCSCxDQWtCUCxFQUFFLEFBQUEsUUFBUSxBQUFBLGVBQWU7RUFsQjNCLEFBbUJhLFNBbkJKLENBbUJQLEVBQUUsQUFBQSxTQUFTLEFBQUEsZ0JBQWdCLENBQUM7SUFDMUIsT0FBTyxFQUFDLENBQUU7SUFDVixTQUFTLEVBQUUsNkJBQThCLEdBQzFDO0VBdEJILEFBd0JLLFNBeEJJLENBd0JQLEVBQUUsQ0FBQyxFQUFFLENBQUM7SUFDSixhQUFhLEVBQUUsQ0FBRSxHQWVsQjtJQXhDSCxBQTJCSSxTQTNCSyxDQXdCUCxFQUFFLENBQUMsRUFBRSxDQUdILEVBQUUsQ0FBQztNQUNELEtBQUssRUFBRSxlQUFnQjtNQUN2QixZQUFZLEVBQUUsSUFBSyxHQUNwQjtJQTlCTCxBQWdDTSxTQWhDRyxDQXdCUCxFQUFFLENBQUMsRUFBRSxDQVFILEVBQUUsQUFBQSxNQUFNLENBQUM7TUFDUCxtQkFBbUI7TUFDbkIsT0FBTyxFQUFFLEdBQUksR0FDZDtJQW5DTCxBQXFDSSxTQXJDSyxDQXdCUCxFQUFFLENBQUMsRUFBRSxDQWFILEVBQUUsQ0FBQztNQUNELFdBQVcsRUFBRSxZQUFhLEdBQzNCOztBRnpDTCxVQUFVLENBQUMsQUFBQSxZQUFZO0VBQ3JCLEFBQUEsSUFBSTtJQUNGLFNBQVMsRUFBRSx1QkFBVztJQUN0QixVQUFVLEVBQUUsT0FBUTtFQUd0QixBQUFBLEVBQUU7SUFDQSxTQUFTLEVBQUUsb0JBQVc7O0FBSTFCLFVBQVUsQ0FBQyxBQUFBLGFBQWE7RUFDdEIsQUFBQSxJQUFJO0lBQ0YsU0FBUyxFQUFFLG9CQUFXO0VBR3hCLEFBQUEsRUFBRTtJQUNBLFVBQVUsRUFBRSxNQUFPO0lBQ25CLFNBQVMsRUFBRSx1QkFBVzs7QUFJMUIsVUFBVSxDQUFDLEFBQUEsUUFBUTtFQUNqQixBQUFBLElBQUk7SUFDRixPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSx1QkFBVztFQUd4QixBQUFBLEVBQUU7SUFDQSxPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSxJQUFLOztBQUlwQixVQUFVLENBQUMsQUFBQSxXQUFXO0VBQ3BCLEFBQUEsSUFBSTtJQUNGLE9BQU8sRUFBRSxDQUFFO0VBR2IsQUFBQSxFQUFFO0lBQ0EsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsdUJBQVc7O0FHdkMxQixBQUFBLFNBQVMsQ0FBQztFQUVSLGlCQUFpQjtFQUdqQixrQkFBa0IsRUFFbkI7RUFQRCxBQUdFLFNBSE8sQ0FHUCxZQUFZLENBQVM7SUFBRSxTQUFTLEVBQUMsNEJBQTZCLEdBQUk7RUFIcEUsQUFNRSxTQU5PLENBTVAsZUFBZSxDQUFNO0lBQUUsU0FBUyxFQUFDLHlCQUEwQixHQUFJOztBSFJqRSxVQUFVLENBQUMsQUFBQSxZQUFZO0VBQ3JCLEFBQUEsSUFBSTtJQUNGLFNBQVMsRUFBRSx1QkFBVztJQUN0QixVQUFVLEVBQUUsT0FBUTtFQUd0QixBQUFBLEVBQUU7SUFDQSxTQUFTLEVBQUUsb0JBQVc7O0FBSTFCLFVBQVUsQ0FBQyxBQUFBLGFBQWE7RUFDdEIsQUFBQSxJQUFJO0lBQ0YsU0FBUyxFQUFFLG9CQUFXO0VBR3hCLEFBQUEsRUFBRTtJQUNBLFVBQVUsRUFBRSxNQUFPO0lBQ25CLFNBQVMsRUFBRSx1QkFBVzs7QUFJMUIsVUFBVSxDQUFDLEFBQUEsUUFBUTtFQUNqQixBQUFBLElBQUk7SUFDRixPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSx1QkFBVztFQUd4QixBQUFBLEVBQUU7SUFDQSxPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSxJQUFLOztBQUlwQixVQUFVLENBQUMsQUFBQSxXQUFXO0VBQ3BCLEFBQUEsSUFBSTtJQUNGLE9BQU8sRUFBRSxDQUFFO0VBR2IsQUFBQSxFQUFFO0lBQ0EsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsdUJBQVc7O0FJdEMxQixBQUFRLEtBQUgsR0FBRyxjQUFjLENBQUM7RUFDckIsVUFBVSxFSHdOcUIsSUFBSTtFR3ZObkMsT0FBTyxFQUFFLEtBQU0sR0FDaEI7O0NMR0QsQUFBQSxBQUFVLFNBQVQsQUFBQSxJQUFZLEFBQUEsQUFBUyxRQUFSLEFBQUEsSUFBVyxBQUFBLEFBQWMsYUFBYixBQUFBLElBQWdCLEFBQUEsQUFBVyxVQUFWLEFBQUEsR0FBYSxBQUFBLFNBQVMsRUFBRSxBQUFBLFdBQVcsQ0FBQztFQUM3RSxPQUFPLEVBQUUsZUFBZ0IsR0FDMUI7O0FBRUQsQUFBTyxJQUFILEdBQUcsSUFBSSxDQUFDO0VBQ1YsMEJBQTBCO0VBQzFCLFVBQVUsRUU2TXFCLElBQUksR0Y1TXBDIiwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== */
+/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieG9zTmdMaWIuY3NzIiwic291cmNlcyI6WyJtYWluLnNjc3MiLCJhbmltYXRpb25zLnNjc3MiLCIuLi8uLi8uLi8uLi9zdHlsZS9zYXNzL2Jvb3RzdHJhcC9ib290c3RyYXAvX3ZhcmlhYmxlcy5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy90YWJsZS90YWJsZS5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy9hbGVydC9hbGVydC5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy92YWxpZGF0aW9uL3ZhbGlkYXRpb24uc2NzcyIsIi4uL3VpX2NvbXBvbmVudHMvZHVtYkNvbXBvbmVudHMvZmllbGQvZmllbGQuc2NzcyIsIi4uL3VpX2NvbXBvbmVudHMvc21hcnRDb21wb25lbnRzL3NtYXJ0VGFibGUvc21hcnRUYWJsZS5zY3NzIl0sInNvdXJjZXNDb250ZW50IjpbIkBpbXBvcnQgJy4vYW5pbWF0aW9ucy5zY3NzJztcbkBpbXBvcnQgJy4uLy4uLy4uLy4uLy4uL3ZpZXdzL3N0eWxlL3Nhc3MvYm9vdHN0cmFwL2Jvb3RzdHJhcC9fdmFyaWFibGVzLnNjc3MnO1xuXG5AaW1wb3J0ICcuLi91aV9jb21wb25lbnRzL2R1bWJDb21wb25lbnRzL3RhYmxlL3RhYmxlLnNjc3MnO1xuQGltcG9ydCAnLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy9hbGVydC9hbGVydC5zY3NzJztcbkBpbXBvcnQgJy4uL3VpX2NvbXBvbmVudHMvZHVtYkNvbXBvbmVudHMvdmFsaWRhdGlvbi92YWxpZGF0aW9uLnNjc3MnO1xuQGltcG9ydCAnLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy9maWVsZC9maWVsZC5zY3NzJztcblxuQGltcG9ydCAnLi4vdWlfY29tcG9uZW50cy9zbWFydENvbXBvbmVudHMvc21hcnRUYWJsZS9zbWFydFRhYmxlLnNjc3MnO1xuXG5bbmdcXDpjbG9ha10sIFtuZy1jbG9ha10sIFtkYXRhLW5nLWNsb2FrXSwgW3gtbmctY2xvYWtdLCAubmctY2xvYWssIC54LW5nLWNsb2FrIHtcbiAgZGlzcGxheTogbm9uZSAhaW1wb3J0YW50O1xufVxuXG4ucm93ICsgLnJvdyB7XG4gIC8qIFRPRE8gbW92ZSBpbiB4b3Muc2NzcyovIFxuICBtYXJnaW4tdG9wOiAkZm9ybS1ncm91cC1tYXJnaW4tYm90dG9tO1xufSIsIkBrZXlmcmFtZXMgc2xpZGVJblJpZ2h0IHtcbiAgZnJvbSB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgxMDAlLCAwLCAwKTtcbiAgICB2aXNpYmlsaXR5OiB2aXNpYmxlO1xuICB9XG5cbiAgdG8ge1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgMCwgMCk7XG4gIH1cbn1cblxuQGtleWZyYW1lcyBzbGlkZU91dFJpZ2h0IHtcbiAgZnJvbSB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAwLCAwKTtcbiAgfVxuXG4gIHRvIHtcbiAgICB2aXNpYmlsaXR5OiBoaWRkZW47XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgxMDAlLCAwLCAwKTtcbiAgfVxufVxuXG5Aa2V5ZnJhbWVzIGZhZGVJblVwIHtcbiAgZnJvbSB7XG4gICAgb3BhY2l0eTogMDtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDEwMCUsIDApO1xuICB9XG5cbiAgdG8ge1xuICAgIG9wYWNpdHk6IDE7XG4gICAgdHJhbnNmb3JtOiBub25lO1xuICB9XG59XG5cbkBrZXlmcmFtZXMgZmFkZU91dERvd24ge1xuICBmcm9tIHtcbiAgICBvcGFjaXR5OiAxO1xuICB9XG5cbiAgdG8ge1xuICAgIG9wYWNpdHk6IDA7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAxMDAlLCAwKTtcbiAgfVxufSIsIiRib290c3RyYXAtc2Fzcy1hc3NldC1oZWxwZXI6IGZhbHNlICFkZWZhdWx0O1xuLy9cbi8vIFZhcmlhYmxlc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXG4vLz09IENvbG9yc1xuLy9cbi8vIyMgR3JheSBhbmQgYnJhbmQgY29sb3JzIGZvciB1c2UgYWNyb3NzIEJvb3RzdHJhcC5cblxuJGdyYXktYmFzZTogICAgICAgICAgICAgICMwMDAgIWRlZmF1bHQ7XG4kZ3JheS1kYXJrZXI6ICAgICAgICAgICAgbGlnaHRlbigkZ3JheS1iYXNlLCAxMy41JSkgIWRlZmF1bHQ7IC8vICMyMjJcbiRncmF5LWRhcms6ICAgICAgICAgICAgICBsaWdodGVuKCRncmF5LWJhc2UsIDIwJSkgIWRlZmF1bHQ7ICAgLy8gIzMzM1xuJGdyYXk6ICAgICAgICAgICAgICAgICAgIGxpZ2h0ZW4oJGdyYXktYmFzZSwgMzMuNSUpICFkZWZhdWx0OyAvLyAjNTU1XG4kZ3JheS1saWdodDogICAgICAgICAgICAgbGlnaHRlbigkZ3JheS1iYXNlLCA0Ni43JSkgIWRlZmF1bHQ7IC8vICM3NzdcbiRncmF5LWxpZ2h0ZXI6ICAgICAgICAgICBsaWdodGVuKCRncmF5LWJhc2UsIDkzLjUlKSAhZGVmYXVsdDsgLy8gI2VlZVxuXG4kYnJhbmQtcHJpbWFyeTogICAgICAgICBkYXJrZW4oIzQyOGJjYSwgNi41JSkgIWRlZmF1bHQ7IC8vICMzMzdhYjdcbiRicmFuZC1zdWNjZXNzOiAgICAgICAgICM1Y2I4NWMgIWRlZmF1bHQ7XG4kYnJhbmQtaW5mbzogICAgICAgICAgICAjNWJjMGRlICFkZWZhdWx0O1xuJGJyYW5kLXdhcm5pbmc6ICAgICAgICAgI2YwYWQ0ZSAhZGVmYXVsdDtcbiRicmFuZC1kYW5nZXI6ICAgICAgICAgICNkOTUzNGYgIWRlZmF1bHQ7XG5cblxuLy89PSBTY2FmZm9sZGluZ1xuLy9cbi8vIyMgU2V0dGluZ3MgZm9yIHNvbWUgb2YgdGhlIG1vc3QgZ2xvYmFsIHN0eWxlcy5cblxuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIGZvciBgPGJvZHk+YC5cbiRib2R5LWJnOiAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIEdsb2JhbCB0ZXh0IGNvbG9yIG9uIGA8Ym9keT5gLlxuJHRleHQtY29sb3I6ICAgICAgICAgICAgJGdyYXktZGFyayAhZGVmYXVsdDtcblxuLy8qKiBHbG9iYWwgdGV4dHVhbCBsaW5rIGNvbG9yLlxuJGxpbmstY29sb3I6ICAgICAgICAgICAgJGJyYW5kLXByaW1hcnkgIWRlZmF1bHQ7XG4vLyoqIExpbmsgaG92ZXIgY29sb3Igc2V0IHZpYSBgZGFya2VuKClgIGZ1bmN0aW9uLlxuJGxpbmstaG92ZXItY29sb3I6ICAgICAgZGFya2VuKCRsaW5rLWNvbG9yLCAxNSUpICFkZWZhdWx0O1xuLy8qKiBMaW5rIGhvdmVyIGRlY29yYXRpb24uXG4kbGluay1ob3Zlci1kZWNvcmF0aW9uOiB1bmRlcmxpbmUgIWRlZmF1bHQ7XG5cblxuLy89PSBUeXBvZ3JhcGh5XG4vL1xuLy8jIyBGb250LCBsaW5lLWhlaWdodCwgYW5kIGNvbG9yIGZvciBib2R5IHRleHQsIGhlYWRpbmdzLCBhbmQgbW9yZS5cblxuJGZvbnQtZmFtaWx5LXNhbnMtc2VyaWY6ICBcIkhlbHZldGljYSBOZXVlXCIsIEhlbHZldGljYSwgQXJpYWwsIHNhbnMtc2VyaWYgIWRlZmF1bHQ7XG4kZm9udC1mYW1pbHktc2VyaWY6ICAgICAgIEdlb3JnaWEsIFwiVGltZXMgTmV3IFJvbWFuXCIsIFRpbWVzLCBzZXJpZiAhZGVmYXVsdDtcbi8vKiogRGVmYXVsdCBtb25vc3BhY2UgZm9udHMgZm9yIGA8Y29kZT5gLCBgPGtiZD5gLCBhbmQgYDxwcmU+YC5cbiRmb250LWZhbWlseS1tb25vc3BhY2U6ICAgTWVubG8sIE1vbmFjbywgQ29uc29sYXMsIFwiQ291cmllciBOZXdcIiwgbW9ub3NwYWNlICFkZWZhdWx0O1xuJGZvbnQtZmFtaWx5LWJhc2U6ICAgICAgICAkZm9udC1mYW1pbHktc2Fucy1zZXJpZiAhZGVmYXVsdDtcblxuJGZvbnQtc2l6ZS1iYXNlOiAgICAgICAgICAxNHB4ICFkZWZhdWx0O1xuJGZvbnQtc2l6ZS1sYXJnZTogICAgICAgICBjZWlsKCgkZm9udC1zaXplLWJhc2UgKiAxLjI1KSkgIWRlZmF1bHQ7IC8vIH4xOHB4XG4kZm9udC1zaXplLXNtYWxsOiAgICAgICAgIGNlaWwoKCRmb250LXNpemUtYmFzZSAqIDAuODUpKSAhZGVmYXVsdDsgLy8gfjEycHhcblxuJGZvbnQtc2l6ZS1oMTogICAgICAgICAgICBmbG9vcigoJGZvbnQtc2l6ZS1iYXNlICogMi42KSkgIWRlZmF1bHQ7IC8vIH4zNnB4XG4kZm9udC1zaXplLWgyOiAgICAgICAgICAgIGZsb29yKCgkZm9udC1zaXplLWJhc2UgKiAyLjE1KSkgIWRlZmF1bHQ7IC8vIH4zMHB4XG4kZm9udC1zaXplLWgzOiAgICAgICAgICAgIGNlaWwoKCRmb250LXNpemUtYmFzZSAqIDEuNykpICFkZWZhdWx0OyAvLyB+MjRweFxuJGZvbnQtc2l6ZS1oNDogICAgICAgICAgICBjZWlsKCgkZm9udC1zaXplLWJhc2UgKiAxLjI1KSkgIWRlZmF1bHQ7IC8vIH4xOHB4XG4kZm9udC1zaXplLWg1OiAgICAgICAgICAgICRmb250LXNpemUtYmFzZSAhZGVmYXVsdDtcbiRmb250LXNpemUtaDY6ICAgICAgICAgICAgY2VpbCgoJGZvbnQtc2l6ZS1iYXNlICogMC44NSkpICFkZWZhdWx0OyAvLyB+MTJweFxuXG4vLyoqIFVuaXQtbGVzcyBgbGluZS1oZWlnaHRgIGZvciB1c2UgaW4gY29tcG9uZW50cyBsaWtlIGJ1dHRvbnMuXG4kbGluZS1oZWlnaHQtYmFzZTogICAgICAgIDEuNDI4NTcxNDI5ICFkZWZhdWx0OyAvLyAyMC8xNFxuLy8qKiBDb21wdXRlZCBcImxpbmUtaGVpZ2h0XCIgKGBmb250LXNpemVgICogYGxpbmUtaGVpZ2h0YCkgZm9yIHVzZSB3aXRoIGBtYXJnaW5gLCBgcGFkZGluZ2AsIGV0Yy5cbiRsaW5lLWhlaWdodC1jb21wdXRlZDogICAgZmxvb3IoKCRmb250LXNpemUtYmFzZSAqICRsaW5lLWhlaWdodC1iYXNlKSkgIWRlZmF1bHQ7IC8vIH4yMHB4XG5cbi8vKiogQnkgZGVmYXVsdCwgdGhpcyBpbmhlcml0cyBmcm9tIHRoZSBgPGJvZHk+YC5cbiRoZWFkaW5ncy1mb250LWZhbWlseTogICAgaW5oZXJpdCAhZGVmYXVsdDtcbiRoZWFkaW5ncy1mb250LXdlaWdodDogICAgNTAwICFkZWZhdWx0O1xuJGhlYWRpbmdzLWxpbmUtaGVpZ2h0OiAgICAxLjEgIWRlZmF1bHQ7XG4kaGVhZGluZ3MtY29sb3I6ICAgICAgICAgIGluaGVyaXQgIWRlZmF1bHQ7XG5cblxuLy89PSBJY29ub2dyYXBoeVxuLy9cbi8vIyMgU3BlY2lmeSBjdXN0b20gbG9jYXRpb24gYW5kIGZpbGVuYW1lIG9mIHRoZSBpbmNsdWRlZCBHbHlwaGljb25zIGljb24gZm9udC4gVXNlZnVsIGZvciB0aG9zZSBpbmNsdWRpbmcgQm9vdHN0cmFwIHZpYSBCb3dlci5cblxuLy8qKiBMb2FkIGZvbnRzIGZyb20gdGhpcyBkaXJlY3RvcnkuXG5cbi8vIFtjb252ZXJ0ZXJdIElmICRib290c3RyYXAtc2Fzcy1hc3NldC1oZWxwZXIgaWYgdXNlZCwgcHJvdmlkZSBwYXRoIHJlbGF0aXZlIHRvIHRoZSBhc3NldHMgbG9hZCBwYXRoLlxuLy8gW2NvbnZlcnRlcl0gVGhpcyBpcyBiZWNhdXNlIHNvbWUgYXNzZXQgaGVscGVycywgc3VjaCBhcyBTcHJvY2tldHMsIGRvIG5vdCB3b3JrIHdpdGggZmlsZS1yZWxhdGl2ZSBwYXRocy5cbiRpY29uLWZvbnQtcGF0aDogaWYoJGJvb3RzdHJhcC1zYXNzLWFzc2V0LWhlbHBlciwgXCJib290c3RyYXAvXCIsIFwiLi4vZm9udHMvYm9vdHN0cmFwL1wiKSAhZGVmYXVsdDtcblxuLy8qKiBGaWxlIG5hbWUgZm9yIGFsbCBmb250IGZpbGVzLlxuJGljb24tZm9udC1uYW1lOiAgICAgICAgICBcImdseXBoaWNvbnMtaGFsZmxpbmdzLXJlZ3VsYXJcIiAhZGVmYXVsdDtcbi8vKiogRWxlbWVudCBJRCB3aXRoaW4gU1ZHIGljb24gZmlsZS5cbiRpY29uLWZvbnQtc3ZnLWlkOiAgICAgICAgXCJnbHlwaGljb25zX2hhbGZsaW5nc3JlZ3VsYXJcIiAhZGVmYXVsdDtcblxuXG4vLz09IENvbXBvbmVudHNcbi8vXG4vLyMjIERlZmluZSBjb21tb24gcGFkZGluZyBhbmQgYm9yZGVyIHJhZGl1cyBzaXplcyBhbmQgbW9yZS4gVmFsdWVzIGJhc2VkIG9uIDE0cHggdGV4dCBhbmQgMS40MjggbGluZS1oZWlnaHQgKH4yMHB4IHRvIHN0YXJ0KS5cblxuJHBhZGRpbmctYmFzZS12ZXJ0aWNhbDogICAgIDZweCAhZGVmYXVsdDtcbiRwYWRkaW5nLWJhc2UtaG9yaXpvbnRhbDogICAxMnB4ICFkZWZhdWx0O1xuXG4kcGFkZGluZy1sYXJnZS12ZXJ0aWNhbDogICAgMTBweCAhZGVmYXVsdDtcbiRwYWRkaW5nLWxhcmdlLWhvcml6b250YWw6ICAxNnB4ICFkZWZhdWx0O1xuXG4kcGFkZGluZy1zbWFsbC12ZXJ0aWNhbDogICAgNXB4ICFkZWZhdWx0O1xuJHBhZGRpbmctc21hbGwtaG9yaXpvbnRhbDogIDEwcHggIWRlZmF1bHQ7XG5cbiRwYWRkaW5nLXhzLXZlcnRpY2FsOiAgICAgICAxcHggIWRlZmF1bHQ7XG4kcGFkZGluZy14cy1ob3Jpem9udGFsOiAgICAgNXB4ICFkZWZhdWx0O1xuXG4kbGluZS1oZWlnaHQtbGFyZ2U6ICAgICAgICAgMS4zMzMzMzMzICFkZWZhdWx0OyAvLyBleHRyYSBkZWNpbWFscyBmb3IgV2luIDguMSBDaHJvbWVcbiRsaW5lLWhlaWdodC1zbWFsbDogICAgICAgICAxLjUgIWRlZmF1bHQ7XG5cbiRib3JkZXItcmFkaXVzLWJhc2U6ICAgICAgICA0cHggIWRlZmF1bHQ7XG4kYm9yZGVyLXJhZGl1cy1sYXJnZTogICAgICAgNnB4ICFkZWZhdWx0O1xuJGJvcmRlci1yYWRpdXMtc21hbGw6ICAgICAgIDNweCAhZGVmYXVsdDtcblxuLy8qKiBHbG9iYWwgY29sb3IgZm9yIGFjdGl2ZSBpdGVtcyAoZS5nLiwgbmF2cyBvciBkcm9wZG93bnMpLlxuJGNvbXBvbmVudC1hY3RpdmUtY29sb3I6ICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIEdsb2JhbCBiYWNrZ3JvdW5kIGNvbG9yIGZvciBhY3RpdmUgaXRlbXMgKGUuZy4sIG5hdnMgb3IgZHJvcGRvd25zKS5cbiRjb21wb25lbnQtYWN0aXZlLWJnOiAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcblxuLy8qKiBXaWR0aCBvZiB0aGUgYGJvcmRlcmAgZm9yIGdlbmVyYXRpbmcgY2FyZXRzIHRoYXQgaW5kaWNhdG9yIGRyb3Bkb3ducy5cbiRjYXJldC13aWR0aC1iYXNlOiAgICAgICAgICA0cHggIWRlZmF1bHQ7XG4vLyoqIENhcmV0cyBpbmNyZWFzZSBzbGlnaHRseSBpbiBzaXplIGZvciBsYXJnZXIgY29tcG9uZW50cy5cbiRjYXJldC13aWR0aC1sYXJnZTogICAgICAgICA1cHggIWRlZmF1bHQ7XG5cblxuLy89PSBUYWJsZXNcbi8vXG4vLyMjIEN1c3RvbWl6ZXMgdGhlIGAudGFibGVgIGNvbXBvbmVudCB3aXRoIGJhc2ljIHZhbHVlcywgZWFjaCB1c2VkIGFjcm9zcyBhbGwgdGFibGUgdmFyaWF0aW9ucy5cblxuLy8qKiBQYWRkaW5nIGZvciBgPHRoPmBzIGFuZCBgPHRkPmBzLlxuJHRhYmxlLWNlbGwtcGFkZGluZzogICAgICAgICAgICA4cHggIWRlZmF1bHQ7XG4vLyoqIFBhZGRpbmcgZm9yIGNlbGxzIGluIGAudGFibGUtY29uZGVuc2VkYC5cbiR0YWJsZS1jb25kZW5zZWQtY2VsbC1wYWRkaW5nOiAgNXB4ICFkZWZhdWx0O1xuXG4vLyoqIERlZmF1bHQgYmFja2dyb3VuZCBjb2xvciB1c2VkIGZvciBhbGwgdGFibGVzLlxuJHRhYmxlLWJnOiAgICAgICAgICAgICAgICAgICAgICB0cmFuc3BhcmVudCAhZGVmYXVsdDtcbi8vKiogQmFja2dyb3VuZCBjb2xvciB1c2VkIGZvciBgLnRhYmxlLXN0cmlwZWRgLlxuJHRhYmxlLWJnLWFjY2VudDogICAgICAgICAgICAgICAjZjlmOWY5ICFkZWZhdWx0O1xuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIHVzZWQgZm9yIGAudGFibGUtaG92ZXJgLlxuJHRhYmxlLWJnLWhvdmVyOiAgICAgICAgICAgICAgICAjZjVmNWY1ICFkZWZhdWx0O1xuJHRhYmxlLWJnLWFjdGl2ZTogICAgICAgICAgICAgICAkdGFibGUtYmctaG92ZXIgIWRlZmF1bHQ7XG5cbi8vKiogQm9yZGVyIGNvbG9yIGZvciB0YWJsZSBhbmQgY2VsbCBib3JkZXJzLlxuJHRhYmxlLWJvcmRlci1jb2xvcjogICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuXG5cbi8vPT0gQnV0dG9uc1xuLy9cbi8vIyMgRm9yIGVhY2ggb2YgQm9vdHN0cmFwJ3MgYnV0dG9ucywgZGVmaW5lIHRleHQsIGJhY2tncm91bmQgYW5kIGJvcmRlciBjb2xvci5cblxuJGJ0bi1mb250LXdlaWdodDogICAgICAgICAgICAgICAgbm9ybWFsICFkZWZhdWx0O1xuXG4kYnRuLWRlZmF1bHQtY29sb3I6ICAgICAgICAgICAgICAjMzMzICFkZWZhdWx0O1xuJGJ0bi1kZWZhdWx0LWJnOiAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRidG4tZGVmYXVsdC1ib3JkZXI6ICAgICAgICAgICAgICNjY2MgIWRlZmF1bHQ7XG5cbiRidG4tcHJpbWFyeS1jb2xvcjogICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kYnRuLXByaW1hcnktYmc6ICAgICAgICAgICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcbiRidG4tcHJpbWFyeS1ib3JkZXI6ICAgICAgICAgICAgIGRhcmtlbigkYnRuLXByaW1hcnktYmcsIDUlKSAhZGVmYXVsdDtcblxuJGJ0bi1zdWNjZXNzLWNvbG9yOiAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRidG4tc3VjY2Vzcy1iZzogICAgICAgICAgICAgICAgICRicmFuZC1zdWNjZXNzICFkZWZhdWx0O1xuJGJ0bi1zdWNjZXNzLWJvcmRlcjogICAgICAgICAgICAgZGFya2VuKCRidG4tc3VjY2Vzcy1iZywgNSUpICFkZWZhdWx0O1xuXG4kYnRuLWluZm8tY29sb3I6ICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGJ0bi1pbmZvLWJnOiAgICAgICAgICAgICAgICAgICAgJGJyYW5kLWluZm8gIWRlZmF1bHQ7XG4kYnRuLWluZm8tYm9yZGVyOiAgICAgICAgICAgICAgICBkYXJrZW4oJGJ0bi1pbmZvLWJnLCA1JSkgIWRlZmF1bHQ7XG5cbiRidG4td2FybmluZy1jb2xvcjogICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kYnRuLXdhcm5pbmctYmc6ICAgICAgICAgICAgICAgICAkYnJhbmQtd2FybmluZyAhZGVmYXVsdDtcbiRidG4td2FybmluZy1ib3JkZXI6ICAgICAgICAgICAgIGRhcmtlbigkYnRuLXdhcm5pbmctYmcsIDUlKSAhZGVmYXVsdDtcblxuJGJ0bi1kYW5nZXItY29sb3I6ICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRidG4tZGFuZ2VyLWJnOiAgICAgICAgICAgICAgICAgICRicmFuZC1kYW5nZXIgIWRlZmF1bHQ7XG4kYnRuLWRhbmdlci1ib3JkZXI6ICAgICAgICAgICAgICBkYXJrZW4oJGJ0bi1kYW5nZXItYmcsIDUlKSAhZGVmYXVsdDtcblxuJGJ0bi1saW5rLWRpc2FibGVkLWNvbG9yOiAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG5cbi8vIEFsbG93cyBmb3IgY3VzdG9taXppbmcgYnV0dG9uIHJhZGl1cyBpbmRlcGVuZGVudGx5IGZyb20gZ2xvYmFsIGJvcmRlciByYWRpdXNcbiRidG4tYm9yZGVyLXJhZGl1cy1iYXNlOiAgICAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG4kYnRuLWJvcmRlci1yYWRpdXMtbGFyZ2U6ICAgICAgICAkYm9yZGVyLXJhZGl1cy1sYXJnZSAhZGVmYXVsdDtcbiRidG4tYm9yZGVyLXJhZGl1cy1zbWFsbDogICAgICAgICRib3JkZXItcmFkaXVzLXNtYWxsICFkZWZhdWx0O1xuXG5cbi8vPT0gRm9ybXNcbi8vXG4vLyMjXG5cbi8vKiogYDxpbnB1dD5gIGJhY2tncm91bmQgY29sb3JcbiRpbnB1dC1iZzogICAgICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIGA8aW5wdXQgZGlzYWJsZWQ+YCBiYWNrZ3JvdW5kIGNvbG9yXG4kaW5wdXQtYmctZGlzYWJsZWQ6ICAgICAgICAgICAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuXG4vLyoqIFRleHQgY29sb3IgZm9yIGA8aW5wdXQ+YHNcbiRpbnB1dC1jb2xvcjogICAgICAgICAgICAgICAgICAgICRncmF5ICFkZWZhdWx0O1xuLy8qKiBgPGlucHV0PmAgYm9yZGVyIGNvbG9yXG4kaW5wdXQtYm9yZGVyOiAgICAgICAgICAgICAgICAgICAjY2NjICFkZWZhdWx0O1xuXG4vLyBUT0RPOiBSZW5hbWUgYCRpbnB1dC1ib3JkZXItcmFkaXVzYCB0byBgJGlucHV0LWJvcmRlci1yYWRpdXMtYmFzZWAgaW4gdjRcbi8vKiogRGVmYXVsdCBgLmZvcm0tY29udHJvbGAgYm9yZGVyIHJhZGl1c1xuLy8gVGhpcyBoYXMgbm8gZWZmZWN0IG9uIGA8c2VsZWN0PmBzIGluIHNvbWUgYnJvd3NlcnMsIGR1ZSB0byB0aGUgbGltaXRlZCBzdHlsYWJpbGl0eSBvZiBgPHNlbGVjdD5gcyBpbiBDU1MuXG4kaW5wdXQtYm9yZGVyLXJhZGl1czogICAgICAgICAgICAkYm9yZGVyLXJhZGl1cy1iYXNlICFkZWZhdWx0O1xuLy8qKiBMYXJnZSBgLmZvcm0tY29udHJvbGAgYm9yZGVyIHJhZGl1c1xuJGlucHV0LWJvcmRlci1yYWRpdXMtbGFyZ2U6ICAgICAgJGJvcmRlci1yYWRpdXMtbGFyZ2UgIWRlZmF1bHQ7XG4vLyoqIFNtYWxsIGAuZm9ybS1jb250cm9sYCBib3JkZXIgcmFkaXVzXG4kaW5wdXQtYm9yZGVyLXJhZGl1cy1zbWFsbDogICAgICAkYm9yZGVyLXJhZGl1cy1zbWFsbCAhZGVmYXVsdDtcblxuLy8qKiBCb3JkZXIgY29sb3IgZm9yIGlucHV0cyBvbiBmb2N1c1xuJGlucHV0LWJvcmRlci1mb2N1czogICAgICAgICAgICAgIzY2YWZlOSAhZGVmYXVsdDtcblxuLy8qKiBQbGFjZWhvbGRlciB0ZXh0IGNvbG9yXG4kaW5wdXQtY29sb3ItcGxhY2Vob2xkZXI6ICAgICAgICAjOTk5ICFkZWZhdWx0O1xuXG4vLyoqIERlZmF1bHQgYC5mb3JtLWNvbnRyb2xgIGhlaWdodFxuJGlucHV0LWhlaWdodC1iYXNlOiAgICAgICAgICAgICAgKCRsaW5lLWhlaWdodC1jb21wdXRlZCArICgkcGFkZGluZy1iYXNlLXZlcnRpY2FsICogMikgKyAyKSAhZGVmYXVsdDtcbi8vKiogTGFyZ2UgYC5mb3JtLWNvbnRyb2xgIGhlaWdodFxuJGlucHV0LWhlaWdodC1sYXJnZTogICAgICAgICAgICAgKGNlaWwoJGZvbnQtc2l6ZS1sYXJnZSAqICRsaW5lLWhlaWdodC1sYXJnZSkgKyAoJHBhZGRpbmctbGFyZ2UtdmVydGljYWwgKiAyKSArIDIpICFkZWZhdWx0O1xuLy8qKiBTbWFsbCBgLmZvcm0tY29udHJvbGAgaGVpZ2h0XG4kaW5wdXQtaGVpZ2h0LXNtYWxsOiAgICAgICAgICAgICAoZmxvb3IoJGZvbnQtc2l6ZS1zbWFsbCAqICRsaW5lLWhlaWdodC1zbWFsbCkgKyAoJHBhZGRpbmctc21hbGwtdmVydGljYWwgKiAyKSArIDIpICFkZWZhdWx0O1xuXG4vLyoqIGAuZm9ybS1ncm91cGAgbWFyZ2luXG4kZm9ybS1ncm91cC1tYXJnaW4tYm90dG9tOiAgICAgICAxNXB4ICFkZWZhdWx0O1xuXG4kbGVnZW5kLWNvbG9yOiAgICAgICAgICAgICAgICAgICAkZ3JheS1kYXJrICFkZWZhdWx0O1xuJGxlZ2VuZC1ib3JkZXItY29sb3I6ICAgICAgICAgICAgI2U1ZTVlNSAhZGVmYXVsdDtcblxuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIGZvciB0ZXh0dWFsIGlucHV0IGFkZG9uc1xuJGlucHV0LWdyb3VwLWFkZG9uLWJnOiAgICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbi8vKiogQm9yZGVyIGNvbG9yIGZvciB0ZXh0dWFsIGlucHV0IGFkZG9uc1xuJGlucHV0LWdyb3VwLWFkZG9uLWJvcmRlci1jb2xvcjogJGlucHV0LWJvcmRlciAhZGVmYXVsdDtcblxuLy8qKiBEaXNhYmxlZCBjdXJzb3IgZm9yIGZvcm0gY29udHJvbHMgYW5kIGJ1dHRvbnMuXG4kY3Vyc29yLWRpc2FibGVkOiAgICAgICAgICAgICAgICBub3QtYWxsb3dlZCAhZGVmYXVsdDtcblxuXG4vLz09IERyb3Bkb3duc1xuLy9cbi8vIyMgRHJvcGRvd24gbWVudSBjb250YWluZXIgYW5kIGNvbnRlbnRzLlxuXG4vLyoqIEJhY2tncm91bmQgZm9yIHRoZSBkcm9wZG93biBtZW51LlxuJGRyb3Bkb3duLWJnOiAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogRHJvcGRvd24gbWVudSBgYm9yZGVyLWNvbG9yYC5cbiRkcm9wZG93bi1ib3JkZXI6ICAgICAgICAgICAgICAgIHJnYmEoMCwwLDAsLjE1KSAhZGVmYXVsdDtcbi8vKiogRHJvcGRvd24gbWVudSBgYm9yZGVyLWNvbG9yYCAqKmZvciBJRTgqKi5cbiRkcm9wZG93bi1mYWxsYmFjay1ib3JkZXI6ICAgICAgICNjY2MgIWRlZmF1bHQ7XG4vLyoqIERpdmlkZXIgY29sb3IgZm9yIGJldHdlZW4gZHJvcGRvd24gaXRlbXMuXG4kZHJvcGRvd24tZGl2aWRlci1iZzogICAgICAgICAgICAjZTVlNWU1ICFkZWZhdWx0O1xuXG4vLyoqIERyb3Bkb3duIGxpbmsgdGV4dCBjb2xvci5cbiRkcm9wZG93bi1saW5rLWNvbG9yOiAgICAgICAgICAgICRncmF5LWRhcmsgIWRlZmF1bHQ7XG4vLyoqIEhvdmVyIGNvbG9yIGZvciBkcm9wZG93biBsaW5rcy5cbiRkcm9wZG93bi1saW5rLWhvdmVyLWNvbG9yOiAgICAgIGRhcmtlbigkZ3JheS1kYXJrLCA1JSkgIWRlZmF1bHQ7XG4vLyoqIEhvdmVyIGJhY2tncm91bmQgZm9yIGRyb3Bkb3duIGxpbmtzLlxuJGRyb3Bkb3duLWxpbmstaG92ZXItYmc6ICAgICAgICAgI2Y1ZjVmNSAhZGVmYXVsdDtcblxuLy8qKiBBY3RpdmUgZHJvcGRvd24gbWVudSBpdGVtIHRleHQgY29sb3IuXG4kZHJvcGRvd24tbGluay1hY3RpdmUtY29sb3I6ICAgICAkY29tcG9uZW50LWFjdGl2ZS1jb2xvciAhZGVmYXVsdDtcbi8vKiogQWN0aXZlIGRyb3Bkb3duIG1lbnUgaXRlbSBiYWNrZ3JvdW5kIGNvbG9yLlxuJGRyb3Bkb3duLWxpbmstYWN0aXZlLWJnOiAgICAgICAgJGNvbXBvbmVudC1hY3RpdmUtYmcgIWRlZmF1bHQ7XG5cbi8vKiogRGlzYWJsZWQgZHJvcGRvd24gbWVudSBpdGVtIGJhY2tncm91bmQgY29sb3IuXG4kZHJvcGRvd24tbGluay1kaXNhYmxlZC1jb2xvcjogICAkZ3JheS1saWdodCAhZGVmYXVsdDtcblxuLy8qKiBUZXh0IGNvbG9yIGZvciBoZWFkZXJzIHdpdGhpbiBkcm9wZG93biBtZW51cy5cbiRkcm9wZG93bi1oZWFkZXItY29sb3I6ICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuXG4vLyoqIERlcHJlY2F0ZWQgYCRkcm9wZG93bi1jYXJldC1jb2xvcmAgYXMgb2YgdjMuMS4wXG4kZHJvcGRvd24tY2FyZXQtY29sb3I6ICAgICAgICAgICAjMDAwICFkZWZhdWx0O1xuXG5cbi8vLS0gWi1pbmRleCBtYXN0ZXIgbGlzdFxuLy9cbi8vIFdhcm5pbmc6IEF2b2lkIGN1c3RvbWl6aW5nIHRoZXNlIHZhbHVlcy4gVGhleSdyZSB1c2VkIGZvciBhIGJpcmQncyBleWUgdmlld1xuLy8gb2YgY29tcG9uZW50cyBkZXBlbmRlbnQgb24gdGhlIHotYXhpcyBhbmQgYXJlIGRlc2lnbmVkIHRvIGFsbCB3b3JrIHRvZ2V0aGVyLlxuLy9cbi8vIE5vdGU6IFRoZXNlIHZhcmlhYmxlcyBhcmUgbm90IGdlbmVyYXRlZCBpbnRvIHRoZSBDdXN0b21pemVyLlxuXG4kemluZGV4LW5hdmJhcjogICAgICAgICAgICAxMDAwICFkZWZhdWx0O1xuJHppbmRleC1kcm9wZG93bjogICAgICAgICAgMTAwMCAhZGVmYXVsdDtcbiR6aW5kZXgtcG9wb3ZlcjogICAgICAgICAgIDEwNjAgIWRlZmF1bHQ7XG4kemluZGV4LXRvb2x0aXA6ICAgICAgICAgICAxMDcwICFkZWZhdWx0O1xuJHppbmRleC1uYXZiYXItZml4ZWQ6ICAgICAgMTAzMCAhZGVmYXVsdDtcbiR6aW5kZXgtbW9kYWwtYmFja2dyb3VuZDogIDEwNDAgIWRlZmF1bHQ7XG4kemluZGV4LW1vZGFsOiAgICAgICAgICAgICAxMDUwICFkZWZhdWx0O1xuXG5cbi8vPT0gTWVkaWEgcXVlcmllcyBicmVha3BvaW50c1xuLy9cbi8vIyMgRGVmaW5lIHRoZSBicmVha3BvaW50cyBhdCB3aGljaCB5b3VyIGxheW91dCB3aWxsIGNoYW5nZSwgYWRhcHRpbmcgdG8gZGlmZmVyZW50IHNjcmVlbiBzaXplcy5cblxuLy8gRXh0cmEgc21hbGwgc2NyZWVuIC8gcGhvbmVcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi14c2AgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLXhzOiAgICAgICAgICAgICAgICAgIDQ4MHB4ICFkZWZhdWx0O1xuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLXhzLW1pbmAgYXMgb2YgdjMuMi4wXG4kc2NyZWVuLXhzLW1pbjogICAgICAgICAgICAgICRzY3JlZW4teHMgIWRlZmF1bHQ7XG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4tcGhvbmVgIGFzIG9mIHYzLjAuMVxuJHNjcmVlbi1waG9uZTogICAgICAgICAgICAgICAkc2NyZWVuLXhzLW1pbiAhZGVmYXVsdDtcblxuLy8gU21hbGwgc2NyZWVuIC8gdGFibGV0XG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4tc21gIGFzIG9mIHYzLjAuMVxuJHNjcmVlbi1zbTogICAgICAgICAgICAgICAgICA3NjhweCAhZGVmYXVsdDtcbiRzY3JlZW4tc20tbWluOiAgICAgICAgICAgICAgJHNjcmVlbi1zbSAhZGVmYXVsdDtcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi10YWJsZXRgIGFzIG9mIHYzLjAuMVxuJHNjcmVlbi10YWJsZXQ6ICAgICAgICAgICAgICAkc2NyZWVuLXNtLW1pbiAhZGVmYXVsdDtcblxuLy8gTWVkaXVtIHNjcmVlbiAvIGRlc2t0b3Bcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi1tZGAgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLW1kOiAgICAgICAgICAgICAgICAgIDk5MnB4ICFkZWZhdWx0O1xuJHNjcmVlbi1tZC1taW46ICAgICAgICAgICAgICAkc2NyZWVuLW1kICFkZWZhdWx0O1xuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLWRlc2t0b3BgIGFzIG9mIHYzLjAuMVxuJHNjcmVlbi1kZXNrdG9wOiAgICAgICAgICAgICAkc2NyZWVuLW1kLW1pbiAhZGVmYXVsdDtcblxuLy8gTGFyZ2Ugc2NyZWVuIC8gd2lkZSBkZXNrdG9wXG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4tbGdgIGFzIG9mIHYzLjAuMVxuJHNjcmVlbi1sZzogICAgICAgICAgICAgICAgICAxMjAwcHggIWRlZmF1bHQ7XG4kc2NyZWVuLWxnLW1pbjogICAgICAgICAgICAgICRzY3JlZW4tbGcgIWRlZmF1bHQ7XG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4tbGctZGVza3RvcGAgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLWxnLWRlc2t0b3A6ICAgICAgICAgICRzY3JlZW4tbGctbWluICFkZWZhdWx0O1xuXG4vLyBTbyBtZWRpYSBxdWVyaWVzIGRvbid0IG92ZXJsYXAgd2hlbiByZXF1aXJlZCwgcHJvdmlkZSBhIG1heGltdW1cbiRzY3JlZW4teHMtbWF4OiAgICAgICAgICAgICAgKCRzY3JlZW4tc20tbWluIC0gMSkgIWRlZmF1bHQ7XG4kc2NyZWVuLXNtLW1heDogICAgICAgICAgICAgICgkc2NyZWVuLW1kLW1pbiAtIDEpICFkZWZhdWx0O1xuJHNjcmVlbi1tZC1tYXg6ICAgICAgICAgICAgICAoJHNjcmVlbi1sZy1taW4gLSAxKSAhZGVmYXVsdDtcblxuXG4vLz09IEdyaWQgc3lzdGVtXG4vL1xuLy8jIyBEZWZpbmUgeW91ciBjdXN0b20gcmVzcG9uc2l2ZSBncmlkLlxuXG4vLyoqIE51bWJlciBvZiBjb2x1bW5zIGluIHRoZSBncmlkLlxuJGdyaWQtY29sdW1uczogICAgICAgICAgICAgIDEyICFkZWZhdWx0O1xuLy8qKiBQYWRkaW5nIGJldHdlZW4gY29sdW1ucy4gR2V0cyBkaXZpZGVkIGluIGhhbGYgZm9yIHRoZSBsZWZ0IGFuZCByaWdodC5cbiRncmlkLWd1dHRlci13aWR0aDogICAgICAgICAzMHB4ICFkZWZhdWx0O1xuLy8gTmF2YmFyIGNvbGxhcHNlXG4vLyoqIFBvaW50IGF0IHdoaWNoIHRoZSBuYXZiYXIgYmVjb21lcyB1bmNvbGxhcHNlZC5cbiRncmlkLWZsb2F0LWJyZWFrcG9pbnQ6ICAgICAkc2NyZWVuLXNtLW1pbiAhZGVmYXVsdDtcbi8vKiogUG9pbnQgYXQgd2hpY2ggdGhlIG5hdmJhciBiZWdpbnMgY29sbGFwc2luZy5cbiRncmlkLWZsb2F0LWJyZWFrcG9pbnQtbWF4OiAoJGdyaWQtZmxvYXQtYnJlYWtwb2ludCAtIDEpICFkZWZhdWx0O1xuXG5cbi8vPT0gQ29udGFpbmVyIHNpemVzXG4vL1xuLy8jIyBEZWZpbmUgdGhlIG1heGltdW0gd2lkdGggb2YgYC5jb250YWluZXJgIGZvciBkaWZmZXJlbnQgc2NyZWVuIHNpemVzLlxuXG4vLyBTbWFsbCBzY3JlZW4gLyB0YWJsZXRcbiRjb250YWluZXItdGFibGV0OiAgICAgICAgICAgICAoNzIwcHggKyAkZ3JpZC1ndXR0ZXItd2lkdGgpICFkZWZhdWx0O1xuLy8qKiBGb3IgYCRzY3JlZW4tc20tbWluYCBhbmQgdXAuXG4kY29udGFpbmVyLXNtOiAgICAgICAgICAgICAgICAgJGNvbnRhaW5lci10YWJsZXQgIWRlZmF1bHQ7XG5cbi8vIE1lZGl1bSBzY3JlZW4gLyBkZXNrdG9wXG4kY29udGFpbmVyLWRlc2t0b3A6ICAgICAgICAgICAgKDk0MHB4ICsgJGdyaWQtZ3V0dGVyLXdpZHRoKSAhZGVmYXVsdDtcbi8vKiogRm9yIGAkc2NyZWVuLW1kLW1pbmAgYW5kIHVwLlxuJGNvbnRhaW5lci1tZDogICAgICAgICAgICAgICAgICRjb250YWluZXItZGVza3RvcCAhZGVmYXVsdDtcblxuLy8gTGFyZ2Ugc2NyZWVuIC8gd2lkZSBkZXNrdG9wXG4kY29udGFpbmVyLWxhcmdlLWRlc2t0b3A6ICAgICAgKDExNDBweCArICRncmlkLWd1dHRlci13aWR0aCkgIWRlZmF1bHQ7XG4vLyoqIEZvciBgJHNjcmVlbi1sZy1taW5gIGFuZCB1cC5cbiRjb250YWluZXItbGc6ICAgICAgICAgICAgICAgICAkY29udGFpbmVyLWxhcmdlLWRlc2t0b3AgIWRlZmF1bHQ7XG5cblxuLy89PSBOYXZiYXJcbi8vXG4vLyMjXG5cbi8vIEJhc2ljcyBvZiBhIG5hdmJhclxuJG5hdmJhci1oZWlnaHQ6ICAgICAgICAgICAgICAgICAgICA1MHB4ICFkZWZhdWx0O1xuJG5hdmJhci1tYXJnaW4tYm90dG9tOiAgICAgICAgICAgICAkbGluZS1oZWlnaHQtY29tcHV0ZWQgIWRlZmF1bHQ7XG4kbmF2YmFyLWJvcmRlci1yYWRpdXM6ICAgICAgICAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG4kbmF2YmFyLXBhZGRpbmctaG9yaXpvbnRhbDogICAgICAgIGZsb29yKCgkZ3JpZC1ndXR0ZXItd2lkdGggLyAyKSkgIWRlZmF1bHQ7XG4kbmF2YmFyLXBhZGRpbmctdmVydGljYWw6ICAgICAgICAgICgoJG5hdmJhci1oZWlnaHQgLSAkbGluZS1oZWlnaHQtY29tcHV0ZWQpIC8gMikgIWRlZmF1bHQ7XG4kbmF2YmFyLWNvbGxhcHNlLW1heC1oZWlnaHQ6ICAgICAgIDM0MHB4ICFkZWZhdWx0O1xuXG4kbmF2YmFyLWRlZmF1bHQtY29sb3I6ICAgICAgICAgICAgICM3NzcgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtYmc6ICAgICAgICAgICAgICAgICNmOGY4ZjggIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtYm9yZGVyOiAgICAgICAgICAgIGRhcmtlbigkbmF2YmFyLWRlZmF1bHQtYmcsIDYuNSUpICFkZWZhdWx0O1xuXG4vLyBOYXZiYXIgbGlua3NcbiRuYXZiYXItZGVmYXVsdC1saW5rLWNvbG9yOiAgICAgICAgICAgICAgICAjNzc3ICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWxpbmstaG92ZXItY29sb3I6ICAgICAgICAgICMzMzMgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtbGluay1ob3Zlci1iZzogICAgICAgICAgICAgdHJhbnNwYXJlbnQgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtbGluay1hY3RpdmUtY29sb3I6ICAgICAgICAgIzU1NSAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1saW5rLWFjdGl2ZS1iZzogICAgICAgICAgICBkYXJrZW4oJG5hdmJhci1kZWZhdWx0LWJnLCA2LjUlKSAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1saW5rLWRpc2FibGVkLWNvbG9yOiAgICAgICAjY2NjICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWxpbmstZGlzYWJsZWQtYmc6ICAgICAgICAgIHRyYW5zcGFyZW50ICFkZWZhdWx0O1xuXG4vLyBOYXZiYXIgYnJhbmQgbGFiZWxcbiRuYXZiYXItZGVmYXVsdC1icmFuZC1jb2xvcjogICAgICAgICAgICAgICAkbmF2YmFyLWRlZmF1bHQtbGluay1jb2xvciAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1icmFuZC1ob3Zlci1jb2xvcjogICAgICAgICBkYXJrZW4oJG5hdmJhci1kZWZhdWx0LWJyYW5kLWNvbG9yLCAxMCUpICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWJyYW5kLWhvdmVyLWJnOiAgICAgICAgICAgIHRyYW5zcGFyZW50ICFkZWZhdWx0O1xuXG4vLyBOYXZiYXIgdG9nZ2xlXG4kbmF2YmFyLWRlZmF1bHQtdG9nZ2xlLWhvdmVyLWJnOiAgICAgICAgICAgI2RkZCAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC10b2dnbGUtaWNvbi1iYXItYmc6ICAgICAgICAjODg4ICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LXRvZ2dsZS1ib3JkZXItY29sb3I6ICAgICAgICNkZGQgIWRlZmF1bHQ7XG5cblxuLy89PT0gSW52ZXJ0ZWQgbmF2YmFyXG4vLyBSZXNldCBpbnZlcnRlZCBuYXZiYXIgYmFzaWNzXG4kbmF2YmFyLWludmVyc2UtY29sb3I6ICAgICAgICAgICAgICAgICAgICAgIGxpZ2h0ZW4oJGdyYXktbGlnaHQsIDE1JSkgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtYmc6ICAgICAgICAgICAgICAgICAgICAgICAgICMyMjIgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtYm9yZGVyOiAgICAgICAgICAgICAgICAgICAgIGRhcmtlbigkbmF2YmFyLWludmVyc2UtYmcsIDEwJSkgIWRlZmF1bHQ7XG5cbi8vIEludmVydGVkIG5hdmJhciBsaW5rc1xuJG5hdmJhci1pbnZlcnNlLWxpbmstY29sb3I6ICAgICAgICAgICAgICAgICBsaWdodGVuKCRncmF5LWxpZ2h0LCAxNSUpICFkZWZhdWx0O1xuJG5hdmJhci1pbnZlcnNlLWxpbmstaG92ZXItY29sb3I6ICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJG5hdmJhci1pbnZlcnNlLWxpbmstaG92ZXItYmc6ICAgICAgICAgICAgICB0cmFuc3BhcmVudCAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1saW5rLWFjdGl2ZS1jb2xvcjogICAgICAgICAgJG5hdmJhci1pbnZlcnNlLWxpbmstaG92ZXItY29sb3IgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtbGluay1hY3RpdmUtYmc6ICAgICAgICAgICAgIGRhcmtlbigkbmF2YmFyLWludmVyc2UtYmcsIDEwJSkgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtbGluay1kaXNhYmxlZC1jb2xvcjogICAgICAgICM0NDQgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtbGluay1kaXNhYmxlZC1iZzogICAgICAgICAgIHRyYW5zcGFyZW50ICFkZWZhdWx0O1xuXG4vLyBJbnZlcnRlZCBuYXZiYXIgYnJhbmQgbGFiZWxcbiRuYXZiYXItaW52ZXJzZS1icmFuZC1jb2xvcjogICAgICAgICAgICAgICAgJG5hdmJhci1pbnZlcnNlLWxpbmstY29sb3IgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtYnJhbmQtaG92ZXItY29sb3I6ICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtYnJhbmQtaG92ZXItYmc6ICAgICAgICAgICAgIHRyYW5zcGFyZW50ICFkZWZhdWx0O1xuXG4vLyBJbnZlcnRlZCBuYXZiYXIgdG9nZ2xlXG4kbmF2YmFyLWludmVyc2UtdG9nZ2xlLWhvdmVyLWJnOiAgICAgICAgICAgICMzMzMgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtdG9nZ2xlLWljb24tYmFyLWJnOiAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtdG9nZ2xlLWJvcmRlci1jb2xvcjogICAgICAgICMzMzMgIWRlZmF1bHQ7XG5cblxuLy89PSBOYXZzXG4vL1xuLy8jI1xuXG4vLz09PSBTaGFyZWQgbmF2IHN0eWxlc1xuJG5hdi1saW5rLXBhZGRpbmc6ICAgICAgICAgICAgICAgICAgICAgICAgICAxMHB4IDE1cHggIWRlZmF1bHQ7XG4kbmF2LWxpbmstaG92ZXItYmc6ICAgICAgICAgICAgICAgICAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG5cbiRuYXYtZGlzYWJsZWQtbGluay1jb2xvcjogICAgICAgICAgICAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG4kbmF2LWRpc2FibGVkLWxpbmstaG92ZXItY29sb3I6ICAgICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuXG4vLz09IFRhYnNcbiRuYXYtdGFicy1ib3JkZXItY29sb3I6ICAgICAgICAgICAgICAgICAgICAgI2RkZCAhZGVmYXVsdDtcblxuJG5hdi10YWJzLWxpbmstaG92ZXItYm9yZGVyLWNvbG9yOiAgICAgICAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuXG4kbmF2LXRhYnMtYWN0aXZlLWxpbmstaG92ZXItYmc6ICAgICAgICAgICAgICRib2R5LWJnICFkZWZhdWx0O1xuJG5hdi10YWJzLWFjdGl2ZS1saW5rLWhvdmVyLWNvbG9yOiAgICAgICAgICAkZ3JheSAhZGVmYXVsdDtcbiRuYXYtdGFicy1hY3RpdmUtbGluay1ob3Zlci1ib3JkZXItY29sb3I6ICAgI2RkZCAhZGVmYXVsdDtcblxuJG5hdi10YWJzLWp1c3RpZmllZC1saW5rLWJvcmRlci1jb2xvcjogICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuJG5hdi10YWJzLWp1c3RpZmllZC1hY3RpdmUtbGluay1ib3JkZXItY29sb3I6ICAgICAkYm9keS1iZyAhZGVmYXVsdDtcblxuLy89PSBQaWxsc1xuJG5hdi1waWxscy1ib3JkZXItcmFkaXVzOiAgICAgICAgICAgICAgICAgICAkYm9yZGVyLXJhZGl1cy1iYXNlICFkZWZhdWx0O1xuJG5hdi1waWxscy1hY3RpdmUtbGluay1ob3Zlci1iZzogICAgICAgICAgICAkY29tcG9uZW50LWFjdGl2ZS1iZyAhZGVmYXVsdDtcbiRuYXYtcGlsbHMtYWN0aXZlLWxpbmstaG92ZXItY29sb3I6ICAgICAgICAgJGNvbXBvbmVudC1hY3RpdmUtY29sb3IgIWRlZmF1bHQ7XG5cblxuLy89PSBQYWdpbmF0aW9uXG4vL1xuLy8jI1xuXG4kcGFnaW5hdGlvbi1jb2xvcjogICAgICAgICAgICAgICAgICAgICAkbGluay1jb2xvciAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWJnOiAgICAgICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kcGFnaW5hdGlvbi1ib3JkZXI6ICAgICAgICAgICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuXG4kcGFnaW5hdGlvbi1ob3Zlci1jb2xvcjogICAgICAgICAgICAgICAkbGluay1ob3Zlci1jb2xvciAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWhvdmVyLWJnOiAgICAgICAgICAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG4kcGFnaW5hdGlvbi1ob3Zlci1ib3JkZXI6ICAgICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuXG4kcGFnaW5hdGlvbi1hY3RpdmUtY29sb3I6ICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJHBhZ2luYXRpb24tYWN0aXZlLWJnOiAgICAgICAgICAgICAgICAgJGJyYW5kLXByaW1hcnkgIWRlZmF1bHQ7XG4kcGFnaW5hdGlvbi1hY3RpdmUtYm9yZGVyOiAgICAgICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcblxuJHBhZ2luYXRpb24tZGlzYWJsZWQtY29sb3I6ICAgICAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG4kcGFnaW5hdGlvbi1kaXNhYmxlZC1iZzogICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJHBhZ2luYXRpb24tZGlzYWJsZWQtYm9yZGVyOiAgICAgICAgICAgI2RkZCAhZGVmYXVsdDtcblxuXG4vLz09IFBhZ2VyXG4vL1xuLy8jI1xuXG4kcGFnZXItYmc6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkcGFnaW5hdGlvbi1iZyAhZGVmYXVsdDtcbiRwYWdlci1ib3JkZXI6ICAgICAgICAgICAgICAgICAgICAgICAgICRwYWdpbmF0aW9uLWJvcmRlciAhZGVmYXVsdDtcbiRwYWdlci1ib3JkZXItcmFkaXVzOiAgICAgICAgICAgICAgICAgIDE1cHggIWRlZmF1bHQ7XG5cbiRwYWdlci1ob3Zlci1iZzogICAgICAgICAgICAgICAgICAgICAgICRwYWdpbmF0aW9uLWhvdmVyLWJnICFkZWZhdWx0O1xuXG4kcGFnZXItYWN0aXZlLWJnOiAgICAgICAgICAgICAgICAgICAgICAkcGFnaW5hdGlvbi1hY3RpdmUtYmcgIWRlZmF1bHQ7XG4kcGFnZXItYWN0aXZlLWNvbG9yOiAgICAgICAgICAgICAgICAgICAkcGFnaW5hdGlvbi1hY3RpdmUtY29sb3IgIWRlZmF1bHQ7XG5cbiRwYWdlci1kaXNhYmxlZC1jb2xvcjogICAgICAgICAgICAgICAgICRwYWdpbmF0aW9uLWRpc2FibGVkLWNvbG9yICFkZWZhdWx0O1xuXG5cbi8vPT0gSnVtYm90cm9uXG4vL1xuLy8jI1xuXG4kanVtYm90cm9uLXBhZGRpbmc6ICAgICAgICAgICAgICAzMHB4ICFkZWZhdWx0O1xuJGp1bWJvdHJvbi1jb2xvcjogICAgICAgICAgICAgICAgaW5oZXJpdCAhZGVmYXVsdDtcbiRqdW1ib3Ryb24tYmc6ICAgICAgICAgICAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG4kanVtYm90cm9uLWhlYWRpbmctY29sb3I6ICAgICAgICBpbmhlcml0ICFkZWZhdWx0O1xuJGp1bWJvdHJvbi1mb250LXNpemU6ICAgICAgICAgICAgY2VpbCgoJGZvbnQtc2l6ZS1iYXNlICogMS41KSkgIWRlZmF1bHQ7XG4kanVtYm90cm9uLWhlYWRpbmctZm9udC1zaXplOiAgICBjZWlsKCgkZm9udC1zaXplLWJhc2UgKiA0LjUpKSAhZGVmYXVsdDtcblxuXG4vLz09IEZvcm0gc3RhdGVzIGFuZCBhbGVydHNcbi8vXG4vLyMjIERlZmluZSBjb2xvcnMgZm9yIGZvcm0gZmVlZGJhY2sgc3RhdGVzIGFuZCwgYnkgZGVmYXVsdCwgYWxlcnRzLlxuXG4kc3RhdGUtc3VjY2Vzcy10ZXh0OiAgICAgICAgICAgICAjM2M3NjNkICFkZWZhdWx0O1xuJHN0YXRlLXN1Y2Nlc3MtYmc6ICAgICAgICAgICAgICAgI2RmZjBkOCAhZGVmYXVsdDtcbiRzdGF0ZS1zdWNjZXNzLWJvcmRlcjogICAgICAgICAgIGRhcmtlbihhZGp1c3QtaHVlKCRzdGF0ZS1zdWNjZXNzLWJnLCAtMTApLCA1JSkgIWRlZmF1bHQ7XG5cbiRzdGF0ZS1pbmZvLXRleHQ6ICAgICAgICAgICAgICAgICMzMTcwOGYgIWRlZmF1bHQ7XG4kc3RhdGUtaW5mby1iZzogICAgICAgICAgICAgICAgICAjZDllZGY3ICFkZWZhdWx0O1xuJHN0YXRlLWluZm8tYm9yZGVyOiAgICAgICAgICAgICAgZGFya2VuKGFkanVzdC1odWUoJHN0YXRlLWluZm8tYmcsIC0xMCksIDclKSAhZGVmYXVsdDtcblxuJHN0YXRlLXdhcm5pbmctdGV4dDogICAgICAgICAgICAgIzhhNmQzYiAhZGVmYXVsdDtcbiRzdGF0ZS13YXJuaW5nLWJnOiAgICAgICAgICAgICAgICNmY2Y4ZTMgIWRlZmF1bHQ7XG4kc3RhdGUtd2FybmluZy1ib3JkZXI6ICAgICAgICAgICBkYXJrZW4oYWRqdXN0LWh1ZSgkc3RhdGUtd2FybmluZy1iZywgLTEwKSwgNSUpICFkZWZhdWx0O1xuXG4kc3RhdGUtZGFuZ2VyLXRleHQ6ICAgICAgICAgICAgICAjYTk0NDQyICFkZWZhdWx0O1xuJHN0YXRlLWRhbmdlci1iZzogICAgICAgICAgICAgICAgI2YyZGVkZSAhZGVmYXVsdDtcbiRzdGF0ZS1kYW5nZXItYm9yZGVyOiAgICAgICAgICAgIGRhcmtlbihhZGp1c3QtaHVlKCRzdGF0ZS1kYW5nZXItYmcsIC0xMCksIDUlKSAhZGVmYXVsdDtcblxuXG4vLz09IFRvb2x0aXBzXG4vL1xuLy8jI1xuXG4vLyoqIFRvb2x0aXAgbWF4IHdpZHRoXG4kdG9vbHRpcC1tYXgtd2lkdGg6ICAgICAgICAgICAyMDBweCAhZGVmYXVsdDtcbi8vKiogVG9vbHRpcCB0ZXh0IGNvbG9yXG4kdG9vbHRpcC1jb2xvcjogICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBUb29sdGlwIGJhY2tncm91bmQgY29sb3JcbiR0b29sdGlwLWJnOiAgICAgICAgICAgICAgICAgICMwMDAgIWRlZmF1bHQ7XG4kdG9vbHRpcC1vcGFjaXR5OiAgICAgICAgICAgICAuOSAhZGVmYXVsdDtcblxuLy8qKiBUb29sdGlwIGFycm93IHdpZHRoXG4kdG9vbHRpcC1hcnJvdy13aWR0aDogICAgICAgICA1cHggIWRlZmF1bHQ7XG4vLyoqIFRvb2x0aXAgYXJyb3cgY29sb3JcbiR0b29sdGlwLWFycm93LWNvbG9yOiAgICAgICAgICR0b29sdGlwLWJnICFkZWZhdWx0O1xuXG5cbi8vPT0gUG9wb3ZlcnNcbi8vXG4vLyMjXG5cbi8vKiogUG9wb3ZlciBib2R5IGJhY2tncm91bmQgY29sb3JcbiRwb3BvdmVyLWJnOiAgICAgICAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogUG9wb3ZlciBtYXhpbXVtIHdpZHRoXG4kcG9wb3Zlci1tYXgtd2lkdGg6ICAgICAgICAgICAgICAgICAgIDI3NnB4ICFkZWZhdWx0O1xuLy8qKiBQb3BvdmVyIGJvcmRlciBjb2xvclxuJHBvcG92ZXItYm9yZGVyLWNvbG9yOiAgICAgICAgICAgICAgICByZ2JhKDAsMCwwLC4yKSAhZGVmYXVsdDtcbi8vKiogUG9wb3ZlciBmYWxsYmFjayBib3JkZXIgY29sb3JcbiRwb3BvdmVyLWZhbGxiYWNrLWJvcmRlci1jb2xvcjogICAgICAgI2NjYyAhZGVmYXVsdDtcblxuLy8qKiBQb3BvdmVyIHRpdGxlIGJhY2tncm91bmQgY29sb3JcbiRwb3BvdmVyLXRpdGxlLWJnOiAgICAgICAgICAgICAgICAgICAgZGFya2VuKCRwb3BvdmVyLWJnLCAzJSkgIWRlZmF1bHQ7XG5cbi8vKiogUG9wb3ZlciBhcnJvdyB3aWR0aFxuJHBvcG92ZXItYXJyb3ctd2lkdGg6ICAgICAgICAgICAgICAgICAxMHB4ICFkZWZhdWx0O1xuLy8qKiBQb3BvdmVyIGFycm93IGNvbG9yXG4kcG9wb3Zlci1hcnJvdy1jb2xvcjogICAgICAgICAgICAgICAgICRwb3BvdmVyLWJnICFkZWZhdWx0O1xuXG4vLyoqIFBvcG92ZXIgb3V0ZXIgYXJyb3cgd2lkdGhcbiRwb3BvdmVyLWFycm93LW91dGVyLXdpZHRoOiAgICAgICAgICAgKCRwb3BvdmVyLWFycm93LXdpZHRoICsgMSkgIWRlZmF1bHQ7XG4vLyoqIFBvcG92ZXIgb3V0ZXIgYXJyb3cgY29sb3JcbiRwb3BvdmVyLWFycm93LW91dGVyLWNvbG9yOiAgICAgICAgICAgZmFkZV9pbigkcG9wb3Zlci1ib3JkZXItY29sb3IsIDAuMDUpICFkZWZhdWx0O1xuLy8qKiBQb3BvdmVyIG91dGVyIGFycm93IGZhbGxiYWNrIGNvbG9yXG4kcG9wb3Zlci1hcnJvdy1vdXRlci1mYWxsYmFjay1jb2xvcjogIGRhcmtlbigkcG9wb3Zlci1mYWxsYmFjay1ib3JkZXItY29sb3IsIDIwJSkgIWRlZmF1bHQ7XG5cblxuLy89PSBMYWJlbHNcbi8vXG4vLyMjXG5cbi8vKiogRGVmYXVsdCBsYWJlbCBiYWNrZ3JvdW5kIGNvbG9yXG4kbGFiZWwtZGVmYXVsdC1iZzogICAgICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbi8vKiogUHJpbWFyeSBsYWJlbCBiYWNrZ3JvdW5kIGNvbG9yXG4kbGFiZWwtcHJpbWFyeS1iZzogICAgICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcbi8vKiogU3VjY2VzcyBsYWJlbCBiYWNrZ3JvdW5kIGNvbG9yXG4kbGFiZWwtc3VjY2Vzcy1iZzogICAgICAgICAgICAkYnJhbmQtc3VjY2VzcyAhZGVmYXVsdDtcbi8vKiogSW5mbyBsYWJlbCBiYWNrZ3JvdW5kIGNvbG9yXG4kbGFiZWwtaW5mby1iZzogICAgICAgICAgICAgICAkYnJhbmQtaW5mbyAhZGVmYXVsdDtcbi8vKiogV2FybmluZyBsYWJlbCBiYWNrZ3JvdW5kIGNvbG9yXG4kbGFiZWwtd2FybmluZy1iZzogICAgICAgICAgICAkYnJhbmQtd2FybmluZyAhZGVmYXVsdDtcbi8vKiogRGFuZ2VyIGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC1kYW5nZXItYmc6ICAgICAgICAgICAgICRicmFuZC1kYW5nZXIgIWRlZmF1bHQ7XG5cbi8vKiogRGVmYXVsdCBsYWJlbCB0ZXh0IGNvbG9yXG4kbGFiZWwtY29sb3I6ICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBEZWZhdWx0IHRleHQgY29sb3Igb2YgYSBsaW5rZWQgbGFiZWxcbiRsYWJlbC1saW5rLWhvdmVyLWNvbG9yOiAgICAgICNmZmYgIWRlZmF1bHQ7XG5cblxuLy89PSBNb2RhbHNcbi8vXG4vLyMjXG5cbi8vKiogUGFkZGluZyBhcHBsaWVkIHRvIHRoZSBtb2RhbCBib2R5XG4kbW9kYWwtaW5uZXItcGFkZGluZzogICAgICAgICAxNXB4ICFkZWZhdWx0O1xuXG4vLyoqIFBhZGRpbmcgYXBwbGllZCB0byB0aGUgbW9kYWwgdGl0bGVcbiRtb2RhbC10aXRsZS1wYWRkaW5nOiAgICAgICAgIDE1cHggIWRlZmF1bHQ7XG4vLyoqIE1vZGFsIHRpdGxlIGxpbmUtaGVpZ2h0XG4kbW9kYWwtdGl0bGUtbGluZS1oZWlnaHQ6ICAgICAkbGluZS1oZWlnaHQtYmFzZSAhZGVmYXVsdDtcblxuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIG9mIG1vZGFsIGNvbnRlbnQgYXJlYVxuJG1vZGFsLWNvbnRlbnQtYmc6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBNb2RhbCBjb250ZW50IGJvcmRlciBjb2xvclxuJG1vZGFsLWNvbnRlbnQtYm9yZGVyLWNvbG9yOiAgICAgICAgICAgICAgICAgICByZ2JhKDAsMCwwLC4yKSAhZGVmYXVsdDtcbi8vKiogTW9kYWwgY29udGVudCBib3JkZXIgY29sb3IgKipmb3IgSUU4KipcbiRtb2RhbC1jb250ZW50LWZhbGxiYWNrLWJvcmRlci1jb2xvcjogICAgICAgICAgIzk5OSAhZGVmYXVsdDtcblxuLy8qKiBNb2RhbCBiYWNrZHJvcCBiYWNrZ3JvdW5kIGNvbG9yXG4kbW9kYWwtYmFja2Ryb3AtYmc6ICAgICAgICAgICAjMDAwICFkZWZhdWx0O1xuLy8qKiBNb2RhbCBiYWNrZHJvcCBvcGFjaXR5XG4kbW9kYWwtYmFja2Ryb3Atb3BhY2l0eTogICAgICAuNSAhZGVmYXVsdDtcbi8vKiogTW9kYWwgaGVhZGVyIGJvcmRlciBjb2xvclxuJG1vZGFsLWhlYWRlci1ib3JkZXItY29sb3I6ICAgI2U1ZTVlNSAhZGVmYXVsdDtcbi8vKiogTW9kYWwgZm9vdGVyIGJvcmRlciBjb2xvclxuJG1vZGFsLWZvb3Rlci1ib3JkZXItY29sb3I6ICAgJG1vZGFsLWhlYWRlci1ib3JkZXItY29sb3IgIWRlZmF1bHQ7XG5cbiRtb2RhbC1sZzogICAgICAgICAgICAgICAgICAgIDkwMHB4ICFkZWZhdWx0O1xuJG1vZGFsLW1kOiAgICAgICAgICAgICAgICAgICAgNjAwcHggIWRlZmF1bHQ7XG4kbW9kYWwtc206ICAgICAgICAgICAgICAgICAgICAzMDBweCAhZGVmYXVsdDtcblxuXG4vLz09IEFsZXJ0c1xuLy9cbi8vIyMgRGVmaW5lIGFsZXJ0IGNvbG9ycywgYm9yZGVyIHJhZGl1cywgYW5kIHBhZGRpbmcuXG5cbiRhbGVydC1wYWRkaW5nOiAgICAgICAgICAgICAgIDE1cHggIWRlZmF1bHQ7XG4kYWxlcnQtYm9yZGVyLXJhZGl1czogICAgICAgICAkYm9yZGVyLXJhZGl1cy1iYXNlICFkZWZhdWx0O1xuJGFsZXJ0LWxpbmstZm9udC13ZWlnaHQ6ICAgICAgYm9sZCAhZGVmYXVsdDtcblxuJGFsZXJ0LXN1Y2Nlc3MtYmc6ICAgICAgICAgICAgJHN0YXRlLXN1Y2Nlc3MtYmcgIWRlZmF1bHQ7XG4kYWxlcnQtc3VjY2Vzcy10ZXh0OiAgICAgICAgICAkc3RhdGUtc3VjY2Vzcy10ZXh0ICFkZWZhdWx0O1xuJGFsZXJ0LXN1Y2Nlc3MtYm9yZGVyOiAgICAgICAgJHN0YXRlLXN1Y2Nlc3MtYm9yZGVyICFkZWZhdWx0O1xuXG4kYWxlcnQtaW5mby1iZzogICAgICAgICAgICAgICAkc3RhdGUtaW5mby1iZyAhZGVmYXVsdDtcbiRhbGVydC1pbmZvLXRleHQ6ICAgICAgICAgICAgICRzdGF0ZS1pbmZvLXRleHQgIWRlZmF1bHQ7XG4kYWxlcnQtaW5mby1ib3JkZXI6ICAgICAgICAgICAkc3RhdGUtaW5mby1ib3JkZXIgIWRlZmF1bHQ7XG5cbiRhbGVydC13YXJuaW5nLWJnOiAgICAgICAgICAgICRzdGF0ZS13YXJuaW5nLWJnICFkZWZhdWx0O1xuJGFsZXJ0LXdhcm5pbmctdGV4dDogICAgICAgICAgJHN0YXRlLXdhcm5pbmctdGV4dCAhZGVmYXVsdDtcbiRhbGVydC13YXJuaW5nLWJvcmRlcjogICAgICAgICRzdGF0ZS13YXJuaW5nLWJvcmRlciAhZGVmYXVsdDtcblxuJGFsZXJ0LWRhbmdlci1iZzogICAgICAgICAgICAgJHN0YXRlLWRhbmdlci1iZyAhZGVmYXVsdDtcbiRhbGVydC1kYW5nZXItdGV4dDogICAgICAgICAgICRzdGF0ZS1kYW5nZXItdGV4dCAhZGVmYXVsdDtcbiRhbGVydC1kYW5nZXItYm9yZGVyOiAgICAgICAgICRzdGF0ZS1kYW5nZXItYm9yZGVyICFkZWZhdWx0O1xuXG5cbi8vPT0gUHJvZ3Jlc3MgYmFyc1xuLy9cbi8vIyNcblxuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIG9mIHRoZSB3aG9sZSBwcm9ncmVzcyBjb21wb25lbnRcbiRwcm9ncmVzcy1iZzogICAgICAgICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG4vLyoqIFByb2dyZXNzIGJhciB0ZXh0IGNvbG9yXG4kcHJvZ3Jlc3MtYmFyLWNvbG9yOiAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBWYXJpYWJsZSBmb3Igc2V0dGluZyByb3VuZGVkIGNvcm5lcnMgb24gcHJvZ3Jlc3MgYmFyLlxuJHByb2dyZXNzLWJvcmRlci1yYWRpdXM6ICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcblxuLy8qKiBEZWZhdWx0IHByb2dyZXNzIGJhciBjb2xvclxuJHByb2dyZXNzLWJhci1iZzogICAgICAgICAgICAgJGJyYW5kLXByaW1hcnkgIWRlZmF1bHQ7XG4vLyoqIFN1Y2Nlc3MgcHJvZ3Jlc3MgYmFyIGNvbG9yXG4kcHJvZ3Jlc3MtYmFyLXN1Y2Nlc3MtYmc6ICAgICAkYnJhbmQtc3VjY2VzcyAhZGVmYXVsdDtcbi8vKiogV2FybmluZyBwcm9ncmVzcyBiYXIgY29sb3JcbiRwcm9ncmVzcy1iYXItd2FybmluZy1iZzogICAgICRicmFuZC13YXJuaW5nICFkZWZhdWx0O1xuLy8qKiBEYW5nZXIgcHJvZ3Jlc3MgYmFyIGNvbG9yXG4kcHJvZ3Jlc3MtYmFyLWRhbmdlci1iZzogICAgICAkYnJhbmQtZGFuZ2VyICFkZWZhdWx0O1xuLy8qKiBJbmZvIHByb2dyZXNzIGJhciBjb2xvclxuJHByb2dyZXNzLWJhci1pbmZvLWJnOiAgICAgICAgJGJyYW5kLWluZm8gIWRlZmF1bHQ7XG5cblxuLy89PSBMaXN0IGdyb3VwXG4vL1xuLy8jI1xuXG4vLyoqIEJhY2tncm91bmQgY29sb3Igb24gYC5saXN0LWdyb3VwLWl0ZW1gXG4kbGlzdC1ncm91cC1iZzogICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIGAubGlzdC1ncm91cC1pdGVtYCBib3JkZXIgY29sb3JcbiRsaXN0LWdyb3VwLWJvcmRlcjogICAgICAgICAgICAgI2RkZCAhZGVmYXVsdDtcbi8vKiogTGlzdCBncm91cCBib3JkZXIgcmFkaXVzXG4kbGlzdC1ncm91cC1ib3JkZXItcmFkaXVzOiAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG5cbi8vKiogQmFja2dyb3VuZCBjb2xvciBvZiBzaW5nbGUgbGlzdCBpdGVtcyBvbiBob3ZlclxuJGxpc3QtZ3JvdXAtaG92ZXItYmc6ICAgICAgICAgICAjZjVmNWY1ICFkZWZhdWx0O1xuLy8qKiBUZXh0IGNvbG9yIG9mIGFjdGl2ZSBsaXN0IGl0ZW1zXG4kbGlzdC1ncm91cC1hY3RpdmUtY29sb3I6ICAgICAgICRjb21wb25lbnQtYWN0aXZlLWNvbG9yICFkZWZhdWx0O1xuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIG9mIGFjdGl2ZSBsaXN0IGl0ZW1zXG4kbGlzdC1ncm91cC1hY3RpdmUtYmc6ICAgICAgICAgICRjb21wb25lbnQtYWN0aXZlLWJnICFkZWZhdWx0O1xuLy8qKiBCb3JkZXIgY29sb3Igb2YgYWN0aXZlIGxpc3QgZWxlbWVudHNcbiRsaXN0LWdyb3VwLWFjdGl2ZS1ib3JkZXI6ICAgICAgJGxpc3QtZ3JvdXAtYWN0aXZlLWJnICFkZWZhdWx0O1xuLy8qKiBUZXh0IGNvbG9yIGZvciBjb250ZW50IHdpdGhpbiBhY3RpdmUgbGlzdCBpdGVtc1xuJGxpc3QtZ3JvdXAtYWN0aXZlLXRleHQtY29sb3I6ICBsaWdodGVuKCRsaXN0LWdyb3VwLWFjdGl2ZS1iZywgNDAlKSAhZGVmYXVsdDtcblxuLy8qKiBUZXh0IGNvbG9yIG9mIGRpc2FibGVkIGxpc3QgaXRlbXNcbiRsaXN0LWdyb3VwLWRpc2FibGVkLWNvbG9yOiAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIG9mIGRpc2FibGVkIGxpc3QgaXRlbXNcbiRsaXN0LWdyb3VwLWRpc2FibGVkLWJnOiAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG4vLyoqIFRleHQgY29sb3IgZm9yIGNvbnRlbnQgd2l0aGluIGRpc2FibGVkIGxpc3QgaXRlbXNcbiRsaXN0LWdyb3VwLWRpc2FibGVkLXRleHQtY29sb3I6ICRsaXN0LWdyb3VwLWRpc2FibGVkLWNvbG9yICFkZWZhdWx0O1xuXG4kbGlzdC1ncm91cC1saW5rLWNvbG9yOiAgICAgICAgICM1NTUgIWRlZmF1bHQ7XG4kbGlzdC1ncm91cC1saW5rLWhvdmVyLWNvbG9yOiAgICRsaXN0LWdyb3VwLWxpbmstY29sb3IgIWRlZmF1bHQ7XG4kbGlzdC1ncm91cC1saW5rLWhlYWRpbmctY29sb3I6ICMzMzMgIWRlZmF1bHQ7XG5cblxuLy89PSBQYW5lbHNcbi8vXG4vLyMjXG5cbiRwYW5lbC1iZzogICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kcGFuZWwtYm9keS1wYWRkaW5nOiAgICAgICAgICAxNXB4ICFkZWZhdWx0O1xuJHBhbmVsLWhlYWRpbmctcGFkZGluZzogICAgICAgMTBweCAxNXB4ICFkZWZhdWx0O1xuJHBhbmVsLWZvb3Rlci1wYWRkaW5nOiAgICAgICAgJHBhbmVsLWhlYWRpbmctcGFkZGluZyAhZGVmYXVsdDtcbiRwYW5lbC1ib3JkZXItcmFkaXVzOiAgICAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG5cbi8vKiogQm9yZGVyIGNvbG9yIGZvciBlbGVtZW50cyB3aXRoaW4gcGFuZWxzXG4kcGFuZWwtaW5uZXItYm9yZGVyOiAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuJHBhbmVsLWZvb3Rlci1iZzogICAgICAgICAgICAgI2Y1ZjVmNSAhZGVmYXVsdDtcblxuJHBhbmVsLWRlZmF1bHQtdGV4dDogICAgICAgICAgJGdyYXktZGFyayAhZGVmYXVsdDtcbiRwYW5lbC1kZWZhdWx0LWJvcmRlcjogICAgICAgICNkZGQgIWRlZmF1bHQ7XG4kcGFuZWwtZGVmYXVsdC1oZWFkaW5nLWJnOiAgICAjZjVmNWY1ICFkZWZhdWx0O1xuXG4kcGFuZWwtcHJpbWFyeS10ZXh0OiAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJHBhbmVsLXByaW1hcnktYm9yZGVyOiAgICAgICAgJGJyYW5kLXByaW1hcnkgIWRlZmF1bHQ7XG4kcGFuZWwtcHJpbWFyeS1oZWFkaW5nLWJnOiAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcblxuJHBhbmVsLXN1Y2Nlc3MtdGV4dDogICAgICAgICAgJHN0YXRlLXN1Y2Nlc3MtdGV4dCAhZGVmYXVsdDtcbiRwYW5lbC1zdWNjZXNzLWJvcmRlcjogICAgICAgICRzdGF0ZS1zdWNjZXNzLWJvcmRlciAhZGVmYXVsdDtcbiRwYW5lbC1zdWNjZXNzLWhlYWRpbmctYmc6ICAgICRzdGF0ZS1zdWNjZXNzLWJnICFkZWZhdWx0O1xuXG4kcGFuZWwtaW5mby10ZXh0OiAgICAgICAgICAgICAkc3RhdGUtaW5mby10ZXh0ICFkZWZhdWx0O1xuJHBhbmVsLWluZm8tYm9yZGVyOiAgICAgICAgICAgJHN0YXRlLWluZm8tYm9yZGVyICFkZWZhdWx0O1xuJHBhbmVsLWluZm8taGVhZGluZy1iZzogICAgICAgJHN0YXRlLWluZm8tYmcgIWRlZmF1bHQ7XG5cbiRwYW5lbC13YXJuaW5nLXRleHQ6ICAgICAgICAgICRzdGF0ZS13YXJuaW5nLXRleHQgIWRlZmF1bHQ7XG4kcGFuZWwtd2FybmluZy1ib3JkZXI6ICAgICAgICAkc3RhdGUtd2FybmluZy1ib3JkZXIgIWRlZmF1bHQ7XG4kcGFuZWwtd2FybmluZy1oZWFkaW5nLWJnOiAgICAkc3RhdGUtd2FybmluZy1iZyAhZGVmYXVsdDtcblxuJHBhbmVsLWRhbmdlci10ZXh0OiAgICAgICAgICAgJHN0YXRlLWRhbmdlci10ZXh0ICFkZWZhdWx0O1xuJHBhbmVsLWRhbmdlci1ib3JkZXI6ICAgICAgICAgJHN0YXRlLWRhbmdlci1ib3JkZXIgIWRlZmF1bHQ7XG4kcGFuZWwtZGFuZ2VyLWhlYWRpbmctYmc6ICAgICAkc3RhdGUtZGFuZ2VyLWJnICFkZWZhdWx0O1xuXG5cbi8vPT0gVGh1bWJuYWlsc1xuLy9cbi8vIyNcblxuLy8qKiBQYWRkaW5nIGFyb3VuZCB0aGUgdGh1bWJuYWlsIGltYWdlXG4kdGh1bWJuYWlsLXBhZGRpbmc6ICAgICAgICAgICA0cHggIWRlZmF1bHQ7XG4vLyoqIFRodW1ibmFpbCBiYWNrZ3JvdW5kIGNvbG9yXG4kdGh1bWJuYWlsLWJnOiAgICAgICAgICAgICAgICAkYm9keS1iZyAhZGVmYXVsdDtcbi8vKiogVGh1bWJuYWlsIGJvcmRlciBjb2xvclxuJHRodW1ibmFpbC1ib3JkZXI6ICAgICAgICAgICAgI2RkZCAhZGVmYXVsdDtcbi8vKiogVGh1bWJuYWlsIGJvcmRlciByYWRpdXNcbiR0aHVtYm5haWwtYm9yZGVyLXJhZGl1czogICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG5cbi8vKiogQ3VzdG9tIHRleHQgY29sb3IgZm9yIHRodW1ibmFpbCBjYXB0aW9uc1xuJHRodW1ibmFpbC1jYXB0aW9uLWNvbG9yOiAgICAgJHRleHQtY29sb3IgIWRlZmF1bHQ7XG4vLyoqIFBhZGRpbmcgYXJvdW5kIHRoZSB0aHVtYm5haWwgY2FwdGlvblxuJHRodW1ibmFpbC1jYXB0aW9uLXBhZGRpbmc6ICAgOXB4ICFkZWZhdWx0O1xuXG5cbi8vPT0gV2VsbHNcbi8vXG4vLyMjXG5cbiR3ZWxsLWJnOiAgICAgICAgICAgICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG4kd2VsbC1ib3JkZXI6ICAgICAgICAgICAgICAgICBkYXJrZW4oJHdlbGwtYmcsIDclKSAhZGVmYXVsdDtcblxuXG4vLz09IEJhZGdlc1xuLy9cbi8vIyNcblxuJGJhZGdlLWNvbG9yOiAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogTGlua2VkIGJhZGdlIHRleHQgY29sb3Igb24gaG92ZXJcbiRiYWRnZS1saW5rLWhvdmVyLWNvbG9yOiAgICAgICNmZmYgIWRlZmF1bHQ7XG4kYmFkZ2UtYmc6ICAgICAgICAgICAgICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcblxuLy8qKiBCYWRnZSB0ZXh0IGNvbG9yIGluIGFjdGl2ZSBuYXYgbGlua1xuJGJhZGdlLWFjdGl2ZS1jb2xvcjogICAgICAgICAgJGxpbmstY29sb3IgIWRlZmF1bHQ7XG4vLyoqIEJhZGdlIGJhY2tncm91bmQgY29sb3IgaW4gYWN0aXZlIG5hdiBsaW5rXG4kYmFkZ2UtYWN0aXZlLWJnOiAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuXG4kYmFkZ2UtZm9udC13ZWlnaHQ6ICAgICAgICAgICBib2xkICFkZWZhdWx0O1xuJGJhZGdlLWxpbmUtaGVpZ2h0OiAgICAgICAgICAgMSAhZGVmYXVsdDtcbiRiYWRnZS1ib3JkZXItcmFkaXVzOiAgICAgICAgIDEwcHggIWRlZmF1bHQ7XG5cblxuLy89PSBCcmVhZGNydW1ic1xuLy9cbi8vIyNcblxuJGJyZWFkY3J1bWItcGFkZGluZy12ZXJ0aWNhbDogICA4cHggIWRlZmF1bHQ7XG4kYnJlYWRjcnVtYi1wYWRkaW5nLWhvcml6b250YWw6IDE1cHggIWRlZmF1bHQ7XG4vLyoqIEJyZWFkY3J1bWIgYmFja2dyb3VuZCBjb2xvclxuJGJyZWFkY3J1bWItYmc6ICAgICAgICAgICAgICAgICAjZjVmNWY1ICFkZWZhdWx0O1xuLy8qKiBCcmVhZGNydW1iIHRleHQgY29sb3JcbiRicmVhZGNydW1iLWNvbG9yOiAgICAgICAgICAgICAgI2NjYyAhZGVmYXVsdDtcbi8vKiogVGV4dCBjb2xvciBvZiBjdXJyZW50IHBhZ2UgaW4gdGhlIGJyZWFkY3J1bWJcbiRicmVhZGNydW1iLWFjdGl2ZS1jb2xvcjogICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG4vLyoqIFRleHR1YWwgc2VwYXJhdG9yIGZvciBiZXR3ZWVuIGJyZWFkY3J1bWIgZWxlbWVudHNcbiRicmVhZGNydW1iLXNlcGFyYXRvcjogICAgICAgICAgXCIvXCIgIWRlZmF1bHQ7XG5cblxuLy89PSBDYXJvdXNlbFxuLy9cbi8vIyNcblxuJGNhcm91c2VsLXRleHQtc2hhZG93OiAgICAgICAgICAgICAgICAgICAgICAgIDAgMXB4IDJweCByZ2JhKDAsMCwwLC42KSAhZGVmYXVsdDtcblxuJGNhcm91c2VsLWNvbnRyb2wtY29sb3I6ICAgICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kY2Fyb3VzZWwtY29udHJvbC13aWR0aDogICAgICAgICAgICAgICAgICAgICAgMTUlICFkZWZhdWx0O1xuJGNhcm91c2VsLWNvbnRyb2wtb3BhY2l0eTogICAgICAgICAgICAgICAgICAgIC41ICFkZWZhdWx0O1xuJGNhcm91c2VsLWNvbnRyb2wtZm9udC1zaXplOiAgICAgICAgICAgICAgICAgIDIwcHggIWRlZmF1bHQ7XG5cbiRjYXJvdXNlbC1pbmRpY2F0b3ItYWN0aXZlLWJnOiAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGNhcm91c2VsLWluZGljYXRvci1ib3JkZXItY29sb3I6ICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG5cbiRjYXJvdXNlbC1jYXB0aW9uLWNvbG9yOiAgICAgICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuXG5cbi8vPT0gQ2xvc2Vcbi8vXG4vLyMjXG5cbiRjbG9zZS1mb250LXdlaWdodDogICAgICAgICAgIGJvbGQgIWRlZmF1bHQ7XG4kY2xvc2UtY29sb3I6ICAgICAgICAgICAgICAgICAjMDAwICFkZWZhdWx0O1xuJGNsb3NlLXRleHQtc2hhZG93OiAgICAgICAgICAgMCAxcHggMCAjZmZmICFkZWZhdWx0O1xuXG5cbi8vPT0gQ29kZVxuLy9cbi8vIyNcblxuJGNvZGUtY29sb3I6ICAgICAgICAgICAgICAgICAgI2M3MjU0ZSAhZGVmYXVsdDtcbiRjb2RlLWJnOiAgICAgICAgICAgICAgICAgICAgICNmOWYyZjQgIWRlZmF1bHQ7XG5cbiRrYmQtY29sb3I6ICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4ka2JkLWJnOiAgICAgICAgICAgICAgICAgICAgICAjMzMzICFkZWZhdWx0O1xuXG4kcHJlLWJnOiAgICAgICAgICAgICAgICAgICAgICAjZjVmNWY1ICFkZWZhdWx0O1xuJHByZS1jb2xvcjogICAgICAgICAgICAgICAgICAgJGdyYXktZGFyayAhZGVmYXVsdDtcbiRwcmUtYm9yZGVyLWNvbG9yOiAgICAgICAgICAgICNjY2MgIWRlZmF1bHQ7XG4kcHJlLXNjcm9sbGFibGUtbWF4LWhlaWdodDogICAzNDBweCAhZGVmYXVsdDtcblxuXG4vLz09IFR5cGVcbi8vXG4vLyMjXG5cbi8vKiogSG9yaXpvbnRhbCBvZmZzZXQgZm9yIGZvcm1zIGFuZCBsaXN0cy5cbiRjb21wb25lbnQtb2Zmc2V0LWhvcml6b250YWw6IDE4MHB4ICFkZWZhdWx0O1xuLy8qKiBUZXh0IG11dGVkIGNvbG9yXG4kdGV4dC1tdXRlZDogICAgICAgICAgICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbi8vKiogQWJicmV2aWF0aW9ucyBhbmQgYWNyb255bXMgYm9yZGVyIGNvbG9yXG4kYWJici1ib3JkZXItY29sb3I6ICAgICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbi8vKiogSGVhZGluZ3Mgc21hbGwgY29sb3JcbiRoZWFkaW5ncy1zbWFsbC1jb2xvcjogICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBCbG9ja3F1b3RlIHNtYWxsIGNvbG9yXG4kYmxvY2txdW90ZS1zbWFsbC1jb2xvcjogICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbi8vKiogQmxvY2txdW90ZSBmb250IHNpemVcbiRibG9ja3F1b3RlLWZvbnQtc2l6ZTogICAgICAgICgkZm9udC1zaXplLWJhc2UgKiAxLjI1KSAhZGVmYXVsdDtcbi8vKiogQmxvY2txdW90ZSBib3JkZXIgY29sb3JcbiRibG9ja3F1b3RlLWJvcmRlci1jb2xvcjogICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG4vLyoqIFBhZ2UgaGVhZGVyIGJvcmRlciBjb2xvclxuJHBhZ2UtaGVhZGVyLWJvcmRlci1jb2xvcjogICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbi8vKiogV2lkdGggb2YgaG9yaXpvbnRhbCBkZXNjcmlwdGlvbiBsaXN0IHRpdGxlc1xuJGRsLWhvcml6b250YWwtb2Zmc2V0OiAgICAgICAgJGNvbXBvbmVudC1vZmZzZXQtaG9yaXpvbnRhbCAhZGVmYXVsdDtcbi8vKiogUG9pbnQgYXQgd2hpY2ggLmRsLWhvcml6b250YWwgYmVjb21lcyBob3Jpem9udGFsXG4kZGwtaG9yaXpvbnRhbC1icmVha3BvaW50OiAgICAkZ3JpZC1mbG9hdC1icmVha3BvaW50ICFkZWZhdWx0O1xuLy8qKiBIb3Jpem9udGFsIGxpbmUgY29sb3IuXG4kaHItYm9yZGVyOiAgICAgICAgICAgICAgICAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuIiwiQGltcG9ydCAnLi4vLi4vLi4vc3R5bGVzL2FuaW1hdGlvbnMuc2Nzcyc7XG5cbnhvcy10YWJsZSB7XG5cbiAgZGlzcGxheTogYmxvY2s7XG5cbiAgdHIubmctbW92ZSxcbiAgdHIubmctZW50ZXIsXG4gIHRyLm5nLWxlYXZlIHtcbiAgICB0cmFuc2l0aW9uOmFsbCBsaW5lYXIgMC41cztcbiAgfVxuXG4gIHRyLm5nLWxlYXZlLm5nLWxlYXZlLWFjdGl2ZSxcbiAgdHIubmctbW92ZSxcbiAgdHIubmctZW50ZXIge1xuICAgIG9wYWNpdHk6MDtcbiAgICBhbmltYXRpb246IDAuNXMgc2xpZGVPdXRSaWdodCBlYXNlLWluLW91dDtcbiAgfVxuXG4gIHRyLm5nLWxlYXZlLFxuICB0ci5uZy1tb3ZlLm5nLW1vdmUtYWN0aXZlLFxuICB0ci5uZy1lbnRlci5uZy1lbnRlci1hY3RpdmUge1xuICAgIG9wYWNpdHk6MTtcbiAgICBhbmltYXRpb246IDAuNXMgc2xpZGVJblJpZ2h0IGVhc2UtaW4tb3V0O1xuICB9XG5cbiAgdGQgZGwge1xuICAgIG1hcmdpbi1ib3R0b206IDA7XG5cbiAgICBkdCB7XG4gICAgICB3aWR0aDogYXV0byAhaW1wb3J0YW50O1xuICAgICAgbWFyZ2luLXJpZ2h0OiAxMHB4O1xuICAgIH1cbiAgICBcbiAgICBkdDphZnRlciB7XG4gICAgICAvKmRpc3BsYXk6IGJsb2NrOyovXG4gICAgICBjb250ZW50OiAnOic7XG4gICAgfVxuXG4gICAgZGQge1xuICAgICAgbWFyZ2luLWxlZnQ6IDAgIWltcG9ydGFudDtcbiAgICB9XG4gIH1cbn0iLCJAaW1wb3J0ICcuLi8uLi8uLi9zdHlsZXMvYW5pbWF0aW9ucy5zY3NzJztcblxueG9zLWFsZXJ0IHtcblxuICAvKiB3aGVuIGhpZGluZyAqL1xuICAubmctaGlkZS1hZGQgICAgICAgICB7IGFuaW1hdGlvbjowLjVzIGZhZGVPdXREb3duIGVhc2UtaW4tb3V0OyB9XG5cbiAgLyogd2hlbiBzaG93aW5nICovXG4gIC5uZy1oaWRlLXJlbW92ZSAgICAgIHsgYW5pbWF0aW9uOjAuNXMgZmFkZUluVXAgZWFzZS1pbi1vdXQ7IH1cbn0iLCJAaW1wb3J0ICcuLi8uLi8uLi9zdHlsZXMvYW5pbWF0aW9ucy5zY3NzJztcbkBpbXBvcnQgJy4uLy4uLy4uLy4uLy4uLy4uL3N0eWxlL3Nhc3MvYm9vdHN0cmFwL2Jvb3RzdHJhcC9fdmFyaWFibGVzLnNjc3MnO1xuXG5pbnB1dCArIHhvcy12YWxpZGF0aW9uIHtcbiAgbWFyZ2luLXRvcDogJGZvcm0tZ3JvdXAtbWFyZ2luLWJvdHRvbTtcbiAgZGlzcGxheTogYmxvY2s7XG59IiwieG9zLWZpZWxkIHtcbiAgZGlzcGxheTogYmxvY2s7XG59IiwieG9zLXNtYXJ0LXRhYmxle1xuICBcbn0iXSwibWFwcGluZ3MiOiJBQ0FBLFVBQVUsQ0FBQyxBQUFBLFlBQVk7RUFDckIsQUFBQSxJQUFJO0lBQ0YsU0FBUyxFQUFFLHVCQUFXO0lBQ3RCLFVBQVUsRUFBRSxPQUFRO0VBR3RCLEFBQUEsRUFBRTtJQUNBLFNBQVMsRUFBRSxvQkFBVzs7QUFJMUIsVUFBVSxDQUFDLEFBQUEsYUFBYTtFQUN0QixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsb0JBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsVUFBVSxFQUFFLE1BQU87SUFDbkIsU0FBUyxFQUFFLHVCQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxRQUFRO0VBQ2pCLEFBQUEsSUFBSTtJQUNGLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXO0VBR3hCLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLElBQUs7O0FBSXBCLFVBQVUsQ0FBQyxBQUFBLFdBQVc7RUFDcEIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7RUFHYixBQUFBLEVBQUU7SUFDQSxPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSx1QkFBVzs7QUF6QzFCLFVBQVUsQ0FBQyxBQUFBLFlBQVk7RUFDckIsQUFBQSxJQUFJO0lBQ0YsU0FBUyxFQUFFLHVCQUFXO0lBQ3RCLFVBQVUsRUFBRSxPQUFRO0VBR3RCLEFBQUEsRUFBRTtJQUNBLFNBQVMsRUFBRSxvQkFBVzs7QUFJMUIsVUFBVSxDQUFDLEFBQUEsYUFBYTtFQUN0QixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsb0JBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsVUFBVSxFQUFFLE1BQU87SUFDbkIsU0FBUyxFQUFFLHVCQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxRQUFRO0VBQ2pCLEFBQUEsSUFBSTtJQUNGLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXO0VBR3hCLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLElBQUs7O0FBSXBCLFVBQVUsQ0FBQyxBQUFBLFdBQVc7RUFDcEIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7RUFHYixBQUFBLEVBQUU7SUFDQSxPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSx1QkFBVzs7QUV2QzFCLEFBQUEsU0FBUyxDQUFDO0VBRVIsT0FBTyxFQUFFLEtBQU0sR0F1Q2hCO0VBekNELEFBSUksU0FKSyxDQUlQLEVBQUUsQUFBQSxRQUFRO0VBSlosQUFLSSxTQUxLLENBS1AsRUFBRSxBQUFBLFNBQVM7RUFMYixBQU1JLFNBTkssQ0FNUCxFQUFFLEFBQUEsU0FBUyxDQUFDO0lBQ1YsVUFBVSxFQUFDLGVBQWdCLEdBQzVCO0VBUkgsQUFVYSxTQVZKLENBVVAsRUFBRSxBQUFBLFNBQVMsQUFBQSxnQkFBZ0I7RUFWN0IsQUFXSSxTQVhLLENBV1AsRUFBRSxBQUFBLFFBQVE7RUFYWixBQVlJLFNBWkssQ0FZUCxFQUFFLEFBQUEsU0FBUyxDQUFDO0lBQ1YsT0FBTyxFQUFDLENBQUU7SUFDVixTQUFTLEVBQUUsOEJBQStCLEdBQzNDO0VBZkgsQUFpQkksU0FqQkssQ0FpQlAsRUFBRSxBQUFBLFNBQVM7RUFqQmIsQUFrQlksU0FsQkgsQ0FrQlAsRUFBRSxBQUFBLFFBQVEsQUFBQSxlQUFlO0VBbEIzQixBQW1CYSxTQW5CSixDQW1CUCxFQUFFLEFBQUEsU0FBUyxBQUFBLGdCQUFnQixDQUFDO0lBQzFCLE9BQU8sRUFBQyxDQUFFO0lBQ1YsU0FBUyxFQUFFLDZCQUE4QixHQUMxQztFQXRCSCxBQXdCSyxTQXhCSSxDQXdCUCxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ0osYUFBYSxFQUFFLENBQUUsR0FlbEI7SUF4Q0gsQUEyQkksU0EzQkssQ0F3QlAsRUFBRSxDQUFDLEVBQUUsQ0FHSCxFQUFFLENBQUM7TUFDRCxLQUFLLEVBQUUsZUFBZ0I7TUFDdkIsWUFBWSxFQUFFLElBQUssR0FDcEI7SUE5QkwsQUFnQ00sU0FoQ0csQ0F3QlAsRUFBRSxDQUFDLEVBQUUsQ0FRSCxFQUFFLEFBQUEsTUFBTSxDQUFDO01BQ1AsbUJBQW1CO01BQ25CLE9BQU8sRUFBRSxHQUFJLEdBQ2Q7SUFuQ0wsQUFxQ0ksU0FyQ0ssQ0F3QlAsRUFBRSxDQUFDLEVBQUUsQ0FhSCxFQUFFLENBQUM7TUFDRCxXQUFXLEVBQUUsWUFBYSxHQUMzQjs7QUZ6Q0wsVUFBVSxDQUFDLEFBQUEsWUFBWTtFQUNyQixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsdUJBQVc7SUFDdEIsVUFBVSxFQUFFLE9BQVE7RUFHdEIsQUFBQSxFQUFFO0lBQ0EsU0FBUyxFQUFFLG9CQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxhQUFhO0VBQ3RCLEFBQUEsSUFBSTtJQUNGLFNBQVMsRUFBRSxvQkFBVztFQUd4QixBQUFBLEVBQUU7SUFDQSxVQUFVLEVBQUUsTUFBTztJQUNuQixTQUFTLEVBQUUsdUJBQVc7O0FBSTFCLFVBQVUsQ0FBQyxBQUFBLFFBQVE7RUFDakIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsdUJBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsSUFBSzs7QUFJcEIsVUFBVSxDQUFDLEFBQUEsV0FBVztFQUNwQixBQUFBLElBQUk7SUFDRixPQUFPLEVBQUUsQ0FBRTtFQUdiLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXOztBR3ZDMUIsQUFBQSxTQUFTLENBQUM7RUFFUixpQkFBaUI7RUFHakIsa0JBQWtCLEVBRW5CO0VBUEQsQUFHRSxTQUhPLENBR1AsWUFBWSxDQUFTO0lBQUUsU0FBUyxFQUFDLDRCQUE2QixHQUFJO0VBSHBFLEFBTUUsU0FOTyxDQU1QLGVBQWUsQ0FBTTtJQUFFLFNBQVMsRUFBQyx5QkFBMEIsR0FBSTs7QUhSakUsVUFBVSxDQUFDLEFBQUEsWUFBWTtFQUNyQixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsdUJBQVc7SUFDdEIsVUFBVSxFQUFFLE9BQVE7RUFHdEIsQUFBQSxFQUFFO0lBQ0EsU0FBUyxFQUFFLG9CQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxhQUFhO0VBQ3RCLEFBQUEsSUFBSTtJQUNGLFNBQVMsRUFBRSxvQkFBVztFQUd4QixBQUFBLEVBQUU7SUFDQSxVQUFVLEVBQUUsTUFBTztJQUNuQixTQUFTLEVBQUUsdUJBQVc7O0FBSTFCLFVBQVUsQ0FBQyxBQUFBLFFBQVE7RUFDakIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsdUJBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsSUFBSzs7QUFJcEIsVUFBVSxDQUFDLEFBQUEsV0FBVztFQUNwQixBQUFBLElBQUk7SUFDRixPQUFPLEVBQUUsQ0FBRTtFQUdiLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXOztBSXRDMUIsQUFBUSxLQUFILEdBQUcsY0FBYyxDQUFDO0VBQ3JCLFVBQVUsRUh3TnFCLElBQUk7RUd2Tm5DLE9BQU8sRUFBRSxLQUFNLEdBQ2hCOztBQ05ELEFBQUEsU0FBUyxDQUFDO0VBQ1IsT0FBTyxFQUFFLEtBQU0sR0FDaEI7O0NOUUQsQUFBQSxBQUFVLFNBQVQsQUFBQSxJQUFZLEFBQUEsQUFBUyxRQUFSLEFBQUEsSUFBVyxBQUFBLEFBQWMsYUFBYixBQUFBLElBQWdCLEFBQUEsQUFBVyxVQUFWLEFBQUEsR0FBYSxBQUFBLFNBQVMsRUFBRSxBQUFBLFdBQVcsQ0FBQztFQUM3RSxPQUFPLEVBQUUsZUFBZ0IsR0FDMUI7O0FBRUQsQUFBTyxJQUFILEdBQUcsSUFBSSxDQUFDO0VBQ1YsMEJBQTBCO0VBQzFCLFVBQVUsRUU0TXFCLElBQUksR0YzTXBDIiwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== */
diff --git a/xos/core/templatetags/core_tags.py b/xos/core/templatetags/core_tags.py
index 6caf034..a17be08 100644
--- a/xos/core/templatetags/core_tags.py
+++ b/xos/core/templatetags/core_tags.py
@@ -2,9 +2,11 @@
 # import sys
 from core.models import DashboardView
 from itertools import chain
+from core.dashboard.views.home import DashboardDynamicView
 
 register = template.Library()
 
+
 @register.inclusion_tag('admin/tags/dashboard_list.html', takes_context=True)
 def dashboard_list(context):
     request = context['request']
@@ -14,4 +16,10 @@
         result_list = list(chain(dashboards, customize))
     else:
         result_list = []
-    return {'dashboards': result_list, 'path': request.path}
\ No newline at end of file
+    return {'dashboards': result_list, 'path': request.path}
+
+
+@register.inclusion_tag('admin/tags/notification.html', takes_context=True)
+def notification(context):
+    template = DashboardDynamicView.readTemplate(DashboardDynamicView(), "xosSynchronizerNotifier")
+    return {'template': template}
diff --git a/xos/core/views/observer.py b/xos/core/views/observer.py
index 77f1d1b..ff3ee28 100644
--- a/xos/core/views/observer.py
+++ b/xos/core/views/observer.py
@@ -9,15 +9,17 @@
     try:
         observer_name = Config().observer_name
     except AttributeError:
-        observer_name = ''
+        observer_name = 'openstack'
 
     diag = Diag.objects.filter(name=observer_name).first()
     if not diag:
         return HttpResponse(json.dumps({"health": ":-X", "time": time.time(), "comp": 0}))
 
     t = time.time()
+
     
     d = json.loads(diag.backend_register)
+
     comp = d['last_run'] + d['last_duration']*2 + 300
     if comp>t:
         d['health'] = ':-)'
diff --git a/xos/core/xoslib/dashboards/xosSynchronizerNotifier.html b/xos/core/xoslib/dashboards/xosSynchronizerNotifier.html
new file mode 100644
index 0000000..ef69861
--- /dev/null
+++ b/xos/core/xoslib/dashboards/xosSynchronizerNotifier.html
@@ -0,0 +1,16 @@
+<!-- browserSync -->
+
+<!-- endcss -->
+<!-- inject:css -->
+<link rel="stylesheet" href="/static/css/xosSynchronizerNotifier.css">
+<!-- endinject -->
+
+<div id="xosSynchronizerNotifier">
+  <sync-status></sync-status>
+</div>
+
+
+<!-- endjs -->
+<!-- inject:js -->
+<script src="/static/js/xosSynchronizerNotifier.js"></script>
+<!-- endinject -->
\ No newline at end of file
diff --git a/xos/core/xoslib/methods/cordsubscriber.py b/xos/core/xoslib/methods/cordsubscriber.py
index 0be9b33..b69b09d 100644
--- a/xos/core/xoslib/methods/cordsubscriber.py
+++ b/xos/core/xoslib/methods/cordsubscriber.py
@@ -28,7 +28,6 @@
 class CordSubscriberIdSerializer(serializers.ModelSerializer, PlusSerializerMixin):
         id = ReadOnlyField()
         service_specific_id = ReadOnlyField()
-        vlan_id = ReadOnlyField()      # XXX remove this
         c_tag = ReadOnlyField()
         s_tag = ReadOnlyField()
         vcpe_id = ReadOnlyField()
@@ -67,7 +66,7 @@
         class Meta:
             model = CordSubscriber
             fields = ('humanReadableName', 'id',
-                      'service_specific_id', 'vlan_id', 's_tag', 'c_tag',
+                      'service_specific_id', 's_tag', 'c_tag',
                       'vcpe_id', 'instance', 'instance_name', 'image', 'image_name',
                       'firewall_enable', 'firewall_rules',
                       'url_filter_enable', 'url_filter_rules', 'url_filter_level',
diff --git a/xos/core/xoslib/methods/volttenant.py b/xos/core/xoslib/methods/volttenant.py
index 229e105..25559a0 100644
--- a/xos/core/xoslib/methods/volttenant.py
+++ b/xos/core/xoslib/methods/volttenant.py
@@ -64,11 +64,6 @@
         if service_specific_id is not None:
             queryset = queryset.filter(service_specific_id=service_specific_id)
 
-#        vlan_id = self.request.query_params.get('vlan_id', None)
-#        if vlan_id is not None:
-#            ids = [x.id for x in queryset if x.get_attribute("vlan_id", None)==vlan_id]
-#            queryset = queryset.filter(id__in=ids)
-
         c_tag = self.request.query_params.get('c_tag', None)
         if c_tag is not None:
             ids = [x.id for x in queryset if x.get_attribute("c_tag", None)==c_tag]
diff --git a/xos/core/xoslib/objects/cordsubscriber.py b/xos/core/xoslib/objects/cordsubscriber.py
index 27596b7..681b769 100644
--- a/xos/core/xoslib/objects/cordsubscriber.py
+++ b/xos/core/xoslib/objects/cordsubscriber.py
@@ -39,7 +39,6 @@
                      # ("cdn_enable", "vcpe.cdn_enable"),
                      # uplink_speed, downlink_speed, status, enable_uverse
 
-                     ("vlan_id", "volt.vlan_id"),      # XXX remove this
                      ("c_tag", "volt.c_tag"),
                      ("s_tag", "volt.s_tag"),
 
diff --git a/xos/core/xoslib/static/css/xosSynchronizerNotifier.css b/xos/core/xoslib/static/css/xosSynchronizerNotifier.css
new file mode 100644
index 0000000..89374fb
--- /dev/null
+++ b/xos/core/xoslib/static/css/xosSynchronizerNotifier.css
@@ -0,0 +1 @@
+#xosSynchronizerNotifier{float:left}#xosSynchronizerNotifier .alert{margin-bottom:0!important}#xosSynchronizerNotifier .sync-status-container{position:relative;z-index:200}#xosSynchronizerNotifier .notification-panel{position:absolute;width:200px}#xosSynchronizerNotifier sync-status .badge.success{background-color:#5cb85c}#xosSynchronizerNotifier sync-status .badge.warning{background-color:#f0ad4e}
\ No newline at end of file
diff --git a/xos/core/xoslib/static/js/vendor/ngXosHelpers.js b/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
index 1971f9f..4af4da5 100644
--- a/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
+++ b/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
@@ -1,2486 +1 @@
-'use strict';
-
-/**
- * © OpenCORD
- *
- * Visit http://guide.xosproject.org/devguide/addview/ for more information
- *
- * Created by teone on 3/24/16.
- */
-
-(function () {
-  'use strict';
-
-  /**
-  * @ngdoc overview
-  * @name xos.uiComponents
-  * @description
-  * A collection of UI components useful for Dashboard development.
-  * Currently available components are:
-  * - [xosAlert](/#/module/xos.uiComponents.directive:xosAlert)
-  * - [xosForm](/#/module/xos.uiComponents.directive:xosForm)
-  * - [xosPagination](/#/module/xos.uiComponents.directive:xosPagination)
-  * - [xosSmartTable](/#/module/xos.uiComponents.directive:xosSmartTable)
-  * - [xosTable](/#/module/xos.uiComponents.directive:xosTable)
-  * - [xosValidation](/#/module/xos.uiComponents.directive:xosValidation)
-  **/
-
-  angular.module('xos.uiComponents', ['chart.js']);
-})();
-//# sourceMappingURL=../maps/ui_components/ui-components.module.js.map
-
-'use strict';
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
-
-/**
- * © OpenCORD
- *
- * Visit http://guide.xosproject.org/devguide/addview/ for more information
- *
- * Created by teone on 3/24/16.
- */
-
-(function () {
-  'use strict';
-
-  angular.module('xos.uiComponents')
-
-  /**
-  * @ngdoc directive
-  * @name xos.uiComponents.directive:xosSmartTable
-  * @link xos.uiComponents.directive:xosTable xosTable
-  * @link xos.uiComponents.directive:xosForm xosForm
-  * @restrict E
-  * @description The xos-table directive
-  * @param {Object} config The configuration for the component,
-  * it is composed by the name of an angular [$resource](https://docs.angularjs.org/api/ngResource/service/$resource)
-  * and an array of fields that shouldn't be printed.
-  * ```
-  * {
-      resource: 'Users',
-      hiddenFields: []
-    }
-  * ```
-  * @scope
-  * @example
-   <example module="sampleSmartTable">
-    <file name="index.html">
-      <div ng-controller="SampleCtrl as vm">
-        <xos-smart-table config="vm.config"></xos-smart-table>
-      </div>
-    </file>
-    <file name="script.js">
-      angular.module('sampleSmartTable', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
-      // This is only for documentation purpose
-      .run(function($httpBackend, _){
-        let datas = [{id: 1, name: 'Jhon', surname: 'Doe'}];
-        let count = 1;
-         let paramsUrl = new RegExp(/\/test\/(.+)/);
-         $httpBackend.whenDELETE(paramsUrl, undefined, ['id']).respond((method, url, data, headers, params) => {
-          data = angular.fromJson(data);
-          let id = url.match(paramsUrl)[1];
-          _.remove(datas, (d) => {
-            return d.id === parseInt(id);
-          })
-          return [204];
-        });
-         $httpBackend.whenGET('/test').respond(200, datas)
-        $httpBackend.whenPOST('/test').respond((method, url, data) => {
-          data = angular.fromJson(data);
-          data.id = ++count;
-          datas.push(data);
-          return [201, data, {}];
-        });
-      })
-      .factory('_', function($window){
-        return $window._;
-      })
-      .service('SampleResource', function($resource){
-        return $resource('/test/:id', {id: '@id'});
-      })
-      // End of documentation purpose, example start
-      .controller('SampleCtrl', function(){
-        this.config = {
-          resource: 'SampleResource'
-        };
-      });
-    </file>
-  </example>
-  */
-
-  .directive('xosSmartTable', function () {
-    return {
-      restrict: 'E',
-      scope: {
-        config: '='
-      },
-      template: '\n        <div class="row" ng-show="vm.data.length > 0">\n          <div class="col-xs-12 text-right">\n            <a href="" class="btn btn-success" ng-click="vm.createItem()">\n              Add\n            </a>\n          </div>\n        </div>\n        <div class="row">\n          <div class="col-xs-12 table-responsive">\n            <xos-table config="vm.tableConfig" data="vm.data"></xos-table>\n          </div>\n        </div>\n        <div class="panel panel-default" ng-show="vm.detailedItem">\n          <div class="panel-heading">\n            <div class="row">\n              <div class="col-xs-11">\n                <h3 class="panel-title" ng-show="vm.detailedItem.id">Update {{vm.config.resource}} {{vm.detailedItem.id}}</h3>\n                <h3 class="panel-title" ng-show="!vm.detailedItem.id">Create {{vm.config.resource}} item</h3>\n              </div>\n              <div class="col-xs-1">\n                <a href="" ng-click="vm.cleanForm()">\n                  <i class="glyphicon glyphicon-remove pull-right"></i>\n                </a>\n              </div>\n            </div>\n          </div>\n          <div class="panel-body">\n            <xos-form config="vm.formConfig" ng-model="vm.detailedItem"></xos-form>\n          </div>\n        </div>\n        <xos-alert config="{type: \'success\', closeBtn: true}" show="vm.responseMsg">{{vm.responseMsg}}</xos-alert>\n        <xos-alert config="{type: \'danger\', closeBtn: true}" show="vm.responseErr">{{vm.responseErr}}</xos-alert>\n      ',
-      bindToController: true,
-      controllerAs: 'vm',
-      controller: ["$injector", "LabelFormatter", "_", "XosFormHelpers", function controller($injector, LabelFormatter, _, XosFormHelpers) {
-        var _this = this;
-
-        // TODO
-        // - Validate the config (what if resource does not exist?)
-
-        // NOTE
-        // Corner case
-        // - if response is empty, how can we generate a form ?
-
-        this.responseMsg = false;
-        this.responseErr = false;
-
-        this.tableConfig = {
-          columns: [],
-          actions: [{
-            label: 'delete',
-            icon: 'remove',
-            cb: function cb(item) {
-              _this.Resource.delete({ id: item.id }).$promise.then(function () {
-                _.remove(_this.data, function (d) {
-                  return d.id === item.id;
-                });
-                _this.responseMsg = _this.config.resource + ' with id ' + item.id + ' successfully deleted';
-              }).catch(function (err) {
-                _this.responseErr = err.data.detail || 'Error while deleting ' + _this.config.resource + ' with id ' + item.id;
-              });
-            },
-            color: 'red'
-          }, {
-            label: 'details',
-            icon: 'search',
-            cb: function cb(item) {
-              _this.detailedItem = item;
-            }
-          }],
-          classes: 'table table-striped table-bordered table-responsive',
-          filter: 'field',
-          order: true,
-          pagination: {
-            pageSize: 10
-          }
-        };
-
-        this.formConfig = {
-          exclude: this.config.hiddenFields,
-          fields: {},
-          formName: this.config.resource + 'Form',
-          actions: [{
-            label: 'Save',
-            icon: 'ok',
-            cb: function cb(item) {
-              var p = void 0;
-              var isNew = true;
-
-              if (item.id) {
-                p = item.$update();
-                isNew = false;
-              } else {
-                p = item.$save();
-              }
-
-              p.then(function (res) {
-                if (isNew) {
-                  _this.data.push(angular.copy(res));
-                }
-                delete _this.detailedItem;
-                _this.responseMsg = _this.config.resource + ' with id ' + item.id + ' successfully saved';
-              }).catch(function (err) {
-                _this.responseErr = err.data.detail || 'Error while saving ' + _this.config.resource + ' with id ' + item.id;
-              });
-            },
-            class: 'success'
-          }]
-        };
-
-        this.cleanForm = function () {
-          delete _this.detailedItem;
-        };
-
-        this.createItem = function () {
-          _this.detailedItem = new _this.Resource();
-        };
-
-        this.Resource = $injector.get(this.config.resource);
-
-        var getData = function getData() {
-          _this.Resource.query().$promise.then(function (res) {
-
-            if (!res[0]) {
-              return;
-            }
-
-            var item = res[0];
-            var props = Object.keys(item);
-
-            _.remove(props, function (p) {
-              return p == 'id' || p == 'validators';
-            });
-
-            // TODO move out cb,  non sense triggering a lot of times
-            if (angular.isArray(_this.config.hiddenFields)) {
-              props = _.difference(props, _this.config.hiddenFields);
-            }
-
-            var labels = props.map(function (p) {
-              return LabelFormatter.format(p);
-            });
-
-            props.forEach(function (p, i) {
-              var fieldConfig = {
-                label: labels[i],
-                prop: p
-              };
-
-              if (typeof item[p] !== 'string' && typeof item[p] !== 'undefined') {
-                fieldConfig.type = _typeof(item[p]);
-              }
-
-              _this.tableConfig.columns.push(fieldConfig);
-            });
-
-            // build form structure
-            // TODO move in a pure function for testing purposes
-            props.forEach(function (p, i) {
-              _this.formConfig.fields[p] = {
-                label: LabelFormatter.format(labels[i]).replace(':', ''),
-                type: XosFormHelpers._getFieldFormat(item[p])
-              };
-            });
-
-            _this.data = res;
-          });
-        };
-
-        getData();
-      }]
-    };
-  });
-})();
-//# sourceMappingURL=../../../maps/ui_components/smartComponents/smartTable/smartTable.component.js.map
-
-'use strict';
-
-/**
- * © OpenCORD
- *
- * Visit http://guide.xosproject.org/devguide/addview/ for more information
- *
- * Created by teone on 3/24/16.
- */
-
-(function () {
-  'use strict';
-
-  angular.module('xos.uiComponents')
-  /**
-    * @ngdoc directive
-    * @name xos.uiComponents.directive:xosSmartPie
-    * @restrict E
-    * @description The xos-table directive
-    * @param {Object} config The configuration for the component,
-    * it is composed by the name of an angular [$resource](https://docs.angularjs.org/api/ngResource/service/$resource)
-    * and a field name that is used to group the data.
-    * ```
-    * {
-        resource: 'Users',
-        groupBy: 'fieldName',
-        classes: 'my-custom-class',
-        labelFormatter: (labels) => {
-          // here you can format your label,
-          // you should return an array with the same order
-          return labels;
-        }
-      }
-    * ```
-    * @scope
-    * @example
-    
-    Displaying Local data
-     <example module="sampleSmartPieLocal">
-      <file name="index.html">
-        <div ng-controller="SampleCtrlLocal as vm">
-          <xos-smart-pie config="vm.configLocal"></xos-smart-pie>
-        </div>
-      </file>
-      <file name="script.js">
-        angular.module('sampleSmartPieLocal', ['xos.uiComponents'])
-        .factory('_', function($window){
-          return $window._;
-        })
-        .controller('SampleCtrlLocal', function($timeout){
-          
-          this.datas = [
-            {id: 1, first_name: 'Jon', last_name: 'aaa', category: 2},
-            {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 1},
-            {id: 3, first_name: 'Aria', last_name: 'Stark', category: 2}
-          ];
-           this.configLocal = {
-            data: [],
-            groupBy: 'category',
-            classes: 'local',
-            labelFormatter: (labels) => {
-              return labels.map(l => l === '1' ? 'North' : 'Dragon');
-            }
-          };
-          
-          $timeout(() => {
-            // this need to be triggered in this way just because of ngDoc,
-            // otherwise you can assign data directly in the config
-            this.configLocal.data = this.datas;
-          }, 1)
-        });
-      </file>
-    </example>
-     Fetching data from API
-     <example module="sampleSmartPieResource">
-      <file name="index.html">
-        <div ng-controller="SampleCtrl as vm">
-          <xos-smart-pie config="vm.config"></xos-smart-pie>
-        </div>
-      </file>
-      <file name="script.js">
-        angular.module('sampleSmartPieResource', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
-        .controller('SampleCtrl', function(){
-          this.config = {
-            resource: 'SampleResource',
-            groupBy: 'category',
-            classes: 'resource',
-            labelFormatter: (labels) => {
-              return labels.map(l => l === '1' ? 'North' : 'Dragon');
-            }
-          };
-        });
-      </file>
-      <file name="backendPoll.js">
-        angular.module('sampleSmartPieResource')
-        .run(function($httpBackend, _){
-          let datas = [
-            {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
-            {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
-            {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1}
-          ];
-           $httpBackend.whenGET('/test').respond(200, datas)
-        })
-        .factory('_', function($window){
-          return $window._;
-        })
-        .service('SampleResource', function($resource){
-          return $resource('/test/:id', {id: '@id'});
-        })
-      </file>
-    </example>
-     Polling data from API
-     <example module="sampleSmartPiePoll">
-      <file name="index.html">
-        <div ng-controller="SampleCtrl as vm">
-          <xos-smart-pie config="vm.config"></xos-smart-pie>
-        </div>
-      </file>
-      <file name="script.js">
-        angular.module('sampleSmartPiePoll', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
-        .controller('SampleCtrl', function(){
-          this.config = {
-            resource: 'SampleResource',
-            groupBy: 'category',
-            poll: 2,
-            labelFormatter: (labels) => {
-              return labels.map(l => l === '1' ? 'Active' : 'Banned');
-            }
-          };
-        });
-      </file>
-      <file name="backend.js">
-        angular.module('sampleSmartPiePoll')
-        .run(function($httpBackend, _){
-          let mock = [
-            [
-              {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
-              {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
-              {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1},
-              {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 1}
-            ],
-             [
-              {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
-              {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
-              {id: 3, first_name: 'Aria', last_name: 'Stark', category: 2},
-              {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 2}
-            ],
-             [
-              {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
-              {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
-              {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1},
-              {id: 3, first_name: 'Tyrion', last_name: 'Lannister', category: 2}
-            ]
-          ];
-          $httpBackend.whenGET('/test').respond(function(method, url, data, headers, params) {
-            return [200, mock[Math.round(Math.random() * 3)]];
-          });
-        })
-        .factory('_', function($window){
-          return $window._;
-        })
-        .service('SampleResource', function($resource){
-          return $resource('/test/:id', {id: '@id'});
-        })
-      </file>
-    </example>
-    */
-  .directive('xosSmartPie', function () {
-    return {
-      restrict: 'E',
-      scope: {
-        config: '='
-      },
-      template: '\n        <canvas\n          class="chart chart-pie {{vm.config.classes}}"\n          chart-data="vm.data" chart-labels="vm.labels"\n          chart-legend="{{vm.config.legend}}">\n        </canvas>\n      ',
-      bindToController: true,
-      controllerAs: 'vm',
-      controller: ["$injector", "$interval", "$scope", "$timeout", "_", function controller($injector, $interval, $scope, $timeout, _) {
-        var _this = this;
-
-        if (!this.config.resource && !this.config.data) {
-          throw new Error('[xosSmartPie] Please provide a resource or an array of data in the configuration');
-        }
-
-        var groupData = function groupData(data) {
-          return _.groupBy(data, _this.config.groupBy);
-        };
-        var formatData = function formatData(data) {
-          return _.reduce(Object.keys(data), function (list, group) {
-            return list.concat(data[group].length);
-          }, []);
-        };
-        var formatLabels = function formatLabels(data) {
-          return angular.isFunction(_this.config.labelFormatter) ? _this.config.labelFormatter(Object.keys(data)) : Object.keys(data);
-        };
-
-        var prepareData = function prepareData(data) {
-          // $timeout(() => {
-          // group data
-          var grouped = groupData(data);
-          _this.data = formatData(grouped);
-          // create labels
-          _this.labels = formatLabels(grouped);
-          // }, 10);
-        };
-
-        if (this.config.resource) {
-          (function () {
-
-            _this.Resource = $injector.get(_this.config.resource);
-            var getData = function getData() {
-              _this.Resource.query().$promise.then(function (res) {
-
-                if (!res[0]) {
-                  return;
-                }
-
-                prepareData(res);
-              });
-            };
-
-            getData();
-
-            if (_this.config.poll) {
-              $interval(function () {
-                getData();
-              }, _this.config.poll * 1000);
-            }
-          })();
-        } else {
-          $scope.$watch(function () {
-            return _this.config.data;
-          }, function (data) {
-            if (data) {
-              prepareData(_this.config.data);
-            }
-          }, true);
-        }
-
-        $scope.$on('create', function (event, chart) {
-          console.log('create: ' + chart.id);
-        });
-
-        $scope.$on('destroy', function (event, chart) {
-          console.log('destroy: ' + chart.id);
-        });
-      }]
-    };
-  });
-})();
-//# sourceMappingURL=../../../maps/ui_components/smartComponents/smartPie/smartPie.component.js.map
-
-'use strict';
-
-/**
- * © OpenCORD
- *
- * Visit http://guide.xosproject.org/devguide/addview/ for more information
- *
- * Created by teone on 4/15/16.
- */
-
-(function () {
-  'use strict';
-
-  angular.module('xos.uiComponents')
-
-  /**
-    * @ngdoc directive
-    * @name xos.uiComponents.directive:xosValidation
-    * @restrict E
-    * @description The xos-validation directive
-    * @param {Object} errors The error object
-    * @element ANY
-    * @scope
-  * @example
-  <example module="sampleValidation">
-    <file name="index.html">
-      <div ng-controller="SampleCtrl as vm">
-        <div class="row">
-          <div class="col-xs-12">
-            <label>Set an error type:</label>
-          </div>
-          <div class="col-xs-2">
-            <a class="btn"
-              ng-click="vm.errors.required = !vm.errors.required"
-              ng-class="{'btn-default': !vm.errors.required, 'btn-success': vm.errors.required}">
-              Required
-            </a>
-          </div>
-          <div class="col-xs-2">
-            <a class="btn"
-              ng-click="vm.errors.email = !vm.errors.email"
-              ng-class="{'btn-default': !vm.errors.email, 'btn-success': vm.errors.email}">
-              Email
-            </a>
-          </div>
-          <div class="col-xs-2">
-            <a class="btn"
-              ng-click="vm.errors.minlength = !vm.errors.minlength"
-              ng-class="{'btn-default': !vm.errors.minlength, 'btn-success': vm.errors.minlength}">
-              Min Length
-            </a>
-          </div>
-          <div class="col-xs-2">
-            <a class="btn"
-              ng-click="vm.errors.maxlength = !vm.errors.maxlength"
-              ng-class="{'btn-default': !vm.errors.maxlength, 'btn-success': vm.errors.maxlength}">
-              Max Length
-            </a>
-          </div>
-        </div>
-        <xos-validation errors="vm.errors"></xos-validation>
-      </div>
-    </file>
-    <file name="script.js">
-      angular.module('sampleValidation', ['xos.uiComponents'])
-      .controller('SampleCtrl', function(){
-        this.errors = {
-          email: false
-        }
-      });
-    </file>
-  </example>
-    */
-
-  .directive('xosValidation', function () {
-    return {
-      restrict: 'E',
-      scope: {
-        errors: '='
-      },
-      template: '\n        <div ng-cloak>\n          <!-- <pre>{{vm.errors.email | json}}</pre> -->\n          <xos-alert config="vm.config" show="vm.errors.required !== undefined && vm.errors.required !== false">\n            Field required\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.errors.email !== undefined && vm.errors.email !== false">\n            This is not a valid email\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.errors.minlength !== undefined && vm.errors.minlength !== false">\n            Too short\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.errors.maxlength !== undefined && vm.errors.maxlength !== false">\n            Too long\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.errors.custom !== undefined && vm.errors.custom !== false">\n            Field invalid\n          </xos-alert>\n        </div>\n      ',
-      transclude: true,
-      bindToController: true,
-      controllerAs: 'vm',
-      controller: function controller() {
-        this.config = {
-          type: 'danger'
-        };
-      }
-    };
-  });
-})();
-//# sourceMappingURL=../../../maps/ui_components/dumbComponents/validation/validation.component.js.map
-
-'use strict';
-
-/**
- * © OpenCORD
- *
- * Visit http://guide.xosproject.org/devguide/addview/ for more information
- *
- * Created by teone on 3/24/16.
- */
-
-(function () {
-  'use strict';
-
-  angular.module('xos.uiComponents')
-
-  /**
-  * @ngdoc directive
-  * @name xos.uiComponents.directive:xosTable
-  * @restrict E
-  * @description The xos-table directive
-  * @param {Object} config The configuration for the component.
-  * ```
-  * {
-  *   columns: [
-  *     {
-  *       label: 'Human readable name',
-  *       prop: 'Property to read in the model object',
-  *       type: 'boolean'| 'array'| 'object'| 'custom'| 'date' | 'icon' // see examples for more details
-          formatter: fn(), // receive the whole item if tipe is custom and return a string
-          link: fn() // receive the whole item and return an url
-  *     }
-  *   ],
-  *   classes: 'table table-striped table-bordered',
-  *   actions: [ // if defined add an action column
-        {
-          label: 'delete',
-          icon: 'remove', // refers to bootstraps glyphicon
-          cb: (user) => { // receive the model
-            console.log(user);
-          },
-          color: 'red'
-        }
-      ],
-      filter: 'field', // can be by `field` or `fulltext`
-      order: true | {field: 'property name', reverse: true | false} // whether to show ordering arrows, or a configuration for a default ordering
-  * }
-  * ```
-  * @param {Array} data The data that should be rendered
-  * @element ANY
-  * @scope
-  * @example
-   # Basic usage
-  <example module="sampleTable1">
-  <file name="index.html">
-    <div ng-controller="SampleCtrl1 as vm">
-      <xos-table data="vm.data" config="vm.config"></xos-table>
-    </div>
-  </file>
-  <file name="script.js">
-    angular.module('sampleTable1', ['xos.uiComponents'])
-    .factory('_', function($window){
-      return $window._;
-    })
-    .controller('SampleCtrl1', function(){
-      this.config = {
-        columns: [
-          {
-            label: 'First Name', // column title
-            prop: 'name' // property to read in the data array
-          },
-          {
-            label: 'Last Name',
-            prop: 'lastname'
-          }
-        ]
-      };
-       this.data = [
-        {
-          name: 'John',
-          lastname: 'Doe'
-        },
-        {
-          name: 'Gili',
-          lastname: 'Fereydoun'
-        }
-      ]
-    });
-  </file>
-  </example>
-   # Filtering
-  <example module="sampleTable2" animations="true">
-  <file name="index.html">
-    <div ng-controller="SampleCtrl2 as vm">
-      <xos-table data="vm.data" config="vm.config"></xos-table>
-    </div>
-  </file>
-  <file name="script.js">
-    angular.module('sampleTable2', ['xos.uiComponents', 'ngAnimate'])
-    .factory('_', function($window){
-      return $window._;
-    })
-    .controller('SampleCtrl2', function(){
-      this.config = {
-        columns: [
-          {
-            label: 'First Name', // column title
-            prop: 'name' // property to read in the data array
-          },
-          {
-            label: 'Last Name',
-            prop: 'lastname'
-          }
-        ],
-        classes: 'table table-striped table-condensed', // table classes, default to `table table-striped table-bordered`
-        actions: [ // if defined add an action column
-          {
-            label: 'delete', // label
-            icon: 'remove', // icons, refers to bootstraps glyphicon
-            cb: (user) => { // callback, get feeded with the full object
-              console.log(user);
-            },
-            color: 'red' // icon color
-          }
-        ],
-        filter: 'field', // can be by `field` or `fulltext`
-        order: true
-      };
-       this.data = [
-        {
-          name: 'John',
-          lastname: 'Doe'
-        },
-        {
-          name: 'Gili',
-          lastname: 'Fereydoun'
-        }
-      ]
-    });
-  </file>
-  </example>
-   # Pagination
-  <example module="sampleTable3">
-  <file name="index.html">
-    <div ng-controller="SampleCtrl3 as vm">
-      <xos-table data="vm.data" config="vm.config"></xos-table>
-    </div>
-  </file>
-  <file name="script.js">
-    angular.module('sampleTable3', ['xos.uiComponents'])
-    .factory('_', function($window){
-      return $window._;
-    })
-    .controller('SampleCtrl3', function(){
-      this.config = {
-        columns: [
-          {
-            label: 'First Name', // column title
-            prop: 'name' // property to read in the data array
-          },
-          {
-            label: 'Last Name',
-            prop: 'lastname'
-          }
-        ],
-        pagination: {
-          pageSize: 2
-        }
-      };
-       this.data = [
-        {
-          name: 'John',
-          lastname: 'Doe'
-        },
-        {
-          name: 'Gili',
-          lastname: 'Fereydoun'
-        },
-        {
-          name: 'Lucky',
-          lastname: 'Clarkson'
-        },
-        {
-          name: 'Tate',
-          lastname: 'Spalding'
-        }
-      ]
-    });
-  </file>
-  </example>
-   # Field formatter
-  <example module="sampleTable4">
-  <file name="index.html">
-    <div ng-controller="SampleCtrl as vm">
-      <xos-table data="vm.data" config="vm.config"></xos-table>
-    </div>
-  </file>
-  <file name="script.js">
-    angular.module('sampleTable4', ['xos.uiComponents'])
-    .factory('_', function($window){
-      return $window._;
-    })
-    .controller('SampleCtrl', function(){
-      this.config = {
-        columns: [
-          {
-            label: 'First Name',
-            prop: 'name',
-            link: item => `https://www.google.it/#q=${item.name}`
-          },
-          {
-            label: 'Enabled',
-            prop: 'enabled',
-            type: 'boolean'
-          },
-          {
-            label: 'Services',
-            prop: 'services',
-            type: 'array'
-          },
-          {
-            label: 'Details',
-            prop: 'details',
-            type: 'object'
-          },
-          {
-            label: 'Created',
-            prop: 'created',
-            type: 'date'
-          },
-          {
-            label: 'Icon',
-            type: 'icon',
-            formatter: item => item.icon //note that this refer to [Bootstrap Glyphicon](http://getbootstrap.com/components/#glyphicons)
-          }
-        ]
-      };
-       this.data = [
-        {
-          name: 'John',
-          enabled: true,
-          services: ['Cdn', 'IpTv'],
-          details: {
-            c_tag: '243',
-            s_tag: '444'
-          },
-          created: new Date('December 17, 1995 03:24:00'),
-          icon: 'music'
-        },
-        {
-          name: 'Gili',
-          enabled: false,
-          services: ['Cdn', 'IpTv', 'Cache'],
-          details: {
-            c_tag: '675',
-            s_tag: '893'
-          },
-          created: new Date(),
-          icon: 'camera'
-        }
-      ]
-    });
-  </file>
-  </example>
-  # Custom formatter
-  <example module="sampleTable5">
-  <file name="index.html">
-    <div ng-controller="SampleCtrl as vm">
-      <xos-table data="vm.data" config="vm.config"></xos-table>
-    </div>
-  </file>
-  <file name="script.js">
-    angular.module('sampleTable5', ['xos.uiComponents'])
-    .factory('_', function($window){
-      return $window._;
-    })
-    .controller('SampleCtrl', function(){
-      this.config = {
-        columns: [
-          {
-            label: 'Username',
-            prop: 'username'
-          },
-          {
-            label: 'Features',
-            type: 'custom',
-            formatter: (val) => {
-              
-              let cdnEnabled = val.features.cdn ? 'enabled' : 'disabled';
-              return `
-                Cdn is ${cdnEnabled},
-                uplink speed is ${val.features.uplink_speed}
-                and downlink speed is ${val.features.downlink_speed}
-              `;
-            }
-          }
-        ]
-      };
-       this.data = [
-        {
-          username: 'John',
-          features: {
-            "cdn": false,
-            "uplink_speed": 1000000000,
-            "downlink_speed": 1000000000,
-            "uverse": true,
-            "status": "enabled"
-          }
-        },
-        {
-          username: 'Gili',
-          features: {
-            "cdn": true,
-            "uplink_speed": 3000000000,
-            "downlink_speed": 2000000000,
-            "uverse": true,
-            "status": "enabled"
-          }
-        }
-      ]
-    });
-  </file>
-  </example>
-  **/
-
-  .directive('xosTable', function () {
-    return {
-      restrict: 'E',
-      scope: {
-        data: '=',
-        config: '='
-      },
-      template: '\n          <div ng-show="vm.data.length > 0">\n            <div class="row" ng-if="vm.config.filter == \'fulltext\'">\n              <div class="col-xs-12">\n                <input\n                  class="form-control"\n                  placeholder="Type to search.."\n                  type="text"\n                  ng-model="vm.query"/>\n              </div>\n            </div>\n            <table ng-class="vm.classes" ng-hide="vm.data.length == 0">\n              <thead>\n                <tr>\n                  <th ng-repeat="col in vm.columns">\n                    {{col.label}}\n                    <span ng-if="vm.config.order">\n                      <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = false">\n                        <i class="glyphicon glyphicon-chevron-up"></i>\n                      </a>\n                      <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = true">\n                        <i class="glyphicon glyphicon-chevron-down"></i>\n                      </a>\n                    </span>\n                  </th>\n                  <th ng-if="vm.config.actions">Actions:</th>\n                </tr>\n              </thead>\n              <tbody ng-if="vm.config.filter == \'field\'">\n                <tr>\n                  <td ng-repeat="col in vm.columns">\n                    <input\n                      ng-if="col.type !== \'boolean\'"\n                      class="form-control"\n                      placeholder="Type to search by {{col.label}}"\n                      type="text"\n                      ng-model="vm.query[col.prop]"/>\n                    <select\n                      ng-if="col.type === \'boolean\'"\n                      class="form-control"\n                      ng-model="vm.query[col.prop]">\n                      <option value="">-</option>\n                      <option value="true">True</option>\n                      <option value="false">False</option>\n                    </select>\n                  </td>\n                  <td ng-if="vm.config.actions"></td>\n                </tr>\n              </tbody>\n              <tbody>\n                <tr ng-repeat="item in vm.data | filter:vm.query | orderBy:vm.orderBy:vm.reverse | pagination:vm.currentPage * vm.config.pagination.pageSize | limitTo: (vm.config.pagination.pageSize || vm.data.length) track by $index">\n                  <td ng-repeat="col in vm.columns" link-wrapper>\n                    <span ng-if="!col.type">{{item[col.prop]}}</span>\n                    <span ng-if="col.type === \'boolean\'">\n                      <i class="glyphicon"\n                        ng-class="{\'glyphicon-ok\': item[col.prop], \'glyphicon-remove\': !item[col.prop]}">\n                      </i>\n                    </span>\n                    <span ng-if="col.type === \'date\'">\n                      {{item[col.prop] | date:\'H:mm MMM d, yyyy\'}}\n                    </span>\n                    <span ng-if="col.type === \'array\'">\n                      {{item[col.prop] | arrayToList}}\n                    </span>\n                    <span ng-if="col.type === \'object\'">\n                      <dl class="dl-horizontal">\n                        <span ng-repeat="(k,v) in item[col.prop]">\n                          <dt>{{k}}</dt>\n                          <dd>{{v}}</dd>\n                        </span>\n                      </dl>\n                    </span>\n                    <span ng-if="col.type === \'custom\'">\n                      {{col.formatter(item)}}\n                    </span>\n                    <span ng-if="col.type === \'icon\'">\n                      <i class="glyphicon glyphicon-{{col.formatter(item)}}">\n                      </i>\n                    </span>\n                  </td>\n                  <td ng-if="vm.config.actions">\n                    <a href=""\n                      ng-repeat="action in vm.config.actions"\n                      ng-click="action.cb(item)"\n                      title="{{action.label}}">\n                      <i\n                        class="glyphicon glyphicon-{{action.icon}}"\n                        style="color: {{action.color}};"></i>\n                    </a>\n                  </td>\n                </tr>\n              </tbody>\n            </table>\n            <xos-pagination\n              ng-if="vm.config.pagination"\n              page-size="vm.config.pagination.pageSize"\n              total-elements="vm.data.length"\n              change="vm.goToPage">\n              </xos-pagination>\n          </div>\n          <div ng-show="vm.data.length == 0 || !vm.data">\n             <xos-alert config="{type: \'info\'}">\n              No data to show.\n            </xos-alert>\n          </div>\n        ',
-      bindToController: true,
-      controllerAs: 'vm',
-      controller: ["_", function controller(_) {
-        var _this = this;
-
-        if (!this.config) {
-          throw new Error('[xosTable] Please provide a configuration via the "config" attribute');
-        }
-
-        if (!this.config.columns) {
-          throw new Error('[xosTable] Please provide a columns list in the configuration');
-        }
-
-        // handle default ordering
-        if (this.config.order && angular.isObject(this.config.order)) {
-          this.reverse = this.config.order.reverse || false;
-          this.orderBy = this.config.order.field || 'id';
-        }
-
-        // if columns with type 'custom' are provided
-        // check that a custom formatte3 is provided too
-        var customCols = _.filter(this.config.columns, { type: 'custom' });
-        if (angular.isArray(customCols) && customCols.length > 0) {
-          _.forEach(customCols, function (col) {
-            if (!col.formatter || !angular.isFunction(col.formatter)) {
-              throw new Error('[xosTable] You have provided a custom field type, a formatter function should provided too.');
-            }
-          });
-        }
-
-        // if columns with type 'icon' are provided
-        // check that a custom formatte3 is provided too
-        var iconCols = _.filter(this.config.columns, { type: 'icon' });
-        if (angular.isArray(iconCols) && iconCols.length > 0) {
-          _.forEach(iconCols, function (col) {
-            if (!col.formatter || !angular.isFunction(col.formatter)) {
-              throw new Error('[xosTable] You have provided an icon field type, a formatter function should provided too.');
-            }
-          });
-        }
-
-        // if a link property is passed,
-        // it should be a function
-        var linkedColumns = _.filter(this.config.columns, function (col) {
-          return angular.isDefined(col.link);
-        });
-        if (angular.isArray(linkedColumns) && linkedColumns.length > 0) {
-          _.forEach(linkedColumns, function (col) {
-            if (!angular.isFunction(col.link)) {
-              throw new Error('[xosTable] The link property should be a function.');
-            }
-          });
-        }
-
-        this.columns = this.config.columns;
-        this.classes = this.config.classes || 'table table-striped table-bordered';
-
-        if (this.config.actions) {
-          // TODO validate action format
-        }
-        if (this.config.pagination) {
-          this.currentPage = 0;
-          this.goToPage = function (n) {
-            _this.currentPage = n;
-          };
-        }
-      }]
-    };
-  })
-  // TODO move in separate files
-  // TODO test
-  .filter('arrayToList', function () {
-    return function (input) {
-      if (!angular.isArray(input)) {
-        return input;
-      }
-      return input.join(', ');
-    };
-  })
-  // TODO test
-  .directive('linkWrapper', function () {
-    return {
-      restrict: 'A',
-      transclude: true,
-      template: '\n          <a ng-if="col.link" href="{{col.link(item)}}">\n            <div ng-transclude></div>\n          </a>\n          <div ng-transclude ng-if="!col.link"></div>\n        '
-    };
-  });
-})();
-//# sourceMappingURL=../../../maps/ui_components/dumbComponents/table/table.component.js.map
-
-'use strict';
-
-/**
- * © OpenCORD
- *
- * Visit http://guide.xosproject.org/devguide/addview/ for more information
- *
- * Created by teone on 5/25/16.
- */
-
-(function () {
-  'use strict';
-
-  angular.module('xos.uiComponents')
-  /**
-    * @ngdoc directive
-    * @name xos.uiComponents.directive:xosField
-    * @restrict E
-    * @description The xos-field directive.
-    * This component decide, give a field wich kind of input it need to print.
-    * @param {string} name The field name
-    * @param {object} field The field configuration:
-    * ```
-    * {
-    *   label: 'Label',
-    *   type: 'number', //typeof field
-    *   validators: {} // see xosForm for more details
-    * }
-    * ```
-    * @param {mixed} ngModel The field value
-    */
-  .directive('xosField', ["RecursionHelper", function (RecursionHelper) {
-    return {
-      restrict: 'E',
-      scope: {
-        name: '=',
-        field: '=',
-        ngModel: '='
-      },
-      template: '\n        <label ng-if="vm.field.type !== \'object\'">{{vm.field.label}}</label>\n            <input\n              ng-if="vm.field.type !== \'boolean\' && vm.field.type !== \'object\'"\n              type="{{vm.field.type}}"\n              name="{{vm.name}}"\n              class="form-control"\n              ng-model="vm.ngModel"\n              ng-minlength="vm.field.validators.minlength || 0"\n              ng-maxlength="vm.field.validators.maxlength || 2000"\n              ng-required="vm.field.validators.required || false" />\n            <span class="boolean-field" ng-if="vm.field.type === \'boolean\'">\n              <button\n                class="btn btn-success"\n                ng-show="vm.ngModel"\n                ng-click="vm.ngModel = false">\n                <i class="glyphicon glyphicon-ok"></i>\n              </button>\n              <button\n                class="btn btn-danger"\n                ng-show="!vm.ngModel"\n                ng-click="vm.ngModel = true">\n                <i class="glyphicon glyphicon-remove"></i>\n              </button>\n            </span>\n            <div\n              class="panel panel-default object-field"\n              ng-if="vm.field.type == \'object\' && !vm.isEmptyObject(vm.ngModel)"\n              >\n              <div class="panel-heading">{{vm.field.label}}</div>\n              <div class="panel-body">\n                <div ng-repeat="(k, v) in vm.ngModel">\n                  <xos-field\n                    name="k"\n                    field="{label: k, type: vm.getType(v)}"\n                    ng-model="v">\n                  </xos-field>\n                </div>\n              </div>\n            </div>\n      ',
-      bindToController: true,
-      controllerAs: 'vm',
-      // the compile cicle is needed to support recursion
-      compile: function compile(element) {
-        return RecursionHelper.compile(element);
-      },
-      controller: ["XosFormHelpers", function controller(XosFormHelpers) {
-        // console.log('Field: ', this.name, this.field, this.ngModel);
-        if (!this.name) {
-          throw new Error('[xosField] Please provide a field name');
-        }
-        if (!this.field) {
-          throw new Error('[xosField] Please provide a field definition');
-        }
-        if (!angular.isDefined(this.ngModel)) {
-          throw new Error('[xosField] Please provide an ng-model');
-        }
-
-        this.getType = XosFormHelpers._getFieldFormat;
-
-        this.isEmptyObject = function (o) {
-          return Object.keys(o).length === 0;
-        };
-      }]
-    };
-  }]);
-})();
-//# sourceMappingURL=../../../maps/ui_components/dumbComponents/field/field.component.js.map
-
-'use strict';
-
-/**
- * © OpenCORD
- *
- * Visit http://guide.xosproject.org/devguide/addview/ for more information
- *
- * Created by teone on 4/15/16.
- */
-
-(function () {
-  'use strict';
-
-  angular.module('xos.uiComponents')
-
-  /**
-    * @ngdoc directive
-    * @name xos.uiComponents.directive:xosPagination
-    * @restrict E
-    * @description The xos-table directive
-    * @param {Number} pageSize Number of elements per page
-    * @param {Number} totalElements Number of total elements in the collection
-    * @param {Function} change The callback to be triggered on page change.
-    * * @element ANY
-    * @scope
-    * @example
-  <example module="samplePagination">
-    <file name="index.html">
-      <div ng-controller="SampleCtrl1 as vm">
-        <xos-pagination
-          page-size="vm.pageSize"
-          total-elements="vm.totalElements"
-          change="vm.change">
-        </xos-pagination>
-      </div>
-    </file>
-    <file name="script.js">
-      angular.module('samplePagination', ['xos.uiComponents'])
-      .controller('SampleCtrl1', function(){
-        this.pageSize = 10;
-        this.totalElements = 35;
-        this.change = (pageNumber) => {
-          console.log(pageNumber);
-        }
-      });
-    </file>
-  </example>
-  **/
-
-  .directive('xosPagination', function () {
-    return {
-      restrict: 'E',
-      scope: {
-        pageSize: '=',
-        totalElements: '=',
-        change: '='
-      },
-      template: '\n        <div class="row" ng-if="vm.pageList.length > 1">\n          <div class="col-xs-12 text-center">\n            <ul class="pagination">\n              <li\n                ng-click="vm.goToPage(vm.currentPage - 1)"\n                ng-class="{disabled: vm.currentPage == 0}">\n                <a href="" aria-label="Previous">\n                    <span aria-hidden="true">&laquo;</span>\n                </a>\n              </li>\n              <li ng-repeat="i in vm.pageList" ng-class="{active: i === vm.currentPage}">\n                <a href="" ng-click="vm.goToPage(i)">{{i + 1}}</a>\n              </li>\n              <li\n                ng-click="vm.goToPage(vm.currentPage + 1)"\n                ng-class="{disabled: vm.currentPage == vm.pages - 1}">\n                <a href="" aria-label="Next">\n                    <span aria-hidden="true">&raquo;</span>\n                </a>\n              </li>\n            </ul>\n          </div>\n        </div>\n      ',
-      bindToController: true,
-      controllerAs: 'vm',
-      controller: ["$scope", function controller($scope) {
-        var _this = this;
-
-        this.currentPage = 0;
-
-        this.goToPage = function (n) {
-          if (n < 0 || n === _this.pages) {
-            return;
-          }
-          _this.currentPage = n;
-          _this.change(n);
-        };
-
-        this.createPages = function (pages) {
-          var arr = [];
-          for (var i = 0; i < pages; i++) {
-            arr.push(i);
-          }
-          return arr;
-        };
-
-        // watch for data changes
-        $scope.$watch(function () {
-          return _this.totalElements;
-        }, function () {
-          if (_this.totalElements) {
-            _this.pages = Math.ceil(_this.totalElements / _this.pageSize);
-            _this.pageList = _this.createPages(_this.pages);
-          }
-        });
-      }]
-    };
-  }).filter('pagination', function () {
-    return function (input, start) {
-      if (!input || !angular.isArray(input)) {
-        return input;
-      }
-      start = parseInt(start, 10);
-      return input.slice(start);
-    };
-  });
-})();
-//# sourceMappingURL=../../../maps/ui_components/dumbComponents/pagination/pagination.component.js.map
-
-'use strict';
-
-/**
- * © OpenCORD
- *
- * Visit http://guide.xosproject.org/devguide/addview/ for more information
- *
- * Created by teone on 4/18/16.
- */
-
-(function () {
-  'use strict';
-
-  angular.module('xos.uiComponents')
-
-  /**
-    * @ngdoc directive
-    * @name xos.uiComponents.directive:xosForm
-    * @restrict E
-    * @description The xos-form directive.
-    * This components have two usage, given a model it is able to autogenerate a form or it can be configured to create a custom form.
-    * @param {Object} config The configuration object
-    * ```
-    * {
-    *   exclude: ['id', 'validators', 'created', 'updated', 'deleted'], //field to be skipped in the form, the provide values are concatenated
-    *   actions: [ // define the form buttons with related callback
-    *     {
-            label: 'save',
-            icon: 'ok', // refers to bootstraps glyphicon
-            cb: (user) => { // receive the model
-              console.log(user);
-            },
-            class: 'success'
-          }
-    *   ],
-    *   fields: {
-    *     field_name: {
-    *       label: 'Field Label',
-    *       type: 'string' // options are: [date, boolean, number, email, string],
-    *       validators: {
-    *         minlength: number,
-              maxlength: number,
-              required: boolean,
-              min: number,
-              max: number
-    *       }
-    *     }
-    *   }
-    * }
-    * ```
-    * @element ANY
-    * @scope
-    * @requires xos.uiComponents.directive:xosField
-    * @requires xos.uiComponents.XosFormHelpers
-    * @requires xos.helpers._
-    * @example
-    
-    Autogenerated form
-   <example module="sampleForm">
-    <file name="script.js">
-      angular.module('sampleForm', ['xos.uiComponents'])
-      .factory('_', function($window){
-        return $window._;
-      })
-      .controller('SampleCtrl', function(){
-        this.model = {
-          first_name: 'Jhon',
-          last_name: 'Doe',
-          email: 'jhon.doe@sample.com',
-          active: true,
-          birthDate: '2015-02-17T22:06:38.059000Z'
-        }
-        this.config = {
-          exclude: ['password', 'last_login'],
-          formName: 'sampleForm',
-          actions: [
-            {
-              label: 'Save',
-              icon: 'ok', // refers to bootstraps glyphicon
-              cb: (user) => { // receive the model
-                console.log(user);
-              },
-              class: 'success'
-            }
-          ]
-        };
-      });
-    </file>
-    <file name="index.html">
-      <div ng-controller="SampleCtrl as vm">
-        <xos-form ng-model="vm.model" config="vm.config"></xos-form>
-      </div>
-    </file>
-  </example>
-   Configuration defined form
-   <example module="sampleForm1">
-    <file name="script.js">
-      angular.module('sampleForm1', ['xos.uiComponents'])
-      .factory('_', function($window){
-        return $window._;
-      })
-      .controller('SampleCtrl1', function(){
-        this.model = {
-        };
-         this.config = {
-          exclude: ['password', 'last_login'],
-          formName: 'sampleForm1',
-          actions: [
-            {
-              label: 'Save',
-              icon: 'ok', // refers to bootstraps glyphicon
-              cb: (user) => { // receive the model
-                console.log(user);
-              },
-              class: 'success'
-            }
-          ],
-          fields: {
-            first_name: {
-              type: 'string',
-              validators: {
-                required: true
-              }
-            },
-            last_name: {
-              label: 'Surname',
-              type: 'string',
-              validators: {
-                required: true,
-                minlength: 10
-              }
-            },
-            age: {
-              type: 'number',
-              validators: {
-                required: true,
-                min: 21
-              }
-            },
-          }
-        };
-      });
-    </file>
-    <file name="index.html">
-      <div ng-controller="SampleCtrl1 as vm">
-        <xos-form ng-model="vm.model" config="vm.config"></xos-form>
-      </div>
-    </file>
-  </example>
-   **/
-
-  .directive('xosForm', function () {
-    return {
-      restrict: 'E',
-      scope: {
-        config: '=',
-        ngModel: '='
-      },
-      template: '\n        <ng-form name="vm.{{vm.config.formName || \'form\'}}">\n          <div class="form-group" ng-repeat="(name, field) in vm.formField">\n            <xos-field name="name" field="field" ng-model="vm.ngModel[name]"></xos-field>\n            <xos-validation errors="vm[vm.config.formName || \'form\'][name].$error"></xos-validation>\n          </div>\n          <div class="form-group" ng-if="vm.config.actions">\n            <button role="button" href=""\n              ng-repeat="action in vm.config.actions"\n              ng-click="action.cb(vm.ngModel)"\n              class="btn btn-{{action.class}}"\n              title="{{action.label}}">\n              <i class="glyphicon glyphicon-{{action.icon}}"></i>\n              {{action.label}}\n            </button>\n          </div>\n        </ng-form>\n      ',
-      bindToController: true,
-      controllerAs: 'vm',
-      controller: ["$scope", "$log", "_", "XosFormHelpers", function controller($scope, $log, _, XosFormHelpers) {
-        var _this = this;
-
-        if (!this.config) {
-          throw new Error('[xosForm] Please provide a configuration via the "config" attribute');
-        }
-
-        if (!this.config.actions) {
-          throw new Error('[xosForm] Please provide an action list in the configuration');
-        }
-
-        this.excludedField = ['id', 'validators', 'created', 'updated', 'deleted', 'backend_status'];
-        if (this.config && this.config.exclude) {
-          this.excludedField = this.excludedField.concat(this.config.exclude);
-        }
-
-        this.formField = [];
-        $scope.$watch(function () {
-          return _this.ngModel;
-        }, function (model) {
-
-          // empty from old stuff
-          _this.formField = {};
-
-          if (!model) {
-            return;
-          }
-
-          var diff = _.difference(Object.keys(model), _this.excludedField);
-          var modelField = XosFormHelpers.parseModelField(diff);
-          _this.formField = XosFormHelpers.buildFormStructure(modelField, _this.config.fields, model);
-        });
-      }]
-    };
-  });
-})();
-//# sourceMappingURL=../../../maps/ui_components/dumbComponents/form/form.component.js.map
-
-'use strict';
-
-/**
- * © OpenCORD
- *
- * Visit http://guide.xosproject.org/devguide/addview/ for more information
- *
- * Created by teone on 4/15/16.
- */
-
-(function () {
-  'use strict';
-
-  angular.module('xos.uiComponents')
-
-  /**
-    * @ngdoc directive
-    * @name xos.uiComponents.directive:xosAlert
-    * @restrict E
-    * @description The xos-alert directive
-    * @param {Object} config The configuration object
-    * ```
-    * {
-    *   type: 'danger', //info, success, warning
-    *   closeBtn: true, //default false
-    *   autoHide: 3000 //delay to automatically hide the alert
-    * }
-    * ```
-    * @param {Boolean=} show Binding to show and hide the alert, default to true
-    * @element ANY
-    * @scope
-    * @example
-  <example module="sampleAlert1">
-    <file name="index.html">
-      <div ng-controller="SampleCtrl1 as vm">
-        <xos-alert config="vm.config1">
-          A sample alert message
-        </xos-alert>
-        <xos-alert config="vm.config2">
-          A sample alert message (with close button)
-        </xos-alert>
-        <xos-alert config="vm.config3">
-          A sample info message
-        </xos-alert>
-        <xos-alert config="vm.config4">
-          A sample success message
-        </xos-alert>
-        <xos-alert config="vm.config5">
-          A sample warning message
-        </xos-alert>
-      </div>
-    </file>
-    <file name="script.js">
-      angular.module('sampleAlert1', ['xos.uiComponents'])
-      .controller('SampleCtrl1', function(){
-        this.config1 = {
-          type: 'danger'
-        };
-         this.config2 = {
-          type: 'danger',
-          closeBtn: true
-        };
-         this.config3 = {
-          type: 'info'
-        };
-         this.config4 = {
-          type: 'success'
-        };
-         this.config5 = {
-          type: 'warning'
-        };
-      });
-    </file>
-  </example>
-   <example module="sampleAlert2" animations="true">
-    <file name="index.html">
-      <div ng-controller="SampleCtrl as vm" class="row">
-        <div class="col-sm-4">
-          <a class="btn btn-default btn-block" ng-show="!vm.show" ng-click="vm.show = true">Show Alert</a>
-          <a class="btn btn-default btn-block" ng-show="vm.show" ng-click="vm.show = false">Hide Alert</a>
-        </div>
-        <div class="col-sm-8">
-          <xos-alert config="vm.config1" show="vm.show">
-            A sample alert message, not displayed by default.
-          </xos-alert>
-        </div>
-      </div>
-    </file>
-    <file name="script.js">
-      angular.module('sampleAlert2', ['xos.uiComponents', 'ngAnimate'])
-      .controller('SampleCtrl', function(){
-        this.config1 = {
-          type: 'success'
-        };
-         this.show = false;
-      });
-    </file>
-  </example>
-  **/
-
-  .directive('xosAlert', function () {
-    return {
-      restrict: 'E',
-      scope: {
-        config: '=',
-        show: '=?'
-      },
-      template: '\n        <div ng-cloak class="alert alert-{{vm.config.type}}" ng-hide="!vm.show">\n          <button type="button" class="close" ng-if="vm.config.closeBtn" ng-click="vm.dismiss()">\n            <span aria-hidden="true">&times;</span>\n          </button>\n          <p ng-transclude></p>\n        </div>\n      ',
-      transclude: true,
-      bindToController: true,
-      controllerAs: 'vm',
-      controller: ["$timeout", function controller($timeout) {
-        var _this = this;
-
-        if (!this.config) {
-          throw new Error('[xosAlert] Please provide a configuration via the "config" attribute');
-        }
-
-        // default the value to true
-        this.show = this.show !== false;
-
-        this.dismiss = function () {
-          _this.show = false;
-        };
-
-        if (this.config.autoHide) {
-          (function () {
-            var to = $timeout(function () {
-              _this.dismiss();
-              $timeout.cancel(to);
-            }, _this.config.autoHide);
-          })();
-        }
-      }]
-    };
-  });
-})();
-//# sourceMappingURL=../../../maps/ui_components/dumbComponents/alert/alert.component.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  /**
-  * @ngdoc service
-  * @name xos.uiComponents.LabelFormatter
-  * @description This factory define a set of helper function to format label started from an object property
-  **/
-
-  angular.module('xos.uiComponents').factory('LabelFormatter', labelFormatter);
-
-  function labelFormatter() {
-
-    var _formatByUnderscore = function _formatByUnderscore(string) {
-      return string.split('_').join(' ').trim();
-    };
-
-    var _formatByUppercase = function _formatByUppercase(string) {
-      return string.split(/(?=[A-Z])/).map(function (w) {
-        return w.toLowerCase();
-      }).join(' ');
-    };
-
-    var _capitalize = function _capitalize(string) {
-      return string.slice(0, 1).toUpperCase() + string.slice(1);
-    };
-
-    var format = function format(string) {
-      string = _formatByUnderscore(string);
-      string = _formatByUppercase(string);
-
-      string = _capitalize(string).replace(/\s\s+/g, ' ') + ':';
-      return string.replace('::', ':');
-    };
-
-    return {
-      // test export
-      _formatByUnderscore: _formatByUnderscore,
-      _formatByUppercase: _formatByUppercase,
-      _capitalize: _capitalize,
-      // export to use
-      format: format
-    };
-  }
-})();
-//# sourceMappingURL=../../../maps/services/helpers/ui/label_formatter.service.js.map
-
-'use strict';
-
-var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
-
-(function () {
-
-  angular.module('xos.uiComponents')
-
-  /**
-  * @ngdoc service
-  * @name xos.uiComponents.XosFormHelpers
-  * @requires xos.uiComponents.LabelFormatter
-  * @requires xos.helpers._
-  **/
-
-  .service('XosFormHelpers', ["_", "LabelFormatter", function (_, LabelFormatter) {
-    var _this = this;
-
-    /**
-    * @ngdoc method
-    * @name xos.uiComponents.XosFormHelpers#_isEmail
-    * @methodOf xos.uiComponents.XosFormHelpers
-    * @description
-    * Return true if the string is an email address
-    * @param {string} text The string to be evaluated
-    * @returns {boolean} If the string match an email format
-    **/
-
-    this._isEmail = function (text) {
-      var re = /(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/;
-      return re.test(text);
-    };
-
-    /**
-    * @ngdoc method
-    * @name xos.uiComponents.XosFormHelpers#_getFieldFormat
-    * @methodOf xos.uiComponents.XosFormHelpers
-    * @description
-    * Return the type of the input
-    * @param {mixed} value The data to be evaluated
-    * @returns {string} The type of the input
-    **/
-
-    this._getFieldFormat = function (value) {
-
-      if (angular.isArray(value)) {
-        return 'array';
-      }
-
-      // check if is date
-      if (_.isDate(value) || !Number.isNaN(Date.parse(value)) && new Date(value).getTime() > 631180800000) {
-        return 'date';
-      }
-
-      // check if is boolean
-      // isNaN(false) = false, false is a number (0), true is a number (1)
-      if (typeof value === 'boolean') {
-        return 'boolean';
-      }
-
-      // check if a string is an email
-      if (_this._isEmail(value)) {
-        return 'email';
-      }
-
-      // if null return string
-      if (typeof value === 'string' || value === null) {
-        return 'text';
-      }
-
-      return typeof value === 'undefined' ? 'undefined' : _typeof(value);
-    };
-
-    /**
-    * @ngdoc method
-    * @name xos.uiComponents.XosFormHelpers#buildFormStructure
-    * @methodOf xos.uiComponents.XosFormHelpers
-    * @description
-    * Return the type of the input
-    * @param {object} modelField An object containing one property for each field of the model
-    * @param {object} customField An object containing one property for each field custom field
-    * @param {object} model The actual model on wich build the form structure (it is used to determine the type of the input)
-    * @returns {object} An object describing the form structure in the form of:
-    * ```
-    * {
-    *   'field-name': {
-    *     label: 'Label',
-    *     type: 'number', //typeof field
-    *     validators: {} // see xosForm for more details
-    *   }
-    * }
-    * ```
-    **/
-
-    this.buildFormStructure = function (modelField, customField, model) {
-
-      modelField = Object.keys(modelField).length > 0 ? modelField : customField; //if no model field are provided, check custom
-      customField = customField || {};
-
-      return _.reduce(Object.keys(modelField), function (form, f) {
-
-        form[f] = {
-          label: customField[f] && customField[f].label ? customField[f].label + ':' : LabelFormatter.format(f),
-          type: customField[f] && customField[f].type ? customField[f].type : _this._getFieldFormat(model[f]),
-          validators: customField[f] && customField[f].validators ? customField[f].validators : {}
-        };
-
-        if (form[f].type === 'date') {
-          model[f] = new Date(model[f]);
-        }
-
-        if (form[f].type === 'number') {
-          model[f] = parseInt(model[f], 10);
-        }
-
-        return form;
-      }, {});
-    };
-
-    /**
-    * @ngdoc method
-    * @name xos.uiComponents.XosFormHelpers#parseModelField
-    * @methodOf xos.uiComponents.XosFormHelpers
-    * @description
-    * Helpers for buildFormStructure, convert a list of model properties in an object used to build the form structure, eg:
-    * ```
-    * // input:
-    * ['id', 'name'm 'mail']
-    *
-    * // output
-    * {
-    *   id: {},
-    *   name: {},
-    *   mail: {}
-    * }
-    * ```
-    * @param {array} fields An array of fields representing the model properties
-    * @returns {object} An object containing one property for each field of the model
-    **/
-
-    this.parseModelField = function (fields) {
-      return _.reduce(fields, function (form, f) {
-        form[f] = {};
-        return form;
-      }, {});
-    };
-  }]);
-})();
-//# sourceMappingURL=../../../maps/services/helpers/ui/form.helpers.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  config.$inject = ["$httpProvider", "$interpolateProvider", "$resourceProvider"];
-  angular.module('bugSnag', []).factory('$exceptionHandler', function () {
-    return function (exception, cause) {
-      if (window.Bugsnag) {
-        Bugsnag.notifyException(exception, { diagnostics: { cause: cause } });
-      } else {
-        console.error(exception, cause, exception.stack);
-      }
-    };
-  });
-
-  /**
-  * @ngdoc overview
-  * @name xos.helpers
-  * @description this is the module that group all the helpers service and components for XOS
-  **/
-
-  angular.module('xos.helpers', ['ngCookies', 'ngResource', 'ngAnimate', 'bugSnag', 'xos.uiComponents', 'RecursionHelper']).config(config)
-
-  /**
-  * @ngdoc service
-  * @name xos.helpers._
-  * @description Wrap [lodash](https://lodash.com/docs) in an Angular Service
-  **/
-
-  .factory('_', ["$window", function ($window) {
-    return $window._;
-  }]);
-
-  function config($httpProvider, $interpolateProvider, $resourceProvider) {
-    $httpProvider.interceptors.push('SetCSRFToken');
-
-    $interpolateProvider.startSymbol('{$');
-    $interpolateProvider.endSymbol('$}');
-
-    // NOTE http://www.masnun.com/2013/09/18/django-rest-framework-angularjs-resource-trailing-slash-problem.html
-    $resourceProvider.defaults.stripTrailingSlashes = false;
-  }
-})();
-//# sourceMappingURL=maps/xosHelpers.module.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.vSG-Collection
-  * @description Angular resource to fetch /api/service/vsg/
-  **/
-  .service('vSG-Collection', ["$resource", function ($resource) {
-    return $resource('/api/service/vsg/');
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/vSG.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.vOLT-Collection
-  * @description Angular resource to fetch /api/tenant/cord/volt/:volt_id/
-  **/
-  .service('vOLT-Collection', ["$resource", function ($resource) {
-    return $resource('/api/tenant/cord/volt/:volt_id/', { volt_id: '@id' }, {
-      update: { method: 'PUT' }
-    });
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/vOLT.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.Login
-  * @description Angular resource to fetch /api/utility/login/
-  **/
-  .service('Login', ["$resource", function ($resource) {
-    return $resource('/api/utility/login/');
-  }])
-  /**
-  * @ngdoc service
-  * @name xos.helpers.Logout
-  * @description Angular resource to fetch /api/utility/logout/
-  **/
-  .service('Logout', ["$resource", function ($resource) {
-    return $resource('/api/utility/logout/');
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/Utility.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.Users
-  * @description Angular resource to fetch /api/core/users/:id/
-  **/
-  .service('Users', ["$resource", function ($resource) {
-    return $resource('/api/core/users/:id/', { id: '@id' }, {
-      update: { method: 'PUT' }
-    });
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/Users.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.Truckroll
-  * @description Angular resource to fetch /api/tenant/truckroll/:id/
-  **/
-  .service('Truckroll', ["$resource", function ($resource) {
-    return $resource('/api/tenant/truckroll/:id/', { id: '@id' }, {
-      update: { method: 'PUT' }
-    });
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/Truckroll.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.Tenant
-  * @description Angular resource to fetch /api/core/tenant/:id/
-  **/
-  .service('Tenants', ["$resource", function ($resource) {
-    return $resource('/api/core/tenants/:id/', { id: '@id' }, {
-      update: { method: 'PUT' }
-    });
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/Tenant.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.Subscribers
-  * @description Angular resource to fetch Subscribers
-  **/
-  .service('Subscribers', ["$resource", function ($resource) {
-    return $resource('/api/tenant/cord/subscriber/:id/', { id: '@id' }, {
-      update: { method: 'PUT' },
-      /**
-      * @ngdoc method
-      * @name xos.helpers.Subscribers#View-a-Subscriber-Features-Detail
-      * @methodOf xos.helpers.Subscribers
-      * @description
-      * View-a-Subscriber-Features-Detail
-      **/
-      'View-a-Subscriber-Features-Detail': {
-        method: 'GET',
-        isArray: false,
-        url: '/api/tenant/cord/subscriber/:id/features/'
-      },
-      /**
-      * @ngdoc method
-      * @name xos.helpers.Subscribers#Read-Subscriber-uplink_speed
-      * @methodOf xos.helpers.Subscribers
-      * @description
-      * Read-Subscriber-uplink_speed
-      **/
-      'Read-Subscriber-uplink_speed': {
-        method: 'GET',
-        isArray: false,
-        url: '/api/tenant/cord/subscriber/:id/features/uplink_speed/'
-      },
-      /**
-      * @ngdoc method
-      * @name xos.helpers.Subscribers#Update-Subscriber-uplink_speed
-      * @methodOf xos.helpers.Subscribers
-      * @description
-      * Update-Subscriber-uplink_speed
-      **/
-      'Update-Subscriber-uplink_speed': {
-        method: 'PUT',
-        isArray: false,
-        url: '/api/tenant/cord/subscriber/:id/features/uplink_speed/'
-      },
-      /**
-      * @ngdoc method
-      * @name xos.helpers.Subscribers#Read-Subscriber-downlink_speed
-      * @methodOf xos.helpers.Subscribers
-      * @description
-      * Read-Subscriber-downlink_speed
-      **/
-      'Read-Subscriber-downlink_speed': {
-        method: 'GET',
-        isArray: false,
-        url: '/api/tenant/cord/subscriber/:id/features/downlink_speed/'
-      },
-      /**
-      * @ngdoc method
-      * @name xos.helpers.Subscribers#Update-Subscriber-downlink_speed
-      * @methodOf xos.helpers.Subscribers
-      * @description
-      * Update-Subscriber-downlink_speed
-      **/
-      'Update-Subscriber-downlink_speed': {
-        method: 'PUT',
-        isArray: false,
-        url: '/api/tenant/cord/subscriber/:id/features/downlink_speed/'
-      },
-      /**
-      * @ngdoc method
-      * @name xos.helpers.Subscribers#Read-Subscriber-cdn
-      * @methodOf xos.helpers.Subscribers
-      * @description
-      * Read-Subscriber-cdn
-      **/
-      'Read-Subscriber-cdn': {
-        method: 'GET',
-        isArray: false,
-        url: '/api/tenant/cord/subscriber/:id/features/cdn/'
-      },
-      /**
-      * @ngdoc method
-      * @name xos.helpers.Subscribers#Update-Subscriber-cdn
-      * @methodOf xos.helpers.Subscribers
-      * @description
-      * Update-Subscriber-cdn
-      **/
-      'Update-Subscriber-cdn': {
-        method: 'PUT',
-        isArray: false,
-        url: '/api/tenant/cord/subscriber/:id/features/cdn/'
-      },
-      /**
-      * @ngdoc method
-      * @name xos.helpers.Subscribers#Read-Subscriber-uverse
-      * @methodOf xos.helpers.Subscribers
-      * @description
-      * Read-Subscriber-uverse
-      **/
-      'Read-Subscriber-uverse': {
-        method: 'GET',
-        isArray: false,
-        url: '/api/tenant/cord/subscriber/:id/features/uverse/'
-      },
-      /**
-      * @ngdoc method
-      * @name xos.helpers.Subscribers#Update-Subscriber-uverse
-      * @methodOf xos.helpers.Subscribers
-      * @description
-      * Update-Subscriber-uverse
-      **/
-      'Update-Subscriber-uverse': {
-        method: 'PUT',
-        isArray: false,
-        url: '/api/tenant/cord/subscriber/:id/features/uverse/'
-      },
-      /**
-      * @ngdoc method
-      * @name xos.helpers.Subscribers#Read-Subscriber-status
-      * @methodOf xos.helpers.Subscribers
-      * @description
-      * Read-Subscriber-status
-      **/
-      'Read-Subscriber-status': {
-        method: 'GET',
-        isArray: false,
-        url: '/api/tenant/cord/subscriber/:id/features/status/'
-      },
-      /**
-      * @ngdoc method
-      * @name xos.helpers.Subscribers#Update-Subscriber-status
-      * @methodOf xos.helpers.Subscribers
-      * @description
-      * Update-Subscriber-status
-      **/
-      'Update-Subscriber-status': {
-        method: 'PUT',
-        isArray: false,
-        url: '/api/tenant/cord/subscriber/:id/features/status/'
-      }
-    });
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/Subscribers.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.SlicesPlus
-  * @description Angular resource to fetch /api/utility/slicesplus/
-  * This is a read-only API and only the `query` method is currently supported.
-  **/
-  .service('SlicesPlus', ["$http", "$q", function ($http, $q) {
-    this.query = function (params) {
-      var deferred = $q.defer();
-
-      $http.get('/api/utility/slicesplus/', { params: params }).then(function (res) {
-        deferred.resolve(res.data);
-      }).catch(function (res) {
-        deferred.reject(res.data);
-      });
-
-      return { $promise: deferred.promise };
-    };
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/Slices_plus.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.Slices
-  * @description Angular resource to fetch /api/core/slices/:id/
-  **/
-  .service('Slices', ["$resource", function ($resource) {
-    return $resource('/api/core/slices/:id/', { id: '@id' }, {
-      update: { method: 'PUT' }
-    });
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/Slices.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.Sites
-  * @description Angular resource to fetch /api/core/sites/:id/
-  **/
-  .service('Sites', ["$resource", function ($resource) {
-    return $resource('/api/core/sites/:id/', { id: '@id' }, {
-      update: { method: 'PUT' }
-    });
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/Sites.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.Services
-  * @description Angular resource to fetch /api/core/services/:id/
-  **/
-  .service('Services', ["$resource", function ($resource) {
-    return $resource('/api/core/services/:id/', { id: '@id' }, {
-      update: { method: 'PUT' }
-    });
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/Services.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.ONOS-Services-Collection
-  * @description Angular resource to fetch /api/service/onos/
-  **/
-  .service('ONOS-Services-Collection', ["$resource", function ($resource) {
-    return $resource('/api/service/onos/');
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/ONOS-Services.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.ONOS-App-Collection
-  * @description Angular resource to fetch /api/tenant/onos/app/
-  **/
-  .service('ONOS-App-Collection', ["$resource", function ($resource) {
-    return $resource('/api/tenant/onos/app/');
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/ONOS-Apps.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.Nodes
-  * @description Angular resource to fetch /api/core/nodes/:id/
-  **/
-  .service('Nodes', ["$resource", function ($resource) {
-    return $resource('/api/core/nodes/:id/', { id: '@id' }, {
-      update: { method: 'PUT' }
-    });
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/Nodes.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.Networks
-  * @description Angular resource to fetch /api/core/networks/:id/
-  **/
-  .service('Networks', ["$resource", function ($resource) {
-    return $resource('/api/core/networks/:id/', { id: '@id' }, {
-      update: { method: 'PUT' }
-    });
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/Networks.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.Instances
-  * @description Angular resource to fetch /api/core/instances/:id/
-  **/
-  .service('Instances', ["$resource", function ($resource) {
-    return $resource('/api/core/instances/:id/', { id: '@id' }, {
-      update: { method: 'PUT' }
-    });
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/Instances.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.Flavors
-  * @description Angular resource to fetch /api/core/flavors/:id/
-  **/
-  .service('Flavors', ["$resource", function ($resource) {
-    return $resource('/api/core/flavors/:id/', { id: '@id' }, {
-      update: { method: 'PUT' }
-    });
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/Flavors.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.Example-Services-Collection
-  * @description Angular resource to fetch /api/service/exampleservice/
-  **/
-  .service('Example-Services-Collection', ["$resource", function ($resource) {
-    return $resource('/api/service/exampleservice/');
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/Example.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  angular.module('xos.helpers')
-  /**
-  * @ngdoc service
-  * @name xos.helpers.Deployments
-  * @description Angular resource to fetch /api/core/deployments/:id/
-  **/
-  .service('Deployments', ["$resource", function ($resource) {
-    return $resource('/api/core/deployments/:id/', { id: '@id' }, {
-      update: { method: 'PUT' }
-    });
-  }]);
-})();
-//# sourceMappingURL=../../maps/services/rest/Deployments.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  /**
-  * @ngdoc service
-  * @name xos.helpers.ServiceGraph
-  * @description This factory define a set of helper function to query the service tenancy graph
-  **/
-
-  angular.module('xos.helpers').service('GraphService', ["$q", "Tenants", "Services", function ($q, Tenants, Services) {
-    var _this = this;
-
-    this.loadCoarseData = function () {
-
-      var services = void 0;
-
-      var deferred = $q.defer();
-
-      Services.query().$promise.then(function (res) {
-        services = res;
-        return Tenants.query({ kind: 'coarse' }).$promise;
-      }).then(function (tenants) {
-        deferred.resolve({
-          tenants: tenants,
-          services: services
-        });
-      });
-
-      return deferred.promise;
-    };
-
-    this.getCoarseGraph = function () {
-      _this.loadCoarseData().then(function (res) {
-        console.log(res);
-      });
-      return 'ciao';
-    };
-  }]);
-})();
-//# sourceMappingURL=../maps/services/service_graph.service.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  /**
-  * @ngdoc service
-  * @name xos.helpers.NoHyperlinks
-  * @description This factory is automatically loaded trough xos.helpers and will add an $http interceptor that will add ?no_hyperlinks=1 to your api request, that is required by django
-  **/
-
-  angular.module('xos.helpers').factory('NoHyperlinks', noHyperlinks);
-
-  function noHyperlinks() {
-    return {
-      request: function request(_request) {
-        if (_request.url.indexOf('.html') === -1) {
-          _request.url += '?no_hyperlinks=1';
-        }
-        return _request;
-      }
-    };
-  }
-})();
-//# sourceMappingURL=../maps/services/noHyperlinks.interceptor.js.map
-
-'use strict';
-
-// TODO write tests for log
-
-angular.module('xos.helpers').config(['$provide', function ($provide) {
-  // Use the `decorator` solution to substitute or attach behaviors to
-  // original service instance; @see angular-mocks for more examples....
-
-  $provide.decorator('$log', ['$delegate', function ($delegate) {
-
-    var isLogEnabled = function isLogEnabled() {
-      return window.location.href.indexOf('debug=true') >= 0;
-    };
-    // Save the original $log.debug()
-    var logFn = $delegate.log;
-    var infoFn = $delegate.info;
-    var warnFn = $delegate.warn;
-    var errorFn = $delegate.error;
-    var debugFn = $delegate.debug;
-
-    // create the replacement function
-    var replacement = function replacement(fn) {
-      return function () {
-        // console.log(`Is Log Enabled: ${isLogEnabled()}`)
-        if (!isLogEnabled()) {
-          // console.log('logging is disabled');
-          return;
-        }
-        var args = [].slice.call(arguments);
-        var now = new Date();
-
-        // Prepend timestamp
-        args[0] = '[' + now.getHours() + ':' + now.getMinutes() + ':' + now.getSeconds() + '] ' + args[0];
-
-        // HACK awfull fix for angular mock implementation whithin jasmine test failing issue
-        if (typeof $delegate.reset === 'function' && !($delegate.debug.logs instanceof Array)) {
-          // if we are within the mock and did not reset yet, we call it to avoid issue
-          // console.log('mock log impl fix to avoid logs array not existing...');
-          $delegate.reset();
-        }
-
-        // Call the original with the output prepended with formatted timestamp
-        fn.apply(null, args);
-      };
-    };
-
-    $delegate.info = replacement(infoFn);
-    $delegate.log = replacement(logFn);
-    $delegate.warn = replacement(warnFn);
-    $delegate.error = replacement(errorFn);
-    $delegate.debug = replacement(debugFn);
-
-    return $delegate;
-  }]);
-}]);
-//# sourceMappingURL=../maps/services/log.decorator.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  /**
-  * @ngdoc service
-  * @name xos.uiComponents.LabelFormatter
-  * @description This factory define a set of helper function to format label started from an object property
-  **/
-
-  angular.module('xos.uiComponents').factory('LabelFormatter', labelFormatter);
-
-  function labelFormatter() {
-
-    var _formatByUnderscore = function _formatByUnderscore(string) {
-      return string.split('_').join(' ').trim();
-    };
-
-    var _formatByUppercase = function _formatByUppercase(string) {
-      return string.split(/(?=[A-Z])/).map(function (w) {
-        return w.toLowerCase();
-      }).join(' ');
-    };
-
-    var _capitalize = function _capitalize(string) {
-      return string.slice(0, 1).toUpperCase() + string.slice(1);
-    };
-
-    var format = function format(string) {
-      string = _formatByUnderscore(string);
-      string = _formatByUppercase(string);
-
-      string = _capitalize(string).replace(/\s\s+/g, ' ') + ':';
-      return string.replace('::', ':');
-    };
-
-    return {
-      // test export
-      _formatByUnderscore: _formatByUnderscore,
-      _formatByUppercase: _formatByUppercase,
-      _capitalize: _capitalize,
-      // export to use
-      format: format
-    };
-  }
-})();
-//# sourceMappingURL=../maps/services/label_formatter.service.js.map
-
-'use strict';
-
-(function () {
-  'use strict';
-
-  /**
-  * @ngdoc service
-  * @name xos.helpers.SetCSRFToken
-  * @description This factory is automatically loaded trough xos.helpers and will add an $http interceptor that will the CSRF-Token to your request headers
-  **/
-
-  setCSRFToken.$inject = ["$cookies"];
-  angular.module('xos.helpers').factory('SetCSRFToken', setCSRFToken);
-
-  function setCSRFToken($cookies) {
-    return {
-      request: function request(_request) {
-        if (_request.method !== 'GET') {
-          _request.headers['X-CSRFToken'] = $cookies.get('xoscsrftoken');
-        }
-        return _request;
-      }
-    };
-  }
-})();
-//# sourceMappingURL=../maps/services/csrfToken.interceptor.js.map
+"use strict";!function(){angular.module("xos.uiComponents",["chart.js","RecursionHelper"])}(),function(){function e(){var e=function(e){return e.split("_").join(" ").trim()},n=function(e){return e.split(/(?=[A-Z])/).map(function(e){return e.toLowerCase()}).join(" ")},o=function(e){return e.slice(0,1).toUpperCase()+e.slice(1)},t=function(t){return t=e(t),t=n(t),t=o(t).replace(/\s\s+/g," ")+":",t.replace("::",":")};return{_formatByUnderscore:e,_formatByUppercase:n,_capitalize:o,format:t}}angular.module("xos.uiComponents").factory("LabelFormatter",e)}();var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};!function(){angular.module("xos.uiComponents").service("XosFormHelpers",["_","LabelFormatter",function(e,n){var o=this;this._isEmail=function(e){var n=/(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/;return n.test(e)},this._getFieldFormat=function(n){return angular.isArray(n)?"array":e.isDate(n)||!Number.isNaN(Date.parse(n))&&new Date(n).getTime()>6311808e5?"date":"boolean"==typeof n?"boolean":o._isEmail(n)?"email":"string"==typeof n||null===n?"text":"undefined"==typeof n?"undefined":_typeof(n)},this.buildFormStructure=function(t,i,r){return t=Object.keys(t).length>0?t:i,i=i||{},e.reduce(Object.keys(t),function(e,t){return e[t]={label:i[t]&&i[t].label?i[t].label+":":n.format(t),type:i[t]&&i[t].type?i[t].type:o._getFieldFormat(r[t]),validators:i[t]&&i[t].validators?i[t].validators:{},hint:i[t]&&i[t].hint?i[t].hint:""},"date"===e[t].type&&(r[t]=new Date(r[t])),"number"===e[t].type&&(r[t]=parseInt(r[t],10)),e},{})},this.parseModelField=function(n){return e.reduce(n,function(e,n){return e[n]={},e},{})}}])}(),function(){angular.module("xos.uiComponents").directive("xosValidation",function(){return{restrict:"E",scope:{field:"=",form:"="},template:'\n        <div ng-cloak>\n          <xos-alert config="vm.config" show="vm.field.$error.required !== undefined && vm.field.$error.required !== false  && (vm.field.$touched || vm.form.$submitted)">\n            Field required\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.email !== undefined && vm.field.$error.email !== false  && (vm.field.$touched || vm.form.$submitted)">\n            This is not a valid email\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.minlength !== undefined && vm.field.$error.minlength !== false  && (vm.field.$touched || vm.form.$submitted)">\n            Too short\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.maxlength !== undefined && vm.field.$error.maxlength !== false  && (vm.field.$touched || vm.form.$submitted)">\n            Too long\n          </xos-alert>\n          <xos-alert config="vm.config" show="vm.field.$error.custom !== undefined && vm.field.$error.custom !== false  && (vm.field.$touched || vm.form.$submitted)">\n            Field invalid\n          </xos-alert>\n        </div>\n      ',transclude:!0,bindToController:!0,controllerAs:"vm",controller:function(){this.config={type:"danger"}}}})}(),function(){angular.module("xos.uiComponents").directive("xosForm",function(){return{restrict:"E",scope:{config:"=",ngModel:"="},template:'\n        <ng-form name="vm.{{vm.config.formName || \'form\'}}">\n          <div class="form-group" ng-repeat="(name, field) in vm.formField">\n            <xos-field name="name" field="field" ng-model="vm.ngModel[name]"></xos-field>\n            <xos-validation errors="vm[vm.config.formName || \'form\'][name].$error"></xos-validation>\n          </div>\n          <div class="form-group" ng-if="vm.config.actions">\n            <button role="button" href=""\n              ng-repeat="action in vm.config.actions"\n              ng-click="action.cb(vm.ngModel)"\n              class="btn btn-{{action.class}}"\n              title="{{action.label}}">\n              <i class="glyphicon glyphicon-{{action.icon}}"></i>\n              {{action.label}}\n            </button>\n          </div>\n        </ng-form>\n      ',bindToController:!0,controllerAs:"vm",controller:["$scope","$log","_","XosFormHelpers",function(e,n,o,t){var i=this;if(!this.config)throw new Error('[xosForm] Please provide a configuration via the "config" attribute');if(!this.config.actions)throw new Error("[xosForm] Please provide an action list in the configuration");this.excludedField=["id","validators","created","updated","deleted","backend_status"],this.config&&this.config.exclude&&(this.excludedField=this.excludedField.concat(this.config.exclude)),this.formField=[],e.$watch(function(){return i.ngModel},function(e){if(i.formField={},e){var n=o.difference(Object.keys(e),i.excludedField),r=t.parseModelField(n);i.formField=t.buildFormStructure(r,i.config.fields,e)}})}]}})}(),function(){angular.module("xos.uiComponents").directive("xosTable",function(){return{restrict:"E",scope:{data:"=",config:"="},template:'\n          <div ng-show="vm.data.length > 0">\n            <div class="row" ng-if="vm.config.filter == \'fulltext\'">\n              <div class="col-xs-12">\n                <input\n                  class="form-control"\n                  placeholder="Type to search.."\n                  type="text"\n                  ng-model="vm.query"/>\n              </div>\n            </div>\n            <table ng-class="vm.classes" ng-hide="vm.data.length == 0">\n              <thead>\n                <tr>\n                  <th ng-repeat="col in vm.columns">\n                    {{col.label}}\n                    <span ng-if="vm.config.order">\n                      <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = false">\n                        <i class="glyphicon glyphicon-chevron-up"></i>\n                      </a>\n                      <a href="" ng-click="vm.orderBy = col.prop; vm.reverse = true">\n                        <i class="glyphicon glyphicon-chevron-down"></i>\n                      </a>\n                    </span>\n                  </th>\n                  <th ng-if="vm.config.actions">Actions:</th>\n                </tr>\n              </thead>\n              <tbody ng-if="vm.config.filter == \'field\'">\n                <tr>\n                  <td ng-repeat="col in vm.columns">\n                    <input\n                      ng-if="col.type !== \'boolean\'"\n                      class="form-control"\n                      placeholder="Type to search by {{col.label}}"\n                      type="text"\n                      ng-model="vm.query[col.prop]"/>\n                    <select\n                      ng-if="col.type === \'boolean\'"\n                      class="form-control"\n                      ng-model="vm.query[col.prop]">\n                      <option value="">-</option>\n                      <option value="true">True</option>\n                      <option value="false">False</option>\n                    </select>\n                  </td>\n                  <td ng-if="vm.config.actions"></td>\n                </tr>\n              </tbody>\n              <tbody>\n                <tr ng-repeat="item in vm.data | filter:vm.query | orderBy:vm.orderBy:vm.reverse | pagination:vm.currentPage * vm.config.pagination.pageSize | limitTo: (vm.config.pagination.pageSize || vm.data.length) track by $index">\n                  <td ng-repeat="col in vm.columns" link-wrapper>\n                    <span ng-if="!col.type">{{item[col.prop]}}</span>\n                    <span ng-if="col.type === \'boolean\'">\n                      <i class="glyphicon"\n                        ng-class="{\'glyphicon-ok\': item[col.prop], \'glyphicon-remove\': !item[col.prop]}">\n                      </i>\n                    </span>\n                    <span ng-if="col.type === \'date\'">\n                      {{item[col.prop] | date:\'H:mm MMM d, yyyy\'}}\n                    </span>\n                    <span ng-if="col.type === \'array\'">\n                      {{item[col.prop] | arrayToList}}\n                    </span>\n                    <span ng-if="col.type === \'object\'">\n                      <dl class="dl-horizontal">\n                        <span ng-repeat="(k,v) in item[col.prop]">\n                          <dt>{{k}}</dt>\n                          <dd>{{v}}</dd>\n                        </span>\n                      </dl>\n                    </span>\n                    <span ng-if="col.type === \'custom\'">\n                      {{col.formatter(item)}}\n                    </span>\n                    <span ng-if="col.type === \'icon\'">\n                      <i class="glyphicon glyphicon-{{col.formatter(item)}}">\n                      </i>\n                    </span>\n                  </td>\n                  <td ng-if="vm.config.actions">\n                    <a href=""\n                      ng-repeat="action in vm.config.actions"\n                      ng-click="action.cb(item)"\n                      title="{{action.label}}">\n                      <i\n                        class="glyphicon glyphicon-{{action.icon}}"\n                        style="color: {{action.color}};"></i>\n                    </a>\n                  </td>\n                </tr>\n              </tbody>\n            </table>\n            <xos-pagination\n              ng-if="vm.config.pagination"\n              page-size="vm.config.pagination.pageSize"\n              total-elements="vm.data.length"\n              change="vm.goToPage">\n              </xos-pagination>\n          </div>\n          <div ng-show="vm.data.length == 0 || !vm.data">\n             <xos-alert config="{type: \'info\'}">\n              No data to show.\n            </xos-alert>\n          </div>\n        ',bindToController:!0,controllerAs:"vm",controller:["_",function(e){var n=this;if(!this.config)throw new Error('[xosTable] Please provide a configuration via the "config" attribute');if(!this.config.columns)throw new Error("[xosTable] Please provide a columns list in the configuration");this.config.order&&angular.isObject(this.config.order)&&(this.reverse=this.config.order.reverse||!1,this.orderBy=this.config.order.field||"id");var o=e.filter(this.config.columns,{type:"custom"});angular.isArray(o)&&o.length>0&&e.forEach(o,function(e){if(!e.formatter||!angular.isFunction(e.formatter))throw new Error("[xosTable] You have provided a custom field type, a formatter function should provided too.")});var t=e.filter(this.config.columns,{type:"icon"});angular.isArray(t)&&t.length>0&&e.forEach(t,function(e){if(!e.formatter||!angular.isFunction(e.formatter))throw new Error("[xosTable] You have provided an icon field type, a formatter function should provided too.")});var i=e.filter(this.config.columns,function(e){return angular.isDefined(e.link)});angular.isArray(i)&&i.length>0&&e.forEach(i,function(e){if(!angular.isFunction(e.link))throw new Error("[xosTable] The link property should be a function.")}),this.columns=this.config.columns,this.classes=this.config.classes||"table table-striped table-bordered",this.config.actions,this.config.pagination&&(this.currentPage=0,this.goToPage=function(e){n.currentPage=e})}]}}).filter("arrayToList",function(){return function(e){return angular.isArray(e)?e.join(", "):e}}).directive("linkWrapper",function(){return{restrict:"A",transclude:!0,template:'\n          <a ng-if="col.link" href="{{col.link(item)}}">\n            <div ng-transclude></div>\n          </a>\n          <div ng-transclude ng-if="!col.link"></div>\n        '}})}(),function(){angular.module("xos.uiComponents").directive("xosPagination",function(){return{restrict:"E",scope:{pageSize:"=",totalElements:"=",change:"="},template:'\n        <div class="row" ng-if="vm.pageList.length > 1">\n          <div class="col-xs-12 text-center">\n            <ul class="pagination">\n              <li\n                ng-click="vm.goToPage(vm.currentPage - 1)"\n                ng-class="{disabled: vm.currentPage == 0}">\n                <a href="" aria-label="Previous">\n                    <span aria-hidden="true">&laquo;</span>\n                </a>\n              </li>\n              <li ng-repeat="i in vm.pageList" ng-class="{active: i === vm.currentPage}">\n                <a href="" ng-click="vm.goToPage(i)">{{i + 1}}</a>\n              </li>\n              <li\n                ng-click="vm.goToPage(vm.currentPage + 1)"\n                ng-class="{disabled: vm.currentPage == vm.pages - 1}">\n                <a href="" aria-label="Next">\n                    <span aria-hidden="true">&raquo;</span>\n                </a>\n              </li>\n            </ul>\n          </div>\n        </div>\n      ',bindToController:!0,controllerAs:"vm",controller:["$scope",function(e){var n=this;this.currentPage=0,this.goToPage=function(e){0>e||e===n.pages||(n.currentPage=e,n.change(e))},this.createPages=function(e){for(var n=[],o=0;e>o;o++)n.push(o);return n},e.$watch(function(){return n.totalElements},function(){n.totalElements&&(n.pages=Math.ceil(n.totalElements/n.pageSize),n.pageList=n.createPages(n.pages))})}]}}).filter("pagination",function(){return function(e,n){return e&&angular.isArray(e)?(n=parseInt(n,10),e.slice(n)):e}})}(),function(){angular.module("xos.uiComponents").directive("xosAlert",function(){return{restrict:"E",scope:{config:"=",show:"=?"},template:'\n        <div ng-cloak class="alert alert-{{vm.config.type}}" ng-hide="!vm.show">\n          <button type="button" class="close" ng-if="vm.config.closeBtn" ng-click="vm.dismiss()">\n            <span aria-hidden="true">&times;</span>\n          </button>\n          <p ng-transclude></p>\n        </div>\n      ',transclude:!0,bindToController:!0,controllerAs:"vm",controller:["$timeout",function(e){var n=this;if(!this.config)throw new Error('[xosAlert] Please provide a configuration via the "config" attribute');this.show=this.show!==!1,this.dismiss=function(){n.show=!1},this.config.autoHide&&!function(){var o=e(function(){n.dismiss(),e.cancel(o)},n.config.autoHide)}()}]}})}(),function(){angular.module("xos.uiComponents").directive("xosField",["RecursionHelper",function(e){return{restrict:"E",scope:{name:"=",field:"=",ngModel:"="},template:'\n        <label ng-if="vm.field.type !== \'object\'">{{vm.field.label}}</label>\n            <input\n              ng-if="vm.field.type !== \'boolean\' && vm.field.type !== \'object\'"\n              type="{{vm.field.type}}"\n              name="{{vm.name}}"\n              class="form-control"\n              ng-model="vm.ngModel"\n              ng-minlength="vm.field.validators.minlength || 0"\n              ng-maxlength="vm.field.validators.maxlength || 2000"\n              ng-required="vm.field.validators.required || false" />\n            <span class="boolean-field" ng-if="vm.field.type === \'boolean\'">\n              <button\n                class="btn btn-success"\n                ng-show="vm.ngModel"\n                ng-click="vm.ngModel = false">\n                <i class="glyphicon glyphicon-ok"></i>\n              </button>\n              <button\n                class="btn btn-danger"\n                ng-show="!vm.ngModel"\n                ng-click="vm.ngModel = true">\n                <i class="glyphicon glyphicon-remove"></i>\n              </button>\n            </span>\n            <div\n              class="panel panel-default object-field"\n              ng-if="vm.field.type == \'object\' && !vm.isEmptyObject(vm.ngModel)"\n              >\n              <div class="panel-heading">{{vm.field.label}}</div>\n              <div class="panel-body">\n                <div ng-repeat="(k, v) in vm.ngModel">\n                  <xos-field\n                    name="k"\n                    field="{label: vm.formatLabel(k), type: vm.getType(v)}"\n                    ng-model="v">\n                  </xos-field>\n                </div>\n              </div>\n            </div>\n      ',bindToController:!0,controllerAs:"vm",compile:function(n){return e.compile(n)},controller:["$attrs","XosFormHelpers","LabelFormatter",function(e,n,o){if(!this.name)throw new Error("[xosField] Please provide a field name");if(!this.field)throw new Error("[xosField] Please provide a field definition");if(!e.ngModel)throw new Error("[xosField] Please provide an ng-model");this.getType=n._getFieldFormat,this.formatLabel=o.format,this.isEmptyObject=function(e){return 0===Object.keys(e).length}}]}}])}();var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};!function(){angular.module("xos.uiComponents").directive("xosSmartTable",function(){return{restrict:"E",scope:{config:"="},template:'\n        <div class="row" ng-show="vm.data.length > 0">\n          <div class="col-xs-12 text-right">\n            <a href="" class="btn btn-success" ng-click="vm.createItem()">\n              Add\n            </a>\n          </div>\n        </div>\n        <div class="row">\n          <div class="col-xs-12 table-responsive">\n            <xos-table config="vm.tableConfig" data="vm.data"></xos-table>\n          </div>\n        </div>\n        <div class="panel panel-default" ng-show="vm.detailedItem">\n          <div class="panel-heading">\n            <div class="row">\n              <div class="col-xs-11">\n                <h3 class="panel-title" ng-show="vm.detailedItem.id">Update {{vm.config.resource}} {{vm.detailedItem.id}}</h3>\n                <h3 class="panel-title" ng-show="!vm.detailedItem.id">Create {{vm.config.resource}} item</h3>\n              </div>\n              <div class="col-xs-1">\n                <a href="" ng-click="vm.cleanForm()">\n                  <i class="glyphicon glyphicon-remove pull-right"></i>\n                </a>\n              </div>\n            </div>\n          </div>\n          <div class="panel-body">\n            <xos-form config="vm.formConfig" ng-model="vm.detailedItem"></xos-form>\n          </div>\n        </div>\n        <xos-alert config="{type: \'success\', closeBtn: true}" show="vm.responseMsg">{{vm.responseMsg}}</xos-alert>\n        <xos-alert config="{type: \'danger\', closeBtn: true}" show="vm.responseErr">{{vm.responseErr}}</xos-alert>\n      ',bindToController:!0,controllerAs:"vm",controller:["$injector","LabelFormatter","_","XosFormHelpers",function(e,n,o,t){var i=this;this.responseMsg=!1,this.responseErr=!1,this.tableConfig={columns:[],actions:[{label:"delete",icon:"remove",cb:function(e){i.Resource["delete"]({id:e.id}).$promise.then(function(){o.remove(i.data,function(n){return n.id===e.id}),i.responseMsg=i.config.resource+" with id "+e.id+" successfully deleted"})["catch"](function(n){i.responseErr=n.data.detail||"Error while deleting "+i.config.resource+" with id "+e.id})},color:"red"},{label:"details",icon:"search",cb:function(e){i.detailedItem=e}}],classes:"table table-striped table-bordered table-responsive",filter:"field",order:!0,pagination:{pageSize:10}},this.formConfig={exclude:this.config.hiddenFields,fields:{},formName:this.config.resource+"Form",actions:[{label:"Save",icon:"ok",cb:function(e){var n=void 0,o=!0;e.id?(n=e.$update(),o=!1):n=e.$save(),n.then(function(n){o&&i.data.push(angular.copy(n)),delete i.detailedItem,i.responseMsg=i.config.resource+" with id "+e.id+" successfully saved"})["catch"](function(n){i.responseErr=n.data.detail||"Error while saving "+i.config.resource+" with id "+e.id})},"class":"success"}]},this.cleanForm=function(){delete i.detailedItem},this.createItem=function(){i.detailedItem=new i.Resource},this.Resource=e.get(this.config.resource);var r=function(){i.Resource.query().$promise.then(function(e){if(e[0]){var r=e[0],s=Object.keys(r);o.remove(s,function(e){return"id"==e||"validators"==e}),angular.isArray(i.config.hiddenFields)&&(s=o.difference(s,i.config.hiddenFields));var a=s.map(function(e){return n.format(e)});s.forEach(function(e,n){var o={label:a[n],prop:e};"string"!=typeof r[e]&&"undefined"!=typeof r[e]&&(o.type=_typeof(r[e])),i.tableConfig.columns.push(o)}),s.forEach(function(e,o){i.formConfig.fields[e]={label:n.format(a[o]).replace(":",""),type:t._getFieldFormat(r[e])}}),i.data=e}})};r()}]}})}(),function(){angular.module("xos.uiComponents").directive("xosSmartPie",function(){return{restrict:"E",scope:{config:"="},template:'\n        <canvas\n          class="chart chart-pie {{vm.config.classes}}"\n          chart-data="vm.data" chart-labels="vm.labels"\n          chart-legend="{{vm.config.legend}}">\n        </canvas>\n      ',bindToController:!0,controllerAs:"vm",controller:["$injector","$interval","$scope","$timeout","_",function(e,n,o,t,i){var r=this;if(!this.config.resource&&!this.config.data)throw new Error("[xosSmartPie] Please provide a resource or an array of data in the configuration");var s=function(e){return i.groupBy(e,r.config.groupBy)},a=function(e){return i.reduce(Object.keys(e),function(n,o){return n.concat(e[o].length)},[])},c=function(e){return angular.isFunction(r.config.labelFormatter)?r.config.labelFormatter(Object.keys(e)):Object.keys(e)},l=function(e){var n=s(e);r.data=a(n),r.labels=c(n)};this.config.resource?!function(){r.Resource=e.get(r.config.resource);var o=function(){r.Resource.query().$promise.then(function(e){e[0]&&l(e)})};o(),r.config.poll&&n(function(){o()},1e3*r.config.poll)}():o.$watch(function(){return r.config.data},function(e){e&&l(r.config.data)},!0),o.$on("create",function(e,n){console.log("create: "+n.id)}),o.$on("destroy",function(e,n){console.log("destroy: "+n.id)})}]}})}(),function(){function e(e,n,o){e.interceptors.push("SetCSRFToken"),n.startSymbol("{$"),n.endSymbol("$}"),o.defaults.stripTrailingSlashes=!1}e.$inject=["$httpProvider","$interpolateProvider","$resourceProvider"],angular.module("bugSnag",[]).factory("$exceptionHandler",function(){return function(e,n){window.Bugsnag?Bugsnag.notifyException(e,{diagnostics:{cause:n}}):console.error(e,n,e.stack)}}),angular.module("xos.helpers",["ngCookies","ngResource","ngAnimate","bugSnag","xos.uiComponents"]).config(e).factory("_",["$window",function(e){return e._}])}(),function(){angular.module("xos.helpers").service("vSG-Collection",["$resource",function(e){return e("/api/service/vsg/")}])}(),function(){angular.module("xos.helpers").service("vOLT-Collection",["$resource",function(e){return e("/api/tenant/cord/volt/:volt_id/",{volt_id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Login",["$resource",function(e){return e("/api/utility/login/")}]).service("Logout",["$resource",function(e){return e("/api/utility/logout/")}])}(),function(){angular.module("xos.helpers").service("Users",["$resource",function(e){return e("/api/core/users/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Truckroll",["$resource",function(e){return e("/api/tenant/truckroll/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Tenants",["$resource",function(e){return e("/api/core/tenants/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Subscribers",["$resource",function(e){return e("/api/tenant/cord/subscriber/:id/",{id:"@id"},{update:{method:"PUT"},"View-a-Subscriber-Features-Detail":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/"},"Read-Subscriber-uplink_speed":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/uplink_speed/"},"Update-Subscriber-uplink_speed":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/uplink_speed/"},"Read-Subscriber-downlink_speed":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/downlink_speed/"},"Update-Subscriber-downlink_speed":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/downlink_speed/"},"Read-Subscriber-cdn":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/cdn/"},"Update-Subscriber-cdn":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/cdn/"},"Read-Subscriber-uverse":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/uverse/"},"Update-Subscriber-uverse":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/uverse/"},"Read-Subscriber-status":{method:"GET",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/status/"},"Update-Subscriber-status":{method:"PUT",isArray:!1,url:"/api/tenant/cord/subscriber/:id/features/status/"}})}])}(),function(){angular.module("xos.helpers").service("SlicesPlus",["$http","$q",function(e,n){this.query=function(o){var t=n.defer();return e.get("/api/utility/slicesplus/",{params:o}).then(function(e){t.resolve(e.data)})["catch"](function(e){t.reject(e.data)}),{$promise:t.promise}},this.get=function(o,t){var i=n.defer();return e.get("/api/utility/slicesplus/"+o,{params:t}).then(function(e){i.resolve(e.data)})["catch"](function(e){i.reject(e.data)}),{$promise:i.promise}}}])}(),function(){angular.module("xos.helpers").service("Slices",["$resource",function(e){return e("/api/core/slices/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Sites",["$resource",function(e){return e("/api/core/sites/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Services",["$resource",function(e){return e("/api/core/services/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("ONOS-Services-Collection",["$resource",function(e){return e("/api/service/onos/")}])}(),function(){angular.module("xos.helpers").service("ONOS-App-Collection",["$resource",function(e){return e("/api/tenant/onos/app/")}])}(),function(){angular.module("xos.helpers").service("Nodes",["$resource",function(e){return e("/api/core/nodes/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Networks",["$resource",function(e){return e("/api/core/networks/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Instances",["$resource",function(e){return e("/api/core/instances/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Flavors",["$resource",function(e){return e("/api/core/flavors/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("Example-Services-Collection",["$resource",function(e){return e("/api/service/exampleservice/")}])}(),function(){angular.module("xos.helpers").service("Deployments",["$resource",function(e){return e("/api/core/deployments/:id/",{id:"@id"},{update:{method:"PUT"}})}])}(),function(){angular.module("xos.helpers").service("XosUserPrefs",["$cookies",function(e){var n=this,o=e.get("xosUserPrefs")?JSON.parse(e.get("xosUserPrefs")):{};this.getAll=function(){return o=e.get("xosUserPrefs")?JSON.parse(e.get("xosUserPrefs")):{}},this.setAll=function(n){e.put("xosUserPrefs",JSON.stringify(n))},this.getSynchronizerNotificationStatus=function(){var e=arguments.length<=0||void 0===arguments[0]?!1:arguments[0];return e?n.getAll().synchronizers.notification[e]:n.getAll().synchronizers.notification},this.setSynchronizerNotificationStatus=function(){var e=arguments.length<=0||void 0===arguments[0]?!1:arguments[0],o=arguments[1];if(!e)throw new Error("[XosUserPrefs] When updating a synchronizer is mandatory to provide a name.");var t=n.getAll();t.synchronizers||(t.synchronizers={notification:{}}),t.synchronizers.notification[e]=o,n.setAll(t)}}])}(),function(){angular.module("xos.helpers").service("GraphService",["$q","Tenants","Services",function(e,n,o){var t=this;this.loadCoarseData=function(){var t=void 0,i=e.defer();return o.query().$promise.then(function(e){return t=e,n.query({kind:"coarse"}).$promise}).then(function(e){i.resolve({tenants:e,services:t})}),i.promise},this.getCoarseGraph=function(){return t.loadCoarseData().then(function(e){console.log(e)}),"ciao"}}])}(),function(){angular.module("xos.helpers").factory("Notification",function(){return window.Notification}).service("xosNotification",["$q","$log","Notification",function(e,n,o){var t=this;this.checkPermission=function(){var n=e.defer();return o.requestPermission().then(function(e){"granted"===e?n.resolve(e):n.reject(e)}),n.promise},this.sendNotification=function(e,t){var i=new o(e,t);i.onerror=function(e){n.error(e)}},this.notify=function(e,i){"Notification"in window?"granted"!==o.permission?t.checkPermission().then(function(){return t.sendNotification(e,i)}):"granted"===o.permission&&t.sendNotification(e,i):n.info("This browser does not support desktop notification")}}])}(),function(){function e(){return{request:function(e){return-1===e.url.indexOf(".html")&&(e.url+="?no_hyperlinks=1"),e}}}angular.module("xos.helpers").factory("NoHyperlinks",e)}(),angular.module("xos.helpers").config(["$provide",function(e){e.decorator("$log",["$delegate",function(e){var n=function(){return window.location.href.indexOf("debug=true")>=0},o=e.log,t=e.info,i=e.warn,r=e.error,s=e.debug,a=function(o){return function(){if(n()){var t=[].slice.call(arguments),i=new Date;t[0]="["+i.getHours()+":"+i.getMinutes()+":"+i.getSeconds()+"] "+t[0],"function"!=typeof e.reset||e.debug.logs instanceof Array||e.reset(),o.apply(null,t)}}};return e.info=a(t),e.log=a(o),e.warn=a(i),e.error=a(r),e.debug=a(s),e}])}]),function(){function e(){var e=function(e){return e.split("_").join(" ").trim()},n=function(e){return e.split(/(?=[A-Z])/).map(function(e){return e.toLowerCase()}).join(" ")},o=function(e){return e.slice(0,1).toUpperCase()+e.slice(1)},t=function(t){return t=e(t),t=n(t),t=o(t).replace(/\s\s+/g," ")+":",t.replace("::",":")};return{_formatByUnderscore:e,_formatByUppercase:n,_capitalize:o,format:t}}angular.module("xos.uiComponents").factory("LabelFormatter",e)}(),function(){function e(e){return{request:function(n){return"GET"!==n.method&&(n.headers["X-CSRFToken"]=e.get("xoscsrftoken")),n}}}e.$inject=["$cookies"],angular.module("xos.helpers").factory("SetCSRFToken",e)}();
\ No newline at end of file
diff --git a/xos/core/xoslib/static/js/xosSynchronizerNotifier.js b/xos/core/xoslib/static/js/xosSynchronizerNotifier.js
new file mode 100644
index 0000000..894f9ea
--- /dev/null
+++ b/xos/core/xoslib/static/js/xosSynchronizerNotifier.js
@@ -0,0 +1 @@
+"use strict";angular.module("xos.synchronizerNotifier",["ngResource","ngCookies","ui.router","xos.helpers"]).service("Diag",["$rootScope","$http","$q","$interval",function(n,t,s,e){var a=this,i=!1;this.getDiags=function(){var n=s.defer();return t.get("/api/core/diags").then(function(t){n.resolve(t.data)})["catch"](function(t){n.reject(t)}),n.promise},this.sendEvents=function(t){t.forEach(function(t){var s=JSON.parse(t.backend_register);s.last_run=new Date(1e3*s.last_run),s.last_duration=1e3*s.last_duration,s.last_synchronizer_start=new Date(1e3*s.last_synchronizer_start),s.last_syncrecord_start=s.last_syncrecord_start?new Date(1e3*s.last_syncrecord_start):null,n.$broadcast("diag",{name:t.name,updated:t.updated,info:s,status:a.getSyncStatus(s)})})},this.start=function(){return i=!0,a.getDiags().then(function(n){a.sendEvents(n)}),i},this.stop=function(){return i=!1},this.getSyncStatus=function(n){var t=new Date,s=9e5;return!(t-n.last_synchronizer_start>s&&t-n.last_syncrecord_start>s&&t-n.last_run>s)},e(function(){i&&a.getDiags().then(function(n){a.sendEvents(n)})},3e5)}]).directive("syncStatus",function(){return{restrict:"E",scope:{},bindToController:!0,controllerAs:"vm",templateUrl:"templates/sync-status.tpl.html",controller:["$log","$rootScope","Diag","xosNotification","XosUserPrefs",function(n,t,s,e,a){var i=this;s.start(),this.synchronizers={},this.showNoSync=!0,t.$on("diag",function(n,t){i.synchronizers[t.name]=t,t.status?a.setSynchronizerNotificationStatus(t.name,!1):(a.getSynchronizerNotificationStatus(t.name)||e.notify("CORD Synchronizer",{icon:"/static/cord-logo.png",body:"The "+t.name+" synchronizer has not performed actions in the last 15 minutes."}),a.setSynchronizerNotificationStatus(t.name,!0)),i.showNoSync=!1,0===Object.keys(i.synchronizers).length&&(i.showNoSync=!0)})}]}}),angular.element(document).ready(function(){angular.bootstrap("#xosSynchronizerNotifier",["xos.synchronizerNotifier"])}),angular.module("xos.synchronizerNotifier").run(["$templateCache",function(n){n.put("templates/sync-status.tpl.html",'<div class="sync-status-container">\n  <div class="btn btn-default" ng-click="vm.showNotificationPanel = !vm.showNotificationPanel">\n    <i class="glyphicon glyphicon-inbox"></i>\n  </div>\n  <div class="notification-panel panel panel-default" ng-show="vm.showNotificationPanel">\n    <ul class="list-group" ng-show="!vm.showNoSync">\n      <li class="list-group-item" ng-repeat="(syncName, syncStatus) in vm.synchronizers">\n        <span class="badge" ng-class="{success: syncStatus.status, warning: !syncStatus.status}">\n          <span ng-show="syncStatus.status"><i class="glyphicon glyphicon-ok"></i></span>\n          <span ng-hide="syncStatus.status"><i class="glyphicon glyphicon-time"></i></span>\n        </span>\n        <b>{{syncName}}</b>\n        <br/>\n        <small><i>{{syncStatus.info.last_run | date:\'mediumTime\'}}</i></small>\n      </li>\n    </ul>\n    <div class="alert alert-info" ng-show="vm.showNoSync">\n      No syncronizers are running.\n    </div>\n  </div>\n</div>\n')}]),angular.module("xos.synchronizerNotifier").run(["$location",function(n){n.path("/")}]);
\ No newline at end of file
diff --git a/xos/core/xoslib/static/js/xoslib/xos-backbone.js b/xos/core/xoslib/static/js/xoslib/xos-backbone.js
index 04d5fb7..d22d0ec 100644
--- a/xos/core/xoslib/static/js/xoslib/xos-backbone.js
+++ b/xos/core/xoslib/static/js/xoslib/xos-backbone.js
@@ -827,7 +827,7 @@
         define_model(this, {urlRoot: CORDSUBSCRIBER_API,
                             modelName: "cordSubscriber",
                             relatedCollections: {"cordUsers": "subscriber"},
-                            listFields: ["id", "service_specific_id", "vlan_id", "routeable_subnet"],
+                            listFields: ["id", "service_specific_id", "routeable_subnet"],
                             detailFields: ["id", "service_specific_id", "vcpe_id", "image_name", "instance_name",
                                            "firewall_enable", "firewall_rules", "url_filter_enable", "url_filter_rules", "cdn_enable",
                                            "nat_ip", "lan_ip", "wan_ip", "private_ip",
diff --git a/xos/services/cord/admin.py b/xos/services/cord/admin.py
index e7704d3..18f1e81 100644
--- a/xos/services/cord/admin.py
+++ b/xos/services/cord/admin.py
@@ -94,6 +94,59 @@
     def queryset(self, request):
         return VOLTTenant.get_tenant_objects_by_user(request.user)
 
+class AccessDeviceInline(XOSTabularInline):
+    model = AccessDevice
+    fields = ['volt_device','uplink','vlan']
+    readonly_fields = []
+    extra = 0
+#    max_num = 0
+    suit_classes = 'suit-tab suit-tab-accessdevices'
+
+#    @property
+#    def selflink_reverse_path(self):
+#        return "admin:cord_volttenant_change"
+
+class VOLTDeviceAdmin(ReadOnlyAwareAdmin):
+    list_display = ('backend_status_icon', 'name', 'openflow_id', 'driver' )
+    list_display_links = ('backend_status_icon', 'name', 'openflow_id')
+    fieldsets = [ (None, {'fields': ['backend_status_text','name','volt_service','openflow_id','driver','access_agent'],
+                          'classes':['suit-tab suit-tab-general']})]
+    readonly_fields = ('backend_status_text',)
+    inlines = [AccessDeviceInline]
+
+    suit_form_tabs = (('general','Details'), ('accessdevices','Access Devices'))
+
+class AccessDeviceAdmin(ReadOnlyAwareAdmin):
+    list_display = ('backend_status_icon', 'id', 'volt_device', 'uplink', 'vlan' )
+    list_display_links = ('backend_status_icon', 'id')
+    fieldsets = [ (None, {'fields': ['backend_status_text','volt_device','uplink','vlan'],
+                          'classes':['suit-tab suit-tab-general']})]
+    readonly_fields = ('backend_status_text',)
+
+    suit_form_tabs = (('general','Details'),)
+
+class AgentPortMappingInline(XOSTabularInline):
+    model = AgentPortMapping
+    fields = ['access_agent', 'mac', 'port']
+    readonly_fields = []
+    extra = 0
+#    max_num = 0
+    suit_classes = 'suit-tab suit-tab-accessportmaps'
+
+#    @property
+#    def selflink_reverse_path(self):
+#        return "admin:cord_volttenant_change"
+
+class AccessAgentAdmin(ReadOnlyAwareAdmin):
+    list_display = ('backend_status_icon', 'name', 'mac' )
+    list_display_links = ('backend_status_icon', 'name')
+    fieldsets = [ (None, {'fields': ['backend_status_text','name','volt_service','mac'],
+                          'classes':['suit-tab suit-tab-general']})]
+    readonly_fields = ('backend_status_text',)
+    inlines= [AgentPortMappingInline]
+
+    suit_form_tabs = (('general','Details'), ('accessportmaps', 'Port Mappings'))
+
 #-----------------------------------------------------------------------------
 # vCPE
 #-----------------------------------------------------------------------------
@@ -398,6 +451,10 @@
 
 admin.site.register(VOLTService, VOLTServiceAdmin)
 admin.site.register(VOLTTenant, VOLTTenantAdmin)
+admin.site.register(VOLTDevice, VOLTDeviceAdmin)
+admin.site.register(AccessDevice, AccessDeviceAdmin)
+admin.site.register(AccessAgent, AccessAgentAdmin)
+
 admin.site.register(VSGService, VSGServiceAdmin)
 admin.site.register(VSGTenant, VSGTenantAdmin)
 admin.site.register(VBNGService, VBNGServiceAdmin)
diff --git a/xos/services/cord/models.py b/xos/services/cord/models.py
index 48c9597..19b3ba6 100644
--- a/xos/services/cord/models.py
+++ b/xos/services/cord/models.py
@@ -1,5 +1,5 @@
 from django.db import models
-from core.models import Service, PlCoreBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor, Subscriber, NetworkParameter, NetworkParameterType, Port, AddressPool
+from core.models import Service, PlCoreBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor, Subscriber, NetworkParameter, NetworkParameterType, Port, AddressPool, User
 from core.models.plcorebase import StrippedCharField
 import os
 from django.db import models, transaction
@@ -188,15 +188,20 @@
     class Meta:
         app_label = "cord"
         verbose_name = "vOLT Service"
-        proxy = True
 
 class VOLTTenant(Tenant):
-    class Meta:
-        proxy = True
-
     KIND = VOLT_KIND
 
-    default_attributes = {"vlan_id": None, "s_tag": None, "c_tag": None}
+    class Meta:
+        app_label = "cord"
+        verbose_name = "vOLT Tenant"
+
+    s_tag = models.IntegerField(null=True, blank=True, help_text="s-tag")
+    c_tag = models.IntegerField(null=True, blank=True, help_text="c-tag")
+
+    # at some point, this should probably end up part of Tenant.
+    creator = models.ForeignKey(User, related_name='created_volts', blank=True, null=True)
+
     def __init__(self, *args, **kwargs):
         volt_services = VOLTService.get_service_objects().all()
         if volt_services:
@@ -205,32 +210,6 @@
         self.cached_vcpe = None
 
     @property
-    def s_tag(self):
-        return self.get_attribute("s_tag", self.default_attributes["s_tag"])
-
-    @s_tag.setter
-    def s_tag(self, value):
-        self.set_attribute("s_tag", value)
-
-    @property
-    def c_tag(self):
-        return self.get_attribute("c_tag", self.default_attributes["c_tag"])
-
-    @c_tag.setter
-    def c_tag(self, value):
-        self.set_attribute("c_tag", value)
-
-    # for now, vlan_id is a synonym for c_tag
-
-    @property
-    def vlan_id(self):
-        return self.c_tag
-
-    @vlan_id.setter
-    def vlan_id(self, value):
-        self.c_tag = value
-
-    @property
     def vcpe(self):
         vcpe = self.get_newest_subscribed_tenant(VSGTenant)
         if not vcpe:
@@ -257,28 +236,6 @@
             return None
         return subs[0]
 
-    @property
-    def creator(self):
-        if getattr(self, "cached_creator", None):
-            return self.cached_creator
-        creator_id=self.get_attribute("creator_id")
-        if not creator_id:
-            return None
-        users=User.objects.filter(id=creator_id)
-        if not users:
-            return None
-        user=users[0]
-        self.cached_creator = users[0]
-        return user
-
-    @creator.setter
-    def creator(self, value):
-        if value:
-            value = value.id
-        if (value != self.get_attribute("creator_id", None)):
-            self.cached_creator=None
-        self.set_attribute("creator_id", value)
-
     def manage_vcpe(self):
         # Each VOLT object owns exactly one VCPE object
 
@@ -347,9 +304,6 @@
 
         super(VOLTTenant, self).save(*args, **kwargs)
         model_policy_volt(self.pk)
-        #self.manage_vcpe()
-        #self.manage_subscriber()
-        #self.cleanup_orphans()
 
     def delete(self, *args, **kwargs):
         self.cleanup_vcpe()
@@ -366,6 +320,49 @@
         volt.manage_subscriber()
         volt.cleanup_orphans()
 
+class VOLTDevice(PlCoreBase):
+    class Meta:
+        app_label = "cord"
+
+    name = models.CharField(max_length=254, help_text="name of device", null=False, blank=False)
+    volt_service = models.ForeignKey(VOLTService, related_name='volt_devices')
+    openflow_id = models.CharField(max_length=254, help_text="OpenFlow ID", null=True, blank=True)
+    driver = models.CharField(max_length=254, help_text="driver", null=True, blank=True)
+    access_agent = models.ForeignKey("AccessAgent", related_name='volt_devices', blank=True, null=True)
+
+    def __unicode__(self): return u'%s' % (self.name)
+
+class AccessDevice(PlCoreBase):
+    class Meta:
+        app_label = "cord"
+
+    volt_device = models.ForeignKey(VOLTDevice, related_name='access_devices')
+    uplink = models.IntegerField(null=True, blank=True)
+    vlan = models.IntegerField(null=True, blank=True)
+
+    def __unicode__(self): return u'%s-%d:%d' % (self.volt_device.name,self.uplink,self.vlan)
+
+class AccessAgent(PlCoreBase):
+    class Meta:
+        app_label = "cord"
+
+    name = models.CharField(max_length=254, help_text="name of agent", null=False, blank=False)
+    volt_service = models.ForeignKey(VOLTService, related_name='access_agents')
+    mac = models.CharField(max_length=32, help_text="MAC Address or Access Agent", null=True, blank=True)
+
+    def __unicode__(self): return u'%s' % (self.name)
+
+class AgentPortMapping(PlCoreBase):
+    class Meta:
+        app_label = "cord"
+
+    access_agent = models.ForeignKey(AccessAgent, related_name='port_mappings')
+    mac = models.CharField(max_length=32, help_text="MAC Address", null=True, blank=True)
+    port = models.CharField(max_length=32, help_text="Openflow port ID", null=True, blank=True)
+
+    def __unicode__(self): return u'%s-%s-%s' % (self.access_agent.name, self.port, self.mac)
+
+
 # -------------------------------------------
 # VCPE
 # -------------------------------------------
diff --git a/xos/services/cord/templates/voltadmin.html b/xos/services/cord/templates/voltadmin.html
index e6887c5..807ab2c 100644
--- a/xos/services/cord/templates/voltadmin.html
+++ b/xos/services/cord/templates/voltadmin.html
@@ -1,6 +1,10 @@
 <div class = "row text-center">
     <div class="col-xs-12">
         <a href="/admin/cord/volttenant/">vOLT Tenants</a>
+    </div><div class="col-xs-12">
+        <a href="/admin/cord/voltdevice/">vOLT Devices</a>
+    </div><div class="col-xs-12">
+        <a href="/admin/cord/accessagent/">vOLT Access Agents</a>
     </div>
 </div>
 
diff --git a/xos/synchronizers/base/backend.py b/xos/synchronizers/base/backend.py
index d7307fa..af51e73 100644
--- a/xos/synchronizers/base/backend.py
+++ b/xos/synchronizers/base/backend.py
@@ -7,12 +7,16 @@
 from xos.logger import Logger, logging
 from synchronizers.model_policy import run_policy
 from xos.config import Config
+from django.utils import timezone
+from diag import update_diag
 
 logger = Logger(level=logging.INFO)
 
 class Backend:
 
     def run(self):
+        update_diag(sync_start=time.time(), backend_status="0 - Synchronizer Start")
+
         # start the openstack observer
         observer = XOSObserver()
         observer_thread = threading.Thread(target=observer.run,name='synchronizer')
diff --git a/xos/synchronizers/base/diag.py b/xos/synchronizers/base/diag.py
new file mode 100644
index 0000000..87fab70
--- /dev/null
+++ b/xos/synchronizers/base/diag.py
@@ -0,0 +1,40 @@
+import os
+import time
+import sys
+import traceback
+import json
+
+from core.models import Diag
+from xos.config import Config, XOS_DIR
+from xos.logger import Logger, logging, logger
+
+logger = Logger(level=logging.INFO)
+
+def update_diag(loop_end=None, loop_start=None, syncrecord_start=None, sync_start=None, backend_status=None):
+    try:
+        observer_name = Config().observer_name
+    except:
+        observer_name = 'openstack'
+
+    try:
+        diag = Diag.objects.filter(name=observer_name).first()
+        if (not diag):
+            diag = Diag(name=observer_name)
+        br_str = diag.backend_register
+        br = json.loads(br_str)
+        if loop_end:
+            br['last_run'] = loop_end
+        if loop_end and loop_start:
+            br['last_duration'] = loop_end - loop_start
+        if syncrecord_start:
+            br['last_syncrecord_start'] = syncrecord_start
+        if sync_start:
+            br['last_synchronizer_start'] = sync_start
+        if backend_status:
+            diag.backend_status = backend_status
+        diag.backend_register = json.dumps(br)
+        diag.save()
+    except:
+        logger.log_exc("Exception in update_diag")
+        traceback.print_exc()
+
diff --git a/xos/synchronizers/base/event_loop.py b/xos/synchronizers/base/event_loop.py
index 4f7d436..37ec4ca 100644
--- a/xos/synchronizers/base/event_loop.py
+++ b/xos/synchronizers/base/event_loop.py
@@ -28,6 +28,8 @@
 from synchronizers.base.error_mapper import *
 from synchronizers.openstack.openstacksyncstep import OpenStackSyncStep
 from synchronizers.base.steps.sync_object import SyncObject
+from django.utils import timezone
+from diag import update_diag
 
 # Load app models
 
@@ -521,20 +523,10 @@
 
                         loop_end = time.time()
 
-                        try:
-                            observer_name = Config().observer_name
-                        except:
-                            observer_name = ''
+                        update_diag(loop_end=loop_end, loop_start=loop_start, backend_status="1 - Bottom Of Loop")
 
-                        diag = Diag.objects.filter(name=observer_name).first()
-                        if (diag):
-                            br_str = diag.backend_register
-                            br = json.loads(br_str)
-                            br['last_run'] = loop_end
-                            br['last_duration'] = loop_end - loop_start
-                            diag.backend_register = json.dumps(br)
-                            diag.save() 
                 except Exception, e:
                         logger.error('Core error. This seems like a misconfiguration or bug: %r. This error will not be relayed to the user!' % e)
                         logger.log_exc("Exception in observer run loop")
                         traceback.print_exc()
+                        update_diag(backend_status="2 - Exception in Event Loop")
diff --git a/xos/synchronizers/base/syncstep.py b/xos/synchronizers/base/syncstep.py
index d505481..2fa6c38 100644
--- a/xos/synchronizers/base/syncstep.py
+++ b/xos/synchronizers/base/syncstep.py
@@ -10,8 +10,8 @@
 from django.db import reset_queries
 from synchronizers.base.ansible import *
 from generate.dependency_walker import *
+from diag import update_diag
 
-from time import time
 import json
 import time
 import pdb
@@ -236,9 +236,11 @@
 
                         self.sync_record(o)
 
-                        if (not run_always):
-                            o.enacted = new_enacted
+#                         if (not run_always):
+#                             o.enacted = new_enacted
 
+                        update_diag(syncrecord_start = time.time(), backend_status="1 - Synced Record")
+                        o.enacted = new_enacted
                         scratchpad = {'next_run':0, 'exponent':0, 'last_success':time.time()}
                         o.backend_register = json.dumps(scratchpad)
                         o.backend_status = "1 - OK"
diff --git a/xos/synchronizers/onos/steps/sync_onosapp.py b/xos/synchronizers/onos/steps/sync_onosapp.py
index 64c9452..3a9abfc 100644
--- a/xos/synchronizers/onos/steps/sync_onosapp.py
+++ b/xos/synchronizers/onos/steps/sync_onosapp.py
@@ -18,6 +18,7 @@
 from xos.logger import Logger, logging
 from services.vrouter.models import VRouterService
 from services.vtn.models import VTNService
+from services.cord.models import VOLTService, VOLTDevice, AccessDevice
 
 # hpclibrary will be in steps/..
 parentdir = os.path.join(os.path.dirname(__file__),"..")
@@ -243,18 +244,44 @@
         return json.dumps(data, indent=4, sort_keys=True)
 
     def get_volt_network_config(self, o, attrs):
-        data = {
-            "devices" : {
-                "of:1000000000000001" : {
-                    "accessDevice" : {
-                        "uplink" : "2",
-                        "vlan"   : "222",
-                    },
-                    "basic" : {
-                        "driver" : "pmc-olt"
-                    }
+        try:
+            volt = VOLTService.get_service_objects().all()[0]
+        except:
+            return None
+
+        devices = []
+        for voltdev in volt.volt_devices.all():
+            access_devices = []
+            for access in voltdev.access_devices.all():
+                access_device = {
+                    "uplink" : access.uplink,
+                    "vlan" : access.vlan
+                }
+                access_devices.append(access_device)
+
+            if voltdev.access_agent:
+                agent = voltdev.access_agent
+                olts = {}
+                for port_mapping in agent.port_mappings.all():
+                    olts[port_mapping.port] = port_mapping.mac
+                agent_config = {
+                    "olts" : olts,
+                    "mac" : agent.mac
+                }
+
+            device = {
+                voltdev.openflow_id : {
+                    "accessDevice" : access_devices,
+                    "accessAgent" : agent_config
+                },
+                "basic" : {
+                    "driver" : voltdev.driver
                 }
             }
+            devices.append(device)
+
+        data = {
+            "devices" : devices
         }
         return json.dumps(data, indent=4, sort_keys=True)
 
diff --git a/xos/synchronizers/vcpe/steps/sync_vcpetenant.py b/xos/synchronizers/vcpe/steps/sync_vcpetenant.py
index 9e3dfac..d8bc525 100644
--- a/xos/synchronizers/vcpe/steps/sync_vcpetenant.py
+++ b/xos/synchronizers/vcpe/steps/sync_vcpetenant.py
@@ -130,11 +130,9 @@
         else:
             logger.info("neither bbs_slice nor bbs_server is configured in the vCPE",extra=o.tologdict())
 
-        vlan_ids = []
         s_tags = []
         c_tags = []
         if o.volt:
-            vlan_ids.append(o.volt.vlan_id)  # XXX remove this
             s_tags.append(o.volt.s_tag)
             c_tags.append(o.volt.c_tag)
 
@@ -146,15 +144,14 @@
         safe_macs=[]
         if vcpe_service.url_filter_kind == "safebrowsing":
             if o.volt and o.volt.subscriber:
-                for user in o.volt.subscriber.users:
+                for user in o.volt.subscriber.devices:
                     level = user.get("level",None)
                     mac = user.get("mac",None)
                     if level in ["G", "PG"]:
                         if mac:
                             safe_macs.append(mac)
 
-        fields = {"vlan_ids": vlan_ids,   # XXX remove this
-                "s_tags": s_tags,
+        fields = {"s_tags": s_tags,
                 "c_tags": c_tags,
                 "dnsdemux_ip": dnsdemux_ip,
                 "cdn_prefixes": cdn_prefixes,
@@ -199,7 +196,7 @@
         if o.volt and o.volt.subscriber:
             url_filter_enable = o.volt.subscriber.url_filter_enable
             url_filter_level = o.volt.subscriber.url_filter_level
-            url_filter_users = o.volt.subscriber.users
+            url_filter_users = o.volt.subscriber.devices
 
         if service.url_filter_kind == "broadbandshield":
             # disable url_filter if there are no bbs_addrs
diff --git a/xos/synchronizers/vcpe/steps/sync_vcpetenant.yaml b/xos/synchronizers/vcpe/steps/sync_vcpetenant.yaml
index 3823328..9be0f98 100644
--- a/xos/synchronizers/vcpe/steps/sync_vcpetenant.yaml
+++ b/xos/synchronizers/vcpe/steps/sync_vcpetenant.yaml
@@ -9,10 +9,6 @@
       dnsdemux_ip: {{ dnsdemux_ip }}
       firewall_enable: {{ firewall_enable }}
       url_filter_enable: {{ url_filter_enable }}
-      vlan_ids:
-        {% for vlan_id in vlan_ids %}
-        - {{ vlan_id }}
-        {% endfor %}
       c_tags:
         {% for c_tag in c_tags %}
         - {{ c_tag }}
diff --git a/xos/synchronizers/vcpe/steps/sync_vcpetenant_new.yaml b/xos/synchronizers/vcpe/steps/sync_vcpetenant_new.yaml
index 324e274..435b721 100644
--- a/xos/synchronizers/vcpe/steps/sync_vcpetenant_new.yaml
+++ b/xos/synchronizers/vcpe/steps/sync_vcpetenant_new.yaml
@@ -10,10 +10,6 @@
       dnsdemux_ip: {{ dnsdemux_ip }}
       firewall_enable: {{ firewall_enable }}
       url_filter_enable: {{ url_filter_enable }}
-      vlan_ids:
-        {% for vlan_id in vlan_ids %}
-        - {{ vlan_id }}
-        {% endfor %}
       c_tags:
         {% for c_tag in c_tags %}
         - {{ c_tag }}
diff --git a/xos/synchronizers/vcpe/steps/sync_vcpetenant_vtn.yaml b/xos/synchronizers/vcpe/steps/sync_vcpetenant_vtn.yaml
index 09e4d23..b24d15a 100644
--- a/xos/synchronizers/vcpe/steps/sync_vcpetenant_vtn.yaml
+++ b/xos/synchronizers/vcpe/steps/sync_vcpetenant_vtn.yaml
@@ -10,10 +10,6 @@
       dnsdemux_ip: {{ dnsdemux_ip }}
       firewall_enable: {{ firewall_enable }}
       url_filter_enable: {{ url_filter_enable }}
-      vlan_ids:
-        {% for vlan_id in vlan_ids %}
-        - {{ vlan_id }}
-        {% endfor %}
       c_tags:
         {% for c_tag in c_tags %}
         - {{ c_tag }}
diff --git a/xos/synchronizers/vcpe/templates/vlan_sample.j2 b/xos/synchronizers/vcpe/templates/vlan_sample.j2
index a26c840..b73954b 100644
--- a/xos/synchronizers/vcpe/templates/vlan_sample.j2
+++ b/xos/synchronizers/vcpe/templates/vlan_sample.j2
@@ -1,5 +1,5 @@
 # below is a list of all vlan_ids associated with this vcpe
 
-{% for vlan_id in vlan_ids %}
+{% for vlan_id in c_tags %}
 {{ vlan_id }}
 {% endfor %}
diff --git a/xos/templates/admin/base.html b/xos/templates/admin/base.html
index ba01201..408a1e8 100644
--- a/xos/templates/admin/base.html
+++ b/xos/templates/admin/base.html
@@ -1,4 +1,4 @@
-{% load admin_static %}{% load suit_tags %}{% load url from future %}
+{% load admin_static %}{% load suit_tags core_tags %}{% load url from future %}
 <!DOCTYPE html>
 <html lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
 <head>
@@ -148,6 +148,7 @@
                     {% endblock %}
 
                     {% if user.is_active and user.is_staff %}
+                    {% notification %}
                       <div id="user-tools">
                         {% trans 'Welcome,' %}
                         <a href="http://{{ request.get_host}}/admin/core/user/{{user.id}}">{{user.email}}</a>
diff --git a/xos/templates/admin/tags/notification.html b/xos/templates/admin/tags/notification.html
new file mode 100644
index 0000000..558b9ff
--- /dev/null
+++ b/xos/templates/admin/tags/notification.html
@@ -0,0 +1 @@
+{{template | safe}}
\ No newline at end of file
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index 473e313..109fc1d 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -309,6 +309,16 @@
                 required: true
                 description: MAC address for this device.
 
+    tosca.nodes.VOLTService:
+        derived_from: tosca.nodes.Root
+        description: >
+            CORD: The vOLT Service
+        capabilities:
+            xos_base_service_caps
+        properties:
+            xos_base_props
+            xos_base_service_props
+
     tosca.nodes.VOLTTenant:
         derived_from: tosca.nodes.Root
         description: >
@@ -325,6 +335,58 @@
                 required: false
                 description: c_tag, identifies which subscriber within s_tag
 
+    tosca.nodes.VOLTDevice:
+        derived_from: tosca.nodes.Root
+        description: >
+            CORD: A vOLT Device.
+        properties:
+            xos_base_props
+            openflow_id:
+                type: string
+                required: false
+                description: openflow id
+            driver:
+                type: string
+                required: false
+                description: driver name
+            access_devices:
+                type: string
+                required: false
+                description: list of access devices, in format "uplink vlan", multiple entries separated by commas
+
+# XXX - uncomment if we want access device to be specified as separate Tosca
+# objects, rather than encoding them into VOLTDevice.access_devices
+#    tosca.nodes.AccessDevice:
+#        derived_from: tosca.nodes.Root
+#        description: >
+#            CORD: A vOLT Access Device.
+#        properties:
+#            xos_base_props
+#            uplink:
+#               type: integer
+#               required: false
+#               description: uplink
+#            vlan:
+#               type: integer
+#               required: false
+#               description: vlan
+
+    tosca.nodes.AccessAgent:
+        derived_from: tosca.nodes.Root
+        description: >
+            CORD: A vOLT Access Agent.
+        properties:
+            xos_base_props
+            mac:
+                type: string
+                required: false
+                description: mac address
+            port_mappings:
+                type: string
+                required: false
+                description: list of port mappings, in format "port mac", multiple entries separated by commas
+
+
     tosca.nodes.User:
         derived_from: tosca.nodes.Root
 
@@ -966,6 +1028,12 @@
     tosca.relationships.TagsObject:
         derived_from: tosca.relationships.Root
 
+    tosca.relationships.MemberOfDevice:
+        derived_from: tosca.relationships.Root
+
+    tosca.relationships.UsesAgent:
+        derived_from: tosca.relationships.Root
+
     tosca.capabilities.xos.Service:
         derived_from: tosca.capabilities.Root
         description: An XOS Service
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index 67d5367..8b4c669 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -766,6 +766,64 @@
                 required: true
                 description: MAC address for this device.
 
+    tosca.nodes.VOLTService:
+        derived_from: tosca.nodes.Root
+        description: >
+            CORD: The vOLT Service
+        capabilities:
+            scalable:
+                type: tosca.capabilities.Scalable
+            service:
+                type: tosca.capabilities.xos.Service
+        properties:
+            no-delete:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to delete this object
+            no-create:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to create this object
+            no-update:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
+            kind:
+                type: string
+                default: generic
+                description: Type of service.
+            view_url:
+                type: string
+                required: false
+                description: URL to follow when icon is clicked in the Service Directory.
+            icon_url:
+                type: string
+                required: false
+                description: ICON to display in the Service Directory.
+            enabled:
+                type: boolean
+                default: true
+            published:
+                type: boolean
+                default: true
+                description: If True then display this Service in the Service Directory.
+            public_key:
+                type: string
+                required: false
+                description: Public key to install into Instances to allows Services to SSH into them.
+            private_key_fn:
+                type: string
+                required: false
+                description: Location of private key file
+            versionNumber:
+                type: string
+                required: false
+                description: Version number of Service.
+
     tosca.nodes.VOLTTenant:
         derived_from: tosca.nodes.Root
         description: >
@@ -789,6 +847,86 @@
                 required: false
                 description: c_tag, identifies which subscriber within s_tag
 
+    tosca.nodes.VOLTDevice:
+        derived_from: tosca.nodes.Root
+        description: >
+            CORD: A vOLT Device.
+        properties:
+            no-delete:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to delete this object
+            no-create:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to create this object
+            no-update:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
+            openflow_id:
+                type: string
+                required: false
+                description: openflow id
+            driver:
+                type: string
+                required: false
+                description: driver name
+            access_devices:
+                type: string
+                required: false
+                description: list of access devices, in format "uplink vlan", multiple entries separated by commas
+
+#    tosca.nodes.AccessDevice:
+#        derived_from: tosca.nodes.Root
+#        description: >
+#            CORD: A vOLT Access Device.
+#        properties:
+#            xos_base_props
+#            uplink:
+#               type: integer
+#               required: false
+#               description: uplink
+#            vlan:
+#               type: integer
+#               required: false
+#               description: vlan
+
+    tosca.nodes.AccessAgent:
+        derived_from: tosca.nodes.Root
+        description: >
+            CORD: A vOLT Access Agent.
+        properties:
+            no-delete:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to delete this object
+            no-create:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to create this object
+            no-update:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to update this object
+            replaces:
+                type: string
+                required: false
+                descrption: Replaces/renames this object
+            mac:
+                type: string
+                required: false
+                description: mac address
+            port_mappings:
+                type: string
+                required: false
+                description: list of port mappings, in format "port mac", multiple entries separated by commas
+
+
     tosca.nodes.User:
         derived_from: tosca.nodes.Root
 
@@ -1715,6 +1853,9 @@
     tosca.relationships.TagsObject:
         derived_from: tosca.relationships.Root
 
+    tosca.relationships.MemberOfDevice:
+        derived_from: tosca.relationships.Root
+
     tosca.capabilities.xos.Service:
         derived_from: tosca.capabilities.Root
         description: An XOS Service
diff --git a/xos/tosca/resources/accessagent.py b/xos/tosca/resources/accessagent.py
new file mode 100644
index 0000000..368ce55
--- /dev/null
+++ b/xos/tosca/resources/accessagent.py
@@ -0,0 +1,56 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from services.cord.models import AccessAgent, VOLTDevice, VOLTService, AgentPortMapping
+from xosresource import XOSResource
+
+class XOSAccessAgent(XOSResource):
+    provides = "tosca.nodes.AccessAgent"
+    xos_model = AccessAgent
+    copyin_props = ["mac"]
+
+    def get_xos_args(self, throw_exception=True):
+        args = super(XOSAccessAgent, self).get_xos_args()
+
+        volt_service_name = self.get_requirement("tosca.relationships.MemberOfService", throw_exception=throw_exception)
+        if volt_service_name:
+            args["volt_service"] = self.get_xos_object(VOLTService, throw_exception=throw_exception, name=volt_service_name)
+
+        return args
+
+    def postprocess(self, obj):
+        # For convenient, allow the port mappings to be specified by a Tosca
+        # string with commas between lines.
+        #      <port> <mac>,
+        #      <port> <mac>,
+        #      ...
+        #      <port> <mac>
+
+        port_mappings_str = self.get_property("port_mappings")
+        port_mappings = []
+        if port_mappings_str:
+            lines = [x.strip() for x in port_mappings_str.split(",")]
+            for line in lines:
+                if not (" " in line):
+                    raise "Malformed port mapping `%s`", line
+                (port, mac) = line.split(" ")
+                port=port.strip()
+                mac=mac.strip()
+                port_mappings.append( (port, mac) )
+
+            for apm in list(AgentPortMapping.objects.filter(access_agent=obj)):
+                if (apm.port, apm.mac) not in port_mappings:
+                    print "Deleting AgentPortMapping '%s'" % apm
+                    apm.delete()
+
+            for port_mapping in port_mappings:
+                existing_objs = AgentPortMapping.objects.filter(access_agent=obj, port=port_mapping[0], mac=port_mapping[1])
+                if not existing_objs:
+                    apm = AgentPortMapping(access_agent=obj, port=port_mapping[0], mac=port_mapping[1])
+                    apm.save()
+                    print "Created AgentPortMapping '%s'" % apm
+
diff --git a/xos/tosca/resources/accessdevice.py b/xos/tosca/resources/accessdevice.py
new file mode 100644
index 0000000..94deb86
--- /dev/null
+++ b/xos/tosca/resources/accessdevice.py
@@ -0,0 +1,40 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from services.cord.models import AccessDevice, VOLTDevice
+from xosresource import XOSResource
+
+class XOSAccessDevice(XOSResource):
+    provides = "tosca.nodes.AccessDevice"
+    xos_model = AccessDevice
+    copyin_props = ["uplink", "vlan"]
+    name_field = None
+
+    def get_xos_args(self, throw_exception=True):
+        args = super(XOSAccessDevice, self).get_xos_args()
+
+        volt_device_name = self.get_requirement("tosca.relationships.MemberOfDevice", throw_exception=throw_exception)
+        if volt_device_name:
+            args["volt_device"] = self.get_xos_object(VOLTDevice, throw_exception=throw_exception, name=volt_device_name)
+
+        return args
+
+    # AccessDevice has no name field, so we rely on matching the keys. We assume
+    # the for a given VOLTDevice, there is only one AccessDevice per (uplink, vlan)
+    # pair.
+
+    def get_existing_objs(self):
+        args = self.get_xos_args(throw_exception=False)
+        volt_device = args.get("volt_device", None)
+        uplink = args.get("uplink", None)
+        vlan = args.get("vlan", None)
+        if (volt_device is not None) and (uplink is not None) and (vlan is not None):
+            existing_obj = self.get_xos_object(AccessDevice, volt_device=volt_device, uplink=uplink, vlan=vlan, throw_exception=False)
+            if existing_obj:
+                return [ existing_obj ]
+        return []
+
diff --git a/xos/tosca/resources/voltdevice.py b/xos/tosca/resources/voltdevice.py
new file mode 100644
index 0000000..f1c6830
--- /dev/null
+++ b/xos/tosca/resources/voltdevice.py
@@ -0,0 +1,52 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from services.cord.models import VOLTDevice, VOLTService, AccessDevice, AccessAgent
+from xosresource import XOSResource
+
+class XOSVOLTDevice(XOSResource):
+    provides = "tosca.nodes.VOLTDevice"
+    xos_model = VOLTDevice
+    copyin_props = ["openflow_id", "driver"]
+
+    def get_xos_args(self, throw_exception=True):
+        args = super(XOSVOLTDevice, self).get_xos_args()
+
+        volt_service_name = self.get_requirement("tosca.relationships.MemberOfService", throw_exception=throw_exception)
+        if volt_service_name:
+            args["volt_service"] = self.get_xos_object(VOLTService, throw_exception=throw_exception, name=volt_service_name)
+
+        agent_name = self.get_requirement("tosca.relationships.UsesAgent", throw_exception=throw_exception)
+        if agent_name:
+            args["access_agent"] = self.get_xos_object(AccessAgent, throw_exception=throw_exception, name=agent_name)
+
+        return args
+
+    def postprocess(self, obj):
+        access_devices_str = self.get_property("access_devices")
+        access_devices = []
+        if access_devices_str:
+            lines = [x.strip() for x in access_devices_str.split(",")]
+            for line in lines:
+                if not (" " in line):
+                    raise "Malformed access device `%s`", line
+                (uplink, vlan) = line.split(" ")
+                uplink=int(uplink.strip())
+                vlan=int(vlan.strip())
+                access_devices.append( (uplink, vlan) )
+
+            for ad in list(AccessDevice.objects.filter(volt_device=obj)):
+                if (ad.uplink, ad.vlan) not in access_devices:
+                    print "Deleting AccessDevice '%s'" % ad
+                    ad.delete()
+
+            for access_device in access_devices:
+                existing_objs = AccessDevice.objects.filter(volt_device=obj, uplink=access_device[0], vlan=access_device[1])
+                if not existing_objs:
+                    ad = AccessDevice(volt_device=obj, uplink=access_device[0], vlan=access_device[1])
+                    ad.save()
+                    print "Created AccessDevice '%s'" % ad
diff --git a/xos/tosca/resources/voltservice.py b/xos/tosca/resources/voltservice.py
new file mode 100644
index 0000000..57cf846
--- /dev/null
+++ b/xos/tosca/resources/voltservice.py
@@ -0,0 +1,15 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from services.cord.models import VOLTService
+
+from service import XOSService
+
+class XOSVOLTService(XOSService):
+    provides = "tosca.nodes.VOLTService"
+    xos_model = VOLTService
+    copyin_props = ["view_url", "icon_url", "kind", "enabled", "published", "public_key", "private_key_fn", "versionNumber"]
diff --git a/xos/tosca/run.py b/xos/tosca/run.py
old mode 100644
new mode 100755
diff --git a/xos/xos/settings.py b/xos/xos/settings.py
index 607c145..231228a 100644
--- a/xos/xos/settings.py
+++ b/xos/xos/settings.py
@@ -244,6 +244,8 @@
             'handlers': ['mail_admins'],
             'level': 'ERROR',
             'propagate': True,
+        },'django.db.backends': {
+            'level': 'WARNING',
         },
     }
 }