Actually compute variations in background

This reenables the computation of plan variations but now in a separate
thread. Once finieshed, a signal is sent to update the notes.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
This commit is contained in:
Robert C. Helling 2017-11-27 17:36:21 +01:00 committed by Dirk Hohndel
parent f159792b80
commit a9703628c4
6 changed files with 73 additions and 44 deletions

View file

@ -688,7 +688,6 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
int decostopcounter = 0; int decostopcounter = 0;
set_gf(diveplan->gflow, diveplan->gfhigh); set_gf(diveplan->gflow, diveplan->gfhigh);
lock_planner();
set_vpmb_conservatism(diveplan->vpmb_conservatism); set_vpmb_conservatism(diveplan->vpmb_conservatism);
if (!diveplan->surface_pressure) if (!diveplan->surface_pressure)
diveplan->surface_pressure = SURFACE_PRESSURE; diveplan->surface_pressure = SURFACE_PRESSURE;
@ -733,7 +732,6 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
transitiontime = depth / 75; /* this still needs to be made configurable */ transitiontime = depth / 75; /* this still needs to be made configurable */
plan_add_segment(diveplan, transitiontime, 0, current_cylinder, po2, false); plan_add_segment(diveplan, transitiontime, 0, current_cylinder, po2, false);
create_dive_from_plan(diveplan, dive, is_planner); create_dive_from_plan(diveplan, dive, is_planner);
unlock_planner();
return false; return false;
} }
@ -820,7 +818,6 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
free(stoplevels); free(stoplevels);
free(gaschanges); free(gaschanges);
unlock_planner();
return false; return false;
} }
@ -1084,7 +1081,6 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i
free(stoplevels); free(stoplevels);
free(gaschanges); free(gaschanges);
free(bottom_cache); free(bottom_cache);
unlock_planner();
return decodive; return decodive;
} }

View file

@ -55,7 +55,6 @@ slots:
void printDecoPlan(); void printDecoPlan();
void setSurfacePressure(int surface_pressure); void setSurfacePressure(int surface_pressure);
void setSalinity(int salinity); void setSalinity(int salinity);
private: private:
Ui::DivePlanner ui; Ui::DivePlanner ui;
QAbstractButton *replanButton; QAbstractButton *replanButton;
@ -103,6 +102,7 @@ public:
explicit PlannerDetails(QWidget *parent = 0); explicit PlannerDetails(QWidget *parent = 0);
QPushButton *printPlan() const { return ui.printPlan; } QPushButton *printPlan() const { return ui.printPlan; }
QTextEdit *divePlanOutput() const { return ui.divePlanOutput; } QTextEdit *divePlanOutput() const { return ui.divePlanOutput; }
QLabel *divePlannerOutputLabel() const { return ui.divePlanOutputLabel; }
private: private:
Ui::plannerDetails ui; Ui::plannerDetails ui;

View file

