Unverified Commit 342fea6f authored by Juon Kawakami's avatar Juon Kawakami 🥗
Browse files

init

parent 54f6cedf
package gis2.scenario;
import javax.swing.undo.AbstractUndoableEdit;
import maps.gml.GMLBuilding;
import maps.gml.GMLShape;
/**
* Tool for removing refuges.
*/
public class RemoveGasStationTool extends ShapeTool {
/**
* Construct a RemoveGasStationTool.
*
* @param editor The editor instance.
*/
public RemoveGasStationTool(ScenarioEditor editor) {
super(editor);
}
@Override
public String getName() {
return "Remove gas station";
}
@Override
protected boolean shouldHighlight(GMLShape shape) {
return shape instanceof GMLBuilding;
}
@Override
protected void processClick(GMLShape shape) {
editor.getScenario().removeGasStation(shape.getID());
editor.setChanged();
editor.updateOverlays();
editor.addEdit(new RemoveGasStationEdit(shape.getID()));
}
private class RemoveGasStationEdit extends AbstractUndoableEdit {
private int id;
public RemoveGasStationEdit(int id) {
this.id = id;
}
@Override
public void undo() {
super.undo();
editor.getScenario().addGasStation(id);
editor.updateOverlays();
}
@Override
public void redo() {
super.redo();
editor.getScenario().removeGasStation(id);
editor.updateOverlays();
}
}
}
\ No newline at end of file
package gis2.scenario;
import javax.swing.undo.AbstractUndoableEdit;
import maps.gml.GMLRoad;
import maps.gml.GMLShape;
/**
* Tool for removing refuges.
*/
public class RemoveHydrantTool extends ShapeTool {
/**
* Construct a RemoveHydrantTool.
*
* @param editor The editor instance.
*/
public RemoveHydrantTool(ScenarioEditor editor) {
super(editor);
}
@Override
public String getName() {
return "Remove hydrant";
}
@Override
protected boolean shouldHighlight(GMLShape shape) {
return shape instanceof GMLRoad;
}
@Override
protected void processClick(GMLShape shape) {
editor.getScenario().removeHydrant(shape.getID());
editor.setChanged();
editor.updateOverlays();
editor.addEdit(new RemoveHydrantEdit(shape.getID()));
}
private class RemoveHydrantEdit extends AbstractUndoableEdit {
private int id;
public RemoveHydrantEdit(int id) {
this.id = id;
}
@Override
public void undo() {
super.undo();
editor.getScenario().addHydrant(id);
editor.updateOverlays();
}
@Override
public void redo() {
super.redo();
editor.getScenario().removeHydrant(id);
editor.updateOverlays();
}
}
}
\ No newline at end of file
package gis2.scenario;
import javax.swing.undo.AbstractUndoableEdit;
import maps.gml.GMLShape;
/**
* Tool for removing police forces.
*/
public class RemovePoliceForceTool extends ShapeTool {
/**
* Construct a RemovePoliceForceTool.
*
* @param editor The editor instance.
*/
public RemovePoliceForceTool(ScenarioEditor editor) {
super(editor);
}
@Override
public String getName() {
return "Remove police force";
}
@Override
protected boolean shouldHighlight(GMLShape shape) {
return true;
}
@Override
protected void processClick(GMLShape shape) {
editor.getScenario().removePoliceForce(shape.getID());
editor.setChanged();
editor.updateOverlays();
editor.addEdit(new RemovePoliceForceEdit(shape.getID()));
}
private class RemovePoliceForceEdit extends AbstractUndoableEdit {
private int id;
public RemovePoliceForceEdit(int id) {
this.id = id;
}
@Override
public void undo() {
super.undo();
editor.getScenario().addPoliceForce(id);
editor.updateOverlays();
}
@Override
public void redo() {
super.redo();
editor.getScenario().removePoliceForce(id);
editor.updateOverlays();
}
}
}
\ No newline at end of file
package gis2.scenario;
import javax.swing.undo.AbstractUndoableEdit;
import maps.gml.GMLBuilding;
import maps.gml.GMLShape;
/**
* Tool for removing police offices.
*/
public class RemovePoliceOfficeTool extends ShapeTool {
/**
* Construct a RemovePoliceOfficeTool.
*
* @param editor The editor instance.
*/
public RemovePoliceOfficeTool(ScenarioEditor editor) {
super(editor);
}
@Override
public String getName() {
return "Remove police office";
}
@Override
protected boolean shouldHighlight(GMLShape shape) {
return shape instanceof GMLBuilding;
}
@Override
protected void processClick(GMLShape shape) {
editor.getScenario().removePoliceOffice(shape.getID());
editor.setChanged();
editor.updateOverlays();
editor.addEdit(new RemovePoliceOfficeEdit(shape.getID()));
}
private class RemovePoliceOfficeEdit extends AbstractUndoableEdit {
private int id;
public RemovePoliceOfficeEdit(int id) {
this.id = id;
}
@Override
public void undo() {
super.undo();
editor.getScenario().addPoliceOffice(id);
editor.updateOverlays();
}
@Override
public void redo() {
super.redo();
editor.getScenario().removePoliceOffice(id);
editor.updateOverlays();
}
}
}
\ No newline at end of file
package gis2.scenario;
import javax.swing.undo.AbstractUndoableEdit;
import maps.gml.GMLBuilding;
import maps.gml.GMLShape;
/**
* Tool for removing refuges.
*/
public class RemoveRefugeTool extends ShapeTool {
/**
* Construct a RemoveRefugeTool.
*
* @param editor The editor instance.
*/
public RemoveRefugeTool(ScenarioEditor editor) {
super(editor);
}
@Override
public String getName() {
return "Remove refuge";
}
@Override
protected boolean shouldHighlight(GMLShape shape) {
return shape instanceof GMLBuilding;
}
@Override
protected void processClick(GMLShape shape) {
editor.getScenario().removeRefuge(shape.getID());
editor.setChanged();
editor.updateOverlays();
editor.addEdit(new RemoveRefugeEdit(shape.getID()));
}
private class RemoveRefugeEdit extends AbstractUndoableEdit {
private int id;
public RemoveRefugeEdit(int id) {
this.id = id;
}
@Override
public void undo() {
super.undo();
editor.getScenario().addRefuge(id);
editor.updateOverlays();
}
@Override
public void redo() {
super.redo();
editor.getScenario().removeRefuge(id);
editor.updateOverlays();
}
}
}
\ No newline at end of file
package gis2.scenario;
import gis2.GisScenario;
import gis2.ScenarioException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.filechooser.FileFilter;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
import maps.MapException;
import maps.MapReader;
import maps.gml.GMLMap;
import maps.gml.GMLRefuge;
import maps.gml.view.DecoratorOverlay;
import maps.gml.view.FilledShapeDecorator;
import maps.gml.view.GMLMapViewer;
import maps.gml.view.GMLObjectInspector;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import rescuecore2.config.Config;
/**
* A component for editing scenarios.
*/
public class ScenarioEditor extends JPanel {
private static final int VIEWER_PREFERRED_SIZE = 500;
private static final int INSPECTOR_PREFERRED_WIDTH = 300;
private static final int INSPECTOR_PREFERRED_HEIGHT = 500;
private static final Color FIRE_COLOUR = new Color(255, 0, 0, 128);
private static final Color FIRE_STATION_COLOUR = new Color(255, 255, 0);
private static final Color POLICE_OFFICE_COLOUR = new Color(0, 0, 255);
private static final Color AMBULANCE_CENTRE_COLOUR = new Color(255, 255, 255);
private static final Color REFUGE_COLOUR = new Color(0, 128, 0);
private static final Color HYDRANT_COLOUR = new Color(128, 128, 0);
private static final Color GAS_STATION_COLOUR = new Color(255, 128, 0);
private GMLMap map;
private GMLMapViewer viewer;
private GMLObjectInspector inspector;
private DecoratorOverlay fireOverlay;
private DecoratorOverlay centreOverlay;
private transient AgentOverlay agentOverlay;
private GisScenario scenario;
private Tool currentTool;
private JLabel statusLabel;
private boolean changed;
private UndoManager undoManager;
private transient Action undoAction;
private transient Action redoAction;
private File baseDir;
private File saveFile;
private FilledShapeDecorator fireDecorator = new FilledShapeDecorator(
FIRE_COLOUR, null, null);
private FilledShapeDecorator fireStationDecorator = new FilledShapeDecorator(
FIRE_STATION_COLOUR, null, null);
private FilledShapeDecorator policeOfficeDecorator = new FilledShapeDecorator(
POLICE_OFFICE_COLOUR, null, null);
private FilledShapeDecorator ambulanceCentreDecorator = new FilledShapeDecorator(
AMBULANCE_CENTRE_COLOUR, null, null);
private FilledShapeDecorator refugeDecorator = new FilledShapeDecorator(
REFUGE_COLOUR, null, null);
private FilledShapeDecorator gasStationDecorator = new FilledShapeDecorator(
GAS_STATION_COLOUR, null, null);
private FilledShapeDecorator hydrantDecorator = new FilledShapeDecorator(null,
HYDRANT_COLOUR, null);
/**
* Construct a new ScenarioEditor.
*
* @param menuBar
* The menu bar to add menus to.
*/
public ScenarioEditor(JMenuBar menuBar) {
this(menuBar, null, null);
}
/**
* Construct a new ScenarioEditor.
*
* @param menuBar
* The menu bar to add menus to.
* @param map
* The GMLMap to view.
* @param scenario
* The scenario to edit.
*/
public ScenarioEditor(JMenuBar menuBar, GMLMap map, GisScenario scenario) {
super(new BorderLayout());
this.map = map;
this.scenario = scenario;
viewer = new GMLMapViewer(map);
viewer.setPaintNodes(false);
statusLabel = new JLabel("Status");
fireOverlay = new DecoratorOverlay();
centreOverlay = new DecoratorOverlay();
agentOverlay = new AgentOverlay(this);
viewer.addOverlay(fireOverlay);
viewer.addOverlay(centreOverlay);
viewer.addOverlay(agentOverlay);
inspector = new GMLObjectInspector(map);
undoManager = new UndoManager();
viewer.setPreferredSize(
new Dimension(VIEWER_PREFERRED_SIZE, VIEWER_PREFERRED_SIZE));
inspector.setPreferredSize(
new Dimension(INSPECTOR_PREFERRED_WIDTH, INSPECTOR_PREFERRED_HEIGHT));
viewer.setBackground(Color.GRAY);
viewer.getPanZoomListener().setPanOnRightMouse();
changed = false;
JToolBar fileToolbar = new JToolBar("File");
JToolBar editToolbar = new JToolBar("Edit");
JToolBar toolsToolbar = new JToolBar("Tools");
toolsToolbar.setLayout(new ModifiedFlowLayout());
JToolBar functionsToolbar = new JToolBar("Functions");
JMenu fileMenu = new JMenu("File", false);
JMenu editMenu = new JMenu("Edit", false);
JMenu toolsMenu = new JMenu("Tools", false);
JMenu functionsMenu = new JMenu("Functions", false);
createFileActions(fileMenu, fileToolbar);
createEditActions(editMenu, editToolbar);
createToolActions(toolsMenu, toolsToolbar);
createFunctionActions(functionsMenu, functionsToolbar);
JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, viewer,
inspector);
add(split, BorderLayout.CENTER);
JPanel toolbars = new JPanel(new ModifiedFlowLayout());
toolbars.add(fileToolbar);
toolbars.add(editToolbar);
toolbars.add(functionsToolbar);
toolbars.add(toolsToolbar);
add(toolbars, BorderLayout.NORTH);
add(statusLabel, BorderLayout.SOUTH);
menuBar.add(fileMenu);
menuBar.add(editMenu);
menuBar.add(toolsMenu);
menuBar.add(functionsMenu);
baseDir = new File(System.getProperty("user.dir"));
saveFile = null;
}
/**
* Entry point.
*
* @param args
* Command line arguments.
*/
public static void main(String[] args) {
final JFrame frame = new JFrame("Scenario Editor");
JMenuBar menuBar = new JMenuBar();
final ScenarioEditor editor = new ScenarioEditor(menuBar);
if (args.length > 0 && args[0].length() > 0) {
try {
editor.load(args[0]);
} catch (CancelledByUserException e) {
return;
} catch (MapException e) {
e.printStackTrace();
} catch (ScenarioException e) {
e.printStackTrace();
} catch (rescuecore2.scenario.exceptions.ScenarioException e) {
e.printStackTrace();
}
}
frame.setJMenuBar(menuBar);
frame.setContentPane(editor);
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
frame.pack();
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
try {
editor.close();
frame.setVisible(false);
frame.dispose();
System.exit(0);
} catch (CancelledByUserException ex) {
frame.setVisible(true);
}
}
});
frame.setVisible(true);
}
/**
* Load a map and scenario by showing a file chooser dialog.
*
* @throws CancelledByUserException
* If the user cancels
* the change due to
* unsaved changes.
* @throws MapException
* If there is a
* problem reading the
* map.
* @throws ScenarioException
* If there is a
* problem reading the
* scenario.
* @throws rescuecore2.scenario.exceptions.ScenarioException
*/
public void load() throws CancelledByUserException, MapException,
ScenarioException, rescuecore2.scenario.exceptions.ScenarioException {
JFileChooser chooser = new JFileChooser(baseDir);
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setFileFilter(new FileFilter() {
@Override
public boolean accept(File f) {
return f.isDirectory();
}
@Override
public String getDescription() {
return "Directories";
}
});
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
load(chooser.getSelectedFile());
}
}
/**
* Load a map and scenario from a directory.
*
* @param filename
* The name of the file to read.
*
* @throws CancelledByUserException
* If the user cancels
* the change due to
* unsaved changes.
* @throws MapException
* If there is a
* problem reading the
* map.
* @throws ScenarioException
* If there is a
* problem reading the
* scenario.
* @throws rescuecore2.scenario.exceptions.ScenarioException
*/
public void load(String filename)
throws CancelledByUserException, MapException, ScenarioException,
rescuecore2.scenario.exceptions.ScenarioException {
load(new File(filename));
}
/**
* Load a map and scenario from a directory.
*
* @param dir
* The directory to read.
*
* @throws CancelledByUserException
* If the user cancels
* the change due to
* unsaved changes.
* @throws MapException
* If there is a
* problem reading the
* map.
* @throws ScenarioException
* If there is a
* problem reading the
* scenario.
* @throws rescuecore2.scenario.exceptions.ScenarioException
*/
public void load(File dir) throws CancelledByUserException, MapException,
ScenarioException, rescuecore2.scenario.exceptions.ScenarioException {
try (FileReader r = new FileReader(new File(dir, "scenario.xml"))) {
GMLMap newMap = (GMLMap) MapReader.readMap(new File(dir, "map.gml"));
SAXReader saxReader = new SAXReader();
Document doc = saxReader.read(r);
GisScenario newScenario = new GisScenario(doc, new Config());
setScenario(newMap, newScenario);
baseDir = dir;
saveFile = new File(dir, "scenario.xml");
} catch (IOException | DocumentException e) {
throw new ScenarioException(e);
}
}
/**
* Set the map and scenario.
*
* @param newMap
* The new map.
* @param newScenario
* The new scenario.
*
* @throws CancelledByUserException
* If the user cancels the change due to
* unsaved changes.
*/
public void setScenario(GMLMap newMap, GisScenario newScenario)
throws CancelledByUserException {
checkForChanges();
if (!checkScenario(newMap, newScenario)) {
JOptionPane.showMessageDialog(null,
"The scenario file contained errors.");
return;
}
map = newMap;
scenario = newScenario;
changed = false;
viewer.setMap(map);
inspector.setMap(map);
updateOverlays();
}
public void updateGMLRefuges() {
for (int next : scenario.getRefuges()) {
GMLRefuge refuge = new GMLRefuge(next, map.getBuilding(next).getEdges());
refuge.setBedCapacity(scenario.getRefugeBedCapacity().get(next));
refuge.setRefillCapacity(scenario.getRefugeRefillCapacity().get(next));
scenario.addGMLRefuge(refuge);
}
}
/**
* Get the map.
*
* @return The map.
*/
public GMLMap getMap() {
return map;
}
/**
* Get the scenario.
*
* @return The scenario.
*/
public GisScenario getScenario() {
return scenario;
}
/**
* Save the scenario.
*
* @throws ScenarioException
* If there is a problem saving the scenario.
*/
public void save() throws ScenarioException {
if (saveFile == null) {
saveAs();
}
if (saveFile != null) {
Document doc = DocumentHelper.createDocument();
scenario.write(doc);
try {
if (!saveFile.exists()) {
File parent = saveFile.getParentFile();
if ((!parent.exists()) && (!saveFile.getParentFile().mkdirs())) {
throw new ScenarioException(
"Couldn't create file " + saveFile.getPath());
}
if (!saveFile.createNewFile()) {
throw new ScenarioException(
"Couldn't create file " + saveFile.getPath());
}
}
XMLWriter writer = new XMLWriter(new FileOutputStream(saveFile),
OutputFormat.createPrettyPrint());
writer.write(doc);
writer.flush();
writer.close();
} catch (IOException e) {
throw new ScenarioException(e);
}
baseDir = saveFile.getParentFile();
changed = false;
}
}
/**
* Save the scenario.
*
* @throws ScenarioException
* If there is a problem saving the scenario.
*/
public void saveAs() throws ScenarioException {
JFileChooser chooser = new JFileChooser(baseDir);
if (chooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
saveFile = chooser.getSelectedFile();
save();
}
}
/**
* Close the editor.
*
* @throws CancelledByUserException
* If the user cancels the close due to unsaved
* changes."
*/
public void close() throws CancelledByUserException {
checkForChanges();
}
/**
* Get the map viewer.
*
* @return The map viewer.
*/
public GMLMapViewer getViewer() {
return viewer;
}
/**
* Get the object inspector.
*
* @return The object inspector.
*/
public GMLObjectInspector getInspector() {
return inspector;
}
/**
* Register a change to the map.
*/
public void setChanged() {
changed = true;
}
/**
* Register an undoable edit.
*
* @param edit
* The edit to add.
*/
public void addEdit(UndoableEdit edit) {
undoManager.addEdit(edit);
undoAction.setEnabled(undoManager.canUndo());
redoAction.setEnabled(undoManager.canRedo());
}
/**
* Update the overlay views.
*/
public void updateOverlays() {
updateGMLRefuges();
updateFireOverlay();
updateCentreOverlay();
updateAgentOverlay();
updateStatusLabel();
viewer.repaint();
}
private void checkForChanges() throws CancelledByUserException {
if (changed) {
switch (JOptionPane.showConfirmDialog(null,
"The current scenario has changes. Do you want to save them?")) {
case JOptionPane.YES_OPTION:
try {
save();
} catch (ScenarioException e) {
JOptionPane.showMessageDialog(null, e);
throw new CancelledByUserException();
}
break;
case JOptionPane.NO_OPTION:
changed = false;
return;
case JOptionPane.CANCEL_OPTION:
throw new CancelledByUserException();
default:
throw new RuntimeException(
"JOptionPane.showConfirmDialog returned something weird");
}
}
}
private void createFileActions(JMenu menu, JToolBar toolbar) {
Action newAction = new AbstractAction("New") {
@Override
public void actionPerformed(ActionEvent e) {
try {
checkForChanges();
setScenario(map, new GisScenario());
} catch (CancelledByUserException ex) {
}
}
};
Action loadAction = new AbstractAction("Load") {
@Override
public void actionPerformed(ActionEvent e) {
try {
checkForChanges();
load();
} catch (CancelledByUserException ex) {
} catch (MapException | ScenarioException ex) {
JOptionPane.showMessageDialog(null, ex);
} catch (rescuecore2.scenario.exceptions.ScenarioException ex) {
ex.printStackTrace();
}
}
};
Action saveAction = new AbstractAction("Save") {
@Override
public void actionPerformed(ActionEvent e) {
try {
save();
} catch (ScenarioException ex) {
JOptionPane.showMessageDialog(null, ex);
}
}
};
Action saveAsAction = new AbstractAction("Save as") {
@Override
public void actionPerformed(ActionEvent e) {
try {
saveAs();
} catch (ScenarioException ex) {
JOptionPane.showMessageDialog(null, ex);
}
}
};
toolbar.add(newAction);
toolbar.add(loadAction);
toolbar.add(saveAction);
toolbar.add(saveAsAction);
menu.add(newAction);
menu.add(loadAction);
menu.add(saveAction);
menu.add(saveAsAction);
}
private void createEditActions(JMenu menu, JToolBar toolbar) {
undoAction = new AbstractAction("Undo") {
@Override
public void actionPerformed(ActionEvent e) {
try {
undoManager.undo();
} catch (CannotUndoException ex) {
JOptionPane.showMessageDialog(null, ex);
}
setEnabled(undoManager.canUndo());
redoAction.setEnabled(undoManager.canRedo());
}
};
redoAction = new AbstractAction("Redo") {
@Override
public void actionPerformed(ActionEvent e) {
try {
undoManager.redo();
} catch (CannotUndoException ex) {
JOptionPane.showMessageDialog(null, ex);
}
setEnabled(undoManager.canRedo());
undoAction.setEnabled(undoManager.canUndo());
}
};
undoAction.setEnabled(false);
redoAction.setEnabled(false);
toolbar.add(undoAction);
toolbar.add(redoAction);
menu.add(undoAction);
menu.add(redoAction);
}
private void createToolActions(JMenu menu, JToolBar toolbar) {
ButtonGroup toolbarGroup = new ButtonGroup();
ButtonGroup menuGroup = new ButtonGroup();
menu.addSeparator();
toolbar.addSeparator();
addTool(new PlaceFireTool(this), menu, toolbar, menuGroup, toolbarGroup);
addTool(new RemoveFireTool(this), menu, toolbar, menuGroup, toolbarGroup);
addTool(new PlaceRefugeTool(this), menu, toolbar, menuGroup, toolbarGroup);
addTool(new RemoveRefugeTool(this), menu, toolbar, menuGroup, toolbarGroup);
addTool(new PlaceGasStationTool(this), menu, toolbar, menuGroup,
toolbarGroup);
addTool(new RemoveGasStationTool(this), menu, toolbar, menuGroup,
toolbarGroup);
addTool(new PlaceHydrantTool(this), menu, toolbar, menuGroup, toolbarGroup);
addTool(new RemoveHydrantTool(this), menu, toolbar, menuGroup,
toolbarGroup);
addTool(new PlaceCivilianTool(this), menu, toolbar, menuGroup,
toolbarGroup);
addTool(new RemoveCivilianTool(this), menu, toolbar, menuGroup,
toolbarGroup);
menu.addSeparator();
toolbar.addSeparator();
addTool(new PlaceFireBrigadeTool(this), menu, toolbar, menuGroup,
toolbarGroup);
addTool(new RemoveFireBrigadeTool(this), menu, toolbar, menuGroup,
toolbarGroup);
addTool(new PlacePoliceForceTool(this), menu, toolbar, menuGroup,
toolbarGroup);
addTool(new RemovePoliceForceTool(this), menu, toolbar, menuGroup,
toolbarGroup);
addTool(new PlaceAmbulanceTeamTool(this), menu, toolbar, menuGroup,
toolbarGroup);
addTool(new RemoveAmbulanceTeamTool(this), menu, toolbar, menuGroup,
toolbarGroup);
menu.addSeparator();
toolbar.addSeparator();
addTool(new PlaceFireStationTool(this), menu, toolbar, menuGroup,
toolbarGroup);
addTool(new RemoveFireStationTool(this), menu, toolbar, menuGroup,
toolbarGroup);
addTool(new PlacePoliceOfficeTool(this), menu, toolbar, menuGroup,
toolbarGroup);
addTool(new RemovePoliceOfficeTool(this), menu, toolbar, menuGroup,
toolbarGroup);
addTool(new PlaceAmbulanceCentreTool(this), menu, toolbar, menuGroup,
toolbarGroup);
addTool(new RemoveAmbulanceCentreTool(this), menu, toolbar, menuGroup,
toolbarGroup);
}
private void createFunctionActions(JMenu menu, JToolBar toolbar) {
addFunction(new RandomiseFunction(this), menu, toolbar);
addFunction(new ClearFiresFunction(this), menu, toolbar);
addFunction(new ClearAgentsFunction(this), menu, toolbar);
addFunction(new ClearAllFunction(this), menu, toolbar);
addFunction(new PlaceAgentsFunction(this), menu, toolbar);
addFunction(new RandomHydrantPlacementFunction(this), menu, toolbar);
}
private void addTool(final Tool t, JMenu menu, JToolBar toolbar,
ButtonGroup menuGroup, ButtonGroup toolbarGroup) {
final JToggleButton toggle = new JToggleButton();
final JCheckBoxMenuItem check = new JCheckBoxMenuItem();
Action action = new AbstractAction(t.getName()) {
@Override
public void actionPerformed(ActionEvent e) {
if (currentTool != null) {
currentTool.deactivate();
}
currentTool = t;
toggle.setSelected(true);
check.setSelected(true);
currentTool.activate();
}
};
toggle.setAction(action);
check.setAction(action);
menu.add(check);
toolbar.add(toggle);
menuGroup.add(check);
toolbarGroup.add(toggle);
}
private void addFunction(final Function f, JMenu menu, JToolBar toolbar) {
Action action = new AbstractAction(f.getName()) {
@Override
public void actionPerformed(ActionEvent e) {
f.execute();
}
};
toolbar.add(action);
menu.add(action);
}
private boolean checkScenario(GMLMap newMap, GisScenario newScenario) {
boolean valid = true;
for (int id : newScenario.getFires()) {
if (newMap.getBuilding(id) == null) {
valid = false;
}
}
for (int id : newScenario.getRefuges()) {
if (newMap.getBuilding(id) == null) {
valid = false;
}
}
for (int id : newScenario.getHydrants()) {
if (newMap.getRoad(id) == null) {
valid = false;
}
}
for (int id : newScenario.getFireStations()) {
if (newMap.getBuilding(id) == null) {
valid = false;
}
}
for (int id : newScenario.getAmbulanceCentres()) {
if (newMap.getBuilding(id) == null) {
valid = false;
}
}
for (int id : newScenario.getPoliceOffices()) {
if (newMap.getBuilding(id) == null) {
valid = false;
}
}
for (int id : newScenario.getCivilians()) {
if (newMap.getShape(id) == null) {
valid = false;
}
}
for (int id : newScenario.getFireBrigades()) {
if (newMap.getShape(id) == null) {
valid = false;
}
}
for (int id : newScenario.getAmbulanceTeams()) {
if (newMap.getShape(id) == null) {
valid = false;
}
}
for (int id : newScenario.getPoliceForces()) {
if (newMap.getShape(id) == null) {
valid = false;
}
}
return valid;
}
private void updateStatusLabel() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
statusLabel.setText(scenario.getFires().size() + " fires, "
+ scenario.getRefuges().size() + " refuges, "
+ scenario.getHydrants().size() + " hydrants, "
+ scenario.getGasStations().size() + " gas stations, "
+ scenario.getCivilians().size() + " civilians, "
+ scenario.getFireBrigades().size() + " fb, "
+ scenario.getFireStations().size() + " fs, "
+ scenario.getPoliceForces().size() + " pf, "
+ scenario.getPoliceOffices().size() + " po, "
+ scenario.getAmbulanceTeams().size() + " at, "
+ scenario.getAmbulanceCentres().size() + " ac");
}
});
}
private void updateFireOverlay() {
fireOverlay.clearAllBuildingDecorators();
for (int next : scenario.getFires()) {
fireOverlay.setBuildingDecorator(fireDecorator, map.getBuilding(next));
}
}
private void updateCentreOverlay() {
centreOverlay.clearAllBuildingDecorators();
centreOverlay.clearAllRoadDecorators();
for (int next : scenario.getFireStations()) {
centreOverlay.setBuildingDecorator(fireStationDecorator,
map.getBuilding(next));
}
for (int next : scenario.getPoliceOffices()) {
centreOverlay.setBuildingDecorator(policeOfficeDecorator,
map.getBuilding(next));
}
for (int next : scenario.getAmbulanceCentres()) {
centreOverlay.setBuildingDecorator(ambulanceCentreDecorator,
map.getBuilding(next));
}
for (int next : scenario.getRefuges()) {
centreOverlay.setBuildingDecorator(refugeDecorator,
scenario.getRefuge(next));
}
for (int next : scenario.getGasStations()) {
centreOverlay.setBuildingDecorator(gasStationDecorator,
map.getBuilding(next));
}
for (int next : scenario.getHydrants()) {
centreOverlay.setRoadDecorator(hydrantDecorator, map.getRoad(next));
}
}
private void updateAgentOverlay() {
}
}
\ No newline at end of file
package gis2.scenario;
import java.awt.Color;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import maps.gml.GMLBuilding;
import maps.gml.GMLCoordinates;
import maps.gml.GMLRoad;
import maps.gml.GMLShape;
import maps.gml.GMLSpace;
import maps.gml.view.FilledShapeDecorator;
/**
* Abstract base class for tools that operate on GML shapes.
*/
public abstract class ShapeTool extends AbstractTool {
private static final Color HIGHLIGHT_COLOUR = new Color(0, 0, 255, 128);
private Listener listener;
private FilledShapeDecorator highlight;
private GMLShape highlightShape;
/**
* Construct a ShapeTool.
*
* @param editor The editor instance.
*/
public ShapeTool(ScenarioEditor editor) {
super(editor);
listener = new Listener();
highlight = new FilledShapeDecorator(HIGHLIGHT_COLOUR, HIGHLIGHT_COLOUR, HIGHLIGHT_COLOUR);
}
@Override
public void activate() {
editor.getViewer().addMouseListener(listener);
editor.getViewer().addMouseMotionListener(listener);
highlightShape = null;
}
@Override
public void deactivate() {
editor.getViewer().removeMouseListener(listener);
editor.getViewer().removeMouseMotionListener(listener);
editor.getViewer().clearAllBuildingDecorators();
editor.getViewer().clearAllRoadDecorators();
editor.getViewer().clearAllSpaceDecorators();
editor.getViewer().repaint();
}
/**
* Handle a click on a shape.
*
* @param shape The shape that was clicked.
*/
protected abstract void processClick(GMLShape shape);
/**
* Find out if a shape should be highlighted or not. Only highlighted shapes can
* be clicked.
*
* @param shape The shape to check.
* @return True if the shape should be highlighted, false otherwise.
*/
protected abstract boolean shouldHighlight(GMLShape shape);
private void highlight(GMLShape newShape) {
if (!shouldHighlight(newShape)) {
return;
}
if (highlightShape == newShape) {
return;
}
if (highlightShape != null) {
if (highlightShape instanceof GMLBuilding) {
editor.getViewer().clearBuildingDecorator((GMLBuilding) highlightShape);
}
if (highlightShape instanceof GMLRoad) {
editor.getViewer().clearRoadDecorator((GMLRoad) highlightShape);
}
if (highlightShape instanceof GMLSpace) {
editor.getViewer().clearSpaceDecorator((GMLSpace) highlightShape);
}
}
highlightShape = newShape;
if (highlightShape != null) {
if (highlightShape instanceof GMLBuilding) {
editor.getViewer().setBuildingDecorator(highlight, (GMLBuilding) highlightShape);
}
if (highlightShape instanceof GMLRoad) {
editor.getViewer().setRoadDecorator(highlight, (GMLRoad) highlightShape);
}
if (highlightShape instanceof GMLSpace) {
editor.getViewer().setSpaceDecorator(highlight, (GMLSpace) highlightShape);
}
}
editor.getViewer().repaint();
}
private class Listener implements MouseListener, MouseMotionListener {
@Override
public void mouseClicked(MouseEvent e) {
if (highlightShape != null && e.getButton() == MouseEvent.BUTTON1) {
processClick(highlightShape);
}
}
@Override
public void mouseMoved(MouseEvent e) {
Point p = fixEventPoint(e.getPoint());
GMLCoordinates c = editor.getViewer().getCoordinatesAtPoint(p.x, p.y);
highlight(editor.getMap().findShapeUnder(c.getX(), c.getY()));
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
private Point fixEventPoint(Point p) {
Insets insets = editor.getViewer().getInsets();
return new Point(p.x - insets.left, p.y - insets.top);
}
}
}
\ No newline at end of file
package gis2.scenario;
/**
* Interface for a scenario editing tool.
*/
public interface Tool {
/**
* Get the name of this tool.
*
* @return The name of the tool.
*/
String getName();
/**
* Activate this tool.
*/
void activate();
/**
* Deactivate this tool.
*/
void deactivate();
}
\ No newline at end of file
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";
}
}
}
package human;
import static rescuecore2.misc.Handy.objectsToIDs;
import rescuecore2.worldmodel.EntityID;
import rescuecore2.worldmodel.ChangeSet;
import rescuecore2.messages.Command;
import rescuecore2.log.Logger;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardEntityURN;
import rescuecore2.standard.entities.Refuge;
import rescuecore2.standard.entities.Human;
import rescuecore2.standard.entities.AmbulanceTeam;
import rescuecore2.standard.components.StandardAgent;
import sample.SampleSearch;
import java.util.Collection;
import java.util.List;
import java.util.EnumSet;
/**
A basic ambulance team agent that will try to rescue a given target. Once the target is unburied this agent will attempt to load it and transport it to a refuge. If there is no target then this agent does nothing.
*/
public class ControlledAmbulanceTeam extends StandardAgent<AmbulanceTeam> {
private SampleSearch search;
private Human target;
/**
Set the target of this ambulance team.
@param target The new target.
*/
public void setTarget(Human target) {
this.target = target;
}
@Override
protected void think(int time, ChangeSet changed, Collection<Command> heard) {
if (target == null) {
Logger.info("Nothing to do.");
return;
}
else {
// Is the target on board?
if (target.getPosition().equals(getID())) {
// Yes
// Are we at a refuge?
if (location() instanceof Refuge) {
sendUnload(time);
return;
}
else {
List<EntityID> path = search.breadthFirstSearch(me().getPosition(), objectsToIDs(model.getEntitiesOfType(StandardEntityURN.REFUGE)));
if (path != null) {
sendMove(time, path);
return;
}
else {
Logger.info("Couldn't plan a path to refuge.");
return;
}
}
}
else {
if (target.getPosition().equals(me().getPosition())) {
// We're at the same location
if (target.getBuriedness() != 0) {
sendRescue(time, target.getID());
return;
}
else {
// Unburied: try to load
sendLoad(time, target.getID());
return;
}
}
else {
// Plan a path
List<EntityID> path = search.breadthFirstSearch(me().getPosition(), target.getID());
if (path != null) {
sendMove(time, path);
return;
}
else {
Logger.info("Couldn't plan a path to target.");
}
}
}
}
}
@Override
protected EnumSet<StandardEntityURN> getRequestedEntityURNsEnum() {
return EnumSet.of(StandardEntityURN.AMBULANCE_TEAM);
}
/**
Get the location of the entity controlled by this agent.
@return The location of the entity controlled by this agent.
*/
protected StandardEntity location() {
AmbulanceTeam me = me();
return me.getPosition(model);
}
@Override
protected void postConnect() {
super.postConnect();
search = new SampleSearch(model);
}
@Override
public String toString() {
if (me() == null) {
return "Human controlled ambulance team";
}
StringBuilder result = new StringBuilder();
result.append("Human controlled ambulance team ");
result.append(getID());
result.append(" ");
if (target == null) {
result.append("(no target)");
}
else {
result.append("target: human ");
result.append(target.getID());
if (target.getPosition().equals(getID())) {
result.append(" (loaded)");
}
}
return result.toString();
}
}
package human;
import static rescuecore2.misc.Handy.objectsToIDs;
import rescuecore2.worldmodel.EntityID;
import rescuecore2.worldmodel.ChangeSet;
import rescuecore2.messages.Command;
import rescuecore2.log.Logger;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardEntityURN;
import rescuecore2.standard.entities.Building;
import rescuecore2.standard.entities.Refuge;
import rescuecore2.standard.entities.FireBrigade;
import rescuecore2.standard.components.StandardAgent;
import sample.SampleSearch;
import java.util.List;
import java.util.Collection;
import java.util.EnumSet;
/**
A basic fire brigade agent that will try to extinguish a given target. If the target is a refuge then the fire brigade will attempt to enter the building to replenish water. If there is no target then this agent does nothing.
*/
public class ControlledFireBrigade extends StandardAgent<FireBrigade> {
private static final int MAX_WATER = 15000;
private static final int EXTINGUISH_DISTANCE = 30000;
private static final int EXTINGUISH_POWER = 1000;
private SampleSearch search;
private Building target;
/**
Set the target of this fire brigade.
@param target The new target.
*/
public void setTarget(Building target) {
this.target = target;
}
@Override
protected void think(int time, ChangeSet changed, Collection<Command> heard) {
if (target == null) {
Logger.info("Nothing to do");
return;
}
if (target instanceof Refuge) {
// Just go there
List<EntityID> path = search.breadthFirstSearch(me().getPosition(), target.getID());
if (path != null) {
sendMove(time, path);
return;
}
else {
Logger.info("Couldn't plan a path to refuge.");
}
}
// Are we close enough to extinguish?
int distance = model.getDistance(me(), target);
if (distance < EXTINGUISH_DISTANCE) {
sendExtinguish(time, target.getID(), EXTINGUISH_POWER);
return;
}
// Otherwise plan a path
if (!target.equals(location())) {
List<EntityID> path = planPathToFire();
if (path != null) {
sendMove(time, path);
return;
}
else {
Logger.info("Couldn't plan a path to target.");
}
}
}
private List<EntityID> planPathToFire() {
// Try to get to anything within EXTINGUISH_DISTANCE of the target
Collection<StandardEntity> targets = model.getObjectsInRange(target, EXTINGUISH_DISTANCE);
if (targets.isEmpty()) {
return null;
}
return search.breadthFirstSearch(me().getPosition(), objectsToIDs(targets));
}
@Override
protected EnumSet<StandardEntityURN> getRequestedEntityURNsEnum() {
return EnumSet.of(StandardEntityURN.FIRE_BRIGADE);
}
/**
Get the location of the entity controlled by this agent.
@return The location of the entity controlled by this agent.
*/
protected StandardEntity location() {
FireBrigade me = me();
return me.getPosition(model);
}
@Override
protected void postConnect() {
super.postConnect();
search = new SampleSearch(model);
}
@Override
public String toString() {
if (me() == null) {
return "Human controlled fire brigade";
}
return "Human controlled fire brigade " + me().getID() + " (" + me().getWater() + " water)" + (target == null ? " (no target)" : " target: building " + target.getID());
}
}
\ No newline at end of file
package human;
import rescuecore2.worldmodel.EntityID;
import rescuecore2.worldmodel.ChangeSet;
import rescuecore2.messages.Command;
import rescuecore2.misc.Pair;
import rescuecore2.log.Logger;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardEntityURN;
import rescuecore2.standard.entities.Area;
import rescuecore2.standard.entities.Road;
import rescuecore2.standard.entities.PoliceForce;
import rescuecore2.standard.components.StandardAgent;
import sample.SampleSearch;
import java.util.Collection;
import java.util.List;
import java.util.EnumSet;
/**
A basic police force agent that will try to clear a given target. Fully-blocked roads encountered along the way are also cleared. If there is no target then this agent does nothing.
*/
public class ControlledPoliceForce extends StandardAgent<PoliceForce> {
private SampleSearch search;
private Road target;
/**
Set the target for this police force.
@param target The new target.
*/
public void setTarget(Road target) {
this.target = target;
}
@Override
protected void think(int time, ChangeSet changed, Collection<Command> heard) {
if (location() instanceof Road) {
Road r = (Road)location();
EntityID nearest = getNearestBlockade();
if (nearest != null) {
sendClear(time, nearest);
return;
}
}
if (target == null) {
Logger.info("Nothing to do.");
return;
}
List<EntityID> path = search.breadthFirstSearch(me().getPosition(), target.getID());
if (path != null) {
sendMove(time, path);
return;
}
else {
Logger.info("Couldn't plan a path to target.");
}
}
@Override
protected EnumSet<StandardEntityURN> getRequestedEntityURNsEnum() {
return EnumSet.of(StandardEntityURN.POLICE_FORCE);
}
/**
Get the location of the entity controlled by this agent.
@return The location of the entity controlled by this agent.
*/
protected StandardEntity location() {
PoliceForce me = me();
return me.getPosition(model);
}
@Override
protected void postConnect() {
super.postConnect();
search = new SampleSearch(model);
}
@Override
public String toString() {
if (me() == null) {
return "Human controlled police force";
}
return "Human controlled police force " + getID() + (target == null ? " (no target)" : " target: road " + target.getID() + " with " + (target.isBlockadesDefined() ? " unknown" : String.valueOf(target.getBlockades().size())) + " blockades");
}
/**
Get the blockade that is nearest this agent.
@return The EntityID of the nearest blockade, or null if there are no blockades in the agents current location.
*/
public EntityID getNearestBlockade() {
return getNearestBlockade((Area)location(), me().getX(), me().getY());
}
/**
Get the blockade that is nearest a point.
@param area The area to check.
@param x The X coordinate to look up.
@param y The X coordinate to look up.
@return The EntityID of the nearest blockade, or null if there are no blockades in this area.
*/
public EntityID getNearestBlockade(Area area, int x, int y) {
double bestDistance = 0;
EntityID best = null;
if (area.isBlockadesDefined()) {
for (EntityID blockadeID : area.getBlockades()) {
StandardEntity entity = model.getEntity(blockadeID);
Pair<Integer, Integer> location = entity.getLocation(model);
if (location == null) {
continue;
}
double dx = location.first() - x;
double dy = location.second() - y;
double distance = Math.hypot(dx, dy);
if (best == null || distance < bestDistance) {
bestDistance = distance;
best = entity.getID();
}
}
}
return best;
}
}
package ignition;
import rescuecore2.standard.entities.StandardWorldModel;
import rescuecore2.standard.entities.Building;
import java.util.Set;
/**
A model for determining which buildings ignite at any timestep.
*/
public interface IgnitionModel {
/**
Find out which buildings have ignited.
@param world The world model.
@param time The current time.
@return A list of newly ignited buildings.
*/
Set<Building> findIgnitionPoints(StandardWorldModel world, int time);
}
package ignition;
import rescuecore2.worldmodel.ChangeSet;
import rescuecore2.messages.control.KSCommands;
import rescuecore2.log.Logger;
import rescuecore2.standard.components.StandardSimulator;
import rescuecore2.standard.entities.Building;
import rescuecore2.standard.entities.GasStation;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardEntityURN;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
A simulator that determines when new building fires begin.
*/
public class IgnitionSimulator extends StandardSimulator {
private IgnitionModel ignitionModel;
private int GAS_STATION_EXPLOSION_RANG;
private List<GasStation> notIgnaitedGasStations;
@Override
protected void postConnect() {
super.postConnect();
ignitionModel = new RandomIgnitionModel(model, config);
GAS_STATION_EXPLOSION_RANG=config.getIntValue("ignition.gas_station.explosion.range");
notIgnaitedGasStations=new ArrayList<GasStation>();
for (StandardEntity entity : model.getEntitiesOfType(StandardEntityURN.GAS_STATION)) {
notIgnaitedGasStations.add((GasStation) entity);
}
}
@Override
protected void processCommands(KSCommands c, ChangeSet changes) {
long start = System.currentTimeMillis();
int time = c.getTime();
Logger.info("Timestep " + time);
explosionGasStations(changes);
Logger.info("Ignating after shock ");
// Find out which buildings have ignited.
Set<Building> buildings = ignitionModel.findIgnitionPoints(model, c.getTime());
for (Building next : buildings) {
Logger.info("Igniting " + next);
next.setIgnition(true);
changes.addChange(next, next.getIgnitionProperty());
}
long end = System.currentTimeMillis();
Logger.info("Timestep " + time + " took " + (end - start) + " ms");
}
private void explosionGasStations(ChangeSet changes) {
Logger.info("explosion Gas Stations ");
for (Iterator<GasStation> iterator= notIgnaitedGasStations.iterator(); iterator.hasNext();) {
GasStation gasStation = iterator.next();
if(gasStation.isFierynessDefined()&&gasStation.getFieryness()==1){
explode(gasStation,changes);
iterator.remove();
}
}
}
private void explode(GasStation gasStation, ChangeSet changes) {
Logger.info(gasStation+" Ignited ==> explosion" );
for (StandardEntity rangeEntity : model.getObjectsInRange(gasStation, GAS_STATION_EXPLOSION_RANG)) {
if(rangeEntity instanceof Building){
Building rangeBuilding = (Building)rangeEntity;
Logger.info("Igniting " + rangeBuilding);
rangeBuilding.setIgnition(true);
changes.addChange(rangeBuilding, rangeBuilding.getIgnitionProperty());
}
}
}
@Override
public String getName() {
return "Ignition simulator";
}
}
\ No newline at end of file
package ignition;
import rescuecore2.config.Config;
import rescuecore2.log.Logger;
import rescuecore2.standard.entities.StandardWorldModel;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.Building;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Collections;
import org.uncommons.maths.random.PoissonGenerator;
/**
An IgnitionModel that ignites unburnt buildings in a random order. The number of ignitions per timestep is drawn from a Poisson distribution.
*/
public class RandomIgnitionModel implements IgnitionModel {
private static final String MEAN_KEY = "ignition.random.lambda";
private PoissonGenerator generator;
private Iterator<Building> it;
/**
Construct a RandomIgnitionModel.
@param world The world model.
@param config The system configuration.
*/
public RandomIgnitionModel(StandardWorldModel world, Config config) {
List<Building> unburnt = new ArrayList<Building>();
for (StandardEntity next : world) {
if (next instanceof Building) {
unburnt.add((Building)next);
}
}
Collections.shuffle(unburnt, config.getRandom());
double mean = config.getFloatValue(MEAN_KEY);
generator = new PoissonGenerator(mean, config.getRandom());
it = unburnt.iterator();
}
@Override
public Set<Building> findIgnitionPoints(StandardWorldModel world, int time) {
Set<Building> result = new HashSet<Building>();
if (it.hasNext()) {
int number = generator.nextValue();
Logger.debug("Igniting " + number + " buildings");
for (int i = 0; i < number && it.hasNext(); ++i) {
result.add(it.next());
}
}
return result;
}
}
package kernel;
import java.util.Collection;
import java.util.Iterator;
import rescuecore2.config.Config;
import rescuecore2.messages.Command;
/**
An abstract base class for command filters.
*/
public abstract class AbstractCommandFilter implements CommandFilter {
@Override
public void initialise(Config config) {
}
@Override
public void filter(Collection<Command> commands, KernelState state) {
for (Iterator<Command> it = commands.iterator(); it.hasNext();) {
if (!allowed(it.next(), state)) {
it.remove();
}
}
}
/**
Find out if a particular command is allowed.
@param command The command.
@param state The kernel state.
@return True iff the command is allowed.
*/
protected abstract boolean allowed(Command command, KernelState state);
}
package kernel;
import java.util.Collection;
import java.util.List;
import java.util.LinkedList;
import java.util.Map;
import java.util.Arrays;
import rescuecore2.messages.Command;
import rescuecore2.config.Config;
import rescuecore2.worldmodel.Entity;
import rescuecore2.worldmodel.WorldModel;
import rescuecore2.misc.collections.LazyMap;
/**
Abstract base class for communication models.
*/
public abstract class AbstractCommunicationModel implements CommunicationModel {
private Map<Entity, List<Command>> hearing;
/**
Construct an AbstractCommunicationModel.
*/
public AbstractCommunicationModel() {
hearing = new LazyMap<Entity, List<Command>>() {
@Override
public List<Command> createValue() {
return new LinkedList<Command>();
}
};
}
@Override
public void initialise(Config config, WorldModel<? extends Entity> model) {
hearing.clear();
}
@Override
public void process(int time, Collection<? extends Command> agentCommands) {
hearing.clear();
}
@Override
public Collection<Command> getHearing(Entity agent) {
return hearing.get(agent);
}
/**
Register a set of heard messages for an agent.
@param agent The agent.
@param c The messages heard.
*/
protected void addHearing(Entity agent, Command... c) {
addHearing(agent, Arrays.asList(c));
}
/**
Register a set of heard messages for an agent.
@param agent The agent.
@param c The messages heard.
*/
protected void addHearing(Entity agent, Collection<? extends Command> c) {
hearing.get(agent).addAll(c);
}
}
package kernel;
import rescuecore2.messages.Message;
import rescuecore2.messages.control.Shutdown;
import rescuecore2.connection.Connection;
import rescuecore2.connection.ConnectionException;
import rescuecore2.log.Logger;
import java.util.Collection;
import java.util.Collections;
/**
Abstract base class for KernelComponent implementations.
*/
public abstract class AbstractKernelComponent implements KernelComponent {
private Connection connection;
private String name;
/**
Construct a new abstract component.
@param name The name of this component.
@param c The connection this component is using.
*/
protected AbstractKernelComponent(String name, Connection c) {
this.name = name;
this.connection = c;
}
@Override
public void send(Collection<? extends Message> messages) {
if (!connection.isAlive()) {
return;
}
try {
connection.sendMessages(messages);
}
catch (ConnectionException e) {
Logger.error("Error sending message", e);
}
}
@Override
public Connection getConnection() {
return connection;
}
@Override
public void shutdown() {
send(new Shutdown());
connection.shutdown();
}
@Override
public String getName() {
return name;
}
/**
Send a single message.
@param message The message to send.
*/
protected void send(Message message) {
send(Collections.singleton(message));
}
}
package kernel;
import java.util.Collection;
import java.util.Map;
import java.util.ArrayList;
import rescuecore2.connection.Connection;
import rescuecore2.connection.ConnectionListener;
import rescuecore2.messages.Message;
import rescuecore2.messages.Command;
import rescuecore2.messages.control.KASense;
import rescuecore2.worldmodel.Entity;
import rescuecore2.worldmodel.EntityID;
import rescuecore2.worldmodel.ChangeSet;
import rescuecore2.log.Logger;
import rescuecore2.misc.collections.LazyMap;
import rescuecore2.registry.Registry;
/**
This class is the kernel interface to an agent.
*/
public class AgentProxy extends AbstractKernelComponent {
private Entity entity;
private Map<Integer, Collection<Command>> commands;
/**
Construct an agent.
@param name The name of the controlling agent.
@param e The entity controlled by the agent.
@param c The connection to the agent.
*/
public AgentProxy(String name, Entity e, Connection c) {
super(name, c);
this.entity = e;
commands = new LazyMap<Integer, Collection<Command>>() {
@Override
public Collection<Command> createValue() {
return new ArrayList<Command>();
}
};
c.addConnectionListener(new AgentConnectionListener());
}
@Override
public String toString() {
return getName() + ": " + Registry.getCurrentRegistry().toPrettyName(entity.getURN()) + " " + entity.getID();
}
/**
Get the entity controlled by this agent.
@return The entity controlled by this agent.
*/
public Entity getControlledEntity() {
return entity;
}
/**
Get all agent commands at a particular time.
@param timestep The current timestep.
@return A collection of messages representing the commands
*/
public Collection<Command> getAgentCommands(int timestep) {
Collection<Command> result;
synchronized (commands) {
result = new ArrayList<>(commands.get(timestep));
}
Logger.trace(entity.toString() + " getAgentCommands(" + timestep + ") returning " + result);
return result;
}
/**
Notify the of a perception update.
@param time The current timestep.
@param visible The set of visible changes.
@param heard The set of communication messages that the agent heard.
*/
public void sendPerceptionUpdate(int time, ChangeSet visible, Collection<? extends Command> heard) {
KASense sense = new KASense(getControlledEntity().getID(), time, visible, heard);
send(sense);
}
/**
Register an agent command received.
@param c The command that was received.
*/
protected void commandReceived(Command c) {
// Check that the command is for the right agent
if (!c.getAgentID().equals(entity.getID())) {
Logger.warn("Ignoring bogus command: Agent " + entity.getID() + " tried to send a command for agent " + c.getAgentID());
return;
}
int time = c.getTime();
Logger.trace("AgentProxy " + entity + " received " + c);
synchronized (commands) {
Collection<Command> result = commands.get(time);
result.add(c);
commands.notifyAll();
}
}
private class AgentConnectionListener implements ConnectionListener {
@Override
public void messageReceived(Connection c, Message msg) {
if (msg instanceof Command) {
EntityID id = ((Command)msg).getAgentID();
if (id.equals(getControlledEntity().getID())) {
commandReceived((Command)msg);
}
}
}
}
@Override
public int hashCode() {
return entity.getID().hashCode();
}
}
package kernel;
import rescuecore2.worldmodel.WorldModel;
import rescuecore2.worldmodel.Entity;
import rescuecore2.config.Config;
/**
Implementations of this decide which entities are controlled by agents and what each agent can see on startup.
*/
public interface AgentRegistrar {
/**
Process a WorldModel and Config and tell the ComponentManager which entities are agent-controlled and what they can see on connection.
@param world The WorldModel.
@param config The Config.
@param manager The ComponentManager.
@throws KernelException If there is a problem registering agents.
*/
void registerAgents(WorldModel<? extends Entity> world, Config config, ComponentManager manager) throws KernelException;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment