void get_gas_string(const struct gasmix *gasmix, char *text, int len) { if (gasmix_is_air(gasmix)) snprintf(text, len, "%s", translate("gettextFromC", "air")); else if (get_he(gasmix) == 0) snprintf(text, len, translate("gettextFromC", "EAN%d"), (get_o2(gasmix) + 5) / 10); else snprintf(text, len, "(%d/%d)", (get_o2(gasmix) + 5) / 10, (get_he(gasmix) + 5) / 10); }
/* Quite crude reverse-blender-function, but it produces a approx result */ static void get_gas_parts(struct gasmix mix, volume_t vol, int o2_in_topup, volume_t *o2, volume_t *he) { volume_t air = {}; if (gasmix_is_air(&mix)) { o2->mliter = 0; he->mliter = 0; return; } air.mliter = rint(((double)vol.mliter * (1000 - get_he(&mix) - get_o2(&mix))) / (1000 - o2_in_topup)); he->mliter = rint(((double)vol.mliter * get_he(&mix)) / 1000.0); o2->mliter += vol.mliter - he->mliter - air.mliter; }
/* add period_in_seconds at the given pressure and gas to the deco calculation */ double add_segment(double pressure, const struct gasmix *gasmix, int period_in_seconds, int ccpo2, const struct dive *dive) { int ci; int fo2 = get_o2(gasmix), fhe = get_he(gasmix); double ppn2 = (pressure - WV_PRESSURE) * (1000 - fo2 - fhe) / 1000.0; double pphe = (pressure - WV_PRESSURE) * fhe / 1000.0; #if GF_LOW_AT_MAXDEPTH if (pressure > gf_low_pressure_this_dive) gf_low_pressure_this_dive = pressure; #endif if (ccpo2) { /* CC */ double rel_o2_amb, f_dilutent; rel_o2_amb = ccpo2 / pressure / 1000; f_dilutent = (1 - rel_o2_amb) / (1 - fo2 / 1000.0); if (f_dilutent < 0) { /* setpoint is higher than ambient pressure -> pure O2 */ ppn2 = 0.0; pphe = 0.0; } else if (f_dilutent < 1.0) { ppn2 *= f_dilutent; pphe *= f_dilutent; } } if (period_in_seconds == 1) { /* one second interval during dive */ for (ci = 0; ci < 16; ci++) { if (ppn2 - tissue_n2_sat[ci] > 0) tissue_n2_sat[ci] += buehlmann_config.satmult * (ppn2 - tissue_n2_sat[ci]) * buehlmann_N2_factor_expositon_one_second[ci]; else tissue_n2_sat[ci] += buehlmann_config.desatmult * (ppn2 - tissue_n2_sat[ci]) * buehlmann_N2_factor_expositon_one_second[ci]; if (pphe - tissue_he_sat[ci] > 0) tissue_he_sat[ci] += buehlmann_config.satmult * (pphe - tissue_he_sat[ci]) * buehlmann_He_factor_expositon_one_second[ci]; else tissue_he_sat[ci] += buehlmann_config.desatmult * (pphe - tissue_he_sat[ci]) * buehlmann_He_factor_expositon_one_second[ci]; } } else { /* all other durations */ for (ci = 0; ci < 16; ci++) { if (ppn2 - tissue_n2_sat[ci] > 0) tissue_n2_sat[ci] += buehlmann_config.satmult * (ppn2 - tissue_n2_sat[ci]) * (1 - pow(2.0,(- period_in_seconds / (buehlmann_N2_t_halflife[ci] * 60)))); else tissue_n2_sat[ci] += buehlmann_config.desatmult * (ppn2 - tissue_n2_sat[ci]) * (1 - pow(2.0,(- period_in_seconds / (buehlmann_N2_t_halflife[ci] * 60)))); if (pphe - tissue_he_sat[ci] > 0) tissue_he_sat[ci] += buehlmann_config.satmult * (pphe - tissue_he_sat[ci]) * (1 - pow(2.0,(- period_in_seconds / (buehlmann_He_t_halflife[ci] * 60)))); else tissue_he_sat[ci] += buehlmann_config.desatmult * (pphe - tissue_he_sat[ci]) * (1 - pow(2.0,(- period_in_seconds / (buehlmann_He_t_halflife[ci] * 60)))); } } return tissue_tolerance_calc(dive); }
QVector<QPair<int, int> > DivePlannerPointsModel::collectGases(struct dive *d) { QVector<QPair<int, int> > l; for (int i = 0; i < MAX_CYLINDERS; i++) { cylinder_t *cyl = &d->cylinder[i]; if (!cylinder_nodata(cyl)) l.push_back(qMakePair(get_o2(&cyl->gasmix), get_he(&cyl->gasmix))); } return l; }
static int get_he(afs_uint32 idx) { int i; char * p; if (get_h_hdr()) return 1; if (idx >= hdrs.h_hdr.records) return 1; if (he_cursor.idx == idx && he_cursor.hdr_valid && he_cursor.he_valid) return 0; he_cursor.hdr_valid = he_cursor.he_valid = 0; if (he_cache.cursor == NULL) { he_cache.cursor = (void **) calloc(hdrs.h_hdr.records, sizeof(void *)); assert(he_cache.cursor != NULL); } if (idx && he_cache.cursor[idx-1] == NULL) { for (i = 0; i < idx; i++) { if (he_cache.cursor[i] == NULL) { get_he(i); } } } if (!idx) { he_cursor.cursor = he_cursor.fh; } else if (he_cursor.cursor == he_cache.cursor[idx-1]) { p = (char *)he_cursor.cursor; p += he_cursor.hdr.len; he_cursor.cursor = (void *)p; } else { he_cursor.cursor = he_cache.cursor[idx-1]; if (get_he_hdr()) return 1; p = (char *)he_cursor.cursor; p += he_cursor.hdr.len; he_cursor.cursor = (void *)p; } he_cursor.idx = idx; he_cache.cursor[idx] = he_cursor.cursor; if (get_he_hdr()) return 1; if (get_he_entry()) return 1; return 0; }
static void dump_he(afs_uint32 idx) { if (get_he(idx)) { fprintf(stderr, "error getting he %d\n", idx); return; } DPFOFF(he_cursor.cursor); dump_he_hdr(); dump_he_entry(); dump_he_interfaces(); dump_he_hcps(); }
/* * If the event has an explicit cylinder index, * we return that. If it doesn't, we return the best * match based on the gasmix. * * Some dive computers give cylinder indexes, some * give just the gas mix. */ int get_cylinder_index(struct dive *dive, struct event *ev) { int i; int best = 0, score = INT_MAX; int target_o2, target_he; struct gasmix *g; if (ev->gas.index >= 0) return ev->gas.index; g = get_gasmix_from_event(ev); target_o2 = get_o2(g); target_he = get_he(g); /* * Try to find a cylinder that best matches the target gas * mix. */ for (i = 0; i < MAX_CYLINDERS; i++) { cylinder_t *cyl = dive->cylinder + i; int delta_o2, delta_he, distance; if (cylinder_nodata(cyl)) continue; delta_o2 = get_o2(&cyl->gasmix) - target_o2; delta_he = get_he(&cyl->gasmix) - target_he; distance = delta_o2 * delta_o2; distance += delta_he * delta_he; if (distance >= score) continue; score = distance; best = i; } return best; }
void ProfileGraphicsView::plot_cylinder_pressure_text() { int i; int mbar, cyl; int seen_cyl[MAX_CYLINDERS] = { FALSE, }; int last_pressure[MAX_CYLINDERS] = { 0, }; int last_time[MAX_CYLINDERS] = { 0, }; struct plot_data *entry; struct plot_info *pi = &gc.pi; if (!get_cylinder_pressure_range(&gc)) return; cyl = -1; for (i = 0; i < pi->nr; i++) { entry = pi->entry + i; mbar = GET_PRESSURE(entry); if (!mbar) continue; if (cyl != entry->cylinderindex) { cyl = entry->cylinderindex; if (!seen_cyl[cyl]) { plot_pressure_value(mbar, entry->sec, LEFT, BOTTOM); plot_gas_value(mbar, entry->sec, LEFT, TOP, get_o2(&dive->cylinder[cyl].gasmix), get_he(&dive->cylinder[cyl].gasmix)); seen_cyl[cyl] = TRUE; } } last_pressure[cyl] = mbar; last_time[cyl] = entry->sec; } for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) { if (last_time[cyl]) { plot_pressure_value(last_pressure[cyl], last_time[cyl], CENTER, TOP); } } }
bool is_gas_used(struct dive *dive, int idx) { cylinder_t *cyl = &dive->cylinder[idx]; int o2, he; struct divecomputer *dc; bool used = FALSE; bool firstGasExplicit = FALSE; if (cylinder_none(cyl)) return FALSE; o2 = get_o2(&cyl->gasmix); he = get_he(&cyl->gasmix); dc = &dive->dc; while (dc) { struct event *event = dc->events; while (event) { if (event->value) { if (event->name && !strcmp(event->name, "gaschange")) { unsigned int event_he = event->value >> 16; unsigned int event_o2 = event->value & 0xffff; if (event->time.seconds < 30) firstGasExplicit = TRUE; if (is_air(o2, he)) { if (is_air(event_o2 * 10, event_he * 10)) used = TRUE; } else if (he == event_he * 10 && o2 == event_o2 * 10) { used = TRUE; } } } if (used) break; event = event->next; } if (used) break; dc = dc->next; }
static int find_he_by_index(afs_uint32 idx) { int i; if (get_h_hdr()) { return 1; } for (i = 0; i < hdrs.h_hdr.records; i++) { if (get_he(i)) { fprintf(stderr, "error getting he %d\n", i); return 1; } if (he_cursor.he.index == idx) break; } if (i < hdrs.h_hdr.records) { dump_this_he(); return 0; } return 1; }
void plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool show_disclaimer) { struct sample *sample; int po2; int transitiontime, gi; int current_cylinder; unsigned int stopidx; int depth; double tissue_tolerance = 0.0; struct gaschanges *gaschanges = NULL; int gaschangenr; int *stoplevels = NULL; char *trial_cache = NULL; bool stopping = false; bool clear_to_ascend; int clock, previous_point_time; int avg_depth, bottom_time = 0; int last_ascend_rate; int best_first_ascend_cylinder; struct gasmix gas; int o2time = 0; int breaktime = -1; int breakcylinder; set_gf(diveplan->gflow, diveplan->gfhigh, prefs.gf_low_at_maxdepth); if (!diveplan->surface_pressure) diveplan->surface_pressure = SURFACE_PRESSURE; create_dive_from_plan(diveplan, is_planner); /* Let's start at the last 'sample', i.e. the last manually entered waypoint. */ sample = &displayed_dive.dc.sample[displayed_dive.dc.samples - 1]; get_gas_at_time(&displayed_dive, &displayed_dive.dc, sample->time, &gas); po2 = displayed_dive.dc.sample[displayed_dive.dc.samples - 1].po2.mbar; if ((current_cylinder = get_gasidx(&displayed_dive, &gas)) == -1) { report_error(translate("gettextFromC", "Can't find gas %s"), gasname(&gas)); current_cylinder = 0; } depth = displayed_dive.dc.sample[displayed_dive.dc.samples - 1].depth.mm; avg_depth = average_depth(diveplan); last_ascend_rate = ascend_velocity(depth, avg_depth, bottom_time); /* if all we wanted was the dive just get us back to the surface */ if (!is_planner) { transitiontime = depth / 75; /* this still needs to be made configurable */ plan_add_segment(diveplan, transitiontime, 0, gas, po2, false); create_dive_from_plan(diveplan, is_planner); return; } tissue_tolerance = tissue_at_end(&displayed_dive, cached_datap); #if DEBUG_PLAN & 4 printf("gas %s\n", gasname(&gas)); printf("depth %5.2lfm \n", depth / 1000.0); #endif best_first_ascend_cylinder = current_cylinder; /* Find the gases available for deco */ gaschanges = analyze_gaslist(diveplan, &gaschangenr, depth, &best_first_ascend_cylinder); /* Find the first potential decostopdepth above current depth */ for (stopidx = 0; stopidx < sizeof(decostoplevels) / sizeof(int); stopidx++) if (decostoplevels[stopidx] >= depth) break; if (stopidx > 0) stopidx--; /* Stoplevels are either depths of gas changes or potential deco stop depths. */ stoplevels = sort_stops(decostoplevels, stopidx + 1, gaschanges, gaschangenr); stopidx += gaschangenr; /* Keep time during the ascend */ bottom_time = clock = previous_point_time = displayed_dive.dc.sample[displayed_dive.dc.samples - 1].time.seconds; gi = gaschangenr - 1; if (best_first_ascend_cylinder != current_cylinder) { stopping = true; current_cylinder = best_first_ascend_cylinder; gas = displayed_dive.cylinder[current_cylinder].gasmix; #if DEBUG_PLAN & 16 printf("switch to gas %d (%d/%d) @ %5.2lfm\n", best_first_ascend_cylinder, (get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[best_first_ascend_cylinder].depth / 1000.0); #endif } while (1) { /* We will break out when we hit the surface */ do { /* Ascend to next stop depth */ int deltad = ascend_velocity(depth, avg_depth, bottom_time) * TIMESTEP; if (ascend_velocity(depth, avg_depth, bottom_time) != last_ascend_rate) { plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; stopping = false; last_ascend_rate = ascend_velocity(depth, avg_depth, bottom_time); } if (depth - deltad < stoplevels[stopidx]) deltad = depth - stoplevels[stopidx]; tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0, &displayed_dive.cylinder[current_cylinder].gasmix, TIMESTEP, po2, &displayed_dive); clock += TIMESTEP; depth -= deltad; } while (depth > stoplevels[stopidx]); if (depth <= 0) break; /* We are at the surface */ if (gi >= 0 && stoplevels[stopidx] == gaschanges[gi].depth) { /* We have reached a gas change. * Record this in the dive plan */ plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; stopping = true; current_cylinder = gaschanges[gi].gasidx; gas = displayed_dive.cylinder[current_cylinder].gasmix; #if DEBUG_PLAN & 16 printf("switch to gas %d (%d/%d) @ %5.2lfm\n", gaschanges[gi].gasidx, (get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[gi].depth / 1000.0); #endif gi--; } --stopidx; /* Save the current state and try to ascend to the next stopdepth */ int trial_depth = depth; cache_deco_state(tissue_tolerance, &trial_cache); while (1) { /* Check if ascending to next stop is clear, go back and wait if we hit the ceiling on the way */ clear_to_ascend = true; while (trial_depth > stoplevels[stopidx]) { int deltad = ascend_velocity(trial_depth, avg_depth, bottom_time) * TIMESTEP; if (deltad > trial_depth) /* don't test against depth above surface */ deltad = trial_depth; tissue_tolerance = add_segment(depth_to_mbar(trial_depth, &displayed_dive) / 1000.0, &displayed_dive.cylinder[current_cylinder].gasmix, TIMESTEP, po2, &displayed_dive); if (deco_allowed_depth(tissue_tolerance, diveplan->surface_pressure / 1000.0, &displayed_dive, 1) > trial_depth - deltad) { /* We should have stopped */ clear_to_ascend = false; break; } trial_depth -= deltad; } restore_deco_state(trial_cache); if (clear_to_ascend) break; /* We did not hit the ceiling */ /* Add a minute of deco time and then try again */ if (!stopping) { /* The last segment was an ascend segment. * Add a waypoint for start of this deco stop */ plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; stopping = true; } tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0, &displayed_dive.cylinder[current_cylinder].gasmix, DECOTIMESTEP, po2, &displayed_dive); cache_deco_state(tissue_tolerance, &trial_cache); clock += DECOTIMESTEP; if (prefs.doo2breaks) { if (get_o2(&displayed_dive.cylinder[current_cylinder].gasmix) == 1000) { o2time += DECOTIMESTEP; if (o2time >= 12 * 60) { breaktime = 0; breakcylinder = current_cylinder; plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; current_cylinder = 0; gas = displayed_dive.cylinder[current_cylinder].gasmix; } } else { if (breaktime >= 0) { breaktime += DECOTIMESTEP; if (breaktime >= 6 * 60) { o2time = 0; plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; current_cylinder = breakcylinder; gas = displayed_dive.cylinder[current_cylinder].gasmix; breaktime = -1; } } } } trial_depth = depth; } if (stopping) { /* Next we will ascend again. Add a waypoint if we have spend deco time */ plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; stopping = false; } } /* We made it to the surface */ plan_add_segment(diveplan, clock - previous_point_time, 0, gas, po2, false); create_dive_from_plan(diveplan, is_planner); add_plan_to_notes(diveplan, &displayed_dive, show_disclaimer); free(stoplevels); free(gaschanges); }
void dump_plan(struct diveplan *diveplan) { struct divedatapoint *dp; struct tm tm; if (!diveplan) { printf("Diveplan NULL\n"); return; } utc_mkdate(diveplan->when, &tm); printf("\nDiveplan @ %04d-%02d-%02d %02d:%02d:%02d (surfpres %dmbar):\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, diveplan->surface_pressure); dp = diveplan->dp; while (dp) { printf("\t%3u:%02u: %dmm gas: %d o2 %d h2\n", FRACTION(dp->time, 60), dp->depth, get_o2(&dp->gasmix), get_he(&dp->gasmix)); dp = dp->next; } }
bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool show_disclaimer) { struct sample *sample; int po2; int transitiontime, gi; int current_cylinder; unsigned int stopidx; int depth; double tissue_tolerance = 0.0; struct gaschanges *gaschanges = NULL; int gaschangenr; unsigned int *stoplevels = NULL; bool stopping = false; bool clear_to_ascend; int clock, previous_point_time; int avg_depth, max_depth, bottom_time = 0; int last_ascend_rate; int best_first_ascend_cylinder; struct gasmix gas; int o2time = 0; int breaktime = -1; int breakcylinder = 0; int error = 0; bool decodive = false; set_gf(diveplan->gflow, diveplan->gfhigh, prefs.gf_low_at_maxdepth); if (!diveplan->surface_pressure) diveplan->surface_pressure = SURFACE_PRESSURE; create_dive_from_plan(diveplan, is_planner); if (prefs.verbatim_plan) plan_verbatim = true; if (prefs.display_runtime) plan_display_runtime = true; if (prefs.display_duration) plan_display_duration = true; if (prefs.display_transitions) plan_display_transitions = true; if (prefs.last_stop) decostoplevels[1] = 6000; /* Let's start at the last 'sample', i.e. the last manually entered waypoint. */ sample = &displayed_dive.dc.sample[displayed_dive.dc.samples - 1]; get_gas_at_time(&displayed_dive, &displayed_dive.dc, sample->time, &gas); po2 = sample->setpoint.mbar; if ((current_cylinder = get_gasidx(&displayed_dive, &gas)) == -1) { report_error(translate("gettextFromC", "Can't find gas %s"), gasname(&gas)); current_cylinder = 0; } depth = displayed_dive.dc.sample[displayed_dive.dc.samples - 1].depth.mm; average_max_depth(diveplan, &avg_depth, &max_depth); last_ascend_rate = ascent_velocity(depth, avg_depth, bottom_time); /* if all we wanted was the dive just get us back to the surface */ if (!is_planner) { transitiontime = depth / 75; /* this still needs to be made configurable */ plan_add_segment(diveplan, transitiontime, 0, gas, po2, false); create_dive_from_plan(diveplan, is_planner); return(false); } tissue_tolerance = tissue_at_end(&displayed_dive, cached_datap); #if DEBUG_PLAN & 4 printf("gas %s\n", gasname(&gas)); printf("depth %5.2lfm \n", depth / 1000.0); #endif best_first_ascend_cylinder = current_cylinder; /* Find the gases available for deco */ if (po2) { // Don't change gas in CCR mode gaschanges = NULL; gaschangenr = 0; } else { gaschanges = analyze_gaslist(diveplan, &gaschangenr, depth, &best_first_ascend_cylinder); } /* Find the first potential decostopdepth above current depth */ for (stopidx = 0; stopidx < sizeof(decostoplevels) / sizeof(int); stopidx++) if (decostoplevels[stopidx] >= depth) break; if (stopidx > 0) stopidx--; /* Stoplevels are either depths of gas changes or potential deco stop depths. */ stoplevels = sort_stops(decostoplevels, stopidx + 1, gaschanges, gaschangenr); stopidx += gaschangenr; /* Keep time during the ascend */ bottom_time = clock = previous_point_time = displayed_dive.dc.sample[displayed_dive.dc.samples - 1].time.seconds; gi = gaschangenr - 1; if(prefs.recreational_mode) { bool safety_stop = prefs.safetystop && max_depth >= 10000; track_ascent_gas(depth, &displayed_dive.cylinder[current_cylinder], avg_depth, bottom_time, safety_stop); // How long can we stay at the current depth and still directly ascent to the surface? while (trial_ascent(depth, 0, avg_depth, bottom_time, tissue_tolerance, &displayed_dive.cylinder[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0) && enough_gas(current_cylinder)) { tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0, &displayed_dive.cylinder[current_cylinder].gasmix, DECOTIMESTEP, po2, &displayed_dive, prefs.bottomsac); update_cylinder_pressure(&displayed_dive, depth, depth, DECOTIMESTEP, prefs.bottomsac, &displayed_dive.cylinder[current_cylinder], false); clock += DECOTIMESTEP; } clock -= DECOTIMESTEP; plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, true); previous_point_time = clock; do { /* Ascend to surface */ int deltad = ascent_velocity(depth, avg_depth, bottom_time) * TIMESTEP; if (ascent_velocity(depth, avg_depth, bottom_time) != last_ascend_rate) { plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; last_ascend_rate = ascent_velocity(depth, avg_depth, bottom_time); } if (depth - deltad < 0) deltad = depth; tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0, &displayed_dive.cylinder[current_cylinder].gasmix, TIMESTEP, po2, &displayed_dive, prefs.decosac); clock += TIMESTEP; depth -= deltad; if (depth <= 5000 && depth >= (5000 - deltad) && safety_stop) { plan_add_segment(diveplan, clock - previous_point_time, 5000, gas, po2, false); previous_point_time = clock; clock += 180; plan_add_segment(diveplan, clock - previous_point_time, 5000, gas, po2, false); previous_point_time = clock; safety_stop = false; } } while (depth > 0); plan_add_segment(diveplan, clock - previous_point_time, 0, gas, po2, false); create_dive_from_plan(diveplan, is_planner); add_plan_to_notes(diveplan, &displayed_dive, show_disclaimer, error); fixup_dc_duration(&displayed_dive.dc); free(stoplevels); free(gaschanges); return(false); } if (best_first_ascend_cylinder != current_cylinder) { stopping = true; current_cylinder = best_first_ascend_cylinder; gas = displayed_dive.cylinder[current_cylinder].gasmix; #if DEBUG_PLAN & 16 printf("switch to gas %d (%d/%d) @ %5.2lfm\n", best_first_ascend_cylinder, (get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[best_first_ascend_cylinder].depth / 1000.0); #endif } while (1) { /* We will break out when we hit the surface */ do { /* Ascend to next stop depth */ int deltad = ascent_velocity(depth, avg_depth, bottom_time) * TIMESTEP; if (ascent_velocity(depth, avg_depth, bottom_time) != last_ascend_rate) { plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; stopping = false; last_ascend_rate = ascent_velocity(depth, avg_depth, bottom_time); } if (depth - deltad < stoplevels[stopidx]) deltad = depth - stoplevels[stopidx]; tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0, &displayed_dive.cylinder[current_cylinder].gasmix, TIMESTEP, po2, &displayed_dive, prefs.decosac); clock += TIMESTEP; depth -= deltad; } while (depth > 0 && depth > stoplevels[stopidx]); if (depth <= 0) break; /* We are at the surface */ if (gi >= 0 && stoplevels[stopidx] == gaschanges[gi].depth) { /* We have reached a gas change. * Record this in the dive plan */ plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; stopping = true; /* Check we need to change cylinder. * We might not if the cylinder was chosen by the user */ if (current_cylinder != gaschanges[gi].gasidx) { current_cylinder = gaschanges[gi].gasidx; gas = displayed_dive.cylinder[current_cylinder].gasmix; #if DEBUG_PLAN & 16 printf("switch to gas %d (%d/%d) @ %5.2lfm\n", gaschanges[gi].gasidx, (get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[gi].depth / 1000.0); #endif /* Stop for the minimum duration to switch gas */ tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0, &displayed_dive.cylinder[current_cylinder].gasmix, prefs.min_switch_duration, po2, &displayed_dive, prefs.decosac); clock += prefs.min_switch_duration; } gi--; } --stopidx; /* Save the current state and try to ascend to the next stopdepth */ while (1) { /* Check if ascending to next stop is clear, go back and wait if we hit the ceiling on the way */ if (trial_ascent(depth, stoplevels[stopidx], avg_depth, bottom_time, tissue_tolerance, &displayed_dive.cylinder[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0)) break; /* We did not hit the ceiling */ /* Add a minute of deco time and then try again */ decodive = true; if (!stopping) { /* The last segment was an ascend segment. * Add a waypoint for start of this deco stop */ plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; stopping = true; } /* Deco stop should end when runtime is at a whole minute */ int this_decotimestep; this_decotimestep = DECOTIMESTEP - clock % DECOTIMESTEP; tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0, &displayed_dive.cylinder[current_cylinder].gasmix, this_decotimestep, po2, &displayed_dive, prefs.decosac); clock += this_decotimestep; /* Finish infinite deco */ if(clock >= 48 * 3600 && depth >= 6000) { error = LONGDECO; break; } if (prefs.doo2breaks) { if (get_o2(&displayed_dive.cylinder[current_cylinder].gasmix) == 1000) { o2time += DECOTIMESTEP; if (o2time >= 12 * 60) { breaktime = 0; breakcylinder = current_cylinder; plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; current_cylinder = 0; gas = displayed_dive.cylinder[current_cylinder].gasmix; } } else { if (breaktime >= 0) { breaktime += DECOTIMESTEP; if (breaktime >= 6 * 60) { o2time = 0; plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; current_cylinder = breakcylinder; gas = displayed_dive.cylinder[current_cylinder].gasmix; breaktime = -1; } } } } } if (stopping) { /* Next we will ascend again. Add a waypoint if we have spend deco time */ plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; stopping = false; } } /* We made it to the surface * Create the final dive, add the plan to the notes and fixup some internal * data that we need to be there when plotting the dive */ plan_add_segment(diveplan, clock - previous_point_time, 0, gas, po2, false); create_dive_from_plan(diveplan, is_planner); add_plan_to_notes(diveplan, &displayed_dive, show_disclaimer, error); fixup_dc_duration(&displayed_dive.dc); free(stoplevels); free(gaschanges); return decodive; }
QString gasToStr(struct gasmix gas) { uint o2 = (get_o2(&gas) + 5) / 10, he = (get_he(&gas) + 5) / 10; QString result = gasmix_is_air(&gas) ? QObject::tr("AIR") : he == 0 ? QString("EAN%1").arg(o2, 2, 10, QChar('0')) : QString("%1/%2").arg(o2).arg(he); return result; }
void DiveGasPressureItem::modelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) { // We don't have enougth data to calculate things, quit. if (!shouldCalculateStuff(topLeft, bottomRight)) return; int last_index = -1; QPolygonF boundingPoly; // This is the "Whole Item", but a pressure can be divided in N Polygons. polygons.clear(); for (int i = 0, count = dataModel->rowCount(); i < count; i++) { plot_data* entry = dataModel->data().entry + i; int mbar = GET_PRESSURE(entry); if (entry->cylinderindex != last_index) { polygons.append(QPolygonF()); // this is the polygon that will be actually drawned on screen. last_index = entry->cylinderindex; } if (!mbar) { continue; } QPointF point(hAxis->posAtValue(entry->sec), vAxis->posAtValue(mbar)); boundingPoly.push_back(point); // The BoundingRect polygons.last().push_back(point); // The polygon thta will be plotted. } setPolygon(boundingPoly); qDeleteAll(texts); texts.clear(); int mbar, cyl; int seen_cyl[MAX_CYLINDERS] = { false, }; int last_pressure[MAX_CYLINDERS] = { 0, }; int last_time[MAX_CYLINDERS] = { 0, }; struct plot_data *entry; struct dive *dive = getDiveById(dataModel->id()); Q_ASSERT(dive != NULL); cyl = -1; for (int i = 0, count = dataModel->rowCount(); i < count; i++) { entry = dataModel->data().entry + i; mbar = GET_PRESSURE(entry); if (!mbar) continue; if (cyl != entry->cylinderindex) { cyl = entry->cylinderindex; if (!seen_cyl[cyl]) { plot_pressure_value(mbar, entry->sec, Qt::AlignRight | Qt::AlignTop); plot_gas_value(mbar, entry->sec, Qt::AlignRight | Qt::AlignBottom, get_o2(&dive->cylinder[cyl].gasmix), get_he(&dive->cylinder[cyl].gasmix)); seen_cyl[cyl] = true; } } last_pressure[cyl] = mbar; last_time[cyl] = entry->sec; } for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) { if (last_time[cyl]) { plot_pressure_value(last_pressure[cyl], last_time[cyl], Qt::AlignLeft | Qt::AlignTop); } } }
bool plan(struct diveplan *diveplan, char **cached_datap, bool is_planner, bool show_disclaimer) { int bottom_depth; int bottom_gi; int bottom_stopidx; bool is_final_plan = true; int deco_time; int previous_deco_time; char *bottom_cache = NULL; struct sample *sample; int po2; int transitiontime, gi; int current_cylinder; unsigned int stopidx; int depth; double tissue_tolerance = 0.0; struct gaschanges *gaschanges = NULL; int gaschangenr; int *decostoplevels; int decostoplevelcount; unsigned int *stoplevels = NULL; int vpmb_first_stop; bool stopping = false; bool pendinggaschange = false; bool clear_to_ascend; int clock, previous_point_time; int avg_depth, max_depth, bottom_time = 0; int last_ascend_rate; int best_first_ascend_cylinder; struct gasmix gas, bottom_gas; int o2time = 0; int breaktime = -1; int breakcylinder = 0; int error = 0; bool decodive = false; set_gf(diveplan->gflow, diveplan->gfhigh, prefs.gf_low_at_maxdepth); if (!diveplan->surface_pressure) diveplan->surface_pressure = SURFACE_PRESSURE; create_dive_from_plan(diveplan, is_planner); // Do we want deco stop array in metres or feet? if (prefs.units.length == METERS ) { decostoplevels = decostoplevels_metric; decostoplevelcount = sizeof(decostoplevels_metric) / sizeof(int); } else { decostoplevels = decostoplevels_imperial; decostoplevelcount = sizeof(decostoplevels_imperial) / sizeof(int); } /* If the user has selected last stop to be at 6m/20', we need to get rid of the 3m/10' stop. * Otherwise reinstate the last stop 3m/10' stop. */ if (prefs.last_stop) *(decostoplevels + 1) = 0; else *(decostoplevels + 1) = M_OR_FT(3,10); /* Let's start at the last 'sample', i.e. the last manually entered waypoint. */ sample = &displayed_dive.dc.sample[displayed_dive.dc.samples - 1]; get_gas_at_time(&displayed_dive, &displayed_dive.dc, sample->time, &gas); po2 = sample->setpoint.mbar; if ((current_cylinder = get_gasidx(&displayed_dive, &gas)) == -1) { report_error(translate("gettextFromC", "Can't find gas %s"), gasname(&gas)); current_cylinder = 0; } depth = displayed_dive.dc.sample[displayed_dive.dc.samples - 1].depth.mm; average_max_depth(diveplan, &avg_depth, &max_depth); last_ascend_rate = ascent_velocity(depth, avg_depth, bottom_time); /* if all we wanted was the dive just get us back to the surface */ if (!is_planner) { transitiontime = depth / 75; /* this still needs to be made configurable */ plan_add_segment(diveplan, transitiontime, 0, gas, po2, false); create_dive_from_plan(diveplan, is_planner); return(false); } calc_crushing_pressure(depth_to_mbar(depth, &displayed_dive) / 1000.0); nuclear_regeneration(clock); clear_deco(displayed_dive.surface_pressure.mbar / 1000.0); vpmb_start_gradient(); previous_deco_time = 100000000; deco_time = 10000000; tissue_tolerance = tissue_at_end(&displayed_dive, cached_datap); displayed_dive.surface_pressure.mbar = diveplan->surface_pressure; #if DEBUG_PLAN & 4 printf("gas %s\n", gasname(&gas)); printf("depth %5.2lfm \n", depth / 1000.0); #endif best_first_ascend_cylinder = current_cylinder; /* Find the gases available for deco */ if (po2) { // Don't change gas in CCR mode gaschanges = NULL; gaschangenr = 0; } else { gaschanges = analyze_gaslist(diveplan, &gaschangenr, depth, &best_first_ascend_cylinder); } /* Find the first potential decostopdepth above current depth */ for (stopidx = 0; stopidx < decostoplevelcount; stopidx++) if (*(decostoplevels + stopidx) >= depth) break; if (stopidx > 0) stopidx--; /* Stoplevels are either depths of gas changes or potential deco stop depths. */ stoplevels = sort_stops(decostoplevels, stopidx + 1, gaschanges, gaschangenr); stopidx += gaschangenr; /* Keep time during the ascend */ bottom_time = clock = previous_point_time = displayed_dive.dc.sample[displayed_dive.dc.samples - 1].time.seconds; gi = gaschangenr - 1; if(prefs.deco_mode == RECREATIONAL) { bool safety_stop = prefs.safetystop && max_depth >= 10000; track_ascent_gas(depth, &displayed_dive.cylinder[current_cylinder], avg_depth, bottom_time, safety_stop); // How long can we stay at the current depth and still directly ascent to the surface? while (trial_ascent(depth, 0, avg_depth, bottom_time, tissue_tolerance, &displayed_dive.cylinder[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0) && enough_gas(current_cylinder)) { tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0, &displayed_dive.cylinder[current_cylinder].gasmix, DECOTIMESTEP, po2, &displayed_dive, prefs.bottomsac); update_cylinder_pressure(&displayed_dive, depth, depth, DECOTIMESTEP, prefs.bottomsac, &displayed_dive.cylinder[current_cylinder], false); clock += DECOTIMESTEP; } clock -= DECOTIMESTEP; plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, true); previous_point_time = clock; do { /* Ascend to surface */ int deltad = ascent_velocity(depth, avg_depth, bottom_time) * TIMESTEP; if (ascent_velocity(depth, avg_depth, bottom_time) != last_ascend_rate) { plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; last_ascend_rate = ascent_velocity(depth, avg_depth, bottom_time); } if (depth - deltad < 0) deltad = depth; tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0, &displayed_dive.cylinder[current_cylinder].gasmix, TIMESTEP, po2, &displayed_dive, prefs.decosac); clock += TIMESTEP; depth -= deltad; if (depth <= 5000 && depth >= (5000 - deltad) && safety_stop) { plan_add_segment(diveplan, clock - previous_point_time, 5000, gas, po2, false); previous_point_time = clock; clock += 180; plan_add_segment(diveplan, clock - previous_point_time, 5000, gas, po2, false); previous_point_time = clock; safety_stop = false; } } while (depth > 0); plan_add_segment(diveplan, clock - previous_point_time, 0, gas, po2, false); create_dive_from_plan(diveplan, is_planner); add_plan_to_notes(diveplan, &displayed_dive, show_disclaimer, error); fixup_dc_duration(&displayed_dive.dc); free(stoplevels); free(gaschanges); return(false); } if (best_first_ascend_cylinder != current_cylinder) { stopping = true; current_cylinder = best_first_ascend_cylinder; gas = displayed_dive.cylinder[current_cylinder].gasmix; #if DEBUG_PLAN & 16 printf("switch to gas %d (%d/%d) @ %5.2lfm\n", best_first_ascend_cylinder, (get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[best_first_ascend_cylinder].depth / 1000.0); #endif } // VPM-B or Buehlmann Deco nuclear_regeneration(clock); vpmb_start_gradient(); previous_deco_time = 100000000; deco_time = 10000000; cache_deco_state(tissue_tolerance, &bottom_cache); // Lets us make several iterations bottom_depth = depth; bottom_gi = gi; bottom_gas = gas; bottom_stopidx = stopidx; // Find first stop used for VPM-B Boyle's law compensation if (prefs.deco_mode == VPMB) { vpmb_first_stop = deco_allowed_depth(tissue_tolerance, diveplan->surface_pressure / 1000, &displayed_dive, 1); if (vpmb_first_stop > 0) { while (stoplevels[stopidx] > vpmb_first_stop) { stopidx--; } stopidx++; vpmb_first_stop = stoplevels[stopidx]; } first_stop_pressure.mbar = depth_to_mbar(vpmb_first_stop, &displayed_dive); } else { first_stop_pressure.mbar = 0; } //CVA do { is_final_plan = (prefs.deco_mode == BUEHLMANN) || (previous_deco_time - deco_time < 10); // CVA time converges if (deco_time != 10000000) vpmb_next_gradient(deco_time, diveplan->surface_pressure / 1000.0); previous_deco_time = deco_time; tissue_tolerance = restore_deco_state(bottom_cache); depth = bottom_depth; gi = bottom_gi; clock = previous_point_time = bottom_time; gas = bottom_gas; stopping = false; decodive = false; stopidx = bottom_stopidx; breaktime = -1; breakcylinder = 0; o2time = 0; last_ascend_rate = ascent_velocity(depth, avg_depth, bottom_time); if ((current_cylinder = get_gasidx(&displayed_dive, &gas)) == -1) { report_error(translate("gettextFromC", "Can't find gas %s"), gasname(&gas)); current_cylinder = 0; } while (1) { /* We will break out when we hit the surface */ do { /* Ascend to next stop depth */ int deltad = ascent_velocity(depth, avg_depth, bottom_time) * TIMESTEP; if (ascent_velocity(depth, avg_depth, bottom_time) != last_ascend_rate) { if (is_final_plan) plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; stopping = false; last_ascend_rate = ascent_velocity(depth, avg_depth, bottom_time); } if (depth - deltad < stoplevels[stopidx]) deltad = depth - stoplevels[stopidx]; tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0, &displayed_dive.cylinder[current_cylinder].gasmix, TIMESTEP, po2, &displayed_dive, prefs.decosac); clock += TIMESTEP; depth -= deltad; } while (depth > 0 && depth > stoplevels[stopidx]); if (depth <= 0) break; /* We are at the surface */ if (gi >= 0 && stoplevels[stopidx] <= gaschanges[gi].depth) { /* We have reached a gas change. * Record this in the dive plan */ if (is_final_plan) plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; stopping = true; // Boyles Law compensation boyles_law(depth_to_mbar(stoplevels[stopidx], &displayed_dive) / 1000.0); /* Check we need to change cylinder. * We might not if the cylinder was chosen by the user * or user has selected only to switch only at required stops. * If current gas is hypoxic, we want to switch asap */ if (current_cylinder != gaschanges[gi].gasidx) { if (!prefs.switch_at_req_stop || !trial_ascent(depth, stoplevels[stopidx - 1], avg_depth, bottom_time, tissue_tolerance, &displayed_dive.cylinder[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0) || get_o2(&displayed_dive.cylinder[current_cylinder].gasmix) < 160) { current_cylinder = gaschanges[gi].gasidx; gas = displayed_dive.cylinder[current_cylinder].gasmix; #if DEBUG_PLAN & 16 printf("switch to gas %d (%d/%d) @ %5.2lfm\n", gaschanges[gi].gasidx, (get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[gi].depth / 1000.0); #endif /* Stop for the minimum duration to switch gas */ tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0, &displayed_dive.cylinder[current_cylinder].gasmix, prefs.min_switch_duration, po2, &displayed_dive, prefs.decosac); clock += prefs.min_switch_duration; if (prefs.doo2breaks && get_o2(&displayed_dive.cylinder[current_cylinder].gasmix) == 1000) o2time += prefs.min_switch_duration; } else { /* The user has selected the option to switch gas only at required stops. * Remember that we are waiting to switch gas */ pendinggaschange = true; } } gi--; } --stopidx; /* Save the current state and try to ascend to the next stopdepth */ while (1) { /* Check if ascending to next stop is clear, go back and wait if we hit the ceiling on the way */ if (trial_ascent(depth, stoplevels[stopidx], avg_depth, bottom_time, tissue_tolerance, &displayed_dive.cylinder[current_cylinder].gasmix, po2, diveplan->surface_pressure / 1000.0)) break; /* We did not hit the ceiling */ /* Add a minute of deco time and then try again */ decodive = true; if (!stopping) { /* The last segment was an ascend segment. * Add a waypoint for start of this deco stop */ if (is_final_plan) plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; stopping = true; // Boyles Law compensation boyles_law(depth_to_mbar(stoplevels[stopidx], &displayed_dive) / 1000.0); } /* Are we waiting to switch gas? * Occurs when the user has selected the option to switch only at required stops */ if (pendinggaschange) { current_cylinder = gaschanges[gi + 1].gasidx; gas = displayed_dive.cylinder[current_cylinder].gasmix; #if DEBUG_PLAN & 16 printf("switch to gas %d (%d/%d) @ %5.2lfm\n", gaschanges[gi + 1].gasidx, (get_o2(&gas) + 5) / 10, (get_he(&gas) + 5) / 10, gaschanges[gi + 1].depth / 1000.0); #endif /* Stop for the minimum duration to switch gas */ tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0, &displayed_dive.cylinder[current_cylinder].gasmix, prefs.min_switch_duration, po2, &displayed_dive, prefs.decosac); clock += prefs.min_switch_duration; if (prefs.doo2breaks && get_o2(&displayed_dive.cylinder[current_cylinder].gasmix) == 1000) o2time += prefs.min_switch_duration; pendinggaschange = false; } /* Deco stop should end when runtime is at a whole minute */ int this_decotimestep; this_decotimestep = DECOTIMESTEP - clock % DECOTIMESTEP; tissue_tolerance = add_segment(depth_to_mbar(depth, &displayed_dive) / 1000.0, &displayed_dive.cylinder[current_cylinder].gasmix, this_decotimestep, po2, &displayed_dive, prefs.decosac); clock += this_decotimestep; /* Finish infinite deco */ if(clock >= 48 * 3600 && depth >= 6000) { error = LONGDECO; break; } if (prefs.doo2breaks) { /* The backgas breaks option limits time on oxygen to 12 minutes, followed by 6 minutes on * backgas (first defined gas). This could be customized if there were demand. */ if (get_o2(&displayed_dive.cylinder[current_cylinder].gasmix) == 1000) { o2time += DECOTIMESTEP; if (o2time >= 12 * 60) { breaktime = 0; breakcylinder = current_cylinder; if (is_final_plan) plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; current_cylinder = 0; gas = displayed_dive.cylinder[current_cylinder].gasmix; } } else { if (breaktime >= 0) { breaktime += DECOTIMESTEP; if (breaktime >= 6 * 60) { o2time = 0; if (is_final_plan) plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; current_cylinder = breakcylinder; gas = displayed_dive.cylinder[current_cylinder].gasmix; breaktime = -1; } } } } } if (stopping) { /* Next we will ascend again. Add a waypoint if we have spend deco time */ if (is_final_plan) plan_add_segment(diveplan, clock - previous_point_time, depth, gas, po2, false); previous_point_time = clock; stopping = false; } } deco_time = clock - bottom_time; } while (!is_final_plan); plan_add_segment(diveplan, clock - previous_point_time, 0, gas, po2, false); create_dive_from_plan(diveplan, is_planner); add_plan_to_notes(diveplan, &displayed_dive, show_disclaimer, error); fixup_dc_duration(&displayed_dive.dc); free(stoplevels); free(gaschanges); return decodive; }
void ProfileGraphicsView::plot_one_event(struct event *ev) { int i; struct plot_info *pi = &gc.pi; struct plot_data *entry; /* is plotting of this event disabled? */ if (ev->name) { for (i = 0; i < evn_used; i++) { if (! strcmp(ev->name, ev_namelist[i].ev_name)) { if (ev_namelist[i].plot_ev) break; else return; } } } if (ev->time.seconds < 30 && !strcmp(ev->name, "gaschange")) /* a gas change in the first 30 seconds is the way of some dive computers * to tell us the gas that is used; let's not plot a marker for that */ return; for (i = 0; i < pi->nr; i++) { entry = pi->entry + i; if (ev->time.seconds < entry->sec) break; } /* draw a little triangular marker and attach tooltip */ int x = SCALEXGC(ev->time.seconds); int y = SCALEYGC(entry->depth); EventItem *item = new EventItem(0, isGrayscale); item->setPos(x, y); scene()->addItem(item); /* we display the event on screen - so translate */ QString name = tr(ev->name); if (ev->value) { if (ev->name && name == "gaschange") { int he = get_he(&dive->cylinder[entry->cylinderindex].gasmix); int o2 = get_o2(&dive->cylinder[entry->cylinderindex].gasmix); name += ": "; name += (he) ? QString("%1/%2").arg((o2 + 5) / 10).arg((he + 5) / 10) : is_air(o2, he) ? name += tr("air") : QString(tr("EAN%1")).arg((o2 + 5) / 10); } else if (ev->name && !strcmp(ev->name, "SP change")) { name += QString(":%1").arg((double) ev->value / 1000); } else { name += QString(":%1").arg(ev->value); } } else if (ev->name && name == "SP change") { name += tr("Bailing out to OC"); } else { name += ev->flags == SAMPLE_FLAGS_BEGIN ? tr(" begin", "Starts with space!") : ev->flags == SAMPLE_FLAGS_END ? tr(" end", "Starts with space!") : ""; } //item->setToolTipController(toolTip); //item->addToolTip(name); item->setToolTip(name); }
/* we try to show the data from the currently selected divecomputer * right now for some values (e.g., surface pressure) we could fall back * to dive data, but for consistency we don't. */ static void show_single_dive_stats(struct dive *dive) { char buf[256]; double value; int decimals; const char *unit; int idx, offset, gas_used, mbar; struct dive *prev_dive; struct tm tm; struct divecomputer *dc; process_all_dives(dive, &prev_dive); if (!dive) return; dc = select_dc(&dive->dc); utc_mkdate(dive->when, &tm); snprintf(buf, sizeof(buf), /*++GETTEXT 80 chars: weekday, monthname, day, year, hour, min */ _("%1$s, %2$s %3$d, %4$d %5$2d:%6$02d"), weekday(tm.tm_wday), monthname(tm.tm_mon), tm.tm_mday, tm.tm_year + 1900, tm.tm_hour, tm.tm_min); set_label(single_w.date, buf); set_label(single_w.dive_time, _("%d min"), (dive->duration.seconds + 30) / 60); if (prev_dive) set_label(single_w.surf_intv, get_time_string(dive->when - (prev_dive->when + prev_dive->duration.seconds), 4)); else set_label(single_w.surf_intv, _("unknown")); value = get_depth_units(dc->maxdepth.mm, &decimals, &unit); set_label(single_w.max_depth, "%.*f %s", decimals, value, unit); value = get_depth_units(dc->meandepth.mm, &decimals, &unit); set_label(single_w.avg_depth, "%.*f %s", decimals, value, unit); set_label(single_w.viz, star_strings[dive->visibility]); if (dc->watertemp.mkelvin) { value = get_temp_units(dc->watertemp.mkelvin, &unit); set_label(single_w.water_temp, "%.1f %s", value, unit); } else { set_label(single_w.water_temp, ""); } if (dc->airtemp.mkelvin) { value = get_temp_units(dc->airtemp.mkelvin, &unit); set_label(single_w.air_temp, "%.1f %s", value, unit); } else { if (dive->airtemp.mkelvin) { value = get_temp_units(dive->airtemp.mkelvin, &unit); set_label(single_w.air_temp, "%.1f %s", value, unit); } else { set_label(single_w.air_temp, ""); } } mbar = dc->surface_pressure.mbar; /* it would be easy to get dive data here: * if (!mbar) * mbar = get_surface_pressure_in_mbar(dive, FALSE); */ if (mbar) { set_label(single_w.air_press, "%d mbar", mbar); } else { set_label(single_w.air_press, ""); } value = get_volume_units(dive->sac, &decimals, &unit); if (value > 0) set_label(single_w.sac, _("%.*f %s/min"), decimals, value, unit); else set_label(single_w.sac, ""); set_label(single_w.otu, "%d", dive->otu); offset = 0; gas_used = 0; buf[0] = '\0'; /* for the O2/He readings just create a list of them */ for (idx = 0; idx < MAX_CYLINDERS; idx++) { cylinder_t *cyl = &dive->cylinder[idx]; pressure_t start, end; start = cyl->start.mbar ? cyl->start : cyl->sample_start; end = cyl->end.mbar ?cyl->sample_end : cyl->sample_end; if (!cylinder_none(cyl)) { /* 0% O2 strangely means air, so 21% - I don't like that at all */ int o2 = get_o2(&cyl->gasmix); int he = get_he(&cyl->gasmix); if (offset > 0) { snprintf(buf+offset, 80-offset, ", "); offset += 2; } snprintf(buf+offset, 80-offset, "%d/%d", (o2 + 5) / 10, (he + 5) / 10); offset = strlen(buf); } /* and if we have size, start and end pressure, we can * calculate the total gas used */ if (start.mbar && end.mbar) gas_used += gas_volume(cyl, start) - gas_volume(cyl, end); } set_label(single_w.o2he, buf); if (gas_used) { value = get_volume_units(gas_used, &decimals, &unit); set_label(single_w.gas_used, "%.*f %s", decimals, value, unit); } else { set_label(single_w.gas_used, ""); } }