@ -212,6 +212,7 @@ MainWindow::MainWindow() : QMainWindow(),
connect(information(), SIGNAL(dateTimeChanged()), graphics(), SLOT(dateTimeChanged())); connect(information(), SIGNAL(dateTimeChanged()), graphics(), SLOT(dateTimeChanged()));
connect(DivePlannerPointsModel::instance(), SIGNAL(planCreated()), this, SLOT(planCreated())); connect(DivePlannerPointsModel::instance(), SIGNAL(planCreated()), this, SLOT(planCreated()));
connect(DivePlannerPointsModel::instance(), SIGNAL(planCanceled()), this, SLOT(planCanceled())); connect(DivePlannerPointsModel::instance(), SIGNAL(planCanceled()), this, SLOT(planCanceled()));
connect(DivePlannerPointsModel::instance(), SIGNAL(variationsComputed(QString)), this, SLOT(updateVariations(QString)));
connect(plannerDetails->printPlan(), SIGNAL(pressed()), divePlannerWidget(), SLOT(printDecoPlan())); connect(plannerDetails->printPlan(), SIGNAL(pressed()), divePlannerWidget(), SLOT(printDecoPlan()));
connect(this, SIGNAL(startDiveSiteEdit()), this, SLOT(on_actionDiveSiteEdit_triggered())); connect(this, SIGNAL(startDiveSiteEdit()), this, SLOT(on_actionDiveSiteEdit_triggered()));
connect(information(), SIGNAL(diveSiteChanged(struct dive_site *)), mapWidget, SLOT(centerOnDiveSite(struct dive_site *))); connect(information(), SIGNAL(diveSiteChanged(struct dive_site *)), mapWidget, SLOT(centerOnDiveSite(struct dive_site *)));
@ -445,7 +446,6 @@ void MainWindow::enableDisableCloudActions()
PlannerDetails *MainWindow::plannerDetails() const { PlannerDetails *MainWindow::plannerDetails() const {
return qobject_cast<PlannerDetails*>(applicationState["PlanDive"].bottomRight); return qobject_cast<PlannerDetails*>(applicationState["PlanDive"].bottomRight);
} }
PlannerSettingsWidget *MainWindow::divePlannerSettingsWidget() { PlannerSettingsWidget *MainWindow::divePlannerSettingsWidget() {
return qobject_cast<PlannerSettingsWidget*>(applicationState["PlanDive"].bottomLeft); return qobject_cast<PlannerSettingsWidget*>(applicationState["PlanDive"].bottomLeft);
} }
@ -899,6 +899,14 @@ void MainWindow::setPlanNotes()
plannerDetails()->divePlanOutput()->setHtml(displayed_dive.notes); plannerDetails()->divePlanOutput()->setHtml(displayed_dive.notes);
} }
void MainWindow::updateVariations(QString variations)
{
QString notes = QString(displayed_dive.notes);
free(displayed_dive.notes);
displayed_dive.notes = strdup(notes.replace("VARIATIONS", variations).toUtf8().data());
plannerDetails()->divePlanOutput()->setHtml(displayed_dive.notes);
}
void MainWindow::printPlan() void MainWindow::printPlan()
{ {
#ifndef NO_PRINTING #ifndef NO_PRINTING

View file

@ -15,6 +15,7 @@
#include <QProgressDialog> #include <QProgressDialog>
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "ui_plannerDetails.h"
#include "desktop-widgets/notificationwidget.h" #include "desktop-widgets/notificationwidget.h"
#include "core/windowtitleupdate.h" #include "core/windowtitleupdate.h"
#include "core/gpslocation.h" #include "core/gpslocation.h"
@ -186,6 +187,8 @@ slots:
void socialNetworkRequestUpload(); void socialNetworkRequestUpload();
void facebookLoggedIn(); void facebookLoggedIn();
void facebookLoggedOut(); void facebookLoggedOut();
void updateVariations(QString);
private: private:
Ui::MainWindow ui; Ui::MainWindow ui;

View file

@ -11,6 +11,7 @@
#include <QApplication> #include <QApplication>
#include <QTextDocument> #include <QTextDocument>
#include <QtConcurrent> #include <QtConcurrent>
#include <desktop-widgets/mainwindow.h>
#define UNIT_FACTOR ((prefs.units.length == units::METERS) ? 1000.0 / 60.0 : feet_to_mm(1.0) / 60.0) #define UNIT_FACTOR ((prefs.units.length == units::METERS) ? 1000.0 / 60.0 : feet_to_mm(1.0) / 60.0)
@ -922,8 +923,14 @@ void DivePlannerPointsModel::createTemporaryPlan()
if (recalcQ() && !diveplan_empty(&diveplan)) { if (recalcQ() && !diveplan_empty(&diveplan)) {
struct decostop stoptable[60]; struct decostop stoptable[60];
struct deco_state plan_deco_state; struct deco_state plan_deco_state;
struct diveplan *plan_copy;
plan(&plan_deco_state, &diveplan, &displayed_dive, DECOTIMESTEP, stoptable, &cache, isPlanner(), false); plan(&plan_deco_state, &diveplan, &displayed_dive, DECOTIMESTEP, stoptable, &cache, isPlanner(), false);
//QtConcurrent::run(this, &DivePlannerPointsModel::computeVariations, &ds_after_previous_dives); plan_copy = (struct diveplan *)malloc(sizeof(struct diveplan));
lock_planner();
cloneDiveplan(&diveplan, plan_copy);
unlock_planner();
QtConcurrent::run(this, &DivePlannerPointsModel::computeVariations, plan_copy, &plan_deco_state);
final_deco_state = plan_deco_state; final_deco_state = plan_deco_state;
emit calculatedPlanNotes(); emit calculatedPlanNotes();
} }
@ -950,14 +957,13 @@ void DivePlannerPointsModel::saveDuplicatePlan()
createPlan(true); createPlan(true);
} }
struct divedatapoint * DivePlannerPointsModel::cloneDiveplan(struct diveplan *plan_copy) struct divedatapoint * DivePlannerPointsModel::cloneDiveplan(struct diveplan *plan_src, struct diveplan *plan_copy)
{ {
divedatapoint *src, *last_segment; divedatapoint *src, *last_segment;
divedatapoint **dp; divedatapoint **dp;
lock_planner(); src = plan_src->dp;
src = diveplan.dp; *plan_copy = *plan_src;
*plan_copy = diveplan;
dp = &plan_copy->dp; dp = &plan_copy->dp;
while (src && (!src->time || src->entered)) { while (src && (!src->time || src->entered)) {
*dp = (struct divedatapoint *)malloc(sizeof(struct divedatapoint)); *dp = (struct divedatapoint *)malloc(sizeof(struct divedatapoint));
@ -970,7 +976,6 @@ struct divedatapoint * DivePlannerPointsModel::cloneDiveplan(struct diveplan *pl
last_segment = plan_copy->dp; last_segment = plan_copy->dp;
while (last_segment && last_segment->next && last_segment->next->next) while (last_segment && last_segment->next && last_segment->next->next)
last_segment = last_segment->next; last_segment = last_segment->next;
unlock_planner();
return last_segment; return last_segment;
} }
@ -1008,9 +1013,9 @@ int DivePlannerPointsModel::analyzeVariations(struct decostop *min, struct decos
return (leftsum + rightsum) / 2; return (leftsum + rightsum) / 2;
} }
void DivePlannerPointsModel::computeVariations(struct deco_state *ds) void DivePlannerPointsModel::computeVariations(struct diveplan *original_plan, struct deco_state *previos_ds)
{ {
return;
bool oldRecalc = setRecalc(false); bool oldRecalc = setRecalc(false);
struct dive *dive = alloc_dive(); struct dive *dive = alloc_dive();
copy_dive(&displayed_dive, dive); copy_dive(&displayed_dive, dive);
@ -1018,62 +1023,71 @@ void DivePlannerPointsModel::computeVariations(struct deco_state *ds)
struct deco_state *cache = NULL, *save = NULL; struct deco_state *cache = NULL, *save = NULL;
struct diveplan plan_copy; struct diveplan plan_copy;
struct divedatapoint *last_segment; struct divedatapoint *last_segment;
struct deco_state ds = *previos_ds;
if(!original_plan) {
setRecalc(oldRecalc);
return;
}
if(in_planner() && prefs.display_variations) { if(in_planner() && prefs.display_variations) {
int my_instance = ++instanceCounter; int my_instance = ++instanceCounter;
cache_deco_state(ds, &save); cache_deco_state(&ds, &save);
cloneDiveplan(&plan_copy);
if (my_instance != instanceCounter)
return;
plan(ds, &plan_copy, dive, 1, original, &cache, true, false);
free_dps(&plan_copy);
restore_deco_state(save, ds, false);
last_segment = cloneDiveplan(&plan_copy); last_segment = cloneDiveplan(original_plan, &plan_copy);
if (!last_segment) {
goto finish;
}
if (my_instance != instanceCounter)
goto finish;
plan(&ds, &plan_copy, dive, 1, original, &cache, true, false);
free_dps(&plan_copy);
restore_deco_state(save, &ds, false);
last_segment = cloneDiveplan(original_plan, &plan_copy);
last_segment->depth.mm += 1000; last_segment->depth.mm += 1000;
last_segment->next->depth.mm += 1000; last_segment->next->depth.mm += 1000;
if (my_instance != instanceCounter) if (my_instance != instanceCounter)
return; goto finish;
plan(ds, &plan_copy, dive, 1, deeper, &cache, true, false); plan(&ds, &plan_copy, dive, 1, deeper, &cache, true, false);
free_dps(&plan_copy); free_dps(&plan_copy);
restore_deco_state(save, ds, false); restore_deco_state(save, &ds, false);
last_segment = cloneDiveplan(&plan_copy); last_segment = cloneDiveplan(original_plan, &plan_copy);
last_segment->depth.mm -= 1000; last_segment->depth.mm -= 1000;
last_segment->next->depth.mm -= 1000; last_segment->next->depth.mm -= 1000;
if (my_instance != instanceCounter) if (my_instance != instanceCounter)
return; goto finish;
plan(ds, &plan_copy, dive, 1, shallower, &cache, true, false); plan(&ds, &plan_copy, dive, 1, shallower, &cache, true, false);
free_dps(&plan_copy); free_dps(&plan_copy);
restore_deco_state(save, ds, false); restore_deco_state(save, &ds, false);
last_segment = cloneDiveplan(&plan_copy); last_segment = cloneDiveplan(original_plan, &plan_copy);
last_segment->next->time += 60; last_segment->next->time += 60;
if (my_instance != instanceCounter) if (my_instance != instanceCounter)
return; goto finish;
plan(ds, &plan_copy, dive, 1, longer, &cache, true, false); plan(&ds, &plan_copy, dive, 1, longer, &cache, true, false);
free_dps(&plan_copy); free_dps(&plan_copy);
restore_deco_state(save, ds, false); restore_deco_state(save, &ds, false);
last_segment = cloneDiveplan(&plan_copy); last_segment = cloneDiveplan(original_plan, &plan_copy);
last_segment->next->time -= 60; last_segment->next->time -= 60;
if (my_instance != instanceCounter) if (my_instance != instanceCounter)
return; goto finish;
plan(ds, &plan_copy, dive, 1, shorter, &cache, true, false); plan(&ds, &plan_copy, dive, 1, shorter, &cache, true, false);
free_dps(&plan_copy); free_dps(&plan_copy);
restore_deco_state(save, ds, false); restore_deco_state(save, &ds, false);
finish:
free_dps(original_plan);
free(original_plan);
#ifdef SHOWSTOPVARIATIONS #ifdef SHOWSTOPVARIATIONS
printf("\n\n"); printf("\n\n");
#endif #endif
QString notes(displayed_dive.notes);
free(displayed_dive.notes);
char buf[200]; char buf[200];
sprintf(buf, "+ %d:%02d /m + %d:%02d /min", FRACTION(analyzeVariations(shallower, original, deeper, "m"),60), sprintf(buf, "+ %d:%02d /m + %d:%02d /min", FRACTION(analyzeVariations(shallower, original, deeper, "m"),60),
FRACTION(analyzeVariations(shorter, original, longer, "min"), 60)); FRACTION(analyzeVariations(shorter, original, longer, "min"), 60));
emit variationsComputed(QString(buf));
displayed_dive.notes = strdup(notes.replace("VARIATIONS", QString(buf)).toUtf8().data());
} }
setRecalc(oldRecalc); setRecalc(oldRecalc);
} }
@ -1090,6 +1104,13 @@ void DivePlannerPointsModel::createPlan(bool replanCopy)
//TODO: C-based function here? //TODO: C-based function here?
struct decostop stoptable[60]; struct decostop stoptable[60];
plan(&ds_after_previous_dives, &diveplan, &displayed_dive, DECOTIMESTEP, stoptable, &cache, isPlanner(), true); plan(&ds_after_previous_dives, &diveplan, &displayed_dive, DECOTIMESTEP, stoptable, &cache, isPlanner(), true);
struct diveplan *plan_copy;
plan_copy = (struct diveplan *)malloc(sizeof(struct diveplan));
lock_planner();
cloneDiveplan(&diveplan, plan_copy);
unlock_planner();
computeVariations(plan_copy, &ds_after_previous_dives);
free(cache); free(cache);
if (!current_dive || displayed_dive.id != current_dive->id) { if (!current_dive || displayed_dive.id != current_dive->id) {
// we were planning a new dive, not re-planning an existing on // we were planning a new dive, not re-planning an existing on

View file

@ -110,13 +110,14 @@ signals:
void startTimeChanged(QDateTime); void startTimeChanged(QDateTime);
void recreationChanged(bool); void recreationChanged(bool);
void calculatedPlanNotes(); void calculatedPlanNotes();
void variationsComputed(QString);
private: private:
explicit DivePlannerPointsModel(QObject *parent = 0); explicit DivePlannerPointsModel(QObject *parent = 0);
void createPlan(bool replanCopy); void createPlan(bool replanCopy);
struct diveplan diveplan; struct diveplan diveplan;
struct divedatapoint *cloneDiveplan(struct diveplan *plan_copy); struct divedatapoint *cloneDiveplan(struct diveplan *plan_src, struct diveplan *plan_copy);
void computeVariations(struct deco_state *ds); void computeVariations(struct diveplan *diveplan, struct deco_state *ds);
int analyzeVariations(struct decostop *min, struct decostop *mid, struct decostop *max, const char *unit); int analyzeVariations(struct decostop *min, struct decostop *mid, struct decostop *max, const char *unit);
Mode mode; Mode mode;
bool recalc; bool recalc;