Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 41 additions & 4 deletions src/application/ScenarioAuthoringWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <utility>
#include <vector>

#include <QCheckBox>
#include <QComboBox>
#include <QDialog>
#include <QDialogButtonBox>
Expand Down Expand Up @@ -172,7 +173,11 @@ QString severityLabel(safecrowd::domain::ScenarioElementSeverity severity) {
}

QString hazardScheduleSummary(const safecrowd::domain::EnvironmentHazardDraft& hazard) {
return QString("%1s - %2s").arg(hazard.startSeconds, 0, 'f', 1).arg(hazard.endSeconds, 0, 'f', 1);
const auto start = std::max(0.0, hazard.startSeconds);
if (safecrowd::domain::environmentHazardHasOpenEndedSchedule(hazard)) {
return QString("%1s - open").arg(start, 0, 'f', 1);
}
return QString("%1s - %2s").arg(start, 0, 'f', 1).arg(std::max(start, hazard.endSeconds), 0, 'f', 1);
}

QString hazardZoneSummary(
Expand Down Expand Up @@ -245,13 +250,35 @@ bool editEnvironmentHazard(
startSpin->setRange(0.0, 86400.0);
startSpin->setDecimals(1);
startSpin->setSuffix(" s");
startSpin->setValue(std::max(0.0, hazard->startSeconds));
const auto initialStartSeconds = std::max(0.0, hazard->startSeconds);
const auto initialOpenEnded = safecrowd::domain::environmentHazardHasOpenEndedSchedule(*hazard);
startSpin->setValue(initialStartSeconds);

auto* endSpin = new QDoubleSpinBox(&dialog);
endSpin->setRange(0.0, 86400.0);
endSpin->setDecimals(1);
endSpin->setSuffix(" s");
endSpin->setValue(std::max(0.0, hazard->endSeconds));
endSpin->setValue(initialOpenEnded
? initialStartSeconds
: std::max(initialStartSeconds, hazard->endSeconds));

auto* openEndedCheck = new QCheckBox("Open ended", &dialog);
openEndedCheck->setChecked(initialOpenEnded);
endSpin->setEnabled(!initialOpenEnded);

QObject::connect(openEndedCheck, &QCheckBox::toggled, &dialog, [=](bool checked) {
endSpin->setEnabled(!checked);
if (checked) {
endSpin->setValue(startSpin->value());
} else if (endSpin->value() <= startSpin->value()) {
endSpin->setValue(std::min(86400.0, startSpin->value() + 60.0));
}
});
QObject::connect(startSpin, qOverload<double>(&QDoubleSpinBox::valueChanged), &dialog, [=](double value) {
if (openEndedCheck->isChecked()) {
endSpin->setValue(value);
}
});

auto* severityCombo = new QComboBox(&dialog);
severityCombo->addItem("Low", static_cast<int>(safecrowd::domain::ScenarioElementSeverity::Low));
Expand All @@ -270,6 +297,7 @@ bool editEnvironmentHazard(
form->addRow("Y", ySpin);
form->addRow("Start", startSpin);
form->addRow("End", endSpin);
form->addRow("", openEndedCheck);
form->addRow("Severity", severityCombo);
form->addRow("Note", noteEdit);
root->addLayout(form);
Expand Down Expand Up @@ -301,6 +329,11 @@ bool editEnvironmentHazard(
xSpin->setFocus();
return;
}
if (!openEndedCheck->isChecked() && endSpin->value() <= startSpin->value()) {
QMessageBox::warning(&dialog, "Edit hazard", "Set the end time after the start time.");
endSpin->setFocus();
return;
}

dialog.accept();
});
Expand Down Expand Up @@ -332,14 +365,18 @@ bool editEnvironmentHazard(
QMessageBox::warning(parent, "Edit hazard", "The hazard location must stay inside the affected zone.");
return false;
}
if (!openEndedCheck->isChecked() && endSpin->value() <= startSpin->value()) {
QMessageBox::warning(parent, "Edit hazard", "Set the end time after the start time.");
return false;
}

hazard->kind = static_cast<safecrowd::domain::EnvironmentHazardKind>(kindCombo->currentData().toInt());
hazard->name = name.toStdString();
hazard->affectedZoneId = selectedZoneId;
hazard->floorId = selectedZone->floorId;
hazard->position = selectedPosition;
hazard->startSeconds = startSpin->value();
hazard->endSeconds = std::max(hazard->startSeconds, endSpin->value());
hazard->endSeconds = openEndedCheck->isChecked() ? hazard->startSeconds : endSpin->value();
hazard->severity = static_cast<safecrowd::domain::ScenarioElementSeverity>(severityCombo->currentData().toInt());
hazard->note = noteEdit->toPlainText().trimmed().toStdString();
return true;
Expand Down
1 change: 1 addition & 0 deletions src/application/ScenarioBatchResultWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,7 @@ void ScenarioBatchResultWidget::applyReplayFrameData(const safecrowd::domain::Si

if (canvas_ != nullptr) {
canvas_->setConnectionBlocks(result.scenario.control.connectionBlocks);
canvas_->setEnvironmentHazards(result.scenario.environment.hazards);
canvas_->setFrame(frame);
canvas_->setHotspotOverlay(result.risk.hotspots);
canvas_->setBottleneckOverlay(result.risk.bottlenecks);
Expand Down
31 changes: 10 additions & 21 deletions src/application/ScenarioCanvasWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,14 @@ QString formatEnvironmentHazardTooltip(const safecrowd::domain::EnvironmentHazar
if (!hazard.name.empty()) {
text.append(QString("\n%1").arg(QString::fromStdString(hazard.name)));
}
text.append(QString("\nActive: %1s ~ %2s").arg(hazard.startSeconds, 0, 'f', 1).arg(hazard.endSeconds, 0, 'f', 1));
const auto start = std::max(0.0, hazard.startSeconds);
if (safecrowd::domain::environmentHazardHasOpenEndedSchedule(hazard)) {
text.append(QString("\nActive: %1s ~ open").arg(start, 0, 'f', 1));
} else {
text.append(QString("\nActive: %1s ~ %2s")
.arg(start, 0, 'f', 1)
.arg(std::max(start, hazard.endSeconds), 0, 'f', 1));
}
text.append(QString("\nSeverity: %1").arg(severityLabel(hazard.severity)));
return text;
}
Expand All @@ -232,16 +239,7 @@ std::optional<std::size_t> hoveredEnvironmentHazardIndex(
double closestDistanceSq = kHoverRadiusPixels * kHoverRadiusPixels;
for (std::size_t index = 0; index < hazards.size(); ++index) {
const auto& hazard = hazards[index];
auto floorId = hazard.floorId;
if (floorId.empty() && !hazard.affectedZoneId.empty()) {
const auto zoneIt = std::find_if(layout.zones.begin(), layout.zones.end(), [&](const auto& zone) {
return zone.id == hazard.affectedZoneId;
});
if (zoneIt != layout.zones.end()) {
floorId = zoneIt->floorId;
}
}
if (!matchesFloor(floorId, currentFloorId)) {
if (!matchesFloor(safecrowd::domain::environmentHazardFloorId(layout, hazard), currentFloorId)) {
continue;
}

Expand Down Expand Up @@ -2045,16 +2043,7 @@ void ScenarioCanvasWidget::drawConnectionBlocks(QPainter& painter, const LayoutC

void ScenarioCanvasWidget::drawEnvironmentHazards(QPainter& painter, const LayoutCanvasTransform& transform) const {
for (const auto& hazard : environmentHazards_) {
auto floorId = hazard.floorId;
if (floorId.empty() && !hazard.affectedZoneId.empty()) {
const auto zoneIt = std::find_if(layout_.zones.begin(), layout_.zones.end(), [&](const auto& zone) {
return zone.id == hazard.affectedZoneId;
});
if (zoneIt != layout_.zones.end()) {
floorId = zoneIt->floorId;
}
}
if (!matchesFloor(floorId, currentFloorId_)) {
if (!matchesFloor(safecrowd::domain::environmentHazardFloorId(layout_, hazard), currentFloorId_)) {
continue;
}

Expand Down
1 change: 1 addition & 0 deletions src/application/ScenarioResultWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1284,6 +1284,7 @@ ScenarioResultWidget::ScenarioResultWidget(

auto* canvas = new SimulationCanvasWidget(layout_, shell_);
canvas->setFrame(frame_);
canvas->setEnvironmentHazards(scenario_.environment.hazards);
canvas->setHotspotOverlay(risk_.hotspots);
canvas->setBottleneckOverlay(risk_.bottlenecks);
ResultReplayControls* replayControls = nullptr;
Expand Down
2 changes: 2 additions & 0 deletions src/application/ScenarioRunWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ QWidget* ScenarioRunWidget::createRunCanvas() {
if (!batchRunner_.empty()) {
const auto& run = batchRunner_.run(0);
canvas_->setConnectionBlocks(run.scenario.control.connectionBlocks);
canvas_->setEnvironmentHazards(run.scenario.environment.hazards);
canvas_->setRouteGuidances(run.scenario.control.routeGuidances);
canvas_->setFrame(run.frame);
}
Expand Down Expand Up @@ -568,6 +569,7 @@ void ScenarioRunWidget::refreshStatus() {
const auto& frame = selectedRun.frame;
if (canvas_ != nullptr) {
canvas_->setConnectionBlocks(selectedRun.scenario.control.connectionBlocks);
canvas_->setEnvironmentHazards(selectedRun.scenario.environment.hazards);
canvas_->setRouteGuidances(selectedRun.scenario.control.routeGuidances);
canvas_->setFrame(selectedRun.frame);
}
Expand Down
Loading
Loading