{% extends "/base.html" %}

{% block html_attr %} ng-app="TaskApp"{% endblock %}

{% block title_text %}Rally Task Report{% endblock %}

{% block libs %}
  {% if include_libs %}
  <style>
    {{ include_raw_file("/libs/nv.d3.1.1.15-beta.min.css") }}
  </style>
  <script type="text/javascript">
    {{ include_raw_file("/libs/angular.1.3.3.min.js") }}
    {{ include_raw_file("/libs/d3.3.4.13.min.js") }}
    {{ include_raw_file("/libs/nv.d3.1.1.15-beta.min.js") }}
  </script>
  {% else %}
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.1.15-beta/nv.d3.min.css">
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular.min.js"></script>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3.min.js"></script>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.1.15-beta/nv.d3.min.js"></script>
  {% endif %}
{% endblock %}

{% block js_before %}
{% raw %}
    "use strict";
    if (typeof angular === "object") { angular.module("TaskApp", []).controller(
      "TaskController", ["$scope", "$location", function($scope, $location) {
{% endraw %}
        $scope.source = {{ source }};
        $scope.scenarios = {{ data }};
{% raw %}
      $scope.location = {
        /* #/path/hash/sub/div */
        normalize: function(str) {
          /* Remove unwanted characters from string */
          if (typeof str !== "string") { return "" }
          return str.replace(/[^\w\-\.]/g, "")
        },
        uri: function(obj) {
          /* Getter/Setter */
          if (! obj) {
            var uri = {path: "", hash: "", sub: "", div: ""};
            var arr = ["div", "sub", "hash", "path"];
            angular.forEach($location.url().split("/"), function(value){
              var v = $scope.location.normalize(value);
              if (v) { var k = arr.pop(); if (k) { this[k] = v }}
            }, uri);
            return uri
          }
          var arr = [obj.path, obj.hash, obj.sub, obj.div], res = [];
          for (var i in arr) { if (! arr[i]) { break }; res.push(arr[i]) }
          return $location.url("/" + res.join("/"))
        },
        path: function(path, hash) {
          /* Getter/Setter */
          if (path === "") { return this.uri({}) }
          path = this.normalize(path);
          var uri = this.uri();
          if (! path) { return uri.path }
          uri.path = path;
          var _hash = this.normalize(hash);
          if (_hash || hash === "") { uri.hash = _hash }
          return this.uri(uri)
        },
        hash: function(hash) {
          /* Getter/Setter */
          if (hash) { this.uri({path:this.uri().path, hash:hash}) }
          return this.uri().hash
        }
      }

      /* Dispatch */

      $scope.route = function(uri) {
        if (! $scope.scenarios_map) { return }
        if (uri.path in $scope.scenarios_map) {
          $scope.view = {is_scenario:true};
          $scope.scenario = $scope.scenarios_map[uri.path];
          $scope.nav_idx = $scope.nav_map[uri.path];
          if ($scope.scenario.iterations.histogram.views.length) {
            $scope.mainHistogram = $scope.scenario.iterations.histogram.views[0]
          }
          if ($scope.scenario.atomic.histogram.views.length) {
            $scope.atomicHistogram = $scope.scenario.atomic.histogram.views[0]
          }
          $scope.outputIteration = 0;
          $scope.showTab(uri);
        } else {
          $scope.scenario = null;
          if (uri.path === "source") {
            $scope.view = {is_source:true}
          } else {
            $scope.view = {is_main:true}
          }
        }
      }

      $scope.$on("$locationChangeSuccess", function (event, newUrl, oldUrl) {
        $scope.route($scope.location.uri())
      });

      $scope.showNav = function(nav_idx) { $scope.nav_idx = nav_idx }

      /* Tabs */

      $scope.tabs = [
        {
          id: "overview",
          name: "Overview",
          visible: function(){ return !! $scope.scenario.iterations.pie.length }
        },{
          id: "details",
          name: "Details",
          visible: function(){ return !! $scope.scenario.atomic.pie.length }
        },{
          id: "output",
          name: "Scenario Data",
          visible: function(){ return $scope.scenario.output.length }
        },{
          id: "failures",
          name: "Failures",
          visible: function(){ return !! $scope.scenario.errors.length }
        },{
          id: "task",
          name: "Input task",
          visible: function(){ return !! $scope.scenario.config }
        }
      ];
      $scope.tabs_map = {};
      angular.forEach($scope.tabs,
                      function(tab){ this[tab.id] = tab }, $scope.tabs_map);

      $scope.showTab = function(uri) {
        $scope.tab = uri.hash in $scope.tabs_map ? uri.hash : "overview";
        if (! $scope.scenario.output) {
          var has_additive = !! $scope.scenario.additive_output.length;
          var has_complete = !! ($scope.scenario.complete_output.length
                                 && $scope.scenario.complete_output[0].length);
          $scope.scenario.output = {
            has_additive: has_additive,
            has_complete: has_complete,
            length: has_additive + has_complete,
            active: has_additive ? "additive" : (has_complete ? "complete" : "")
          }
        }
        if (uri.hash === "output") {
          if (uri.sub && $scope.scenario.output["has_" + uri.sub]) {
            $scope.scenario.output.active = uri.sub
          }
        }
      }

      for (var i in $scope.tabs) {
        if ($scope.tabs[i].id === $scope.location.hash()) {
          $scope.tab = $scope.tabs[i].id
        }
        $scope.tabs[i].isVisible = function() {
          if ($scope.scenario) {
            if (this.visible()) { return true }
            /* If tab should be hidden but is selected - show another one */
            if (this.id === $scope.location.hash()) {
              for (var i in $scope.tabs) {
                var tab = $scope.tabs[i];
                if (tab.id != this.id && tab.visible()) {
                  $scope.tab = tab.id;
                  return false
                }
              }
            }
          }
          return false
        }
      }

      $scope.showError = function(message) {
          return (function (e) {
            e.style.display = "block";
            e.textContent = message
          })(document.getElementById("page-error"))
      }

      /* Initialization */

      angular.element(document).ready(function(){
        if (! $scope.scenarios.length) {
          return $scope.showError("No data...")
        }

        /* Compose data mapping */

        $scope.nav = [];
        $scope.nav_map = {};
        $scope.scenarios_map = {};
        var met = [], itr = 0, cls_idx = 0;
        var prev_cls, prev_met;

        for (var idx in $scope.scenarios) {
          var sc = $scope.scenarios[idx];
          if (! prev_cls) {
            prev_cls = sc.cls
          }
          else if (prev_cls !== sc.cls) {
            $scope.nav.push({cls:prev_cls, met:met, idx:cls_idx});
            prev_cls = sc.cls;
            met = [];
            itr = 1;
            cls_idx += 1
          }

          if (prev_met !== sc.met) { itr = 1 };
          sc.ref = $scope.location.normalize(sc.cls+"."+sc.met+(itr > 1 ? "-"+itr : ""));
          $scope.scenarios_map[sc.ref] = sc;
          $scope.nav_map[sc.ref] = cls_idx;
          met.push({name:sc.name, itr:itr, idx:idx, ref:sc.ref});
          prev_met = sc.met;
          itr += 1;
        }

        if (met.length) {
          $scope.nav.push({cls:prev_cls, met:met, idx:cls_idx})
        }

        /* Start */

        var uri = $scope.location.uri();
        uri.path = $scope.location.path();
        $scope.route(uri);
        $scope.$digest()
      });
    }])
    .directive("widget", function($compile) {

      var Chart = {
        _render: function(node, data, chart, do_after){
          nv.addGraph(function() {
            d3.select(node)
              .datum(data).transition().duration(0)
              .call(chart);
            if (typeof do_after === "function") {
              do_after(node, chart)
            }
            nv.utils.windowResize(chart.update);
          })
        },
        /* NOTE(amaretskiy): this is actually a result of
           d3.scale.category20().range(), excluding red color (#d62728)
           which is reserved for errors */
        _colors: ["#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c",
                  "#98df8a", "#ff9896", "#9467bd", "#c5b0d5", "#8c564b",
                  "#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f", "#c7c7c7",
                  "#bcbd22", "#dbdb8d", "#17becf", "#9edae5"],
        _widgets: {
          Pie: "pie",
          StackedArea: "stack",
          Lines: "lines",
          Histogram: "histogram"
        },
        get_chart: function(widget) {
          if (widget in this._widgets) {
            var name = this._widgets[widget];
            return Chart[name]
          }
          return function() { console.log("Error: unexpected widget:", widget) }
        },
        pie: function(node, data, opts, do_after) {
          var chart = nv.models.pieChart()
            .x(function(d) { return d.key })
            .y(function(d) { return d.values })
            .showLabels(true)
            .labelType("percent")
            .donut(true)
            .donutRatio(0.25)
            .donutLabelsOutside(true)
            .color(function(d){
              if (d.data && d.data.color) { return d.data.color }
            });

          var data_ = [], colors = [], colors_map = {errors: "#d62728"};
          for (var i in data) {
            var key = data[i][0];
            if (! (key in colors_map)) {
              if (! colors.length) { colors = Chart._colors.slice() }
              colors_map[key] = colors.shift()
            }
            data_.push({key:key, values:data[i][1], color:colors_map[key]})
          }
          Chart._render(node, data_, chart)
        },
        stack: function(node, data, opts, do_after) {
          var chart = nv.models.stackedAreaChart()
            .x(function(d) { return d[0] })
            .y(function(d) { return d[1] })
            .useInteractiveGuideline(opts.guide)
            .showControls(opts.controls)
            .clipEdge(true);
          chart.xAxis
            .tickFormat(d3.format(opts.xformat || "d"))
            .axisLabel(opts.xname || "")
            .showMaxMin(false);
          chart.yAxis
            .orient("left")
            .tickFormat(d3.format(opts.yformat || ",.3f"));
          var data_ = [];
          for (var i in data) {
            var d = {key:data[i][0], values:data[i][1]};
            if (d.key === "failed_duration") {
              d.color = "#d62728"
            }
            data_.push(d);
          }
          Chart._render(node, data_, chart, do_after);
        },
        lines: function(node, data, opts, do_after) {
          var chart = nv.models.lineChart()
            .x(function(d) { return d[0] })
            .y(function(d) { return d[1] })
            .useInteractiveGuideline(opts.guide)
            .clipEdge(true);
          chart.xAxis
            .tickFormat(d3.format(opts.xformat || "d"))
            .axisLabel(opts.xname || "")
            .showMaxMin(false);
          chart.yAxis
            .orient("left")
            .tickFormat(d3.format(opts.yformat || ",.3f"));
          var data_ = [];
          for (var i in data) {
            var d = {key:data[i][0], values:data[i][1]};
            if (d.key === "failed_duration") {
              d.color = "#d62728"
            }
            data_.push(d)
          }
          Chart._render(node, data_, chart, do_after)
        },
        histogram: function(node, data, opts) {
          var chart = nv.models.multiBarChart()
            .reduceXTicks(true)
            .showControls(false)
            .transitionDuration(0)
            .groupSpacing(0.05);
          chart
            .legend.radioButtonMode(true);
          chart.xAxis
            .axisLabel("Duration (seconds)")
            .tickFormat(d3.format(",.2f"));
          chart.yAxis
            .axisLabel("Iterations (frequency)")
            .tickFormat(d3.format("d"));
          Chart._render(node, data, chart)
        }
      };

      return {
        restrict: "A",
        scope: { data: "=" },
        link: function(scope, element, attrs) {
          scope.$watch("data", function(data) {
            if (! data) { return console.log("Chart has no data to render!") }
            if (attrs.widget === "Table") {
              var ng_class = attrs.lastrowClass ? " ng-class='{"+attrs.lastrowClass+":$last}'" : "";
              var template = "<table class='striped'><thead>" +
                "<tr><th ng-repeat='i in data.cols track by $index'>{{i}}<tr>" +
                "</thead><tbody>" +
                "<tr" + ng_class + " ng-repeat='row in data.rows track by $index'>" +
                "<td ng-repeat='i in row track by $index'>{{i}}" +
                "<tr>" +
                "</tbody></table>";
              var el = element.empty().append($compile(template)(scope)).children()[0]
            } else {

              var el_chart = element.addClass("chart").css({display:"block"});
              var el = el_chart.html("<svg></svg>").children()[0];

              var do_after = null;

              if (attrs.widget in {StackedArea:0, Lines:0}) {

                /* Hide widget if not enough data */
                if ((! data.length) || (data[0].length < 1) || (data[0][1].length < 2)) {
                  return element.empty().css({display:"none"})
                }

                /* NOTE(amaretskiy): Dirty fix for changing chart width in case
                   if there are too long Y values that overlaps chart box. */
                var do_after = function(node, chart){
                  var g_box = angular.element(el_chart[0].querySelector(".nv-y.nv-axis"));

                  if (g_box && g_box[0] && g_box[0].getBBox) {

                    try {
                      // 30 is padding aroung graphs
                      var width = g_box[0].getBBox().width + 30;
                    } catch (err) {
                      // This happens sometimes, just skip silently
                      return
                    }

                    // 890 is chart width (set by CSS)
                    if (typeof width === "number" && width > 890) {
                      width = (890 * 2) - width;
                      if (width > 0) {
                        angular.element(node).css({width:width+"px"});
                        chart.update()
                      }
                    }
                  }
                }
              }
              else if (attrs.widget === "Pie") {
                if (! data.length) {
                  return element.empty().css({display:"none"})
                }
              }

              var options = {
                xname: attrs.nameX || "",
                xformat: attrs.formatX || "d",
                yformat: attrs.formatY || ",.3f",
                controls: attrs.controls === "true",
                guide: attrs.guide === "true"
              };
              Chart.get_chart(attrs.widget)(el, data, options, do_after);
            }

            if (attrs.nameY) {
              /* NOTE(amaretskiy): Dirty fix for displaying Y-axis label correctly.
                 I believe sometimes NVD3 will allow doing this in normal way */
              var label_y = angular.element("<div>").addClass("chart-label-y").text(attrs.nameY);
              angular.element(el).parent().prepend(label_y)
            }

            if (attrs.description) {
              var desc_el = angular.element("<div>").addClass(attrs.descriptionClass || "h3").text(attrs.description);
              angular.element(el).parent().prepend(desc_el)
            }

            if (attrs.title) {
              var title_el = angular.element("<div>").addClass(attrs.titleClass || "h2").text(attrs.title);
              angular.element(el).parent().prepend(title_el)
            }

            angular.element(el).parent().append(angular.element("<div style='clear:both'>"))
          });
        }
      }
    })
  }
{% endraw %}
{% endblock %}

