Skip to content

Commit aeec4ee

Browse files
SilverSupplierlearncold
authored andcommitted
[Domain] Refine fire smoke reaction behavior
1 parent 0530f3b commit aeec4ee

9 files changed

Lines changed: 484 additions & 188 deletions

src/application/ScenarioAuthoringWidget.cpp

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <utility>
88
#include <vector>
99

10+
#include <QCheckBox>
1011
#include <QComboBox>
1112
#include <QDialog>
1213
#include <QDialogButtonBox>
@@ -172,7 +173,11 @@ QString severityLabel(safecrowd::domain::ScenarioElementSeverity severity) {
172173
}
173174

174175
QString hazardScheduleSummary(const safecrowd::domain::EnvironmentHazardDraft& hazard) {
175-
return QString("%1s - %2s").arg(hazard.startSeconds, 0, 'f', 1).arg(hazard.endSeconds, 0, 'f', 1);
176+
const auto start = std::max(0.0, hazard.startSeconds);
177+
if (safecrowd::domain::environmentHazardHasOpenEndedSchedule(hazard)) {
178+
return QString("%1s - open").arg(start, 0, 'f', 1);
179+
}
180+
return QString("%1s - %2s").arg(start, 0, 'f', 1).arg(std::max(start, hazard.endSeconds), 0, 'f', 1);
176181
}
177182

