blob: a4b296d1b144e868e5c5c4c25207e7b52deda5ac [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright 2015 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="import" href="/tracing/extras/rail/rail_score.html">
<link rel="import" href="/tracing/extras/rail/rail_ir_finder.html">
<link rel="import" href="/tracing/model/ir_coverage.html">
<link rel="import" href="/tracing/ui/analysis/analysis_link.html">
<link rel="import" href="/tracing/ui/base/color_legend.html">
<link rel="import" href="/tracing/ui/base/table.html">
<link rel="import" href="/tracing/ui/extras/rail/rail_score_span.html">
<link rel="import" href="/tracing/ui/side_panel/side_panel.html">
<link rel="import" href="/tracing/ui/units/time_duration_span.html">
<polymer-element name='tr-ui-e-rail-rail-score-side-panel'
extends='tr-ui-side-panel'>
<template>
<style>
:host {
display: flex;
flex-direction: column;
width: 450px;
overflow-x: auto;
}
#score {
background-color: rgb(236, 236, 236)
flex: 0 0 auto;
}
#content {
min-width: 0;
flex-direction: column;
display: flex;
flex: 1 1 auto;
}
#coverage {
font-size: 10px;
}
</style>
<tr-ui-e-rail-rail-score-span id="score"></tr-ui-e-rail-rail-score-span>
<tr-ui-b-table id="table"></tr-ui-b-table>
<div id="coverage">
<b>Coverage:</b><br>
<tr-ui-a-analysis-link id="associated-events"></tr-ui-a-analysis-link><br>
<tr-ui-a-analysis-link id="unassociated-events"></tr-ui-a-analysis-link>
</div>
<button id="test">Create Test</button>
</template>
</polymer-element>
<script>
'use strict';
(function() {
function setCoverageLink(
link, labelString, events, eventRatio, cpuMs, cpuRatio) {
link.setSelectionAndContent(events);
labelString += ' ' + events.length + ' events';
labelString += ' (' + parseInt(100 * eventRatio) + '%)';
if (cpuRatio !== undefined)
labelString += ', ';
link.appendChild(document.createTextNode(labelString));
if (cpuRatio === undefined)
return;
var cpuMsSpan = document.createElement('tr-ui-u-time-duration-span');
// There will be some text after the cpuMsSpan, that should be on the same
// line if it fits. This "span" has display: block for its sparkline... so I
// guess I'll set it inline here?
cpuMsSpan.style.display = 'inline';
cpuMsSpan.duration = cpuMs;
cpuMsSpan.contentTextDecoration = 'underline';
link.appendChild(cpuMsSpan);
var cpuString = ' (' + parseInt(100 * cpuRatio) + '%)';
link.appendChild(document.createTextNode(cpuString));
}
Polymer('tr-ui-e-rail-rail-score-side-panel', {
ready: function() {
this.rangeOfInterest_ = new tr.b.Range();
this.model_ = undefined;
this.railScore_ = undefined;
this.selection_ = new tr.model.EventSet();
this.$.test.addEventListener('click', this.createTest_.bind(this));
},
createTest_: function() {
var overlay = new tr.ui.b.Overlay();
overlay.title = 'RAILIRFinder test';
var textarea = document.createElement('textarea');
textarea.textContent = tr.e.rail.createIRFinderTestCaseStringFromModel(
this.model_);
textarea.rows = textarea.textContent.split('\n').length;
textarea.cols = 80;
overlay.appendChild(textarea);
overlay.visible = true;
textarea.select();
textarea.focus();
},
get textLabel() {
return 'RAIL Info';
},
supportsModel: function(m) {
if (m === undefined) {
return {
supported: false,
reason: 'Unknown tracing model'
};
}
var railScore = tr.e.rail.RAILScore.fromModel(m);
if (railScore === undefined) {
return {
supported: false,
reason: 'RAIL interactions were not found on the model'
};
}
return {
supported: true
};
},
get model() {
return this.model_;
},
set model(model) {
this.model_ = model;
this.updateScore_();
this.updateCoverage_();
this.updateTable_();
},
get listeningToKeys() {
return false;
},
get effectiveRangeOfInterest() {
if (!this.rangeOfInterest_ || this.rangeOfInterest_.isEmpty) {
if (this.model)
return this.model.bounds;
else
return new tr.b.Range();
}
return this.rangeOfInterest_;
},
set rangeOfInterest(rangeOfInterest) {
this.rangeOfInterest_ = rangeOfInterest;
this.updateScore_();
// TODO(benjhayden): Make updateCoverage_ reflect rangeOfInterest.
// https://github.com/catapult-project/catapult/issues/1753
this.updateTable_();
},
updateScore_: function() {
if (!this.model)
return;
this.railScore_ = tr.e.rail.RAILScore.fromModel(
this.model, this.effectiveRangeOfInterest);
this.$.score.railScore = this.railScore_;
},
updateCoverage_: function() {
if (!this.model)
return;
var coverage = tr.model.getIRCoverageFromModel(this.model);
if (!coverage)
return;
var associatedEvents =
tr.model.getAssociatedEvents(this.model.interactionRecords);
var unassociatedEvents = tr.model.getUnassociatedEvents(
this.model, associatedEvents);
setCoverageLink(this.shadowRoot.querySelector('#associated-events'),
'Associated',
associatedEvents,
coverage.coveredEventsCountRatio,
coverage.associatedEventsCpuTimeMs,
coverage.coveredEventsCpuTimeRatio);
setCoverageLink(this.shadowRoot.querySelector('#unassociated-events'),
'Unassociated',
unassociatedEvents,
1.0 - coverage.coveredEventsCountRatio,
coverage.unassociatedEventsCpuTimeMs,
1.0 - coverage.coveredEventsCpuTimeRatio);
},
updateTable_: function() {
if (!this.model)
return;
function toThreeDigitLocaleString(value) {
return value.toLocaleString(undefined,
{minimumFractionDigits: 3,
maximumFractionDigits: 3});
}
var columns = [
{
title: 'Type',
width: '150px',
value: function(ir) {
var events = new tr.model.EventSet([ir]);
events.addEventSet(ir.associatedEvents);
var linkEl = document.createElement('tr-ui-a-analysis-link');
linkEl.setSelectionAndContent(events, ir.railTypeName);
var el = document.createElement('tr-ui-b-color-legend');
el.setLabelAndColorId(linkEl, ir.colorId);
el.compoundEventSelectionState =
ir.computeCompoundEvenSelectionState(this.selection_);
return el;
}.bind(this),
cmp: function(a, b) {
return a.railTypeName.localeCompare(b.railTypeName);
}
},
{
title: 'Efficiency',
width: '33%',
value: function(ir) {
return toThreeDigitLocaleString(ir.normalizedEfficiency);
},
textAlign: 'right',
cmp: function(a, b) {
return a.normalizedEfficiency - b.normalizedEfficiency;
}
},
{
title: 'Comfort',
width: '33%',
value: function(ir) {
return toThreeDigitLocaleString(ir.normalizedUserComfort);
},
textAlign: 'right',
cmp: function(a, b) {
return a.normalizedUserComfort - b.normalizedUserComfort;
}
},
{
title: 'Score',
width: '33%',
value: function(ir) {
var span = document.createElement('span');
span.style.fontWeight = 'bold';
span.textContent = toThreeDigitLocaleString(ir.railScore);
return span;
},
textAlign: 'right',
cmp: function(a, b) {
return a.railScore - b.railScore;
}
}
];
this.$.table.tableColumns = columns;
var rows = [];
if (this.railScore_) {
this.railScore_.interactionRecords.forEach(function(ir) {
if (!this.effectiveRangeOfInterest.intersectsExplicitRangeExclusive(
ir.start, ir.end))
return;
rows.push(ir);
}, this);
}
this.$.table.tableRows = rows;
this.$.table.rebuild();
},
onTableSelectionChanged_: function() {
var selectedIR = this.$.table.selectedTableRow;
var event = new tr.c.RequestSelectionChangeEvent();
event.selection = new tr.c.Selection([selectedIR]);
this.dispatchEvent(event);
},
set selection(selection) {
if (selection === undefined)
selection = new tr.model.EventSet();
if (this.selection_.equals(selection))
return;
this.selection_ = selection;
this.updateTable_();
}
});
})();
</script>