{% block css %}
    .aside { margin:0 20px 0 0; display:block; width:255px; float:left }
    .aside > div { margin-bottom: 15px }
    .aside > div div:first-child { border-top-left-radius:4px; border-top-right-radius:4px }
    .aside > div div:last-child { border-bottom-left-radius:4px; border-bottom-right-radius:4px }
    .navcls { color:#678; background:#eee; border:1px solid #ddd; margin-bottom:-1px; display:block; padding:8px 9px; font-weight:bold; text-align:left; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; cursor:pointer }
    .navcls.expanded { color:#469 }
    .navcls.active { background:#428bca; background-image:linear-gradient(to bottom, #428bca 0px, #3278b3 100%); border-color:#3278b3; color:#fff }
    .navmet { color:#555; background:#fff; border:1px solid #ddd; font-size:12px; display:block; margin-bottom:-1px; padding:8px 10px; text-align:left; text-overflow:ellipsis; white-space:nowrap; overflow:hidden; cursor:pointer }
    .navmet:hover { background:#f8f8f8 }
    .navmet.active, .navmet.active:hover { background:#428bca; background-image:linear-gradient(to bottom, #428bca 0px, #3278b3 100%); border-color:#3278b3; color:#fff }

    .tabs { list-style:outside none none; margin:0 0 5px; padding:0; border-bottom:1px solid #ddd }
    .tabs:after { clear:both }
    .tabs li { float:left; margin-bottom:-1px; display:block; position:relative }
    .tabs li div { border:1px solid transparent; border-radius:4px 4px 0 0; line-height:20px; margin-right:2px; padding:10px 15px; color:#428bca }
    .tabs li div:hover { border-color:#eee #eee #ddd; background:#eee; cursor:pointer; }
    .tabs li.active div { background:#fff; border-color:#ddd #ddd transparent; border-style:solid; border-width:1px; color:#555; cursor:default }
    .failure-mesg { color:#900 }
    .failure-trace { color:#333; white-space:pre; overflow:auto }

    .link { color:#428BCA; padding:5px 15px 5px 5px; text-decoration:underline; cursor:pointer }
    .link.active { color:#333; text-decoration:none }

    .chart { padding:0; margin:0; width:890px }
    .chart svg { height:300px; padding:0; margin:0; overflow:visible; float:right }
    .chart.lower svg { height:180px }
    .chart-label-y { font-size:12px; position:relative; top:5px; padding:0; margin:0 }

    .expandable { cursor:pointer }
    .clearfix { clear:both }
    .sortable > .arrow { display:inline-block; width:12px; height:inherit; color:#c90 }
    .content-main { margin:0 5px; display:block; float:left }
{% endblock %}

{% block media_queries %}
    @media only screen and (min-width: 320px)  { .content-wrap { width:900px  } .content-main { width:600px } }
    @media only screen and (min-width: 900px)  { .content-wrap { width:880px  } .content-main { width:590px } }
    @media only screen and (min-width: 1000px) { .content-wrap { width:980px  } .content-main { width:690px } }
    @media only screen and (min-width: 1100px) { .content-wrap { width:1080px } .content-main { width:790px } }
    @media only screen and (min-width: 1200px) { .content-wrap { width:1180px } .content-main { width:890px } }
{% endblock %}

{% block body_attr %} ng-controller="TaskController"{% endblock %}

{% block header_text %}task results{% endblock %}

{% block content %}
{% raw %}
    <p id="page-error" class="notify-error" style="display:none"></p>

    <div id="content-nav" class="aside" ng-show="scenarios.length" ng-cloack>
      <div>
        <div class="navcls"
             ng-class="{active:view.is_main}"
             ng-click="location.path('')">Task overview</div>
        <div class="navcls"
             ng-class="{active:view.is_source}"
             ng-click="location.path('source', '')">Input file</div>
      </div>
      <div>
        <div class="navcls" title="{{n.cls}}"
             ng-repeat-start="n in nav track by $index"
             ng-click="showNav(n.idx)"
             ng-class="{expanded:n.idx==nav_idx}">
                <span ng-hide="n.idx==nav_idx">&#9658;</span>
                <span ng-show="n.idx==nav_idx">&#9660;</span>
                {{n.cls}}</div>
        <div class="navmet" title="{{m.name}}"
             ng-show="n.idx==nav_idx"
             ng-class="{active:m.ref==scenario.ref}"
             ng-click="location.path(m.ref)"
             ng-repeat="m in n.met track by $index"
             ng-repeat-end>{{m.name}}</div>
      </div>
    </div>

    <div id="content-main" class="content-main" ng-show="scenarios.length" ng-cloak>

      <div ng-show="view.is_main">
        <h1>Task overview</h1>
        <table class="linked compact"
               ng-init="ov_srt='ref'; ov_dir=false">
          <thead>
            <tr>
              <th class="sortable"
                  title="Scenario name, with optional suffix of call number"
                  ng-click="ov_srt='ref'; ov_dir=!ov_dir">
                Scenario
                <span class="arrow">
                  <b ng-show="ov_srt=='ref' && !ov_dir">&#x25b4;</b>
                  <b ng-show="ov_srt=='ref' && ov_dir">&#x25be;</b>
                </span>
              <th class="sortable"
                  title="How long the scenario run, without context duration"
                  ng-click="ov_srt='load_duration'; ov_dir=!ov_dir">
                Load duration (s)
                <span class="arrow">
                  <b ng-show="ov_srt=='load_duration' && !ov_dir">&#x25b4;</b>
                  <b ng-show="ov_srt=='load_duration' && ov_dir">&#x25be;</b>
                </span>
              <th class="sortable"
                  title="Scenario duration plus context duration"
                  ng-click="ov_srt='full_duration'; ov_dir=!ov_dir">
                Full duration (s)
                <span class="arrow">
                  <b ng-show="ov_srt=='full_duration' && !ov_dir">&#x25b4;</b>
                  <b ng-show="ov_srt=='full_duration' && ov_dir">&#x25be;</b>
                </span>
              <th class="sortable" title="Number of iterations"
                  ng-click="ov_srt='iterations_count'; ov_dir=!ov_dir">
                Iterations
                <span class="arrow">
                  <b ng-show="ov_srt=='iterations_count' && !ov_dir">&#x25b4;</b>
                  <b ng-show="ov_srt=='iterations_count' && ov_dir">&#x25be;</b>
                </span>
              <th class="sortable" title="Scenario runner type"
                  ng-click="ov_srt='runner'; ov_dir=!ov_dir">
                Runner
                <span class="arrow">
                  <b ng-show="ov_srt=='runner' && !ov_dir">&#x25b4;</b>
                  <b ng-show="ov_srt=='runner' && ov_dir">&#x25be;</b>
                </span>
              <th class="sortable" title="Number of errors occurred"
                  ng-click="ov_srt='errors.length'; ov_dir=!ov_dir">
                Errors
                <span class="arrow">
                  <b ng-show="ov_srt=='errors.length' && !ov_dir">&#x25b4;</b>
                  <b ng-show="ov_srt=='errors.length' && ov_dir">&#x25be;</b>
                </span>
              <th class="sortable" title="Whether SLA check is successful"
                  ng-click="ov_srt='sla_success'; ov_dir=!ov_dir">
                Success (SLA)
                <span class="arrow">
                  <b ng-show="ov_srt=='sla_success' && !ov_dir">&#x25b4;</b>
                  <b ng-show="ov_srt=='sla_success' && ov_dir">&#x25be;</b>
                </span>
            <tr>
          </thead>
          <tbody>
            <tr ng-repeat="sc in scenarios | orderBy:ov_srt:ov_dir"
                ng-click="location.path(sc.ref)">
              <td>{{sc.ref}}
              <td>{{sc.load_duration | number:3}}
              <td>{{sc.full_duration | number:3}}
              <td>{{sc.iterations_count}}
              <td>{{sc.runner}}
              <td>{{sc.errors.length}}
              <td>
                <span ng-show="sc.sla_success" class="status-pass">&#x2714;</span>
                <span ng-hide="sc.sla_success" class="status-fail">&#x2716;</span>
            <tr>
          </tbody>
        </table>
      </div>

      <div ng-show="view.is_source">
        <h1>Input file</h1>
        <pre class="code">{{source}}</pre>
      </div>

      <div ng-show="view.is_scenario">
        <h1>{{scenario.cls}}.<wbr>{{scenario.name}} ({{scenario.full_duration | number:3}}s)</h1>
        <ul class="tabs">
          <li ng-repeat="t in tabs"
              ng-show="t.isVisible()"
              ng-class="{active:t.id == tab}"
              ng-click="location.hash(t.id)">
            <div>{{t.name}}</div>
          </li>
          <div class="clearfix"></div>
        </ul>
        <div ng-include="tab"></div>

        <script type="text/ng-template" id="overview">
          <p class="thesis">
            Load duration: <b>{{scenario.load_duration | number:3}} s</b> &nbsp;
            Full duration: <b>{{scenario.full_duration | number:3}} s</b> &nbsp;
            Iterations: <b>{{scenario.iterations_count}}</b> &nbsp;
            Failures: <b>{{scenario.errors.length}}</b>
          </p>

          <div ng-show="scenario.sla.length">
            <h2>Service-level agreement</h2>
            <table class="striped">
              <thead>
                <tr>
                  <th>Criterion
                  <th>Detail
                  <th>Success
                <tr>
              </thead>
              <tbody>
                <tr class="rich"
                    ng-repeat="row in scenario.sla track by $index"
                    ng-class="{'status-fail':!row.success, 'status-pass':row.success}">
                  <td>{{row.criterion}}
                  <td>{{row.detail}}
                  <td class="capitalize">{{row.success}}
                <tr>
              </tbody>
            </table>
          </div>

          <div widget="Table"
               data="scenario.table"
               lastrow-class="rich"
               title="Total durations">
          </div>

          <div widget="StackedArea"
               data="scenario.iterations.iter"
               name-x="Iteration sequence number"
               controls="true"
               guide="true">
          </div>

          <div widget="StackedArea"
               data="scenario.load_profile"
               title="Load Profile"
               title-class="h3"
               name-x="Timeline (seconds)"
               format-x=",.2f"
               class="lower">
          </div>

          <div widget="Pie"
               data="scenario.iterations.pie"
               title="Distribution"
               title-class="h3"
               style="float:left; width:40%; margin-top:15px">
          </div>

          <div widget="Histogram"
               ng-if="scenario.iterations.histogram.data.length"
               data="scenario.iterations.histogram.data[mainHistogram.id]"
               style="float:left; width:59%; margin-top:15px; position:relative; top:40px">
          </div>

          <select ng-model="mainHistogram"
                  ng-show="scenario.iterations.histogram.data.length"
                  ng-options="i.name for i in scenario.iterations.histogram.views track by i.id"
                  style="float:right; margin:45px 35px 0">
          </select>

          <div class="clearfix"></div>

        </script>

        <script type="text/ng-template" id="details">

          <div widget="StackedArea"
               data="scenario.atomic.iter"
               title="Atomic Action Durations"
               name-x="Iteration sequence number"
               controls="true"
               guide="true">
          </div>

          <div widget="Pie"
               data="scenario.atomic.pie"
               title="Distribution"
               title-class="h3"
               style="float:left; width:40%; margin-top:15px">
          </div>

          <div widget="Histogram" data="scenario.atomic.histogram.data[atomicHistogram.id]"
               ng-if="scenario.atomic.histogram.data.length"
               style="float:left; width:59%; margin-top:15px; position:relative; top:40px">
          </div>

          <select ng-show="scenario.atomic.histogram.data.length"
                  ng-model="atomicHistogram"
                  ng-options="i.name for i in scenario.atomic.histogram.views track by i.id"
                  style="float:right; margin:45px 35px 0">
          </select>

          <div class="clearfix"></div>

        </script>

        <script type="text/ng-template" id="output">

          <div style="padding:10px 0 0">
            <span class="link"
                  ng-click="location.hash('output/additive')"
                  ng-class="{active:scenario.output.active === 'additive'}"
                  ng-if="scenario.output.has_additive">Aggregated</span>
            <span class="link"
                  ng-click="location.hash('output/complete')"
                  ng-class="{active:scenario.output.active === 'complete'}"
                  ng-if="scenario.output.has_complete">Per iteration</span>
          </div>

          <div ng-repeat="chart in scenario.additive_output"
               ng-if="scenario.output.active === 'additive'">
            <div widget="{{chart.widget}}"
                 title="{{chart.title}}"
                 description="{{chart.description}}"
                 name-x="{{chart.axis_label}}"
                 name-y="{{chart.label}}"
                 data="chart.data">
            </div>
          </div>

          <div ng-if="scenario.output.active === 'complete'" style="padding:10px 0 0">
            <select ng-model="outputIteration">
              <option ng-repeat="i in scenario.complete_output track by $index"
                      value="{{$index}}">
                Iteration {{$index}}
            </select>

            <div ng-repeat="chart in scenario.complete_output[outputIteration]">
              <div widget="{{chart.widget}}"
                   title="{{chart.title}}"
                   description="{{chart.description}}"
                   name-x="{{chart.axis_label}}"
                   name-y="{{chart.label}}"
                   data="chart.data">
              </div>
            </div>
          </div>
        </script>

        <script type="text/ng-template" id="failures">
          <h2>Task failures (<ng-pluralize
            count="scenario.errors.length"
            when="{'1': '1 iteration', 'other': '{} iterations'}"></ng-pluralize> failed)
          </h2>
          <table class="striped">
            <thead>
              <tr>
                <th>
                <th>Iteration
                <th>Exception type
                <th>Exception message
              </tr>
            </thead>
            <tbody>
              <tr class="expandable"
                  ng-repeat-start="i in scenario.errors track by $index"
                  ng-click="i.expanded = ! i.expanded">
                <td>
                  <span ng-hide="i.expanded">&#9658;</span>
                  <span ng-show="i.expanded">&#9660;</span>
                <td>{{i.iteration}}
                <td>{{i.type}}
                <td class="failure-mesg">{{i.message}}
              </tr>
              <tr ng-show="i.expanded" ng-repeat-end>
                <td colspan="4" class="failure-trace">{{i.traceback}}
              </tr>
            </tbody>
          </table>
        </script>

        <script type="text/ng-template" id="task">
          <h2>Subtask Configuration</h2>
          <pre class="code">{{scenario.config}}</pre>
        </script>
      </div>

    </div>
    <div class="clearfix"></div>
{% endraw %}
{% endblock %}

{% block js_after %}
    if (! window.angular) {(function(f){
      f(document.getElementById("content-nav"), "none");
      f(document.getElementById("content-main"), "none");
      f(document.getElementById("page-error"), "block").textContent = "Failed to load AngularJS framework"
    })(function(e, s){e.style.display = s; return e})}
{% endblock %}
