24.09., 9:00 - 11:00: Due to updates GitLab will be unavailable for some minutes between 09:00 and 11:00.

Commit 2ae965fc authored by Benedikt Zoennchen's avatar Benedikt Zoennchen

issue #141.

parent 7c6c18ea
Pipeline #70354 passed with stages
in 64 minutes and 8 seconds
......@@ -121,6 +121,7 @@ ProjectView.mntmReapplyMigration.text=Remigrate project and open...
ProjectView.chooseMigrationBaseDialog.text=Choose the version of this project
ProjectView.chooseMigrationBaseDialog.title=Migration
ProjectView.chooseMigrationBaseDialog.defaultOption=automatic
ProjectView.chooseFile=Chose file
SaveBeforeClosing.text=Do you want to save the current project before closing?
SaveBeforeClosing.unsavedChanges.text=Unsaved changes:
......@@ -274,6 +275,8 @@ ProjectView.btnShowDensity.tooltip=Show Density
ProjectView.btnSettings.tooltip=Settings
ProjectView.btnOk=OK
ProjectView.btnCancel=Cancel
ProjectView.btnExpertCSV=Export as csv
ProjectView.label.simResults=Simulation Results
TopographyCreator.btnMinimizeTopography.tooltip=Select Viewport area
TopographyCreator.btnMaximizeTopography.tooltip=Maximize Viewport area
......
......@@ -120,6 +120,9 @@ ProjectView.mntmReapplyMigration.text=Projekt remigrieren und \u00F6ffnen...
ProjectView.chooseMigrationBaseDialog.text=W\u00c4hlen Sie die Version dieses Projekts
ProjectView.chooseMigrationBaseDialog.title=Migration
ProjectView.chooseMigrationBaseDialog.defaultOption=Automatisch
ProjectView.chooseFile=Datei ausw\u00E4hlen
ProjectView.btnExpertCSV=Als CSV exportieren
ProjectView.label.simResults=Simulationsergebniss
SaveBeforeClosing.text=Aktuelles Projekt vor dem Beenden speichern?
SaveBeforeClosing.unsavedChanges.text=Ungespeicherte \u00c4nderungen:
......
......@@ -2,6 +2,7 @@ package org.vadere.gui.projectview.view;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.projectview.model.ProjectViewModel;
import org.vadere.simulator.projects.ProjectFinishedListener;
import org.vadere.simulator.projects.SimulationResult;
......@@ -40,11 +41,14 @@ public class ProjectRunResultDialog implements ProjectFinishedListener {
public void postProjectRun(VadereProject project) {
LinkedList<SimulationResult> simulationResultList = project.getSimulationResults();
StringBuilder sb = new StringBuilder();
for (SimulationResult res : simulationResultList) {
sb.append(res.getScenarioName()).append(":\n")
.append(" Runtime: ").append(res.getRunTimeAsString()).append("\n")
.append(" Overlaps: ").append(res.getTotalOverlaps()).append("\n")
.append(" State: ").append(res.getState()).append("\n\n");
String[] headers = res.getHeaders();
String[] values = res.getAsTableRow();
for(int i = 0; i < headers.length; i++) {
sb.append(" " + headers[i] + ": ").append(values[i]).append("\n");
}
}
......@@ -61,11 +65,6 @@ public class ProjectRunResultDialog implements ProjectFinishedListener {
}
class ResultDialog extends JDialog {
private final String[] columnNames = {"Scenario_Name",
"Runtime",
"Overlaps",
"MaxOverlap",
"State"};
Button btnOk, btnCsv;
private JTable table;
JPanel main;
......@@ -80,15 +79,15 @@ public class ProjectRunResultDialog implements ProjectFinishedListener {
main = new JPanel();
main.setLayout(new BoxLayout(main, BoxLayout.PAGE_AXIS));
table = new JTable(getData(data), columnNames);
table = new JTable(getData(data), data.getFirst().getHeaders());
table.setFillsViewportHeight(true);
table.doLayout();
scrollPane = new JScrollPane(table);
main.add(scrollPane);
btnOk = new Button("Close");
btnOk = new Button(Messages.getString("SettingsDialog.btnClose.text"));
btnOk.addActionListener(this::btnOKListener);
btnCsv = new Button("Export csv");
btnCsv = new Button(Messages.getString("ProjectView.btnExpertCSV"));
btnPane = new JPanel();
btnCsv.addActionListener(this::btnCsvListener);
btnPane.setLayout(new BoxLayout(btnPane, BoxLayout.LINE_AXIS));
......@@ -102,7 +101,7 @@ public class ProjectRunResultDialog implements ProjectFinishedListener {
c.add(main, BorderLayout.CENTER);
c.add(btnPane, BorderLayout.PAGE_END);
setTitle("Simulation Result");
setTitle(Messages.getString("ProjectView.label.simResults"));
setSize(600, 200);
}
......@@ -124,11 +123,11 @@ public class ProjectRunResultDialog implements ProjectFinishedListener {
private void btnCsvListener(ActionEvent actionEvent) {
StringBuilder sj = new StringBuilder();
SimulationResult.addCsvHeader(sj, ';');
data.forEach(i -> i.addCsvRow(sj, ';'));
SimulationResult.addCsvHeader(data.getFirst(), sj, ';');
data.forEach(simulationResult -> simulationResult.addCsvRow(sj, ';'));
FileDialog fd = new FileDialog(this, "Bitte eine Datei waehlen!", FileDialog.SAVE);
FileDialog fd = new FileDialog(this, Messages.getString("ProjectView.chooseFile"), FileDialog.SAVE);
fd.setVisible(true);
Path p = (Paths.get(fd.getDirectory()).resolve(fd.getFile()));
......
......@@ -9,6 +9,7 @@ import org.vadere.state.scenario.ScenarioElement;
import org.vadere.util.geometry.shapes.VShape;
import java.awt.*;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
......@@ -16,6 +17,7 @@ public class AgentRender implements Renderer {
private static Logger logger = LogManager.getLogger(AgentRender.class);
private static final Integer COLOR_NUM = 9;
private Random random;
private final SimulationModel model;
private final Color defaultColor;
......@@ -26,6 +28,7 @@ public class AgentRender implements Renderer {
this.defaultColor = model.config.getPedestrianDefaultColor();
this.colorMap = new ConcurrentHashMap<>();
this.colorMap.put(-1, defaultColor);
this.random = new Random();
}
@Override
......@@ -57,13 +60,14 @@ public class AgentRender implements Renderer {
}
private Color getHSBColor(int groupId) {
float hue = ((float) (groupId) / COLOR_NUM);
// float hue = ((float) (groupId) / COLOR_NUM);
float hue = random.nextFloat();
// System.out.printf("groupId: %d | hue: %f%n",groupId, hue);
return new Color(Color.HSBtoRGB(hue, 1f, 0.75f));
}
public Color getGroupColor(Pedestrian ped) {
if (ped.getGroupIds().isEmpty()) {
if (ped.getGroupIds().isEmpty() || (!ped.getGroupSizes().isEmpty() && ped.getGroupSizes().getFirst() <= 1)) {
return defaultColor;
}
......@@ -77,7 +81,7 @@ public class AgentRender implements Renderer {
}
public VShape getShape(Pedestrian ped) {
if (ped.getGroupIds().isEmpty()) {
if (ped.getGroupIds().isEmpty() || (!ped.getGroupSizes().isEmpty() && ped.getGroupSizes().getFirst() <= 1)) {
return ped.getShape();
} else if (ped.getGroupIds().getFirst() == 1) {
return ped.getShape();
......
......@@ -51,6 +51,7 @@ public class TopographyController extends OfflineTopographyController {
*/
realPed.setTargets(new LinkedList<>(initialValues.getTargets()));
realPed.setGroupIds(new LinkedList<>(initialValues.getGroupIds()));
realPed.setGroupSizes(new LinkedList<>(initialValues.getGroupSizes()));
realPed.setChild(initialValues.isChild());
realPed.setLikelyInjured(initialValues.isLikelyInjured());
......
......@@ -34,7 +34,7 @@ public class CentroidGroupFactory extends GroupFactory {
}
currentGroup.addMember(ped);
ped.addGroupId(currentGroup.getID());
ped.addGroupId(currentGroup.getID(), currentGroup.getSize());
groupCollection.registerMember(ped, currentGroup);
if (currentGroup.getOpenPersons() == 0) {
newGroups.pollFirst(); // remove full group from list.
......
package org.vadere.simulator.projects;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.Map;
import java.util.TreeMap;
public class SimulationResult {
private static Logger log = LogManager.getLogger(SimulationResult.class);
// tree map such that keys are sorted.
private TreeMap<String, Object> data;
private String scenarioName;
private Duration runTime;
......@@ -17,42 +27,25 @@ public class SimulationResult {
public SimulationResult(String scenarioName) {
this.scenarioName = scenarioName;
this.data = new TreeMap<>();
}
public void addData(@NotNull final String header, @NotNull final Object value) {
assert !data.containsKey(header);
if(data.containsKey(header)) {
log.warn("duplicated headers ("+ header +") in simulation results");
}
data.put(header, value);
}
public void startTime(){
startTime = Instant.now();
}
public void stopTime(){
runTime = Duration.between(startTime, Instant.now());
}
public String getScenarioName() {
return scenarioName;
}
public void setScenarioName(String scenarioName) {
this.scenarioName = scenarioName;
}
public Duration getRunTime() {
return runTime;
}
public String getRunTimeAsString(){
return runTime.toString();
}
public int getTotalOverlaps() {
return totalOverlaps;
}
public void setTotalOverlaps(int totalOverlaps) {
this.totalOverlaps = totalOverlaps;
}
public String getState() {
return state;
}
......@@ -61,21 +54,18 @@ public class SimulationResult {
this.state = state;
}
public double getMaxOverlap() {
return maxOverlap;
}
public void setMaxOverlap(double maxOverlap) {
this.maxOverlap = maxOverlap;
}
public String[] getAsTableRow(){
String[] ret = new String[5];
String[] ret = new String[3 + data.size()];
ret[0] = scenarioName;
ret[1] = runTime.toString();
ret[2] = Integer.toString(totalOverlaps);
ret[3] = String.format("%.5f", maxOverlap);
ret[4] = state;
int i = 2;
for(Map.Entry<String, Object> entry : data.entrySet()) {
ret[i] = entry.getValue().toString();
i++;
}
ret[i] = state;
return ret;
}
......@@ -85,22 +75,69 @@ public class SimulationResult {
sj.append("\n");
}
public static void addCsvHeader(StringBuilder sj, char dl){
public String[] getHeaders(){
String[] ret = new String[3 + data.size()];
ret[0] = "Scenario_Name";
ret[1] = "Runtime";
int i = 2;
for(Map.Entry<String, Object> entry : data.entrySet()) {
ret[i] = entry.getKey();
i++;
}
ret[i] = "State";
return ret;
}
public static void addCsvHeader(SimulationResult simulationResult, StringBuilder sj, char dl){
sj.append("Scenario_Name").append(dl);
sj.append("Runtime").append(dl);
sj.append("NumberOverlaps").append(dl);
sj.append("MaxOverlap").append(dl);
for(Map.Entry<String, Object> entry : simulationResult.data.entrySet()) {
sj.append(entry.getKey());
}
sj.append("State\n");
}
public String toJson() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("SimulationResult{");
stringBuilder.append("scenarioName='");
stringBuilder.append("\"");
stringBuilder.append(scenarioName);
stringBuilder.append("\"");
stringBuilder.append(", ");
for(Map.Entry<String, Object> entry : data.entrySet()) {
stringBuilder.append(entry.getKey());
if(entry.getValue().getClass() == String.class) {
stringBuilder.append("\"");
}
stringBuilder.append("=");
stringBuilder.append(entry.getValue().toString());
if(entry.getValue().getClass() == String.class) {
stringBuilder.append("\"");
}
stringBuilder.append(", ");
}
stringBuilder.append("state='");
stringBuilder.append("\"");
stringBuilder.append(state);
stringBuilder.append("\"");
stringBuilder.append("}");
return stringBuilder.toString();
}
@Override
public String toString() {
return "SimulationResult{" +
"scenarioName='" + scenarioName + '\'' +
", runTime=" + runTime +
", totalOverlaps=" + totalOverlaps +
", state='" + state + '\'' +
'}';
return toJson();
}
}
......@@ -14,7 +14,7 @@ import java.util.Collections;
*
*/
@DataProcessorClass()
public class EvacuationTimeProcessor extends DataProcessor<NoDataKey, Double> {
public class EvacuationTimeProcessor extends NoDataKeyProcessor<Double> {
private PedestrianEvacuationTimeProcessor pedEvacTimeProc;
public EvacuationTimeProcessor() {
......
......@@ -22,7 +22,7 @@ import java.util.OptionalDouble;
@DataProcessorClass()
public class MaxOverlapProcessor extends DataProcessor<NoDataKey, Double> {
public class MaxOverlapProcessor extends NoDataKeyProcessor<Double> {
private PedestrianOverlapProcessor pedOverlapProc;
......@@ -46,12 +46,6 @@ public class MaxOverlapProcessor extends DataProcessor<NoDataKey, Double> {
this.putValue(NoDataKey.key(),maximumOverlap.getOverlap());
}
public void postLoopAddResultInfo(final SimulationState state, SimulationResult result){
result.setMaxOverlap(this.getValue(NoDataKey.key()));
}
@Override
public void init(final ProcessorManager manager) {
super.init(manager);
......
......@@ -15,7 +15,7 @@ import java.util.stream.Collectors;
* @author Mario Teixeira Parente
*/
@DataProcessorClass()
public class MeanPedestrianEvacuationTimeProcessor extends DataProcessor<NoDataKey, Double> {
public class MeanPedestrianEvacuationTimeProcessor extends NoDataKeyProcessor<Double> {
private PedestrianEvacuationTimeProcessor pedEvacTimeProc;
public MeanPedestrianEvacuationTimeProcessor() {
......
package org.vadere.simulator.projects.dataprocessing.processor;
import org.jetbrains.annotations.NotNull;
import org.vadere.simulator.control.SimulationState;
import org.vadere.simulator.projects.SimulationResult;
import org.vadere.simulator.projects.dataprocessing.datakey.NoDataKey;
/**
* @author Benedikt Zoennchen
* @param <V>
*/
public abstract class NoDataKeyProcessor<V> extends DataProcessor<NoDataKey, V> {
private String header;
protected NoDataKeyProcessor() {
super();
}
protected NoDataKeyProcessor(final String header) {
super(new String[]{header});
this.header = header;
}
public String getSimulationResultHeader() {
return header;
}
@Override
public void postLoopAddResultInfo(@NotNull final SimulationState state, @NotNull final SimulationResult result){
result.addData(getSimulationResultHeader(), getValue(NoDataKey.key()));
}
}
......@@ -20,7 +20,7 @@ import java.util.Optional;
@DataProcessorClass()
public class NumberOverlapsProcessor extends DataProcessor<NoDataKey, Long> {
public class NumberOverlapsProcessor extends NoDataKeyProcessor<Long> {
private PedestrianOverlapProcessor pedOverlapProc;
......@@ -43,17 +43,11 @@ public class NumberOverlapsProcessor extends DataProcessor<NoDataKey, Long> {
this.putValue(NoDataKey.key(), numberOverlaps);
}
@Override
public void postLoopAddResultInfo(final SimulationState state, SimulationResult result){
result.setTotalOverlaps(this.getValue(NoDataKey.key()).intValue());
}
@Override
public void init(final ProcessorManager manager) {
super.init(manager);
AttributesNumberOverlapsProcessor att = (AttributesNumberOverlapsProcessor) this.getAttributes();
this.pedOverlapProc = (PedestrianOverlapProcessor) manager.getProcessor(att.getPedestrianOverlapProcessorId());
}
......
......@@ -45,7 +45,6 @@ public class PedestrianPositionProcessor extends DataProcessor<TimestepPedestria
public String[] toStrings(TimestepPedestrianIdKey key) {
VPoint p = this.getValue(key);
if(p == null) {
System.out.println("wtf?");
return new String[]{Double.toString(0), Double.toString(0)};
}
else {
......
......@@ -52,6 +52,7 @@ public class TrajectoryReader {
private Set<String> yKeys;
private Set<String> targetIdKeys;
private Set<String> groupIdKeys;
private Set<String> groupSizeKeys;
private int pedIdIndex;
......@@ -60,6 +61,7 @@ public class TrajectoryReader {
private int yIndex;
private int targetIdIndex;
private int groupIdIndex;
private int groupSizeIndex;
public TrajectoryReader(final Path trajectoryFilePath, final Scenario scenario) {
this(trajectoryFilePath, scenario.getAttributesPedestrian());
......@@ -78,6 +80,7 @@ public class TrajectoryReader {
yKeys = new HashSet<>();
targetIdKeys = new HashSet<>();
groupIdKeys = new HashSet<>();
groupSizeKeys = new HashSet<>();
//should be set via Processor.getHeader
pedestrianIdKeys.add("id");
......@@ -88,6 +91,7 @@ public class TrajectoryReader {
yKeys.add("y");
targetIdKeys.add("targetId");
groupIdKeys.add("groupId");
groupSizeKeys.add("groupSize");
pedIdIndex = -1;
stepIndex = -1;
......@@ -95,6 +99,7 @@ public class TrajectoryReader {
yIndex = -1;
targetIdIndex = -1;
groupIdIndex = -1;
groupSizeIndex = -1;
}
......@@ -121,6 +126,9 @@ public class TrajectoryReader {
} else if (groupIdKeys.contains(columns[index])){
groupIdIndex = index;
}
else if (groupSizeKeys.contains(columns[index])){
groupSizeIndex = index;
}
}
try {
if (pedIdIndex != -1 && xIndex != -1 && yIndex != -1 && stepIndex != -1) {
......@@ -204,8 +212,9 @@ public class TrajectoryReader {
ped.setTargets(targets);
if(groupIdIndex != -1) {
int groupId = targetIdIndex != -1 ? Integer.parseInt(rowTokens[groupIdIndex]) : -1;
ped.addGroupId(groupId);
int groupId = groupIdIndex != -1 ? Integer.parseInt(rowTokens[groupIdIndex]) : -1;
int groupSize = groupSizeIndex != -1 ? Integer.parseInt(rowTokens[groupSizeIndex]) : -1;
ped.addGroupId(groupId, groupSize);
}
return Pair.create(new Step(step), ped);
......
......@@ -26,6 +26,8 @@ public class Pedestrian extends Agent {
// TODO used at all? Car does NOT have this field. remove if unused!
private ScenarioElementType type = ScenarioElementType.PEDESTRIAN;
private LinkedList<Integer> groupSizes;
@SuppressWarnings("unused")
private Pedestrian() {
// TODO constructor may be required for Jackson?
......@@ -45,6 +47,7 @@ public class Pedestrian extends Agent {
isChild = false;
isLikelyInjured = false;
groupIds = new LinkedList<>();
groupSizes = new LinkedList<>();
}
/**
......@@ -60,13 +63,16 @@ public class Pedestrian extends Agent {
if (other.groupIds != null) {
groupIds = new LinkedList<>(other.groupIds);
groupSizes = new LinkedList<>(other.groupSizes);
} else {
groupIds = new LinkedList<>();
groupSizes = new LinkedList<>();
}
}
public void addGroupId(int groupId){
public void addGroupId(int groupId, int size){
groupIds.add(groupId);
groupSizes.add(size);
}
public <T extends ModelPedestrian> T getModelPedestrian(Class<? extends T> modelType) {
......@@ -81,6 +87,10 @@ public class Pedestrian extends Agent {
this.groupIds = groupIds;
}
public void setGroupSizes(LinkedList<Integer> groupSizes) {
this.groupSizes = groupSizes;
}
public VShape getInformationShape() {
return null;
}
......@@ -89,6 +99,10 @@ public class Pedestrian extends Agent {
return groupIds;
}
public LinkedList<Integer> getGroupSizes() {
return groupSizes;
}
public boolean isTarget() {
return this.idAsTarget != -1;
}
......
Markdown is supported
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