package human;
import rescuecore2.Constants;
import rescuecore2.misc.CommandLineOptions;
import rescuecore2.config.Config;
import rescuecore2.config.ConfigException;
import rescuecore2.connection.ConnectionException;
import rescuecore2.components.Agent;
import rescuecore2.components.ComponentLauncher;
import rescuecore2.components.TCPComponentLauncher;
import rescuecore2.components.ComponentConnectionException;
import rescuecore2.view.ViewComponent;
import rescuecore2.view.ViewListener;
import rescuecore2.view.RenderedObject;
import rescuecore2.messages.control.KVTimestep;
import rescuecore2.log.Logger;
import rescuecore2.standard.entities.Human;
import rescuecore2.standard.entities.Building;
import rescuecore2.standard.entities.Road;
import rescuecore2.standard.view.StandardWorldModelViewer;
import rescuecore2.standard.components.StandardViewer;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.BorderFactory;
import javax.swing.AbstractListModel;
import java.util.List;
import java.util.ArrayList;
import java.io.IOException;
/**
GUI for controlled agents.
*/
public class ControlledAgentGUI extends JPanel {
private static final int VIEW_SIZE = 500;
private List<ControlledFireBrigade> fbs;
private ListListModel fbListModel;
private JList fbList;
private List<ControlledPoliceForce> pfs;
private ListListModel pfListModel;
private JList pfList;
private List<ControlledAmbulanceTeam> ats;
private ListListModel atListModel;
private JList atList;
/**
Construct a ControlledAgentGUI.
@param view The view of the world.
*/
public ControlledAgentGUI(StandardWorldModelViewer view) {
super(new BorderLayout());
fbs = new ArrayList<ControlledFireBrigade>();
fbListModel = new ListListModel(fbs);
fbList = new JList(fbListModel);
pfs = new ArrayList<ControlledPoliceForce>();
pfListModel = new ListListModel(pfs);
pfList = new JList(pfListModel);
ats = new ArrayList<ControlledAmbulanceTeam>();
atListModel = new ListListModel(ats);
atList = new JList(atListModel);
// CHECKSTYLE:OFF:MagicNumber
JPanel agents = new JPanel(new GridLayout(3, 1));
// CHECKSTYLE:ON:MagicNumber
JScrollPane scroll = new JScrollPane(fbList);
scroll.setBorder(BorderFactory.createTitledBorder("Fire brigades"));
agents.add(scroll);
scroll = new JScrollPane(pfList);
scroll.setBorder(BorderFactory.createTitledBorder("Police forces"));
agents.add(scroll);
scroll = new JScrollPane(atList);
scroll.setBorder(BorderFactory.createTitledBorder("Ambulance teams"));
agents.add(scroll);
add(agents, BorderLayout.WEST);
add(view, BorderLayout.CENTER);
view.addViewListener(new ViewListener() {
@Override
public void objectsClicked(ViewComponent view, List<RenderedObject> objects) {
handleClick(objects);
}
@Override
public void objectsRollover(ViewComponent view, List<RenderedObject> objects) {
}
});
}
/**
Entry point.
@param args Command-line arguments.
*/
public static void main(String[] args) {
Config config = new Config();
try {
CommandLineOptions.processArgs(args, config);
}
catch (ConfigException e) {
Logger.error("Configuration error", e);
System.exit(-1);
}
catch (IOException e) {
Logger.error("Configuration error", e);
System.exit(-1);
}
StandardWorldModelViewer view = new StandardWorldModelViewer();
view.setPreferredSize(new Dimension(VIEW_SIZE, VIEW_SIZE));
ControlledAgentGUI gui = new ControlledAgentGUI(view);
JFrame frame = new JFrame("Controlled agents");
frame.add(gui);
frame.pack();
frame.setVisible(true);
// Connect a viewer and agents
int port = config.getIntValue(Constants.KERNEL_PORT_NUMBER_KEY, Constants.DEFAULT_KERNEL_PORT_NUMBER);
String host = config.getValue(Constants.KERNEL_HOST_NAME_KEY, Constants.DEFAULT_KERNEL_HOST_NAME);
ComponentLauncher launcher = new TCPComponentLauncher(host, port, config);
ControlViewer viewer = new ControlViewer(view, gui);
try {
launcher.connect(viewer);
}
catch (InterruptedException e) {
Logger.error("Interrupted", e);
System.exit(-1);
}
catch (ConnectionException e) {
Logger.error("Viewer connection failed", e);
System.exit(-1);
}
catch (ComponentConnectionException e) {
Logger.error("Viewer connection failed", e);
System.exit(-1);
}
gui.launchAgents(launcher);
}
private void launchAgents(ComponentLauncher launcher) {
// Connect as many fire brigades, police forces and ambulance teams as possible, but do it in a new thread.
new AgentConnector(launcher).start();
}
private void refreshLists() {
fbListModel.refresh();
pfListModel.refresh();
atListModel.refresh();
}
private void handleClick(List<RenderedObject> clicked) {
handleFBClick(clicked);
handlePFClick(clicked);
handleATClick(clicked);
}
private void handleFBClick(List<RenderedObject> clicked) {
for (RenderedObject next : clicked) {
if (next.getObject() instanceof Building) {
Building b = (Building)next.getObject();
for (ControlledFireBrigade agent : getSelectedFireBrigades()) {
agent.setTarget(b);
}
break;
}
}
fbListModel.refresh();
}
private void handlePFClick(List<RenderedObject> clicked) {
for (RenderedObject next : clicked) {
if (next.getObject() instanceof Road) {
Road r = (Road)next.getObject();
for (ControlledPoliceForce agent : getSelectedPoliceForces()) {
agent.setTarget(r);
}
break;
}
}
pfListModel.refresh();
}
private void handleATClick(List<RenderedObject> clicked) {
for (RenderedObject next : clicked) {
if (next.getObject() instanceof Human) {
Human h = (Human)next.getObject();
for (ControlledAmbulanceTeam agent : getSelectedAmbulanceTeams()) {
agent.setTarget(h);
}
break;
}
}
atListModel.refresh();
}
private List<ControlledFireBrigade> getSelectedFireBrigades() {
int[] selected = fbList.getSelectedIndices();
List<ControlledFireBrigade> agents = new ArrayList<ControlledFireBrigade>(selected.length);
for (int next : selected) {
agents.add(fbs.get(next));
}
return agents;
}
private List<ControlledPoliceForce> getSelectedPoliceForces() {
int[] selected = pfList.getSelectedIndices();
List<ControlledPoliceForce> agents = new ArrayList<ControlledPoliceForce>(selected.length);
for (int next : selected) {
agents.add(pfs.get(next));
}
return agents;
}
private List<ControlledAmbulanceTeam> getSelectedAmbulanceTeams() {
int[] selected = atList.getSelectedIndices();
List<ControlledAmbulanceTeam> agents = new ArrayList<ControlledAmbulanceTeam>(selected.length);
for (int next : selected) {
agents.add(ats.get(next));
}
return agents;
}
private static class ControlViewer extends StandardViewer {
private StandardWorldModelViewer view;
private ControlledAgentGUI gui;
public ControlViewer(StandardWorldModelViewer view, ControlledAgentGUI gui) {
this.view = view;
this.gui = gui;
}
@Override
protected void postConnect() {
view.view(model);
}
@Override
protected void handleTimestep(KVTimestep t) {
super.handleTimestep(t);
view.repaint();
gui.refreshLists();
}
}
private static class ListListModel extends AbstractListModel {
private List<?> data;
public ListListModel(List<?> data) {
this.data = data;
}
@Override
public int getSize() {
return data.size();
}
@Override
public Object getElementAt(int index) {
return data.get(index);
}
public void refresh() {
fireContentsChanged(this, 0, data.size());
}
}
private class AgentConnector extends Thread {
private ComponentLauncher launcher;
public AgentConnector(ComponentLauncher launcher) {
this.launcher = launcher;
}
@Override
public void run() {
connectAgents(new FireBrigadeAgentType(), fbs, fbListModel);
connectAgents(new PoliceForceAgentType(), pfs, pfListModel);
connectAgents(new AmbulanceTeamAgentType(), ats, atListModel);
}
private <T extends Agent> void connectAgents(AgentType<T> type, List<? super T> list, ListListModel model) {
int count = 0;
while (true) {
++count;
T agent = type.createAgent();
try {
launcher.connect(agent);
list.add(agent);
}
catch (ComponentConnectionException e) {
break;
}
catch (InterruptedException e) {
break;
}
catch (ConnectionException e) {
break;
}
}
model.refresh();
}
}
private interface AgentType<T extends Agent> {
/**
Create an Agent of the right type.
@return A new Agent implementation.
*/
T createAgent();
}
private static class FireBrigadeAgentType implements AgentType<ControlledFireBrigade> {
@Override
public ControlledFireBrigade createAgent() {
return new ControlledFireBrigade();
}
@Override
public String toString() {
return "fire brigade";
}
}
private static class PoliceForceAgentType implements AgentType<ControlledPoliceForce> {
@Override
public ControlledPoliceForce createAgent() {
return new ControlledPoliceForce();
}
@Override
public String toString() {
return "police force";
}
}
private static class AmbulanceTeamAgentType implements AgentType<ControlledAmbulanceTeam> {
@Override
public ControlledAmbulanceTeam createAgent() {
return new ControlledAmbulanceTeam();
}
@Override
public String toString() {
return "ambulance team";
}
}
}