mirror of
https://github.com/subsurface/subsurface.git
synced 2025-01-19 14:25:27 +00:00
Make planner work again
This partially reverts changes in commit 1b655d5c806b ("Correctly track gases when manually adding and then editing dives") as it turns out this did NOT help us correctly track gases (which is ironic, given the title of that commit). I didn't actually want to revert that commit as infrastructure has changed since then and this made the patches look even more incomprehensible. So we are back to tracking the "gas on which we arrive at this spot" in each dive plan node as this makes the rest of our planning so much easier - I had forgotten about the reasons why we did things this way when I made the above mentioned commit. Instead we now make sure that our available tanks are added the correct way, that such entries are ignored when planning and when drawing the editable profile, and that at the end it all gets assembled correctly. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
d72c69db7a
commit
ad4812c22e
3 changed files with 70 additions and 36 deletions
16
planner.c
16
planner.c
|
@ -233,7 +233,6 @@ struct dive *create_dive_from_plan(struct diveplan *diveplan, const char **error
|
||||||
int time = dp->time;
|
int time = dp->time;
|
||||||
int depth = dp->depth;
|
int depth = dp->depth;
|
||||||
|
|
||||||
#if 0 // the new planner doesn't use that any more
|
|
||||||
if (time == 0) {
|
if (time == 0) {
|
||||||
/* special entries that just inform the algorithm about
|
/* special entries that just inform the algorithm about
|
||||||
* additional gases that are available */
|
* additional gases that are available */
|
||||||
|
@ -242,7 +241,6 @@ struct dive *create_dive_from_plan(struct diveplan *diveplan, const char **error
|
||||||
dp = dp->next;
|
dp = dp->next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (!o2 && !he) {
|
if (!o2 && !he) {
|
||||||
o2 = oldo2;
|
o2 = oldo2;
|
||||||
he = oldhe;
|
he = oldhe;
|
||||||
|
@ -258,14 +256,14 @@ struct dive *create_dive_from_plan(struct diveplan *diveplan, const char **error
|
||||||
/* Create new gas, and gas change event if necessary;
|
/* Create new gas, and gas change event if necessary;
|
||||||
* Sadly, we inherited our gaschange event from libdivecomputer which only
|
* Sadly, we inherited our gaschange event from libdivecomputer which only
|
||||||
* support percentage values, so round the entries */
|
* support percentage values, so round the entries */
|
||||||
if (time == 0 || o2 != oldo2 || he != oldhe) {
|
if (o2 != oldo2 || he != oldhe) {
|
||||||
int plano2 = (o2 + 5) / 10 * 10;
|
int plano2 = (o2 + 5) / 10 * 10;
|
||||||
int planhe = (he + 5) / 10 * 10;
|
int planhe = (he + 5) / 10 * 10;
|
||||||
int value;
|
int value;
|
||||||
if (add_gas(dive, plano2, planhe) < 0)
|
if (add_gas(dive, plano2, planhe) < 0)
|
||||||
goto gas_error_exit;
|
goto gas_error_exit;
|
||||||
value = (plano2 / 10) | ((planhe / 10) << 16);
|
value = (plano2 / 10) | ((planhe / 10) << 16);
|
||||||
add_event(dc, time, 25, 0, value, "gaschange"); // SAMPLE_EVENT_GASCHANGE2
|
add_event(dc, lasttime, 25, 0, value, "gaschange"); // SAMPLE_EVENT_GASCHANGE2
|
||||||
oldo2 = o2; oldhe = he;
|
oldo2 = o2; oldhe = he;
|
||||||
}
|
}
|
||||||
/* Create sample */
|
/* Create sample */
|
||||||
|
@ -350,7 +348,7 @@ void add_to_end_of_diveplan(struct diveplan *diveplan, struct divedatapoint *dp)
|
||||||
lastdp = &(*lastdp)->next;
|
lastdp = &(*lastdp)->next;
|
||||||
}
|
}
|
||||||
*lastdp = dp;
|
*lastdp = dp;
|
||||||
if (ldp)
|
if (ldp && dp->time != 0)
|
||||||
dp->time += lasttime;
|
dp->time += lasttime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,9 +563,9 @@ void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep, b
|
||||||
int transitiontime, gi;
|
int transitiontime, gi;
|
||||||
unsigned int stopidx, depth, ceiling;
|
unsigned int stopidx, depth, ceiling;
|
||||||
double tissue_tolerance;
|
double tissue_tolerance;
|
||||||
struct gaschanges *gaschanges;
|
struct gaschanges *gaschanges = NULL;
|
||||||
int gaschangenr;
|
int gaschangenr;
|
||||||
unsigned int *stoplevels;
|
unsigned int *stoplevels = NULL;
|
||||||
|
|
||||||
set_gf(diveplan->gflow, diveplan->gfhigh);
|
set_gf(diveplan->gflow, diveplan->gfhigh);
|
||||||
if (!diveplan->surface_pressure)
|
if (!diveplan->surface_pressure)
|
||||||
|
@ -613,6 +611,8 @@ void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep, b
|
||||||
#endif
|
#endif
|
||||||
if (depth < ceiling) /* that's not good... */
|
if (depth < ceiling) /* that's not good... */
|
||||||
depth = ceiling;
|
depth = ceiling;
|
||||||
|
if (depth == 0 && ceiling == 0) /* we are done here */
|
||||||
|
goto done;
|
||||||
for (stopidx = 0; stopidx < sizeof(decostoplevels) / sizeof(int); stopidx++)
|
for (stopidx = 0; stopidx < sizeof(decostoplevels) / sizeof(int); stopidx++)
|
||||||
if (decostoplevels[stopidx] >= depth)
|
if (decostoplevels[stopidx] >= depth)
|
||||||
break;
|
break;
|
||||||
|
@ -687,6 +687,8 @@ void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep, b
|
||||||
stopidx--;
|
stopidx--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
#if DO_WE_WANT_THIS_IN_QT
|
#if DO_WE_WANT_THIS_IN_QT
|
||||||
add_plan_to_notes(diveplan, dive);
|
add_plan_to_notes(diveplan, dive);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -418,7 +418,7 @@ void DivePlannerGraphics::mouseDoubleClickEvent(QMouseEvent* event)
|
||||||
|
|
||||||
int minutes = rint(timeLine->valueAt(mappedPos));
|
int minutes = rint(timeLine->valueAt(mappedPos));
|
||||||
int milimeters = rint(depthLine->valueAt(mappedPos) / M_OR_FT(1,1)) * M_OR_FT(1,1);
|
int milimeters = rint(depthLine->valueAt(mappedPos) / M_OR_FT(1,1)) * M_OR_FT(1,1);
|
||||||
plannerModel->addStop(milimeters, minutes * 60, O2_IN_AIR, 0, 0);
|
plannerModel->addStop(milimeters, minutes * 60, -1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivePlannerPointsModel::createSimpleDive()
|
void DivePlannerPointsModel::createSimpleDive()
|
||||||
|
@ -511,16 +511,20 @@ void DivePlannerGraphics::drawProfile()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-position the user generated dive handlers
|
// Re-position the user generated dive handlers
|
||||||
|
int last = 0;
|
||||||
for (int i = 1; i < plannerModel->rowCount(); i++) {
|
for (int i = 1; i < plannerModel->rowCount(); i++) {
|
||||||
divedatapoint dp = plannerModel->at(i);
|
divedatapoint dp = plannerModel->at(i);
|
||||||
|
if (dp.time == 0) // those are the magic entries for tanks
|
||||||
|
continue;
|
||||||
DiveHandler *h = handles.at(i);
|
DiveHandler *h = handles.at(i);
|
||||||
h->setPos(timeLine->posAtValue(dp.time / 60), depthLine->posAtValue(dp.depth));
|
h->setPos(timeLine->posAtValue(dp.time / 60), depthLine->posAtValue(dp.depth));
|
||||||
QPointF p1 = handles[i-1]->pos();
|
QPointF p1 = handles[last]->pos();
|
||||||
QPointF p2 = handles[i]->pos();
|
QPointF p2 = handles[i]->pos();
|
||||||
QLineF line(p1, p2);
|
QLineF line(p1, p2);
|
||||||
QPointF pos = line.pointAt(0.5);
|
QPointF pos = line.pointAt(0.5);
|
||||||
gases[i]->setPos(pos);
|
gases[i]->setPos(pos);
|
||||||
gases[i]->setText(dpGasToStr(plannerModel->at(i-1)));
|
gases[i]->setText(dpGasToStr(plannerModel->at(i)));
|
||||||
|
last = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// (re-) create the profile with different colors for segments that were
|
// (re-) create the profile with different colors for segments that were
|
||||||
|
@ -532,6 +536,8 @@ void DivePlannerGraphics::drawProfile()
|
||||||
poly.append(QPointF(lastx, lasty));
|
poly.append(QPointF(lastx, lasty));
|
||||||
|
|
||||||
for (dp = diveplan.dp; dp != NULL; dp = dp->next) {
|
for (dp = diveplan.dp; dp != NULL; dp = dp->next) {
|
||||||
|
if (dp->time == 0) // magic entry for available tank
|
||||||
|
continue;
|
||||||
double xpos = timeLine->posAtValue(dp->time / 60.0);
|
double xpos = timeLine->posAtValue(dp->time / 60.0);
|
||||||
double ypos = depthLine->posAtValue(dp->depth);
|
double ypos = depthLine->posAtValue(dp->depth);
|
||||||
if (!dp->entered) {
|
if (!dp->entered) {
|
||||||
|
@ -944,10 +950,6 @@ DivePlannerWidget::DivePlannerWidget(QWidget* parent, Qt::WindowFlags f): QWidge
|
||||||
|
|
||||||
void DivePlannerPointsModel::addCylinder_clicked()
|
void DivePlannerPointsModel::addCylinder_clicked()
|
||||||
{
|
{
|
||||||
qDebug() << "add Cylinder clicked";
|
|
||||||
if (!stagingDive)
|
|
||||||
stagingDive = alloc_dive();
|
|
||||||
CylindersModel::instance()->setDive(stagingDive);
|
|
||||||
CylindersModel::instance()->add();
|
CylindersModel::instance()->add();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1009,12 +1011,7 @@ QVariant DivePlannerPointsModel::data(const QModelIndex& index, int role) const
|
||||||
case CCSETPOINT: return p.po2;
|
case CCSETPOINT: return p.po2;
|
||||||
case DEPTH: return rint(get_depth_units(p.depth, NULL, NULL));
|
case DEPTH: return rint(get_depth_units(p.depth, NULL, NULL));
|
||||||
case DURATION: return p.time / 60;
|
case DURATION: return p.time / 60;
|
||||||
case GAS:
|
case GAS: return dpGasToStr(p);
|
||||||
if (index.row() > 0) {
|
|
||||||
p = divepoints.at(index.row() - 1);
|
|
||||||
return dpGasToStr(p);
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
} else if (role == Qt::DecorationRole) {
|
} else if (role == Qt::DecorationRole) {
|
||||||
switch(index.column()) {
|
switch(index.column()) {
|
||||||
|
@ -1028,6 +1025,8 @@ QVariant DivePlannerPointsModel::data(const QModelIndex& index, int role) const
|
||||||
|
|
||||||
bool DivePlannerPointsModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
bool DivePlannerPointsModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||||
{
|
{
|
||||||
|
int o2 = 0;
|
||||||
|
int he = 0;
|
||||||
if(role == Qt::EditRole) {
|
if(role == Qt::EditRole) {
|
||||||
divedatapoint& p = divepoints[index.row()];
|
divedatapoint& p = divepoints[index.row()];
|
||||||
switch(index.column()) {
|
switch(index.column()) {
|
||||||
|
@ -1040,19 +1039,11 @@ bool DivePlannerPointsModel::setData(const QModelIndex& index, const QVariant& v
|
||||||
p.po2 = po2;
|
p.po2 = po2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GAS: {
|
case GAS:
|
||||||
if (index.row() == 0) {
|
|
||||||
qDebug() << "how can index.row be 0???";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
divedatapoint& pp = divepoints[index.row() - 1];
|
|
||||||
int o2 = 0;
|
|
||||||
int he = 0;
|
|
||||||
QByteArray gasv = value.toByteArray();
|
QByteArray gasv = value.toByteArray();
|
||||||
if (validate_gas(gasv.data(), &o2, &he)) {
|
if (validate_gas(gasv.data(), &o2, &he)) {
|
||||||
pp.o2 = o2;
|
p.o2 = o2;
|
||||||
pp.he = he;
|
p.he = he;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1143,10 +1134,38 @@ bool divePointsLessThan(const divedatapoint& p1, const divedatapoint& p2)
|
||||||
return p1.time <= p2.time;
|
return p1.time <= p2.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DivePlannerPointsModel::addGas(int o2, int he)
|
||||||
|
{
|
||||||
|
cylinder_t *cyl = stagingDive->cylinder;
|
||||||
|
if (is_air(o2, he))
|
||||||
|
o2 = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_CYLINDERS; i++) {
|
||||||
|
if (cylinder_nodata(cyl)) {
|
||||||
|
cyl->type.description = strdup("Cylinder for planning");
|
||||||
|
cyl->gasmix.o2.permille = o2;
|
||||||
|
cyl->gasmix.he.permille = he;
|
||||||
|
CylindersModel::instance()->setDive(stagingDive);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (cyl->gasmix.o2.permille == o2 && cyl->gasmix.he.permille == he)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
qDebug("too many gases");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int DivePlannerPointsModel::addStop(int milimeters, int minutes, int o2, int he, int ccpoint)
|
int DivePlannerPointsModel::addStop(int milimeters, int minutes, int o2, int he, int ccpoint)
|
||||||
{
|
{
|
||||||
int row = divepoints.count();
|
int row = divepoints.count();
|
||||||
|
if (o2 != -1)
|
||||||
|
if (!addGas(o2, he))
|
||||||
|
qDebug("addGas failed"); // FIXME add error propagation
|
||||||
if(row == 0) {
|
if(row == 0) {
|
||||||
|
if (o2 == -1) {
|
||||||
|
o2 = O2_IN_AIR;
|
||||||
|
(void)addGas(o2, 0); // I know this is the first gas - won't fail
|
||||||
|
}
|
||||||
beginInsertRows(QModelIndex(), row, row);
|
beginInsertRows(QModelIndex(), row, row);
|
||||||
divedatapoint point;
|
divedatapoint point;
|
||||||
point.depth = 0;
|
point.depth = 0;
|
||||||
|
@ -1249,6 +1268,10 @@ DivePlannerPointsModel::Mode DivePlannerPointsModel::currentMode() const
|
||||||
|
|
||||||
void DivePlannerPointsModel::clear()
|
void DivePlannerPointsModel::clear()
|
||||||
{
|
{
|
||||||
|
if (!stagingDive)
|
||||||
|
stagingDive = alloc_dive();
|
||||||
|
memset(stagingDive->cylinder, 0, MAX_CYLINDERS * sizeof(cylinder_t));
|
||||||
|
CylindersModel::instance()->setDive(stagingDive);
|
||||||
beginRemoveRows(QModelIndex(), 0, rowCount()-1);
|
beginRemoveRows(QModelIndex(), 0, rowCount()-1);
|
||||||
divepoints.clear();
|
divepoints.clear();
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
|
@ -1262,8 +1285,8 @@ void DivePlannerPointsModel::createTemporaryPlan()
|
||||||
// Get the user-input and calculate the dive info
|
// Get the user-input and calculate the dive info
|
||||||
// Not sure if this is the place to create the diveplan...
|
// Not sure if this is the place to create the diveplan...
|
||||||
// We just start with a surface node at time = 0
|
// We just start with a surface node at time = 0
|
||||||
struct divedatapoint *dp = NULL; // create_dp(0, 0, 209, 0, 0);
|
struct divedatapoint *dp = create_dp(0, 0, 209, 0, 0);
|
||||||
// dp->entered = TRUE;
|
dp->entered = TRUE;
|
||||||
diveplan.dp = dp;
|
diveplan.dp = dp;
|
||||||
int lastIndex = -1;
|
int lastIndex = -1;
|
||||||
for (int i = 0; i < rowCount(); i++) {
|
for (int i = 0; i < rowCount(); i++) {
|
||||||
|
@ -1272,12 +1295,20 @@ void DivePlannerPointsModel::createTemporaryPlan()
|
||||||
lastIndex = i;
|
lastIndex = i;
|
||||||
dp = plan_add_segment(&diveplan, deltaT, p.depth, p.o2, p.he, p.po2);
|
dp = plan_add_segment(&diveplan, deltaT, p.depth, p.o2, p.he, p.po2);
|
||||||
}
|
}
|
||||||
#if DEBUG_PLAN
|
|
||||||
dump_plan(&diveplan);
|
|
||||||
#endif
|
|
||||||
char *cache = NULL;
|
char *cache = NULL;
|
||||||
tempDive = NULL;
|
tempDive = NULL;
|
||||||
const char *errorString = NULL;
|
const char *errorString = NULL;
|
||||||
|
for (int i = 0; i < MAX_CYLINDERS; i++) {
|
||||||
|
cylinder_t *cyl = &stagingDive->cylinder[i];
|
||||||
|
if (cyl->depth.mm) {
|
||||||
|
dp = create_dp(0, cyl->depth.mm, cyl->gasmix.o2.permille, cyl->gasmix.he.permille, 0);
|
||||||
|
dp->next = diveplan.dp->next;
|
||||||
|
diveplan.dp->next = dp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if DEBUG_PLAN
|
||||||
|
dump_plan(&diveplan);
|
||||||
|
#endif
|
||||||
plan(&diveplan, &cache, &tempDive, isPlanner(), &errorString);
|
plan(&diveplan, &cache, &tempDive, isPlanner(), &errorString);
|
||||||
if (mode == ADD) {
|
if (mode == ADD) {
|
||||||
copy_samples(tempDive, current_dive);
|
copy_samples(tempDive, current_dive);
|
||||||
|
|
|
@ -65,6 +65,7 @@ signals:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit DivePlannerPointsModel(QObject* parent = 0);
|
explicit DivePlannerPointsModel(QObject* parent = 0);
|
||||||
|
bool addGas(int o2, int he);
|
||||||
struct diveplan diveplan;
|
struct diveplan diveplan;
|
||||||
Mode mode;
|
Mode mode;
|
||||||
QVector<divedatapoint> divepoints;
|
QVector<divedatapoint> divepoints;
|
||||||
|
|
Loading…
Add table
Reference in a new issue