package vroom.optimization.online.jmsa.vrp.visu;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.util.Arrays;
import java.util.Date;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import vroom.common.modeling.dataModel.IVRPSolution;
import vroom.common.modeling.dataModel.attributes.RequestAttributeKey;
import vroom.optimization.online.jmsa.MSABase;
import vroom.optimization.online.jmsa.events.MSACallbackBase;
import vroom.optimization.online.jmsa.events.MSACallbackEvent;
import vroom.optimization.online.jmsa.events.MSACallbackEvent.EventTypes;
import vroom.optimization.online.jmsa.events.ResourceEvent;
import vroom.optimization.online.jmsa.vrp.MSAVRPInstance;
import vroom.optimization.online.jmsa.vrp.VRPRequest;
public class MSAInfoPanel extends JPanel implements ComponentListener {
private static final long serialVersionUID = 1L;
private MSABase<?, ?> mMSA;
private JTextArea mLogArea;
/** javadoc **/
private final double mPI;
private JSplitPane mSplit;
private JButton mPause;
private JButton mResume;
/**
* Getter for javadoc
*
* @return the value of perfect information
*/
public double getPI() {
return mPI;
}
/**
* Create the panel.
*
* @param msa
*/
public MSAInfoPanel(MSABase<?, ?> msa, double pi) {
mMSA = msa;
mPI = pi;
mMSA.registerCallback(EventTypes.EVENTS_RESOURCE, new UpdateCallback());
initialize();
}
private void initialize() {
setLayout(new BorderLayout());
// Log area
mLogArea = new JTextArea();
mLogArea.setEditable(false);
// Scroll
JScrollPane scrollLog = new JScrollPane(mLogArea);
scrollLog.setBorder(BorderFactory.createTitledBorder("Log"));
scrollLog.setAutoscrolls(true);
// Info
JTextArea info = new JTextArea();
info.setEditable(false);
info.setText(mMSA.getComponentsDescription());
JScrollPane scrollInfo = new JScrollPane(info);
scrollInfo.setBorder(BorderFactory.createTitledBorder("Info"));
scrollInfo.setAutoscrolls(true);
// Split Pane
mSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, false, scrollLog, scrollInfo);
mSplit.validate();
mSplit.setDividerLocation(0.8);
mSplit.setDividerSize(4);
mSplit.addComponentListener(this);
add(mSplit, BorderLayout.CENTER);
// Pause / Resume
JPanel controls = new JPanel();
controls.setLayout(new GridLayout(1, 2));
mPause = new JButton("Pause");
mResume = new JButton("Resume");
controls.add(mPause);
controls.add(mResume);
mPause.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
MSAInfoPanel.this.pause();
}
});
mResume.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
MSAInfoPanel.this.resume();
}
});
mResume.setEnabled(false);
// add(controls, BorderLayout.SOUTH);
}
protected void pause() {
mMSA.pause();
mResume.setEnabled(true);
mPause.setEnabled(false);
}
protected void resume() {
mMSA.resume();
mResume.setEnabled(false);
mPause.setEnabled(true);
}
public class UpdateCallback extends MSACallbackBase {
@Override
public int getPriority() {
return 100;
}
@Override
public boolean isExecutedSynchronously() {
return false;
}
@Override
public void execute(MSACallbackEvent event) {
if (event.getType() == EventTypes.EVENTS_RESOURCE) {
ResourceEvent ev = (ResourceEvent) event.getParams()[0];
switch (ev.getType()) {
case START:
log(ev, "Started");
break;
case STOP:
double cost = ((IVRPSolution<?>) mMSA.getCurrentSolution()).getCost();
log(ev, "Stopped");
log(ev, "Cost: %.3f", cost);
log(ev, "PI : %.3f", getPI());
log(ev, "Gap : %.1f%s", 100 * (cost - mPI) / mPI, "%");
break;
case REQUEST_ASSIGNED:
if (((VRPRequest) ev.getRequest()).isDepot()) {
log(ev, "A %s", ev.getRequest().getID());
} else {
log(ev,
"A %s d:%s",
ev.getRequest().getID(),
((VRPRequest) ev.getRequest()).getParentRequest().getAttribute(
RequestAttributeKey.DEMAND));
}
break;
case START_OF_SERVICE:
if (event.getParams().length == 3) {
// Failure
log(ev, "FAIL %s d:%s ex:%s", ev.getRequest().getID(),
Arrays.toString((double[]) ev.getAdditionalInformation()),
event.getParams()[2]);
} else {
log(ev, "SS %s d:%s", ev.getRequest().getID(),
Arrays.toString((double[]) ev.getAdditionalInformation()));
}
break;
case END_OF_SERVICE:
log(ev, "ES %s", ev.getRequest().getID());
break;
default:
log(ev, "Unknown event: %s", ev);
break;
}
}
}
private void log(ResourceEvent ev, String string, Object... params) {
MSAVRPInstance instance = (MSAVRPInstance) mMSA.getInstance();
double load = instance.getCurrentLoad(ev.getResourceId(), 0);
double cap = instance.getFleet().getVehicle(ev.getResourceId()).getCapacity();
Date now = new Date(System.currentTimeMillis());
mLogArea.append(String.format("\n%1$tH:%1$tM (%2$s/%3$s): %4$s", now, load, cap,
String.format(string, params)));
mLogArea.setCaretPosition(mLogArea.getDocument().getLength());
}
}
@Override
public void componentResized(ComponentEvent e) {
mSplit.setDividerLocation(0.8);
}
@Override
public void componentMoved(ComponentEvent e) {
}
@Override
public void componentShown(ComponentEvent e) {
mSplit.setDividerLocation(0.8);
}
@Override
public void componentHidden(ComponentEvent e) {
}
public void detach() {
mMSA = null;
}
}