The ScenarioObserver
If you want to work with data from scenarios you need to create a scenario observer, from now on referred to as an 'observer'.
You create a new observer by configuring it to watch one or more scenarios and entities. You always need to declare the scenarios to watch but you can either specify a list of entities from those scenarios or that you just want to scenario state information itself.
Once registered and started an observer will fetch the data immediately and callback on a specified function. You can either configure it to just load the data as a one-off or, as is more common, you can configure it to call the specified function every time the data changes.
var view = insight.getView(); view.withFirstScenario() .withEntities('SCALAR1', 'ARRAY1', 'PARAMETER1', 'SET1') .notify(function(scenario) { console.log(scenario); }) .start();
Once an observer is declared you can either start that observer immediately (as above) or you can setup one or more observers and start them in one go when the view is started, for example:
// Create a few observers but don't call .start() on them // This will start any observers that have not yet been started view.start();
If you have created an observer with
ScenarioObserver#notify then you can stop that observer at any time by calling
ScenarioObserver#dispose:
var observer = view.withFirstScenario() .withEntities('SCALAR1', 'ARRAY1', 'PARAMETER1', 'SET1') .notify(function(scenario) { console.log(scenario); }) .start(); // A some other point in your code observer.dispose();
You can listen to multiple scenarios with
view.withAllScenarios() or
view.withScenarios(0,1). If you want to fetch data once and dispose the observer immediately after then you can use:
view.withFirstScenario() .withEntities('ARRAY1') .once(function(scenario) { scenario.getArray('ARRAY1'); }) .start();
When the observer notify/once callback is invoked it is passed either a single scenario (when
ScenarioObserver#withFirstScenario is used) or an array of scenarios (when
ScenarioObserver#withScenarios or
ScenarioObserver#withAllScenarios are used). These scenario objects are pre-loaded with the scenario properties, scenario summary data and all the entity data that has been requested. All the data is immutable, that is it will not change while the callback function is running: fresh objects will passed in on a future callback. Also, the scenario object will only allow you to access entities that were declared in the observer configuration.
// Single scenario view.withFirstScenario() .withEntities('ARRAY1', 'SET1') .notify(function(scenario) { var array1 = scenario.getArray('ARRAY1'); var set1 = scenario.getSet('SET1'); // This would throw an error as ARRAY2 has // not been requested var array2 = scenario.getArray('ARRAY2'); }) .start(); // Multi scenario view.withAllScenarios() .withEntities('ARRAY1') .notify(function(scenarios) { scenarios.forEach(function(scenario) { scenario.getArray('ARRAY1'); }); }) .start();
An observer can subscribe to entity data, scenario summary data or both. Scenario summary data is information about the current (if currently executing) or last solution (if completed, even in error). If you subscribe to just summary data then the notify callback will be called when any existing solution is deleted (a job has been queued) and when a new solution is available (a job has completed). It will not be called for any of the intermediate stages.
// With scenario summary data only view.withFirstScenario() .withSummaryData() .notify(function(scenario) { // You cannot access any entity data here as // no entities have been subscribed to var hasResultData = scenario.getSummaryData().hasResultData(); var objective = scenario.getSummaryData().getObjective(); }) .start();
When you subscribe to entities and scenario summary data then the notify callback will be called whenever the solution changes (as mentioned above) or when any of the entities change.
// With entity data and scenario summary data view.withFirstScenario() .withSummaryData() .withEntities('ARRAY1') .notify(function(scenario) { var array1 = scenario.getArray('ARRAY1'); var hasResultData = scenario.getSummaryData().hasResultData(); var objective = scenario.getSummaryData().getObjective(); }) .start();
It is best to split your view up with multiple scenario observers. Each one should be kept as small as possible, listening to the least number of entities possible, and keeping the responsibility of the notify callback to a minimum. The benefits of this are that you code is more maintainable, easier to separate into modules, and it minimizes the number of UI updates for any given entity change.