Skip to content

Commit

Permalink
Reporting and displaying parse errors.
Browse files Browse the repository at this point in the history
  • Loading branch information
unknown authored and Austin Bingham committed Nov 26, 2015
1 parent c61e5d9 commit 5812938
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 121 deletions.
24 changes: 21 additions & 3 deletions bark_spider/intervention.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@

_INTERVENTIONS = None


class ParseError(Exception):
pass


def _interventions():
"""Get the dict mapping tag names to Intervention subclasses.
Expand All @@ -30,24 +35,34 @@ def _parse_intervention(line):
This find the Intervention plugin associated with the command
portion of the line. It then ues the plugin to construct the right
Intervention instance.
Raises:
ParseError: Unknown or malformed intervention encountered.
"""
assert line

(command, time, *args) = line.split()
try:
(command, time, *args) = line.split()
except ValueError:
raise ParseError(
'Interventions must follow the form "<name> <time> \
[args . . .]" (value={})'.format(
line))

command = command.lower()

try:
cls = _interventions()[command]
except KeyError:
raise ValueError(
raise ParseError(
'Unknown command "{}" while parsing interventions. '
'(full command={})'.format(
command, line))

try:
return cls.make_instance(int(time), *args)
except Exception as e:
raise ValueError(
raise ParseError(
'Invalid command while parsing intervention: {}'.format(
line)) from e

Expand All @@ -59,6 +74,9 @@ def parse_interventions(stream):
stream: A file-like object containing the interventions DSL.
Returns: An iterable of Intervention instances.
Raises:
ValueError: If there is an error parsing the stream.
"""
stripped_lines = map(str.strip, stream.readlines())
non_empty_lines = filter(bool, stripped_lines)
Expand Down
8 changes: 2 additions & 6 deletions bark_spider/simulation/schedule.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
from io import StringIO

from brooks.state import State
from brooks.communication import (
gompertz_overhead_proportion,
)

from ..intervention import parse_interventions


class Schedule:
def __init__(self, state, interventions):
Expand Down Expand Up @@ -48,6 +44,7 @@ def make_schedule(assimilation_delay,
Args:
assimilation_delay: Numer of days needed to assimilate new developers.
interventions: An iterable of `Intervention` instances.
Returns:
A new State object.
Expand All @@ -70,5 +67,4 @@ def make_schedule(assimilation_delay,
cumulative_person_days=0,
)

return Schedule(state,
parse_interventions(StringIO(interventions)))
return Schedule(state, interventions)
13 changes: 5 additions & 8 deletions bark_spider/simulation/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,13 @@
def run_simulation(params):
"""Run a set of simulations using various parameter sets.
Args:
params: A dict-like object that will be unpacked as the
arguments to schedule.make_schedule. In other words, it
should be key-value pairs defining the state variables for
the simulations. The "interventions" value should be a
string containing the intervention DSL to process.
Args: params: A dict-like object that will be unpacked as the arguments to
schedule.make_schedule. In other words, it should be key-value pairs
defining the state variables for the simulations. The "interventions"
value should be an iterable of `Intervention` instances.
Returns: A pandas.DataFrame with three columns - step_number,
elapsed_time, and software_development_rate.
elapsed_time, and software_development_rate.
"""
attributes = ['software_development_rate']

Expand Down
47 changes: 28 additions & 19 deletions bark_spider/static/js/controllers.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
function($scope, $http, $q) {
$scope.simulations = [];

$scope.error_messages = [];

// Create a new parameter set and append it to the list.
$scope.add_simulation = function(name) {
var sim = {
Expand Down Expand Up @@ -69,6 +71,7 @@
// renderings of the same data, i.e. as it arrives
// piecemeal.

$scope.error_messages = [];
var requests = _.map(
$scope.included_params(),
function (p) {
Expand All @@ -79,25 +82,31 @@
headers: {
'Content-Type': 'application/json'
}
}).then(function(response) {
return $http({
method: 'GET',
url: response.data.url
}).then(function(response) {
var name = response.data.name;
var results = response.data.results;
var parameters = response.data.parameters;

// Only update labels if we have more data points
var elapsed_time = results.elapsed_time;
if (_.size(elapsed_time) > labels.length) {
labels = _.values(elapsed_time);
}

series.push(name);
data.push(_.values(results.software_development_rate));
});
});
}).then(
function(response) {

return $http({
method: 'GET',
url: response.data.url
}).then(function(response) {
var name = response.data.name;
var results = response.data.results;
var parameters = response.data.parameters;

// Only update labels if we have more data points
var elapsed_time = results.elapsed_time;
if (_.size(elapsed_time) > labels.length) {
labels = _.values(elapsed_time);
}

series.push(name);
data.push(_.values(results.software_development_rate));
});
},
function(response) {
$scope.error_messages.push(response.data);
}
);
});

$q.all(requests).then(function(_) {
Expand Down
173 changes: 95 additions & 78 deletions bark_spider/templates/main_plot.pt
Original file line number Diff line number Diff line change
@@ -1,86 +1,103 @@
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" integrity="sha512-dTfge/zgoMYpP7QbHy4gWMEGsbsdZeCXz7irItjcC3sPUFtf0kuFbDz/ixG7ArTxmDjLXDmezHubeNikyKGVyQ==" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css" integrity="sha384-aUGj/X2zp5rLCbBxumKTCw2Z50WgIr1vs/PFN4praOTvYXWlVyh2UtNUU0KAUhAX" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-chart.js/0.8.5/angular-chart.min.css">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" integrity="sha512-dTfge/zgoMYpP7QbHy4gWMEGsbsdZeCXz7irItjcC3sPUFtf0kuFbDz/ixG7ArTxmDjLXDmezHubeNikyKGVyQ==" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css" integrity="sha384-aUGj/X2zp5rLCbBxumKTCw2Z50WgIr1vs/PFN4praOTvYXWlVyh2UtNUU0KAUhAX" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-chart.js/0.8.5/angular-chart.min.css">

<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>

<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js" integrity="sha512-K1qjQ+NcF2TYO/eI3M6v8EiNYZfA95pQumfvcVrTHtwQVDG+aHRqLi/ETn2uB+1JqwYqVG3LIvdm9lj6imS/pQ==" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-chart.js/0.8.5/angular-chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.14.3/ui-bootstrap-tpls.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js" integrity="sha512-K1qjQ+NcF2TYO/eI3M6v8EiNYZfA95pQumfvcVrTHtwQVDG+aHRqLi/ETn2uB+1JqwYqVG3LIvdm9lj6imS/pQ==" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-chart.js/0.8.5/angular-chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.14.3/ui-bootstrap-tpls.min.js"></script>

<script src="static/js/app.js"></script>
<script src="static/js/controllers.js"></script>
</head>
<body ng-app="BarkSpiderApp" ng-controller="BarkSpiderCtrl">
<script src="static/js/app.js"></script>
<script src="static/js/controllers.js"></script>
</head>
<body ng-app="BarkSpiderApp" ng-controller="BarkSpiderCtrl">

<div class="container-fluid">
<div class="row">
<div class="col-md-4">
<h1>Simulation parameters</h1>
<div class="container-fluid">
<div class="row">
<div class="col-md-4">
<h1>Simulation parameters</h1>

<button id="add-parameters-btn" type="button" class="btn btn-default" ng-click="add_simulation('New parameter set');">Add parameter set</button>
<button type="button" class="btn btn-primary pull-right" ng-click="simulate()" ng-disabled="included_params().length == 0">Run simulation</button>
<hr>
<div class="row">
<div class="col-md-12">
<button id="add-parameters-btn" type="button" class="btn btn-default" ng-click="add_simulation('New parameter set');">Add parameter set</button>
<button type="button" class="btn btn-primary pull-right" ng-click="simulate()" ng-disabled="included_params().length == 0">Run simulation</button>
</div>
</div>

<div ng-repeat="simulation in simulations" ng-controller="ParameterSetCtrl">
<div>
<div class="input-group input-group">
<span class="input-group-btn">
<button type="button" class="hide-show-parameters form-control btn btn-default" ng-click="opened = !opened">
<span class="glyphicon" ng-class="{'glyphicon-chevron-down': opened, 'glyphicon-chevron-right': !opened}"></span>
</button>
</span>
<input type="text" class="form-control" ng-model="simulation.name">
<div class="input-group-btn">
<button type="button" class="btn btn-default include-exclude-parameters" ng-click="simulation.included = !simulation.included" ng-class="{'btn-info': !simulation.included}">
<span ng-switch="simulation.included">
<span ng-switch-when="true">exclude</span>
<span ng-switch-when="false">include</span>
</span>
</button>
<button type="button" class="btn btn-default" ng-click="remove_parameter_set($index);">
delete
</button>
</div>
</div>
</div>
<div uib-collapse="!opened">
<form class="form-horizontal parameter-set-form">
<div class="form-group">
<label class="col-sm-2 control-label">Assimilation delay (days)</label>
<div class="col-sm-10">
<input class="form-control" type="number" min="0" value="20" ng-model="simulation.parameters.assimilation_delay"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Training overhead (0-1)</label>
<div class="col-sm-10">
<input class="form-control" type="number" min="0" value="1" ng-model="simulation.parameters.training_overhead_proportion"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Interventions</label>
<div class="col-sm-10">
<textarea class="form-control" ng-model="simulation.parameters.interventions"></textarea>
</div>
</div>
</form>
</div> <!-- uib-collapsed -->
</div> <!-- repeat -->
</div>
<div class="col-md-8">
<canvas id="software-development-rate-chart" class="chart chart-line" chart-data="data"
chart-labels="labels" chart-legend="true" chart-series="series"
chart-click="onClick"
chart-options="options">
</canvas>
</div>
</div>
</div>
</body>
<hr>

<div ng-repeat="simulation in simulations" ng-controller="ParameterSetCtrl">
<div>
<div class="input-group input-group">
<span class="input-group-btn">
<button type="button" class="hide-show-parameters form-control btn btn-default" ng-click="opened = !opened">
<span class="glyphicon" ng-class="{'glyphicon-chevron-down': opened, 'glyphicon-chevron-right': !opened}"></span>
</button>
</span>
<input type="text" class="form-control" ng-model="simulation.name">
<div class="input-group-btn">
<button type="button" class="btn btn-default include-exclude-parameters" ng-click="simulation.included = !simulation.included" ng-class="{'btn-info': !simulation.included}">
<span ng-switch="simulation.included">
<span ng-switch-when="true">exclude</span>
<span ng-switch-when="false">include</span>
</span>
</button>
<button type="button" class="btn btn-default" ng-click="remove_parameter_set($index);">
delete
</button>
</div>
</div>
</div>
<div uib-collapse="!opened">
<form class="form-horizontal parameter-set-form">
<div class="form-group">
<label class="col-sm-2 control-label">Assimilation delay (days)</label>
<div class="col-sm-10">
<input class="form-control" type="number" min="0" value="20" ng-model="simulation.parameters.assimilation_delay"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Training overhead (0-1)</label>
<div class="col-sm-10">
<input class="form-control" type="number" min="0" value="1" ng-model="simulation.parameters.training_overhead_proportion"/>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Interventions</label>
<div class="col-sm-10">
<textarea class="form-control" ng-model="simulation.parameters.interventions"></textarea>
</div>
</div>
</form>
</div> <!-- uib-collapsed -->
</div> <!-- repeat -->
</div>
<div class="col-md-8">
<div ng-show="error_messages.length == 0">
<canvas id="software-development-rate-chart" class="chart chart-line" chart-data="data"
chart-labels="labels" chart-legend="true" chart-series="series"
chart-click="onClick"
chart-options="options">
</canvas>
</div>

<div class="panel panel-default" ng-show="error_messages.length > 0">
<div class="panel-heading">Errors</div>
<div class="panel-body">
<div class="alert alert-danger" role="alert" ng-repeat="message in error_messages track by $index">
{{message}}
</div>
</div>
</div>

</div>
</div>
</div>
</body>
</html>
Loading

0 comments on commit 5812938

Please sign in to comment.