Skip to content

Commit

Permalink
Implemented usage of consumption options
Browse files Browse the repository at this point in the history
  • Loading branch information
jirkapok committed Aug 17, 2024
1 parent fd182c7 commit afe22d8
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 48 deletions.
13 changes: 10 additions & 3 deletions projects/planner/src/app/workers/planning.tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
Segments, Gases, ProfileEvents, DepthConverterFactory,
Consumption, Time, Diver, OtuCalculator, CnsCalculator,
DensityAtDepth, EventOptions, AlgorithmParams, BuhlmannAlgorithm,
RestingParameters, Segment, PlanFactory
RestingParameters, Segment, PlanFactory, ConsumptionOptions
} from 'scuba-physics';
import {
ProfileRequestDto, ProfileResultDto, ConsumptionRequestDto,
Expand Down Expand Up @@ -72,13 +72,20 @@ export class PlanningTasks {

const options = DtoSerialization.toOptions(task.options);
const plan = PlanningTasks.selectConsumptionPlan(segments, task.isComplex);
const consumptionOptions: ConsumptionOptions = {
diver: diver,
primaryTankReserve: Consumption.defaultPrimaryReserve,
stageTankReserve: Consumption.defaultStageReserve,
};


// Max bottom changes tank consumed bars, so we need it calculate before real profile consumption
const maxTime = consumption.calculateMaxBottomTime(plan, tanks, diver, options);
const maxTime = consumption.calculateMaxBottomTime(plan, tanks, consumptionOptions, options);

const emergencyAscent = PlanFactory.emergencyAscent(originProfile, options, tanks);
let timeToSurface = Segments.duration(emergencyAscent);
timeToSurface = Time.toMinutes(timeToSurface);
consumption.consumeFromTanks2(originProfile, emergencyAscent, tanks, diver);
consumption.consumeFromTanks2(originProfile, emergencyAscent, tanks, consumptionOptions);

return {
diveId: task.diveId,
Expand Down
60 changes: 32 additions & 28 deletions projects/scuba-physics/src/lib/consumption.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Diver } from './Diver';
import { DepthConverter } from './depth-converter';
import { Tank } from './Tanks';
import { Consumption } from './consumption';
import { Consumption, ConsumptionOptions } from './consumption';
import { Time } from './Time';
import { Segment, Segments } from './Segments';
import { OptionExtensions } from './Options.spec';
Expand All @@ -12,7 +12,11 @@ import { Precision } from './precision';
// TODO consumption test case: /?t=1-24-0-220-0.21-0.35,2-11.1-0-200-0.5-0&de=0-53-360-1,53-53-660-1,53-46-60-1,46-46-360-1,46-24-120-1,24-21-60-1&di=20&o=300,9,3,1,3,20,3,0.75,0.3,6,1.6,30,1.4,10,1,1,1,1,1&ao=1,0
// Ensure if it si valid: generates too high reserve for S80 = 200 b, twin = 120 b
describe('Consumption', () => {
const diver = new Diver(20);
const consumtionOptions: ConsumptionOptions = {
diver: new Diver(20),
primaryTankReserve: Consumption.defaultPrimaryReserve,
stageTankReserve: Consumption.defaultStageReserve
};
const consumption = new Consumption(DepthConverter.forFreshWater());
const options2 = OptionExtensions.createOptions(1, 1, 1.4, 1.6, Salinity.fresh);
options2.safetyStop = SafetyStop.never;
Expand All @@ -31,7 +35,7 @@ describe('Consumption', () => {
segments.add(30, tank.gas, Time.oneMinute * 0.5);
segments.addFlat(tank.gas, Time.oneMinute * 10.5);

const maxBottomTime = consumption.calculateMaxBottomTime(segments, tanks, diver, options);
const maxBottomTime = consumption.calculateMaxBottomTime(segments, tanks, consumtionOptions, options);
expect(maxBottomTime).toEqual(17);
});

Expand All @@ -44,7 +48,7 @@ describe('Consumption', () => {
segments.add(40, airTank.gas, Time.oneMinute * 2);
segments.addFlat(airTank.gas, Time.oneMinute);

const maxBottomTime = consumption.calculateMaxBottomTime(segments, tanks, diver, options);
const maxBottomTime = consumption.calculateMaxBottomTime(segments, tanks, consumtionOptions, options);
expect(maxBottomTime).toEqual(20);
});

Expand All @@ -57,7 +61,7 @@ describe('Consumption', () => {
segments.add(40, airTank.gas, Time.oneMinute * 2);
segments.addFlat(airTank.gas, Time.oneMinute);

const maxBottomTime = consumption.calculateMaxBottomTime(segments, tanks, diver, options);
const maxBottomTime = consumption.calculateMaxBottomTime(segments, tanks, consumtionOptions, options);
expect(maxBottomTime).toEqual(5);
});

Expand All @@ -69,7 +73,7 @@ describe('Consumption', () => {
segments.add(30, tank.gas, Time.oneMinute * 0.5);
segments.addFlat(tank.gas, Time.oneMinute * 23);

const maxBottomTime = consumption.calculateMaxBottomTime(segments, tanks, diver, options);
const maxBottomTime = consumption.calculateMaxBottomTime(segments, tanks, consumtionOptions, options);
expect(maxBottomTime).toEqual(0);
});

Expand All @@ -83,7 +87,7 @@ describe('Consumption', () => {
segments.addFlat(tank.gas, Time.oneMinute * 10);

const startTime = performance.now();
consumption.calculateMaxBottomTime(segments, tanks, diver, options);
consumption.calculateMaxBottomTime(segments, tanks, consumtionOptions, options);
const endTime = performance.now();
const methodDuration = Precision.round(endTime - startTime);

Expand All @@ -100,7 +104,7 @@ describe('Consumption', () => {
segments.addFlat(tank.gas, Time.oneMinute * 10);
segments.addFlat(tank.gas, Time.oneMinute * 10);

const maxBottomTime = consumption.calculateMaxBottomTime(segments, tanks, diver, options);
const maxBottomTime = consumption.calculateMaxBottomTime(segments, tanks, consumtionOptions, options);
expect(maxBottomTime).toEqual(50);
});

Expand All @@ -113,7 +117,7 @@ describe('Consumption', () => {
segments.addFlat(tank.gas, Time.oneMinute * 10);
segments.add(0, tank.gas, Time.oneMinute * 10);

const maxBottomTime = consumption.calculateMaxBottomTime(segments, tanks, diver, options);
const maxBottomTime = consumption.calculateMaxBottomTime(segments, tanks, consumtionOptions, options);
expect(maxBottomTime).toEqual(181);
});
});
Expand All @@ -132,7 +136,7 @@ describe('Consumption', () => {
const options3 = OptionExtensions.createOptions(1, 1, 1.4, 1.6, Salinity.fresh);
options3.safetyStop = SafetyStop.always;
options3.problemSolvingDuration = 2;
consumption.consumeFromTanks(segments, options3, tanks, diver);
consumption.consumeFromTanks(segments, options3, tanks, consumtionOptions);
return tank;
};

Expand Down Expand Up @@ -161,7 +165,7 @@ describe('Consumption', () => {
];

// (2b avg depth * 2 bar/min * 1 minutes) + (3b * 2 bar/min * 10 minutes) + (2b * 2 bar/min * 2 minutes)
consumption.consumeFromTanks(profile, options2, tanks, diver);
consumption.consumeFromTanks(profile, options2, tanks, consumtionOptions);
expect(tank.consumed).toEqual(72);
});
});
Expand All @@ -181,7 +185,7 @@ describe('Consumption', () => {
new Segment(20, 0, ean50Tank.gas, 1 * Time.oneMinute) // 2b * 2 bar/min * 1 minutes = 4b
];

consumption.consumeFromTanks(profile, options2, tanks, diver);
consumption.consumeFromTanks(profile, options2, tanks, consumtionOptions);

it('Both tanks are consumed', () => {
expect(airTank.consumed).toEqual(52);
Expand All @@ -208,7 +212,7 @@ describe('Consumption', () => {
new Segment(20, 0, ean50Tank.gas, 1 * Time.oneMinute) // 2b * 2 bar/min * 1 minutes = 4b
];

consumption.consumeFromTanks(profile, options2, tanks, diver);
consumption.consumeFromTanks(profile, options2, tanks, consumtionOptions);

it('Consumption is updated from second tank only', () => {
expect(airTank.consumed).toEqual(0);
Expand All @@ -231,7 +235,7 @@ describe('Consumption', () => {
new Segment(20, 0, ean50Tank.gas, 1 * Time.oneMinute) // 2b * 2 bar/min * 1 minutes = 4b
];

consumption.consumeFromTanks(profile, options2, tanks, diver);
consumption.consumeFromTanks(profile, options2, tanks, consumtionOptions);

it('Consumption is updated from both air tanks', () => {
expect(airTank.consumed).toEqual(7);
Expand All @@ -251,7 +255,7 @@ describe('Consumption', () => {
new Segment(20, 0, airTank.gas, 2 * Time.oneMinute)
];

consumption.consumeFromTanks(profile, options2, tanks, diver);
consumption.consumeFromTanks(profile, options2, tanks, consumtionOptions);

it('Consumes only user defined tank', () => {
expect(airTank.consumed).toEqual(72);
Expand Down Expand Up @@ -280,7 +284,7 @@ describe('Consumption', () => {
new Segment(20, 0, airTank.gas, 2 * Time.oneMinute)
];

consumption.consumeFromTanks(profile, options2, tanks, diver);
consumption.consumeFromTanks(profile, options2, tanks, consumtionOptions);

it('No tank is updated', () => {
expect(airTank.consumed).toEqual(0);
Expand All @@ -307,7 +311,7 @@ describe('Consumption', () => {
new Segment(20, 0, ean50Tank.gas, 10 * Time.oneMinute) // 2b * 4 bar/min * 10 minutes = 80b
];

consumption.consumeFromTanks(profile, options2, tanks, diver);
consumption.consumeFromTanks(profile, options2, tanks, consumtionOptions);

it('Reserve is updated from both EAN50 tanks', () => {
// ((4b * 2 * 1) + (3.5b * 1 min * 1 b/min.)) * 3
Expand Down Expand Up @@ -337,7 +341,7 @@ describe('Consumption', () => {
new Segment(20, 0, ean50Tank2.gas, 4 * Time.oneMinute), // 2 b * 2 bar/min * 4 minute = 16b
];

consumption.consumeFromTanks(profile, options2, tanks, diver);
consumption.consumeFromTanks(profile, options2, tanks, consumtionOptions);

it('Gas is Consumed from required tank', () => {
expect(airTank.consumed).toEqual(60); // user defined by swim segment
Expand Down Expand Up @@ -370,7 +374,7 @@ describe('Consumption', () => {
new Segment(20, 0, airTank.gas, 4 * Time.oneMinute), // 2 b * 1 bar/min * 4 minute = 8b
];

consumption.consumeFromTanks(profile, options2, tanks, diver);
consumption.consumeFromTanks(profile, options2, tanks, consumtionOptions);

it('Reserve is more than remaining', () => {
expect(airTank.reserve).toEqual(30); // ((3 * 2 * 1) + (2.5 * 2 * 1)) * 3
Expand All @@ -390,7 +394,7 @@ describe('Consumption', () => {
const ascent = new Segment(20, 0, airTank, 4 * Time.oneMinute); // 2 b * 1 bar/min * 4 minute = 8b

const profile = [descent, swim, ascent];
consumption.consumeFromTanks(profile, options3, tanks, diver);
consumption.consumeFromTanks(profile, options3, tanks, consumtionOptions);

it('Tank is updated as with calculated segments', () => {
expect(airTank.reserve).toEqual(42); // 3 min at 3 m + 2 min. solving
Expand All @@ -409,7 +413,7 @@ describe('Consumption', () => {
const segments = [first, second];
// 1.5 * 20 * 2 = 60

consumption.consumeFromTanks(segments, options2, tanks, diver);
consumption.consumeFromTanks(segments, options2, tanks, consumtionOptions);
expect(tank.consumed).toEqual(61); // because of pressure conversion
// emergency ascent: ((2 * 2 * 2) + (1.5 * 1 * 2)) * 3 = 33
expect(tank.reserve).toEqual(33);
Expand All @@ -429,7 +433,7 @@ describe('Consumption', () => {

// currently tank1 30/90, tank2 112/169 (reserve/remaining)
// should be tank1 129/90, tank2 94/169
consumption.consumeFromTanks(segments, options2, tanks, diver);
consumption.consumeFromTanks(segments, options2, tanks, consumtionOptions);
// ((5 * 2 * 1) + (3,3 * 10 * 1)) * 3
expect(tank1.reserve).toEqual(128);
// ((1,6 * 8 * 2 = 25,6) + (1,3 * 2 * 2 = 5,20)) * 3
Expand All @@ -453,7 +457,7 @@ describe('Consumption', () => {
];

// reserve - ascent from 6. segment = ((4 bar * 1 bar/min * 2 min) + (2.5 b * 1 bar/min * 3 min)) * 3
consumption.consumeFromTanks(profile, options2, tanks, diver);
consumption.consumeFromTanks(profile, options2, tanks, consumtionOptions);
expect(tank1.reserve).toEqual(47);
});

Expand All @@ -474,7 +478,7 @@ describe('Consumption', () => {
];

// reserve - ascent from 6. segment = ((3 b * 1 bar/min * 2 min) + (2 b * 1 bar/min * 2 min)) * 3
consumption.consumeFromTanks(profile, options2, tanks, diver);
consumption.consumeFromTanks(profile, options2, tanks, consumtionOptions);
expect(tank1.reserve).toEqual(30);
});

Expand All @@ -494,7 +498,7 @@ describe('Consumption', () => {

// reserve - ascent from 2. segment
// ((4 b * 2 min * 1 bar/min) + (2.5 b * 3 min * 1 bar/min)) * 3
consumption.consumeFromTanks(profile, options2, tanks, diver);
consumption.consumeFromTanks(profile, options2, tanks, consumtionOptions);
expect(tank1.reserve).toEqual(47);
});

Expand All @@ -519,7 +523,7 @@ describe('Consumption', () => {
const s5 = new Segment(6, 0, tank1.gas, Time.oneMinute * 2);
const profile = [s1, s2, s3, s4, s5];

consumption.consumeFromTanks(profile, options2, tanks, diver);
consumption.consumeFromTanks(profile, options2, tanks, consumtionOptions);
// custom ascent is calculated, since no used defined tank was used during ascent
// 40n 120s, 40-6 600s, 6-3 18s, 3-3 285, 3-0 18
expect(tank1.reserve).toEqual(149);
Expand All @@ -538,7 +542,7 @@ describe('Consumption', () => {
const s5 = new Segment(6, 0, tank2, Time.oneMinute * 2); // 1.3 * 2 * 2 = 5.2
const segments = [s1, s2, s3, s4, s5];

consumption.consumeFromTanks(segments, options2, tanks, diver);
consumption.consumeFromTanks(segments, options2, tanks, consumtionOptions);

it('counts the consumption', () => {
expect(tank1.consumed).toEqual(110);
Expand All @@ -565,7 +569,7 @@ describe('Consumption', () => {
const s3 = new Segment(5, 0, tank2, Time.oneMinute);
const segments = [s1, s2, s3];

consumption.consumeFromTanks(segments, options2, tanks, diver);
consumption.consumeFromTanks(segments, options2, tanks, consumtionOptions);

it('First tank', () => {
expect(tank1.reserve).toEqual(30);
Expand Down
Loading

0 comments on commit afe22d8

Please sign in to comment.