Merged branch api-cleanup
diff --git a/views/ngXosLib/xosHelpers/spec/ui/table.test.js b/views/ngXosLib/xosHelpers/spec/ui/table.test.js
index 9247cae..69dadb3 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/table.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/table.test.js
@@ -228,6 +228,9 @@
           });
 
           describe('and is custom', () => {
+
+            let formatterFn = jasmine.createSpy('formatter').and.returnValue('Formatted Content');
+
             beforeEach(() => {
               scope.data = [
                 {categories: ['Film', 'Music']}
@@ -238,7 +241,7 @@
                     label: 'Categories',
                     prop: 'categories',
                     type: 'custom',
-                    formatter: () => 'Formatted Content'
+                    formatter: formatterFn
                   }
                 ]
               }
@@ -285,6 +288,8 @@
             it('should format data using the formatter property', () => {
               let td1 = $(element).find('tbody tr:first-child')[0];
               expect($(td1).text().trim()).toEqual('Formatted Content');
+              // the custom formatted should receive the entire object, otherwise is not so custom
+              expect(formatterFn).toHaveBeenCalledWith({categories: ['Film', 'Music']});
             });
           });
 
@@ -373,7 +378,7 @@
             expect(errorFunctionWrapper).toThrow(new Error('[xosTable] The link property should be a function.'));
           });
 
