Commit 778ef1aa authored by Daniel Lehmberg's avatar Daniel Lehmberg
Browse files

clear split between header and indices + improves tests + resolve name conflicts in header

parent 2a34665d
......@@ -60,7 +60,8 @@
"pedestrianOverlapProcessorId" : 4
}
} ],
"isTimestamped" : true
"isTimestamped" : true,
"writeMetaData" : false
},
"scenario" : {
"mainModel" : "org.vadere.simulator.models.osm.OptimalStepsModel",
......
......@@ -60,7 +60,8 @@
"pedestrianOverlapProcessorId" : 4
}
} ],
"isTimestamped" : true
"isTimestamped" : true,
"writeMetaData" : false
},
"scenario" : {
"mainModel" : "org.vadere.simulator.models.osm.OptimalStepsModel",
......
......@@ -60,7 +60,8 @@
"pedestrianOverlapProcessorId" : 4
}
} ],
"isTimestamped" : true
"isTimestamped" : true,
"writeMetaData" : false
},
"scenario" : {
"mainModel" : "org.vadere.simulator.models.osm.OptimalStepsModel",
......
......@@ -4,7 +4,9 @@ import org.vadere.simulator.projects.dataprocessing.datakey.DataKey;
import org.vadere.simulator.projects.dataprocessing.processor.DataProcessor;
import org.vadere.simulator.projects.dataprocessing.writer.VadereWriter;
import org.vadere.simulator.projects.dataprocessing.writer.VadereWriterFactory;
import sun.awt.image.ImageWatched;
import javax.sound.midi.SysexMessage;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
......@@ -48,13 +50,15 @@ public abstract class OutputFile<K extends DataKey<K>> {
private List<Integer> processorIds;
private List<DataProcessor<K, ?>> dataProcessors;
private boolean isAddedProcessors;
private String separator;
private final String nameConflictAdd = "-Proc?"; // the # is replaced with the processor id
private VadereWriterFactory writerFactory;
private VadereWriter writer;
protected OutputFile(final String... dataIndices) {
this.dataIndices = dataIndices;
this.isAddedProcessors = false; // init method has to be called
this.dataProcessors = new ArrayList<>();
this.writerFactory = VadereWriterFactory.getFileWriterFactory();
}
......@@ -83,13 +87,15 @@ public abstract class OutputFile<K extends DataKey<K>> {
Optional.ofNullable(processorMap.get(pid))
.ifPresent(p -> dataProcessors.add((DataProcessor<K, ?>) p));
});
this.isAddedProcessors = true;
}
public void write() {
if (!isEmpty()) {
try (VadereWriter out = writerFactory.create(absoluteFileName)) {
writer = out;
printIndices(out);
printHeader(out);
this.dataProcessors.stream().flatMap(p -> p.getKeys().stream())
.distinct().sorted()
......@@ -106,30 +112,91 @@ public abstract class OutputFile<K extends DataKey<K>> {
return this.dataProcessors.isEmpty();
}
private List<String> getDataIndices() {
return composeLine(dataIndices, p -> Arrays.stream(p.getHeaders()));
private void printHeader(VadereWriter out) {
writeLine(out, this.getEntireHeader());
}
private List<String> getIndices(){
return new LinkedList<>(Arrays.asList(dataIndices));
}
public List<String> getEntireHeader() {
if(! isAddedProcessors){
throw new RuntimeException("Asking for headers, but processors were not " +
"initialized yet.");
}
//"getHeaders" is called in class DataProcessor.java, the
return composeHeaderLine();
}
public void printIndices(VadereWriter out) {
writeLine(out, getDataIndices());
public String getHeaderLine() {
return String.join(this.separator, this.getEntireHeader());
}
public String getIndices() {
return String.join(this.separator, getDataIndices());
public String getIndicesLine() {
return String.join(this.separator, this.getIndices());
}
private void printRow(final VadereWriter out, final K key) {
@SuppressWarnings("unchecked") final List<String> fields = composeLine(toStrings(key), p -> Arrays.stream(p.toStrings(key)));
// Info: 'key' are the indices values (such as timeStep=3), can be more than one
@SuppressWarnings("unchecked")
final List<String> fields = composeLine(toStrings(key), p -> Arrays.stream(p.toStrings(key)));
writeLine(out, fields);
}
private List<String> headersWithNameMangling(){
LinkedList<String> headers = new LinkedList<>();
boolean isNameMangle = false; // assume there is no nameing conflict
mainloop:
for (DataProcessor l: dataProcessors) {
List<String> list = Arrays.asList(l.getHeaders());
for(String el: list) {
if(headers.contains(el)){
isNameMangle = true; // conflict found: stop collecting headers
break mainloop;
}else{
headers.addLast(el);
}
}
}
if(isNameMangle){
headers.clear(); //start from new...
for (DataProcessor l: dataProcessors) {
List<String> list = Arrays.asList(l.getHeaders());
for (String h: list) {
// ... but now add the processor id
headers.addLast(h +
this.nameConflictAdd.replace('?', (char) (l.getId()+'0')));
}
}
}
return headers;
}
private List<String> composeHeaderLine(){
final List<String> allHeaders = new LinkedList<>(Arrays.asList(dataIndices));
List<String> procHeaders = this.headersWithNameMangling();
allHeaders.addAll(procHeaders);
return allHeaders;
}
private List<String> composeLine(String[] keyFieldArray, @SuppressWarnings("rawtypes") Function<DataProcessor, Stream<String>> valueFields) {
final List<String> fields = new LinkedList<>(Arrays.asList(keyFieldArray));
final List<String> processorFields = dataProcessors.stream()
.flatMap(valueFields)
.collect(Collectors.toList());
fields.addAll(processorFields);
return fields;
}
......@@ -165,9 +232,4 @@ public abstract class OutputFile<K extends DataKey<K>> {
public void setVadereWriterFactory(VadereWriterFactory writerFactory) {
this.writerFactory = writerFactory;
}
public void addDataProcessor(DataProcessor p) {
dataProcessors.add(p);
processorIds.add(p.getId());
}
}
......@@ -7,11 +7,14 @@
"files" : [ {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.TimestepPedestrianIdOutputFile",
"filename" : "out.txt",
"processors" : [ 1 ]
"processors" : [ 1, 2 ]
} ],
"processors" : [ {
"type" : "org.vadere.simulator.projects.dataprocessing.processor.PedestrianPositionProcessor",
"id" : 1
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.processor.PedestrianPositionProcessor",
"id" : 2
} ],
"isTimestamped" : true
},
......@@ -169,4 +172,4 @@
"attributesCar" : null
}
}
}
\ No newline at end of file
}
package org.vadere.simulator.dataprocessing;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.ArrayList;
......@@ -15,7 +16,7 @@ import org.vadere.simulator.projects.dataprocessing.outputfile.OutputFile;
import org.vadere.simulator.projects.io.JsonConverter;
import org.vadere.util.io.IOUtils;
public class TestOutputFileAfterMultipleRuns {
public class TestOutputFile {
private Scenario testScenario;
private MainModel mainModel;
......@@ -40,19 +41,38 @@ public class TestOutputFileAfterMultipleRuns {
@Test()
public void testFileFormatAfterMultipleSimulationRuns() {
ArrayList<String> indicesAfterFirstRun = new ArrayList<>();
ArrayList<String> indicesAfterSecondRun = new ArrayList<>();
ArrayList<String> headerAfterFirstRun = new ArrayList<>();
ArrayList<String> headerAfterSecondRun = new ArrayList<>();
ProcessorManager manager = testScenario.getDataProcessingJsonManager()
.createProcessorManager(mainModel);
manager.initOutputFiles();
List<OutputFile<?>> outputFiles = testScenario.getDataProcessingJsonManager().getOutputFiles();
outputFiles.forEach(f -> indicesAfterFirstRun.add(f.getIndices()));
outputFiles.forEach(f -> headerAfterFirstRun.add(f.getHeaderLine()));
manager.initOutputFiles();
outputFiles.forEach(f -> indicesAfterSecondRun.add(f.getIndices()));
outputFiles.forEach(f -> headerAfterSecondRun.add(f.getHeaderLine()));
assertEquals("Duplicated Processors in OutputFile after multiple Simulations",
indicesAfterFirstRun, indicesAfterSecondRun);
headerAfterFirstRun, headerAfterSecondRun);
}
@Test
public void testHandlingNameConflict(){
ProcessorManager manager = testScenario.getDataProcessingJsonManager()
.createProcessorManager(mainModel);
manager.initOutputFiles();
List<String> header = testScenario.getDataProcessingJsonManager().getOutputFiles().get(0).getEntireHeader();
//Note these fail if the name conflict is handled differently, for now hard coded.
assertTrue(header.contains("timeStep"));
assertTrue(header.contains("pedestrianId"));
assertTrue(header.contains("x-Proc1"));
assertTrue(header.contains("y-Proc1"));
assertTrue(header.contains("x-Proc2"));
assertTrue(header.contains("y-Proc2"));
}
}
......@@ -213,9 +213,9 @@ public class VPolygon extends Path2D.Double implements VShape {
public boolean intersectsRectangleLine(final VRectangle rectangle) {
return intersects(new VLine(rectangle.getMinX(), rectangle.getMinY(), rectangle.getMaxX(), rectangle.getMinY()))
|| intersects(new VLine(rectangle.getMaxX(), rectangle.getMinY(), rectangle.getMaxX(), rectangle.getMaxY()))
|| intersects(new VLine(rectangle.getMaxX(), rectangle.getMaxY(), rectangle.getMinX(), rectangle.getMaxY()))
|| intersects(new VLine(rectangle.getMinX(), rectangle.getMaxY(), rectangle.getMinX(), rectangle.getMinY()));
|| intersects(new VLine(rectangle.getMaxX(), rectangle.getMinY(), rectangle.getMaxX(), rectangle.getMaxY()))
|| intersects(new VLine(rectangle.getMaxX(), rectangle.getMaxY(), rectangle.getMinX(), rectangle.getMaxY()))
|| intersects(new VLine(rectangle.getMinX(), rectangle.getMaxY(), rectangle.getMinX(), rectangle.getMinY()));
}
public double getArea() {
......
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