package org.openlca.app.results.simulation;
import java.util.Set;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.editor.FormPage;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;
import org.openlca.app.M;
import org.openlca.app.db.Cache;
import org.openlca.app.util.Actions;
import org.openlca.app.util.Labels;
import org.openlca.app.util.Numbers;
import org.openlca.app.util.UI;
import org.openlca.app.viewers.combo.AbstractComboViewer;
import org.openlca.app.viewers.combo.FlowViewer;
import org.openlca.app.viewers.combo.ImpactCategoryViewer;
import org.openlca.core.math.CalculationSetup;
import org.openlca.core.model.Exchange;
import org.openlca.core.model.Flow;
import org.openlca.core.model.ProductSystem;
import org.openlca.core.model.Unit;
import org.openlca.core.model.descriptors.FlowDescriptor;
import org.openlca.core.model.descriptors.ImpactCategoryDescriptor;
import org.openlca.core.results.SimulationResult;
import org.openlca.core.results.SimulationResultProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SimulationPage extends FormPage {
private final int FLOW = 0;
private final int IMPACT = 1;
private int resultType = FLOW;
private SimulationEditor editor;
private StatisticsCanvas statisticsCanvas;
private ProgressBar progressBar;
private FlowViewer flowViewer;
private Section progressSection;
private ScrolledForm form;
private SimulationResultProvider<?> result;
private ImpactCategoryViewer impactViewer;
public SimulationPage(SimulationEditor editor) {
super(editor, "SimulationPage", M.MonteCarloSimulation);
this.editor = editor;
SimulationResult result = editor.getSimulator().getResult();
this.result = new SimulationResultProvider<>(result,
Cache.getEntityCache());
}
@Override
protected void createFormContent(IManagedForm managedForm) {
form = managedForm.getForm();
FormToolkit toolkit = managedForm.getToolkit();
form.setText(M.MonteCarloSimulation);
toolkit.decorateFormHeading(form.getForm());
Composite body = UI.formBody(form, toolkit);
createSettingsSection(toolkit, body);
createProgressSection(toolkit, body);
createResultSection(toolkit, body);
form.pack();
}
private void createSettingsSection(FormToolkit toolkit, Composite body) {
Composite settings = UI.formSection(body, toolkit, M.Settings);
Text systemText = UI
.formText(settings, toolkit, M.ProductSystem);
Text processText = UI.formText(settings, toolkit, M.Process);
Text qRefText = UI.formText(settings, toolkit,
M.QuantitativeReference);
Text simCountText = UI.formText(settings, toolkit,
M.NumberOfSimulations);
if (editor.getSetup() != null) {
CalculationSetup setup = editor.getSetup();
systemText.setText(setup.productSystem.getName());
processText.setText(setup.productSystem.getReferenceProcess()
.getName());
qRefText.setText(getQRefText());
simCountText.setText(Integer.toString(setup.numberOfRuns));
}
systemText.setEditable(false);
processText.setEditable(false);
qRefText.setEditable(false);
simCountText.setEditable(false);
}
private String getQRefText() {
try {
CalculationSetup setup = editor.getSetup();
ProductSystem system = setup.productSystem;
Exchange exchange = system.getReferenceExchange();
double amount = system.getTargetAmount();
Flow flow = exchange.getFlow();
Unit unit = system.getTargetUnit();
return String.format("%s %s %s", Numbers.format(amount, 2),
unit.getName(), Labels.getDisplayName(flow));
} catch (Exception e) {
Logger log = LoggerFactory.getLogger(getClass());
log.error("failed to create text for quan. ref.", e);
return "";
}
}
private void createProgressSection(FormToolkit toolkit, Composite body) {
progressSection = UI.section(body, toolkit, M.Progress);
Composite composite = UI.sectionClient(progressSection, toolkit);
progressBar = new ProgressBar(composite, SWT.SMOOTH);
progressBar.setMaximum(editor.getSetup().numberOfRuns);
UI.gridWidth(progressBar, 470);
final Button progressButton = toolkit.createButton(composite,
M.Start, SWT.NONE);
UI.gridWidth(progressButton, 70);
new SimulationControl(progressButton, editor, this);
}
private void createResultSection(FormToolkit toolkit, Composite body) {
if (result == null)
return;
Section section = UI.section(body, toolkit, M.Results);
SimulationExportAction exportAction = new SimulationExportAction(
result, editor.getSetup());
Actions.bind(section, exportAction);
Composite composite = UI.sectionClient(section, toolkit);
initFlowCheckViewer(toolkit, composite);
if (result.hasImpactResults())
initImpactCheckViewer(toolkit, composite);
statisticsCanvas = new StatisticsCanvas(body);
UI.gridData(statisticsCanvas, true, true).verticalIndent = 5;
}
private void initImpactCheckViewer(FormToolkit toolkit, Composite section) {
Button impactCheck = toolkit.createButton(section,
M.ImpactCategories, SWT.RADIO);
impactViewer = new ImpactCategoryViewer(section);
impactViewer.setEnabled(false);
Set<ImpactCategoryDescriptor> impacts = result.getImpactDescriptors();
impactViewer.setInput(impacts);
impactViewer.addSelectionChangedListener((e) -> updateSelection());
impactViewer.selectFirst();
new ResultTypeCheck<>(impactViewer, impactCheck, IMPACT);
}
private void initFlowCheckViewer(FormToolkit toolkit, Composite section) {
Button flowsCheck = toolkit.createButton(section, M.Flows,
SWT.RADIO);
flowsCheck.setSelection(true);
flowViewer = new FlowViewer(section, result.cache);
Set<FlowDescriptor> flows = result.getFlowDescriptors();
flowViewer.setInput(flows.toArray(new FlowDescriptor[flows.size()]));
flowViewer.selectFirst();
flowViewer.addSelectionChangedListener((e) -> updateSelection());
new ResultTypeCheck<>(flowViewer, flowsCheck, FLOW);
}
private void updateSelection() {
if (result == null || statisticsCanvas == null)
return;
if (resultType == FLOW) {
FlowDescriptor flow = flowViewer.getSelected();
if (flow != null)
statisticsCanvas.setValues(result.getFlowResults(flow));
} else {
ImpactCategoryDescriptor cat = impactViewer.getSelected();
if (cat != null)
statisticsCanvas.setValues(result.getImpactResults(cat));
}
}
void updateProgress() {
if (result == null)
return;
updateSelection();
progressBar.setSelection(progressBar.getSelection() + 1);
}
void progressDone(int numberOfIteration) {
// TODO: update count text etc.
// TODO: dispose the solver!
progressSection.setExpanded(false);
progressSection.pack();
progressSection.setVisible(false);
form.reflow(true);
}
private class ResultTypeCheck<T> implements SelectionListener {
private AbstractComboViewer<T> viewer;
private Button check;
private int type;
public ResultTypeCheck(AbstractComboViewer<T> viewer, Button check,
int type) {
this.viewer = viewer;
this.check = check;
this.type = type;
check.addSelectionListener(this);
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
@Override
public void widgetSelected(SelectionEvent e) {
if (check.getSelection()) {
viewer.setEnabled(true);
resultType = this.type;
updateSelection();
} else
viewer.setEnabled(false);
}
}
}