Skip to content

Commit

Permalink
Added not finished air breaks
Browse files Browse the repository at this point in the history
  • Loading branch information
jirkapok committed Sep 11, 2024
1 parent eab0fc6 commit c24bea9
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 12 deletions.
1 change: 1 addition & 0 deletions doc/links.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Following list of external sources was used to develop this application and can
* <https://decodoppler.wordpress.com/2012/08/02/air-breaks-what-are-they-and-do-people-take-them-for-the-wrong-reason/>
* <https://www.diverite.com/uncategorized/oxygen-toxicity-and-ccr-rebreather-diving/>
* <https://www.diverite.com/articles/oxygen-toxicity-signs-and-symptoms/>
* <https://www.diverite.com/uncategorized/oxygen-toxicity-and-ccr-rebreather-diving/>
* Diverite and decodopler: 20min./5 min.
* Gas blender
* https://github.com/atdotde/realblender
Expand Down
4 changes: 2 additions & 2 deletions doc/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Following list of features and improvements ordered by priority is under develop

## Improvements / Features

* TRIMIX support
* Add air breaks
* Gas blender:
* Add use case to identify mix when adding only top mix without adding he or oxygen
* Fix PWA issues https://www.pwabuilder.com/
Expand All @@ -34,8 +36,6 @@ Following list of features and improvements ordered by priority is under develop
* [Z factor](https://www.divegearexpress.com/library/articles/calculating-scuba-cylinder-capacities)
* <https://youtu.be/OI4ZzqJLQjw>
* Add undo/redo to all pages
* TRIMIX support
* Add air breaks
* Add CCR support
* Add localizations
* Add calculation trainings
Expand Down
31 changes: 25 additions & 6 deletions projects/scuba-physics/src/lib/AlgorithmContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Segment, Segments } from './Segments';
import { Options } from './Options';
import { DepthConverter } from './depth-converter';
import { Time } from './Time';
import { StandardGases } from './StandardGases';

export interface ContextMemento {
tissues: Tissue[];
Expand All @@ -20,9 +21,10 @@ export interface ContextMemento {
export class AlgorithmContext {
public tissues: Tissues;
public ceilings: Ceiling[] = [];
public currentGas: Gas;
/** in seconds */
public runTime = 0;
private _oxygenStarted = 0;
private _currentGas: Gas;
private gradients: GradientFactors;
private bestGasOptions: BestGasOptions;
private speeds: AscentSpeeds;
Expand All @@ -39,7 +41,7 @@ export class AlgorithmContext {
// this.gradients = new SimpleGradientFactors(depthConverter, options, this.tissues, this.segments);
this.gradients = new SubSurfaceGradientFactors(depthConverter, options, this.tissues);
const last = segments.last();
this.currentGas = last.gas;
this._currentGas = last.gas;

this.bestGasOptions = {
currentDepth: this.currentDepth,
Expand All @@ -54,6 +56,10 @@ export class AlgorithmContext {
this.gasSource = new OCGasSource(gases, options);
}

public get currentGas(): Gas {
return this._currentGas;
}

public get ascentSpeed(): number {
return this.speeds.ascent(this.currentDepth);
}
Expand All @@ -62,10 +68,6 @@ export class AlgorithmContext {
return this.segments.currentDepth;
}

public get ambientPressure(): number {
return this.depthConverter.toBar(this.currentDepth);
}

public get addSafetyStop(): boolean {
return this.levels.addSafetyStop(this.currentDepth, this.segments.maxDepth);
}
Expand All @@ -78,6 +80,23 @@ export class AlgorithmContext {
return this.segments.last().endDepth === 0;
}

public get runTimeOnOxygen(): number {
return this.runTime - this._oxygenStarted;
}

public get isBreathingOxygen(): boolean {
// Correct is to compare ppO2 >= 1.3, but it may happen also on deep stops, which we want to avoid
return this.currentGas.compositionEquals(StandardGases.oxygen);
}

public set currentGas(newValue: Gas) {
this._currentGas = newValue;

if (newValue.compositionEquals(StandardGases.oxygen)) {
this._oxygenStarted = this.runTime;
}
}

/** use this just before calculating ascent to be able calculate correct speeds */
public markAverageDepth(): void {
this.speeds.markAverageDepth(this.segments);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,5 @@ xdescribe('Buhlmann Algorithm - Air breaks', () => {
// behavior notes:
// * safety stop is also counted to the air break
// TODO add warning if unable to switch to air break if back gas not breathable at 6m
// TODO add test for small depths without deco, but with oxygen - shouldn't add air break
});
26 changes: 22 additions & 4 deletions projects/scuba-physics/src/lib/BuhlmannAlgorithm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@ export class BuhlmannAlgorithm {
while (nextStop >= 0 && !context.isAtSurface) {
// Next steps need to be in this order
this.tryGasSwitch(context); // multiple gas switches may happen before first deco stop
// TODO add air breaks - https://www.diverite.com/uncategorized/oxygen-toxicity-and-ccr-rebreather-diving/
this.stayAtDecoStop(context, nextStop);
this.stayAtSafetyStop(context);
this.ascentToNextStop(context, nextStop);
Expand Down Expand Up @@ -229,12 +228,31 @@ export class BuhlmannAlgorithm {
// the algorithm returns lowest value, so the last second where the deco isn't enough
// so we need to add one more second to be safe and adjust it to the required rounding
const stopDuration = interval.search(searchContext) + Time.oneSecond;
const rounded = Precision.ceilDistance(stopDuration, context.decoStopDuration);
this.swimDecoStop(context, memento, rounded);
// we don't restore last search iteration, we keep the deco stop segment
const roundedStopDuration = Precision.ceilDistance(stopDuration, context.decoStopDuration);

if(context.isBreathingOxygen) {
// TODO this.swimOxygenStop(context, roundedStopDuration);
this.swimDecoStop(context, memento, roundedStopDuration);
} else {
// we don't restore last search iteration, we keep the deco stop segment
this.swimDecoStop(context, memento, roundedStopDuration);
}
}
}

/** Includes air breaks */
private swimOxygenStop(context: AlgorithmContext, totalStopDuration: number): void {
// TODO apply settings for air breaks
// TODO air breaks prolong the deco, so we need to adjust the stop duration,
// but we want to avoid another stop estimation, because it is performance heavy
// easy solution is to use recursion and call the stayAtDecoStop once again
const remainingOxygenTime = totalStopDuration - context.runTimeOnOxygen;
const stopDuration = remainingOxygenTime > 0 ? remainingOxygenTime : 20;
const decoStop = context.addDecoStopSegment();
decoStop.duration = stopDuration;
this.swim(context, decoStop);
}

private swimDecoStop(context: AlgorithmContext, memento: ContextMemento, stopDuration: number): void {
context.restore(memento);
const decoStop = context.addDecoStopSegment();
Expand Down

0 comments on commit c24bea9

Please sign in to comment.