-          it('should render a comma separated list', () => {
+          it('should render a link with the correct url', () => {
             let link = $(element).find('tbody tr:first-child td a')[0];
             expect($(link).attr('href')).toEqual('/link/1');
           });
diff --git a/views/ngXosLib/xosHelpers/src/services/rest/Networks.js b/views/ngXosLib/xosHelpers/src/services/rest/Networks.js
new file mode 100644
index 0000000..74b73b6
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/src/services/rest/Networks.js
@@ -0,0 +1,15 @@
+(function() {
+  'use strict';
+
+  angular.module('xos.helpers')
+  /**
+  * @ngdoc service
+  * @name xos.helpers.Networks
+  * @description Angular resource to fetch /api/core/networks/:id/
+  **/
+  .service('Networks', function($resource){
+    return $resource('/api/core/networks/:id/', { id: '@id' }, {
+      update: { method: 'PUT' }
+    });
+  })
+})();
diff --git a/views/ngXosLib/xosHelpers/src/services/rest/Slices_plus.js b/views/ngXosLib/xosHelpers/src/services/rest/Slices_plus.js
new file mode 100644
index 0000000..e744caa
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/src/services/rest/Slices_plus.js
@@ -0,0 +1,26 @@
+(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', function($http, $q){
+    this.query = (params) => {
+      let deferred = $q.defer();
+
+      $http.get('/api/utility/slicesplus/', {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/ui_components/dumbComponents/table/table.component.js b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/table/table.component.js
index dfbb700..a42f3a4 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/table/table.component.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/table/table.component.js
@@ -289,15 +289,14 @@
             },
             {
               label: 'Features',
-              prop: 'features',
               type: 'custom',
               formatter: (val) => {
                 
-                let cdnEnabled = val.cdn ? 'enabled' : 'disabled';
+                let cdnEnabled = val.features.cdn ? 'enabled' : 'disabled';
                 return `
                   Cdn is ${cdnEnabled},
-                  uplink speed is ${val.uplink_speed}
-                  and downlink speed is ${val.downlink_speed}
+                  uplink speed is ${val.features.uplink_speed}
+                  and downlink speed is ${val.features.downlink_speed}
                 `;
               }
             }
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/table/table.scss b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/table/table.scss
index 70399a9..d9830d8 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/table/table.scss
+++ b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/table/table.scss
@@ -28,11 +28,17 @@
     margin-bottom: 0;
 
     dt {
-      width: 50px !important;
+      width: auto !important;
+      margin-right: 10px;
+    }
+    
+    dt:after {
+      /*display: block;*/
+      content: ':';
     }
 
     dd {
-      margin-left: 60px !important;
+      margin-left: 0 !important;
     }
   }
 }
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartPie/smartPie.component.js b/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartPie/smartPie.component.js
index 6616b50..c1f08fa 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartPie/smartPie.component.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartPie/smartPie.component.js
@@ -187,7 +187,7 @@
       `,
       bindToController: true,
       controllerAs: 'vm',
-      controller: function($injector, $timeout, $interval, $scope, _){
+      controller: function($injector, $interval, $scope, $timeout, _){
 
         if(!this.config.resource && !this.config.data){
           throw new Error('[xosSmartPie] Please provide a resource or an array of data in the configuration');
@@ -198,11 +198,13 @@
         const formatLabels = (data) => angular.isFunction(this.config.labelFormatter) ? this.config.labelFormatter(Object.keys(data)) : Object.keys(data);
 
         const prepareData = (data) => {
-          // group data
-          let grouped = groupData(data);
-          this.data = formatData(grouped);
-          // create labels
-          this.labels = formatLabels(grouped);
+          // $timeout(() => {
+            // group data
+            let grouped = groupData(data);
+            this.data = formatData(grouped);
+            // create labels
+            this.labels = formatLabels(grouped);
+          // }, 10);
         }
 
         if(this.config.resource){
@@ -234,6 +236,14 @@
           }, true);
         }
 
+        $scope.$on('create', function (event, chart) {
+          console.log(`create: ${chart.id}`);
+        });
+
+        $scope.$on('destroy', function (event, chart) {
+          console.log(`destroy: ${chart.id}`);
+        });
+
       }
     };
   });
diff --git a/views/ngXosViews/developer/.bowerrc b/views/ngXosViews/developer/.bowerrc
new file mode 100644
index 0000000..e491038
--- /dev/null
+++ b/views/ngXosViews/developer/.bowerrc
@@ -0,0 +1,3 @@
+{
+  "directory": "src/vendor/"
+}
\ No newline at end of file
diff --git a/views/ngXosViews/developer/.eslintrc b/views/ngXosViews/developer/.eslintrc
new file mode 100644
index 0000000..c852748
--- /dev/null
+++ b/views/ngXosViews/developer/.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/developer/.gitignore b/views/ngXosViews/developer/.gitignore
new file mode 100644
index 0000000..567aee4
--- /dev/null
+++ b/views/ngXosViews/developer/.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/developer/bower.json b/views/ngXosViews/developer/bower.json
new file mode 100644
index 0000000..da4d6b3
--- /dev/null
+++ b/views/ngXosViews/developer/bower.json
@@ -0,0 +1,31 @@
+{
+  "name": "xos-developer",
+  "version": "0.0.0",
+  "authors": [
+    "Matteo Scandolo <teo@onlab.us>"
+  ],
+  "description": "The developer 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"
+  }
+}
diff --git a/views/ngXosViews/developer/env/default.js b/views/ngXosViews/developer/env/default.js
new file mode 100644
index 0000000..56a6b77
--- /dev/null
+++ b/views/ngXosViews/developer/env/default.js
@@ -0,0 +1,13 @@
+// This is a default configuration for your development environment.
+// You can duplicate this configuration for any of your Backend Environments.
+// Different configurations are loaded setting a NODE_ENV variable that contain the config file name.
+// `NODE_ENV=local npm start`
+//
+// If xoscsrftoken or xossessionid are not specified the browser value are used
+// (works only for local environment as both application are served on the same domain)
+
+module.exports = {
+  host: 'http://xos.dev:9999/',
+  xoscsrftoken: 'Di0iR0Sjg6ZLb0icOtuBqnh5AmE1ddKW',
+  xossessionid: 'oem5kppdaihc6pa5qa2ojtxt1r0xterh'
+};
diff --git a/views/ngXosViews/developer/env/mock.js b/views/ngXosViews/developer/env/mock.js
new file mode 100644
index 0000000..777c149
--- /dev/null
+++ b/views/ngXosViews/developer/env/mock.js
@@ -0,0 +1,11 @@
+// This is a default configuration for your development environment.
+// You can duplicate this configuration for any of your Backend Environments.
+// Different configurations are loaded setting a NODE_ENV variable that contain the config file name.
+// `NODE_ENV=local npm start`
+//
+// If xoscsrftoken or xossessionid are not specified the browser value are used
+// (works only for local environment as both application are served on the same domain)
+
+module.exports = {
+  host: 'http://127.0.0.1:4000/'
+};
diff --git a/views/ngXosViews/developer/gulp/build.js b/views/ngXosViews/developer/gulp/build.js
new file mode 100644
index 0000000..f86af0f
--- /dev/null
+++ b/views/ngXosViews/developer/gulp/build.js
@@ -0,0 +1,163 @@
+'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.developer')
+.run(['$location', function(a){
+  a.path('/');
+}])
+`
+
+module.exports = function(options){
+  
+  // delete previous builded file
+  gulp.task('clean', function(){
+    return del(
+      [
+        options.dashboards + 'xosDeveloper.html',
+        options.static + 'css/xosDeveloper.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('xosDeveloper.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('xosDeveloper.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.developer',
+        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/xosDeveloperVendor.js',
+            options.static + 'js/xosDeveloper.js',
+            options.static + 'css/xosDeveloper.css'
+          ]),
+          {ignorePath: '/../../../xos/core/xoslib'}
+        )
+      )
+      .pipe(rename('xosDeveloper.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('xosDeveloperVendor.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',
+      'templates',
+      'babel',
+      'scripts',
+      'wiredep',
+      'css',
+      'copyCss',
+      'copyHtml',
+      'cleanTmp'
+    );
+  });
+};
\ No newline at end of file
diff --git a/views/ngXosViews/developer/gulp/server.js b/views/ngXosViews/developer/gulp/server.js
new file mode 100644
index 0000000..c0678d9
--- /dev/null
+++ b/views/ngXosViews/developer/gulp/server.js
@@ -0,0 +1,168 @@
+'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');
+
+const environment = process.env.NODE_ENV;
+
+if (environment){
+  var conf = require(`../env/${environment}.js`);
+}
+else{
+  var conf = require('../env/default.js')
+}
+
+var proxy = httpProxy.createProxyServer({
+  target: conf.host || 'http://0.0.0.0:9999'
+});
+
+
+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(
+            // to be removed, deprecated API
+            // req.url.indexOf('/xos/') !== -1 ||
+            // req.url.indexOf('/xoslib/') !== -1 ||
+            // req.url.indexOf('/hpcapi/') !== -1 ||
+            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/developer/gulpfile.js b/views/ngXosViews/developer/gulpfile.js
new file mode 100644
index 0000000..08df554
--- /dev/null
+++ b/views/ngXosViews/developer/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/developer/karma.conf.js b/views/ngXosViews/developer/karma.conf.js
new file mode 100644
index 0000000..4123be9
--- /dev/null
+++ b/views/ngXosViews/developer/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/developer/mocks/config.json b/views/ngXosViews/developer/mocks/config.json
new file mode 100644
index 0000000..827ddb5
--- /dev/null
+++ b/views/ngXosViews/developer/mocks/config.json
@@ -0,0 +1,14 @@
+{
+  "endpoints": [
+    {
+      "url": "slicesplus",
+      "base": "api/utility/",
+      "methods": ["GET"]
+    },
+    {
+      "url": "instances",
+      "base": "api/core/",
+      "methods": ["GET"]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/views/ngXosViews/developer/mocks/multi-site/instances.json b/views/ngXosViews/developer/mocks/multi-site/instances.json
new file mode 100644
index 0000000..6e1fad7
--- /dev/null
+++ b/views/ngXosViews/developer/mocks/multi-site/instances.json
@@ -0,0 +1,77 @@
+[
+   {
+      "humanReadableName":"Instance 1",
+      "id":1,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 2",
+      "id":2,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 3",
+      "id":3,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 4",
+      "id":4,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 5",
+      "id":5,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 6",
+      "id":6,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 7",
+      "id":7,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 8",
+      "id":8,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 9",
+      "id":9,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 10",
+      "id":10,
+      "slice":"2"
+   },
+   {
+      "humanReadableName":"Instance 11",
+      "id":11,
+      "slice":"2"
+   },
+   {
+      "humanReadableName":"Instance 12",
+      "id":12,
+      "slice":"2"
+   },
+   {
+      "humanReadableName":"Instance 13",
+      "id":13,
+      "slice":"2"
+   },
+   {
+      "humanReadableName":"Instance 14",
+      "id":14,
+      "slice":"2"
+   },
+   {
+      "humanReadableName":"Instance 15",
+      "id":15,
+      "slice":"2"
+   }
+]
\ No newline at end of file
diff --git a/views/ngXosViews/developer/mocks/multi-site/slicesplus.json b/views/ngXosViews/developer/mocks/multi-site/slicesplus.json
new file mode 100644
index 0000000..ba05da2
--- /dev/null
+++ b/views/ngXosViews/developer/mocks/multi-site/slicesplus.json
@@ -0,0 +1,48 @@
+[
+   {
+      "id":1,
+      "name":"mysite_management1",
+      "site":1,
+      "max_instances":10,
+      "networks":[1, 2],
+      "current_user_roles":[
+         "Admin"
+      ],
+      "instance_distribution":{
+         "mysite": 4,
+         "anothersite": 5
+      },
+      "instance_distribution_ready":{
+         "mysite": 3,
+         "anothersite": 1
+      },
+      "instance_total":9,
+      "instance_total_ready":4,
+      "instance_status":{
+
+      }
+   },
+   {
+      "id":2,
+      "name":"mysite_management2",
+      "site":1,
+      "max_instances":10,
+      "networks":[2, 3, 4],
+      "current_user_roles":[
+         "Access"
+      ],
+      "instance_distribution":{
+        "mysite": 3,
+        "anothersite": 3
+      },
+      "instance_distribution_ready":{
+         "mysite": 2,
+         "anothersite": 3
+      },
+      "instance_total":6,
+      "instance_total_ready":5,
+      "instance_status":{
+
+      }
+   }
+]
\ No newline at end of file
diff --git a/views/ngXosViews/developer/mocks/single-site/instances.json b/views/ngXosViews/developer/mocks/single-site/instances.json
new file mode 100644
index 0000000..6e1fad7
--- /dev/null
+++ b/views/ngXosViews/developer/mocks/single-site/instances.json
@@ -0,0 +1,77 @@
+[
+   {
+      "humanReadableName":"Instance 1",
+      "id":1,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 2",
+      "id":2,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 3",
+      "id":3,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 4",
+      "id":4,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 5",
+      "id":5,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 6",
+      "id":6,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 7",
+      "id":7,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 8",
+      "id":8,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 9",
+      "id":9,
+      "slice":"1"
+   },
+   {
+      "humanReadableName":"Instance 10",
+      "id":10,
+      "slice":"2"
+   },
+   {
+      "humanReadableName":"Instance 11",
+      "id":11,
+      "slice":"2"
+   },
+   {
+      "humanReadableName":"Instance 12",
+      "id":12,
+      "slice":"2"
+   },
+   {
+      "humanReadableName":"Instance 13",
+      "id":13,
+      "slice":"2"
+   },
+   {
+      "humanReadableName":"Instance 14",
+      "id":14,
+      "slice":"2"
+   },
+   {
+      "humanReadableName":"Instance 15",
+      "id":15,
+      "slice":"2"
+   }
+]
\ No newline at end of file
diff --git a/views/ngXosViews/developer/mocks/single-site/slicesplus.json b/views/ngXosViews/developer/mocks/single-site/slicesplus.json
new file mode 100644
index 0000000..9f7802c
--- /dev/null
+++ b/views/ngXosViews/developer/mocks/single-site/slicesplus.json
@@ -0,0 +1,44 @@
+[
+   {
+      "id":1,
+      "name":"mysite_management1",
+      "site":1,
+      "max_instances":10,
+      "networks":[1, 2],
+      "current_user_roles":[
+         "Admin"
+      ],
+      "instance_distribution":{
+         "mysite": 9
+      },
+      "instance_distribution_ready":{
+         "mysite": 4
+      },
+      "instance_total":9,
+      "instance_total_ready":4,
+      "instance_status":{
+
+      }
+   },
+   {
+      "id":2,
+      "name":"mysite_management2",
+      "site":1,
+      "max_instances":10,
+      "networks":[2, 3, 4],
+      "current_user_roles":[
+         "Access"
+      ],
+      "instance_distribution":{
+        "mysite": 6
+      },
+      "instance_distribution_ready":{
+         "mysite": 5
+      },
+      "instance_total":6,
+      "instance_total_ready":5,
+      "instance_status":{
+
+      }
+   }
+]
\ No newline at end of file
diff --git a/views/ngXosViews/developer/package.json b/views/ngXosViews/developer/package.json
new file mode 100644
index 0000000..f28682f
--- /dev/null
+++ b/views/ngXosViews/developer/package.json
@@ -0,0 +1,65 @@
+{
+  "name": "xos-developer",
+  "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/",
+    "single-site": "easy-mocker -c ./mocks/config.json -d ./mocks/single-site",
+    "multi-site": "easy-mocker -c ./mocks/config.json -d ./mocks/multi-site"
+  },
+  "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.3.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/developer/spec/sample.test.js b/views/ngXosViews/developer/spec/sample.test.js
new file mode 100644
index 0000000..f17a717
--- /dev/null
+++ b/views/ngXosViews/developer/spec/sample.test.js
@@ -0,0 +1,37 @@
+'use strict';
+
+describe('The User List', () => {
+  
+  var scope, element, isolatedScope, httpBackend;
+
+  beforeEach(module('xos.developer'));
+  beforeEach(module('templates'));
+
+  beforeEach(inject(function($httpBackend, $compile, $rootScope){
+    
+    httpBackend = $httpBackend;
+    // Setting up mock request
+    $httpBackend.expectGET('/api/core/users/?no_hyperlinks=1').respond([
+      {
+        email: 'teo@onlab.us',
+        firstname: 'Matteo',
+        lastname: 'Scandolo' 
+      }
+    ]);
+  
+    scope = $rootScope.$new();
+    element = angular.element('<users-list></users-list>');
+    $compile(element)(scope);
+    scope.$digest();
+    isolatedScope = element.isolateScope().vm;
+  }));
+
+  it('should load 1 users', () => {
+    httpBackend.flush();
+    expect(isolatedScope.users.length).toBe(1);
+    expect(isolatedScope.users[0].email).toEqual('teo@onlab.us');
+    expect(isolatedScope.users[0].firstname).toEqual('Matteo');
+    expect(isolatedScope.users[0].lastname).toEqual('Scandolo');
+  });
+
+});
\ No newline at end of file
diff --git a/views/ngXosViews/developer/src/css/main.css b/views/ngXosViews/developer/src/css/main.css
new file mode 100644
index 0000000..7b15d7c
--- /dev/null
+++ b/views/ngXosViews/developer/src/css/main.css
@@ -0,0 +1,18 @@
+#xosDeveloper .pie-legend li {
+  display: inline-block;
+  white-space: nowrap;
+  position: relative;
+  margin-bottom: 4px;
+  border-radius: 5px;
+  padding: 2px 8px 2px 28px;
+  font-size: smaller;
+  cursor: default; }
+
+#xosDeveloper .pie-legend-icon {
+  display: block;
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 20px;
+  height: 20px;
+  border-radius: 5px; }
diff --git a/views/ngXosViews/developer/src/index.html b/views/ngXosViews/developer/src/index.html
new file mode 100644
index 0000000..f8946e9
--- /dev/null
+++ b/views/ngXosViews/developer/src/index.html
@@ -0,0 +1,33 @@
+<!-- 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 ng-app="xos.developer" id="xosDeveloper" class="container-fluid">
+  <div ui-view></div>
+</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>
+<!-- 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/developer/src/js/main.js b/views/ngXosViews/developer/src/js/main.js
new file mode 100644
index 0000000..b09f1ef
--- /dev/null
+++ b/views/ngXosViews/developer/src/js/main.js
@@ -0,0 +1,135 @@
+'use strict';
+
+angular.module('xos.developer', [
+  'ngResource',
+  'ngCookies',
+  'ui.router',
+  'xos.helpers'
+])
+.config(($stateProvider) => {
+  $stateProvider
+  .state('developer', {
+    url: '/',
+    template: '<developer-dashboard></developer-dashboard>'
+  });
+})
+.config(function($httpProvider){
+  $httpProvider.interceptors.push('NoHyperlinks');
+})
+.directive('developerDashboard', function(){
+  return {
+    restrict: 'E',
+    scope: {},
+    bindToController: true,
+    controllerAs: 'vm',
+    templateUrl: 'templates/developer-dashboard.tpl.html',
+    controller: function($scope, $timeout, SlicesPlus, Instances, _){
+
+      this.instancePerSliceConfig = {
+        data: [],
+        groupBy: 'slice',
+        legend: true,
+        classes: 'instance per slice',
+        labelFormatter: (labels) => {
+          return labels.map(l => {
+            return _.find(this.slices, {id: parseInt(l)}).name
+          });
+        }
+      };
+
+      this.instancePerSiteConfig = {
+        data: [],
+        groupBy: 'site',
+        legend: true,
+        classes: 'instance per site',
+      };
+
+      this.networkPerSliceConfig = {
+        data: [],
+        groupBy: 'name',
+        legend: true,
+        classes: 'network per slice',
+      };
+
+      this.tableConfig = {
+        columns: [
+          {
+            label: 'Name',
+            prop: 'name'
+          },
+          {
+            label: 'Privileges',
+            prop: 'current_user_roles',
+            type: 'array'
+          },
+          {
+            label: 'Number of Instances (active / total)',
+            type: 'custom',
+            formatter: item => `${item.instance_total_ready} / ${item.instance_total}`
+          },
+          {
+            label: 'Active Instances per Sites',
+            type: 'object',
+            prop: 'instance_distribution_ready'
+          },
+          {
+            label: 'Total Instances per Sites',
+            type: 'object',
+            prop: 'instance_distribution'
+          },
+          {
+            label: 'Networks',
+            type: 'custom',
+            formatter: item => item.networks.length
+          }
+        ]
+      };
+
+      // retrieving user list
+      SlicesPlus.query().$promise
+      .then((slices) => {
+        this.slices = slices;
+        return Instances.query().$promise
+      })
+      .then(instances => {
+        
+        // formatting data in this way sucks.
+        // Provide a way to just pass data to the chart if needed [smartPie].
+
+        // retrieving network per slices
+        let networkPerSlice = _.reduce(this.slices, (list, s) => {
+          if( s.networks.length > 1){
+            // push s.neworks.length values in array
+            for(let i = 0; i < s.networks.length; i++){
+              list.push({id: s.id, name: s.name, network: s.networks[i]})
+            }
+          }
+          else if ( s.networks.length === 1){
+            list.push({id: s.id, name: s.name, network: s.networks[0]});
+          }
+          return list;
+        }, []);
+
+        // retrieving instance distribution across sites
+        let instancePerSite = _.reduce(this.slices, (list, s) => {
+          _.forEach(Object.keys(s.instance_distribution), k => {
+            for(let i = 0; i < s.instance_distribution[k]; i++){
+              list.push({site: k, instance: i})
+            }
+          })
+          return list;
+        }, []);
+
+        this.sites = Object.keys(_.groupBy(instancePerSite, 'site'));
+
+        this.instancePerSliceConfig.data = instances;
+        this.instancePerSiteConfig.data = instancePerSite;
+        this.networkPerSliceConfig.data = networkPerSlice;
+
+      })
+      .catch((e) => {
+        throw new Error(e);
+      });
+    }
+  };
+});
\ No newline at end of file
diff --git a/views/ngXosViews/developer/src/sass/main.scss b/views/ngXosViews/developer/src/sass/main.scss
new file mode 100644
index 0000000..043a334
--- /dev/null
+++ b/views/ngXosViews/developer/src/sass/main.scss
@@ -0,0 +1,25 @@
+@import '../../../../style/sass/lib/_variables.scss';
+
+#xosDeveloper {
+
+  .pie-legend li {
+      display: inline-block;
+    white-space: nowrap;
+    position: relative;
+    margin-bottom: 4px;
+    border-radius: 5px;
+    padding: 2px 8px 2px 28px;
+    font-size: smaller;
+    cursor: default;
+  }
+
+  .pie-legend-icon {
+    display: block;
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 20px;
+    height: 20px;
+    border-radius: 5px;
+  }
+}
\ No newline at end of file
diff --git a/views/ngXosViews/developer/src/templates/developer-dashboard.tpl.html b/views/ngXosViews/developer/src/templates/developer-dashboard.tpl.html
new file mode 100644
index 0000000..fd82f77
--- /dev/null
+++ b/views/ngXosViews/developer/src/templates/developer-dashboard.tpl.html
@@ -0,0 +1,16 @@
+<div class="row">
+  <div ng-class="{'col-sm-4': vm.sites.length > 1 || !vm.sites, 'col-sm-6': vm.sites.length <= 1}" class="text-center">
+    <h3>Instances per Slice</h3>
+    <xos-smart-pie ng-if="vm.instancePerSliceConfig.data.length > 0" config="vm.instancePerSliceConfig"></xos-smart-pie>
+  </div>
+  <div ng-if="vm.sites.length > 1" class="col-sm-4 text-center">
+    <h3>Instances per Site</h3>
+    <xos-smart-pie ng-if="vm.instancePerSiteConfig.data.length > 0" config="vm.instancePerSiteConfig"></xos-smart-pie>
+  </div>
+  <div ng-class="{'col-sm-4': vm.sites.length > 1 || !vm.sites, 'col-sm-6': vm.sites.length <= 1}" class="text-center">
+    <h3>Network per Slice</h3>
+    <xos-smart-pie ng-if="vm.networkPerSliceConfig.data.length > 0" config="vm.networkPerSliceConfig"></xos-smart-pie>
+  </div>
+</div>
+
+<xos-table config="vm.tableConfig" data="vm.slices"></xos-table>
\ No newline at end of file
diff --git a/xos/api/utility/sliceplus.py b/xos/api/utility/sliceplus.py
new file mode 100644
index 0000000..ca52125
--- /dev/null
+++ b/xos/api/utility/sliceplus.py
@@ -0,0 +1,407 @@
+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
+
+# rest_framework 3.x
+IdField = serializers.ReadOnlyField
+WritableField = serializers.Field
+DictionaryField = serializers.DictField
+ListField = serializers.ListField
+
+class SlicePlus(Slice, PlusObjectMixin):
+    class Meta:
+        proxy = True
+
+    def __init__(self, *args, **kwargs):
+        super(SlicePlus, self).__init__(*args, **kwargs)
+        self._update_users = None
+        self._sliceInfo = None
+        self.getSliceInfo()
+        self._instance_status = self._sliceInfo["instanceStatus"]
+        self._instance_distribution = self._sliceInfo["sitesUsed"]
+        self._initial_instance_distribution = self._instance_distribution
+        self._network_ports = self._sliceInfo["networkPorts"]
+        self._initial_network_ports = self._network_ports
+        self._current_user_roles = self._sliceInfo["roles"]
+
+    def getSliceInfo(self, user=None):
+        if not self._sliceInfo:
+            site_status = {}
+            used_sites = {}
+            ready_sites = {}
+            used_deployments = {}
+            instanceCount = 0
+            instance_status = {}
+            sshCommands = []
+            for instance in self.instances.all():
+                site = instance.node.site_deployment.site
+                deployment = instance.node.site_deployment.deployment
+                used_sites[site.name] = used_sites.get(site.name, 0) + 1
+                used_deployments[deployment.name] = used_deployments.get(deployment.name, 0) + 1
+                instanceCount = instanceCount + 1
+
+                if instance.backend_status:
+                    status = instance.backend_status[0]
+                else:
+                    status = "none"
+
+                if not status in instance_status:
+                    instance_status[status] = 0
+                instance_status[status] = instance_status[status] + 1
+
+                sshCommand = instance.get_ssh_command()
+                if sshCommand:
+                    sshCommands.append(sshCommand)
+                    ready_sites[site.name] = ready_sites.get(site.name, 0) + 1
+
+            users = {}
+            for priv in SlicePrivilege.objects.filter(slice=self):
+                if not (priv.user.id in users.keys()):
+                    users[priv.user.id] = {"name": priv.user.email, "id": priv.user.id, "roles": []}
+                users[priv.user.id]["roles"].append(priv.role.role)
+
+            # XXX this assumes there is only one network that can have ports bound
+            # to it for a given slice. This is intended for the tenant view, which
+            # will obey this field.
+            networkPorts = ""
+            for networkSlice in self.networkslices.all():
+                network = networkSlice.network
+                if (network.owner.id != self.id):
+                    continue
+                if network.ports:
+                    networkPorts = network.ports
+
+            self._sliceInfo= {"sitesUsed": used_sites,
+                    "sitesReady": ready_sites,
+                    "instanceStatus": instance_status,
+                    "deploymentsUsed": used_deployments,
+                    "instanceCount": instanceCount,
+                    "siteCount": len(used_sites.keys()),
+                    "users": users,
+                    "roles": [],
+                    "sshCommands": sshCommands,
+                    "networkPorts": networkPorts}
+
+        if user:
+            auser = self._sliceInfo["users"].get(user.id, None)
+            if (auser):
+                self._sliceInfo["roles"] = auser["roles"]
+
+        return self._sliceInfo
+
+    @property
+    def instance_distribution_ready(self):
+        return self._sliceInfo["sitesReady"]
+
+    @property
+    def instance_total_ready(self):
+        return sum(self._sliceInfo["sitesReady"].values())
+
+    @property
+    def current_user_roles(self):
+        return self._current_user_roles
+
+    @property
+    def instance_distribution(self):
+        return self._instance_distribution
+
+    @instance_distribution.setter
+    def instance_distribution(self, value):
+        self._instance_distribution = value
+
+    @property
+    def instance_total(self):
+        return sum(self._instance_distribution.values())
+
+    @property
+    def instance_status(self):
+        return self._instance_status
+
+    @property
+    def user_names(self):
+        return [user["name"] for user in self.getSliceInfo()["users"].values()]
+
+    @user_names.setter
+    def user_names(self, value):
+        pass # it's read-only
+
+    @property
+    def users(self):
+        return [user["id"] for user in self.getSliceInfo()["users"].values()]
+
+    @users.setter
+    def users(self, value):
+        self._update_users = value
+
+    @property
+    def network_ports(self):
+        return self._network_ports
+
+    @network_ports.setter
+    def network_ports(self, value):
+        self._network_ports = value
+
+    @staticmethod
+    def select_by_user(user):
+        if user.is_admin:
+            qs = SlicePlus.objects.all()
+        else:
+            slice_ids = [sp.slice.id for sp in SlicePrivilege.objects.filter(user=user)]
+            qs = SlicePlus.objects.filter(id__in=slice_ids)
+        return qs
+
+    def get_node_allocation(self, siteList):
+        siteIDList = [site.id for site in siteList]
+        nodeList = []
+        for node in Node.objects.all():
+            if (node.site_deployment.site.id in siteIDList):
+                node.instanceCount = 0
+                for instance in node.instances.all():
+                     if instance.slice.id == self.id:
+                         node.instanceCount = node.instanceCount + 1
+                nodeList.append(node)
+        return nodeList
+
+    def save(self, *args, **kwargs):
+        if (not hasattr(self,"caller")) or self.caller==None:
+            raise APIException("no self.caller in SlicePlus.save")
+
+        updated_image = self.has_field_changed("default_image")
+        updated_flavor = self.has_field_changed("default_flavor")
+
+        super(SlicePlus, self).save(*args, **kwargs)
+
+        # try things out first
+
+        updated_sites = (self._instance_distribution != self._initial_instance_distribution) or updated_image or updated_flavor
+        if updated_sites:
+            self.save_instance_distribution(noAct=True, reset=(updated_image or updated_flavor))
+
+        if self._update_users:
+            self.save_users(noAct=True)
+
+        if (self._network_ports != self._initial_network_ports):
+            self.save_network_ports(noAct=True)
+
+        # now actually save them
+
+        if updated_sites:
+            self.save_instance_distribution(reset=(updated_image or updated_flavor))
+
+        if self._update_users:
+            self.save_users()
+
+        if (self._network_ports != self._initial_network_ports):
+            self.save_network_ports()
+
+    def save_instance_distribution(self, noAct = False, reset=False):
+        print "save_instance_distribution, reset=",reset
+
+        if (not self._instance_distribution):
+            # Must be a instance that was just created, and has not instance_distribution
+            # field.
+            return
+
+        all_slice_instances = self.instances.all()
+        for site_name in self._instance_distribution.keys():
+            desired_allocation = self._instance_distribution[site_name]
+
+            # make a list of the instances for this site
+            instances = []
+            for instance in all_slice_instances:
+                if instance.node.site_deployment.site.name == site_name:
+                    instances.append(instance)
+
+            # delete extra instances
+            while (reset and len(instances)>0) or (len(instances) > desired_allocation):
+                instance = instances.pop()
+                if (not noAct):
+                    print "deleting instance", instance
+                    instance.delete()
+                else:
+                    print "would delete instance", instance
+
+            # add more instances
+            if (len(instances) < desired_allocation):
+                site = Site.objects.get(name = site_name)
+                nodes = self.get_node_allocation([site])
+
+                if (not nodes):
+                    raise APIException(detail="no nodes in site %s" % site_name)
+
+                while (len(instances) < desired_allocation):
+                    # pick the least allocated node
+                    nodes = sorted(nodes, key=attrgetter("instanceCount"))
+                    node = nodes[0]
+
+                    instance = Instance(name=node.name,
+                            slice=self,
+                            node=node,
+                            image = self.default_image,
+                            flavor = self.default_flavor,
+                            creator = self.creator,
+                            deployment = node.site_deployment.deployment)
+                    instance.caller = self.caller
+                    instances.append(instance)
+                    if (not noAct):
+                        print "added instance", instance
+                        instance.save()
+                    else:
+                        print "would add instance", instance
+
+                    node.instanceCount = node.instanceCount + 1
+
+    def save_users(self, noAct = False):
+        new_users = self._update_users
+
+        try:
+            default_role = SliceRole.objects.get(role="access")
+        except:
+            default_role = SliceRole.objects.get(role="default")
+
+        slice_privs = self.sliceprivileges.all()
+        slice_user_ids = [priv.user.id for priv in slice_privs]
+
+        for user_id in new_users:
+            if (user_id not in slice_user_ids):
+                priv = SlicePrivilege(slice=self, user=User.objects.get(id=user_id), role=default_role)
+                priv.caller = self.caller
+                if (not noAct):
+                    priv.save()
+
+                print "added user id", user_id
+
+        for priv in slice_privs:
+             if (priv.role.id != default_role.id):
+                 # only mess with 'default' users; don't kill an admin
+                 continue
+
+             if (priv.user.id not in new_users):
+                 if (not noAct):
+                     priv.delete()
+
+                 print "deleted user id", user_id
+
+    def save_network_ports(self, noAct=False):
+        # First search for any network that already has a filled in 'ports'
+        # field. We'll assume there can only be one, so it must be the right
+        # one.
+        for networkSlice in self.networkslices.all():
+            network = networkSlice.network
+            if (network.owner.id != self.id):
+                continue
+            if network.ports:
+                network.ports = self._network_ports
+                network.caller = self.caller
+                if (not noAct):
+                    network.save()
+                return
+
+        # Now try a network that is a "NAT", since setting ports on a non-NAT
+        # network doesn't make much sense.
+        for networkSlice in self.networkslices.all():
+            network = networkSlice.network
+            if (network.owner.id != self.id):
+                continue
+            if network.template.translation=="NAT":
+                network.ports = self._network_ports
+                network.caller = self.caller
+                if (not noAct):
+                    network.save()
+                return
+
+        # uh oh, we didn't find a network
+
+        raise APIException(detail="No network was found that ports could be set on")
+
+class SlicePlusIdSerializer(PlusModelSerializer):
+        id = IdField()
+
+        humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+        network_ports = serializers.CharField(required=False)
+        instance_distribution = DictionaryField(required=False)
+        instance_distribution_ready = DictionaryField(read_only=True)
+        instance_total = serializers.IntegerField(read_only=True)
+        instance_total_ready = serializers.IntegerField(read_only=True)
+        instance_status = DictionaryField(read_only=True)
+        users = ListField(required=False)
+        user_names = ListField(required=False) # readonly = True ?
+        current_user_can_see = serializers.SerializerMethodField("getCurrentUserCanSee")
+
+        def getCurrentUserCanSee(self, slice):
+            # user can 'see' the slice if he is the creator or he has a role
+            current_user = self.context['request'].user
+            if (slice.creator and slice.creator==current_user):
+                return True;
+            return (len(slice.getSliceInfo(current_user)["roles"]) > 0)
+
+        def getSliceInfo(self, slice):
+            return slice.getSliceInfo(user=self.context['request'].user)
+
+        def getHumanReadableName(self, obj):
+            return str(obj)
+
+        networks = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
+
+        class Meta:
+            model = SlicePlus
+            fields = ('humanReadableName', 'id','created','updated','enacted','name','enabled','omf_friendly','description','slice_url','site','max_instances','service','network','mount_data_sets',
+                      'default_image', 'default_flavor',
+                      'serviceClass','creator',
+
+                      # these are the value-added fields from SlicePlus
+                      'networks','network_ports','backendIcon','backendHtml',
+                      'current_user_roles', 'instance_distribution','instance_distribution_ready','instance_total','instance_total_ready','instance_status','users',"user_names","current_user_can_see")
+
+class SlicePlusList(XOSListCreateAPIView):
+    queryset = SlicePlus.objects.select_related().all()
+    serializer_class = SlicePlusIdSerializer
+
+    method_kind = "list"
+    method_name = "slicesplus"
+
+    def get_queryset(self):
+        current_user_can_see = self.request.query_params.get('current_user_can_see', False)
+
+        if (not self.request.user.is_authenticated()):
+            raise XOSPermissionDenied("You must be authenticated in order to use this API")
+
+        slices = SlicePlus.select_by_user(self.request.user)
+
+        # If current_user_can_see is set, then filter the queryset to return
+        # only those slices that the user is either creator or has privilege
+        # on.
+        if (current_user_can_see):
+            slice_ids = []
+            for slice in slices:
+                if (self.request.user == slice.creator) or (len(slice.getSliceInfo(self.request.user)["roles"]) > 0):
+                    slice_ids.append(slice.id)
+
+            slices = SlicePlus.objects.filter(id__in=slice_ids)
+
+        return slices
+
+class SlicePlusDetail(XOSRetrieveUpdateDestroyAPIView):
+    queryset = SlicePlus.objects.select_related().all()
+    serializer_class = SlicePlusIdSerializer
+
+    method_kind = "detail"
+    method_name = "slicesplus"
+
+    def get_queryset(self):
+        if (not self.request.user.is_authenticated()):
+            raise XOSPermissionDenied("You must be authenticated in order to use this API")
+        return SlicePlus.select_by_user(self.request.user)
+
+
diff --git a/xos/api/xosapi_helpers.py b/xos/api/xosapi_helpers.py
index aa5c770..b39ca22 100644
--- a/xos/api/xosapi_helpers.py
+++ b/xos/api/xosapi_helpers.py
@@ -9,12 +9,27 @@
 from rest_framework.reverse import reverse
 from django.core.urlresolvers import get_script_prefix, resolve, Resolver404
 
-if hasattr(serializers, "ReadOnlyField"):
-    # rest_framework 3.x
-    ReadOnlyField = serializers.ReadOnlyField
-else:
-    # rest_framework 2.x
-    ReadOnlyField = serializers.Field
+# rest_framework 3.x
+ReadOnlyField = serializers.ReadOnlyField
+
+ICON_URLS = {"success": "/static/admin/img/icon_success.gif",
+            "clock": "/static/admin/img/icon_clock.gif",
+            "error": "/static/admin/img/icon_error.gif"}
+
+class PlusObjectMixin:
+    def getBackendIcon(self):
+        (icon, tooltip) = self.get_backend_icon()
+        icon_url = ICON_URLS.get(icon, "unknown")
+        return icon_url
+
+    def getBackendHtml(self):
+        (icon, tooltip) = self.get_backend_icon()
+        icon_url = ICON_URLS.get(icon, "unknown")
+
+        if tooltip:
+            return '<span title="%s"><img src="%s"></span>' % (tooltip, icon_url)
+        else:
+            return '<img src="%s">' % icon_url
 
 """ PlusSerializerMixin
 
diff --git a/xos/configurations/common/fixtures.yaml b/xos/configurations/common/fixtures.yaml
index a447e20..e28b03c 100644
--- a/xos/configurations/common/fixtures.yaml
+++ b/xos/configurations/common/fixtures.yaml
@@ -93,7 +93,7 @@
     Developer:
       type: tosca.nodes.DashboardView
       properties:
-          url: template:xosDeveloper_datatables
+          url: template:xosDeveloper
 
     Services Grid:
       type: tosca.nodes.DashboardView
diff --git a/xos/core/static/xosNgLib.css b/xos/core/static/xosNgLib.css
index b78ad2b..e6cbaf6 100644
--- a/xos/core/static/xosNgLib.css
+++ b/xos/core/static/xosNgLib.css
@@ -75,9 +75,13 @@
   xos-table td dl {
     margin-bottom: 0; }
     xos-table td dl dt {
-      width: 50px !important; }
+      width: auto !important;
+      margin-right: 10px; }
+    xos-table td dl dt:after {
+      /*display: block;*/
+      content: ':'; }
     xos-table td dl dd {
-      margin-left: 60px !important; }
+      margin-left: 0 !important; }
 
 @keyframes slideInRight {
   from {
@@ -156,4 +160,4 @@
   /* TODO move in xos.scss*/
   margin-top: 15px; }
 
-/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieG9zTmdMaWIuY3NzIiwic291cmNlcyI6WyJtYWluLnNjc3MiLCJhbmltYXRpb25zLnNjc3MiLCIuLi8uLi8uLi8uLi9zdHlsZS9zYXNzL2Jvb3RzdHJhcC9ib290c3RyYXAvX3ZhcmlhYmxlcy5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy90YWJsZS90YWJsZS5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy9hbGVydC9hbGVydC5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy92YWxpZGF0aW9uL3ZhbGlkYXRpb24uc2NzcyIsIi4uL3VpX2NvbXBvbmVudHMvc21hcnRDb21wb25lbnRzL3NtYXJ0VGFibGUvc21hcnRUYWJsZS5zY3NzIl0sInNvdXJjZXNDb250ZW50IjpbIkBpbXBvcnQgJy4vYW5pbWF0aW9ucy5zY3NzJztcbkBpbXBvcnQgJy4uLy4uLy4uLy4uLy4uL3ZpZXdzL3N0eWxlL3Nhc3MvYm9vdHN0cmFwL2Jvb3RzdHJhcC9fdmFyaWFibGVzLnNjc3MnO1xuXG5AaW1wb3J0ICcuLi91aV9jb21wb25lbnRzL2R1bWJDb21wb25lbnRzL3RhYmxlL3RhYmxlLnNjc3MnO1xuQGltcG9ydCAnLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy9hbGVydC9hbGVydC5zY3NzJztcbkBpbXBvcnQgJy4uL3VpX2NvbXBvbmVudHMvZHVtYkNvbXBvbmVudHMvdmFsaWRhdGlvbi92YWxpZGF0aW9uLnNjc3MnO1xuXG5AaW1wb3J0ICcuLi91aV9jb21wb25lbnRzL3NtYXJ0Q29tcG9uZW50cy9zbWFydFRhYmxlL3NtYXJ0VGFibGUuc2Nzcyc7XG5cbltuZ1xcOmNsb2FrXSwgW25nLWNsb2FrXSwgW2RhdGEtbmctY2xvYWtdLCBbeC1uZy1jbG9ha10sIC5uZy1jbG9haywgLngtbmctY2xvYWsge1xuICBkaXNwbGF5OiBub25lICFpbXBvcnRhbnQ7XG59XG5cbi5yb3cgKyAucm93IHtcbiAgLyogVE9ETyBtb3ZlIGluIHhvcy5zY3NzKi8gXG4gIG1hcmdpbi10b3A6ICRmb3JtLWdyb3VwLW1hcmdpbi1ib3R0b207XG59IiwiQGtleWZyYW1lcyBzbGlkZUluUmlnaHQge1xuICBmcm9tIHtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDEwMCUsIDAsIDApO1xuICAgIHZpc2liaWxpdHk6IHZpc2libGU7XG4gIH1cblxuICB0byB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAwLCAwKTtcbiAgfVxufVxuXG5Aa2V5ZnJhbWVzIHNsaWRlT3V0UmlnaHQge1xuICBmcm9tIHtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDAsIDApO1xuICB9XG5cbiAgdG8ge1xuICAgIHZpc2liaWxpdHk6IGhpZGRlbjtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDEwMCUsIDAsIDApO1xuICB9XG59XG5cbkBrZXlmcmFtZXMgZmFkZUluVXAge1xuICBmcm9tIHtcbiAgICBvcGFjaXR5OiAwO1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgMTAwJSwgMCk7XG4gIH1cblxuICB0byB7XG4gICAgb3BhY2l0eTogMTtcbiAgICB0cmFuc2Zvcm06IG5vbmU7XG4gIH1cbn1cblxuQGtleWZyYW1lcyBmYWRlT3V0RG93biB7XG4gIGZyb20ge1xuICAgIG9wYWNpdHk6IDE7XG4gIH1cblxuICB0byB7XG4gICAgb3BhY2l0eTogMDtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDEwMCUsIDApO1xuICB9XG59IiwiJGJvb3RzdHJhcC1zYXNzLWFzc2V0LWhlbHBlcjogZmFsc2UgIWRlZmF1bHQ7XG4vL1xuLy8gVmFyaWFibGVzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cbi8vPT0gQ29sb3JzXG4vL1xuLy8jIyBHcmF5IGFuZCBicmFuZCBjb2xvcnMgZm9yIHVzZSBhY3Jvc3MgQm9vdHN0cmFwLlxuXG4kZ3JheS1iYXNlOiAgICAgICAgICAgICAgIzAwMCAhZGVmYXVsdDtcbiRncmF5LWRhcmtlcjogICAgICAgICAgICBsaWdodGVuKCRncmF5LWJhc2UsIDEzLjUlKSAhZGVmYXVsdDsgLy8gIzIyMlxuJGdyYXktZGFyazogICAgICAgICAgICAgIGxpZ2h0ZW4oJGdyYXktYmFzZSwgMjAlKSAhZGVmYXVsdDsgICAvLyAjMzMzXG4kZ3JheTogICAgICAgICAgICAgICAgICAgbGlnaHRlbigkZ3JheS1iYXNlLCAzMy41JSkgIWRlZmF1bHQ7IC8vICM1NTVcbiRncmF5LWxpZ2h0OiAgICAgICAgICAgICBsaWdodGVuKCRncmF5LWJhc2UsIDQ2LjclKSAhZGVmYXVsdDsgLy8gIzc3N1xuJGdyYXktbGlnaHRlcjogICAgICAgICAgIGxpZ2h0ZW4oJGdyYXktYmFzZSwgOTMuNSUpICFkZWZhdWx0OyAvLyAjZWVlXG5cbiRicmFuZC1wcmltYXJ5OiAgICAgICAgIGRhcmtlbigjNDI4YmNhLCA2LjUlKSAhZGVmYXVsdDsgLy8gIzMzN2FiN1xuJGJyYW5kLXN1Y2Nlc3M6ICAgICAgICAgIzVjYjg1YyAhZGVmYXVsdDtcbiRicmFuZC1pbmZvOiAgICAgICAgICAgICM1YmMwZGUgIWRlZmF1bHQ7XG4kYnJhbmQtd2FybmluZzogICAgICAgICAjZjBhZDRlICFkZWZhdWx0O1xuJGJyYW5kLWRhbmdlcjogICAgICAgICAgI2Q5NTM0ZiAhZGVmYXVsdDtcblxuXG4vLz09IFNjYWZmb2xkaW5nXG4vL1xuLy8jIyBTZXR0aW5ncyBmb3Igc29tZSBvZiB0aGUgbW9zdCBnbG9iYWwgc3R5bGVzLlxuXG4vLyoqIEJhY2tncm91bmQgY29sb3IgZm9yIGA8Ym9keT5gLlxuJGJvZHktYmc6ICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogR2xvYmFsIHRleHQgY29sb3Igb24gYDxib2R5PmAuXG4kdGV4dC1jb2xvcjogICAgICAgICAgICAkZ3JheS1kYXJrICFkZWZhdWx0O1xuXG4vLyoqIEdsb2JhbCB0ZXh0dWFsIGxpbmsgY29sb3IuXG4kbGluay1jb2xvcjogICAgICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcbi8vKiogTGluayBob3ZlciBjb2xvciBzZXQgdmlhIGBkYXJrZW4oKWAgZnVuY3Rpb24uXG4kbGluay1ob3Zlci1jb2xvcjogICAgICBkYXJrZW4oJGxpbmstY29sb3IsIDE1JSkgIWRlZmF1bHQ7XG4vLyoqIExpbmsgaG92ZXIgZGVjb3JhdGlvbi5cbiRsaW5rLWhvdmVyLWRlY29yYXRpb246IHVuZGVybGluZSAhZGVmYXVsdDtcblxuXG4vLz09IFR5cG9ncmFwaHlcbi8vXG4vLyMjIEZvbnQsIGxpbmUtaGVpZ2h0LCBhbmQgY29sb3IgZm9yIGJvZHkgdGV4dCwgaGVhZGluZ3MsIGFuZCBtb3JlLlxuXG4kZm9udC1mYW1pbHktc2Fucy1zZXJpZjogIFwiSGVsdmV0aWNhIE5ldWVcIiwgSGVsdmV0aWNhLCBBcmlhbCwgc2Fucy1zZXJpZiAhZGVmYXVsdDtcbiRmb250LWZhbWlseS1zZXJpZjogICAgICAgR2VvcmdpYSwgXCJUaW1lcyBOZXcgUm9tYW5cIiwgVGltZXMsIHNlcmlmICFkZWZhdWx0O1xuLy8qKiBEZWZhdWx0IG1vbm9zcGFjZSBmb250cyBmb3IgYDxjb2RlPmAsIGA8a2JkPmAsIGFuZCBgPHByZT5gLlxuJGZvbnQtZmFtaWx5LW1vbm9zcGFjZTogICBNZW5sbywgTW9uYWNvLCBDb25zb2xhcywgXCJDb3VyaWVyIE5ld1wiLCBtb25vc3BhY2UgIWRlZmF1bHQ7XG4kZm9udC1mYW1pbHktYmFzZTogICAgICAgICRmb250LWZhbWlseS1zYW5zLXNlcmlmICFkZWZhdWx0O1xuXG4kZm9udC1zaXplLWJhc2U6ICAgICAgICAgIDE0cHggIWRlZmF1bHQ7XG4kZm9udC1zaXplLWxhcmdlOiAgICAgICAgIGNlaWwoKCRmb250LXNpemUtYmFzZSAqIDEuMjUpKSAhZGVmYXVsdDsgLy8gfjE4cHhcbiRmb250LXNpemUtc21hbGw6ICAgICAgICAgY2VpbCgoJGZvbnQtc2l6ZS1iYXNlICogMC44NSkpICFkZWZhdWx0OyAvLyB+MTJweFxuXG4kZm9udC1zaXplLWgxOiAgICAgICAgICAgIGZsb29yKCgkZm9udC1zaXplLWJhc2UgKiAyLjYpKSAhZGVmYXVsdDsgLy8gfjM2cHhcbiRmb250LXNpemUtaDI6ICAgICAgICAgICAgZmxvb3IoKCRmb250LXNpemUtYmFzZSAqIDIuMTUpKSAhZGVmYXVsdDsgLy8gfjMwcHhcbiRmb250LXNpemUtaDM6ICAgICAgICAgICAgY2VpbCgoJGZvbnQtc2l6ZS1iYXNlICogMS43KSkgIWRlZmF1bHQ7IC8vIH4yNHB4XG4kZm9udC1zaXplLWg0OiAgICAgICAgICAgIGNlaWwoKCRmb250LXNpemUtYmFzZSAqIDEuMjUpKSAhZGVmYXVsdDsgLy8gfjE4cHhcbiRmb250LXNpemUtaDU6ICAgICAgICAgICAgJGZvbnQtc2l6ZS1iYXNlICFkZWZhdWx0O1xuJGZvbnQtc2l6ZS1oNjogICAgICAgICAgICBjZWlsKCgkZm9udC1zaXplLWJhc2UgKiAwLjg1KSkgIWRlZmF1bHQ7IC8vIH4xMnB4XG5cbi8vKiogVW5pdC1sZXNzIGBsaW5lLWhlaWdodGAgZm9yIHVzZSBpbiBjb21wb25lbnRzIGxpa2UgYnV0dG9ucy5cbiRsaW5lLWhlaWdodC1iYXNlOiAgICAgICAgMS40Mjg1NzE0MjkgIWRlZmF1bHQ7IC8vIDIwLzE0XG4vLyoqIENvbXB1dGVkIFwibGluZS1oZWlnaHRcIiAoYGZvbnQtc2l6ZWAgKiBgbGluZS1oZWlnaHRgKSBmb3IgdXNlIHdpdGggYG1hcmdpbmAsIGBwYWRkaW5nYCwgZXRjLlxuJGxpbmUtaGVpZ2h0LWNvbXB1dGVkOiAgICBmbG9vcigoJGZvbnQtc2l6ZS1iYXNlICogJGxpbmUtaGVpZ2h0LWJhc2UpKSAhZGVmYXVsdDsgLy8gfjIwcHhcblxuLy8qKiBCeSBkZWZhdWx0LCB0aGlzIGluaGVyaXRzIGZyb20gdGhlIGA8Ym9keT5gLlxuJGhlYWRpbmdzLWZvbnQtZmFtaWx5OiAgICBpbmhlcml0ICFkZWZhdWx0O1xuJGhlYWRpbmdzLWZvbnQtd2VpZ2h0OiAgICA1MDAgIWRlZmF1bHQ7XG4kaGVhZGluZ3MtbGluZS1oZWlnaHQ6ICAgIDEuMSAhZGVmYXVsdDtcbiRoZWFkaW5ncy1jb2xvcjogICAgICAgICAgaW5oZXJpdCAhZGVmYXVsdDtcblxuXG4vLz09IEljb25vZ3JhcGh5XG4vL1xuLy8jIyBTcGVjaWZ5IGN1c3RvbSBsb2NhdGlvbiBhbmQgZmlsZW5hbWUgb2YgdGhlIGluY2x1ZGVkIEdseXBoaWNvbnMgaWNvbiBmb250LiBVc2VmdWwgZm9yIHRob3NlIGluY2x1ZGluZyBCb290c3RyYXAgdmlhIEJvd2VyLlxuXG4vLyoqIExvYWQgZm9udHMgZnJvbSB0aGlzIGRpcmVjdG9yeS5cblxuLy8gW2NvbnZlcnRlcl0gSWYgJGJvb3RzdHJhcC1zYXNzLWFzc2V0LWhlbHBlciBpZiB1c2VkLCBwcm92aWRlIHBhdGggcmVsYXRpdmUgdG8gdGhlIGFzc2V0cyBsb2FkIHBhdGguXG4vLyBbY29udmVydGVyXSBUaGlzIGlzIGJlY2F1c2Ugc29tZSBhc3NldCBoZWxwZXJzLCBzdWNoIGFzIFNwcm9ja2V0cywgZG8gbm90IHdvcmsgd2l0aCBmaWxlLXJlbGF0aXZlIHBhdGhzLlxuJGljb24tZm9udC1wYXRoOiBpZigkYm9vdHN0cmFwLXNhc3MtYXNzZXQtaGVscGVyLCBcImJvb3RzdHJhcC9cIiwgXCIuLi9mb250cy9ib290c3RyYXAvXCIpICFkZWZhdWx0O1xuXG4vLyoqIEZpbGUgbmFtZSBmb3IgYWxsIGZvbnQgZmlsZXMuXG4kaWNvbi1mb250LW5hbWU6ICAgICAgICAgIFwiZ2x5cGhpY29ucy1oYWxmbGluZ3MtcmVndWxhclwiICFkZWZhdWx0O1xuLy8qKiBFbGVtZW50IElEIHdpdGhpbiBTVkcgaWNvbiBmaWxlLlxuJGljb24tZm9udC1zdmctaWQ6ICAgICAgICBcImdseXBoaWNvbnNfaGFsZmxpbmdzcmVndWxhclwiICFkZWZhdWx0O1xuXG5cbi8vPT0gQ29tcG9uZW50c1xuLy9cbi8vIyMgRGVmaW5lIGNvbW1vbiBwYWRkaW5nIGFuZCBib3JkZXIgcmFkaXVzIHNpemVzIGFuZCBtb3JlLiBWYWx1ZXMgYmFzZWQgb24gMTRweCB0ZXh0IGFuZCAxLjQyOCBsaW5lLWhlaWdodCAofjIwcHggdG8gc3RhcnQpLlxuXG4kcGFkZGluZy1iYXNlLXZlcnRpY2FsOiAgICAgNnB4ICFkZWZhdWx0O1xuJHBhZGRpbmctYmFzZS1ob3Jpem9udGFsOiAgIDEycHggIWRlZmF1bHQ7XG5cbiRwYWRkaW5nLWxhcmdlLXZlcnRpY2FsOiAgICAxMHB4ICFkZWZhdWx0O1xuJHBhZGRpbmctbGFyZ2UtaG9yaXpvbnRhbDogIDE2cHggIWRlZmF1bHQ7XG5cbiRwYWRkaW5nLXNtYWxsLXZlcnRpY2FsOiAgICA1cHggIWRlZmF1bHQ7XG4kcGFkZGluZy1zbWFsbC1ob3Jpem9udGFsOiAgMTBweCAhZGVmYXVsdDtcblxuJHBhZGRpbmcteHMtdmVydGljYWw6ICAgICAgIDFweCAhZGVmYXVsdDtcbiRwYWRkaW5nLXhzLWhvcml6b250YWw6ICAgICA1cHggIWRlZmF1bHQ7XG5cbiRsaW5lLWhlaWdodC1sYXJnZTogICAgICAgICAxLjMzMzMzMzMgIWRlZmF1bHQ7IC8vIGV4dHJhIGRlY2ltYWxzIGZvciBXaW4gOC4xIENocm9tZVxuJGxpbmUtaGVpZ2h0LXNtYWxsOiAgICAgICAgIDEuNSAhZGVmYXVsdDtcblxuJGJvcmRlci1yYWRpdXMtYmFzZTogICAgICAgIDRweCAhZGVmYXVsdDtcbiRib3JkZXItcmFkaXVzLWxhcmdlOiAgICAgICA2cHggIWRlZmF1bHQ7XG4kYm9yZGVyLXJhZGl1cy1zbWFsbDogICAgICAgM3B4ICFkZWZhdWx0O1xuXG4vLyoqIEdsb2JhbCBjb2xvciBmb3IgYWN0aXZlIGl0ZW1zIChlLmcuLCBuYXZzIG9yIGRyb3Bkb3ducykuXG4kY29tcG9uZW50LWFjdGl2ZS1jb2xvcjogICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogR2xvYmFsIGJhY2tncm91bmQgY29sb3IgZm9yIGFjdGl2ZSBpdGVtcyAoZS5nLiwgbmF2cyBvciBkcm9wZG93bnMpLlxuJGNvbXBvbmVudC1hY3RpdmUtYmc6ICAgICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuXG4vLyoqIFdpZHRoIG9mIHRoZSBgYm9yZGVyYCBmb3IgZ2VuZXJhdGluZyBjYXJldHMgdGhhdCBpbmRpY2F0b3IgZHJvcGRvd25zLlxuJGNhcmV0LXdpZHRoLWJhc2U6ICAgICAgICAgIDRweCAhZGVmYXVsdDtcbi8vKiogQ2FyZXRzIGluY3JlYXNlIHNsaWdodGx5IGluIHNpemUgZm9yIGxhcmdlciBjb21wb25lbnRzLlxuJGNhcmV0LXdpZHRoLWxhcmdlOiAgICAgICAgIDVweCAhZGVmYXVsdDtcblxuXG4vLz09IFRhYmxlc1xuLy9cbi8vIyMgQ3VzdG9taXplcyB0aGUgYC50YWJsZWAgY29tcG9uZW50IHdpdGggYmFzaWMgdmFsdWVzLCBlYWNoIHVzZWQgYWNyb3NzIGFsbCB0YWJsZSB2YXJpYXRpb25zLlxuXG4vLyoqIFBhZGRpbmcgZm9yIGA8dGg+YHMgYW5kIGA8dGQ+YHMuXG4kdGFibGUtY2VsbC1wYWRkaW5nOiAgICAgICAgICAgIDhweCAhZGVmYXVsdDtcbi8vKiogUGFkZGluZyBmb3IgY2VsbHMgaW4gYC50YWJsZS1jb25kZW5zZWRgLlxuJHRhYmxlLWNvbmRlbnNlZC1jZWxsLXBhZGRpbmc6ICA1cHggIWRlZmF1bHQ7XG5cbi8vKiogRGVmYXVsdCBiYWNrZ3JvdW5kIGNvbG9yIHVzZWQgZm9yIGFsbCB0YWJsZXMuXG4kdGFibGUtYmc6ICAgICAgICAgICAgICAgICAgICAgIHRyYW5zcGFyZW50ICFkZWZhdWx0O1xuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIHVzZWQgZm9yIGAudGFibGUtc3RyaXBlZGAuXG4kdGFibGUtYmctYWNjZW50OiAgICAgICAgICAgICAgICNmOWY5ZjkgIWRlZmF1bHQ7XG4vLyoqIEJhY2tncm91bmQgY29sb3IgdXNlZCBmb3IgYC50YWJsZS1ob3ZlcmAuXG4kdGFibGUtYmctaG92ZXI6ICAgICAgICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG4kdGFibGUtYmctYWN0aXZlOiAgICAgICAgICAgICAgICR0YWJsZS1iZy1ob3ZlciAhZGVmYXVsdDtcblxuLy8qKiBCb3JkZXIgY29sb3IgZm9yIHRhYmxlIGFuZCBjZWxsIGJvcmRlcnMuXG4kdGFibGUtYm9yZGVyLWNvbG9yOiAgICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG5cblxuLy89PSBCdXR0b25zXG4vL1xuLy8jIyBGb3IgZWFjaCBvZiBCb290c3RyYXAncyBidXR0b25zLCBkZWZpbmUgdGV4dCwgYmFja2dyb3VuZCBhbmQgYm9yZGVyIGNvbG9yLlxuXG4kYnRuLWZvbnQtd2VpZ2h0OiAgICAgICAgICAgICAgICBub3JtYWwgIWRlZmF1bHQ7XG5cbiRidG4tZGVmYXVsdC1jb2xvcjogICAgICAgICAgICAgICMzMzMgIWRlZmF1bHQ7XG4kYnRuLWRlZmF1bHQtYmc6ICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGJ0bi1kZWZhdWx0LWJvcmRlcjogICAgICAgICAgICAgI2NjYyAhZGVmYXVsdDtcblxuJGJ0bi1wcmltYXJ5LWNvbG9yOiAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRidG4tcHJpbWFyeS1iZzogICAgICAgICAgICAgICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuJGJ0bi1wcmltYXJ5LWJvcmRlcjogICAgICAgICAgICAgZGFya2VuKCRidG4tcHJpbWFyeS1iZywgNSUpICFkZWZhdWx0O1xuXG4kYnRuLXN1Y2Nlc3MtY29sb3I6ICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGJ0bi1zdWNjZXNzLWJnOiAgICAgICAgICAgICAgICAgJGJyYW5kLXN1Y2Nlc3MgIWRlZmF1bHQ7XG4kYnRuLXN1Y2Nlc3MtYm9yZGVyOiAgICAgICAgICAgICBkYXJrZW4oJGJ0bi1zdWNjZXNzLWJnLCA1JSkgIWRlZmF1bHQ7XG5cbiRidG4taW5mby1jb2xvcjogICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kYnRuLWluZm8tYmc6ICAgICAgICAgICAgICAgICAgICAkYnJhbmQtaW5mbyAhZGVmYXVsdDtcbiRidG4taW5mby1ib3JkZXI6ICAgICAgICAgICAgICAgIGRhcmtlbigkYnRuLWluZm8tYmcsIDUlKSAhZGVmYXVsdDtcblxuJGJ0bi13YXJuaW5nLWNvbG9yOiAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRidG4td2FybmluZy1iZzogICAgICAgICAgICAgICAgICRicmFuZC13YXJuaW5nICFkZWZhdWx0O1xuJGJ0bi13YXJuaW5nLWJvcmRlcjogICAgICAgICAgICAgZGFya2VuKCRidG4td2FybmluZy1iZywgNSUpICFkZWZhdWx0O1xuXG4kYnRuLWRhbmdlci1jb2xvcjogICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGJ0bi1kYW5nZXItYmc6ICAgICAgICAgICAgICAgICAgJGJyYW5kLWRhbmdlciAhZGVmYXVsdDtcbiRidG4tZGFuZ2VyLWJvcmRlcjogICAgICAgICAgICAgIGRhcmtlbigkYnRuLWRhbmdlci1iZywgNSUpICFkZWZhdWx0O1xuXG4kYnRuLWxpbmstZGlzYWJsZWQtY29sb3I6ICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcblxuLy8gQWxsb3dzIGZvciBjdXN0b21pemluZyBidXR0b24gcmFkaXVzIGluZGVwZW5kZW50bHkgZnJvbSBnbG9iYWwgYm9yZGVyIHJhZGl1c1xuJGJ0bi1ib3JkZXItcmFkaXVzLWJhc2U6ICAgICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcbiRidG4tYm9yZGVyLXJhZGl1cy1sYXJnZTogICAgICAgICRib3JkZXItcmFkaXVzLWxhcmdlICFkZWZhdWx0O1xuJGJ0bi1ib3JkZXItcmFkaXVzLXNtYWxsOiAgICAgICAgJGJvcmRlci1yYWRpdXMtc21hbGwgIWRlZmF1bHQ7XG5cblxuLy89PSBGb3Jtc1xuLy9cbi8vIyNcblxuLy8qKiBgPGlucHV0PmAgYmFja2dyb3VuZCBjb2xvclxuJGlucHV0LWJnOiAgICAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogYDxpbnB1dCBkaXNhYmxlZD5gIGJhY2tncm91bmQgY29sb3JcbiRpbnB1dC1iZy1kaXNhYmxlZDogICAgICAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG5cbi8vKiogVGV4dCBjb2xvciBmb3IgYDxpbnB1dD5gc1xuJGlucHV0LWNvbG9yOiAgICAgICAgICAgICAgICAgICAgJGdyYXkgIWRlZmF1bHQ7XG4vLyoqIGA8aW5wdXQ+YCBib3JkZXIgY29sb3JcbiRpbnB1dC1ib3JkZXI6ICAgICAgICAgICAgICAgICAgICNjY2MgIWRlZmF1bHQ7XG5cbi8vIFRPRE86IFJlbmFtZSBgJGlucHV0LWJvcmRlci1yYWRpdXNgIHRvIGAkaW5wdXQtYm9yZGVyLXJhZGl1cy1iYXNlYCBpbiB2NFxuLy8qKiBEZWZhdWx0IGAuZm9ybS1jb250cm9sYCBib3JkZXIgcmFkaXVzXG4vLyBUaGlzIGhhcyBubyBlZmZlY3Qgb24gYDxzZWxlY3Q+YHMgaW4gc29tZSBicm93c2VycywgZHVlIHRvIHRoZSBsaW1pdGVkIHN0eWxhYmlsaXR5IG9mIGA8c2VsZWN0PmBzIGluIENTUy5cbiRpbnB1dC1ib3JkZXItcmFkaXVzOiAgICAgICAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG4vLyoqIExhcmdlIGAuZm9ybS1jb250cm9sYCBib3JkZXIgcmFkaXVzXG4kaW5wdXQtYm9yZGVyLXJhZGl1cy1sYXJnZTogICAgICAkYm9yZGVyLXJhZGl1cy1sYXJnZSAhZGVmYXVsdDtcbi8vKiogU21hbGwgYC5mb3JtLWNvbnRyb2xgIGJvcmRlciByYWRpdXNcbiRpbnB1dC1ib3JkZXItcmFkaXVzLXNtYWxsOiAgICAgICRib3JkZXItcmFkaXVzLXNtYWxsICFkZWZhdWx0O1xuXG4vLyoqIEJvcmRlciBjb2xvciBmb3IgaW5wdXRzIG9uIGZvY3VzXG4kaW5wdXQtYm9yZGVyLWZvY3VzOiAgICAgICAgICAgICAjNjZhZmU5ICFkZWZhdWx0O1xuXG4vLyoqIFBsYWNlaG9sZGVyIHRleHQgY29sb3JcbiRpbnB1dC1jb2xvci1wbGFjZWhvbGRlcjogICAgICAgICM5OTkgIWRlZmF1bHQ7XG5cbi8vKiogRGVmYXVsdCBgLmZvcm0tY29udHJvbGAgaGVpZ2h0XG4kaW5wdXQtaGVpZ2h0LWJhc2U6ICAgICAgICAgICAgICAoJGxpbmUtaGVpZ2h0LWNvbXB1dGVkICsgKCRwYWRkaW5nLWJhc2UtdmVydGljYWwgKiAyKSArIDIpICFkZWZhdWx0O1xuLy8qKiBMYXJnZSBgLmZvcm0tY29udHJvbGAgaGVpZ2h0XG4kaW5wdXQtaGVpZ2h0LWxhcmdlOiAgICAgICAgICAgICAoY2VpbCgkZm9udC1zaXplLWxhcmdlICogJGxpbmUtaGVpZ2h0LWxhcmdlKSArICgkcGFkZGluZy1sYXJnZS12ZXJ0aWNhbCAqIDIpICsgMikgIWRlZmF1bHQ7XG4vLyoqIFNtYWxsIGAuZm9ybS1jb250cm9sYCBoZWlnaHRcbiRpbnB1dC1oZWlnaHQtc21hbGw6ICAgICAgICAgICAgIChmbG9vcigkZm9udC1zaXplLXNtYWxsICogJGxpbmUtaGVpZ2h0LXNtYWxsKSArICgkcGFkZGluZy1zbWFsbC12ZXJ0aWNhbCAqIDIpICsgMikgIWRlZmF1bHQ7XG5cbi8vKiogYC5mb3JtLWdyb3VwYCBtYXJnaW5cbiRmb3JtLWdyb3VwLW1hcmdpbi1ib3R0b206ICAgICAgIDE1cHggIWRlZmF1bHQ7XG5cbiRsZWdlbmQtY29sb3I6ICAgICAgICAgICAgICAgICAgICRncmF5LWRhcmsgIWRlZmF1bHQ7XG4kbGVnZW5kLWJvcmRlci1jb2xvcjogICAgICAgICAgICAjZTVlNWU1ICFkZWZhdWx0O1xuXG4vLyoqIEJhY2tncm91bmQgY29sb3IgZm9yIHRleHR1YWwgaW5wdXQgYWRkb25zXG4kaW5wdXQtZ3JvdXAtYWRkb24tYmc6ICAgICAgICAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuLy8qKiBCb3JkZXIgY29sb3IgZm9yIHRleHR1YWwgaW5wdXQgYWRkb25zXG4kaW5wdXQtZ3JvdXAtYWRkb24tYm9yZGVyLWNvbG9yOiAkaW5wdXQtYm9yZGVyICFkZWZhdWx0O1xuXG4vLyoqIERpc2FibGVkIGN1cnNvciBmb3IgZm9ybSBjb250cm9scyBhbmQgYnV0dG9ucy5cbiRjdXJzb3ItZGlzYWJsZWQ6ICAgICAgICAgICAgICAgIG5vdC1hbGxvd2VkICFkZWZhdWx0O1xuXG5cbi8vPT0gRHJvcGRvd25zXG4vL1xuLy8jIyBEcm9wZG93biBtZW51IGNvbnRhaW5lciBhbmQgY29udGVudHMuXG5cbi8vKiogQmFja2dyb3VuZCBmb3IgdGhlIGRyb3Bkb3duIG1lbnUuXG4kZHJvcGRvd24tYmc6ICAgICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBEcm9wZG93biBtZW51IGBib3JkZXItY29sb3JgLlxuJGRyb3Bkb3duLWJvcmRlcjogICAgICAgICAgICAgICAgcmdiYSgwLDAsMCwuMTUpICFkZWZhdWx0O1xuLy8qKiBEcm9wZG93biBtZW51IGBib3JkZXItY29sb3JgICoqZm9yIElFOCoqLlxuJGRyb3Bkb3duLWZhbGxiYWNrLWJvcmRlcjogICAgICAgI2NjYyAhZGVmYXVsdDtcbi8vKiogRGl2aWRlciBjb2xvciBmb3IgYmV0d2VlbiBkcm9wZG93biBpdGVtcy5cbiRkcm9wZG93bi1kaXZpZGVyLWJnOiAgICAgICAgICAgICNlNWU1ZTUgIWRlZmF1bHQ7XG5cbi8vKiogRHJvcGRvd24gbGluayB0ZXh0IGNvbG9yLlxuJGRyb3Bkb3duLWxpbmstY29sb3I6ICAgICAgICAgICAgJGdyYXktZGFyayAhZGVmYXVsdDtcbi8vKiogSG92ZXIgY29sb3IgZm9yIGRyb3Bkb3duIGxpbmtzLlxuJGRyb3Bkb3duLWxpbmstaG92ZXItY29sb3I6ICAgICAgZGFya2VuKCRncmF5LWRhcmssIDUlKSAhZGVmYXVsdDtcbi8vKiogSG92ZXIgYmFja2dyb3VuZCBmb3IgZHJvcGRvd24gbGlua3MuXG4kZHJvcGRvd24tbGluay1ob3Zlci1iZzogICAgICAgICAjZjVmNWY1ICFkZWZhdWx0O1xuXG4vLyoqIEFjdGl2ZSBkcm9wZG93biBtZW51IGl0ZW0gdGV4dCBjb2xvci5cbiRkcm9wZG93bi1saW5rLWFjdGl2ZS1jb2xvcjogICAgICRjb21wb25lbnQtYWN0aXZlLWNvbG9yICFkZWZhdWx0O1xuLy8qKiBBY3RpdmUgZHJvcGRvd24gbWVudSBpdGVtIGJhY2tncm91bmQgY29sb3IuXG4kZHJvcGRvd24tbGluay1hY3RpdmUtYmc6ICAgICAgICAkY29tcG9uZW50LWFjdGl2ZS1iZyAhZGVmYXVsdDtcblxuLy8qKiBEaXNhYmxlZCBkcm9wZG93biBtZW51IGl0ZW0gYmFja2dyb3VuZCBjb2xvci5cbiRkcm9wZG93bi1saW5rLWRpc2FibGVkLWNvbG9yOiAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuXG4vLyoqIFRleHQgY29sb3IgZm9yIGhlYWRlcnMgd2l0aGluIGRyb3Bkb3duIG1lbnVzLlxuJGRyb3Bkb3duLWhlYWRlci1jb2xvcjogICAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG5cbi8vKiogRGVwcmVjYXRlZCBgJGRyb3Bkb3duLWNhcmV0LWNvbG9yYCBhcyBvZiB2My4xLjBcbiRkcm9wZG93bi1jYXJldC1jb2xvcjogICAgICAgICAgICMwMDAgIWRlZmF1bHQ7XG5cblxuLy8tLSBaLWluZGV4IG1hc3RlciBsaXN0XG4vL1xuLy8gV2FybmluZzogQXZvaWQgY3VzdG9taXppbmcgdGhlc2UgdmFsdWVzLiBUaGV5J3JlIHVzZWQgZm9yIGEgYmlyZCdzIGV5ZSB2aWV3XG4vLyBvZiBjb21wb25lbnRzIGRlcGVuZGVudCBvbiB0aGUgei1heGlzIGFuZCBhcmUgZGVzaWduZWQgdG8gYWxsIHdvcmsgdG9nZXRoZXIuXG4vL1xuLy8gTm90ZTogVGhlc2UgdmFyaWFibGVzIGFyZSBub3QgZ2VuZXJhdGVkIGludG8gdGhlIEN1c3RvbWl6ZXIuXG5cbiR6aW5kZXgtbmF2YmFyOiAgICAgICAgICAgIDEwMDAgIWRlZmF1bHQ7XG4kemluZGV4LWRyb3Bkb3duOiAgICAgICAgICAxMDAwICFkZWZhdWx0O1xuJHppbmRleC1wb3BvdmVyOiAgICAgICAgICAgMTA2MCAhZGVmYXVsdDtcbiR6aW5kZXgtdG9vbHRpcDogICAgICAgICAgIDEwNzAgIWRlZmF1bHQ7XG4kemluZGV4LW5hdmJhci1maXhlZDogICAgICAxMDMwICFkZWZhdWx0O1xuJHppbmRleC1tb2RhbC1iYWNrZ3JvdW5kOiAgMTA0MCAhZGVmYXVsdDtcbiR6aW5kZXgtbW9kYWw6ICAgICAgICAgICAgIDEwNTAgIWRlZmF1bHQ7XG5cblxuLy89PSBNZWRpYSBxdWVyaWVzIGJyZWFrcG9pbnRzXG4vL1xuLy8jIyBEZWZpbmUgdGhlIGJyZWFrcG9pbnRzIGF0IHdoaWNoIHlvdXIgbGF5b3V0IHdpbGwgY2hhbmdlLCBhZGFwdGluZyB0byBkaWZmZXJlbnQgc2NyZWVuIHNpemVzLlxuXG4vLyBFeHRyYSBzbWFsbCBzY3JlZW4gLyBwaG9uZVxuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLXhzYCBhcyBvZiB2My4wLjFcbiRzY3JlZW4teHM6ICAgICAgICAgICAgICAgICAgNDgwcHggIWRlZmF1bHQ7XG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4teHMtbWluYCBhcyBvZiB2My4yLjBcbiRzY3JlZW4teHMtbWluOiAgICAgICAgICAgICAgJHNjcmVlbi14cyAhZGVmYXVsdDtcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi1waG9uZWAgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLXBob25lOiAgICAgICAgICAgICAgICRzY3JlZW4teHMtbWluICFkZWZhdWx0O1xuXG4vLyBTbWFsbCBzY3JlZW4gLyB0YWJsZXRcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi1zbWAgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLXNtOiAgICAgICAgICAgICAgICAgIDc2OHB4ICFkZWZhdWx0O1xuJHNjcmVlbi1zbS1taW46ICAgICAgICAgICAgICAkc2NyZWVuLXNtICFkZWZhdWx0O1xuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLXRhYmxldGAgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLXRhYmxldDogICAgICAgICAgICAgICRzY3JlZW4tc20tbWluICFkZWZhdWx0O1xuXG4vLyBNZWRpdW0gc2NyZWVuIC8gZGVza3RvcFxuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLW1kYCBhcyBvZiB2My4wLjFcbiRzY3JlZW4tbWQ6ICAgICAgICAgICAgICAgICAgOTkycHggIWRlZmF1bHQ7XG4kc2NyZWVuLW1kLW1pbjogICAgICAgICAgICAgICRzY3JlZW4tbWQgIWRlZmF1bHQ7XG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4tZGVza3RvcGAgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLWRlc2t0b3A6ICAgICAgICAgICAgICRzY3JlZW4tbWQtbWluICFkZWZhdWx0O1xuXG4vLyBMYXJnZSBzY3JlZW4gLyB3aWRlIGRlc2t0b3Bcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi1sZ2AgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLWxnOiAgICAgICAgICAgICAgICAgIDEyMDBweCAhZGVmYXVsdDtcbiRzY3JlZW4tbGctbWluOiAgICAgICAgICAgICAgJHNjcmVlbi1sZyAhZGVmYXVsdDtcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi1sZy1kZXNrdG9wYCBhcyBvZiB2My4wLjFcbiRzY3JlZW4tbGctZGVza3RvcDogICAgICAgICAgJHNjcmVlbi1sZy1taW4gIWRlZmF1bHQ7XG5cbi8vIFNvIG1lZGlhIHF1ZXJpZXMgZG9uJ3Qgb3ZlcmxhcCB3aGVuIHJlcXVpcmVkLCBwcm92aWRlIGEgbWF4aW11bVxuJHNjcmVlbi14cy1tYXg6ICAgICAgICAgICAgICAoJHNjcmVlbi1zbS1taW4gLSAxKSAhZGVmYXVsdDtcbiRzY3JlZW4tc20tbWF4OiAgICAgICAgICAgICAgKCRzY3JlZW4tbWQtbWluIC0gMSkgIWRlZmF1bHQ7XG4kc2NyZWVuLW1kLW1heDogICAgICAgICAgICAgICgkc2NyZWVuLWxnLW1pbiAtIDEpICFkZWZhdWx0O1xuXG5cbi8vPT0gR3JpZCBzeXN0ZW1cbi8vXG4vLyMjIERlZmluZSB5b3VyIGN1c3RvbSByZXNwb25zaXZlIGdyaWQuXG5cbi8vKiogTnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhlIGdyaWQuXG4kZ3JpZC1jb2x1bW5zOiAgICAgICAgICAgICAgMTIgIWRlZmF1bHQ7XG4vLyoqIFBhZGRpbmcgYmV0d2VlbiBjb2x1bW5zLiBHZXRzIGRpdmlkZWQgaW4gaGFsZiBmb3IgdGhlIGxlZnQgYW5kIHJpZ2h0LlxuJGdyaWQtZ3V0dGVyLXdpZHRoOiAgICAgICAgIDMwcHggIWRlZmF1bHQ7XG4vLyBOYXZiYXIgY29sbGFwc2Vcbi8vKiogUG9pbnQgYXQgd2hpY2ggdGhlIG5hdmJhciBiZWNvbWVzIHVuY29sbGFwc2VkLlxuJGdyaWQtZmxvYXQtYnJlYWtwb2ludDogICAgICRzY3JlZW4tc20tbWluICFkZWZhdWx0O1xuLy8qKiBQb2ludCBhdCB3aGljaCB0aGUgbmF2YmFyIGJlZ2lucyBjb2xsYXBzaW5nLlxuJGdyaWQtZmxvYXQtYnJlYWtwb2ludC1tYXg6ICgkZ3JpZC1mbG9hdC1icmVha3BvaW50IC0gMSkgIWRlZmF1bHQ7XG5cblxuLy89PSBDb250YWluZXIgc2l6ZXNcbi8vXG4vLyMjIERlZmluZSB0aGUgbWF4aW11bSB3aWR0aCBvZiBgLmNvbnRhaW5lcmAgZm9yIGRpZmZlcmVudCBzY3JlZW4gc2l6ZXMuXG5cbi8vIFNtYWxsIHNjcmVlbiAvIHRhYmxldFxuJGNvbnRhaW5lci10YWJsZXQ6ICAgICAgICAgICAgICg3MjBweCArICRncmlkLWd1dHRlci13aWR0aCkgIWRlZmF1bHQ7XG4vLyoqIEZvciBgJHNjcmVlbi1zbS1taW5gIGFuZCB1cC5cbiRjb250YWluZXItc206ICAgICAgICAgICAgICAgICAkY29udGFpbmVyLXRhYmxldCAhZGVmYXVsdDtcblxuLy8gTWVkaXVtIHNjcmVlbiAvIGRlc2t0b3BcbiRjb250YWluZXItZGVza3RvcDogICAgICAgICAgICAoOTQwcHggKyAkZ3JpZC1ndXR0ZXItd2lkdGgpICFkZWZhdWx0O1xuLy8qKiBGb3IgYCRzY3JlZW4tbWQtbWluYCBhbmQgdXAuXG4kY29udGFpbmVyLW1kOiAgICAgICAgICAgICAgICAgJGNvbnRhaW5lci1kZXNrdG9wICFkZWZhdWx0O1xuXG4vLyBMYXJnZSBzY3JlZW4gLyB3aWRlIGRlc2t0b3BcbiRjb250YWluZXItbGFyZ2UtZGVza3RvcDogICAgICAoMTE0MHB4ICsgJGdyaWQtZ3V0dGVyLXdpZHRoKSAhZGVmYXVsdDtcbi8vKiogRm9yIGAkc2NyZWVuLWxnLW1pbmAgYW5kIHVwLlxuJGNvbnRhaW5lci1sZzogICAgICAgICAgICAgICAgICRjb250YWluZXItbGFyZ2UtZGVza3RvcCAhZGVmYXVsdDtcblxuXG4vLz09IE5hdmJhclxuLy9cbi8vIyNcblxuLy8gQmFzaWNzIG9mIGEgbmF2YmFyXG4kbmF2YmFyLWhlaWdodDogICAgICAgICAgICAgICAgICAgIDUwcHggIWRlZmF1bHQ7XG4kbmF2YmFyLW1hcmdpbi1ib3R0b206ICAgICAgICAgICAgICRsaW5lLWhlaWdodC1jb21wdXRlZCAhZGVmYXVsdDtcbiRuYXZiYXItYm9yZGVyLXJhZGl1czogICAgICAgICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcbiRuYXZiYXItcGFkZGluZy1ob3Jpem9udGFsOiAgICAgICAgZmxvb3IoKCRncmlkLWd1dHRlci13aWR0aCAvIDIpKSAhZGVmYXVsdDtcbiRuYXZiYXItcGFkZGluZy12ZXJ0aWNhbDogICAgICAgICAgKCgkbmF2YmFyLWhlaWdodCAtICRsaW5lLWhlaWdodC1jb21wdXRlZCkgLyAyKSAhZGVmYXVsdDtcbiRuYXZiYXItY29sbGFwc2UtbWF4LWhlaWdodDogICAgICAgMzQwcHggIWRlZmF1bHQ7XG5cbiRuYXZiYXItZGVmYXVsdC1jb2xvcjogICAgICAgICAgICAgIzc3NyAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1iZzogICAgICAgICAgICAgICAgI2Y4ZjhmOCAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1ib3JkZXI6ICAgICAgICAgICAgZGFya2VuKCRuYXZiYXItZGVmYXVsdC1iZywgNi41JSkgIWRlZmF1bHQ7XG5cbi8vIE5hdmJhciBsaW5rc1xuJG5hdmJhci1kZWZhdWx0LWxpbmstY29sb3I6ICAgICAgICAgICAgICAgICM3NzcgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtbGluay1ob3Zlci1jb2xvcjogICAgICAgICAgIzMzMyAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1saW5rLWhvdmVyLWJnOiAgICAgICAgICAgICB0cmFuc3BhcmVudCAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1saW5rLWFjdGl2ZS1jb2xvcjogICAgICAgICAjNTU1ICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWxpbmstYWN0aXZlLWJnOiAgICAgICAgICAgIGRhcmtlbigkbmF2YmFyLWRlZmF1bHQtYmcsIDYuNSUpICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWxpbmstZGlzYWJsZWQtY29sb3I6ICAgICAgICNjY2MgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtbGluay1kaXNhYmxlZC1iZzogICAgICAgICAgdHJhbnNwYXJlbnQgIWRlZmF1bHQ7XG5cbi8vIE5hdmJhciBicmFuZCBsYWJlbFxuJG5hdmJhci1kZWZhdWx0LWJyYW5kLWNvbG9yOiAgICAgICAgICAgICAgICRuYXZiYXItZGVmYXVsdC1saW5rLWNvbG9yICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWJyYW5kLWhvdmVyLWNvbG9yOiAgICAgICAgIGRhcmtlbigkbmF2YmFyLWRlZmF1bHQtYnJhbmQtY29sb3IsIDEwJSkgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtYnJhbmQtaG92ZXItYmc6ICAgICAgICAgICAgdHJhbnNwYXJlbnQgIWRlZmF1bHQ7XG5cbi8vIE5hdmJhciB0b2dnbGVcbiRuYXZiYXItZGVmYXVsdC10b2dnbGUtaG92ZXItYmc6ICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LXRvZ2dsZS1pY29uLWJhci1iZzogICAgICAgICM4ODggIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtdG9nZ2xlLWJvcmRlci1jb2xvcjogICAgICAgI2RkZCAhZGVmYXVsdDtcblxuXG4vLz09PSBJbnZlcnRlZCBuYXZiYXJcbi8vIFJlc2V0IGludmVydGVkIG5hdmJhciBiYXNpY3NcbiRuYXZiYXItaW52ZXJzZS1jb2xvcjogICAgICAgICAgICAgICAgICAgICAgbGlnaHRlbigkZ3JheS1saWdodCwgMTUlKSAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1iZzogICAgICAgICAgICAgICAgICAgICAgICAgIzIyMiAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1ib3JkZXI6ICAgICAgICAgICAgICAgICAgICAgZGFya2VuKCRuYXZiYXItaW52ZXJzZS1iZywgMTAlKSAhZGVmYXVsdDtcblxuLy8gSW52ZXJ0ZWQgbmF2YmFyIGxpbmtzXG4kbmF2YmFyLWludmVyc2UtbGluay1jb2xvcjogICAgICAgICAgICAgICAgIGxpZ2h0ZW4oJGdyYXktbGlnaHQsIDE1JSkgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtbGluay1ob3Zlci1jb2xvcjogICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtbGluay1ob3Zlci1iZzogICAgICAgICAgICAgIHRyYW5zcGFyZW50ICFkZWZhdWx0O1xuJG5hdmJhci1pbnZlcnNlLWxpbmstYWN0aXZlLWNvbG9yOiAgICAgICAgICAkbmF2YmFyLWludmVyc2UtbGluay1ob3Zlci1jb2xvciAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1saW5rLWFjdGl2ZS1iZzogICAgICAgICAgICAgZGFya2VuKCRuYXZiYXItaW52ZXJzZS1iZywgMTAlKSAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1saW5rLWRpc2FibGVkLWNvbG9yOiAgICAgICAgIzQ0NCAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1saW5rLWRpc2FibGVkLWJnOiAgICAgICAgICAgdHJhbnNwYXJlbnQgIWRlZmF1bHQ7XG5cbi8vIEludmVydGVkIG5hdmJhciBicmFuZCBsYWJlbFxuJG5hdmJhci1pbnZlcnNlLWJyYW5kLWNvbG9yOiAgICAgICAgICAgICAgICAkbmF2YmFyLWludmVyc2UtbGluay1jb2xvciAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1icmFuZC1ob3Zlci1jb2xvcjogICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1icmFuZC1ob3Zlci1iZzogICAgICAgICAgICAgdHJhbnNwYXJlbnQgIWRlZmF1bHQ7XG5cbi8vIEludmVydGVkIG5hdmJhciB0b2dnbGVcbiRuYXZiYXItaW52ZXJzZS10b2dnbGUtaG92ZXItYmc6ICAgICAgICAgICAgIzMzMyAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS10b2dnbGUtaWNvbi1iYXItYmc6ICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS10b2dnbGUtYm9yZGVyLWNvbG9yOiAgICAgICAgIzMzMyAhZGVmYXVsdDtcblxuXG4vLz09IE5hdnNcbi8vXG4vLyMjXG5cbi8vPT09IFNoYXJlZCBuYXYgc3R5bGVzXG4kbmF2LWxpbmstcGFkZGluZzogICAgICAgICAgICAgICAgICAgICAgICAgIDEwcHggMTVweCAhZGVmYXVsdDtcbiRuYXYtbGluay1ob3Zlci1iZzogICAgICAgICAgICAgICAgICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcblxuJG5hdi1kaXNhYmxlZC1saW5rLWNvbG9yOiAgICAgICAgICAgICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbiRuYXYtZGlzYWJsZWQtbGluay1ob3Zlci1jb2xvcjogICAgICAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG5cbi8vPT0gVGFic1xuJG5hdi10YWJzLWJvcmRlci1jb2xvcjogICAgICAgICAgICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuXG4kbmF2LXRhYnMtbGluay1ob3Zlci1ib3JkZXItY29sb3I6ICAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG5cbiRuYXYtdGFicy1hY3RpdmUtbGluay1ob3Zlci1iZzogICAgICAgICAgICAgJGJvZHktYmcgIWRlZmF1bHQ7XG4kbmF2LXRhYnMtYWN0aXZlLWxpbmstaG92ZXItY29sb3I6ICAgICAgICAgICRncmF5ICFkZWZhdWx0O1xuJG5hdi10YWJzLWFjdGl2ZS1saW5rLWhvdmVyLWJvcmRlci1jb2xvcjogICAjZGRkICFkZWZhdWx0O1xuXG4kbmF2LXRhYnMtanVzdGlmaWVkLWxpbmstYm9yZGVyLWNvbG9yOiAgICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG4kbmF2LXRhYnMtanVzdGlmaWVkLWFjdGl2ZS1saW5rLWJvcmRlci1jb2xvcjogICAgICRib2R5LWJnICFkZWZhdWx0O1xuXG4vLz09IFBpbGxzXG4kbmF2LXBpbGxzLWJvcmRlci1yYWRpdXM6ICAgICAgICAgICAgICAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG4kbmF2LXBpbGxzLWFjdGl2ZS1saW5rLWhvdmVyLWJnOiAgICAgICAgICAgICRjb21wb25lbnQtYWN0aXZlLWJnICFkZWZhdWx0O1xuJG5hdi1waWxscy1hY3RpdmUtbGluay1ob3Zlci1jb2xvcjogICAgICAgICAkY29tcG9uZW50LWFjdGl2ZS1jb2xvciAhZGVmYXVsdDtcblxuXG4vLz09IFBhZ2luYXRpb25cbi8vXG4vLyMjXG5cbiRwYWdpbmF0aW9uLWNvbG9yOiAgICAgICAgICAgICAgICAgICAgICRsaW5rLWNvbG9yICFkZWZhdWx0O1xuJHBhZ2luYXRpb24tYmc6ICAgICAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWJvcmRlcjogICAgICAgICAgICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG5cbiRwYWdpbmF0aW9uLWhvdmVyLWNvbG9yOiAgICAgICAgICAgICAgICRsaW5rLWhvdmVyLWNvbG9yICFkZWZhdWx0O1xuJHBhZ2luYXRpb24taG92ZXItYmc6ICAgICAgICAgICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWhvdmVyLWJvcmRlcjogICAgICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG5cbiRwYWdpbmF0aW9uLWFjdGl2ZS1jb2xvcjogICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kcGFnaW5hdGlvbi1hY3RpdmUtYmc6ICAgICAgICAgICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWFjdGl2ZS1ib3JkZXI6ICAgICAgICAgICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuXG4kcGFnaW5hdGlvbi1kaXNhYmxlZC1jb2xvcjogICAgICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWRpc2FibGVkLWJnOiAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kcGFnaW5hdGlvbi1kaXNhYmxlZC1ib3JkZXI6ICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuXG5cbi8vPT0gUGFnZXJcbi8vXG4vLyMjXG5cbiRwYWdlci1iZzogICAgICAgICAgICAgICAgICAgICAgICAgICAgICRwYWdpbmF0aW9uLWJnICFkZWZhdWx0O1xuJHBhZ2VyLWJvcmRlcjogICAgICAgICAgICAgICAgICAgICAgICAgJHBhZ2luYXRpb24tYm9yZGVyICFkZWZhdWx0O1xuJHBhZ2VyLWJvcmRlci1yYWRpdXM6ICAgICAgICAgICAgICAgICAgMTVweCAhZGVmYXVsdDtcblxuJHBhZ2VyLWhvdmVyLWJnOiAgICAgICAgICAgICAgICAgICAgICAgJHBhZ2luYXRpb24taG92ZXItYmcgIWRlZmF1bHQ7XG5cbiRwYWdlci1hY3RpdmUtYmc6ICAgICAgICAgICAgICAgICAgICAgICRwYWdpbmF0aW9uLWFjdGl2ZS1iZyAhZGVmYXVsdDtcbiRwYWdlci1hY3RpdmUtY29sb3I6ICAgICAgICAgICAgICAgICAgICRwYWdpbmF0aW9uLWFjdGl2ZS1jb2xvciAhZGVmYXVsdDtcblxuJHBhZ2VyLWRpc2FibGVkLWNvbG9yOiAgICAgICAgICAgICAgICAgJHBhZ2luYXRpb24tZGlzYWJsZWQtY29sb3IgIWRlZmF1bHQ7XG5cblxuLy89PSBKdW1ib3Ryb25cbi8vXG4vLyMjXG5cbiRqdW1ib3Ryb24tcGFkZGluZzogICAgICAgICAgICAgIDMwcHggIWRlZmF1bHQ7XG4kanVtYm90cm9uLWNvbG9yOiAgICAgICAgICAgICAgICBpbmhlcml0ICFkZWZhdWx0O1xuJGp1bWJvdHJvbi1iZzogICAgICAgICAgICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbiRqdW1ib3Ryb24taGVhZGluZy1jb2xvcjogICAgICAgIGluaGVyaXQgIWRlZmF1bHQ7XG4kanVtYm90cm9uLWZvbnQtc2l6ZTogICAgICAgICAgICBjZWlsKCgkZm9udC1zaXplLWJhc2UgKiAxLjUpKSAhZGVmYXVsdDtcbiRqdW1ib3Ryb24taGVhZGluZy1mb250LXNpemU6ICAgIGNlaWwoKCRmb250LXNpemUtYmFzZSAqIDQuNSkpICFkZWZhdWx0O1xuXG5cbi8vPT0gRm9ybSBzdGF0ZXMgYW5kIGFsZXJ0c1xuLy9cbi8vIyMgRGVmaW5lIGNvbG9ycyBmb3IgZm9ybSBmZWVkYmFjayBzdGF0ZXMgYW5kLCBieSBkZWZhdWx0LCBhbGVydHMuXG5cbiRzdGF0ZS1zdWNjZXNzLXRleHQ6ICAgICAgICAgICAgICMzYzc2M2QgIWRlZmF1bHQ7XG4kc3RhdGUtc3VjY2Vzcy1iZzogICAgICAgICAgICAgICAjZGZmMGQ4ICFkZWZhdWx0O1xuJHN0YXRlLXN1Y2Nlc3MtYm9yZGVyOiAgICAgICAgICAgZGFya2VuKGFkanVzdC1odWUoJHN0YXRlLXN1Y2Nlc3MtYmcsIC0xMCksIDUlKSAhZGVmYXVsdDtcblxuJHN0YXRlLWluZm8tdGV4dDogICAgICAgICAgICAgICAgIzMxNzA4ZiAhZGVmYXVsdDtcbiRzdGF0ZS1pbmZvLWJnOiAgICAgICAgICAgICAgICAgICNkOWVkZjcgIWRlZmF1bHQ7XG4kc3RhdGUtaW5mby1ib3JkZXI6ICAgICAgICAgICAgICBkYXJrZW4oYWRqdXN0LWh1ZSgkc3RhdGUtaW5mby1iZywgLTEwKSwgNyUpICFkZWZhdWx0O1xuXG4kc3RhdGUtd2FybmluZy10ZXh0OiAgICAgICAgICAgICAjOGE2ZDNiICFkZWZhdWx0O1xuJHN0YXRlLXdhcm5pbmctYmc6ICAgICAgICAgICAgICAgI2ZjZjhlMyAhZGVmYXVsdDtcbiRzdGF0ZS13YXJuaW5nLWJvcmRlcjogICAgICAgICAgIGRhcmtlbihhZGp1c3QtaHVlKCRzdGF0ZS13YXJuaW5nLWJnLCAtMTApLCA1JSkgIWRlZmF1bHQ7XG5cbiRzdGF0ZS1kYW5nZXItdGV4dDogICAgICAgICAgICAgICNhOTQ0NDIgIWRlZmF1bHQ7XG4kc3RhdGUtZGFuZ2VyLWJnOiAgICAgICAgICAgICAgICAjZjJkZWRlICFkZWZhdWx0O1xuJHN0YXRlLWRhbmdlci1ib3JkZXI6ICAgICAgICAgICAgZGFya2VuKGFkanVzdC1odWUoJHN0YXRlLWRhbmdlci1iZywgLTEwKSwgNSUpICFkZWZhdWx0O1xuXG5cbi8vPT0gVG9vbHRpcHNcbi8vXG4vLyMjXG5cbi8vKiogVG9vbHRpcCBtYXggd2lkdGhcbiR0b29sdGlwLW1heC13aWR0aDogICAgICAgICAgIDIwMHB4ICFkZWZhdWx0O1xuLy8qKiBUb29sdGlwIHRleHQgY29sb3JcbiR0b29sdGlwLWNvbG9yOiAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIFRvb2x0aXAgYmFja2dyb3VuZCBjb2xvclxuJHRvb2x0aXAtYmc6ICAgICAgICAgICAgICAgICAgIzAwMCAhZGVmYXVsdDtcbiR0b29sdGlwLW9wYWNpdHk6ICAgICAgICAgICAgIC45ICFkZWZhdWx0O1xuXG4vLyoqIFRvb2x0aXAgYXJyb3cgd2lkdGhcbiR0b29sdGlwLWFycm93LXdpZHRoOiAgICAgICAgIDVweCAhZGVmYXVsdDtcbi8vKiogVG9vbHRpcCBhcnJvdyBjb2xvclxuJHRvb2x0aXAtYXJyb3ctY29sb3I6ICAgICAgICAgJHRvb2x0aXAtYmcgIWRlZmF1bHQ7XG5cblxuLy89PSBQb3BvdmVyc1xuLy9cbi8vIyNcblxuLy8qKiBQb3BvdmVyIGJvZHkgYmFja2dyb3VuZCBjb2xvclxuJHBvcG92ZXItYmc6ICAgICAgICAgICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBQb3BvdmVyIG1heGltdW0gd2lkdGhcbiRwb3BvdmVyLW1heC13aWR0aDogICAgICAgICAgICAgICAgICAgMjc2cHggIWRlZmF1bHQ7XG4vLyoqIFBvcG92ZXIgYm9yZGVyIGNvbG9yXG4kcG9wb3Zlci1ib3JkZXItY29sb3I6ICAgICAgICAgICAgICAgIHJnYmEoMCwwLDAsLjIpICFkZWZhdWx0O1xuLy8qKiBQb3BvdmVyIGZhbGxiYWNrIGJvcmRlciBjb2xvclxuJHBvcG92ZXItZmFsbGJhY2stYm9yZGVyLWNvbG9yOiAgICAgICAjY2NjICFkZWZhdWx0O1xuXG4vLyoqIFBvcG92ZXIgdGl0bGUgYmFja2dyb3VuZCBjb2xvclxuJHBvcG92ZXItdGl0bGUtYmc6ICAgICAgICAgICAgICAgICAgICBkYXJrZW4oJHBvcG92ZXItYmcsIDMlKSAhZGVmYXVsdDtcblxuLy8qKiBQb3BvdmVyIGFycm93IHdpZHRoXG4kcG9wb3Zlci1hcnJvdy13aWR0aDogICAgICAgICAgICAgICAgIDEwcHggIWRlZmF1bHQ7XG4vLyoqIFBvcG92ZXIgYXJyb3cgY29sb3JcbiRwb3BvdmVyLWFycm93LWNvbG9yOiAgICAgICAgICAgICAgICAgJHBvcG92ZXItYmcgIWRlZmF1bHQ7XG5cbi8vKiogUG9wb3ZlciBvdXRlciBhcnJvdyB3aWR0aFxuJHBvcG92ZXItYXJyb3ctb3V0ZXItd2lkdGg6ICAgICAgICAgICAoJHBvcG92ZXItYXJyb3ctd2lkdGggKyAxKSAhZGVmYXVsdDtcbi8vKiogUG9wb3ZlciBvdXRlciBhcnJvdyBjb2xvclxuJHBvcG92ZXItYXJyb3ctb3V0ZXItY29sb3I6ICAgICAgICAgICBmYWRlX2luKCRwb3BvdmVyLWJvcmRlci1jb2xvciwgMC4wNSkgIWRlZmF1bHQ7XG4vLyoqIFBvcG92ZXIgb3V0ZXIgYXJyb3cgZmFsbGJhY2sgY29sb3JcbiRwb3BvdmVyLWFycm93LW91dGVyLWZhbGxiYWNrLWNvbG9yOiAgZGFya2VuKCRwb3BvdmVyLWZhbGxiYWNrLWJvcmRlci1jb2xvciwgMjAlKSAhZGVmYXVsdDtcblxuXG4vLz09IExhYmVsc1xuLy9cbi8vIyNcblxuLy8qKiBEZWZhdWx0IGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC1kZWZhdWx0LWJnOiAgICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBQcmltYXJ5IGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC1wcmltYXJ5LWJnOiAgICAgICAgICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuLy8qKiBTdWNjZXNzIGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC1zdWNjZXNzLWJnOiAgICAgICAgICAgICRicmFuZC1zdWNjZXNzICFkZWZhdWx0O1xuLy8qKiBJbmZvIGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC1pbmZvLWJnOiAgICAgICAgICAgICAgICRicmFuZC1pbmZvICFkZWZhdWx0O1xuLy8qKiBXYXJuaW5nIGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC13YXJuaW5nLWJnOiAgICAgICAgICAgICRicmFuZC13YXJuaW5nICFkZWZhdWx0O1xuLy8qKiBEYW5nZXIgbGFiZWwgYmFja2dyb3VuZCBjb2xvclxuJGxhYmVsLWRhbmdlci1iZzogICAgICAgICAgICAgJGJyYW5kLWRhbmdlciAhZGVmYXVsdDtcblxuLy8qKiBEZWZhdWx0IGxhYmVsIHRleHQgY29sb3JcbiRsYWJlbC1jb2xvcjogICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIERlZmF1bHQgdGV4dCBjb2xvciBvZiBhIGxpbmtlZCBsYWJlbFxuJGxhYmVsLWxpbmstaG92ZXItY29sb3I6ICAgICAgI2ZmZiAhZGVmYXVsdDtcblxuXG4vLz09IE1vZGFsc1xuLy9cbi8vIyNcblxuLy8qKiBQYWRkaW5nIGFwcGxpZWQgdG8gdGhlIG1vZGFsIGJvZHlcbiRtb2RhbC1pbm5lci1wYWRkaW5nOiAgICAgICAgIDE1cHggIWRlZmF1bHQ7XG5cbi8vKiogUGFkZGluZyBhcHBsaWVkIHRvIHRoZSBtb2RhbCB0aXRsZVxuJG1vZGFsLXRpdGxlLXBhZGRpbmc6ICAgICAgICAgMTVweCAhZGVmYXVsdDtcbi8vKiogTW9kYWwgdGl0bGUgbGluZS1oZWlnaHRcbiRtb2RhbC10aXRsZS1saW5lLWhlaWdodDogICAgICRsaW5lLWhlaWdodC1iYXNlICFkZWZhdWx0O1xuXG4vLyoqIEJhY2tncm91bmQgY29sb3Igb2YgbW9kYWwgY29udGVudCBhcmVhXG4kbW9kYWwtY29udGVudC1iZzogICAgICAgICAgICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIE1vZGFsIGNvbnRlbnQgYm9yZGVyIGNvbG9yXG4kbW9kYWwtY29udGVudC1ib3JkZXItY29sb3I6ICAgICAgICAgICAgICAgICAgIHJnYmEoMCwwLDAsLjIpICFkZWZhdWx0O1xuLy8qKiBNb2RhbCBjb250ZW50IGJvcmRlciBjb2xvciAqKmZvciBJRTgqKlxuJG1vZGFsLWNvbnRlbnQtZmFsbGJhY2stYm9yZGVyLWNvbG9yOiAgICAgICAgICAjOTk5ICFkZWZhdWx0O1xuXG4vLyoqIE1vZGFsIGJhY2tkcm9wIGJhY2tncm91bmQgY29sb3JcbiRtb2RhbC1iYWNrZHJvcC1iZzogICAgICAgICAgICMwMDAgIWRlZmF1bHQ7XG4vLyoqIE1vZGFsIGJhY2tkcm9wIG9wYWNpdHlcbiRtb2RhbC1iYWNrZHJvcC1vcGFjaXR5OiAgICAgIC41ICFkZWZhdWx0O1xuLy8qKiBNb2RhbCBoZWFkZXIgYm9yZGVyIGNvbG9yXG4kbW9kYWwtaGVhZGVyLWJvcmRlci1jb2xvcjogICAjZTVlNWU1ICFkZWZhdWx0O1xuLy8qKiBNb2RhbCBmb290ZXIgYm9yZGVyIGNvbG9yXG4kbW9kYWwtZm9vdGVyLWJvcmRlci1jb2xvcjogICAkbW9kYWwtaGVhZGVyLWJvcmRlci1jb2xvciAhZGVmYXVsdDtcblxuJG1vZGFsLWxnOiAgICAgICAgICAgICAgICAgICAgOTAwcHggIWRlZmF1bHQ7XG4kbW9kYWwtbWQ6ICAgICAgICAgICAgICAgICAgICA2MDBweCAhZGVmYXVsdDtcbiRtb2RhbC1zbTogICAgICAgICAgICAgICAgICAgIDMwMHB4ICFkZWZhdWx0O1xuXG5cbi8vPT0gQWxlcnRzXG4vL1xuLy8jIyBEZWZpbmUgYWxlcnQgY29sb3JzLCBib3JkZXIgcmFkaXVzLCBhbmQgcGFkZGluZy5cblxuJGFsZXJ0LXBhZGRpbmc6ICAgICAgICAgICAgICAgMTVweCAhZGVmYXVsdDtcbiRhbGVydC1ib3JkZXItcmFkaXVzOiAgICAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG4kYWxlcnQtbGluay1mb250LXdlaWdodDogICAgICBib2xkICFkZWZhdWx0O1xuXG4kYWxlcnQtc3VjY2Vzcy1iZzogICAgICAgICAgICAkc3RhdGUtc3VjY2Vzcy1iZyAhZGVmYXVsdDtcbiRhbGVydC1zdWNjZXNzLXRleHQ6ICAgICAgICAgICRzdGF0ZS1zdWNjZXNzLXRleHQgIWRlZmF1bHQ7XG4kYWxlcnQtc3VjY2Vzcy1ib3JkZXI6ICAgICAgICAkc3RhdGUtc3VjY2Vzcy1ib3JkZXIgIWRlZmF1bHQ7XG5cbiRhbGVydC1pbmZvLWJnOiAgICAgICAgICAgICAgICRzdGF0ZS1pbmZvLWJnICFkZWZhdWx0O1xuJGFsZXJ0LWluZm8tdGV4dDogICAgICAgICAgICAgJHN0YXRlLWluZm8tdGV4dCAhZGVmYXVsdDtcbiRhbGVydC1pbmZvLWJvcmRlcjogICAgICAgICAgICRzdGF0ZS1pbmZvLWJvcmRlciAhZGVmYXVsdDtcblxuJGFsZXJ0LXdhcm5pbmctYmc6ICAgICAgICAgICAgJHN0YXRlLXdhcm5pbmctYmcgIWRlZmF1bHQ7XG4kYWxlcnQtd2FybmluZy10ZXh0OiAgICAgICAgICAkc3RhdGUtd2FybmluZy10ZXh0ICFkZWZhdWx0O1xuJGFsZXJ0LXdhcm5pbmctYm9yZGVyOiAgICAgICAgJHN0YXRlLXdhcm5pbmctYm9yZGVyICFkZWZhdWx0O1xuXG4kYWxlcnQtZGFuZ2VyLWJnOiAgICAgICAgICAgICAkc3RhdGUtZGFuZ2VyLWJnICFkZWZhdWx0O1xuJGFsZXJ0LWRhbmdlci10ZXh0OiAgICAgICAgICAgJHN0YXRlLWRhbmdlci10ZXh0ICFkZWZhdWx0O1xuJGFsZXJ0LWRhbmdlci1ib3JkZXI6ICAgICAgICAgJHN0YXRlLWRhbmdlci1ib3JkZXIgIWRlZmF1bHQ7XG5cblxuLy89PSBQcm9ncmVzcyBiYXJzXG4vL1xuLy8jI1xuXG4vLyoqIEJhY2tncm91bmQgY29sb3Igb2YgdGhlIHdob2xlIHByb2dyZXNzIGNvbXBvbmVudFxuJHByb2dyZXNzLWJnOiAgICAgICAgICAgICAgICAgI2Y1ZjVmNSAhZGVmYXVsdDtcbi8vKiogUHJvZ3Jlc3MgYmFyIHRleHQgY29sb3JcbiRwcm9ncmVzcy1iYXItY29sb3I6ICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIFZhcmlhYmxlIGZvciBzZXR0aW5nIHJvdW5kZWQgY29ybmVycyBvbiBwcm9ncmVzcyBiYXIuXG4kcHJvZ3Jlc3MtYm9yZGVyLXJhZGl1czogICAgICAkYm9yZGVyLXJhZGl1cy1iYXNlICFkZWZhdWx0O1xuXG4vLyoqIERlZmF1bHQgcHJvZ3Jlc3MgYmFyIGNvbG9yXG4kcHJvZ3Jlc3MtYmFyLWJnOiAgICAgICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcbi8vKiogU3VjY2VzcyBwcm9ncmVzcyBiYXIgY29sb3JcbiRwcm9ncmVzcy1iYXItc3VjY2Vzcy1iZzogICAgICRicmFuZC1zdWNjZXNzICFkZWZhdWx0O1xuLy8qKiBXYXJuaW5nIHByb2dyZXNzIGJhciBjb2xvclxuJHByb2dyZXNzLWJhci13YXJuaW5nLWJnOiAgICAgJGJyYW5kLXdhcm5pbmcgIWRlZmF1bHQ7XG4vLyoqIERhbmdlciBwcm9ncmVzcyBiYXIgY29sb3JcbiRwcm9ncmVzcy1iYXItZGFuZ2VyLWJnOiAgICAgICRicmFuZC1kYW5nZXIgIWRlZmF1bHQ7XG4vLyoqIEluZm8gcHJvZ3Jlc3MgYmFyIGNvbG9yXG4kcHJvZ3Jlc3MtYmFyLWluZm8tYmc6ICAgICAgICAkYnJhbmQtaW5mbyAhZGVmYXVsdDtcblxuXG4vLz09IExpc3QgZ3JvdXBcbi8vXG4vLyMjXG5cbi8vKiogQmFja2dyb3VuZCBjb2xvciBvbiBgLmxpc3QtZ3JvdXAtaXRlbWBcbiRsaXN0LWdyb3VwLWJnOiAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogYC5saXN0LWdyb3VwLWl0ZW1gIGJvcmRlciBjb2xvclxuJGxpc3QtZ3JvdXAtYm9yZGVyOiAgICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuLy8qKiBMaXN0IGdyb3VwIGJvcmRlciByYWRpdXNcbiRsaXN0LWdyb3VwLWJvcmRlci1yYWRpdXM6ICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcblxuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIG9mIHNpbmdsZSBsaXN0IGl0ZW1zIG9uIGhvdmVyXG4kbGlzdC1ncm91cC1ob3Zlci1iZzogICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG4vLyoqIFRleHQgY29sb3Igb2YgYWN0aXZlIGxpc3QgaXRlbXNcbiRsaXN0LWdyb3VwLWFjdGl2ZS1jb2xvcjogICAgICAgJGNvbXBvbmVudC1hY3RpdmUtY29sb3IgIWRlZmF1bHQ7XG4vLyoqIEJhY2tncm91bmQgY29sb3Igb2YgYWN0aXZlIGxpc3QgaXRlbXNcbiRsaXN0LWdyb3VwLWFjdGl2ZS1iZzogICAgICAgICAgJGNvbXBvbmVudC1hY3RpdmUtYmcgIWRlZmF1bHQ7XG4vLyoqIEJvcmRlciBjb2xvciBvZiBhY3RpdmUgbGlzdCBlbGVtZW50c1xuJGxpc3QtZ3JvdXAtYWN0aXZlLWJvcmRlcjogICAgICAkbGlzdC1ncm91cC1hY3RpdmUtYmcgIWRlZmF1bHQ7XG4vLyoqIFRleHQgY29sb3IgZm9yIGNvbnRlbnQgd2l0aGluIGFjdGl2ZSBsaXN0IGl0ZW1zXG4kbGlzdC1ncm91cC1hY3RpdmUtdGV4dC1jb2xvcjogIGxpZ2h0ZW4oJGxpc3QtZ3JvdXAtYWN0aXZlLWJnLCA0MCUpICFkZWZhdWx0O1xuXG4vLyoqIFRleHQgY29sb3Igb2YgZGlzYWJsZWQgbGlzdCBpdGVtc1xuJGxpc3QtZ3JvdXAtZGlzYWJsZWQtY29sb3I6ICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG4vLyoqIEJhY2tncm91bmQgY29sb3Igb2YgZGlzYWJsZWQgbGlzdCBpdGVtc1xuJGxpc3QtZ3JvdXAtZGlzYWJsZWQtYmc6ICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbi8vKiogVGV4dCBjb2xvciBmb3IgY29udGVudCB3aXRoaW4gZGlzYWJsZWQgbGlzdCBpdGVtc1xuJGxpc3QtZ3JvdXAtZGlzYWJsZWQtdGV4dC1jb2xvcjogJGxpc3QtZ3JvdXAtZGlzYWJsZWQtY29sb3IgIWRlZmF1bHQ7XG5cbiRsaXN0LWdyb3VwLWxpbmstY29sb3I6ICAgICAgICAgIzU1NSAhZGVmYXVsdDtcbiRsaXN0LWdyb3VwLWxpbmstaG92ZXItY29sb3I6ICAgJGxpc3QtZ3JvdXAtbGluay1jb2xvciAhZGVmYXVsdDtcbiRsaXN0LWdyb3VwLWxpbmstaGVhZGluZy1jb2xvcjogIzMzMyAhZGVmYXVsdDtcblxuXG4vLz09IFBhbmVsc1xuLy9cbi8vIyNcblxuJHBhbmVsLWJnOiAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRwYW5lbC1ib2R5LXBhZGRpbmc6ICAgICAgICAgIDE1cHggIWRlZmF1bHQ7XG4kcGFuZWwtaGVhZGluZy1wYWRkaW5nOiAgICAgICAxMHB4IDE1cHggIWRlZmF1bHQ7XG4kcGFuZWwtZm9vdGVyLXBhZGRpbmc6ICAgICAgICAkcGFuZWwtaGVhZGluZy1wYWRkaW5nICFkZWZhdWx0O1xuJHBhbmVsLWJvcmRlci1yYWRpdXM6ICAgICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcblxuLy8qKiBCb3JkZXIgY29sb3IgZm9yIGVsZW1lbnRzIHdpdGhpbiBwYW5lbHNcbiRwYW5lbC1pbm5lci1ib3JkZXI6ICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG4kcGFuZWwtZm9vdGVyLWJnOiAgICAgICAgICAgICAjZjVmNWY1ICFkZWZhdWx0O1xuXG4kcGFuZWwtZGVmYXVsdC10ZXh0OiAgICAgICAgICAkZ3JheS1kYXJrICFkZWZhdWx0O1xuJHBhbmVsLWRlZmF1bHQtYm9yZGVyOiAgICAgICAgI2RkZCAhZGVmYXVsdDtcbiRwYW5lbC1kZWZhdWx0LWhlYWRpbmctYmc6ICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG5cbiRwYW5lbC1wcmltYXJ5LXRleHQ6ICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kcGFuZWwtcHJpbWFyeS1ib3JkZXI6ICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcbiRwYW5lbC1wcmltYXJ5LWhlYWRpbmctYmc6ICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuXG4kcGFuZWwtc3VjY2Vzcy10ZXh0OiAgICAgICAgICAkc3RhdGUtc3VjY2Vzcy10ZXh0ICFkZWZhdWx0O1xuJHBhbmVsLXN1Y2Nlc3MtYm9yZGVyOiAgICAgICAgJHN0YXRlLXN1Y2Nlc3MtYm9yZGVyICFkZWZhdWx0O1xuJHBhbmVsLXN1Y2Nlc3MtaGVhZGluZy1iZzogICAgJHN0YXRlLXN1Y2Nlc3MtYmcgIWRlZmF1bHQ7XG5cbiRwYW5lbC1pbmZvLXRleHQ6ICAgICAgICAgICAgICRzdGF0ZS1pbmZvLXRleHQgIWRlZmF1bHQ7XG4kcGFuZWwtaW5mby1ib3JkZXI6ICAgICAgICAgICAkc3RhdGUtaW5mby1ib3JkZXIgIWRlZmF1bHQ7XG4kcGFuZWwtaW5mby1oZWFkaW5nLWJnOiAgICAgICAkc3RhdGUtaW5mby1iZyAhZGVmYXVsdDtcblxuJHBhbmVsLXdhcm5pbmctdGV4dDogICAgICAgICAgJHN0YXRlLXdhcm5pbmctdGV4dCAhZGVmYXVsdDtcbiRwYW5lbC13YXJuaW5nLWJvcmRlcjogICAgICAgICRzdGF0ZS13YXJuaW5nLWJvcmRlciAhZGVmYXVsdDtcbiRwYW5lbC13YXJuaW5nLWhlYWRpbmctYmc6ICAgICRzdGF0ZS13YXJuaW5nLWJnICFkZWZhdWx0O1xuXG4kcGFuZWwtZGFuZ2VyLXRleHQ6ICAgICAgICAgICAkc3RhdGUtZGFuZ2VyLXRleHQgIWRlZmF1bHQ7XG4kcGFuZWwtZGFuZ2VyLWJvcmRlcjogICAgICAgICAkc3RhdGUtZGFuZ2VyLWJvcmRlciAhZGVmYXVsdDtcbiRwYW5lbC1kYW5nZXItaGVhZGluZy1iZzogICAgICRzdGF0ZS1kYW5nZXItYmcgIWRlZmF1bHQ7XG5cblxuLy89PSBUaHVtYm5haWxzXG4vL1xuLy8jI1xuXG4vLyoqIFBhZGRpbmcgYXJvdW5kIHRoZSB0aHVtYm5haWwgaW1hZ2VcbiR0aHVtYm5haWwtcGFkZGluZzogICAgICAgICAgIDRweCAhZGVmYXVsdDtcbi8vKiogVGh1bWJuYWlsIGJhY2tncm91bmQgY29sb3JcbiR0aHVtYm5haWwtYmc6ICAgICAgICAgICAgICAgICRib2R5LWJnICFkZWZhdWx0O1xuLy8qKiBUaHVtYm5haWwgYm9yZGVyIGNvbG9yXG4kdGh1bWJuYWlsLWJvcmRlcjogICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuLy8qKiBUaHVtYm5haWwgYm9yZGVyIHJhZGl1c1xuJHRodW1ibmFpbC1ib3JkZXItcmFkaXVzOiAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcblxuLy8qKiBDdXN0b20gdGV4dCBjb2xvciBmb3IgdGh1bWJuYWlsIGNhcHRpb25zXG4kdGh1bWJuYWlsLWNhcHRpb24tY29sb3I6ICAgICAkdGV4dC1jb2xvciAhZGVmYXVsdDtcbi8vKiogUGFkZGluZyBhcm91bmQgdGhlIHRodW1ibmFpbCBjYXB0aW9uXG4kdGh1bWJuYWlsLWNhcHRpb24tcGFkZGluZzogICA5cHggIWRlZmF1bHQ7XG5cblxuLy89PSBXZWxsc1xuLy9cbi8vIyNcblxuJHdlbGwtYmc6ICAgICAgICAgICAgICAgICAgICAgI2Y1ZjVmNSAhZGVmYXVsdDtcbiR3ZWxsLWJvcmRlcjogICAgICAgICAgICAgICAgIGRhcmtlbigkd2VsbC1iZywgNyUpICFkZWZhdWx0O1xuXG5cbi8vPT0gQmFkZ2VzXG4vL1xuLy8jI1xuXG4kYmFkZ2UtY29sb3I6ICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBMaW5rZWQgYmFkZ2UgdGV4dCBjb2xvciBvbiBob3ZlclxuJGJhZGdlLWxpbmstaG92ZXItY29sb3I6ICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRiYWRnZS1iZzogICAgICAgICAgICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuXG4vLyoqIEJhZGdlIHRleHQgY29sb3IgaW4gYWN0aXZlIG5hdiBsaW5rXG4kYmFkZ2UtYWN0aXZlLWNvbG9yOiAgICAgICAgICAkbGluay1jb2xvciAhZGVmYXVsdDtcbi8vKiogQmFkZ2UgYmFja2dyb3VuZCBjb2xvciBpbiBhY3RpdmUgbmF2IGxpbmtcbiRiYWRnZS1hY3RpdmUtYmc6ICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG5cbiRiYWRnZS1mb250LXdlaWdodDogICAgICAgICAgIGJvbGQgIWRlZmF1bHQ7XG4kYmFkZ2UtbGluZS1oZWlnaHQ6ICAgICAgICAgICAxICFkZWZhdWx0O1xuJGJhZGdlLWJvcmRlci1yYWRpdXM6ICAgICAgICAgMTBweCAhZGVmYXVsdDtcblxuXG4vLz09IEJyZWFkY3J1bWJzXG4vL1xuLy8jI1xuXG4kYnJlYWRjcnVtYi1wYWRkaW5nLXZlcnRpY2FsOiAgIDhweCAhZGVmYXVsdDtcbiRicmVhZGNydW1iLXBhZGRpbmctaG9yaXpvbnRhbDogMTVweCAhZGVmYXVsdDtcbi8vKiogQnJlYWRjcnVtYiBiYWNrZ3JvdW5kIGNvbG9yXG4kYnJlYWRjcnVtYi1iZzogICAgICAgICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG4vLyoqIEJyZWFkY3J1bWIgdGV4dCBjb2xvclxuJGJyZWFkY3J1bWItY29sb3I6ICAgICAgICAgICAgICAjY2NjICFkZWZhdWx0O1xuLy8qKiBUZXh0IGNvbG9yIG9mIGN1cnJlbnQgcGFnZSBpbiB0aGUgYnJlYWRjcnVtYlxuJGJyZWFkY3J1bWItYWN0aXZlLWNvbG9yOiAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbi8vKiogVGV4dHVhbCBzZXBhcmF0b3IgZm9yIGJldHdlZW4gYnJlYWRjcnVtYiBlbGVtZW50c1xuJGJyZWFkY3J1bWItc2VwYXJhdG9yOiAgICAgICAgICBcIi9cIiAhZGVmYXVsdDtcblxuXG4vLz09IENhcm91c2VsXG4vL1xuLy8jI1xuXG4kY2Fyb3VzZWwtdGV4dC1zaGFkb3c6ICAgICAgICAgICAgICAgICAgICAgICAgMCAxcHggMnB4IHJnYmEoMCwwLDAsLjYpICFkZWZhdWx0O1xuXG4kY2Fyb3VzZWwtY29udHJvbC1jb2xvcjogICAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRjYXJvdXNlbC1jb250cm9sLXdpZHRoOiAgICAgICAgICAgICAgICAgICAgICAxNSUgIWRlZmF1bHQ7XG4kY2Fyb3VzZWwtY29udHJvbC1vcGFjaXR5OiAgICAgICAgICAgICAgICAgICAgLjUgIWRlZmF1bHQ7XG4kY2Fyb3VzZWwtY29udHJvbC1mb250LXNpemU6ICAgICAgICAgICAgICAgICAgMjBweCAhZGVmYXVsdDtcblxuJGNhcm91c2VsLWluZGljYXRvci1hY3RpdmUtYmc6ICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kY2Fyb3VzZWwtaW5kaWNhdG9yLWJvcmRlci1jb2xvcjogICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcblxuJGNhcm91c2VsLWNhcHRpb24tY29sb3I6ICAgICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG5cblxuLy89PSBDbG9zZVxuLy9cbi8vIyNcblxuJGNsb3NlLWZvbnQtd2VpZ2h0OiAgICAgICAgICAgYm9sZCAhZGVmYXVsdDtcbiRjbG9zZS1jb2xvcjogICAgICAgICAgICAgICAgICMwMDAgIWRlZmF1bHQ7XG4kY2xvc2UtdGV4dC1zaGFkb3c6ICAgICAgICAgICAwIDFweCAwICNmZmYgIWRlZmF1bHQ7XG5cblxuLy89PSBDb2RlXG4vL1xuLy8jI1xuXG4kY29kZS1jb2xvcjogICAgICAgICAgICAgICAgICAjYzcyNTRlICFkZWZhdWx0O1xuJGNvZGUtYmc6ICAgICAgICAgICAgICAgICAgICAgI2Y5ZjJmNCAhZGVmYXVsdDtcblxuJGtiZC1jb2xvcjogICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRrYmQtYmc6ICAgICAgICAgICAgICAgICAgICAgICMzMzMgIWRlZmF1bHQ7XG5cbiRwcmUtYmc6ICAgICAgICAgICAgICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG4kcHJlLWNvbG9yOiAgICAgICAgICAgICAgICAgICAkZ3JheS1kYXJrICFkZWZhdWx0O1xuJHByZS1ib3JkZXItY29sb3I6ICAgICAgICAgICAgI2NjYyAhZGVmYXVsdDtcbiRwcmUtc2Nyb2xsYWJsZS1tYXgtaGVpZ2h0OiAgIDM0MHB4ICFkZWZhdWx0O1xuXG5cbi8vPT0gVHlwZVxuLy9cbi8vIyNcblxuLy8qKiBIb3Jpem9udGFsIG9mZnNldCBmb3IgZm9ybXMgYW5kIGxpc3RzLlxuJGNvbXBvbmVudC1vZmZzZXQtaG9yaXpvbnRhbDogMTgwcHggIWRlZmF1bHQ7XG4vLyoqIFRleHQgbXV0ZWQgY29sb3JcbiR0ZXh0LW11dGVkOiAgICAgICAgICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBBYmJyZXZpYXRpb25zIGFuZCBhY3JvbnltcyBib3JkZXIgY29sb3JcbiRhYmJyLWJvcmRlci1jb2xvcjogICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBIZWFkaW5ncyBzbWFsbCBjb2xvclxuJGhlYWRpbmdzLXNtYWxsLWNvbG9yOiAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG4vLyoqIEJsb2NrcXVvdGUgc21hbGwgY29sb3JcbiRibG9ja3F1b3RlLXNtYWxsLWNvbG9yOiAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBCbG9ja3F1b3RlIGZvbnQgc2l6ZVxuJGJsb2NrcXVvdGUtZm9udC1zaXplOiAgICAgICAgKCRmb250LXNpemUtYmFzZSAqIDEuMjUpICFkZWZhdWx0O1xuLy8qKiBCbG9ja3F1b3RlIGJvcmRlciBjb2xvclxuJGJsb2NrcXVvdGUtYm9yZGVyLWNvbG9yOiAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbi8vKiogUGFnZSBoZWFkZXIgYm9yZGVyIGNvbG9yXG4kcGFnZS1oZWFkZXItYm9yZGVyLWNvbG9yOiAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuLy8qKiBXaWR0aCBvZiBob3Jpem9udGFsIGRlc2NyaXB0aW9uIGxpc3QgdGl0bGVzXG4kZGwtaG9yaXpvbnRhbC1vZmZzZXQ6ICAgICAgICAkY29tcG9uZW50LW9mZnNldC1ob3Jpem9udGFsICFkZWZhdWx0O1xuLy8qKiBQb2ludCBhdCB3aGljaCAuZGwtaG9yaXpvbnRhbCBiZWNvbWVzIGhvcml6b250YWxcbiRkbC1ob3Jpem9udGFsLWJyZWFrcG9pbnQ6ICAgICRncmlkLWZsb2F0LWJyZWFrcG9pbnQgIWRlZmF1bHQ7XG4vLyoqIEhvcml6b250YWwgbGluZSBjb2xvci5cbiRoci1ib3JkZXI6ICAgICAgICAgICAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG4iLCJAaW1wb3J0ICcuLi8uLi8uLi9zdHlsZXMvYW5pbWF0aW9ucy5zY3NzJztcblxueG9zLXRhYmxlIHtcblxuICBkaXNwbGF5OiBibG9jaztcblxuICB0ci5uZy1tb3ZlLFxuICB0ci5uZy1lbnRlcixcbiAgdHIubmctbGVhdmUge1xuICAgIHRyYW5zaXRpb246YWxsIGxpbmVhciAwLjVzO1xuICB9XG5cbiAgdHIubmctbGVhdmUubmctbGVhdmUtYWN0aXZlLFxuICB0ci5uZy1tb3ZlLFxuICB0ci5uZy1lbnRlciB7XG4gICAgb3BhY2l0eTowO1xuICAgIGFuaW1hdGlvbjogMC41cyBzbGlkZU91dFJpZ2h0IGVhc2UtaW4tb3V0O1xuICB9XG5cbiAgdHIubmctbGVhdmUsXG4gIHRyLm5nLW1vdmUubmctbW92ZS1hY3RpdmUsXG4gIHRyLm5nLWVudGVyLm5nLWVudGVyLWFjdGl2ZSB7XG4gICAgb3BhY2l0eToxO1xuICAgIGFuaW1hdGlvbjogMC41cyBzbGlkZUluUmlnaHQgZWFzZS1pbi1vdXQ7XG4gIH1cblxuICB0ZCBkbCB7XG4gICAgbWFyZ2luLWJvdHRvbTogMDtcblxuICAgIGR0IHtcbiAgICAgIHdpZHRoOiA1MHB4ICFpbXBvcnRhbnQ7XG4gICAgfVxuXG4gICAgZGQge1xuICAgICAgbWFyZ2luLWxlZnQ6IDYwcHggIWltcG9ydGFudDtcbiAgICB9XG4gIH1cbn0iLCJAaW1wb3J0ICcuLi8uLi8uLi9zdHlsZXMvYW5pbWF0aW9ucy5zY3NzJztcblxueG9zLWFsZXJ0IHtcblxuICAvKiB3aGVuIGhpZGluZyAqL1xuICAubmctaGlkZS1hZGQgICAgICAgICB7IGFuaW1hdGlvbjowLjVzIGZhZGVPdXREb3duIGVhc2UtaW4tb3V0OyB9XG5cbiAgLyogd2hlbiBzaG93aW5nICovXG4gIC5uZy1oaWRlLXJlbW92ZSAgICAgIHsgYW5pbWF0aW9uOjAuNXMgZmFkZUluVXAgZWFzZS1pbi1vdXQ7IH1cbn0iLCJAaW1wb3J0ICcuLi8uLi8uLi9zdHlsZXMvYW5pbWF0aW9ucy5zY3NzJztcbkBpbXBvcnQgJy4uLy4uLy4uLy4uLy4uLy4uL3N0eWxlL3Nhc3MvYm9vdHN0cmFwL2Jvb3RzdHJhcC9fdmFyaWFibGVzLnNjc3MnO1xuXG5pbnB1dCArIHhvcy12YWxpZGF0aW9uIHtcbiAgbWFyZ2luLXRvcDogJGZvcm0tZ3JvdXAtbWFyZ2luLWJvdHRvbTtcbiAgZGlzcGxheTogYmxvY2s7XG59IiwieG9zLXNtYXJ0LXRhYmxle1xuICBcbn0iXSwibWFwcGluZ3MiOiJBQ0FBLFVBQVUsQ0FBQyxBQUFBLFlBQVk7RUFDckIsQUFBQSxJQUFJO0lBQ0YsU0FBUyxFQUFFLHVCQUFXO0lBQ3RCLFVBQVUsRUFBRSxPQUFRO0VBR3RCLEFBQUEsRUFBRTtJQUNBLFNBQVMsRUFBRSxvQkFBVzs7QUFJMUIsVUFBVSxDQUFDLEFBQUEsYUFBYTtFQUN0QixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsb0JBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsVUFBVSxFQUFFLE1BQU87SUFDbkIsU0FBUyxFQUFFLHVCQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxRQUFRO0VBQ2pCLEFBQUEsSUFBSTtJQUNGLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXO0VBR3hCLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLElBQUs7O0FBSXBCLFVBQVUsQ0FBQyxBQUFBLFdBQVc7RUFDcEIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7RUFHYixBQUFBLEVBQUU7SUFDQSxPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSx1QkFBVzs7QUF6QzFCLFVBQVUsQ0FBQyxBQUFBLFlBQVk7RUFDckIsQUFBQSxJQUFJO0lBQ0YsU0FBUyxFQUFFLHVCQUFXO0lBQ3RCLFVBQVUsRUFBRSxPQUFRO0VBR3RCLEFBQUEsRUFBRTtJQUNBLFNBQVMsRUFBRSxvQkFBVzs7QUFJMUIsVUFBVSxDQUFDLEFBQUEsYUFBYTtFQUN0QixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsb0JBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsVUFBVSxFQUFFLE1BQU87SUFDbkIsU0FBUyxFQUFFLHVCQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxRQUFRO0VBQ2pCLEFBQUEsSUFBSTtJQUNGLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXO0VBR3hCLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLElBQUs7O0FBSXBCLFVBQVUsQ0FBQyxBQUFBLFdBQVc7RUFDcEIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7RUFHYixBQUFBLEVBQUU7SUFDQSxPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSx1QkFBVzs7QUV2QzFCLEFBQUEsU0FBUyxDQUFDO0VBRVIsT0FBTyxFQUFFLEtBQU0sR0FpQ2hCO0VBbkNELEFBSUksU0FKSyxDQUlQLEVBQUUsQUFBQSxRQUFRO0VBSlosQUFLSSxTQUxLLENBS1AsRUFBRSxBQUFBLFNBQVM7RUFMYixBQU1JLFNBTkssQ0FNUCxFQUFFLEFBQUEsU0FBUyxDQUFDO0lBQ1YsVUFBVSxFQUFDLGVBQWdCLEdBQzVCO0VBUkgsQUFVYSxTQVZKLENBVVAsRUFBRSxBQUFBLFNBQVMsQUFBQSxnQkFBZ0I7RUFWN0IsQUFXSSxTQVhLLENBV1AsRUFBRSxBQUFBLFFBQVE7RUFYWixBQVlJLFNBWkssQ0FZUCxFQUFFLEFBQUEsU0FBUyxDQUFDO0lBQ1YsT0FBTyxFQUFDLENBQUU7SUFDVixTQUFTLEVBQUUsOEJBQStCLEdBQzNDO0VBZkgsQUFpQkksU0FqQkssQ0FpQlAsRUFBRSxBQUFBLFNBQVM7RUFqQmIsQUFrQlksU0FsQkgsQ0FrQlAsRUFBRSxBQUFBLFFBQVEsQUFBQSxlQUFlO0VBbEIzQixBQW1CYSxTQW5CSixDQW1CUCxFQUFFLEFBQUEsU0FBUyxBQUFBLGdCQUFnQixDQUFDO0lBQzFCLE9BQU8sRUFBQyxDQUFFO0lBQ1YsU0FBUyxFQUFFLDZCQUE4QixHQUMxQztFQXRCSCxBQXdCSyxTQXhCSSxDQXdCUCxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ0osYUFBYSxFQUFFLENBQUUsR0FTbEI7SUFsQ0gsQUEyQkksU0EzQkssQ0F3QlAsRUFBRSxDQUFDLEVBQUUsQ0FHSCxFQUFFLENBQUM7TUFDRCxLQUFLLEVBQUUsZUFBZ0IsR0FDeEI7SUE3QkwsQUErQkksU0EvQkssQ0F3QlAsRUFBRSxDQUFDLEVBQUUsQ0FPSCxFQUFFLENBQUM7TUFDRCxXQUFXLEVBQUUsZUFBZ0IsR0FDOUI7O0FGbkNMLFVBQVUsQ0FBQyxBQUFBLFlBQVk7RUFDckIsQUFBQSxJQUFJO0lBQ0YsU0FBUyxFQUFFLHVCQUFXO0lBQ3RCLFVBQVUsRUFBRSxPQUFRO0VBR3RCLEFBQUEsRUFBRTtJQUNBLFNBQVMsRUFBRSxvQkFBVzs7QUFJMUIsVUFBVSxDQUFDLEFBQUEsYUFBYTtFQUN0QixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsb0JBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsVUFBVSxFQUFFLE1BQU87SUFDbkIsU0FBUyxFQUFFLHVCQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxRQUFRO0VBQ2pCLEFBQUEsSUFBSTtJQUNGLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXO0VBR3hCLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLElBQUs7O0FBSXBCLFVBQVUsQ0FBQyxBQUFBLFdBQVc7RUFDcEIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7RUFHYixBQUFBLEVBQUU7SUFDQSxPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSx1QkFBVzs7QUd2QzFCLEFBQUEsU0FBUyxDQUFDO0VBRVIsaUJBQWlCO0VBR2pCLGtCQUFrQixFQUVuQjtFQVBELEFBR0UsU0FITyxDQUdQLFlBQVksQ0FBUztJQUFFLFNBQVMsRUFBQyw0QkFBNkIsR0FBSTtFQUhwRSxBQU1FLFNBTk8sQ0FNUCxlQUFlLENBQU07SUFBRSxTQUFTLEVBQUMseUJBQTBCLEdBQUk7O0FIUmpFLFVBQVUsQ0FBQyxBQUFBLFlBQVk7RUFDckIsQUFBQSxJQUFJO0lBQ0YsU0FBUyxFQUFFLHVCQUFXO0lBQ3RCLFVBQVUsRUFBRSxPQUFRO0VBR3RCLEFBQUEsRUFBRTtJQUNBLFNBQVMsRUFBRSxvQkFBVzs7QUFJMUIsVUFBVSxDQUFDLEFBQUEsYUFBYTtFQUN0QixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsb0JBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsVUFBVSxFQUFFLE1BQU87SUFDbkIsU0FBUyxFQUFFLHVCQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxRQUFRO0VBQ2pCLEFBQUEsSUFBSTtJQUNGLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXO0VBR3hCLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLElBQUs7O0FBSXBCLFVBQVUsQ0FBQyxBQUFBLFdBQVc7RUFDcEIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7RUFHYixBQUFBLEVBQUU7SUFDQSxPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSx1QkFBVzs7QUl0QzFCLEFBQVEsS0FBSCxHQUFHLGNBQWMsQ0FBQztFQUNyQixVQUFVLEVId05xQixJQUFJO0VHdk5uQyxPQUFPLEVBQUUsS0FBTSxHQUNoQjs7Q0xHRCxBQUFBLEFBQVUsU0FBVCxBQUFBLElBQVksQUFBQSxBQUFTLFFBQVIsQUFBQSxJQUFXLEFBQUEsQUFBYyxhQUFiLEFBQUEsSUFBZ0IsQUFBQSxBQUFXLFVBQVYsQUFBQSxHQUFhLEFBQUEsU0FBUyxFQUFFLEFBQUEsV0FBVyxDQUFDO0VBQzdFLE9BQU8sRUFBRSxlQUFnQixHQUMxQjs7QUFFRCxBQUFPLElBQUgsR0FBRyxJQUFJLENBQUM7RUFDViwwQkFBMEI7RUFDMUIsVUFBVSxFRTZNcUIsSUFBSSxHRjVNcEMiLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 */
+/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoieG9zTmdMaWIuY3NzIiwic291cmNlcyI6WyJtYWluLnNjc3MiLCJhbmltYXRpb25zLnNjc3MiLCIuLi8uLi8uLi8uLi9zdHlsZS9zYXNzL2Jvb3RzdHJhcC9ib290c3RyYXAvX3ZhcmlhYmxlcy5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy90YWJsZS90YWJsZS5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy9hbGVydC9hbGVydC5zY3NzIiwiLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy92YWxpZGF0aW9uL3ZhbGlkYXRpb24uc2NzcyIsIi4uL3VpX2NvbXBvbmVudHMvc21hcnRDb21wb25lbnRzL3NtYXJ0VGFibGUvc21hcnRUYWJsZS5zY3NzIl0sInNvdXJjZXNDb250ZW50IjpbIkBpbXBvcnQgJy4vYW5pbWF0aW9ucy5zY3NzJztcbkBpbXBvcnQgJy4uLy4uLy4uLy4uLy4uL3ZpZXdzL3N0eWxlL3Nhc3MvYm9vdHN0cmFwL2Jvb3RzdHJhcC9fdmFyaWFibGVzLnNjc3MnO1xuXG5AaW1wb3J0ICcuLi91aV9jb21wb25lbnRzL2R1bWJDb21wb25lbnRzL3RhYmxlL3RhYmxlLnNjc3MnO1xuQGltcG9ydCAnLi4vdWlfY29tcG9uZW50cy9kdW1iQ29tcG9uZW50cy9hbGVydC9hbGVydC5zY3NzJztcbkBpbXBvcnQgJy4uL3VpX2NvbXBvbmVudHMvZHVtYkNvbXBvbmVudHMvdmFsaWRhdGlvbi92YWxpZGF0aW9uLnNjc3MnO1xuXG5AaW1wb3J0ICcuLi91aV9jb21wb25lbnRzL3NtYXJ0Q29tcG9uZW50cy9zbWFydFRhYmxlL3NtYXJ0VGFibGUuc2Nzcyc7XG5cbltuZ1xcOmNsb2FrXSwgW25nLWNsb2FrXSwgW2RhdGEtbmctY2xvYWtdLCBbeC1uZy1jbG9ha10sIC5uZy1jbG9haywgLngtbmctY2xvYWsge1xuICBkaXNwbGF5OiBub25lICFpbXBvcnRhbnQ7XG59XG5cbi5yb3cgKyAucm93IHtcbiAgLyogVE9ETyBtb3ZlIGluIHhvcy5zY3NzKi8gXG4gIG1hcmdpbi10b3A6ICRmb3JtLWdyb3VwLW1hcmdpbi1ib3R0b207XG59IiwiQGtleWZyYW1lcyBzbGlkZUluUmlnaHQge1xuICBmcm9tIHtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDEwMCUsIDAsIDApO1xuICAgIHZpc2liaWxpdHk6IHZpc2libGU7XG4gIH1cblxuICB0byB7XG4gICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgwLCAwLCAwKTtcbiAgfVxufVxuXG5Aa2V5ZnJhbWVzIHNsaWRlT3V0UmlnaHQge1xuICBmcm9tIHtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDAsIDApO1xuICB9XG5cbiAgdG8ge1xuICAgIHZpc2liaWxpdHk6IGhpZGRlbjtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDEwMCUsIDAsIDApO1xuICB9XG59XG5cbkBrZXlmcmFtZXMgZmFkZUluVXAge1xuICBmcm9tIHtcbiAgICBvcGFjaXR5OiAwO1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMCwgMTAwJSwgMCk7XG4gIH1cblxuICB0byB7XG4gICAgb3BhY2l0eTogMTtcbiAgICB0cmFuc2Zvcm06IG5vbmU7XG4gIH1cbn1cblxuQGtleWZyYW1lcyBmYWRlT3V0RG93biB7XG4gIGZyb20ge1xuICAgIG9wYWNpdHk6IDE7XG4gIH1cblxuICB0byB7XG4gICAgb3BhY2l0eTogMDtcbiAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKDAsIDEwMCUsIDApO1xuICB9XG59IiwiJGJvb3RzdHJhcC1zYXNzLWFzc2V0LWhlbHBlcjogZmFsc2UgIWRlZmF1bHQ7XG4vL1xuLy8gVmFyaWFibGVzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cbi8vPT0gQ29sb3JzXG4vL1xuLy8jIyBHcmF5IGFuZCBicmFuZCBjb2xvcnMgZm9yIHVzZSBhY3Jvc3MgQm9vdHN0cmFwLlxuXG4kZ3JheS1iYXNlOiAgICAgICAgICAgICAgIzAwMCAhZGVmYXVsdDtcbiRncmF5LWRhcmtlcjogICAgICAgICAgICBsaWdodGVuKCRncmF5LWJhc2UsIDEzLjUlKSAhZGVmYXVsdDsgLy8gIzIyMlxuJGdyYXktZGFyazogICAgICAgICAgICAgIGxpZ2h0ZW4oJGdyYXktYmFzZSwgMjAlKSAhZGVmYXVsdDsgICAvLyAjMzMzXG4kZ3JheTogICAgICAgICAgICAgICAgICAgbGlnaHRlbigkZ3JheS1iYXNlLCAzMy41JSkgIWRlZmF1bHQ7IC8vICM1NTVcbiRncmF5LWxpZ2h0OiAgICAgICAgICAgICBsaWdodGVuKCRncmF5LWJhc2UsIDQ2LjclKSAhZGVmYXVsdDsgLy8gIzc3N1xuJGdyYXktbGlnaHRlcjogICAgICAgICAgIGxpZ2h0ZW4oJGdyYXktYmFzZSwgOTMuNSUpICFkZWZhdWx0OyAvLyAjZWVlXG5cbiRicmFuZC1wcmltYXJ5OiAgICAgICAgIGRhcmtlbigjNDI4YmNhLCA2LjUlKSAhZGVmYXVsdDsgLy8gIzMzN2FiN1xuJGJyYW5kLXN1Y2Nlc3M6ICAgICAgICAgIzVjYjg1YyAhZGVmYXVsdDtcbiRicmFuZC1pbmZvOiAgICAgICAgICAgICM1YmMwZGUgIWRlZmF1bHQ7XG4kYnJhbmQtd2FybmluZzogICAgICAgICAjZjBhZDRlICFkZWZhdWx0O1xuJGJyYW5kLWRhbmdlcjogICAgICAgICAgI2Q5NTM0ZiAhZGVmYXVsdDtcblxuXG4vLz09IFNjYWZmb2xkaW5nXG4vL1xuLy8jIyBTZXR0aW5ncyBmb3Igc29tZSBvZiB0aGUgbW9zdCBnbG9iYWwgc3R5bGVzLlxuXG4vLyoqIEJhY2tncm91bmQgY29sb3IgZm9yIGA8Ym9keT5gLlxuJGJvZHktYmc6ICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogR2xvYmFsIHRleHQgY29sb3Igb24gYDxib2R5PmAuXG4kdGV4dC1jb2xvcjogICAgICAgICAgICAkZ3JheS1kYXJrICFkZWZhdWx0O1xuXG4vLyoqIEdsb2JhbCB0ZXh0dWFsIGxpbmsgY29sb3IuXG4kbGluay1jb2xvcjogICAgICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcbi8vKiogTGluayBob3ZlciBjb2xvciBzZXQgdmlhIGBkYXJrZW4oKWAgZnVuY3Rpb24uXG4kbGluay1ob3Zlci1jb2xvcjogICAgICBkYXJrZW4oJGxpbmstY29sb3IsIDE1JSkgIWRlZmF1bHQ7XG4vLyoqIExpbmsgaG92ZXIgZGVjb3JhdGlvbi5cbiRsaW5rLWhvdmVyLWRlY29yYXRpb246IHVuZGVybGluZSAhZGVmYXVsdDtcblxuXG4vLz09IFR5cG9ncmFwaHlcbi8vXG4vLyMjIEZvbnQsIGxpbmUtaGVpZ2h0LCBhbmQgY29sb3IgZm9yIGJvZHkgdGV4dCwgaGVhZGluZ3MsIGFuZCBtb3JlLlxuXG4kZm9udC1mYW1pbHktc2Fucy1zZXJpZjogIFwiSGVsdmV0aWNhIE5ldWVcIiwgSGVsdmV0aWNhLCBBcmlhbCwgc2Fucy1zZXJpZiAhZGVmYXVsdDtcbiRmb250LWZhbWlseS1zZXJpZjogICAgICAgR2VvcmdpYSwgXCJUaW1lcyBOZXcgUm9tYW5cIiwgVGltZXMsIHNlcmlmICFkZWZhdWx0O1xuLy8qKiBEZWZhdWx0IG1vbm9zcGFjZSBmb250cyBmb3IgYDxjb2RlPmAsIGA8a2JkPmAsIGFuZCBgPHByZT5gLlxuJGZvbnQtZmFtaWx5LW1vbm9zcGFjZTogICBNZW5sbywgTW9uYWNvLCBDb25zb2xhcywgXCJDb3VyaWVyIE5ld1wiLCBtb25vc3BhY2UgIWRlZmF1bHQ7XG4kZm9udC1mYW1pbHktYmFzZTogICAgICAgICRmb250LWZhbWlseS1zYW5zLXNlcmlmICFkZWZhdWx0O1xuXG4kZm9udC1zaXplLWJhc2U6ICAgICAgICAgIDE0cHggIWRlZmF1bHQ7XG4kZm9udC1zaXplLWxhcmdlOiAgICAgICAgIGNlaWwoKCRmb250LXNpemUtYmFzZSAqIDEuMjUpKSAhZGVmYXVsdDsgLy8gfjE4cHhcbiRmb250LXNpemUtc21hbGw6ICAgICAgICAgY2VpbCgoJGZvbnQtc2l6ZS1iYXNlICogMC44NSkpICFkZWZhdWx0OyAvLyB+MTJweFxuXG4kZm9udC1zaXplLWgxOiAgICAgICAgICAgIGZsb29yKCgkZm9udC1zaXplLWJhc2UgKiAyLjYpKSAhZGVmYXVsdDsgLy8gfjM2cHhcbiRmb250LXNpemUtaDI6ICAgICAgICAgICAgZmxvb3IoKCRmb250LXNpemUtYmFzZSAqIDIuMTUpKSAhZGVmYXVsdDsgLy8gfjMwcHhcbiRmb250LXNpemUtaDM6ICAgICAgICAgICAgY2VpbCgoJGZvbnQtc2l6ZS1iYXNlICogMS43KSkgIWRlZmF1bHQ7IC8vIH4yNHB4XG4kZm9udC1zaXplLWg0OiAgICAgICAgICAgIGNlaWwoKCRmb250LXNpemUtYmFzZSAqIDEuMjUpKSAhZGVmYXVsdDsgLy8gfjE4cHhcbiRmb250LXNpemUtaDU6ICAgICAgICAgICAgJGZvbnQtc2l6ZS1iYXNlICFkZWZhdWx0O1xuJGZvbnQtc2l6ZS1oNjogICAgICAgICAgICBjZWlsKCgkZm9udC1zaXplLWJhc2UgKiAwLjg1KSkgIWRlZmF1bHQ7IC8vIH4xMnB4XG5cbi8vKiogVW5pdC1sZXNzIGBsaW5lLWhlaWdodGAgZm9yIHVzZSBpbiBjb21wb25lbnRzIGxpa2UgYnV0dG9ucy5cbiRsaW5lLWhlaWdodC1iYXNlOiAgICAgICAgMS40Mjg1NzE0MjkgIWRlZmF1bHQ7IC8vIDIwLzE0XG4vLyoqIENvbXB1dGVkIFwibGluZS1oZWlnaHRcIiAoYGZvbnQtc2l6ZWAgKiBgbGluZS1oZWlnaHRgKSBmb3IgdXNlIHdpdGggYG1hcmdpbmAsIGBwYWRkaW5nYCwgZXRjLlxuJGxpbmUtaGVpZ2h0LWNvbXB1dGVkOiAgICBmbG9vcigoJGZvbnQtc2l6ZS1iYXNlICogJGxpbmUtaGVpZ2h0LWJhc2UpKSAhZGVmYXVsdDsgLy8gfjIwcHhcblxuLy8qKiBCeSBkZWZhdWx0LCB0aGlzIGluaGVyaXRzIGZyb20gdGhlIGA8Ym9keT5gLlxuJGhlYWRpbmdzLWZvbnQtZmFtaWx5OiAgICBpbmhlcml0ICFkZWZhdWx0O1xuJGhlYWRpbmdzLWZvbnQtd2VpZ2h0OiAgICA1MDAgIWRlZmF1bHQ7XG4kaGVhZGluZ3MtbGluZS1oZWlnaHQ6ICAgIDEuMSAhZGVmYXVsdDtcbiRoZWFkaW5ncy1jb2xvcjogICAgICAgICAgaW5oZXJpdCAhZGVmYXVsdDtcblxuXG4vLz09IEljb25vZ3JhcGh5XG4vL1xuLy8jIyBTcGVjaWZ5IGN1c3RvbSBsb2NhdGlvbiBhbmQgZmlsZW5hbWUgb2YgdGhlIGluY2x1ZGVkIEdseXBoaWNvbnMgaWNvbiBmb250LiBVc2VmdWwgZm9yIHRob3NlIGluY2x1ZGluZyBCb290c3RyYXAgdmlhIEJvd2VyLlxuXG4vLyoqIExvYWQgZm9udHMgZnJvbSB0aGlzIGRpcmVjdG9yeS5cblxuLy8gW2NvbnZlcnRlcl0gSWYgJGJvb3RzdHJhcC1zYXNzLWFzc2V0LWhlbHBlciBpZiB1c2VkLCBwcm92aWRlIHBhdGggcmVsYXRpdmUgdG8gdGhlIGFzc2V0cyBsb2FkIHBhdGguXG4vLyBbY29udmVydGVyXSBUaGlzIGlzIGJlY2F1c2Ugc29tZSBhc3NldCBoZWxwZXJzLCBzdWNoIGFzIFNwcm9ja2V0cywgZG8gbm90IHdvcmsgd2l0aCBmaWxlLXJlbGF0aXZlIHBhdGhzLlxuJGljb24tZm9udC1wYXRoOiBpZigkYm9vdHN0cmFwLXNhc3MtYXNzZXQtaGVscGVyLCBcImJvb3RzdHJhcC9cIiwgXCIuLi9mb250cy9ib290c3RyYXAvXCIpICFkZWZhdWx0O1xuXG4vLyoqIEZpbGUgbmFtZSBmb3IgYWxsIGZvbnQgZmlsZXMuXG4kaWNvbi1mb250LW5hbWU6ICAgICAgICAgIFwiZ2x5cGhpY29ucy1oYWxmbGluZ3MtcmVndWxhclwiICFkZWZhdWx0O1xuLy8qKiBFbGVtZW50IElEIHdpdGhpbiBTVkcgaWNvbiBmaWxlLlxuJGljb24tZm9udC1zdmctaWQ6ICAgICAgICBcImdseXBoaWNvbnNfaGFsZmxpbmdzcmVndWxhclwiICFkZWZhdWx0O1xuXG5cbi8vPT0gQ29tcG9uZW50c1xuLy9cbi8vIyMgRGVmaW5lIGNvbW1vbiBwYWRkaW5nIGFuZCBib3JkZXIgcmFkaXVzIHNpemVzIGFuZCBtb3JlLiBWYWx1ZXMgYmFzZWQgb24gMTRweCB0ZXh0IGFuZCAxLjQyOCBsaW5lLWhlaWdodCAofjIwcHggdG8gc3RhcnQpLlxuXG4kcGFkZGluZy1iYXNlLXZlcnRpY2FsOiAgICAgNnB4ICFkZWZhdWx0O1xuJHBhZGRpbmctYmFzZS1ob3Jpem9udGFsOiAgIDEycHggIWRlZmF1bHQ7XG5cbiRwYWRkaW5nLWxhcmdlLXZlcnRpY2FsOiAgICAxMHB4ICFkZWZhdWx0O1xuJHBhZGRpbmctbGFyZ2UtaG9yaXpvbnRhbDogIDE2cHggIWRlZmF1bHQ7XG5cbiRwYWRkaW5nLXNtYWxsLXZlcnRpY2FsOiAgICA1cHggIWRlZmF1bHQ7XG4kcGFkZGluZy1zbWFsbC1ob3Jpem9udGFsOiAgMTBweCAhZGVmYXVsdDtcblxuJHBhZGRpbmcteHMtdmVydGljYWw6ICAgICAgIDFweCAhZGVmYXVsdDtcbiRwYWRkaW5nLXhzLWhvcml6b250YWw6ICAgICA1cHggIWRlZmF1bHQ7XG5cbiRsaW5lLWhlaWdodC1sYXJnZTogICAgICAgICAxLjMzMzMzMzMgIWRlZmF1bHQ7IC8vIGV4dHJhIGRlY2ltYWxzIGZvciBXaW4gOC4xIENocm9tZVxuJGxpbmUtaGVpZ2h0LXNtYWxsOiAgICAgICAgIDEuNSAhZGVmYXVsdDtcblxuJGJvcmRlci1yYWRpdXMtYmFzZTogICAgICAgIDRweCAhZGVmYXVsdDtcbiRib3JkZXItcmFkaXVzLWxhcmdlOiAgICAgICA2cHggIWRlZmF1bHQ7XG4kYm9yZGVyLXJhZGl1cy1zbWFsbDogICAgICAgM3B4ICFkZWZhdWx0O1xuXG4vLyoqIEdsb2JhbCBjb2xvciBmb3IgYWN0aXZlIGl0ZW1zIChlLmcuLCBuYXZzIG9yIGRyb3Bkb3ducykuXG4kY29tcG9uZW50LWFjdGl2ZS1jb2xvcjogICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogR2xvYmFsIGJhY2tncm91bmQgY29sb3IgZm9yIGFjdGl2ZSBpdGVtcyAoZS5nLiwgbmF2cyBvciBkcm9wZG93bnMpLlxuJGNvbXBvbmVudC1hY3RpdmUtYmc6ICAgICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuXG4vLyoqIFdpZHRoIG9mIHRoZSBgYm9yZGVyYCBmb3IgZ2VuZXJhdGluZyBjYXJldHMgdGhhdCBpbmRpY2F0b3IgZHJvcGRvd25zLlxuJGNhcmV0LXdpZHRoLWJhc2U6ICAgICAgICAgIDRweCAhZGVmYXVsdDtcbi8vKiogQ2FyZXRzIGluY3JlYXNlIHNsaWdodGx5IGluIHNpemUgZm9yIGxhcmdlciBjb21wb25lbnRzLlxuJGNhcmV0LXdpZHRoLWxhcmdlOiAgICAgICAgIDVweCAhZGVmYXVsdDtcblxuXG4vLz09IFRhYmxlc1xuLy9cbi8vIyMgQ3VzdG9taXplcyB0aGUgYC50YWJsZWAgY29tcG9uZW50IHdpdGggYmFzaWMgdmFsdWVzLCBlYWNoIHVzZWQgYWNyb3NzIGFsbCB0YWJsZSB2YXJpYXRpb25zLlxuXG4vLyoqIFBhZGRpbmcgZm9yIGA8dGg+YHMgYW5kIGA8dGQ+YHMuXG4kdGFibGUtY2VsbC1wYWRkaW5nOiAgICAgICAgICAgIDhweCAhZGVmYXVsdDtcbi8vKiogUGFkZGluZyBmb3IgY2VsbHMgaW4gYC50YWJsZS1jb25kZW5zZWRgLlxuJHRhYmxlLWNvbmRlbnNlZC1jZWxsLXBhZGRpbmc6ICA1cHggIWRlZmF1bHQ7XG5cbi8vKiogRGVmYXVsdCBiYWNrZ3JvdW5kIGNvbG9yIHVzZWQgZm9yIGFsbCB0YWJsZXMuXG4kdGFibGUtYmc6ICAgICAgICAgICAgICAgICAgICAgIHRyYW5zcGFyZW50ICFkZWZhdWx0O1xuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIHVzZWQgZm9yIGAudGFibGUtc3RyaXBlZGAuXG4kdGFibGUtYmctYWNjZW50OiAgICAgICAgICAgICAgICNmOWY5ZjkgIWRlZmF1bHQ7XG4vLyoqIEJhY2tncm91bmQgY29sb3IgdXNlZCBmb3IgYC50YWJsZS1ob3ZlcmAuXG4kdGFibGUtYmctaG92ZXI6ICAgICAgICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG4kdGFibGUtYmctYWN0aXZlOiAgICAgICAgICAgICAgICR0YWJsZS1iZy1ob3ZlciAhZGVmYXVsdDtcblxuLy8qKiBCb3JkZXIgY29sb3IgZm9yIHRhYmxlIGFuZCBjZWxsIGJvcmRlcnMuXG4kdGFibGUtYm9yZGVyLWNvbG9yOiAgICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG5cblxuLy89PSBCdXR0b25zXG4vL1xuLy8jIyBGb3IgZWFjaCBvZiBCb290c3RyYXAncyBidXR0b25zLCBkZWZpbmUgdGV4dCwgYmFja2dyb3VuZCBhbmQgYm9yZGVyIGNvbG9yLlxuXG4kYnRuLWZvbnQtd2VpZ2h0OiAgICAgICAgICAgICAgICBub3JtYWwgIWRlZmF1bHQ7XG5cbiRidG4tZGVmYXVsdC1jb2xvcjogICAgICAgICAgICAgICMzMzMgIWRlZmF1bHQ7XG4kYnRuLWRlZmF1bHQtYmc6ICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGJ0bi1kZWZhdWx0LWJvcmRlcjogICAgICAgICAgICAgI2NjYyAhZGVmYXVsdDtcblxuJGJ0bi1wcmltYXJ5LWNvbG9yOiAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRidG4tcHJpbWFyeS1iZzogICAgICAgICAgICAgICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuJGJ0bi1wcmltYXJ5LWJvcmRlcjogICAgICAgICAgICAgZGFya2VuKCRidG4tcHJpbWFyeS1iZywgNSUpICFkZWZhdWx0O1xuXG4kYnRuLXN1Y2Nlc3MtY29sb3I6ICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGJ0bi1zdWNjZXNzLWJnOiAgICAgICAgICAgICAgICAgJGJyYW5kLXN1Y2Nlc3MgIWRlZmF1bHQ7XG4kYnRuLXN1Y2Nlc3MtYm9yZGVyOiAgICAgICAgICAgICBkYXJrZW4oJGJ0bi1zdWNjZXNzLWJnLCA1JSkgIWRlZmF1bHQ7XG5cbiRidG4taW5mby1jb2xvcjogICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kYnRuLWluZm8tYmc6ICAgICAgICAgICAgICAgICAgICAkYnJhbmQtaW5mbyAhZGVmYXVsdDtcbiRidG4taW5mby1ib3JkZXI6ICAgICAgICAgICAgICAgIGRhcmtlbigkYnRuLWluZm8tYmcsIDUlKSAhZGVmYXVsdDtcblxuJGJ0bi13YXJuaW5nLWNvbG9yOiAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRidG4td2FybmluZy1iZzogICAgICAgICAgICAgICAgICRicmFuZC13YXJuaW5nICFkZWZhdWx0O1xuJGJ0bi13YXJuaW5nLWJvcmRlcjogICAgICAgICAgICAgZGFya2VuKCRidG4td2FybmluZy1iZywgNSUpICFkZWZhdWx0O1xuXG4kYnRuLWRhbmdlci1jb2xvcjogICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuJGJ0bi1kYW5nZXItYmc6ICAgICAgICAgICAgICAgICAgJGJyYW5kLWRhbmdlciAhZGVmYXVsdDtcbiRidG4tZGFuZ2VyLWJvcmRlcjogICAgICAgICAgICAgIGRhcmtlbigkYnRuLWRhbmdlci1iZywgNSUpICFkZWZhdWx0O1xuXG4kYnRuLWxpbmstZGlzYWJsZWQtY29sb3I6ICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcblxuLy8gQWxsb3dzIGZvciBjdXN0b21pemluZyBidXR0b24gcmFkaXVzIGluZGVwZW5kZW50bHkgZnJvbSBnbG9iYWwgYm9yZGVyIHJhZGl1c1xuJGJ0bi1ib3JkZXItcmFkaXVzLWJhc2U6ICAgICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcbiRidG4tYm9yZGVyLXJhZGl1cy1sYXJnZTogICAgICAgICRib3JkZXItcmFkaXVzLWxhcmdlICFkZWZhdWx0O1xuJGJ0bi1ib3JkZXItcmFkaXVzLXNtYWxsOiAgICAgICAgJGJvcmRlci1yYWRpdXMtc21hbGwgIWRlZmF1bHQ7XG5cblxuLy89PSBGb3Jtc1xuLy9cbi8vIyNcblxuLy8qKiBgPGlucHV0PmAgYmFja2dyb3VuZCBjb2xvclxuJGlucHV0LWJnOiAgICAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogYDxpbnB1dCBkaXNhYmxlZD5gIGJhY2tncm91bmQgY29sb3JcbiRpbnB1dC1iZy1kaXNhYmxlZDogICAgICAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG5cbi8vKiogVGV4dCBjb2xvciBmb3IgYDxpbnB1dD5gc1xuJGlucHV0LWNvbG9yOiAgICAgICAgICAgICAgICAgICAgJGdyYXkgIWRlZmF1bHQ7XG4vLyoqIGA8aW5wdXQ+YCBib3JkZXIgY29sb3JcbiRpbnB1dC1ib3JkZXI6ICAgICAgICAgICAgICAgICAgICNjY2MgIWRlZmF1bHQ7XG5cbi8vIFRPRE86IFJlbmFtZSBgJGlucHV0LWJvcmRlci1yYWRpdXNgIHRvIGAkaW5wdXQtYm9yZGVyLXJhZGl1cy1iYXNlYCBpbiB2NFxuLy8qKiBEZWZhdWx0IGAuZm9ybS1jb250cm9sYCBib3JkZXIgcmFkaXVzXG4vLyBUaGlzIGhhcyBubyBlZmZlY3Qgb24gYDxzZWxlY3Q+YHMgaW4gc29tZSBicm93c2VycywgZHVlIHRvIHRoZSBsaW1pdGVkIHN0eWxhYmlsaXR5IG9mIGA8c2VsZWN0PmBzIGluIENTUy5cbiRpbnB1dC1ib3JkZXItcmFkaXVzOiAgICAgICAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG4vLyoqIExhcmdlIGAuZm9ybS1jb250cm9sYCBib3JkZXIgcmFkaXVzXG4kaW5wdXQtYm9yZGVyLXJhZGl1cy1sYXJnZTogICAgICAkYm9yZGVyLXJhZGl1cy1sYXJnZSAhZGVmYXVsdDtcbi8vKiogU21hbGwgYC5mb3JtLWNvbnRyb2xgIGJvcmRlciByYWRpdXNcbiRpbnB1dC1ib3JkZXItcmFkaXVzLXNtYWxsOiAgICAgICRib3JkZXItcmFkaXVzLXNtYWxsICFkZWZhdWx0O1xuXG4vLyoqIEJvcmRlciBjb2xvciBmb3IgaW5wdXRzIG9uIGZvY3VzXG4kaW5wdXQtYm9yZGVyLWZvY3VzOiAgICAgICAgICAgICAjNjZhZmU5ICFkZWZhdWx0O1xuXG4vLyoqIFBsYWNlaG9sZGVyIHRleHQgY29sb3JcbiRpbnB1dC1jb2xvci1wbGFjZWhvbGRlcjogICAgICAgICM5OTkgIWRlZmF1bHQ7XG5cbi8vKiogRGVmYXVsdCBgLmZvcm0tY29udHJvbGAgaGVpZ2h0XG4kaW5wdXQtaGVpZ2h0LWJhc2U6ICAgICAgICAgICAgICAoJGxpbmUtaGVpZ2h0LWNvbXB1dGVkICsgKCRwYWRkaW5nLWJhc2UtdmVydGljYWwgKiAyKSArIDIpICFkZWZhdWx0O1xuLy8qKiBMYXJnZSBgLmZvcm0tY29udHJvbGAgaGVpZ2h0XG4kaW5wdXQtaGVpZ2h0LWxhcmdlOiAgICAgICAgICAgICAoY2VpbCgkZm9udC1zaXplLWxhcmdlICogJGxpbmUtaGVpZ2h0LWxhcmdlKSArICgkcGFkZGluZy1sYXJnZS12ZXJ0aWNhbCAqIDIpICsgMikgIWRlZmF1bHQ7XG4vLyoqIFNtYWxsIGAuZm9ybS1jb250cm9sYCBoZWlnaHRcbiRpbnB1dC1oZWlnaHQtc21hbGw6ICAgICAgICAgICAgIChmbG9vcigkZm9udC1zaXplLXNtYWxsICogJGxpbmUtaGVpZ2h0LXNtYWxsKSArICgkcGFkZGluZy1zbWFsbC12ZXJ0aWNhbCAqIDIpICsgMikgIWRlZmF1bHQ7XG5cbi8vKiogYC5mb3JtLWdyb3VwYCBtYXJnaW5cbiRmb3JtLWdyb3VwLW1hcmdpbi1ib3R0b206ICAgICAgIDE1cHggIWRlZmF1bHQ7XG5cbiRsZWdlbmQtY29sb3I6ICAgICAgICAgICAgICAgICAgICRncmF5LWRhcmsgIWRlZmF1bHQ7XG4kbGVnZW5kLWJvcmRlci1jb2xvcjogICAgICAgICAgICAjZTVlNWU1ICFkZWZhdWx0O1xuXG4vLyoqIEJhY2tncm91bmQgY29sb3IgZm9yIHRleHR1YWwgaW5wdXQgYWRkb25zXG4kaW5wdXQtZ3JvdXAtYWRkb24tYmc6ICAgICAgICAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuLy8qKiBCb3JkZXIgY29sb3IgZm9yIHRleHR1YWwgaW5wdXQgYWRkb25zXG4kaW5wdXQtZ3JvdXAtYWRkb24tYm9yZGVyLWNvbG9yOiAkaW5wdXQtYm9yZGVyICFkZWZhdWx0O1xuXG4vLyoqIERpc2FibGVkIGN1cnNvciBmb3IgZm9ybSBjb250cm9scyBhbmQgYnV0dG9ucy5cbiRjdXJzb3ItZGlzYWJsZWQ6ICAgICAgICAgICAgICAgIG5vdC1hbGxvd2VkICFkZWZhdWx0O1xuXG5cbi8vPT0gRHJvcGRvd25zXG4vL1xuLy8jIyBEcm9wZG93biBtZW51IGNvbnRhaW5lciBhbmQgY29udGVudHMuXG5cbi8vKiogQmFja2dyb3VuZCBmb3IgdGhlIGRyb3Bkb3duIG1lbnUuXG4kZHJvcGRvd24tYmc6ICAgICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBEcm9wZG93biBtZW51IGBib3JkZXItY29sb3JgLlxuJGRyb3Bkb3duLWJvcmRlcjogICAgICAgICAgICAgICAgcmdiYSgwLDAsMCwuMTUpICFkZWZhdWx0O1xuLy8qKiBEcm9wZG93biBtZW51IGBib3JkZXItY29sb3JgICoqZm9yIElFOCoqLlxuJGRyb3Bkb3duLWZhbGxiYWNrLWJvcmRlcjogICAgICAgI2NjYyAhZGVmYXVsdDtcbi8vKiogRGl2aWRlciBjb2xvciBmb3IgYmV0d2VlbiBkcm9wZG93biBpdGVtcy5cbiRkcm9wZG93bi1kaXZpZGVyLWJnOiAgICAgICAgICAgICNlNWU1ZTUgIWRlZmF1bHQ7XG5cbi8vKiogRHJvcGRvd24gbGluayB0ZXh0IGNvbG9yLlxuJGRyb3Bkb3duLWxpbmstY29sb3I6ICAgICAgICAgICAgJGdyYXktZGFyayAhZGVmYXVsdDtcbi8vKiogSG92ZXIgY29sb3IgZm9yIGRyb3Bkb3duIGxpbmtzLlxuJGRyb3Bkb3duLWxpbmstaG92ZXItY29sb3I6ICAgICAgZGFya2VuKCRncmF5LWRhcmssIDUlKSAhZGVmYXVsdDtcbi8vKiogSG92ZXIgYmFja2dyb3VuZCBmb3IgZHJvcGRvd24gbGlua3MuXG4kZHJvcGRvd24tbGluay1ob3Zlci1iZzogICAgICAgICAjZjVmNWY1ICFkZWZhdWx0O1xuXG4vLyoqIEFjdGl2ZSBkcm9wZG93biBtZW51IGl0ZW0gdGV4dCBjb2xvci5cbiRkcm9wZG93bi1saW5rLWFjdGl2ZS1jb2xvcjogICAgICRjb21wb25lbnQtYWN0aXZlLWNvbG9yICFkZWZhdWx0O1xuLy8qKiBBY3RpdmUgZHJvcGRvd24gbWVudSBpdGVtIGJhY2tncm91bmQgY29sb3IuXG4kZHJvcGRvd24tbGluay1hY3RpdmUtYmc6ICAgICAgICAkY29tcG9uZW50LWFjdGl2ZS1iZyAhZGVmYXVsdDtcblxuLy8qKiBEaXNhYmxlZCBkcm9wZG93biBtZW51IGl0ZW0gYmFja2dyb3VuZCBjb2xvci5cbiRkcm9wZG93bi1saW5rLWRpc2FibGVkLWNvbG9yOiAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuXG4vLyoqIFRleHQgY29sb3IgZm9yIGhlYWRlcnMgd2l0aGluIGRyb3Bkb3duIG1lbnVzLlxuJGRyb3Bkb3duLWhlYWRlci1jb2xvcjogICAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG5cbi8vKiogRGVwcmVjYXRlZCBgJGRyb3Bkb3duLWNhcmV0LWNvbG9yYCBhcyBvZiB2My4xLjBcbiRkcm9wZG93bi1jYXJldC1jb2xvcjogICAgICAgICAgICMwMDAgIWRlZmF1bHQ7XG5cblxuLy8tLSBaLWluZGV4IG1hc3RlciBsaXN0XG4vL1xuLy8gV2FybmluZzogQXZvaWQgY3VzdG9taXppbmcgdGhlc2UgdmFsdWVzLiBUaGV5J3JlIHVzZWQgZm9yIGEgYmlyZCdzIGV5ZSB2aWV3XG4vLyBvZiBjb21wb25lbnRzIGRlcGVuZGVudCBvbiB0aGUgei1heGlzIGFuZCBhcmUgZGVzaWduZWQgdG8gYWxsIHdvcmsgdG9nZXRoZXIuXG4vL1xuLy8gTm90ZTogVGhlc2UgdmFyaWFibGVzIGFyZSBub3QgZ2VuZXJhdGVkIGludG8gdGhlIEN1c3RvbWl6ZXIuXG5cbiR6aW5kZXgtbmF2YmFyOiAgICAgICAgICAgIDEwMDAgIWRlZmF1bHQ7XG4kemluZGV4LWRyb3Bkb3duOiAgICAgICAgICAxMDAwICFkZWZhdWx0O1xuJHppbmRleC1wb3BvdmVyOiAgICAgICAgICAgMTA2MCAhZGVmYXVsdDtcbiR6aW5kZXgtdG9vbHRpcDogICAgICAgICAgIDEwNzAgIWRlZmF1bHQ7XG4kemluZGV4LW5hdmJhci1maXhlZDogICAgICAxMDMwICFkZWZhdWx0O1xuJHppbmRleC1tb2RhbC1iYWNrZ3JvdW5kOiAgMTA0MCAhZGVmYXVsdDtcbiR6aW5kZXgtbW9kYWw6ICAgICAgICAgICAgIDEwNTAgIWRlZmF1bHQ7XG5cblxuLy89PSBNZWRpYSBxdWVyaWVzIGJyZWFrcG9pbnRzXG4vL1xuLy8jIyBEZWZpbmUgdGhlIGJyZWFrcG9pbnRzIGF0IHdoaWNoIHlvdXIgbGF5b3V0IHdpbGwgY2hhbmdlLCBhZGFwdGluZyB0byBkaWZmZXJlbnQgc2NyZWVuIHNpemVzLlxuXG4vLyBFeHRyYSBzbWFsbCBzY3JlZW4gLyBwaG9uZVxuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLXhzYCBhcyBvZiB2My4wLjFcbiRzY3JlZW4teHM6ICAgICAgICAgICAgICAgICAgNDgwcHggIWRlZmF1bHQ7XG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4teHMtbWluYCBhcyBvZiB2My4yLjBcbiRzY3JlZW4teHMtbWluOiAgICAgICAgICAgICAgJHNjcmVlbi14cyAhZGVmYXVsdDtcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi1waG9uZWAgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLXBob25lOiAgICAgICAgICAgICAgICRzY3JlZW4teHMtbWluICFkZWZhdWx0O1xuXG4vLyBTbWFsbCBzY3JlZW4gLyB0YWJsZXRcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi1zbWAgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLXNtOiAgICAgICAgICAgICAgICAgIDc2OHB4ICFkZWZhdWx0O1xuJHNjcmVlbi1zbS1taW46ICAgICAgICAgICAgICAkc2NyZWVuLXNtICFkZWZhdWx0O1xuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLXRhYmxldGAgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLXRhYmxldDogICAgICAgICAgICAgICRzY3JlZW4tc20tbWluICFkZWZhdWx0O1xuXG4vLyBNZWRpdW0gc2NyZWVuIC8gZGVza3RvcFxuLy8qKiBEZXByZWNhdGVkIGAkc2NyZWVuLW1kYCBhcyBvZiB2My4wLjFcbiRzY3JlZW4tbWQ6ICAgICAgICAgICAgICAgICAgOTkycHggIWRlZmF1bHQ7XG4kc2NyZWVuLW1kLW1pbjogICAgICAgICAgICAgICRzY3JlZW4tbWQgIWRlZmF1bHQ7XG4vLyoqIERlcHJlY2F0ZWQgYCRzY3JlZW4tZGVza3RvcGAgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLWRlc2t0b3A6ICAgICAgICAgICAgICRzY3JlZW4tbWQtbWluICFkZWZhdWx0O1xuXG4vLyBMYXJnZSBzY3JlZW4gLyB3aWRlIGRlc2t0b3Bcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi1sZ2AgYXMgb2YgdjMuMC4xXG4kc2NyZWVuLWxnOiAgICAgICAgICAgICAgICAgIDEyMDBweCAhZGVmYXVsdDtcbiRzY3JlZW4tbGctbWluOiAgICAgICAgICAgICAgJHNjcmVlbi1sZyAhZGVmYXVsdDtcbi8vKiogRGVwcmVjYXRlZCBgJHNjcmVlbi1sZy1kZXNrdG9wYCBhcyBvZiB2My4wLjFcbiRzY3JlZW4tbGctZGVza3RvcDogICAgICAgICAgJHNjcmVlbi1sZy1taW4gIWRlZmF1bHQ7XG5cbi8vIFNvIG1lZGlhIHF1ZXJpZXMgZG9uJ3Qgb3ZlcmxhcCB3aGVuIHJlcXVpcmVkLCBwcm92aWRlIGEgbWF4aW11bVxuJHNjcmVlbi14cy1tYXg6ICAgICAgICAgICAgICAoJHNjcmVlbi1zbS1taW4gLSAxKSAhZGVmYXVsdDtcbiRzY3JlZW4tc20tbWF4OiAgICAgICAgICAgICAgKCRzY3JlZW4tbWQtbWluIC0gMSkgIWRlZmF1bHQ7XG4kc2NyZWVuLW1kLW1heDogICAgICAgICAgICAgICgkc2NyZWVuLWxnLW1pbiAtIDEpICFkZWZhdWx0O1xuXG5cbi8vPT0gR3JpZCBzeXN0ZW1cbi8vXG4vLyMjIERlZmluZSB5b3VyIGN1c3RvbSByZXNwb25zaXZlIGdyaWQuXG5cbi8vKiogTnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhlIGdyaWQuXG4kZ3JpZC1jb2x1bW5zOiAgICAgICAgICAgICAgMTIgIWRlZmF1bHQ7XG4vLyoqIFBhZGRpbmcgYmV0d2VlbiBjb2x1bW5zLiBHZXRzIGRpdmlkZWQgaW4gaGFsZiBmb3IgdGhlIGxlZnQgYW5kIHJpZ2h0LlxuJGdyaWQtZ3V0dGVyLXdpZHRoOiAgICAgICAgIDMwcHggIWRlZmF1bHQ7XG4vLyBOYXZiYXIgY29sbGFwc2Vcbi8vKiogUG9pbnQgYXQgd2hpY2ggdGhlIG5hdmJhciBiZWNvbWVzIHVuY29sbGFwc2VkLlxuJGdyaWQtZmxvYXQtYnJlYWtwb2ludDogICAgICRzY3JlZW4tc20tbWluICFkZWZhdWx0O1xuLy8qKiBQb2ludCBhdCB3aGljaCB0aGUgbmF2YmFyIGJlZ2lucyBjb2xsYXBzaW5nLlxuJGdyaWQtZmxvYXQtYnJlYWtwb2ludC1tYXg6ICgkZ3JpZC1mbG9hdC1icmVha3BvaW50IC0gMSkgIWRlZmF1bHQ7XG5cblxuLy89PSBDb250YWluZXIgc2l6ZXNcbi8vXG4vLyMjIERlZmluZSB0aGUgbWF4aW11bSB3aWR0aCBvZiBgLmNvbnRhaW5lcmAgZm9yIGRpZmZlcmVudCBzY3JlZW4gc2l6ZXMuXG5cbi8vIFNtYWxsIHNjcmVlbiAvIHRhYmxldFxuJGNvbnRhaW5lci10YWJsZXQ6ICAgICAgICAgICAgICg3MjBweCArICRncmlkLWd1dHRlci13aWR0aCkgIWRlZmF1bHQ7XG4vLyoqIEZvciBgJHNjcmVlbi1zbS1taW5gIGFuZCB1cC5cbiRjb250YWluZXItc206ICAgICAgICAgICAgICAgICAkY29udGFpbmVyLXRhYmxldCAhZGVmYXVsdDtcblxuLy8gTWVkaXVtIHNjcmVlbiAvIGRlc2t0b3BcbiRjb250YWluZXItZGVza3RvcDogICAgICAgICAgICAoOTQwcHggKyAkZ3JpZC1ndXR0ZXItd2lkdGgpICFkZWZhdWx0O1xuLy8qKiBGb3IgYCRzY3JlZW4tbWQtbWluYCBhbmQgdXAuXG4kY29udGFpbmVyLW1kOiAgICAgICAgICAgICAgICAgJGNvbnRhaW5lci1kZXNrdG9wICFkZWZhdWx0O1xuXG4vLyBMYXJnZSBzY3JlZW4gLyB3aWRlIGRlc2t0b3BcbiRjb250YWluZXItbGFyZ2UtZGVza3RvcDogICAgICAoMTE0MHB4ICsgJGdyaWQtZ3V0dGVyLXdpZHRoKSAhZGVmYXVsdDtcbi8vKiogRm9yIGAkc2NyZWVuLWxnLW1pbmAgYW5kIHVwLlxuJGNvbnRhaW5lci1sZzogICAgICAgICAgICAgICAgICRjb250YWluZXItbGFyZ2UtZGVza3RvcCAhZGVmYXVsdDtcblxuXG4vLz09IE5hdmJhclxuLy9cbi8vIyNcblxuLy8gQmFzaWNzIG9mIGEgbmF2YmFyXG4kbmF2YmFyLWhlaWdodDogICAgICAgICAgICAgICAgICAgIDUwcHggIWRlZmF1bHQ7XG4kbmF2YmFyLW1hcmdpbi1ib3R0b206ICAgICAgICAgICAgICRsaW5lLWhlaWdodC1jb21wdXRlZCAhZGVmYXVsdDtcbiRuYXZiYXItYm9yZGVyLXJhZGl1czogICAgICAgICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcbiRuYXZiYXItcGFkZGluZy1ob3Jpem9udGFsOiAgICAgICAgZmxvb3IoKCRncmlkLWd1dHRlci13aWR0aCAvIDIpKSAhZGVmYXVsdDtcbiRuYXZiYXItcGFkZGluZy12ZXJ0aWNhbDogICAgICAgICAgKCgkbmF2YmFyLWhlaWdodCAtICRsaW5lLWhlaWdodC1jb21wdXRlZCkgLyAyKSAhZGVmYXVsdDtcbiRuYXZiYXItY29sbGFwc2UtbWF4LWhlaWdodDogICAgICAgMzQwcHggIWRlZmF1bHQ7XG5cbiRuYXZiYXItZGVmYXVsdC1jb2xvcjogICAgICAgICAgICAgIzc3NyAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1iZzogICAgICAgICAgICAgICAgI2Y4ZjhmOCAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1ib3JkZXI6ICAgICAgICAgICAgZGFya2VuKCRuYXZiYXItZGVmYXVsdC1iZywgNi41JSkgIWRlZmF1bHQ7XG5cbi8vIE5hdmJhciBsaW5rc1xuJG5hdmJhci1kZWZhdWx0LWxpbmstY29sb3I6ICAgICAgICAgICAgICAgICM3NzcgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtbGluay1ob3Zlci1jb2xvcjogICAgICAgICAgIzMzMyAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1saW5rLWhvdmVyLWJnOiAgICAgICAgICAgICB0cmFuc3BhcmVudCAhZGVmYXVsdDtcbiRuYXZiYXItZGVmYXVsdC1saW5rLWFjdGl2ZS1jb2xvcjogICAgICAgICAjNTU1ICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWxpbmstYWN0aXZlLWJnOiAgICAgICAgICAgIGRhcmtlbigkbmF2YmFyLWRlZmF1bHQtYmcsIDYuNSUpICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWxpbmstZGlzYWJsZWQtY29sb3I6ICAgICAgICNjY2MgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtbGluay1kaXNhYmxlZC1iZzogICAgICAgICAgdHJhbnNwYXJlbnQgIWRlZmF1bHQ7XG5cbi8vIE5hdmJhciBicmFuZCBsYWJlbFxuJG5hdmJhci1kZWZhdWx0LWJyYW5kLWNvbG9yOiAgICAgICAgICAgICAgICRuYXZiYXItZGVmYXVsdC1saW5rLWNvbG9yICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LWJyYW5kLWhvdmVyLWNvbG9yOiAgICAgICAgIGRhcmtlbigkbmF2YmFyLWRlZmF1bHQtYnJhbmQtY29sb3IsIDEwJSkgIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtYnJhbmQtaG92ZXItYmc6ICAgICAgICAgICAgdHJhbnNwYXJlbnQgIWRlZmF1bHQ7XG5cbi8vIE5hdmJhciB0b2dnbGVcbiRuYXZiYXItZGVmYXVsdC10b2dnbGUtaG92ZXItYmc6ICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuJG5hdmJhci1kZWZhdWx0LXRvZ2dsZS1pY29uLWJhci1iZzogICAgICAgICM4ODggIWRlZmF1bHQ7XG4kbmF2YmFyLWRlZmF1bHQtdG9nZ2xlLWJvcmRlci1jb2xvcjogICAgICAgI2RkZCAhZGVmYXVsdDtcblxuXG4vLz09PSBJbnZlcnRlZCBuYXZiYXJcbi8vIFJlc2V0IGludmVydGVkIG5hdmJhciBiYXNpY3NcbiRuYXZiYXItaW52ZXJzZS1jb2xvcjogICAgICAgICAgICAgICAgICAgICAgbGlnaHRlbigkZ3JheS1saWdodCwgMTUlKSAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1iZzogICAgICAgICAgICAgICAgICAgICAgICAgIzIyMiAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1ib3JkZXI6ICAgICAgICAgICAgICAgICAgICAgZGFya2VuKCRuYXZiYXItaW52ZXJzZS1iZywgMTAlKSAhZGVmYXVsdDtcblxuLy8gSW52ZXJ0ZWQgbmF2YmFyIGxpbmtzXG4kbmF2YmFyLWludmVyc2UtbGluay1jb2xvcjogICAgICAgICAgICAgICAgIGxpZ2h0ZW4oJGdyYXktbGlnaHQsIDE1JSkgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtbGluay1ob3Zlci1jb2xvcjogICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kbmF2YmFyLWludmVyc2UtbGluay1ob3Zlci1iZzogICAgICAgICAgICAgIHRyYW5zcGFyZW50ICFkZWZhdWx0O1xuJG5hdmJhci1pbnZlcnNlLWxpbmstYWN0aXZlLWNvbG9yOiAgICAgICAgICAkbmF2YmFyLWludmVyc2UtbGluay1ob3Zlci1jb2xvciAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1saW5rLWFjdGl2ZS1iZzogICAgICAgICAgICAgZGFya2VuKCRuYXZiYXItaW52ZXJzZS1iZywgMTAlKSAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1saW5rLWRpc2FibGVkLWNvbG9yOiAgICAgICAgIzQ0NCAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1saW5rLWRpc2FibGVkLWJnOiAgICAgICAgICAgdHJhbnNwYXJlbnQgIWRlZmF1bHQ7XG5cbi8vIEludmVydGVkIG5hdmJhciBicmFuZCBsYWJlbFxuJG5hdmJhci1pbnZlcnNlLWJyYW5kLWNvbG9yOiAgICAgICAgICAgICAgICAkbmF2YmFyLWludmVyc2UtbGluay1jb2xvciAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1icmFuZC1ob3Zlci1jb2xvcjogICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS1icmFuZC1ob3Zlci1iZzogICAgICAgICAgICAgdHJhbnNwYXJlbnQgIWRlZmF1bHQ7XG5cbi8vIEludmVydGVkIG5hdmJhciB0b2dnbGVcbiRuYXZiYXItaW52ZXJzZS10b2dnbGUtaG92ZXItYmc6ICAgICAgICAgICAgIzMzMyAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS10b2dnbGUtaWNvbi1iYXItYmc6ICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRuYXZiYXItaW52ZXJzZS10b2dnbGUtYm9yZGVyLWNvbG9yOiAgICAgICAgIzMzMyAhZGVmYXVsdDtcblxuXG4vLz09IE5hdnNcbi8vXG4vLyMjXG5cbi8vPT09IFNoYXJlZCBuYXYgc3R5bGVzXG4kbmF2LWxpbmstcGFkZGluZzogICAgICAgICAgICAgICAgICAgICAgICAgIDEwcHggMTVweCAhZGVmYXVsdDtcbiRuYXYtbGluay1ob3Zlci1iZzogICAgICAgICAgICAgICAgICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcblxuJG5hdi1kaXNhYmxlZC1saW5rLWNvbG9yOiAgICAgICAgICAgICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbiRuYXYtZGlzYWJsZWQtbGluay1ob3Zlci1jb2xvcjogICAgICAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG5cbi8vPT0gVGFic1xuJG5hdi10YWJzLWJvcmRlci1jb2xvcjogICAgICAgICAgICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuXG4kbmF2LXRhYnMtbGluay1ob3Zlci1ib3JkZXItY29sb3I6ICAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG5cbiRuYXYtdGFicy1hY3RpdmUtbGluay1ob3Zlci1iZzogICAgICAgICAgICAgJGJvZHktYmcgIWRlZmF1bHQ7XG4kbmF2LXRhYnMtYWN0aXZlLWxpbmstaG92ZXItY29sb3I6ICAgICAgICAgICRncmF5ICFkZWZhdWx0O1xuJG5hdi10YWJzLWFjdGl2ZS1saW5rLWhvdmVyLWJvcmRlci1jb2xvcjogICAjZGRkICFkZWZhdWx0O1xuXG4kbmF2LXRhYnMtanVzdGlmaWVkLWxpbmstYm9yZGVyLWNvbG9yOiAgICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG4kbmF2LXRhYnMtanVzdGlmaWVkLWFjdGl2ZS1saW5rLWJvcmRlci1jb2xvcjogICAgICRib2R5LWJnICFkZWZhdWx0O1xuXG4vLz09IFBpbGxzXG4kbmF2LXBpbGxzLWJvcmRlci1yYWRpdXM6ICAgICAgICAgICAgICAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG4kbmF2LXBpbGxzLWFjdGl2ZS1saW5rLWhvdmVyLWJnOiAgICAgICAgICAgICRjb21wb25lbnQtYWN0aXZlLWJnICFkZWZhdWx0O1xuJG5hdi1waWxscy1hY3RpdmUtbGluay1ob3Zlci1jb2xvcjogICAgICAgICAkY29tcG9uZW50LWFjdGl2ZS1jb2xvciAhZGVmYXVsdDtcblxuXG4vLz09IFBhZ2luYXRpb25cbi8vXG4vLyMjXG5cbiRwYWdpbmF0aW9uLWNvbG9yOiAgICAgICAgICAgICAgICAgICAgICRsaW5rLWNvbG9yICFkZWZhdWx0O1xuJHBhZ2luYXRpb24tYmc6ICAgICAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWJvcmRlcjogICAgICAgICAgICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG5cbiRwYWdpbmF0aW9uLWhvdmVyLWNvbG9yOiAgICAgICAgICAgICAgICRsaW5rLWhvdmVyLWNvbG9yICFkZWZhdWx0O1xuJHBhZ2luYXRpb24taG92ZXItYmc6ICAgICAgICAgICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWhvdmVyLWJvcmRlcjogICAgICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG5cbiRwYWdpbmF0aW9uLWFjdGl2ZS1jb2xvcjogICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kcGFnaW5hdGlvbi1hY3RpdmUtYmc6ICAgICAgICAgICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWFjdGl2ZS1ib3JkZXI6ICAgICAgICAgICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuXG4kcGFnaW5hdGlvbi1kaXNhYmxlZC1jb2xvcjogICAgICAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbiRwYWdpbmF0aW9uLWRpc2FibGVkLWJnOiAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kcGFnaW5hdGlvbi1kaXNhYmxlZC1ib3JkZXI6ICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuXG5cbi8vPT0gUGFnZXJcbi8vXG4vLyMjXG5cbiRwYWdlci1iZzogICAgICAgICAgICAgICAgICAgICAgICAgICAgICRwYWdpbmF0aW9uLWJnICFkZWZhdWx0O1xuJHBhZ2VyLWJvcmRlcjogICAgICAgICAgICAgICAgICAgICAgICAgJHBhZ2luYXRpb24tYm9yZGVyICFkZWZhdWx0O1xuJHBhZ2VyLWJvcmRlci1yYWRpdXM6ICAgICAgICAgICAgICAgICAgMTVweCAhZGVmYXVsdDtcblxuJHBhZ2VyLWhvdmVyLWJnOiAgICAgICAgICAgICAgICAgICAgICAgJHBhZ2luYXRpb24taG92ZXItYmcgIWRlZmF1bHQ7XG5cbiRwYWdlci1hY3RpdmUtYmc6ICAgICAgICAgICAgICAgICAgICAgICRwYWdpbmF0aW9uLWFjdGl2ZS1iZyAhZGVmYXVsdDtcbiRwYWdlci1hY3RpdmUtY29sb3I6ICAgICAgICAgICAgICAgICAgICRwYWdpbmF0aW9uLWFjdGl2ZS1jb2xvciAhZGVmYXVsdDtcblxuJHBhZ2VyLWRpc2FibGVkLWNvbG9yOiAgICAgICAgICAgICAgICAgJHBhZ2luYXRpb24tZGlzYWJsZWQtY29sb3IgIWRlZmF1bHQ7XG5cblxuLy89PSBKdW1ib3Ryb25cbi8vXG4vLyMjXG5cbiRqdW1ib3Ryb24tcGFkZGluZzogICAgICAgICAgICAgIDMwcHggIWRlZmF1bHQ7XG4kanVtYm90cm9uLWNvbG9yOiAgICAgICAgICAgICAgICBpbmhlcml0ICFkZWZhdWx0O1xuJGp1bWJvdHJvbi1iZzogICAgICAgICAgICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbiRqdW1ib3Ryb24taGVhZGluZy1jb2xvcjogICAgICAgIGluaGVyaXQgIWRlZmF1bHQ7XG4kanVtYm90cm9uLWZvbnQtc2l6ZTogICAgICAgICAgICBjZWlsKCgkZm9udC1zaXplLWJhc2UgKiAxLjUpKSAhZGVmYXVsdDtcbiRqdW1ib3Ryb24taGVhZGluZy1mb250LXNpemU6ICAgIGNlaWwoKCRmb250LXNpemUtYmFzZSAqIDQuNSkpICFkZWZhdWx0O1xuXG5cbi8vPT0gRm9ybSBzdGF0ZXMgYW5kIGFsZXJ0c1xuLy9cbi8vIyMgRGVmaW5lIGNvbG9ycyBmb3IgZm9ybSBmZWVkYmFjayBzdGF0ZXMgYW5kLCBieSBkZWZhdWx0LCBhbGVydHMuXG5cbiRzdGF0ZS1zdWNjZXNzLXRleHQ6ICAgICAgICAgICAgICMzYzc2M2QgIWRlZmF1bHQ7XG4kc3RhdGUtc3VjY2Vzcy1iZzogICAgICAgICAgICAgICAjZGZmMGQ4ICFkZWZhdWx0O1xuJHN0YXRlLXN1Y2Nlc3MtYm9yZGVyOiAgICAgICAgICAgZGFya2VuKGFkanVzdC1odWUoJHN0YXRlLXN1Y2Nlc3MtYmcsIC0xMCksIDUlKSAhZGVmYXVsdDtcblxuJHN0YXRlLWluZm8tdGV4dDogICAgICAgICAgICAgICAgIzMxNzA4ZiAhZGVmYXVsdDtcbiRzdGF0ZS1pbmZvLWJnOiAgICAgICAgICAgICAgICAgICNkOWVkZjcgIWRlZmF1bHQ7XG4kc3RhdGUtaW5mby1ib3JkZXI6ICAgICAgICAgICAgICBkYXJrZW4oYWRqdXN0LWh1ZSgkc3RhdGUtaW5mby1iZywgLTEwKSwgNyUpICFkZWZhdWx0O1xuXG4kc3RhdGUtd2FybmluZy10ZXh0OiAgICAgICAgICAgICAjOGE2ZDNiICFkZWZhdWx0O1xuJHN0YXRlLXdhcm5pbmctYmc6ICAgICAgICAgICAgICAgI2ZjZjhlMyAhZGVmYXVsdDtcbiRzdGF0ZS13YXJuaW5nLWJvcmRlcjogICAgICAgICAgIGRhcmtlbihhZGp1c3QtaHVlKCRzdGF0ZS13YXJuaW5nLWJnLCAtMTApLCA1JSkgIWRlZmF1bHQ7XG5cbiRzdGF0ZS1kYW5nZXItdGV4dDogICAgICAgICAgICAgICNhOTQ0NDIgIWRlZmF1bHQ7XG4kc3RhdGUtZGFuZ2VyLWJnOiAgICAgICAgICAgICAgICAjZjJkZWRlICFkZWZhdWx0O1xuJHN0YXRlLWRhbmdlci1ib3JkZXI6ICAgICAgICAgICAgZGFya2VuKGFkanVzdC1odWUoJHN0YXRlLWRhbmdlci1iZywgLTEwKSwgNSUpICFkZWZhdWx0O1xuXG5cbi8vPT0gVG9vbHRpcHNcbi8vXG4vLyMjXG5cbi8vKiogVG9vbHRpcCBtYXggd2lkdGhcbiR0b29sdGlwLW1heC13aWR0aDogICAgICAgICAgIDIwMHB4ICFkZWZhdWx0O1xuLy8qKiBUb29sdGlwIHRleHQgY29sb3JcbiR0b29sdGlwLWNvbG9yOiAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIFRvb2x0aXAgYmFja2dyb3VuZCBjb2xvclxuJHRvb2x0aXAtYmc6ICAgICAgICAgICAgICAgICAgIzAwMCAhZGVmYXVsdDtcbiR0b29sdGlwLW9wYWNpdHk6ICAgICAgICAgICAgIC45ICFkZWZhdWx0O1xuXG4vLyoqIFRvb2x0aXAgYXJyb3cgd2lkdGhcbiR0b29sdGlwLWFycm93LXdpZHRoOiAgICAgICAgIDVweCAhZGVmYXVsdDtcbi8vKiogVG9vbHRpcCBhcnJvdyBjb2xvclxuJHRvb2x0aXAtYXJyb3ctY29sb3I6ICAgICAgICAgJHRvb2x0aXAtYmcgIWRlZmF1bHQ7XG5cblxuLy89PSBQb3BvdmVyc1xuLy9cbi8vIyNcblxuLy8qKiBQb3BvdmVyIGJvZHkgYmFja2dyb3VuZCBjb2xvclxuJHBvcG92ZXItYmc6ICAgICAgICAgICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBQb3BvdmVyIG1heGltdW0gd2lkdGhcbiRwb3BvdmVyLW1heC13aWR0aDogICAgICAgICAgICAgICAgICAgMjc2cHggIWRlZmF1bHQ7XG4vLyoqIFBvcG92ZXIgYm9yZGVyIGNvbG9yXG4kcG9wb3Zlci1ib3JkZXItY29sb3I6ICAgICAgICAgICAgICAgIHJnYmEoMCwwLDAsLjIpICFkZWZhdWx0O1xuLy8qKiBQb3BvdmVyIGZhbGxiYWNrIGJvcmRlciBjb2xvclxuJHBvcG92ZXItZmFsbGJhY2stYm9yZGVyLWNvbG9yOiAgICAgICAjY2NjICFkZWZhdWx0O1xuXG4vLyoqIFBvcG92ZXIgdGl0bGUgYmFja2dyb3VuZCBjb2xvclxuJHBvcG92ZXItdGl0bGUtYmc6ICAgICAgICAgICAgICAgICAgICBkYXJrZW4oJHBvcG92ZXItYmcsIDMlKSAhZGVmYXVsdDtcblxuLy8qKiBQb3BvdmVyIGFycm93IHdpZHRoXG4kcG9wb3Zlci1hcnJvdy13aWR0aDogICAgICAgICAgICAgICAgIDEwcHggIWRlZmF1bHQ7XG4vLyoqIFBvcG92ZXIgYXJyb3cgY29sb3JcbiRwb3BvdmVyLWFycm93LWNvbG9yOiAgICAgICAgICAgICAgICAgJHBvcG92ZXItYmcgIWRlZmF1bHQ7XG5cbi8vKiogUG9wb3ZlciBvdXRlciBhcnJvdyB3aWR0aFxuJHBvcG92ZXItYXJyb3ctb3V0ZXItd2lkdGg6ICAgICAgICAgICAoJHBvcG92ZXItYXJyb3ctd2lkdGggKyAxKSAhZGVmYXVsdDtcbi8vKiogUG9wb3ZlciBvdXRlciBhcnJvdyBjb2xvclxuJHBvcG92ZXItYXJyb3ctb3V0ZXItY29sb3I6ICAgICAgICAgICBmYWRlX2luKCRwb3BvdmVyLWJvcmRlci1jb2xvciwgMC4wNSkgIWRlZmF1bHQ7XG4vLyoqIFBvcG92ZXIgb3V0ZXIgYXJyb3cgZmFsbGJhY2sgY29sb3JcbiRwb3BvdmVyLWFycm93LW91dGVyLWZhbGxiYWNrLWNvbG9yOiAgZGFya2VuKCRwb3BvdmVyLWZhbGxiYWNrLWJvcmRlci1jb2xvciwgMjAlKSAhZGVmYXVsdDtcblxuXG4vLz09IExhYmVsc1xuLy9cbi8vIyNcblxuLy8qKiBEZWZhdWx0IGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC1kZWZhdWx0LWJnOiAgICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBQcmltYXJ5IGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC1wcmltYXJ5LWJnOiAgICAgICAgICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuLy8qKiBTdWNjZXNzIGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC1zdWNjZXNzLWJnOiAgICAgICAgICAgICRicmFuZC1zdWNjZXNzICFkZWZhdWx0O1xuLy8qKiBJbmZvIGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC1pbmZvLWJnOiAgICAgICAgICAgICAgICRicmFuZC1pbmZvICFkZWZhdWx0O1xuLy8qKiBXYXJuaW5nIGxhYmVsIGJhY2tncm91bmQgY29sb3JcbiRsYWJlbC13YXJuaW5nLWJnOiAgICAgICAgICAgICRicmFuZC13YXJuaW5nICFkZWZhdWx0O1xuLy8qKiBEYW5nZXIgbGFiZWwgYmFja2dyb3VuZCBjb2xvclxuJGxhYmVsLWRhbmdlci1iZzogICAgICAgICAgICAgJGJyYW5kLWRhbmdlciAhZGVmYXVsdDtcblxuLy8qKiBEZWZhdWx0IGxhYmVsIHRleHQgY29sb3JcbiRsYWJlbC1jb2xvcjogICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIERlZmF1bHQgdGV4dCBjb2xvciBvZiBhIGxpbmtlZCBsYWJlbFxuJGxhYmVsLWxpbmstaG92ZXItY29sb3I6ICAgICAgI2ZmZiAhZGVmYXVsdDtcblxuXG4vLz09IE1vZGFsc1xuLy9cbi8vIyNcblxuLy8qKiBQYWRkaW5nIGFwcGxpZWQgdG8gdGhlIG1vZGFsIGJvZHlcbiRtb2RhbC1pbm5lci1wYWRkaW5nOiAgICAgICAgIDE1cHggIWRlZmF1bHQ7XG5cbi8vKiogUGFkZGluZyBhcHBsaWVkIHRvIHRoZSBtb2RhbCB0aXRsZVxuJG1vZGFsLXRpdGxlLXBhZGRpbmc6ICAgICAgICAgMTVweCAhZGVmYXVsdDtcbi8vKiogTW9kYWwgdGl0bGUgbGluZS1oZWlnaHRcbiRtb2RhbC10aXRsZS1saW5lLWhlaWdodDogICAgICRsaW5lLWhlaWdodC1iYXNlICFkZWZhdWx0O1xuXG4vLyoqIEJhY2tncm91bmQgY29sb3Igb2YgbW9kYWwgY29udGVudCBhcmVhXG4kbW9kYWwtY29udGVudC1iZzogICAgICAgICAgICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIE1vZGFsIGNvbnRlbnQgYm9yZGVyIGNvbG9yXG4kbW9kYWwtY29udGVudC1ib3JkZXItY29sb3I6ICAgICAgICAgICAgICAgICAgIHJnYmEoMCwwLDAsLjIpICFkZWZhdWx0O1xuLy8qKiBNb2RhbCBjb250ZW50IGJvcmRlciBjb2xvciAqKmZvciBJRTgqKlxuJG1vZGFsLWNvbnRlbnQtZmFsbGJhY2stYm9yZGVyLWNvbG9yOiAgICAgICAgICAjOTk5ICFkZWZhdWx0O1xuXG4vLyoqIE1vZGFsIGJhY2tkcm9wIGJhY2tncm91bmQgY29sb3JcbiRtb2RhbC1iYWNrZHJvcC1iZzogICAgICAgICAgICMwMDAgIWRlZmF1bHQ7XG4vLyoqIE1vZGFsIGJhY2tkcm9wIG9wYWNpdHlcbiRtb2RhbC1iYWNrZHJvcC1vcGFjaXR5OiAgICAgIC41ICFkZWZhdWx0O1xuLy8qKiBNb2RhbCBoZWFkZXIgYm9yZGVyIGNvbG9yXG4kbW9kYWwtaGVhZGVyLWJvcmRlci1jb2xvcjogICAjZTVlNWU1ICFkZWZhdWx0O1xuLy8qKiBNb2RhbCBmb290ZXIgYm9yZGVyIGNvbG9yXG4kbW9kYWwtZm9vdGVyLWJvcmRlci1jb2xvcjogICAkbW9kYWwtaGVhZGVyLWJvcmRlci1jb2xvciAhZGVmYXVsdDtcblxuJG1vZGFsLWxnOiAgICAgICAgICAgICAgICAgICAgOTAwcHggIWRlZmF1bHQ7XG4kbW9kYWwtbWQ6ICAgICAgICAgICAgICAgICAgICA2MDBweCAhZGVmYXVsdDtcbiRtb2RhbC1zbTogICAgICAgICAgICAgICAgICAgIDMwMHB4ICFkZWZhdWx0O1xuXG5cbi8vPT0gQWxlcnRzXG4vL1xuLy8jIyBEZWZpbmUgYWxlcnQgY29sb3JzLCBib3JkZXIgcmFkaXVzLCBhbmQgcGFkZGluZy5cblxuJGFsZXJ0LXBhZGRpbmc6ICAgICAgICAgICAgICAgMTVweCAhZGVmYXVsdDtcbiRhbGVydC1ib3JkZXItcmFkaXVzOiAgICAgICAgICRib3JkZXItcmFkaXVzLWJhc2UgIWRlZmF1bHQ7XG4kYWxlcnQtbGluay1mb250LXdlaWdodDogICAgICBib2xkICFkZWZhdWx0O1xuXG4kYWxlcnQtc3VjY2Vzcy1iZzogICAgICAgICAgICAkc3RhdGUtc3VjY2Vzcy1iZyAhZGVmYXVsdDtcbiRhbGVydC1zdWNjZXNzLXRleHQ6ICAgICAgICAgICRzdGF0ZS1zdWNjZXNzLXRleHQgIWRlZmF1bHQ7XG4kYWxlcnQtc3VjY2Vzcy1ib3JkZXI6ICAgICAgICAkc3RhdGUtc3VjY2Vzcy1ib3JkZXIgIWRlZmF1bHQ7XG5cbiRhbGVydC1pbmZvLWJnOiAgICAgICAgICAgICAgICRzdGF0ZS1pbmZvLWJnICFkZWZhdWx0O1xuJGFsZXJ0LWluZm8tdGV4dDogICAgICAgICAgICAgJHN0YXRlLWluZm8tdGV4dCAhZGVmYXVsdDtcbiRhbGVydC1pbmZvLWJvcmRlcjogICAgICAgICAgICRzdGF0ZS1pbmZvLWJvcmRlciAhZGVmYXVsdDtcblxuJGFsZXJ0LXdhcm5pbmctYmc6ICAgICAgICAgICAgJHN0YXRlLXdhcm5pbmctYmcgIWRlZmF1bHQ7XG4kYWxlcnQtd2FybmluZy10ZXh0OiAgICAgICAgICAkc3RhdGUtd2FybmluZy10ZXh0ICFkZWZhdWx0O1xuJGFsZXJ0LXdhcm5pbmctYm9yZGVyOiAgICAgICAgJHN0YXRlLXdhcm5pbmctYm9yZGVyICFkZWZhdWx0O1xuXG4kYWxlcnQtZGFuZ2VyLWJnOiAgICAgICAgICAgICAkc3RhdGUtZGFuZ2VyLWJnICFkZWZhdWx0O1xuJGFsZXJ0LWRhbmdlci10ZXh0OiAgICAgICAgICAgJHN0YXRlLWRhbmdlci10ZXh0ICFkZWZhdWx0O1xuJGFsZXJ0LWRhbmdlci1ib3JkZXI6ICAgICAgICAgJHN0YXRlLWRhbmdlci1ib3JkZXIgIWRlZmF1bHQ7XG5cblxuLy89PSBQcm9ncmVzcyBiYXJzXG4vL1xuLy8jI1xuXG4vLyoqIEJhY2tncm91bmQgY29sb3Igb2YgdGhlIHdob2xlIHByb2dyZXNzIGNvbXBvbmVudFxuJHByb2dyZXNzLWJnOiAgICAgICAgICAgICAgICAgI2Y1ZjVmNSAhZGVmYXVsdDtcbi8vKiogUHJvZ3Jlc3MgYmFyIHRleHQgY29sb3JcbiRwcm9ncmVzcy1iYXItY29sb3I6ICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4vLyoqIFZhcmlhYmxlIGZvciBzZXR0aW5nIHJvdW5kZWQgY29ybmVycyBvbiBwcm9ncmVzcyBiYXIuXG4kcHJvZ3Jlc3MtYm9yZGVyLXJhZGl1czogICAgICAkYm9yZGVyLXJhZGl1cy1iYXNlICFkZWZhdWx0O1xuXG4vLyoqIERlZmF1bHQgcHJvZ3Jlc3MgYmFyIGNvbG9yXG4kcHJvZ3Jlc3MtYmFyLWJnOiAgICAgICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcbi8vKiogU3VjY2VzcyBwcm9ncmVzcyBiYXIgY29sb3JcbiRwcm9ncmVzcy1iYXItc3VjY2Vzcy1iZzogICAgICRicmFuZC1zdWNjZXNzICFkZWZhdWx0O1xuLy8qKiBXYXJuaW5nIHByb2dyZXNzIGJhciBjb2xvclxuJHByb2dyZXNzLWJhci13YXJuaW5nLWJnOiAgICAgJGJyYW5kLXdhcm5pbmcgIWRlZmF1bHQ7XG4vLyoqIERhbmdlciBwcm9ncmVzcyBiYXIgY29sb3JcbiRwcm9ncmVzcy1iYXItZGFuZ2VyLWJnOiAgICAgICRicmFuZC1kYW5nZXIgIWRlZmF1bHQ7XG4vLyoqIEluZm8gcHJvZ3Jlc3MgYmFyIGNvbG9yXG4kcHJvZ3Jlc3MtYmFyLWluZm8tYmc6ICAgICAgICAkYnJhbmQtaW5mbyAhZGVmYXVsdDtcblxuXG4vLz09IExpc3QgZ3JvdXBcbi8vXG4vLyMjXG5cbi8vKiogQmFja2dyb3VuZCBjb2xvciBvbiBgLmxpc3QtZ3JvdXAtaXRlbWBcbiRsaXN0LWdyb3VwLWJnOiAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbi8vKiogYC5saXN0LWdyb3VwLWl0ZW1gIGJvcmRlciBjb2xvclxuJGxpc3QtZ3JvdXAtYm9yZGVyOiAgICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuLy8qKiBMaXN0IGdyb3VwIGJvcmRlciByYWRpdXNcbiRsaXN0LWdyb3VwLWJvcmRlci1yYWRpdXM6ICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcblxuLy8qKiBCYWNrZ3JvdW5kIGNvbG9yIG9mIHNpbmdsZSBsaXN0IGl0ZW1zIG9uIGhvdmVyXG4kbGlzdC1ncm91cC1ob3Zlci1iZzogICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG4vLyoqIFRleHQgY29sb3Igb2YgYWN0aXZlIGxpc3QgaXRlbXNcbiRsaXN0LWdyb3VwLWFjdGl2ZS1jb2xvcjogICAgICAgJGNvbXBvbmVudC1hY3RpdmUtY29sb3IgIWRlZmF1bHQ7XG4vLyoqIEJhY2tncm91bmQgY29sb3Igb2YgYWN0aXZlIGxpc3QgaXRlbXNcbiRsaXN0LWdyb3VwLWFjdGl2ZS1iZzogICAgICAgICAgJGNvbXBvbmVudC1hY3RpdmUtYmcgIWRlZmF1bHQ7XG4vLyoqIEJvcmRlciBjb2xvciBvZiBhY3RpdmUgbGlzdCBlbGVtZW50c1xuJGxpc3QtZ3JvdXAtYWN0aXZlLWJvcmRlcjogICAgICAkbGlzdC1ncm91cC1hY3RpdmUtYmcgIWRlZmF1bHQ7XG4vLyoqIFRleHQgY29sb3IgZm9yIGNvbnRlbnQgd2l0aGluIGFjdGl2ZSBsaXN0IGl0ZW1zXG4kbGlzdC1ncm91cC1hY3RpdmUtdGV4dC1jb2xvcjogIGxpZ2h0ZW4oJGxpc3QtZ3JvdXAtYWN0aXZlLWJnLCA0MCUpICFkZWZhdWx0O1xuXG4vLyoqIFRleHQgY29sb3Igb2YgZGlzYWJsZWQgbGlzdCBpdGVtc1xuJGxpc3QtZ3JvdXAtZGlzYWJsZWQtY29sb3I6ICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG4vLyoqIEJhY2tncm91bmQgY29sb3Igb2YgZGlzYWJsZWQgbGlzdCBpdGVtc1xuJGxpc3QtZ3JvdXAtZGlzYWJsZWQtYmc6ICAgICAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbi8vKiogVGV4dCBjb2xvciBmb3IgY29udGVudCB3aXRoaW4gZGlzYWJsZWQgbGlzdCBpdGVtc1xuJGxpc3QtZ3JvdXAtZGlzYWJsZWQtdGV4dC1jb2xvcjogJGxpc3QtZ3JvdXAtZGlzYWJsZWQtY29sb3IgIWRlZmF1bHQ7XG5cbiRsaXN0LWdyb3VwLWxpbmstY29sb3I6ICAgICAgICAgIzU1NSAhZGVmYXVsdDtcbiRsaXN0LWdyb3VwLWxpbmstaG92ZXItY29sb3I6ICAgJGxpc3QtZ3JvdXAtbGluay1jb2xvciAhZGVmYXVsdDtcbiRsaXN0LWdyb3VwLWxpbmstaGVhZGluZy1jb2xvcjogIzMzMyAhZGVmYXVsdDtcblxuXG4vLz09IFBhbmVsc1xuLy9cbi8vIyNcblxuJHBhbmVsLWJnOiAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRwYW5lbC1ib2R5LXBhZGRpbmc6ICAgICAgICAgIDE1cHggIWRlZmF1bHQ7XG4kcGFuZWwtaGVhZGluZy1wYWRkaW5nOiAgICAgICAxMHB4IDE1cHggIWRlZmF1bHQ7XG4kcGFuZWwtZm9vdGVyLXBhZGRpbmc6ICAgICAgICAkcGFuZWwtaGVhZGluZy1wYWRkaW5nICFkZWZhdWx0O1xuJHBhbmVsLWJvcmRlci1yYWRpdXM6ICAgICAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcblxuLy8qKiBCb3JkZXIgY29sb3IgZm9yIGVsZW1lbnRzIHdpdGhpbiBwYW5lbHNcbiRwYW5lbC1pbm5lci1ib3JkZXI6ICAgICAgICAgICNkZGQgIWRlZmF1bHQ7XG4kcGFuZWwtZm9vdGVyLWJnOiAgICAgICAgICAgICAjZjVmNWY1ICFkZWZhdWx0O1xuXG4kcGFuZWwtZGVmYXVsdC10ZXh0OiAgICAgICAgICAkZ3JheS1kYXJrICFkZWZhdWx0O1xuJHBhbmVsLWRlZmF1bHQtYm9yZGVyOiAgICAgICAgI2RkZCAhZGVmYXVsdDtcbiRwYW5lbC1kZWZhdWx0LWhlYWRpbmctYmc6ICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG5cbiRwYW5lbC1wcmltYXJ5LXRleHQ6ICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kcGFuZWwtcHJpbWFyeS1ib3JkZXI6ICAgICAgICAkYnJhbmQtcHJpbWFyeSAhZGVmYXVsdDtcbiRwYW5lbC1wcmltYXJ5LWhlYWRpbmctYmc6ICAgICRicmFuZC1wcmltYXJ5ICFkZWZhdWx0O1xuXG4kcGFuZWwtc3VjY2Vzcy10ZXh0OiAgICAgICAgICAkc3RhdGUtc3VjY2Vzcy10ZXh0ICFkZWZhdWx0O1xuJHBhbmVsLXN1Y2Nlc3MtYm9yZGVyOiAgICAgICAgJHN0YXRlLXN1Y2Nlc3MtYm9yZGVyICFkZWZhdWx0O1xuJHBhbmVsLXN1Y2Nlc3MtaGVhZGluZy1iZzogICAgJHN0YXRlLXN1Y2Nlc3MtYmcgIWRlZmF1bHQ7XG5cbiRwYW5lbC1pbmZvLXRleHQ6ICAgICAgICAgICAgICRzdGF0ZS1pbmZvLXRleHQgIWRlZmF1bHQ7XG4kcGFuZWwtaW5mby1ib3JkZXI6ICAgICAgICAgICAkc3RhdGUtaW5mby1ib3JkZXIgIWRlZmF1bHQ7XG4kcGFuZWwtaW5mby1oZWFkaW5nLWJnOiAgICAgICAkc3RhdGUtaW5mby1iZyAhZGVmYXVsdDtcblxuJHBhbmVsLXdhcm5pbmctdGV4dDogICAgICAgICAgJHN0YXRlLXdhcm5pbmctdGV4dCAhZGVmYXVsdDtcbiRwYW5lbC13YXJuaW5nLWJvcmRlcjogICAgICAgICRzdGF0ZS13YXJuaW5nLWJvcmRlciAhZGVmYXVsdDtcbiRwYW5lbC13YXJuaW5nLWhlYWRpbmctYmc6ICAgICRzdGF0ZS13YXJuaW5nLWJnICFkZWZhdWx0O1xuXG4kcGFuZWwtZGFuZ2VyLXRleHQ6ICAgICAgICAgICAkc3RhdGUtZGFuZ2VyLXRleHQgIWRlZmF1bHQ7XG4kcGFuZWwtZGFuZ2VyLWJvcmRlcjogICAgICAgICAkc3RhdGUtZGFuZ2VyLWJvcmRlciAhZGVmYXVsdDtcbiRwYW5lbC1kYW5nZXItaGVhZGluZy1iZzogICAgICRzdGF0ZS1kYW5nZXItYmcgIWRlZmF1bHQ7XG5cblxuLy89PSBUaHVtYm5haWxzXG4vL1xuLy8jI1xuXG4vLyoqIFBhZGRpbmcgYXJvdW5kIHRoZSB0aHVtYm5haWwgaW1hZ2VcbiR0aHVtYm5haWwtcGFkZGluZzogICAgICAgICAgIDRweCAhZGVmYXVsdDtcbi8vKiogVGh1bWJuYWlsIGJhY2tncm91bmQgY29sb3JcbiR0aHVtYm5haWwtYmc6ICAgICAgICAgICAgICAgICRib2R5LWJnICFkZWZhdWx0O1xuLy8qKiBUaHVtYm5haWwgYm9yZGVyIGNvbG9yXG4kdGh1bWJuYWlsLWJvcmRlcjogICAgICAgICAgICAjZGRkICFkZWZhdWx0O1xuLy8qKiBUaHVtYm5haWwgYm9yZGVyIHJhZGl1c1xuJHRodW1ibmFpbC1ib3JkZXItcmFkaXVzOiAgICAgJGJvcmRlci1yYWRpdXMtYmFzZSAhZGVmYXVsdDtcblxuLy8qKiBDdXN0b20gdGV4dCBjb2xvciBmb3IgdGh1bWJuYWlsIGNhcHRpb25zXG4kdGh1bWJuYWlsLWNhcHRpb24tY29sb3I6ICAgICAkdGV4dC1jb2xvciAhZGVmYXVsdDtcbi8vKiogUGFkZGluZyBhcm91bmQgdGhlIHRodW1ibmFpbCBjYXB0aW9uXG4kdGh1bWJuYWlsLWNhcHRpb24tcGFkZGluZzogICA5cHggIWRlZmF1bHQ7XG5cblxuLy89PSBXZWxsc1xuLy9cbi8vIyNcblxuJHdlbGwtYmc6ICAgICAgICAgICAgICAgICAgICAgI2Y1ZjVmNSAhZGVmYXVsdDtcbiR3ZWxsLWJvcmRlcjogICAgICAgICAgICAgICAgIGRhcmtlbigkd2VsbC1iZywgNyUpICFkZWZhdWx0O1xuXG5cbi8vPT0gQmFkZ2VzXG4vL1xuLy8jI1xuXG4kYmFkZ2UtY29sb3I6ICAgICAgICAgICAgICAgICAjZmZmICFkZWZhdWx0O1xuLy8qKiBMaW5rZWQgYmFkZ2UgdGV4dCBjb2xvciBvbiBob3ZlclxuJGJhZGdlLWxpbmstaG92ZXItY29sb3I6ICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRiYWRnZS1iZzogICAgICAgICAgICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuXG4vLyoqIEJhZGdlIHRleHQgY29sb3IgaW4gYWN0aXZlIG5hdiBsaW5rXG4kYmFkZ2UtYWN0aXZlLWNvbG9yOiAgICAgICAgICAkbGluay1jb2xvciAhZGVmYXVsdDtcbi8vKiogQmFkZ2UgYmFja2dyb3VuZCBjb2xvciBpbiBhY3RpdmUgbmF2IGxpbmtcbiRiYWRnZS1hY3RpdmUtYmc6ICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG5cbiRiYWRnZS1mb250LXdlaWdodDogICAgICAgICAgIGJvbGQgIWRlZmF1bHQ7XG4kYmFkZ2UtbGluZS1oZWlnaHQ6ICAgICAgICAgICAxICFkZWZhdWx0O1xuJGJhZGdlLWJvcmRlci1yYWRpdXM6ICAgICAgICAgMTBweCAhZGVmYXVsdDtcblxuXG4vLz09IEJyZWFkY3J1bWJzXG4vL1xuLy8jI1xuXG4kYnJlYWRjcnVtYi1wYWRkaW5nLXZlcnRpY2FsOiAgIDhweCAhZGVmYXVsdDtcbiRicmVhZGNydW1iLXBhZGRpbmctaG9yaXpvbnRhbDogMTVweCAhZGVmYXVsdDtcbi8vKiogQnJlYWRjcnVtYiBiYWNrZ3JvdW5kIGNvbG9yXG4kYnJlYWRjcnVtYi1iZzogICAgICAgICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG4vLyoqIEJyZWFkY3J1bWIgdGV4dCBjb2xvclxuJGJyZWFkY3J1bWItY29sb3I6ICAgICAgICAgICAgICAjY2NjICFkZWZhdWx0O1xuLy8qKiBUZXh0IGNvbG9yIG9mIGN1cnJlbnQgcGFnZSBpbiB0aGUgYnJlYWRjcnVtYlxuJGJyZWFkY3J1bWItYWN0aXZlLWNvbG9yOiAgICAgICAkZ3JheS1saWdodCAhZGVmYXVsdDtcbi8vKiogVGV4dHVhbCBzZXBhcmF0b3IgZm9yIGJldHdlZW4gYnJlYWRjcnVtYiBlbGVtZW50c1xuJGJyZWFkY3J1bWItc2VwYXJhdG9yOiAgICAgICAgICBcIi9cIiAhZGVmYXVsdDtcblxuXG4vLz09IENhcm91c2VsXG4vL1xuLy8jI1xuXG4kY2Fyb3VzZWwtdGV4dC1zaGFkb3c6ICAgICAgICAgICAgICAgICAgICAgICAgMCAxcHggMnB4IHJnYmEoMCwwLDAsLjYpICFkZWZhdWx0O1xuXG4kY2Fyb3VzZWwtY29udHJvbC1jb2xvcjogICAgICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRjYXJvdXNlbC1jb250cm9sLXdpZHRoOiAgICAgICAgICAgICAgICAgICAgICAxNSUgIWRlZmF1bHQ7XG4kY2Fyb3VzZWwtY29udHJvbC1vcGFjaXR5OiAgICAgICAgICAgICAgICAgICAgLjUgIWRlZmF1bHQ7XG4kY2Fyb3VzZWwtY29udHJvbC1mb250LXNpemU6ICAgICAgICAgICAgICAgICAgMjBweCAhZGVmYXVsdDtcblxuJGNhcm91c2VsLWluZGljYXRvci1hY3RpdmUtYmc6ICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG4kY2Fyb3VzZWwtaW5kaWNhdG9yLWJvcmRlci1jb2xvcjogICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcblxuJGNhcm91c2VsLWNhcHRpb24tY29sb3I6ICAgICAgICAgICAgICAgICAgICAgICNmZmYgIWRlZmF1bHQ7XG5cblxuLy89PSBDbG9zZVxuLy9cbi8vIyNcblxuJGNsb3NlLWZvbnQtd2VpZ2h0OiAgICAgICAgICAgYm9sZCAhZGVmYXVsdDtcbiRjbG9zZS1jb2xvcjogICAgICAgICAgICAgICAgICMwMDAgIWRlZmF1bHQ7XG4kY2xvc2UtdGV4dC1zaGFkb3c6ICAgICAgICAgICAwIDFweCAwICNmZmYgIWRlZmF1bHQ7XG5cblxuLy89PSBDb2RlXG4vL1xuLy8jI1xuXG4kY29kZS1jb2xvcjogICAgICAgICAgICAgICAgICAjYzcyNTRlICFkZWZhdWx0O1xuJGNvZGUtYmc6ICAgICAgICAgICAgICAgICAgICAgI2Y5ZjJmNCAhZGVmYXVsdDtcblxuJGtiZC1jb2xvcjogICAgICAgICAgICAgICAgICAgI2ZmZiAhZGVmYXVsdDtcbiRrYmQtYmc6ICAgICAgICAgICAgICAgICAgICAgICMzMzMgIWRlZmF1bHQ7XG5cbiRwcmUtYmc6ICAgICAgICAgICAgICAgICAgICAgICNmNWY1ZjUgIWRlZmF1bHQ7XG4kcHJlLWNvbG9yOiAgICAgICAgICAgICAgICAgICAkZ3JheS1kYXJrICFkZWZhdWx0O1xuJHByZS1ib3JkZXItY29sb3I6ICAgICAgICAgICAgI2NjYyAhZGVmYXVsdDtcbiRwcmUtc2Nyb2xsYWJsZS1tYXgtaGVpZ2h0OiAgIDM0MHB4ICFkZWZhdWx0O1xuXG5cbi8vPT0gVHlwZVxuLy9cbi8vIyNcblxuLy8qKiBIb3Jpem9udGFsIG9mZnNldCBmb3IgZm9ybXMgYW5kIGxpc3RzLlxuJGNvbXBvbmVudC1vZmZzZXQtaG9yaXpvbnRhbDogMTgwcHggIWRlZmF1bHQ7XG4vLyoqIFRleHQgbXV0ZWQgY29sb3JcbiR0ZXh0LW11dGVkOiAgICAgICAgICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBBYmJyZXZpYXRpb25zIGFuZCBhY3JvbnltcyBib3JkZXIgY29sb3JcbiRhYmJyLWJvcmRlci1jb2xvcjogICAgICAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBIZWFkaW5ncyBzbWFsbCBjb2xvclxuJGhlYWRpbmdzLXNtYWxsLWNvbG9yOiAgICAgICAgJGdyYXktbGlnaHQgIWRlZmF1bHQ7XG4vLyoqIEJsb2NrcXVvdGUgc21hbGwgY29sb3JcbiRibG9ja3F1b3RlLXNtYWxsLWNvbG9yOiAgICAgICRncmF5LWxpZ2h0ICFkZWZhdWx0O1xuLy8qKiBCbG9ja3F1b3RlIGZvbnQgc2l6ZVxuJGJsb2NrcXVvdGUtZm9udC1zaXplOiAgICAgICAgKCRmb250LXNpemUtYmFzZSAqIDEuMjUpICFkZWZhdWx0O1xuLy8qKiBCbG9ja3F1b3RlIGJvcmRlciBjb2xvclxuJGJsb2NrcXVvdGUtYm9yZGVyLWNvbG9yOiAgICAgJGdyYXktbGlnaHRlciAhZGVmYXVsdDtcbi8vKiogUGFnZSBoZWFkZXIgYm9yZGVyIGNvbG9yXG4kcGFnZS1oZWFkZXItYm9yZGVyLWNvbG9yOiAgICAkZ3JheS1saWdodGVyICFkZWZhdWx0O1xuLy8qKiBXaWR0aCBvZiBob3Jpem9udGFsIGRlc2NyaXB0aW9uIGxpc3QgdGl0bGVzXG4kZGwtaG9yaXpvbnRhbC1vZmZzZXQ6ICAgICAgICAkY29tcG9uZW50LW9mZnNldC1ob3Jpem9udGFsICFkZWZhdWx0O1xuLy8qKiBQb2ludCBhdCB3aGljaCAuZGwtaG9yaXpvbnRhbCBiZWNvbWVzIGhvcml6b250YWxcbiRkbC1ob3Jpem9udGFsLWJyZWFrcG9pbnQ6ICAgICRncmlkLWZsb2F0LWJyZWFrcG9pbnQgIWRlZmF1bHQ7XG4vLyoqIEhvcml6b250YWwgbGluZSBjb2xvci5cbiRoci1ib3JkZXI6ICAgICAgICAgICAgICAgICAgICRncmF5LWxpZ2h0ZXIgIWRlZmF1bHQ7XG4iLCJAaW1wb3J0ICcuLi8uLi8uLi9zdHlsZXMvYW5pbWF0aW9ucy5zY3NzJztcblxueG9zLXRhYmxlIHtcblxuICBkaXNwbGF5OiBibG9jaztcblxuICB0ci5uZy1tb3ZlLFxuICB0ci5uZy1lbnRlcixcbiAgdHIubmctbGVhdmUge1xuICAgIHRyYW5zaXRpb246YWxsIGxpbmVhciAwLjVzO1xuICB9XG5cbiAgdHIubmctbGVhdmUubmctbGVhdmUtYWN0aXZlLFxuICB0ci5uZy1tb3ZlLFxuICB0ci5uZy1lbnRlciB7XG4gICAgb3BhY2l0eTowO1xuICAgIGFuaW1hdGlvbjogMC41cyBzbGlkZU91dFJpZ2h0IGVhc2UtaW4tb3V0O1xuICB9XG5cbiAgdHIubmctbGVhdmUsXG4gIHRyLm5nLW1vdmUubmctbW92ZS1hY3RpdmUsXG4gIHRyLm5nLWVudGVyLm5nLWVudGVyLWFjdGl2ZSB7XG4gICAgb3BhY2l0eToxO1xuICAgIGFuaW1hdGlvbjogMC41cyBzbGlkZUluUmlnaHQgZWFzZS1pbi1vdXQ7XG4gIH1cblxuICB0ZCBkbCB7XG4gICAgbWFyZ2luLWJvdHRvbTogMDtcblxuICAgIGR0IHtcbiAgICAgIHdpZHRoOiBhdXRvICFpbXBvcnRhbnQ7XG4gICAgICBtYXJnaW4tcmlnaHQ6IDEwcHg7XG4gICAgfVxuICAgIFxuICAgIGR0OmFmdGVyIHtcbiAgICAgIC8qZGlzcGxheTogYmxvY2s7Ki9cbiAgICAgIGNvbnRlbnQ6ICc6JztcbiAgICB9XG5cbiAgICBkZCB7XG4gICAgICBtYXJnaW4tbGVmdDogMCAhaW1wb3J0YW50O1xuICAgIH1cbiAgfVxufSIsIkBpbXBvcnQgJy4uLy4uLy4uL3N0eWxlcy9hbmltYXRpb25zLnNjc3MnO1xuXG54b3MtYWxlcnQge1xuXG4gIC8qIHdoZW4gaGlkaW5nICovXG4gIC5uZy1oaWRlLWFkZCAgICAgICAgIHsgYW5pbWF0aW9uOjAuNXMgZmFkZU91dERvd24gZWFzZS1pbi1vdXQ7IH1cblxuICAvKiB3aGVuIHNob3dpbmcgKi9cbiAgLm5nLWhpZGUtcmVtb3ZlICAgICAgeyBhbmltYXRpb246MC41cyBmYWRlSW5VcCBlYXNlLWluLW91dDsgfVxufSIsIkBpbXBvcnQgJy4uLy4uLy4uL3N0eWxlcy9hbmltYXRpb25zLnNjc3MnO1xuQGltcG9ydCAnLi4vLi4vLi4vLi4vLi4vLi4vc3R5bGUvc2Fzcy9ib290c3RyYXAvYm9vdHN0cmFwL192YXJpYWJsZXMuc2Nzcyc7XG5cbmlucHV0ICsgeG9zLXZhbGlkYXRpb24ge1xuICBtYXJnaW4tdG9wOiAkZm9ybS1ncm91cC1tYXJnaW4tYm90dG9tO1xuICBkaXNwbGF5OiBibG9jaztcbn0iLCJ4b3Mtc21hcnQtdGFibGV7XG4gIFxufSJdLCJtYXBwaW5ncyI6IkFDQUEsVUFBVSxDQUFDLEFBQUEsWUFBWTtFQUNyQixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsdUJBQVc7SUFDdEIsVUFBVSxFQUFFLE9BQVE7RUFHdEIsQUFBQSxFQUFFO0lBQ0EsU0FBUyxFQUFFLG9CQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxhQUFhO0VBQ3RCLEFBQUEsSUFBSTtJQUNGLFNBQVMsRUFBRSxvQkFBVztFQUd4QixBQUFBLEVBQUU7SUFDQSxVQUFVLEVBQUUsTUFBTztJQUNuQixTQUFTLEVBQUUsdUJBQVc7O0FBSTFCLFVBQVUsQ0FBQyxBQUFBLFFBQVE7RUFDakIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsdUJBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsSUFBSzs7QUFJcEIsVUFBVSxDQUFDLEFBQUEsV0FBVztFQUNwQixBQUFBLElBQUk7SUFDRixPQUFPLEVBQUUsQ0FBRTtFQUdiLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXOztBQXpDMUIsVUFBVSxDQUFDLEFBQUEsWUFBWTtFQUNyQixBQUFBLElBQUk7SUFDRixTQUFTLEVBQUUsdUJBQVc7SUFDdEIsVUFBVSxFQUFFLE9BQVE7RUFHdEIsQUFBQSxFQUFFO0lBQ0EsU0FBUyxFQUFFLG9CQUFXOztBQUkxQixVQUFVLENBQUMsQUFBQSxhQUFhO0VBQ3RCLEFBQUEsSUFBSTtJQUNGLFNBQVMsRUFBRSxvQkFBVztFQUd4QixBQUFBLEVBQUU7SUFDQSxVQUFVLEVBQUUsTUFBTztJQUNuQixTQUFTLEVBQUUsdUJBQVc7O0FBSTFCLFVBQVUsQ0FBQyxBQUFBLFFBQVE7RUFDakIsQUFBQSxJQUFJO0lBQ0YsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsdUJBQVc7RUFHeEIsQUFBQSxFQUFFO0lBQ0EsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsSUFBSzs7QUFJcEIsVUFBVSxDQUFDLEFBQUEsV0FBVztFQUNwQixBQUFBLElBQUk7SUFDRixPQUFPLEVBQUUsQ0FBRTtFQUdiLEFBQUEsRUFBRTtJQUNBLE9BQU8sRUFBRSxDQUFFO0lBQ1gsU0FBUyxFQUFFLHVCQUFXOztBRXZDMUIsQUFBQSxTQUFTLENBQUM7RUFFUixPQUFPLEVBQUUsS0FBTSxHQXVDaEI7RUF6Q0QsQUFJSSxTQUpLLENBSVAsRUFBRSxBQUFBLFFBQVE7RUFKWixBQUtJLFNBTEssQ0FLUCxFQUFFLEFBQUEsU0FBUztFQUxiLEFBTUksU0FOSyxDQU1QLEVBQUUsQUFBQSxTQUFTLENBQUM7SUFDVixVQUFVLEVBQUMsZUFBZ0IsR0FDNUI7RUFSSCxBQVVhLFNBVkosQ0FVUCxFQUFFLEFBQUEsU0FBUyxBQUFBLGdCQUFnQjtFQVY3QixBQVdJLFNBWEssQ0FXUCxFQUFFLEFBQUEsUUFBUTtFQVhaLEFBWUksU0FaSyxDQVlQLEVBQUUsQUFBQSxTQUFTLENBQUM7SUFDVixPQUFPLEVBQUMsQ0FBRTtJQUNWLFNBQVMsRUFBRSw4QkFBK0IsR0FDM0M7RUFmSCxBQWlCSSxTQWpCSyxDQWlCUCxFQUFFLEFBQUEsU0FBUztFQWpCYixBQWtCWSxTQWxCSCxDQWtCUCxFQUFFLEFBQUEsUUFBUSxBQUFBLGVBQWU7RUFsQjNCLEFBbUJhLFNBbkJKLENBbUJQLEVBQUUsQUFBQSxTQUFTLEFBQUEsZ0JBQWdCLENBQUM7SUFDMUIsT0FBTyxFQUFDLENBQUU7SUFDVixTQUFTLEVBQUUsNkJBQThCLEdBQzFDO0VBdEJILEFBd0JLLFNBeEJJLENBd0JQLEVBQUUsQ0FBQyxFQUFFLENBQUM7SUFDSixhQUFhLEVBQUUsQ0FBRSxHQWVsQjtJQXhDSCxBQTJCSSxTQTNCSyxDQXdCUCxFQUFFLENBQUMsRUFBRSxDQUdILEVBQUUsQ0FBQztNQUNELEtBQUssRUFBRSxlQUFnQjtNQUN2QixZQUFZLEVBQUUsSUFBSyxHQUNwQjtJQTlCTCxBQWdDTSxTQWhDRyxDQXdCUCxFQUFFLENBQUMsRUFBRSxDQVFILEVBQUUsQUFBQSxNQUFNLENBQUM7TUFDUCxtQkFBbUI7TUFDbkIsT0FBTyxFQUFFLEdBQUksR0FDZDtJQW5DTCxBQXFDSSxTQXJDSyxDQXdCUCxFQUFFLENBQUMsRUFBRSxDQWFILEVBQUUsQ0FBQztNQUNELFdBQVcsRUFBRSxZQUFhLEdBQzNCOztBRnpDTCxVQUFVLENBQUMsQUFBQSxZQUFZO0VBQ3JCLEFBQUEsSUFBSTtJQUNGLFNBQVMsRUFBRSx1QkFBVztJQUN0QixVQUFVLEVBQUUsT0FBUTtFQUd0QixBQUFBLEVBQUU7SUFDQSxTQUFTLEVBQUUsb0JBQVc7O0FBSTFCLFVBQVUsQ0FBQyxBQUFBLGFBQWE7RUFDdEIsQUFBQSxJQUFJO0lBQ0YsU0FBUyxFQUFFLG9CQUFXO0VBR3hCLEFBQUEsRUFBRTtJQUNBLFVBQVUsRUFBRSxNQUFPO0lBQ25CLFNBQVMsRUFBRSx1QkFBVzs7QUFJMUIsVUFBVSxDQUFDLEFBQUEsUUFBUTtFQUNqQixBQUFBLElBQUk7SUFDRixPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSx1QkFBVztFQUd4QixBQUFBLEVBQUU7SUFDQSxPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSxJQUFLOztBQUlwQixVQUFVLENBQUMsQUFBQSxXQUFXO0VBQ3BCLEFBQUEsSUFBSTtJQUNGLE9BQU8sRUFBRSxDQUFFO0VBR2IsQUFBQSxFQUFFO0lBQ0EsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsdUJBQVc7O0FHdkMxQixBQUFBLFNBQVMsQ0FBQztFQUVSLGlCQUFpQjtFQUdqQixrQkFBa0IsRUFFbkI7RUFQRCxBQUdFLFNBSE8sQ0FHUCxZQUFZLENBQVM7SUFBRSxTQUFTLEVBQUMsNEJBQTZCLEdBQUk7RUFIcEUsQUFNRSxTQU5PLENBTVAsZUFBZSxDQUFNO0lBQUUsU0FBUyxFQUFDLHlCQUEwQixHQUFJOztBSFJqRSxVQUFVLENBQUMsQUFBQSxZQUFZO0VBQ3JCLEFBQUEsSUFBSTtJQUNGLFNBQVMsRUFBRSx1QkFBVztJQUN0QixVQUFVLEVBQUUsT0FBUTtFQUd0QixBQUFBLEVBQUU7SUFDQSxTQUFTLEVBQUUsb0JBQVc7O0FBSTFCLFVBQVUsQ0FBQyxBQUFBLGFBQWE7RUFDdEIsQUFBQSxJQUFJO0lBQ0YsU0FBUyxFQUFFLG9CQUFXO0VBR3hCLEFBQUEsRUFBRTtJQUNBLFVBQVUsRUFBRSxNQUFPO0lBQ25CLFNBQVMsRUFBRSx1QkFBVzs7QUFJMUIsVUFBVSxDQUFDLEFBQUEsUUFBUTtFQUNqQixBQUFBLElBQUk7SUFDRixPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSx1QkFBVztFQUd4QixBQUFBLEVBQUU7SUFDQSxPQUFPLEVBQUUsQ0FBRTtJQUNYLFNBQVMsRUFBRSxJQUFLOztBQUlwQixVQUFVLENBQUMsQUFBQSxXQUFXO0VBQ3BCLEFBQUEsSUFBSTtJQUNGLE9BQU8sRUFBRSxDQUFFO0VBR2IsQUFBQSxFQUFFO0lBQ0EsT0FBTyxFQUFFLENBQUU7SUFDWCxTQUFTLEVBQUUsdUJBQVc7O0FJdEMxQixBQUFRLEtBQUgsR0FBRyxjQUFjLENBQUM7RUFDckIsVUFBVSxFSHdOcUIsSUFBSTtFR3ZObkMsT0FBTyxFQUFFLEtBQU0sR0FDaEI7O0NMR0QsQUFBQSxBQUFVLFNBQVQsQUFBQSxJQUFZLEFBQUEsQUFBUyxRQUFSLEFBQUEsSUFBVyxBQUFBLEFBQWMsYUFBYixBQUFBLElBQWdCLEFBQUEsQUFBVyxVQUFWLEFBQUEsR0FBYSxBQUFBLFNBQVMsRUFBRSxBQUFBLFdBQVcsQ0FBQztFQUM3RSxPQUFPLEVBQUUsZUFBZ0IsR0FDMUI7O0FBRUQsQUFBTyxJQUFILEdBQUcsSUFBSSxDQUFDO0VBQ1YsMEJBQTBCO0VBQzFCLFVBQVUsRUU2TXFCLElBQUksR0Y1TXBDIiwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== */
diff --git a/xos/core/xoslib/dashboards/xosDeveloper.html b/xos/core/xoslib/dashboards/xosDeveloper.html
index 9227acd..f3abf18 100644
--- a/xos/core/xoslib/dashboards/xosDeveloper.html
+++ b/xos/core/xoslib/dashboards/xosDeveloper.html
@@ -1,32 +1,16 @@
-<script src="{{ STATIC_URL }}/js/vendor/underscore-min.js"></script>
-<script src="{{ STATIC_URL }}/js/vendor/backbone.js"></script>
-<script src="{{ STATIC_URL }}/js/vendor/backbone.wreqr.js"></script>
-<script src="{{ STATIC_URL }}/js/vendor/backbone.babysitter.js"></script>
-<script src="{{ STATIC_URL }}/js/vendor/backbone.marionette.js"></script>
+<!-- browserSync -->
 
-<script src="{{ STATIC_URL }}/js/xoslib/xos-defaults.js"></script>
-<script src="{{ STATIC_URL }}/js/xoslib/xos-backbone.js"></script>
-<script src="{{ STATIC_URL }}/js/xosDeveloper.js"></script>
+<!-- endcss -->
+<!-- inject:css -->
+<link rel="stylesheet" href="/static/css/xosDeveloper.css">
+<!-- endinject -->
 
-<link rel="stylesheet" type="text/css" href="{% static 'css/xosDeveloper.css' %}" media="all">
-
-<div id="developerView">
+<div ng-app="xos.developer" id="xosDeveloper" class="container-fluid">
+  <div ui-view></div>
 </div>
 
-<script type="text/template" id="developer-slicetable-template">
-  <thead>

-    <tr class="developer-header">

-      <th>Slice <span class="sort" id="sort-asc-name">&#9650;</span><span class="sort" id="sort-desc-name">&#9660;</span></th>

-      <th>Privilege<span class="sort" id="sort-asc-sliceInfo.roles">&#9650;</span><span class="sort" id="sort-desc-sliceInfo.roles">&#9660;</span></th>

-      <th>Number of Instances<span class="sort" id="sort-asc-sliceInfo.instanceCount">&#9650;</span><span class="sort" id="sort-desc-sliceInfo.instanceCount">&#9660;</span></th>

-      <th>Number of Sites<span class="sort" id="sort-asc-sliceInfo.siteCount">&#9650;</span><span class="sort" id="sort-desc-sliceInfo.siteCount">&#9660;</span></th>

-    </tr>

-  </thead>

-  <tbody>

-  </tbody>

-</script>
 
-<script type="text/template" id="developer-slicedetail-template">
-  <td><a href="http://{{request.get_host}}/admin/core/slice/<%= id %>/"><%= name %></a></td><td><%= sliceInfo.roles[0] %></td><td><%= sliceInfo.instanceCount %></td><td><%= sliceInfo.siteCount %></td>

-</script>

-
+<!-- endjs -->
+<!-- inject:js -->
+<script src="/static/js/xosDeveloper.js"></script>
+<!-- endinject -->
\ No newline at end of file
diff --git a/xos/core/xoslib/dashboards/xosDeveloper_datatables.html b/xos/core/xoslib/dashboards/xosDeveloper_datatables.html
deleted file mode 100644
index 57777b7..0000000
--- a/xos/core/xoslib/dashboards/xosDeveloper_datatables.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<script src="{{ STATIC_URL }}/js/vendor/underscore-min.js"></script>
-<script src="{{ STATIC_URL }}/js/vendor/backbone.js"></script>
-<script src="{{ STATIC_URL }}/js/vendor/backbone.wreqr.js"></script>
-<script src="{{ STATIC_URL }}/js/vendor/backbone.babysitter.js"></script>
-<script src="{{ STATIC_URL }}/js/vendor/backbone.marionette.js"></script>
-
-<script src="{{ STATIC_URL }}/js/xoslib/xos-defaults.js"></script>
-<script src="{{ STATIC_URL }}/js/xoslib/xos-backbone.js"></script>
-<script src="{{ STATIC_URL }}/js/xosDeveloper_datatables.js"></script>
-
-<div id="developerView">Loading...
-</div>
-
-<script type="text/template" id="developer-slicedetail-template">
-  <td><a href="http://{{request.get_host}}/admin/core/slice/<%= id %>/"><%= name %></a></td><td><%= sliceInfo.roles[0] %></td><td><%= sliceInfo.instanceCount %></td><td><%= sliceInfo.siteCount %></td>

-</script>

-
diff --git a/xos/core/xoslib/static/css/xosDeveloper.css b/xos/core/xoslib/static/css/xosDeveloper.css
index 1bce877..dee3249 100644
--- a/xos/core/xoslib/static/css/xosDeveloper.css
+++ b/xos/core/xoslib/static/css/xosDeveloper.css
@@ -1 +1 @@
-#developerView .sort { cursor: pointer; }
+#xosDeveloper .pie-legend li{display:inline-block;white-space:nowrap;position:relative;margin-bottom:4px;border-radius:5px;padding:2px 8px 2px 28px;font-size:smaller;cursor:default}#xosDeveloper .pie-legend-icon{display:block;position:absolute;left:0;top:0;width:20px;height:20px;border-radius:5px}
\ 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 a9179c3..9a14abc 100644
--- a/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
+++ b/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
@@ -1 +1 @@
-"use strict";!function(){angular.module("xos.uiComponents",["chart.js"])}(),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,r){var t=this;this.responseMsg=!1,this.responseErr=!1,this.tableConfig={columns:[],actions:[{label:"delete",icon:"remove",cb:function(e){t.Resource["delete"]({id:e.id}).$promise.then(function(){o.remove(t.data,function(n){return n.id===e.id}),t.responseMsg=t.config.resource+" with id "+e.id+" successfully deleted"})["catch"](function(n){t.responseErr=n.data.detail||"Error while deleting "+t.config.resource+" with id "+e.id})},color:"red"},{label:"details",icon:"search",cb:function(e){t.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&&t.data.push(angular.copy(n)),delete t.detailedItem,t.responseMsg=t.config.resource+" with id "+e.id+" successfully saved"})["catch"](function(n){t.responseErr=n.data.detail||"Error while saving "+t.config.resource+" with id "+e.id})},"class":"success"}]},this.cleanForm=function(){delete t.detailedItem},this.createItem=function(){t.detailedItem=new t.Resource},this.Resource=e.get(this.config.resource);var i=function(){t.Resource.query().$promise.then(function(e){if(e[0]){var i=e[0],a=Object.keys(i);o.remove(a,function(e){return"id"==e||"validators"==e}),angular.isArray(t.config.hiddenFields)&&(a=o.difference(a,t.config.hiddenFields));var s=a.map(function(e){return n.format(e)});a.forEach(function(e,n){t.tableConfig.columns.push({label:s[n],prop:e})}),a.forEach(function(e,o){t.formConfig.fields[e]={label:n.format(s[o]).replace(":",""),type:r._getFieldFormat(i[e])}}),t.data=e}})};i()}]}})}(),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","$timeout","$interval","$scope","_",function(e,n,o,r,t){var i=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 a=function(e){return t.groupBy(e,i.config.groupBy)},s=function(e){return t.reduce(Object.keys(e),function(n,o){return n.concat(e[o].length)},[])},c=function(e){return angular.isFunction(i.config.labelFormatter)?i.config.labelFormatter(Object.keys(e)):Object.keys(e)},l=function(e){var n=a(e);i.data=s(n),i.labels=c(n)};this.config.resource?!function(){i.Resource=e.get(i.config.resource);var n=function(){i.Resource.query().$promise.then(function(e){e[0]&&l(e)})};n(),i.config.poll&&o(function(){n()},1e3*i.config.poll)}():r.$watch(function(){return i.config.data},function(e){e&&l(i.config.data)},!0)}]}})}(),function(){angular.module("xos.uiComponents").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:!0,bindToController:!0,controllerAs:"vm",controller:function(){this.config={type:"danger"}}}})}(),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                      class="form-control"\n                      placeholder="Type to search by {{col.label}}"\n                      type="text"\n                      ng-model="vm.query[col.prop]"/>\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 r=e.filter(this.config.columns,{type:"icon"});angular.isArray(r)&&r.length>0&&e.forEach(r,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 t=e.filter(this.config.columns,function(e){return angular.isDefined(e.link)});angular.isArray(t)&&t.length>0&&e.forEach(t,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}})}();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("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            <label>{{field.label}}</label>\n            <input\n              ng-if="field.type !== \'boolean\'"\n              type="{{field.type}}"\n              name="{{name}}"\n              class="form-control"\n              ng-model="vm.ngModel[name]"\n              ng-minlength="field.validators.minlength || 0"\n              ng-maxlength="field.validators.maxlength || 2000"\n              ng-required="field.validators.required || false" />\n            <span class="boolean-field" ng-if="field.type === \'boolean\'">\n              <button\n                class="btn btn-success"\n                ng-show="vm.ngModel[name]"\n                ng-click="vm.ngModel[name] = false">\n                <i class="glyphicon glyphicon-ok"></i>\n              </button>\n              <button\n                class="btn btn-danger"\n                ng-show="!vm.ngModel[name]"\n                ng-click="vm.ngModel[name] = true">\n                <i class="glyphicon glyphicon-remove"></i>\n              </button>\n            </span>\n            <!-- <pre>{{vm[vm.config.formName][name].$error | json}}</pre> -->\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,r){var t=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 t.ngModel},function(e){if(t.formField={},e){var n=o.difference(Object.keys(e),t.excludedField),i=r.parseModelField(n);t.formField=r.buildFormStructure(i,t.config.fields,e)}})}]}}).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 e.isDate(n)||!Number.isNaN(Date.parse(n))&&new Date(n).getTime()>6311808e5?"date":"boolean"==typeof n?"boolean":isNaN(n)||null===n?o._isEmail(n)?"email":null===n?"string":"undefined"==typeof n?"undefined":_typeof(n):"number"},this.buildFormStructure=function(r,t,i){return r=Object.keys(r).length>0?r:t,t=t||{},e.reduce(Object.keys(r),function(e,r){return e[r]={label:t[r]&&t[r].label?t[r].label+":":n.format(r),type:t[r]&&t[r].type?t[r].type:o._getFieldFormat(i[r]),validators:t[r]&&t[r].validators?t[r].validators:{}},"date"===e[r].type&&(i[r]=new Date(i[r])),"number"===e[r].type&&(i[r]=parseInt(i[r],10)),e},{})},this.parseModelField=function(n){return e.reduce(n,function(e,n){return e[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(){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 r=n.defer();return e.get("/api/utility/slicesplus/",{params:o}).then(function(e){r.resolve(e.data)})["catch"](function(e){r.reject(e.data)}),{$promise:r.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("GraphService",["$q","Tenants","Services",function(e,n,o){var r=this;this.loadCoarseData=function(){var r=void 0,t=e.defer();return o.query().$promise.then(function(e){return r=e,n.query({kind:"coarse"}).$promise}).then(function(e){t.resolve({tenants:e,services:r})}),t.promise},this.getCoarseGraph=function(){return r.loadCoarseData().then(function(e){console.log(e)}),"ciao"}}])}(),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,r=e.info,t=e.warn,i=e.error,a=e.debug,s=function(o){return function(){if(n()){var r=[].slice.call(arguments),t=new Date;r[0]="["+t.getHours()+":"+t.getMinutes()+":"+t.getSeconds()+"] "+r[0],"function"!=typeof e.reset||e.debug.logs instanceof Array||e.reset(),o.apply(null,r)}}};return e.info=s(r),e.log=s(o),e.warn=s(t),e.error=s(i),e.debug=s(a),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)},r=function(r){return r=e(r),r=n(r),r=o(r).replace(/\s\s+/g," ")+":",r.replace("::",":")};return{_formatByUnderscore:e,_formatByUppercase:n,_capitalize:o,format:r}}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
+"use strict";!function(){angular.module("xos.uiComponents",["chart.js"])}(),function(){angular.module("xos.uiComponents").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:!0,bindToController:!0,controllerAs:"vm",controller:function(){this.config={type:"danger"}}}})}(),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                      class="form-control"\n                      placeholder="Type to search by {{col.label}}"\n                      type="text"\n                      ng-model="vm.query[col.prop]"/>\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 r=e.filter(this.config.columns,{type:"icon"});angular.isArray(r)&&r.length>0&&e.forEach(r,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 t=e.filter(this.config.columns,function(e){return angular.isDefined(e.link)});angular.isArray(t)&&t.length>0&&e.forEach(t,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}})}();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("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            <label>{{field.label}}</label>\n            <input\n              ng-if="field.type !== \'boolean\'"\n              type="{{field.type}}"\n              name="{{name}}"\n              class="form-control"\n              ng-model="vm.ngModel[name]"\n              ng-minlength="field.validators.minlength || 0"\n              ng-maxlength="field.validators.maxlength || 2000"\n              ng-required="field.validators.required || false" />\n            <span class="boolean-field" ng-if="field.type === \'boolean\'">\n              <button\n                class="btn btn-success"\n                ng-show="vm.ngModel[name]"\n                ng-click="vm.ngModel[name] = false">\n                <i class="glyphicon glyphicon-ok"></i>\n              </button>\n              <button\n                class="btn btn-danger"\n                ng-show="!vm.ngModel[name]"\n                ng-click="vm.ngModel[name] = true">\n                <i class="glyphicon glyphicon-remove"></i>\n              </button>\n            </span>\n            <!-- <pre>{{vm[vm.config.formName][name].$error | json}}</pre> -->\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,r){var t=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 t.ngModel},function(e){if(t.formField={},e){var n=o.difference(Object.keys(e),t.excludedField),i=r.parseModelField(n);t.formField=r.buildFormStructure(i,t.config.fields,e)}})}]}}).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 e.isDate(n)||!Number.isNaN(Date.parse(n))&&new Date(n).getTime()>6311808e5?"date":"boolean"==typeof n?"boolean":isNaN(n)||null===n?o._isEmail(n)?"email":null===n?"string":"undefined"==typeof n?"undefined":_typeof(n):"number"},this.buildFormStructure=function(r,t,i){return r=Object.keys(r).length>0?r:t,t=t||{},e.reduce(Object.keys(r),function(e,r){return e[r]={label:t[r]&&t[r].label?t[r].label+":":n.format(r),type:t[r]&&t[r].type?t[r].type:o._getFieldFormat(i[r]),validators:t[r]&&t[r].validators?t[r].validators:{}},"date"===e[r].type&&(i[r]=new Date(i[r])),"number"===e[r].type&&(i[r]=parseInt(i[r],10)),e},{})},this.parseModelField=function(n){return e.reduce(n,function(e,n){return e[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("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,r){var t=this;this.responseMsg=!1,this.responseErr=!1,this.tableConfig={columns:[],actions:[{label:"delete",icon:"remove",cb:function(e){t.Resource["delete"]({id:e.id}).$promise.then(function(){o.remove(t.data,function(n){return n.id===e.id}),t.responseMsg=t.config.resource+" with id "+e.id+" successfully deleted"})["catch"](function(n){t.responseErr=n.data.detail||"Error while deleting "+t.config.resource+" with id "+e.id})},color:"red"},{label:"details",icon:"search",cb:function(e){t.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&&t.data.push(angular.copy(n)),delete t.detailedItem,t.responseMsg=t.config.resource+" with id "+e.id+" successfully saved"})["catch"](function(n){t.responseErr=n.data.detail||"Error while saving "+t.config.resource+" with id "+e.id})},"class":"success"}]},this.cleanForm=function(){delete t.detailedItem},this.createItem=function(){t.detailedItem=new t.Resource},this.Resource=e.get(this.config.resource);var i=function(){t.Resource.query().$promise.then(function(e){if(e[0]){var i=e[0],a=Object.keys(i);o.remove(a,function(e){return"id"==e||"validators"==e}),angular.isArray(t.config.hiddenFields)&&(a=o.difference(a,t.config.hiddenFields));var s=a.map(function(e){return n.format(e)});a.forEach(function(e,n){t.tableConfig.columns.push({label:s[n],prop:e})}),a.forEach(function(e,o){t.formConfig.fields[e]={label:n.format(s[o]).replace(":",""),type:r._getFieldFormat(i[e])}}),t.data=e}})};i()}]}})}(),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,r,t){var i=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 a=function(e){return t.groupBy(e,i.config.groupBy)},s=function(e){return t.reduce(Object.keys(e),function(n,o){return n.concat(e[o].length)},[])},c=function(e){return angular.isFunction(i.config.labelFormatter)?i.config.labelFormatter(Object.keys(e)):Object.keys(e)},l=function(e){var n=a(e);i.data=s(n),i.labels=c(n)};this.config.resource?!function(){i.Resource=e.get(i.config.resource);var o=function(){i.Resource.query().$promise.then(function(e){e[0]&&l(e)})};o(),i.config.poll&&n(function(){o()},1e3*i.config.poll)}():o.$watch(function(){return i.config.data},function(e){e&&l(i.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 r=n.defer();return e.get("/api/utility/slicesplus/",{params:o}).then(function(e){r.resolve(e.data)})["catch"](function(e){r.reject(e.data)}),{$promise:r.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("GraphService",["$q","Tenants","Services",function(e,n,o){var r=this;this.loadCoarseData=function(){var r=void 0,t=e.defer();return o.query().$promise.then(function(e){return r=e,n.query({kind:"coarse"}).$promise}).then(function(e){t.resolve({tenants:e,services:r})}),t.promise},this.getCoarseGraph=function(){return r.loadCoarseData().then(function(e){console.log(e)}),"ciao"}}])}(),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,r=e.info,t=e.warn,i=e.error,a=e.debug,s=function(o){return function(){if(n()){var r=[].slice.call(arguments),t=new Date;r[0]="["+t.getHours()+":"+t.getMinutes()+":"+t.getSeconds()+"] "+r[0],"function"!=typeof e.reset||e.debug.logs instanceof Array||e.reset(),o.apply(null,r)}}};return e.info=s(r),e.log=s(o),e.warn=s(t),e.error=s(i),e.debug=s(a),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)},r=function(r){return r=e(r),r=n(r),r=o(r).replace(/\s\s+/g," ")+":",r.replace("::",":")};return{_formatByUnderscore:e,_formatByUppercase:n,_capitalize:o,format:r}}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/xosDeveloper.js b/xos/core/xoslib/static/js/xosDeveloper.js
index c1af537..8585eac 100644
--- a/xos/core/xoslib/static/js/xosDeveloper.js
+++ b/xos/core/xoslib/static/js/xosDeveloper.js
@@ -1,64 +1 @@
-/* eslint-disable guard-for-in, no-undef, space-before-blocks*/

-/* This is an example that uses xoslib + marionette to display the developer

-   view.

-

-   For an example that uses xoslib + datatables, see xosDeveloper_datatables.js

-*/

-

-DeveloperApp = new Marionette.Application();

-

-DeveloperApp.addRegions({

-  mainRegion: '#developerView'

-});

-

-DeveloperApp.SliceDetailView = Marionette.ItemView.extend({

-  template: '#developer-slicedetail-template',

-  tagName: 'tr',

-  className: 'developer_slicedetail'

-});

-

-DeveloperApp.SliceListView = Marionette.CompositeView.extend({

-  tagName: 'table',

-  className: 'table table-bordered table-striped',

-  template: '#developer-slicetable-template',

-  childView: DeveloperApp.SliceDetailView,

-  childViewContainer: 'tbody',

-

-  events: {'click .sort': 'changeSort'},

-

-  initialize: function() {

-    this.listenTo(this.collection, 'change', this._renderChildren);

-  },

-

-  changeSort: function(e) {

-    parts = $(e.currentTarget).attr('id').split('-');

-    order = parts[1];

-    fieldName = parts[2];

-    this.collection.sortVar = fieldName;

-    this.collection.sortOrder = order;

-    this.collection.sort();

-  },

-

-  attachHtml: function(compositeView, childView, index) {

-    // The REST API will let admin users see everything. For the developer

-    // view we still want to hide slices we are not members of.

-    if(childView.model.get('sliceInfo').roles.length === 0) {

-      return;

-    }

-    DeveloperApp.SliceListView.__super__.attachHtml(compositeView, childView, index);

-  },

-});

-

-DeveloperApp.on('start', function() {

-  var developerSliceListView = new DeveloperApp.SliceListView({

-    collection: xos.slicesPlus

-  });

-

-  DeveloperApp.mainRegion.show(developerSliceListView);

-  xos.slicesPlus.startPolling();

-});

-

-$(document).ready(function() {

-  DeveloperApp.start();

-});

-

+"use strict";angular.module("xos.developer",["ngResource","ngCookies","ui.router","xos.helpers"]).config(["$stateProvider",function(e){e.state("developer",{url:"/",template:"<developer-dashboard></developer-dashboard>"})}]).config(["$httpProvider",function(e){e.interceptors.push("NoHyperlinks")}]).directive("developerDashboard",function(){return{restrict:"E",scope:{},bindToController:!0,controllerAs:"vm",templateUrl:"templates/developer-dashboard.tpl.html",controller:["$scope","$timeout","SlicesPlus","Instances","_",function(e,t,n,s,i){var r=this;this.instancePerSliceConfig={data:[],groupBy:"slice",legend:!0,classes:"instance per slice",labelFormatter:function(e){return e.map(function(e){return i.find(r.slices,{id:parseInt(e)}).name})}},this.instancePerSiteConfig={data:[],groupBy:"site",legend:!0,classes:"instance per site"},this.networkPerSliceConfig={data:[],groupBy:"name",legend:!0,classes:"network per slice"},this.tableConfig={columns:[{label:"Name",prop:"name"},{label:"Privileges",prop:"current_user_roles",type:"array"},{label:"Number of Instances (active / total)",type:"custom",formatter:function(e){return e.instance_total_ready+" / "+e.instance_total}},{label:"Active Instances per Sites",type:"object",prop:"instance_distribution_ready"},{label:"Total Instances per Sites",type:"object",prop:"instance_distribution"},{label:"Networks",type:"custom",formatter:function(e){return e.networks.length}}]},n.query().$promise.then(function(e){return r.slices=e,s.query().$promise}).then(function(e){var t=i.reduce(r.slices,function(e,t){if(t.networks.length>1)for(var n=0;n<t.networks.length;n++)e.push({id:t.id,name:t.name,network:t.networks[n]});else 1===t.networks.length&&e.push({id:t.id,name:t.name,network:t.networks[0]});return e},[]),n=i.reduce(r.slices,function(e,t){return i.forEach(Object.keys(t.instance_distribution),function(n){for(var s=0;s<t.instance_distribution[n];s++)e.push({site:n,instance:s})}),e},[]);r.sites=Object.keys(i.groupBy(n,"site")),r.instancePerSliceConfig.data=e,r.instancePerSiteConfig.data=n,r.networkPerSliceConfig.data=t})["catch"](function(e){throw new Error(e)})}]}}),angular.module("xos.developer").run(["$templateCache",function(e){e.put("templates/developer-dashboard.tpl.html",'<div class="row">\n  <div ng-class="{\'col-sm-4\': vm.sites.length > 1 || !vm.sites, \'col-sm-6\': vm.sites.length <= 1}" class="text-center">\n    <h3>Instances per Slice</h3>\n    <xos-smart-pie ng-if="vm.instancePerSliceConfig.data.length > 0" config="vm.instancePerSliceConfig"></xos-smart-pie>\n  </div>\n  <div ng-if="vm.sites.length > 1" class="col-sm-4 text-center">\n    <h3>Instances per Site</h3>\n    <xos-smart-pie ng-if="vm.instancePerSiteConfig.data.length > 0" config="vm.instancePerSiteConfig"></xos-smart-pie>\n  </div>\n  <div ng-class="{\'col-sm-4\': vm.sites.length > 1 || !vm.sites, \'col-sm-6\': vm.sites.length <= 1}" class="text-center">\n    <h3>Network per Slice</h3>\n    <xos-smart-pie ng-if="vm.networkPerSliceConfig.data.length > 0" config="vm.networkPerSliceConfig"></xos-smart-pie>\n  </div>\n</div>\n\n<xos-table config="vm.tableConfig" data="vm.slices"></xos-table>')}]),angular.module("xos.developer").run(["$location",function(e){e.path("/")}]);
\ No newline at end of file
diff --git a/xos/core/xoslib/static/js/xosDeveloper_datatables.js b/xos/core/xoslib/static/js/xosDeveloper_datatables.js
deleted file mode 100644
index e3df4c3..0000000
--- a/xos/core/xoslib/static/js/xosDeveloper_datatables.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/* eslint-disable guard-for-in, no-undef, indent, space-before-blocks*/
-
-// TODO write test and then fix lint errors
-
-/* This is an example that uses xoslib + datatables to display the developer
-   view.
-
-   For an example that uses xoslib + marionette, see xosDeveloper.js
-*/
-
-function updateSliceTable(data) {
-    $('#developerView').html(
-        '<table cellpadding="0" cellspacing="0" border="0" class="display" id="dynamicusersliceinfo"></table>'
-    );
-    var actualEntries = [];
-
-    for (rowkey in data.models) {
-        row = data.models[rowkey];
-        slicename = row.get('name');
-        sliceid = row.get('id');
-        role = row.get('sliceInfo').roles[0] || '';
-        instancecount = row.get('sliceInfo').instanceCount;
-        sitecount = row.get('sliceInfo').siteCount;
-        backendHtml = row.get('backendHtml');
-
-        //if (! role) {
-        //    continue;
-        //}
-
-        if (! row.get('current_user_can_see')) {
-            continue;
-        }
-
-        actualEntries.push([backendHtml +
-            ' <a href="/admin/core/slice/' + sliceid + '">' +
-            slicename + '</a>',
-            role, instancecount, sitecount]);
-    }
-    oTable = $('#dynamicusersliceinfo').dataTable({
-        'bJQueryUI': true,
-        'aaData': actualEntries,
-        'bStateSave': true,
-        'aoColumns': [
-            {'sTitle': 'Slice'},
-            {'sTitle': 'Privilege' , sClass: 'alignCenter'},
-            {'sTitle': 'Number of Instances' , sClass: 'alignCenter'},
-            {'sTitle': 'Number of Sites' , sClass: 'alignCenter'},
-        ]
-    });
-}
-
-$(document).ready(function() {
-    xos.slicesPlus.on('change', function() {
-        updateSliceTable(xos.slicesPlus);
-    });
-    xos.slicesPlus.on('remove', function() {
-        updateSliceTable(xos.slicesPlus);
-    });
-    xos.slicesPlus.on('sort', function() {
-        updateSliceTable(xos.slicesPlus);
-    });
-
-    xos.slicesPlus.startPolling();
-});
-