Commit a45cb0e3 authored by Stefan Schuhbaeck's avatar Stefan Schuhbaeck

add ScenarioCheckerMessageFormatter and implement gui version.

parent 386f1aa6
......@@ -307,6 +307,15 @@ select_shape_tooltip=Select Shape
# ScenarioChecker
ScenarioChecker.type.error=Error
ScenarioChecker.type.warning=Warning
ScenarioChecker.type.topography.error=Topography Error
ScenarioChecker.type.topography.warning=Topography Warning
ScenarioChecker.type.simulation.error=Simulations Attribute Error
ScenarioChecker.type.simulation.warning=Simulations Attribute Warning
ScenarioChecker.type.model.error=Model Attribute Error
ScenarioChecker.type.model.warning=Model Attribute Warning
ScenarioChecker.type.processor.error=Processor Error
ScenarioChecker.type.processor.warning=Processor Warning
ScenarioChecker.source.targetIdNotFound=The following target ids where not found in the scenario.
ScenarioChecker.source.noTargetIdSet=No Target Ids set for Source.
ScenarioChecker.source.noTargetIdAndNoSpawn=No Target Ids set for Source with SpawnNumber 0. This might be an error.
......@@ -330,7 +339,7 @@ ScenarioChecker.overlap.obstacle.target.warn=Target contains an obstacle. This s
ScenarioChecker.overlap.obstacle.source=Obstacle overlaps with a source. This setup will spawn pedestrians within the obstacle.
ScenarioChecker.overlap.obstacle.obstacle=Two obstacles overlap / is enclosed completely. Delete one for better performance.
ScenarioChecker.simAttr.simTimeStepWrong=simTimeStep parameter outside of allowed range.
ScenarioChecker.simAttr.simTimeStepWrong=simTimeStep parameter outside of allowed range
ScenarioChecker.msg.ok=Scenario ok.
ScenarioChecker.msg.warn=Scenario contains warnings.
......
......@@ -297,8 +297,18 @@ TopographyCreator.btnChecker.tooltip=Topography Linter Nachrichten
TopographyCreator.btnMakro.tooltip=Erzeuge nicht gesetzte IDs.
# ScenarioChecker
ScenarioChecker.type.error=Fehler
ScenarioChecker.type.warning=Warnung
ScenarioChecker.type.error=Error
ScenarioChecker.type.warning=Warning
ScenarioChecker.type.topography.error=Topography Fehler
ScenarioChecker.type.topography.warning=Topography Warnung
ScenarioChecker.type.simulation.error=Simulations Attribut Fehler
ScenarioChecker.type.simulation.warning=Simulations Attribut Wahrnung
ScenarioChecker.type.model.error=Model Attribute Fehler
ScenarioChecker.type.model.warning=Model Attribute Warnung
ScenarioChecker.type.processor.error=Processor Fehler
ScenarioChecker.type.processor.warning=Procesor Warnung
ScenarioChecker.source.targetIdNotFound=Die folgenden Ziel-IDs wurden nicht im Szenario gefunden.
ScenarioChecker.source.noTargetIdSet=In der Quelle wurden keine Ziel Ids vergeben.
ScenarioChecker.source.noTargetIdAndNoSpawn=In der Quelle wurden keine Ziel Ids vergeben, aber die Spawn Anzahl ist bei 0.
......@@ -321,7 +331,7 @@ ScenarioChecker.overlap.obstacle.target.warn=Ziel hat ein Hinderniss in sich. Di
ScenarioChecker.overlap.obstacle.source=Hinderniss \u00fcberdeckt Quelle. Die f\u00fchrt dazu, dass Pedestrians im Hinderniss erzeugt werden.
ScenarioChecker.overlap.obstacle.obstacle=Zwei identische bzw. eingeschlossene Obstacles gefunden. L\u00f6sche eins f\u00fcr bessere Performance
ScenarioChecker.simAttr.simTimeStepWrong=simTimeStep Parameter au\u00dferhalb des Definitionsbereichs.
ScenarioChecker.simAttr.simTimeStepWrong=simTimeStep Parameter au\u00dferhalb des Definitionsbereichs
ScenarioChecker.msg.ok=Scenario ok.
ScenarioChecker.msg.warn=Scenario hat Warnungen.
......
package org.vadere.gui.components.control;
import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.projectview.view.ScenarioNamePanel;
import org.vadere.gui.projectview.view.ScenarioPanel;
import org.vadere.gui.projectview.view.VDialogManager;
......@@ -8,22 +7,18 @@ import org.vadere.gui.topographycreator.model.IDrawPanelModel;
import org.vadere.simulator.projects.Scenario;
import org.vadere.simulator.util.ScenarioChecker;
import org.vadere.simulator.util.ScenarioCheckerMessage;
import org.vadere.state.scenario.ScenarioElement;
import java.awt.event.ActionEvent;
import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;
import java.util.PriorityQueue;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
public class ActionScenarioChecker extends AbstractAction implements Observer {
private PriorityQueue<ScenarioCheckerMessage> errorMsg;
private PriorityQueue<ScenarioCheckerMessage> warnMsg;
private MsgDocument msgDocument;
private PriorityQueue<ScenarioCheckerMessage> messages;
private ScenarioCheckerMessageDocumentView msgDocument;
private IDrawPanelModel model;
private ScenarioNamePanel view;
......@@ -31,8 +26,7 @@ public class ActionScenarioChecker extends AbstractAction implements Observer {
public
ActionScenarioChecker(String name, ScenarioNamePanel view) {
super(name);
this.errorMsg = new PriorityQueue<>();
this.warnMsg = new PriorityQueue<>();
this.messages = new PriorityQueue<>();
this.view = view;
}
......@@ -70,118 +64,24 @@ public class ActionScenarioChecker extends AbstractAction implements Observer {
public void check(final Scenario scenario){
ScenarioChecker checker = new ScenarioChecker(scenario);
errorMsg.clear();
warnMsg.clear();
messages.clear();
ScenarioPanel.setActiveTopographyErrorMsg(null);
addMsg(checker.checkBuildingStep());
messages = checker.checkBuildingStep();
msgDocument = new ScenarioCheckerMessageDocumentView(model);
msgDocument.setMessages(messages);
view.setGreen();
if (warnMsg.size() > 0) {
view.setYellow();
}
if (errorMsg.size() > 0) {
view.setRed();
}
}
/**
* @return MsgDocument containing erros and warnings with links to the specific scenario element
*/
private MsgDocument checkerMessagesToDoc() {
StringBuilder sb = new StringBuilder();
MsgDocument doc = new MsgDocument();
if (errorMsg.size() > 0) {
sb.append("<h3> Errors </h3>").append("<br>");
errorMsg.forEach(m -> msgToDocString(sb, m, doc));
}
if (messages.size() > 0){
if (warnMsg.size() > 0) {
if (sb.length() > 0) {
sb.append("<br>");
if(messages.peek().getMsgType().isWarnMsg()) {
view.setYellow();
}
sb.append("<h3> Warnings </h3>").append("<br>");
warnMsg.forEach(m -> msgToDocString(sb, m, doc));
}
if (errorMsg.size() == 0 && warnMsg.size() == 0) {
sb.append("No Problems found.");
}
doc.setText(sb.toString());
return doc;
}
private void msgToDocString(StringBuilder sb, ScenarioCheckerMessage msg, MsgDocument doc) {
if (msg.hasTarget()){
sb.append("[");
msg.getMsgTarget().getTargets().forEach(t -> {
doc.makeLink(t, sb);
sb.append(", ");
});
sb.setLength(sb.length()-2);
sb.append("] ");
}
sb.append("Reason: ").append(Messages.getString(msg.getReason().getLocalMessageId()));
if (!msg.getReasonModifier().isEmpty()) {
sb.append(" ").append(msg.getReasonModifier());
}
sb.append("<br>");
doc.setText(sb.toString());
}
private void addMsg(PriorityQueue<ScenarioCheckerMessage> msg) {
msg.forEach(m -> {
if (m.getMsgType().getId() >= 500) {
warnMsg.add(m);
} else {
errorMsg.add(m);
if (messages.peek().getMsgType().isErrorMsg()) {
view.setRed();
ScenarioPanel.setActiveTopographyErrorMsg(msgDocument);
}
});
msgDocument = checkerMessagesToDoc();
if (errorMsg.size() > 0) {
ScenarioPanel.setActiveTopographyErrorMsg(msgDocument);
}
}
/**
* Simple {@link JEditorPane} wrapper which manages the links within the document to highlight
* the {@link ScenarioElement} producing the topographyError / topographyWarning.
*/
class MsgDocument extends JEditorPane {
HashMap<String, ScenarioElement> linkMap;
int id;
MsgDocument() {
linkMap = new HashMap<>();
id = 0;
setContentType("text/html");
setEditable(false);
addHyperlinkListener(e -> {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
ScenarioElement element = linkMap.getOrDefault(e.getDescription(), null);
if (element != null) {
if (model != null){
model.setSelectedElement(element);
}
}
}
});
}
void makeLink(ScenarioElement element, StringBuilder sb) {
linkMap.put("element/id/" + id, element);
sb.append("<a href='element/id/")
.append(id).append("'>")
.append(element.getClass().getSimpleName())
.append("{Id:").append(element.getId()).append("}")
.append("</a>");
id++;
}
}
}
package org.vadere.gui.components.control;
import org.vadere.gui.components.utils.GuiScenarioCheckerMessageFormatter;
import org.vadere.gui.topographycreator.model.IDrawPanelModel;
import org.vadere.simulator.util.ScenarioCheckerMessage;
import org.vadere.simulator.util.ScenarioCheckerMessageFormatter;
import org.vadere.state.scenario.ScenarioElement;
import java.util.HashMap;
import java.util.PriorityQueue;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
public class ScenarioCheckerMessageDocumentView extends JEditorPane {
private final IDrawPanelModel model;
private final ScenarioCheckerMessageFormatter formatter;
HashMap<String, ScenarioElement> linkMap;
int id;
public ScenarioCheckerMessageDocumentView(IDrawPanelModel model) {
this.model = model;
this.formatter = new GuiScenarioCheckerMessageFormatter(this);
linkMap = new HashMap<>();
id = 0;
setContentType("text/html");
setEditable(false);
addHyperlinkListener(e -> {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
ScenarioElement element = linkMap.getOrDefault(e.getDescription(), null);
if (element != null && this.model != null) {
this.model.setSelectedElement(element);
}
}
});
}
public void setMessages(PriorityQueue<ScenarioCheckerMessage> messages){
setText(formatter.formatMessages(messages));
}
public int makeLink(ScenarioElement element) {
int currId = id;
id++;
linkMap.put("element/id/" + currId, element);
return currId;
}
}
package org.vadere.gui.components.utils;
import org.vadere.gui.components.control.ScenarioCheckerMessageDocumentView;
import org.vadere.simulator.util.AbstractScenarioCheckerMessageFormatter;
import org.vadere.simulator.util.ScenarioCheckerMessage;
public class GuiScenarioCheckerMessageFormatter extends AbstractScenarioCheckerMessageFormatter {
final ScenarioCheckerMessageDocumentView view;
public GuiScenarioCheckerMessageFormatter(ScenarioCheckerMessageDocumentView view) {
this.view = view;
}
@Override
protected void writeHeader(ScenarioCheckerMessage msg) {
sb.append("<h4>")
.append(Messages.getString(msg.getMsgType().getLocalTypeId()))
.append("</h4>");
}
@Override
protected void writeMsg(ScenarioCheckerMessage msg) {
if (msg.hasTarget()){
sb.append("[");
msg.getMsgTarget().getTargets().forEach(element -> {
int id = view.makeLink(element);
sb.append("<a href='element/id/")
.append(id).append("'>")
.append(element.getClass().getSimpleName())
.append("{Id:").append(element.getId()).append("}")
.append("</a>");
sb.append(", ");
});
sb.setLength(sb.length()-2);
sb.append("] ");
}
sb.append("Reason: ").append(Messages.getString(msg.getReason().getLocalMessageId()));
if (!msg.getReasonModifier().isEmpty()) {
sb.append(" ").append(msg.getReasonModifier());
}
sb.append("<br>");
}
}
......@@ -20,14 +20,13 @@ public class ScenarioNamePanel extends JPanel {
private ActionScenarioChecker action;
public ScenarioNamePanel(){
action = new ActionScenarioChecker("ScenarioChecker", this);
btnScenarioChecker = new JButton(iconGreen);
btnScenarioChecker.setBorderPainted(false);
btnScenarioChecker.setBorder(null);
btnScenarioChecker.setMargin(new Insets(0, 0, 0, 0));
btnScenarioChecker.setContentAreaFilled(false);
btnScenarioChecker.addActionListener(e-> System.out.println("ddd"));
btnScenarioChecker.setRolloverIcon(iconRed);
action = new ActionScenarioChecker("ScenarioChecker", this);
btnScenarioChecker.addActionListener(action);
add(btnScenarioChecker);
lblScenarioName = new JLabel();
......
package org.vadere.simulator.util;
import java.util.Arrays;
import java.util.PriorityQueue;
public abstract class AbstractScenarioCheckerMessageFormatter implements ScenarioCheckerMessageFormatter{
private ScenarioCheckerMessageType currentType;
protected StringBuilder sb;
public AbstractScenarioCheckerMessageFormatter(){
this.sb = new StringBuilder();
}
@Override
public String formatMessages(PriorityQueue<ScenarioCheckerMessage> scenarioCheckerMessages) {
sb.setLength(0);
ScenarioCheckerMessage[] messages = new ScenarioCheckerMessage[scenarioCheckerMessages.size()];
scenarioCheckerMessages.toArray(messages);
Arrays.sort(messages);
for (ScenarioCheckerMessage msg : messages) {
if (isNewType(msg)){
writeHeader(msg);
}
writeMsg(msg);
}
return sb.toString();
}
protected boolean isNewType(ScenarioCheckerMessage msg){
if (currentType == null || !currentType.equals(msg.getMsgType())){
currentType = msg.getMsgType();
return true;
} else {
return false;
}
}
/**
* If msg is the first message of its {@link org.vadere.state.types.ScenarioElementType} write
* some header or headline.
* @param msg current Message
*/
protected abstract void writeHeader(ScenarioCheckerMessage msg);
/**
* Write msg to StringBuilder
* @param msg current Message
*/
protected abstract void writeMsg(ScenarioCheckerMessage msg);
}
......@@ -18,7 +18,7 @@ public class ScenarioCheckerMessage implements Comparable<ScenarioCheckerMessage
private ScenarioCheckerMessageTarget msgTarget;
public ScenarioCheckerMessage(ScenarioCheckerMessageType type) {
public ScenarioCheckerMessage(@NotNull ScenarioCheckerMessageType type) {
msgType = type;
msgTarget = null;
reasonModifier = "";
......
package org.vadere.simulator.util;
import java.util.Arrays;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.stream.Collectors;
public interface ScenarioCheckerMessageFormatter {
/**
* Return a String representation of the given Messages in the order
* of the given PriorityQueue Errors -> Warnings
*
* @param msg List of Messages
* @return String representation of Messages;
*/
String formatMessages(PriorityQueue<ScenarioCheckerMessage> msg);
/**
* Return a String representation of the given Messages in the order
* of the given PriorityQueue. Only return messages matching any of the Types
* given by typeFilter
*
* @param msg List of Messages
* @param typeFilter only include messages of the given types.
* @return String representation of Messages;
*/
default String formatMessages(PriorityQueue<ScenarioCheckerMessage> msg,
ScenarioCheckerMessageType... typeFilter){
Set<ScenarioCheckerMessageType> typeSet = new HashSet<>(Arrays.asList(typeFilter));
return formatMessages(msg.stream()
.filter(m -> typeSet.contains(m.getMsgType()))
.collect(Collectors.toCollection(PriorityQueue::new))
);
}
}
package org.vadere.simulator.util;
import java.util.Comparator;
/**
* Types of {@link ScenarioChecker} messages. The {@link #msgId} is used as messageId for locale
* de/en
*/
public enum ScenarioCheckerMessageType {
TOPOGRAPHY_ERROR("Error",100, "ScenarioChecker.type.error"),
TOPOGRAPHY_WARN("Warning",500, "ScenarioChecker.type.warning"),
SIMULATION_ATTR_ERROR("Error",101, "ScenarioChecker.type.error"),
SIMULATION_ATTR_WARN("Warning",501, "ScenarioChecker.type.warning"),
MODEL_ATTR_ERROR("Error",102, "ScenarioChecker.type.error"),
MODEL_ATTR_WARN("Warning",502, "ScenarioChecker.type.warning"),
DATA_PROCESSOR_ERROR("Error",103, "ScenarioChecker.type.error"),
DATA_PROCESSOR_WARN("Warning",503, "ScenarioChecker.type.warning");
TOPOGRAPHY_ERROR("Error",100, "ScenarioChecker.type.topography.error"),
TOPOGRAPHY_WARN("Warning",500, "ScenarioChecker.type.topography.warning"),
SIMULATION_ATTR_ERROR("Error",101, "ScenarioChecker.type.simulation.error"),
SIMULATION_ATTR_WARN("Warning",501, "ScenarioChecker.type.simulation.warning"),
MODEL_ATTR_ERROR("Error",102, "ScenarioChecker.type.model.error"),
MODEL_ATTR_WARN("Warning",502, "ScenarioChecker.type.model.warning"),
DATA_PROCESSOR_ERROR("Error",103, "ScenarioChecker.type.processor.error"),
DATA_PROCESSOR_WARN("Warning",503, "ScenarioChecker.type.processor.warning");
private static final int ERROR_START = 100;
private static final int WARN_START = 500;
private String type;
private String msgId;
......@@ -27,6 +28,14 @@ public enum ScenarioCheckerMessageType {
this.msgId = msgId;
}
public boolean isErrorMsg(){
return type.equals("Error");
}
public boolean isWarnMsg(){
return type.equals("Warn");
}
public String getType() {
return type;
}
......@@ -41,6 +50,7 @@ public enum ScenarioCheckerMessageType {
public String toString() {
return "ScenarioCheckerMessageType{" +
"type='" + type + '\'' +
", id=" + id +
'}';
}
}
......@@ -22,7 +22,8 @@ public class SimulationTimeStepLengthCheck extends AbstractScenarioCheck {
if(simTimeStep < LOW_BOUND || simTimeStep > HIGH_BOUND){
ret.add(msgBuilder.simulationAttrError()
.reason(ScenarioCheckerReason.SIM_TIME_STEP_WRONG, String.format("[%3.1f - %3.1f]", LOW_BOUND, HIGH_BOUND))
.reason(ScenarioCheckerReason.SIM_TIME_STEP_WRONG,
String.format(" [%3.1f - %3.1f] current value: %3.1f", LOW_BOUND, HIGH_BOUND, simTimeStep))
.build());
}
return ret;
......
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