blob: e098cb6770fbfa675dcce7e29ff7b81f862f3a01 [file] [log] [blame]
// Copyright 2018 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:convert' show json;
import 'dart:html';
import 'package:angular/angular.dart';
import 'package:angular_forms/angular_forms.dart';
import 'package:cocoon/benchmark/benchmark_card.dart';
import 'package:cocoon/models.dart';
import 'package:http/http.dart' as http;
@Component(
selector: 'benchmark-history',
templateUrl: 'benchmark_history.html',
directives: const [
NgIf,
BenchmarkCard,
formDirectives,
],
)
class BenchmarkHistory {
BenchmarkHistory(this._httpClient);
final http.Client _httpClient;
String _key;
@Input()
bool userIsAuthenticated = false;
String _autoUpdateGoal;
String _autoUpdateBaseline;
String _autoUpdateTitle = 'Calculating autoupdate...';
String get autoUpdateTitle => _autoUpdateTitle;
String _goal = '';
String get goal => _goal;
set goal(String textValue) {
_goal = textValue.trim();
_validateInputs();
}
String _baseline = '';
String get baseline => _baseline;
set baseline(String textValue) {
_baseline = textValue.trim();
_validateInputs();
}
String _taskName = '';
String get taskName => _taskName;
set taskName(String value) {
_taskName = value;
_validateInputs();
}
String _label = '';
String get label => _label;
set label(String value) {
_label = value;
_validateInputs();
}
String _unit = '';
String get unit => _unit;
set unit(String value) {
_unit = value;
_validateInputs();
}
bool _archived;
bool get archived => _archived;
set archived(bool value) {
_archived = value;
_validateInputs();
}
bool _isInputValid = false;
bool get isInputValid => _isInputValid;
String _statusMessage;
String get statusMessage => _statusMessage;
void _validateInputs() {
_isInputValid = true;
if (double.tryParse(_goal) == null) _isInputValid = false;
if (double.tryParse(_baseline) == null) _isInputValid = false;
if (_taskName == null || _taskName.trim().isEmpty) {
_isInputValid = false;
}
if (_label == null || _label.trim().isEmpty) {
_isInputValid = false;
}
if (_unit == null || _unit.trim().isEmpty) {
_isInputValid = false;
}
if (archived == null) {
_isInputValid = false;
}
}
void autoUpdateTargets() {
if (_autoUpdateGoal == null) return;
goal = _autoUpdateGoal;
baseline = _autoUpdateBaseline;
}
Future<Null> update() async {
_validateInputs();
if (!_isInputValid) {
window.alert('Invalid input.');
return;
}
Map<String, dynamic> request = <String, dynamic>{
'TimeSeriesKey': _key,
'Goal': double.tryParse(_goal),
'Baseline': double.tryParse(_baseline),
'TaskName': _taskName.trim(),
'Label': _label.trim(),
'Unit': _unit.trim(),
'Archived': _archived,
};
http.Response response = await _httpClient.post('/api/update-timeseries',
body: json.encode(request));
if (response.statusCode == 200) {
_statusMessage = 'New targets saved.';
await _loadData();
} else {
_statusMessage =
'Server responded with an error saving new targets (HTTP ${response.statusCode})';
}
}
@Input()
set timeseriesKey(String key) {
if (key == null) {
throw 'Timeseries key must not be null';
}
_key = key;
_loadData();
}
BenchmarkData data;
String lastPosition;
Future<Null> _loadData() async {
Map<String, dynamic> request = <String, dynamic>{
'TimeSeriesKey': _key,
};
if (lastPosition != null && lastPosition != '{}') {
request['StartFrom'] = lastPosition;
}
http.Response response = await _httpClient
.post('/api/public/get-timeseries-history', body: json.encode(request));
GetTimeseriesHistoryResult result =
GetTimeseriesHistoryResult.fromJson(json.decode(response.body));
data = null;
Timer.run(() {
// force Angular to rerender
final double secondHighest =
computeSecondHighest(result.benchmarkData.values.map((t) => t.value));
_autoUpdateGoal = (1.005 * secondHighest).toStringAsFixed(1);
_autoUpdateBaseline = (1.05 * secondHighest).toStringAsFixed(1);
_autoUpdateTitle =
'Autoupdate to ${_autoUpdateGoal} goal/${_autoUpdateBaseline} baseline';
data = result.benchmarkData;
final Timeseries timeseries = result.benchmarkData.timeseries.timeseries;
_goal = timeseries.goal.toString();
_baseline = timeseries.baseline.toString();
_taskName = timeseries.taskName;
_label = timeseries.label;
_unit = timeseries.unit;
_archived = timeseries.isArchived;
lastPosition = result.lastPosition;
});
}
}
double computeSecondHighest(Iterable<double> values) {
double highest = 0.0;
double secondHighest = 0.0;
int count = 0;
for (double value in values.take(20)) {
count++;
if (value > secondHighest) {
if (value > highest) {
secondHighest = highest;
highest = value;
} else {
secondHighest = value;
}
}
}
return count > 1 ? secondHighest : highest;
}