Added GUI Environment
diff --git a/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/.bower.json b/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/.bower.json
new file mode 100644
index 0000000..b8a080f
--- /dev/null
+++ b/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/.bower.json
@@ -0,0 +1,68 @@
+{
+  "name": "angular-chart.js",
+  "version": "0.8.8",
+  "main": [
+    "./dist/angular-chart.js",
+    "./dist/angular-chart.css"
+  ],
+  "authors": [
+    "Jerome Touffe-Blin <jtblin@gmail.com>"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/jtblin/angular-chart.js.git"
+  },
+  "description": "An angular.js wrapper for Chart.js - reactive, responsive, beautiful charts.",
+  "moduleType": [
+    "globals"
+  ],
+  "keywords": [
+    "angular",
+    "angular.js",
+    "chartjs",
+    "chart",
+    "reactive",
+    "responsive",
+    "graph",
+    "bar",
+    "line",
+    "area",
+    "donut"
+  ],
+  "license": "BSD",
+  "ignore": [
+    "**/.*",
+    "node_modules",
+    "bower_components",
+    "examples",
+    "test",
+    "tests"
+  ],
+  "dependencies": {
+    "angular": "1.x",
+    "Chart.js": "~1.0.1"
+  },
+  "devDependencies": {
+    "Chart.StackedBar.js": "~1.0.1",
+    "angular-bootstrap": "~0.11.0",
+    "angular-mocks": "1.x",
+    "font-awesome": "~4.1.0",
+    "rainbow": "~1.1.9",
+    "requirejs": "~2.1.20"
+  },
+  "resolutions": {
+    "Chart.js": "~1.0.1",
+    "angular": "1.x",
+    "angular-mocks": "1.3.10"
+  },
+  "homepage": "https://github.com/jtblin/angular-chart.js",
+  "_release": "0.8.8",
+  "_resolution": {
+    "type": "version",
+    "tag": "0.8.8",
+    "commit": "25739e972b519676fed7e0bd4c9d1ec6b8bb92f0"
+  },
+  "_source": "git://github.com/jtblin/angular-chart.js.git",
+  "_target": "~0.8.7",
+  "_originalSource": "angular-chart.js"
+}
\ No newline at end of file
diff --git a/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/LICENSE b/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/LICENSE
new file mode 100644
index 0000000..f3bd714
--- /dev/null
+++ b/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) Jerome Touffe-Blin ("Author")
+All rights reserved.
+
+The BSD License
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/README.md b/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/README.md
new file mode 100644
index 0000000..d2044e8
--- /dev/null
+++ b/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/README.md
@@ -0,0 +1,209 @@
+# angular-chart.js
+
+[![Bower version](https://badge.fury.io/bo/angular-chart.js.svg)](http://badge.fury.io/bo/angular-chart.js)
+[![npm version](https://badge.fury.io/js/angular-chart.js.svg)](http://badge.fury.io/js/angular-chart.js)
+[![Build Status](https://travis-ci.org/jtblin/angular-chart.js.png)](https://travis-ci.org/jtblin/angular-chart.js)
+[![Code Climate](https://codeclimate.com/github/jtblin/angular-chart.js/badges/gpa.svg)](https://codeclimate.com/github/jtblin/angular-chart.js)
+[![Code Coverage](https://d3s6mut3hikguw.cloudfront.net/github/jtblin/angular-chart.js/badges/coverage.svg)](https://codeclimate.com/github/jtblin/angular-chart.js)
+
+Beautiful, reactive, responsive charts for Angular.JS using [Chart.js](http://www.chartjs.org/). 
+
+[Demo](http://jtblin.github.io/angular-chart.js/)
+
+# Installation
+
+### bower
+
+    bower install --save angular-chart.js
+
+### npm
+
+    npm install --save angular-chart.js
+
+### cdn
+
+    //cdn.jsdelivr.net/angular.chartjs/latest/angular-chart.min.js
+    //cdn.jsdelivr.net/angular.chartjs/latest/angular-chart.css
+
+### manually
+
+or copy the files from `dist/`. 
+
+Then add the sources to your code (adjust paths as needed) after 
+adding the dependencies for Angular and Chart.js first:
+
+```html
+<head>
+  <link rel="stylesheet" href="bower_components/angular-chart.js/dist/angular-chart.css" />
+<head>
+<body>
+  ...
+</body>
+  <script src="bower_components/angular/angular.min.js"></script>
+  <script src="bower_components/Chart.js/Chart.min.js"></script>
+  <script src="bower_components/angular-chart.js/dist/angular-chart.min.js"></script>
+```
+
+# Utilisation
+
+There are 6 types of charts so 6 directives: `chart-line`, `chart-bar`, `chart-radar`, `chart-pie`, 
+`chart-polar-area`, `chart-doughnut`.
+
+They all use mostly the same API (`[chart-]` indicates an optional but recommended prefix):
+
+- `[chart-]data`: series data
+- `[chart-]labels`: x axis labels (line, bar, radar) or series labels (pie, doughnut, polar area)
+- `[chart-]options`: chart options (as from [Chart.js documentation](http://www.chartjs.org/docs/))
+- `[chart-]series`: (default: `[]`): series labels (line, bar, radar)
+- `[chart-]colours`: data colours (will use default colours if not specified)
+- `getColour`: function that returns a colour in case there are not enough (will use random colours if not specified)
+- `[chart-]click`: onclick event handler
+- `[chart-]hover`: onmousemove event handler
+- `[chart-]legend`: (default: `false`): show legend below the chart
+
+*DEPRECATION WARNING*: Note that all attributes which do *not* use the `[chart-]` prefix are deprecated 
+and may be removed in a future version.
+
+There is another directive `chart-base` that takes an extra attribute `chart-type` to define the type
+dynamically, see [stacked bar example](http://jtblin.github.io/angular-chart.js/examples/stacked-bars.html).
+
+# Example
+
+## Markup
+
+```html
+<canvas id="line" class="chart chart-line" chart-data="data" chart-labels="labels" 
+	chart-legend="true" chart-series="series" chart-click="onClick"></canvas> 
+```
+
+## Javascript
+
+```javascript
+angular.module("app", ["chart.js"])
+  // Optional configuration
+  .config(['ChartJsProvider', function (ChartJsProvider) {
+    // Configure all charts
+    ChartJsProvider.setOptions({
+      colours: ['#FF5252', '#FF8A80'],
+      responsive: false
+    });
+    // Configure all line charts
+    ChartJsProvider.setOptions('Line', {
+      datasetFill: false
+    });
+  }])
+  .controller("LineCtrl", ['$scope', '$timeout', function ($scope, $timeout) {
+
+  $scope.labels = ["January", "February", "March", "April", "May", "June", "July"];
+  $scope.series = ['Series A', 'Series B'];
+  $scope.data = [
+    [65, 59, 80, 81, 56, 55, 40],
+    [28, 48, 40, 19, 86, 27, 90]
+  ];
+  $scope.onClick = function (points, evt) {
+    console.log(points, evt);
+  };
+  
+  // Simulate async data update
+  $timeout(function () {
+    $scope.data = [
+      [28, 48, 40, 19, 86, 27, 90],
+      [65, 59, 80, 81, 56, 55, 40]
+    ];
+  }, 3000);
+}]);
+```
+
+## AMD RequireJS
+
+See [a simple AMD example](examples/amd.js)
+
+## CommonJS e.g. webpack
+
+Module should work with CommonJS out of the box e.g. [browserify](http://browserify.org/) or 
+[webpack](http://webpack.github.io/), see a [webpack example](examples/webpack.config.js).
+
+# Reactive
+
+angular-chart.js watch updates on data, series, labels, colours and options and will update, or destroy and recreate, 
+the chart on changes.
+
+# Events
+
+angular-chart.js emits the following events on the `scope` and pass the chart as argument:
+
+* `create`: when chart is created
+* `update`: when chart is updated
+
+```
+$scope.$on('create', function (event, chart) {
+  console.log(chart);
+});
+```
+
+**Note**: the event can be emitted multiple times for each chart as the chart can be destroyed and
+created multiple times during angular `watch` lifecycle.
+
+angular-chart.js listen to the scope `destroy` event and destroy the chart when it happens.
+
+# Colours
+
+There are a set of 7 default colours. Colours can be replaced using the `colours` attribute.
+If there is more data than colours, colours are generated randomly or can be provided 
+via a function through the `getColour` attribute.
+
+Hex colours are converted to Chart.js colours automatically, 
+including different shades for highlight, fill, stroke, etc.
+
+# Issues
+
+**Issues or feature requests for Chart.js (e.g. new chart type, new axis, etc.) need to be opened on 
+[Chart.js issues tracker](https://github.com/nnnick/Chart.js/issues)**
+
+**For general questions about usage, please use [http://stackoverflow.com/](http://stackoverflow.com/)**
+ 
+Please check if issue exists first, otherwise open issue in [github](https://github.com/jtblin/angular-chart.js/issues). 
+**Ensure you add a link to a plunker, jsbin, or equivalent.** 
+Here is a [jsbin template](http://jsbin.com/dufibi/3/edit?html,js,output) for convenience.
+
+## Browser compatibility
+
+For IE8 and older browsers, you will need 
+to include [excanvas](https://code.google.com/p/explorercanvas/wiki/Instructions). 
+You will also need a [shim](https://github.com/es-shims/es5-shim) for ES5 functions.
+
+You also need to have  ```height``` and ```width``` attributes for the ```<canvas>``` tag of your chart if using IE8 and older browsers. If you *do not* have these attributes, you will need a 
+[getComputedStyle shim](https://github.com/Financial-Times/polyfill-service/blob/master/polyfills/getComputedStyle/polyfill.js) and the line ```document.defaultView = window;```, but there still may be errors (due to code in Chart.js).
+
+```html
+<head>
+<!--[if lt IE 9]>
+  <script src="excanvas.js"></script>
+  <script src="es5-shim.js"></script>
+<![endif]-->
+</head>
+```
+
+# Contributing
+ 
+Pull requests welcome!
+
+1. Fork the repo
+1. Install dependencies: `npm install` and `bower install`
+1. Make your changes
+1. Install [GraphicsMagick](http://www.graphicsmagick.org/)
+1. Run tests: `npm test`
+1. Submit pull request
+
+## Contributors
+
+Thank you to the [contributors](https://github.com/jtblin/angular-chart.js/graphs/contributors)!
+
+# Author
+
+Jerome Touffe-Blin, [@jtblin](https://twitter.com/jtblin), [About me](http://about.me/jtblin)
+
+# License
+
+angular-chart.js is copyright 2015 Jerome Touffe-Blin and contributors. 
+It is licensed under the BSD license. See the include LICENSE file for details.
diff --git a/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/angular-chart.js b/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/angular-chart.js
new file mode 100644
index 0000000..d6df1cd
--- /dev/null
+++ b/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/angular-chart.js
@@ -0,0 +1,362 @@
+(function (factory) {
+  'use strict';
+  if (typeof exports === 'object') {
+    // Node/CommonJS
+    module.exports = factory(
+      typeof angular !== 'undefined' ? angular : require('angular'),
+      typeof Chart !== 'undefined' ? Chart : require('chart.js'));
+  }  else if (typeof define === 'function' && define.amd) {
+    // AMD. Register as an anonymous module.
+    define(['angular', 'chart'], factory);
+  } else {
+    // Browser globals
+    factory(angular, Chart);
+  }
+}(function (angular, Chart) {
+  'use strict';
+
+  Chart.defaults.global.responsive = true;
+  Chart.defaults.global.multiTooltipTemplate = '<%if (datasetLabel){%><%=datasetLabel%>: <%}%><%= value %>';
+
+  Chart.defaults.global.colours = [
+    '#97BBCD', // blue
+    '#DCDCDC', // light grey
+    '#F7464A', // red
+    '#46BFBD', // green
+    '#FDB45C', // yellow
+    '#949FB1', // grey
+    '#4D5360'  // dark grey
+  ];
+
+  var usingExcanvas = typeof window.G_vmlCanvasManager === 'object' &&
+    window.G_vmlCanvasManager !== null &&
+    typeof window.G_vmlCanvasManager.initElement === 'function';
+
+  if (usingExcanvas) Chart.defaults.global.animation = false;
+
+  return angular.module('chart.js', [])
+    .provider('ChartJs', ChartJsProvider)
+    .factory('ChartJsFactory', ['ChartJs', '$timeout', ChartJsFactory])
+    .directive('chartBase', function (ChartJsFactory) { return new ChartJsFactory(); })
+    .directive('chartLine', function (ChartJsFactory) { return new ChartJsFactory('Line'); })
+    .directive('chartBar', function (ChartJsFactory) { return new ChartJsFactory('Bar'); })
+    .directive('chartRadar', function (ChartJsFactory) { return new ChartJsFactory('Radar'); })
+    .directive('chartDoughnut', function (ChartJsFactory) { return new ChartJsFactory('Doughnut'); })
+    .directive('chartPie', function (ChartJsFactory) { return new ChartJsFactory('Pie'); })
+    .directive('chartPolarArea', function (ChartJsFactory) { return new ChartJsFactory('PolarArea'); });
+
+  /**
+   * Wrapper for chart.js
+   * Allows configuring chart js using the provider
+   *
+   * angular.module('myModule', ['chart.js']).config(function(ChartJsProvider) {
+   *   ChartJsProvider.setOptions({ responsive: true });
+   *   ChartJsProvider.setOptions('Line', { responsive: false });
+   * })))
+   */
+  function ChartJsProvider () {
+    var options = {};
+    var ChartJs = {
+      Chart: Chart,
+      getOptions: function (type) {
+        var typeOptions = type && options[type] || {};
+        return angular.extend({}, options, typeOptions);
+      }
+    };
+
+    /**
+     * Allow to set global options during configuration
+     */
+    this.setOptions = function (type, customOptions) {
+      // If no type was specified set option for the global object
+      if (! customOptions) {
+        customOptions = type;
+        options = angular.extend(options, customOptions);
+        return;
+      }
+      // Set options for the specific chart
+      options[type] = angular.extend(options[type] || {}, customOptions);
+    };
+
+    this.$get = function () {
+      return ChartJs;
+    };
+  }
+
+  function ChartJsFactory (ChartJs, $timeout) {
+    return function chart (type) {
+      return {
+        restrict: 'CA',
+        scope: {
+          data: '=?',
+          labels: '=?',
+          options: '=?',
+          series: '=?',
+          colours: '=?',
+          getColour: '=?',
+          chartType: '=',
+          legend: '@',
+          click: '=?',
+          hover: '=?',
+
+          chartData: '=?',
+          chartLabels: '=?',
+          chartOptions: '=?',
+          chartSeries: '=?',
+          chartColours: '=?',
+          chartLegend: '@',
+          chartClick: '=?',
+          chartHover: '=?'
+        },
+        link: function (scope, elem/*, attrs */) {
+          var chart, container = document.createElement('div');
+          container.className = 'chart-container';
+          elem.replaceWith(container);
+          container.appendChild(elem[0]);
+
+          if (usingExcanvas) window.G_vmlCanvasManager.initElement(elem[0]);
+
+          ['data', 'labels', 'options', 'series', 'colours', 'legend', 'click', 'hover'].forEach(deprecated);
+          function aliasVar (fromName, toName) {
+            scope.$watch(fromName, function (newVal) {
+              if (typeof newVal === 'undefined') return;
+              scope[toName] = newVal;
+            });
+          }
+          /* provide backward compatibility to "old" directive names, by
+           * having an alias point from the new names to the old names. */
+          aliasVar('chartData', 'data');
+          aliasVar('chartLabels', 'labels');
+          aliasVar('chartOptions', 'options');
+          aliasVar('chartSeries', 'series');
+          aliasVar('chartColours', 'colours');
+          aliasVar('chartLegend', 'legend');
+          aliasVar('chartClick', 'click');
+          aliasVar('chartHover', 'hover');
+
+          // Order of setting "watch" matter
+
+          scope.$watch('data', function (newVal, oldVal) {
+            if (! newVal || ! newVal.length || (Array.isArray(newVal[0]) && ! newVal[0].length)) return;
+            var chartType = type || scope.chartType;
+            if (! chartType) return;
+
+            if (chart) {
+              if (canUpdateChart(newVal, oldVal)) return updateChart(chart, newVal, scope, elem);
+              chart.destroy();
+            }
+
+            createChart(chartType);
+          }, true);
+
+          scope.$watch('series', resetChart, true);
+          scope.$watch('labels', resetChart, true);
+          scope.$watch('options', resetChart, true);
+          scope.$watch('colours', resetChart, true);
+
+          scope.$watch('chartType', function (newVal, oldVal) {
+            if (isEmpty(newVal)) return;
+            if (angular.equals(newVal, oldVal)) return;
+            if (chart) chart.destroy();
+            createChart(newVal);
+          });
+
+          scope.$on('$destroy', function () {
+            if (chart) chart.destroy();
+          });
+
+          function resetChart (newVal, oldVal) {
+            if (isEmpty(newVal)) return;
+            if (angular.equals(newVal, oldVal)) return;
+            var chartType = type || scope.chartType;
+            if (! chartType) return;
+
+            // chart.update() doesn't work for series and labels
+            // so we have to re-create the chart entirely
+            if (chart) chart.destroy();
+
+            createChart(chartType);
+          }
+
+          function createChart (type) {
+            if (isResponsive(type, scope) && elem[0].clientHeight === 0 && container.clientHeight === 0) {
+              return $timeout(function () {
+                createChart(type);
+              }, 50, false);
+            }
+            if (! scope.data || ! scope.data.length) return;
+            scope.getColour = typeof scope.getColour === 'function' ? scope.getColour : getRandomColour;
+            scope.colours = getColours(type, scope);
+            var cvs = elem[0], ctx = cvs.getContext('2d');
+            var data = Array.isArray(scope.data[0]) ?
+              getDataSets(scope.labels, scope.data, scope.series || [], scope.colours) :
+              getData(scope.labels, scope.data, scope.colours);
+            var options = angular.extend({}, ChartJs.getOptions(type), scope.options);
+            chart = new ChartJs.Chart(ctx)[type](data, options);
+            scope.$emit('create', chart);
+
+            // Bind events
+            cvs.onclick = scope.click ? getEventHandler(scope, chart, 'click', false) : angular.noop;
+            cvs.onmousemove = scope.hover ? getEventHandler(scope, chart, 'hover', true) : angular.noop;
+
+            if (scope.legend && scope.legend !== 'false') setLegend(elem, chart);
+          }
+
+          function deprecated (attr) {
+            if (typeof console !== 'undefined' && ChartJs.getOptions().env !== 'test') {
+              var warn = typeof console.warn === 'function' ? console.warn : console.log;
+              if (!! scope[attr]) {
+                warn.call(console, '"%s" is deprecated and will be removed in a future version. ' +
+                  'Please use "chart-%s" instead.', attr, attr);
+              }
+            }
+          }
+        }
+      };
+    };
+
+    function canUpdateChart (newVal, oldVal) {
+      if (newVal && oldVal && newVal.length && oldVal.length) {
+        return Array.isArray(newVal[0]) ?
+        newVal.length === oldVal.length && newVal.every(function (element, index) {
+          return element.length === oldVal[index].length; }) :
+          oldVal.reduce(sum, 0) > 0 ? newVal.length === oldVal.length : false;
+      }
+      return false;
+    }
+
+    function sum (carry, val) {
+      return carry + val;
+    }
+
+    function getEventHandler (scope, chart, action, triggerOnlyOnChange) {
+      var lastState = null;
+      return function (evt) {
+        var atEvent = chart.getPointsAtEvent || chart.getBarsAtEvent || chart.getSegmentsAtEvent;
+        if (atEvent) {
+          var activePoints = atEvent.call(chart, evt);
+          if (triggerOnlyOnChange === false || angular.equals(lastState, activePoints) === false) {
+            lastState = activePoints;
+            scope[action](activePoints, evt);
+            scope.$apply();
+          }
+        }
+      };
+    }
+
+    function getColours (type, scope) {
+      var colours = angular.copy(scope.colours ||
+        ChartJs.getOptions(type).colours ||
+        Chart.defaults.global.colours
+      );
+      while (colours.length < scope.data.length) {
+        colours.push(scope.getColour());
+      }
+      return colours.map(convertColour);
+    }
+
+    function convertColour (colour) {
+      if (typeof colour === 'object' && colour !== null) return colour;
+      if (typeof colour === 'string' && colour[0] === '#') return getColour(hexToRgb(colour.substr(1)));
+      return getRandomColour();
+    }
+
+    function getRandomColour () {
+      var colour = [getRandomInt(0, 255), getRandomInt(0, 255), getRandomInt(0, 255)];
+      return getColour(colour);
+    }
+
+    function getColour (colour) {
+      return {
+        fillColor: rgba(colour, 0.2),
+        strokeColor: rgba(colour, 1),
+        pointColor: rgba(colour, 1),
+        pointStrokeColor: '#fff',
+        pointHighlightFill: '#fff',
+        pointHighlightStroke: rgba(colour, 0.8)
+      };
+    }
+
+    function getRandomInt (min, max) {
+      return Math.floor(Math.random() * (max - min + 1)) + min;
+    }
+
+    function rgba (colour, alpha) {
+      if (usingExcanvas) {
+        // rgba not supported by IE8
+        return 'rgb(' + colour.join(',') + ')';
+      } else {
+        return 'rgba(' + colour.concat(alpha).join(',') + ')';
+      }
+    }
+
+    // Credit: http://stackoverflow.com/a/11508164/1190235
+    function hexToRgb (hex) {
+      var bigint = parseInt(hex, 16),
+        r = (bigint >> 16) & 255,
+        g = (bigint >> 8) & 255,
+        b = bigint & 255;
+
+      return [r, g, b];
+    }
+
+    function getDataSets (labels, data, series, colours) {
+      return {
+        labels: labels,
+        datasets: data.map(function (item, i) {
+          return angular.extend({}, colours[i], {
+            label: series[i],
+            data: item
+          });
+        })
+      };
+    }
+
+    function getData (labels, data, colours) {
+      return labels.map(function (label, i) {
+        return angular.extend({}, colours[i], {
+          label: label,
+          value: data[i],
+          color: colours[i].strokeColor,
+          highlight: colours[i].pointHighlightStroke
+        });
+      });
+    }
+
+    function setLegend (elem, chart) {
+      var $parent = elem.parent(),
+          $oldLegend = $parent.find('chart-legend'),
+          legend = '<chart-legend>' + chart.generateLegend() + '</chart-legend>';
+      if ($oldLegend.length) $oldLegend.replaceWith(legend);
+      else $parent.append(legend);
+    }
+
+    function updateChart (chart, values, scope, elem) {
+      if (Array.isArray(scope.data[0])) {
+        chart.datasets.forEach(function (dataset, i) {
+          (dataset.points || dataset.bars).forEach(function (dataItem, j) {
+            dataItem.value = values[i][j];
+          });
+        });
+      } else {
+        chart.segments.forEach(function (segment, i) {
+          segment.value = values[i];
+        });
+      }
+      chart.update();
+      scope.$emit('update', chart);
+      if (scope.legend && scope.legend !== 'false') setLegend(elem, chart);
+    }
+
+    function isEmpty (value) {
+      return ! value ||
+        (Array.isArray(value) && ! value.length) ||
+        (typeof value === 'object' && ! Object.keys(value).length);
+    }
+
+    function isResponsive (type, scope) {
+      var options = angular.extend({}, Chart.defaults.global, ChartJs.getOptions(type), scope.options);
+      return options.responsive;
+    }
+  }
+}));
diff --git a/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/angular-chart.less b/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/angular-chart.less
new file mode 100644
index 0000000..ba6b18d
--- /dev/null
+++ b/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/angular-chart.less
@@ -0,0 +1,30 @@
+.chart-legend, .bar-legend, .line-legend, .pie-legend, .radar-legend, .polararea-legend, .doughnut-legend {
+  list-style-type: none;
+  margin-top: 5px;
+  text-align: center;
+  /* NOTE: Browsers automatically add 40px of padding-left to all lists, so we should offset that, otherwise the legend is off-center */
+  -webkit-padding-start:0; /* Webkit */
+  -moz-padding-start:0; /* Mozilla */
+  padding-left:0; /* IE (handles all cases, really, but we should also include the vendor-specific properties just to be safe) */
+
+  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;
+
+    span {
+      display: block;
+      position: absolute;
+      left: 0;
+      top: 0;
+      width: 20px;
+      height: 20px;
+      border-radius: 5px;
+    }
+  }
+}
diff --git a/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/bower.json b/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/bower.json
new file mode 100644
index 0000000..6ada4e5
--- /dev/null
+++ b/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/bower.json
@@ -0,0 +1,58 @@
+{
+  "name": "angular-chart.js",
+  "version": "0.8.8",
+  "main": [
+    "./dist/angular-chart.js",
+    "./dist/angular-chart.css"
+  ],
+  "authors": [
+    "Jerome Touffe-Blin <jtblin@gmail.com>"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/jtblin/angular-chart.js.git"
+  },
+  "description": "An angular.js wrapper for Chart.js - reactive, responsive, beautiful charts.",
+  "moduleType": [
+    "globals"
+  ],
+  "keywords": [
+    "angular",
+    "angular.js",
+    "chartjs",
+    "chart",
+    "reactive",
+    "responsive",
+    "graph",
+    "bar",
+    "line",
+    "area",
+    "donut"
+  ],
+  "license": "BSD",
+  "ignore": [
+    "**/.*",
+    "node_modules",
+    "bower_components",
+    "examples",
+    "test",
+    "tests"
+  ],
+  "dependencies": {
+    "angular": "1.x",
+    "Chart.js": "~1.0.1"
+  },
+  "devDependencies": {
+    "Chart.StackedBar.js": "~1.0.1",
+    "angular-bootstrap": "~0.11.0",
+    "angular-mocks": "1.x",
+    "font-awesome": "~4.1.0",
+    "rainbow": "~1.1.9",
+    "requirejs": "~2.1.20"
+  },
+  "resolutions": {
+    "Chart.js": "~1.0.1",
+    "angular": "1.x",
+    "angular-mocks": "1.3.10"
+  }
+}
diff --git a/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/gulpfile.js b/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/gulpfile.js
new file mode 100644
index 0000000..d32d007
--- /dev/null
+++ b/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/gulpfile.js
@@ -0,0 +1,171 @@
+(function () {
+  'use strict';
+
+  var fs = require('fs');
+  var path = require('path');
+  var gulp = require('gulp');
+  var less = require('gulp-less');
+  var sourcemaps = require('gulp-sourcemaps');
+  var uglify = require('gulp-uglify');
+  var csso = require('gulp-csso');
+  var jshint = require('gulp-jshint');
+  var stylish = require('jshint-stylish');
+  var jscs = require('gulp-jscs');
+  var mocha = require('gulp-spawn-mocha');
+  var tar = require('gulp-tar');
+  var gzip = require('gulp-gzip');
+  var bumper = require('gulp-bump');
+  var git = require('gulp-git');
+  var shell = require('gulp-shell');
+  var rename = require('gulp-rename');
+  var sequence = require('gulp-sequence');
+  var ngAnnotate = require('gulp-ng-annotate');
+  var rimraf = require('gulp-rimraf');
+  var istanbul = require('gulp-istanbul');
+  var istanbulReport = require('gulp-istanbul-report');
+  var mochaPhantomJS = require('gulp-mocha-phantomjs');
+
+  gulp.task('clean', function () {
+    return gulp.src('./dist/*', { read: false })
+      .pipe(rimraf());
+  });
+
+  gulp.task('less', function () {
+    return gulp.src('./*.less')
+      .pipe(less())
+      .pipe(gulp.dest('./dist'));
+  });
+
+  gulp.task('css-min', function () {
+    return gulp.src('./dist/*.css')
+      .pipe(sourcemaps.init())
+      .pipe(csso())
+      .pipe(rename({ suffix: '.min' }))
+      .pipe(sourcemaps.write('./'))
+      .pipe(gulp.dest('./dist'));
+  });
+
+  gulp.task('lint', function () {
+    return gulp.src('**/*.js')
+      .pipe(jshint())
+      .pipe(jshint.reporter(stylish));
+  });
+
+  gulp.task('style', function () {
+    return gulp.src('**/*.js')
+      .pipe(jscs());
+  });
+
+  gulp.task('cover', function () {
+    return gulp.src('angular-chart.js')
+      .pipe(istanbul({ coverageVariable: '__coverage__' }))
+      .pipe(rename('coverage.js'))
+      .pipe(gulp.dest('test/fixtures'));
+  });
+
+  gulp.task('unit', function () {
+    return gulp.src('test/index.html', { read: false })
+      .pipe(mochaPhantomJS({
+        phantomjs: {
+          hooks: 'mocha-phantomjs-istanbul',
+          coverageFile: 'coverage/coverage.json'
+        },
+        reporter: 'spec'
+    }));
+  });
+
+  gulp.task('integration', function () {
+    return gulp.src(path.join('test', 'test.integration.js'), { read: false })
+      .pipe(mocha({ reporter: 'list', timeout: 20000, require: 'test/support/setup.js' }));
+  });
+
+  gulp.task('report', function () {
+    return gulp.src('coverage/coverage.json')
+      .pipe(istanbulReport({ reporters: ['lcov'] }));
+  });
+
+  gulp.task('bump-patch', bump('patch'));
+  gulp.task('bump-minor', bump('minor'));
+  gulp.task('bump-major', bump('major'));
+
+  gulp.task('bower', function () {
+    return gulp.src('./angular-chart.js')
+      .pipe(ngAnnotate({ single_quotes: true }))
+      .pipe(gulp.dest('./dist'));
+  });
+
+  gulp.task('js', ['lint', 'style', 'bower'], function () {
+    return gulp.src('./angular-chart.js')
+      .pipe(rename('angular-chart.min.js'))
+      .pipe(ngAnnotate({ single_quotes: true }))
+      .pipe(sourcemaps.init())
+      .pipe(uglify())
+      .pipe(sourcemaps.write('./'))
+      .pipe(gulp.dest('./dist'));
+  });
+
+  gulp.task('build', function () {
+    return gulp.src(['dist/*', '!./dist/*.tar.gz'])
+      .pipe(tar('angular-chart.js.tar'))
+      .pipe(gzip({ gzipOptions: { level: 9 } }))
+      .pipe(gulp.dest('dist/'));
+  });
+
+  gulp.task('update', function (cb) {
+    fs.readFile('./examples/charts.template.html', 'utf8', function (err, file) {
+      if (err) return cb(err);
+      file = file.replace('<!-- version -->', version());
+      fs.writeFile('./examples/charts.html', file, cb);
+    });
+  });
+
+  gulp.task('git-commit', function () {
+    var v = version();
+    gulp.src(['./dist/*', './package.json', './bower.json', './examples/charts.html', './test/fixtures/coverage.js'])
+      .pipe(git.add())
+      .pipe(git.commit(v))
+    ;
+  });
+
+  gulp.task('git-push', function (cb) {
+    var v = version();
+    git.push('origin', 'master', function (err) {
+      if (err) return cb(err);
+      git.tag(v, v, function (err) {
+        if (err) return cb(err);
+        git.push('origin', 'master', {args: '--tags' }, cb);
+      });
+    });
+  });
+
+  gulp.task('npm', shell.task([
+    'npm publish'
+  ]));
+
+  gulp.task('watch', function () {
+    gulp.watch('./*.js', ['js']);
+    gulp.watch('./*.less', ['less']);
+    return true;
+  });
+
+  function bump (level) {
+    return function () {
+      return gulp.src(['./package.json', './bower.json'])
+        .pipe(bumper({type: level}))
+        .pipe(gulp.dest('./'));
+    };
+  }
+
+  function version () {
+    return JSON.parse(fs.readFileSync('package.json', 'utf8')).version;
+  }
+
+  gulp.task('default', sequence('check', 'assets'));
+  gulp.task('assets', sequence('clean', ['less', 'js'], 'css-min', 'build'));
+  gulp.task('test', sequence('cover', 'unit', 'integration', 'report'));
+  gulp.task('check', sequence(['lint', 'style'], 'test'));
+  gulp.task('deploy-patch', sequence('default', 'bump-patch', 'update', 'git-commit', 'git-push', 'npm'));
+  gulp.task('deploy-minor', sequence('default', 'bump-minor', 'update', 'git-commit', 'git-push', 'npm'));
+  gulp.task('deploy-major', sequence('default', 'bump-patch', 'update', 'git-commit', 'git-push', 'npm'));
+
+})();
diff --git a/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/package.json b/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/package.json
new file mode 100644
index 0000000..650c9c7
--- /dev/null
+++ b/xos-apps/auto-scale/gui/src/vendor/angular-chart.js/package.json
@@ -0,0 +1,60 @@
+{
+  "name": "angular-chart.js",
+  "version": "0.8.8",
+  "description": "An angular.js wrapper for Chart.js",
+  "main": "dist/angular-chart.js",
+  "directories": {
+    "example": "examples"
+  },
+  "scripts": {
+    "test": "gulp check"
+  },
+  "author": "Jerome Touffe-Blin <jtblin@gmail.com>",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/jtblin/angular-chart.js.git"
+  },
+  "license": "BSD-2-Clause",
+  "devDependencies": {
+    "chai": "^3.4.1",
+    "chai-string": "^1.1.1",
+    "codeclimate-test-reporter": "^0.1.0",
+    "cp": "^0.2.0",
+    "gm": "^1.17.0",
+    "gulp": "^3.9.0",
+    "gulp-bump": "^1.0.0",
+    "gulp-csso": "^1.0.1",
+    "gulp-git": "^1.6.0",
+    "gulp-gzip": "^1.2.0",
+    "gulp-istanbul": "^0.10.3",
+    "gulp-istanbul-report": "^0.0.1",
+    "gulp-jscs": "^3.0.2",
+    "gulp-jshint": "^1.9.2",
+    "gulp-less": "^3.0.3",
+    "gulp-mocha-phantomjs": "^0.10.1",
+    "gulp-ng-annotate": "^1.1.0",
+    "gulp-rename": "^1.2.0",
+    "gulp-rimraf": "^0.2.0",
+    "gulp-sequence": "^0.4.1",
+    "gulp-shell": "^0.5.1",
+    "gulp-sourcemaps": "^1.0.0",
+    "gulp-spawn-mocha": "^2.0.1",
+    "gulp-tar": "^1.5.0",
+    "gulp-uglify": "^1.4.2",
+    "imgur-node-api": "^0.1.0",
+    "jshint-stylish": "^2.0.1",
+    "mkdirp": "^0.5.0",
+    "mocha": "^2.1.0",
+    "mocha-phantomjs-istanbul": "^0.0.2",
+    "sinon": "^1.12.2",
+    "sinon-chai": "^2.7.0",
+    "testatic": "^0.1.0",
+    "tmp-sync": "^1.1.0",
+    "webpack": "^1.12.0",
+    "webshot": "^0.16.0"
+  },
+  "dependencies": {
+    "angular": "^1.4.5",
+    "chart.js": "^1.0.2"
+  }
+}