Skip to content

Commit 8083f06

Browse files
committed
Add result skip action for scenario runs
1 parent 622dace commit 8083f06

3 files changed

Lines changed: 124 additions & 6 deletions

File tree

src/application/ScenarioResultWidget.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,6 +1459,9 @@ void ScenarioResultWidget::rerunScenario() {
14591459
saveProjectHandler_,
14601460
openProjectHandler_,
14611461
backToLayoutReviewHandler_,
1462+
frame_,
1463+
risk_,
1464+
artifacts_,
14621465
this);
14631466

14641467
rootLayout->replaceWidget(shell_, runWidget);

src/application/ScenarioRunWidget.cpp

Lines changed: 101 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,35 @@ ScenarioRunWidget::ScenarioRunWidget(
181181
saveProjectHandler_(std::move(saveProjectHandler)),
182182
openProjectHandler_(std::move(openProjectHandler)),
183183
backToLayoutReviewHandler_(std::move(backToLayoutReviewHandler)) {
184+
setupUi();
185+
}
186+
187+
ScenarioRunWidget::ScenarioRunWidget(
188+
const QString& projectName,
189+
const safecrowd::domain::FacilityLayout2D& layout,
190+
const safecrowd::domain::ScenarioDraft& scenario,
191+
std::function<void()> saveProjectHandler,
192+
std::function<void()> openProjectHandler,
193+
std::function<void()> backToLayoutReviewHandler,
194+
safecrowd::domain::SimulationFrame cachedResultFrame,
195+
safecrowd::domain::ScenarioRiskSnapshot cachedResultRisk,
196+
safecrowd::domain::ScenarioResultArtifacts cachedResultArtifacts,
197+
QWidget* parent)
198+
: QWidget(parent),
199+
projectName_(projectName),
200+
layout_(layout),
201+
scenario_(scenario),
202+
runner_(layout_, scenario_),
203+
cachedResultFrame_(std::move(cachedResultFrame)),
204+
cachedResultRisk_(std::move(cachedResultRisk)),
205+
cachedResultArtifacts_(std::move(cachedResultArtifacts)),
206+
saveProjectHandler_(std::move(saveProjectHandler)),
207+
openProjectHandler_(std::move(openProjectHandler)),
208+
backToLayoutReviewHandler_(std::move(backToLayoutReviewHandler)) {
209+
setupUi();
210+
}
211+
212+
void ScenarioRunWidget::setupUi() {
184213
auto* rootLayout = new QVBoxLayout(this);
185214
rootLayout->setContentsMargins(0, 0, 0, 0);
186215
rootLayout->setSpacing(0);
@@ -275,6 +304,12 @@ QWidget* ScenarioRunWidget::createRunPanel() {
275304

276305
layout->addStretch(1);
277306

307+
skipResultButton_ = new QPushButton("Skip for Result", panel);
308+
skipResultButton_->setFont(ui::font(ui::FontRole::Body));
309+
skipResultButton_->setStyleSheet(ui::secondaryButtonStyleSheet());
310+
skipResultButton_->setEnabled(false);
311+
layout->addWidget(skipResultButton_);
312+
278313
resultButton_ = new QPushButton("View Results", panel);
279314
resultButton_->setFont(ui::font(ui::FontRole::Body));
280315
resultButton_->setStyleSheet(ui::primaryButtonStyleSheet());
@@ -287,6 +322,9 @@ QWidget* ScenarioRunWidget::createRunPanel() {
287322
connect(stopButton_, &QPushButton::clicked, this, [this]() {
288323
stopRun();
289324
});
325+
connect(skipResultButton_, &QPushButton::clicked, this, [this]() {
326+
runToCompletion();
327+
});
290328
connect(resultButton_, &QPushButton::clicked, this, [this]() {
291329
showResults();
292330
});
@@ -326,6 +364,12 @@ void ScenarioRunWidget::returnToAuthoring() {
326364
canvas_ = nullptr;
327365
}
328366

367+
bool ScenarioRunWidget::hasCachedResult() const noexcept {
368+
return cachedResultFrame_.has_value()
369+
&& cachedResultRisk_.has_value()
370+
&& cachedResultArtifacts_.has_value();
371+
}
372+
329373
void ScenarioRunWidget::refreshStatus() {
330374
const auto& frame = runner_.frame();
331375
if (scenarioLabel_ != nullptr) {
@@ -390,24 +434,75 @@ void ScenarioRunWidget::refreshStatus() {
390434
if (stopButton_ != nullptr) {
391435
stopButton_->setEnabled(frame.totalAgentCount > 0);
392436
}
437+
if (skipResultButton_ != nullptr) {
438+
skipResultButton_->setEnabled(frame.totalAgentCount > 0 && !frame.complete && !hasCachedResult());
439+
}
393440
if (resultButton_ != nullptr) {
394-
resultButton_->setEnabled(frame.complete && frame.totalAgentCount > 0);
441+
const auto cachedAgentCount = hasCachedResult() ? cachedResultFrame_->totalAgentCount : 0;
442+
resultButton_->setEnabled(
443+
(frame.complete && frame.totalAgentCount > 0)
444+
|| cachedAgentCount > 0);
445+
}
446+
}
447+
448+
bool ScenarioRunWidget::runToCompletion() {
449+
if (timer_ != nullptr) {
450+
timer_->stop();
451+
}
452+
453+
const auto remainingSeconds = std::max(0.0, runner_.timeLimitSeconds() - runner_.frame().elapsedSeconds);
454+
const auto maxSteps = static_cast<int>(std::ceil(remainingSeconds / kSimulationDeltaSeconds)) + 2;
455+
for (int step = 0; step < maxSteps && !runner_.complete(); ++step) {
456+
runner_.step(kSimulationDeltaSeconds);
457+
}
458+
459+
if (canvas_ != nullptr) {
460+
canvas_->setFrame(runner_.frame());
395461
}
462+
if (runner_.complete()) {
463+
storeResultCache(runner_);
464+
}
465+
refreshStatus();
466+
return runner_.complete();
467+
}
468+
469+
void ScenarioRunWidget::storeResultCache(const safecrowd::domain::ScenarioSimulationRunner& runner) {
470+
cachedResultFrame_ = runner.frame();
471+
cachedResultRisk_ = runner.resultRiskSnapshot();
472+
cachedResultArtifacts_ = runner.resultArtifacts();
396473
}
397474

398475
void ScenarioRunWidget::stopRun() {
399476
paused_ = true;
400477
runner_.reset(layout_, scenario_);
478+
cachedResultFrame_.reset();
479+
cachedResultRisk_.reset();
480+
cachedResultArtifacts_.reset();
401481
canvas_->setFrame(runner_.frame());
402482
refreshStatus();
403483
timer_->start();
404484
}
405485

406486
void ScenarioRunWidget::showResults() {
407-
const auto& frame = runner_.frame();
408-
if (frame.totalAgentCount == 0 || !frame.complete) {
487+
if (runner_.frame().totalAgentCount == 0 && !hasCachedResult()) {
409488
return;
410489
}
490+
491+
const auto* resultFrame = &runner_.frame();
492+
const auto* resultRisk = &runner_.resultRiskSnapshot();
493+
const auto* resultArtifacts = &runner_.resultArtifacts();
494+
if (!runner_.complete() && hasCachedResult()) {
495+
resultFrame = &*cachedResultFrame_;
496+
resultRisk = &*cachedResultRisk_;
497+
resultArtifacts = &*cachedResultArtifacts_;
498+
} else if (!runner_.complete()) {
499+
return;
500+
} else {
501+
resultFrame = &runner_.frame();
502+
resultRisk = &runner_.resultRiskSnapshot();
503+
resultArtifacts = &runner_.resultArtifacts();
504+
}
505+
411506
if (timer_ != nullptr) {
412507
timer_->stop();
413508
}
@@ -421,9 +516,9 @@ void ScenarioRunWidget::showResults() {
421516
projectName_,
422517
layout_,
423518
scenario_,
424-
runner_.frame(),
425-
runner_.resultRiskSnapshot(),
426-
runner_.resultArtifacts(),
519+
*resultFrame,
520+
*resultRisk,
521+
*resultArtifacts,
427522
[this]() {
428523
if (saveProjectHandler_) {
429524
saveProjectHandler_();

src/application/ScenarioRunWidget.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <functional>
4+
#include <optional>
45

56
#include <QString>
67
#include <QWidget>
@@ -29,13 +30,28 @@ class ScenarioRunWidget : public QWidget {
2930
std::function<void()> openProjectHandler,
3031
std::function<void()> backToLayoutReviewHandler,
3132
QWidget* parent = nullptr);
33+
explicit ScenarioRunWidget(
34+
const QString& projectName,
35+
const safecrowd::domain::FacilityLayout2D& layout,
36+
const safecrowd::domain::ScenarioDraft& scenario,
37+
std::function<void()> saveProjectHandler,
38+
std::function<void()> openProjectHandler,
39+
std::function<void()> backToLayoutReviewHandler,
40+
safecrowd::domain::SimulationFrame cachedResultFrame,
41+
safecrowd::domain::ScenarioRiskSnapshot cachedResultRisk,
42+
safecrowd::domain::ScenarioResultArtifacts cachedResultArtifacts,
43+
QWidget* parent = nullptr);
3244

3345
const safecrowd::domain::ScenarioDraft& scenario() const noexcept;
3446

3547
private:
3648
QWidget* createRunPanel();
3749
void returnToAuthoring();
50+
bool hasCachedResult() const noexcept;
3851
void refreshStatus();
52+
bool runToCompletion();
53+
void storeResultCache(const safecrowd::domain::ScenarioSimulationRunner& runner);
54+
void setupUi();
3955
void showResults();
4056
void stopRun();
4157
void togglePaused();
@@ -44,6 +60,9 @@ class ScenarioRunWidget : public QWidget {
4460
safecrowd::domain::FacilityLayout2D layout_{};
4561
safecrowd::domain::ScenarioDraft scenario_{};
4662
safecrowd::domain::ScenarioSimulationRunner runner_{};
63+
std::optional<safecrowd::domain::SimulationFrame> cachedResultFrame_{};
64+
std::optional<safecrowd::domain::ScenarioRiskSnapshot> cachedResultRisk_{};
65+
std::optional<safecrowd::domain::ScenarioResultArtifacts> cachedResultArtifacts_{};
4766
std::function<void()> saveProjectHandler_{};
4867
std::function<void()> openProjectHandler_{};
4968
std::function<void()> backToLayoutReviewHandler_{};
@@ -61,6 +80,7 @@ class ScenarioRunWidget : public QWidget {
6180
QLabel* bottleneckLabel_{nullptr};
6281
QPushButton* pauseButton_{nullptr};
6382
QPushButton* stopButton_{nullptr};
83+
QPushButton* skipResultButton_{nullptr};
6484
QPushButton* resultButton_{nullptr};
6585
bool paused_{false};
6686
};

0 commit comments

Comments
 (0)