178183
QString hazardZoneSummary(
@@ -245,13 +250,35 @@ bool editEnvironmentHazard(
245250
startSpin->setRange(0.0, 86400.0);
246251
startSpin->setDecimals(1);
247252
startSpin->setSuffix(" s");
248-
startSpin->setValue(std::max(0.0, hazard->startSeconds));
253+
const auto initialStartSeconds = std::max(0.0, hazard->startSeconds);
254+
const auto initialOpenEnded = safecrowd::domain::environmentHazardHasOpenEndedSchedule(*hazard);
255+
startSpin->setValue(initialStartSeconds);
249256

250257
auto* endSpin = new QDoubleSpinBox(&dialog);
251258
endSpin->setRange(0.0, 86400.0);
252259
endSpin->setDecimals(1);
253260
endSpin->setSuffix(" s");
254-
endSpin->setValue(std::max(0.0, hazard->endSeconds));
261+
endSpin->setValue(initialOpenEnded
262+
? initialStartSeconds
263+
: std::max(initialStartSeconds, hazard->endSeconds));
264+
265+
auto* openEndedCheck = new QCheckBox("Open ended", &dialog);
266+
openEndedCheck->setChecked(initialOpenEnded);
267+
endSpin->setEnabled(!initialOpenEnded);
268+
269+
QObject::connect(openEndedCheck, &QCheckBox::toggled, &dialog, [=](bool checked) {
270+
endSpin->setEnabled(!checked);
271+
if (checked) {
272+
endSpin->setValue(startSpin->value());
273+
} else if (endSpin->value() <= startSpin->value()) {
274+
endSpin->setValue(std::min(86400.0, startSpin->value() + 60.0));
275+
}
276+
});
277+
QObject::connect(startSpin, qOverload<double>(&QDoubleSpinBox::valueChanged), &dialog, [=](double value) {
278+
if (openEndedCheck->isChecked()) {
279+
endSpin->setValue(value);
280+
}
281+
});
255282

256283
auto* severityCombo = new QComboBox(&dialog);
257284
severityCombo->addItem("Low", static_cast<int>(safecrowd::domain::ScenarioElementSeverity::Low));
@@ -270,6 +297,7 @@ bool editEnvironmentHazard(
270297
form->addRow("Y", ySpin);
271298
form->addRow("Start", startSpin);
272299
form->addRow("End", endSpin);
300+
form->addRow("", openEndedCheck);
273301
form->addRow("Severity", severityCombo);
274302
form->addRow("Note", noteEdit);
275303
root->addLayout(form);
@@ -301,6 +329,11 @@ bool editEnvironmentHazard(
301329
xSpin->setFocus();
302330
return;
303331
}
332+
if (!openEndedCheck->isChecked() && endSpin->value() <= startSpin->value()) {
333+
QMessageBox::warning(&dialog, "Edit hazard", "Set the end time after the start time.");
334+
endSpin->setFocus();
335+
return;
336+
}
304337

305338
dialog.accept();
306339
});
@@ -332,14 +365,18 @@ bool editEnvironmentHazard(
332365
QMessageBox::warning(parent, "Edit hazard", "The hazard location must stay inside the affected zone.");
333366
return false;
334367
}
368+
if (!openEndedCheck->isChecked() && endSpin->value() <= startSpin->value()) {
369+
QMessageBox::warning(parent, "Edit hazard", "Set the end time after the start time.");
370+
return false;
371+
}
335372

336373
hazard->kind = static_cast<safecrowd::domain::EnvironmentHazardKind>(kindCombo->currentData().toInt());
337374
hazard->name = name.toStdString();
338375
hazard->affectedZoneId = selectedZoneId;
339376
hazard->floorId = selectedZone->floorId;
340377
hazard->position = selectedPosition;
341378
hazard->startSeconds = startSpin->value();
342-
hazard->endSeconds = std::max(hazard->startSeconds, endSpin->value());
379+
hazard->endSeconds = openEndedCheck->isChecked() ? hazard->startSeconds : endSpin->value();
343380
hazard->severity = static_cast<safecrowd::domain::ScenarioElementSeverity>(severityCombo->currentData().toInt());
344381
hazard->note = noteEdit->toPlainText().trimmed().toStdString();
345382
return true;

src/application/ScenarioCanvasWidget.cpp

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,14 @@ QString formatEnvironmentHazardTooltip(const safecrowd::domain::EnvironmentHazar
215215
if (!hazard.name.empty()) {
216216
text.append(QString("\n%1").arg(QString::fromStdString(hazard.name)));
217217
}
218-
text.append(QString("\nActive: %1s ~ %2s").arg(hazard.startSeconds, 0, 'f', 1).arg(hazard.endSeconds, 0, 'f', 1));
218+
const auto start = std::max(0.0, hazard.startSeconds);
219+
if (safecrowd::domain::environmentHazardHasOpenEndedSchedule(hazard)) {
220+
text.append(QString("\nActive: %1s ~ open").arg(start, 0, 'f', 1));
221+
} else {
222+
text.append(QString("\nActive: %1s ~ %2s")
223+
.arg(start, 0, 'f', 1)
224+
.arg(std::max(start, hazard.endSeconds), 0, 'f', 1));
225+
}
219226
text.append(QString("\nSeverity: %1").arg(severityLabel(hazard.severity)));
220227
return text;
221228
}
@@ -232,16 +239,7 @@ std::optional<std::size_t> hoveredEnvironmentHazardIndex(
232239
double closestDistanceSq = kHoverRadiusPixels * kHoverRadiusPixels;
233240
for (std::size_t index = 0; index < hazards.size(); ++index) {
234241
const auto& hazard = hazards[index];
235-
auto floorId = hazard.floorId;
236-
if (floorId.empty() && !hazard.affectedZoneId.empty()) {
237-
const auto zoneIt = std::find_if(layout.zones.begin(), layout.zones.end(), [&](const auto& zone) {
238-
return zone.id == hazard.affectedZoneId;
239-
});
240-
if (zoneIt != layout.zones.end()) {
241-
floorId = zoneIt->floorId;
242-
}
243-
}
244-
if (!matchesFloor(floorId, currentFloorId)) {
242+
if (!matchesFloor(safecrowd::domain::environmentHazardFloorId(layout, hazard), currentFloorId)) {
245243
continue;
246244
}
247245

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

20462044
void ScenarioCanvasWidget::drawEnvironmentHazards(QPainter& painter, const LayoutCanvasTransform& transform) const {
20472045
for (const auto& hazard : environmentHazards_) {
2048-
auto floorId = hazard.floorId;
2049-
if (floorId.empty() && !hazard.affectedZoneId.empty()) {
2050-
const auto zoneIt = std::find_if(layout_.zones.begin(), layout_.zones.end(), [&](const auto& zone) {
2051-
return zone.id == hazard.affectedZoneId;
2052-
});
2053-
if (zoneIt != layout_.zones.end()) {
2054-
floorId = zoneIt->floorId;
2055-
}
2056-
}
2057-
if (!matchesFloor(floorId, currentFloorId_)) {
2046+
if (!matchesFloor(safecrowd::domain::environmentHazardFloorId(layout_, hazard), currentFloorId_)) {
20582047
continue;
20592048
}
20602049

src/application/SimulationCanvasWidget.cpp

Lines changed: 6 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -72,45 +72,6 @@ bool connectionShouldBeBlocked(const safecrowd::domain::ConnectionBlockDraft& bl
7272
return false;
7373
}
7474

75-
bool hazardIsActive(const safecrowd::domain::EnvironmentHazardDraft& hazard, double timeSeconds) {
76-
const auto start = std::max(0.0, hazard.startSeconds);
77-
if (timeSeconds + 1e-9 < start) {
78-
return false;
79-
}
80-
if (hazard.endSeconds <= hazard.startSeconds) {
81-
return true;
82-
}
83-
const auto end = std::max(start, hazard.endSeconds);
84-
return timeSeconds <= end + 1e-9;
85-
}
86-
87-
double hazardRadiusMeters(safecrowd::domain::ScenarioElementSeverity severity) {
88-
switch (severity) {
89-
case safecrowd::domain::ScenarioElementSeverity::Low:
90-
return 2.0;
91-
case safecrowd::domain::ScenarioElementSeverity::High:
92-
return 5.0;
93-
case safecrowd::domain::ScenarioElementSeverity::Medium:
94-
default:
95-
return 3.5;
96-
}
97-
}
98-
99-
std::string hazardFloorId(
100-
const safecrowd::domain::FacilityLayout2D& layout,
101-
const safecrowd::domain::EnvironmentHazardDraft& hazard) {
102-
if (!hazard.floorId.empty()) {
103-
return hazard.floorId;
104-
}
105-
if (hazard.affectedZoneId.empty()) {
106-
return {};
107-
}
108-
const auto zoneIt = std::find_if(layout.zones.begin(), layout.zones.end(), [&](const auto& zone) {
109-
return zone.id == hazard.affectedZoneId;
110-
});
111-
return zoneIt == layout.zones.end() ? std::string{} : zoneIt->floorId;
112-
}
113-
11475
QString hazardKindLabel(safecrowd::domain::EnvironmentHazardKind kind) {
11576
switch (kind) {
11677
case safecrowd::domain::EnvironmentHazardKind::Smoke:
@@ -139,7 +100,7 @@ QString formatEnvironmentHazardTooltip(const safecrowd::domain::EnvironmentHazar
139100
text.append(QString("\n%1").arg(QString::fromStdString(hazard.name)));
140101
}
141102
const auto start = std::max(0.0, hazard.startSeconds);
142-
if (hazard.endSeconds <= hazard.startSeconds) {
103+
if (safecrowd::domain::environmentHazardHasOpenEndedSchedule(hazard)) {
143104
text.append(QString("\nActive: %1s ~ open").arg(start, 0, 'f', 1));
144105
} else {
145106
text.append(QString("\nActive: %1s ~ %2s")
@@ -295,10 +256,10 @@ std::optional<std::size_t> hoveredActiveEnvironmentHazardIndex(
295256
double closestDistanceSq = kHoverRadiusPixels * kHoverRadiusPixels;
296257
for (std::size_t index = 0; index < hazards.size(); ++index) {
297258
const auto& hazard = hazards[index];
298-
if (!hazardIsActive(hazard, elapsedSeconds)) {
259+
if (!safecrowd::domain::environmentHazardActiveAt(hazard, elapsedSeconds)) {
299260
continue;
300261
}
301-
if (!matchesFloor(hazardFloorId(layout, hazard), currentFloorId)) {
262+
if (!matchesFloor(safecrowd::domain::environmentHazardFloorId(layout, hazard), currentFloorId)) {
302263
continue;
303264
}
304265

@@ -960,15 +921,15 @@ void SimulationCanvasWidget::drawEnvironmentHazardOverlay(QPainter& painter, con
960921
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
961922

962923
for (const auto& hazard : environmentHazards_) {
963-
if (!hazardIsActive(hazard, elapsedSeconds)) {
924+
if (!safecrowd::domain::environmentHazardActiveAt(hazard, elapsedSeconds)) {
964925
continue;
965926
}
966-
if (!matchesFloor(hazardFloorId(layout_, hazard), currentFloorId_)) {
927+
if (!matchesFloor(safecrowd::domain::environmentHazardFloorId(layout_, hazard), currentFloorId_)) {
967928
continue;
968929
}
969930

970931
const auto center = transform.map(hazard.position);
971-
const auto radiusMeters = hazardRadiusMeters(hazard.severity);
932+
const auto radiusMeters = safecrowd::domain::environmentHazardRuntimeProfile(hazard).radiusMeters;
972933
const auto radiusAnchor = transform.map({
973934
.x = hazard.position.x + radiusMeters,
974935
.y = hazard.position.y,

0 commit comments

Comments
 (0)