@@ -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+
329373void 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
398475void 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
406486void 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_ ();
0 commit comments