示例#1
0
        public ZH_L16(ZH_L16 other)
        {
            foreach (ZH_Compartment item in other.Compartments)
            {
                this.Compartments.Add(new ZH_Compartment(item));
            }

            this.ActiveGas = other.ActiveGas;
        }
示例#2
0
        public void ZH_L16_AscendDecsendTest_NoActiveGas_ThrowException()
        {
            ZH_L16 target = new ZH_L16();

            double start = 1;
            double finish = 1;
            double rate = 1;
            Assert.Throws<ArgumentException>(() => target.AscendDecsend(start, finish, rate));
        }
示例#3
0
 public void ZH_L16_ChangeGas()
 {
     Gas gas = new Gas(0.21, 0.79, 0.0);
     ZH_L16 target = new ZH_L16();
     target.ActiveGas = gas;
     Gas newGas = new Gas(0.3, 0.7, 0.0);
     target.ActiveGas = newGas;
     Assert.Equal(newGas, target.ActiveGas);
 }
示例#4
0
        public void ZH_L16_AscendDecsendTest_NegativeFinishDepth_ThrowException()
        {
            Gas gas = new Gas(0.11, 0.79, 0.1);
            ZH_L16 target = new ZH_L16();
            target.ActiveGas = gas;

            double start = 1;
            double finish = -1;
            double rate = 1;
            Assert.Throws<ArgumentException>(() => target.AscendDecsend(start, finish, rate));
        }
示例#5
0
        private TimeSpan GotoDecoDepth(ZH_L16 algorithm, double currentDepth, double finalDepth, int runTime,
            ref Collection<DiveSegment> diveTable, out double stopDepth)
        {
            double minDepthAscent = algorithm.MinDepthAscent(CalcGradient(firstDecoDepth, currentDepth, pref));
            double decoDepth = GetDecoDepth(minDepthAscent, pref);

            if (decoDepth >= currentDepth)
            {
                stopDepth = decoDepth;
                return new TimeSpan();
            }

            Logger.Trace("GotoDecoDepth => start deco depth:" + decoDepth);
            algorithm.AscendDecsend(currentDepth, decoDepth, pref.AscRate);
            stopDepth = ContinueAscend(algorithm, finalDepth, decoDepth);

            TimeSpan timeSpentInGoingUp = CalcAscDescTime(currentDepth - stopDepth, pref.AscRate);
            int timespent = TimeHelper.MinutesRoundedUp(timeSpentInGoingUp);

            // Round to complete minute
            double diffTime = Math.Abs(timeSpentInGoingUp.TotalMinutes - timespent);
            double diffDepth = CalcHalfWayDepth(currentDepth, stopDepth);
            if (Math.Abs(diffTime - 0) > 0.001)
            {
                var algorithm2 = new ZH_L16(algorithm);
                algorithm2.AddRunTimeInMinutes(diffTime, diffDepth);
                    // Try adding additional runtime to verify if we should go up even more.
                double newStopDepth = ContinueAscend(algorithm2, finalDepth, stopDepth);
                if (newStopDepth < stopDepth)
                {
                    ContinueAscend(algorithm, finalDepth, stopDepth);

                    timeSpentInGoingUp = CalcAscDescTime(currentDepth - newStopDepth, pref.AscRate);
                    timespent = TimeHelper.MinutesRoundedUp(timeSpentInGoingUp);

                    // Round to complete minute
                    diffTime = Math.Abs(timeSpentInGoingUp.TotalMinutes - timespent);
                    diffDepth = CalcHalfWayDepth(currentDepth, stopDepth);
                    if (Math.Abs(diffTime - 0) > 0.001)
                    {
                        algorithm.AddRunTimeInMinutes(diffTime, diffDepth);
                    }

                    stopDepth = newStopDepth;
                }
            }

            double cns = CentralNervousSystem.AscendDescend(algorithm.ActiveGas, currentDepth, stopDepth, Math.Abs(pref.AscRate));
            double otu = OxygenToxicityUnit.AscendDescend(algorithm.ActiveGas, currentDepth, stopDepth, Math.Abs(pref.AscRate));
            timeSpentInGoingUp = TimeSpan.FromMinutes(timespent);
            var seg = new DiveSegment(stopDepth, timeSpentInGoingUp, DiveState.Ascend, runTime, runTime + timespent,
                                      algorithm.ActiveGas, cns, otu);
            Logger.Trace("GotoDecoDepth => Segment:" + seg);
            diveTable.Add(seg);

            return timeSpentInGoingUp;
        }
示例#6
0
        private TimeSpan GoingUp(ZH_L16 algorithm, ref Collection<DiveSegment> divetable, int runTime, double depth, WayPoint waypoint)
        {
            var ascdescTime = new TimeSpan();

            double minDepthAscent = algorithm.MinDepthAscent(CalcGradient(firstDecoDepth, depth, pref));

            //// No deco needed
            if (minDepthAscent <= waypoint.Depth)
            {
                algorithm.AscendDecsend(depth, waypoint.Depth, pref.AscRate);
                ascdescTime = CalcAscDescTime(depth - waypoint.Depth, pref.AscRate);
                int timespent = TimeHelper.MinutesRoundedUp(ascdescTime);
                double cns = CentralNervousSystem.AscendDescend(algorithm.ActiveGas, depth, waypoint.Depth, Math.Abs(pref.AscRate));
                double otu = OxygenToxicityUnit.AscendDescend(algorithm.ActiveGas, depth, waypoint.Depth, Math.Abs(pref.AscRate));

                // Round to complete minute
                double diffTime = Math.Abs(ascdescTime.TotalMinutes - timespent);
                double diffDepth = CalcHalfWayDepth(depth, waypoint.Depth);
                algorithm.AddRunTimeInMinutes(diffTime, diffDepth);
                ascdescTime = TimeSpan.FromMinutes(timespent);
                cns += CentralNervousSystem.ConstantDepth(algorithm.ActiveGas, diffDepth, diffTime);
                otu += OxygenToxicityUnit.ConstantDepth(algorithm.ActiveGas, diffDepth, diffTime);

                var seg = new DiveSegment(waypoint.Depth, ascdescTime, DiveState.Ascend, runTime, runTime + timespent,
                                          algorithm.ActiveGas, cns, otu);
                Logger.Trace("Calc => Segment:" + seg);
                divetable.Add(seg);
            }
            else
            {
                ascdescTime = GotoDecoDepth(algorithm, depth, waypoint.Depth, runTime, ref divetable, out depth);
                runTime += TimeHelper.MinutesRoundedUp(ascdescTime);
                if (Math.Abs(depth - waypoint.Depth) > 0.001)
                {
                    TimeSpan decoTime = DoDeco(algorithm, depth, waypoint.Depth, runTime, ref divetable);
                    ascdescTime += decoTime;
                }
            }

            return ascdescTime;
        }
示例#7
0
        private TimeSpan GoingDown(ZH_L16 algorithm, ref Collection<DiveSegment> divetable, int runTime,
            double currentDepth, WayPoint waypoint)
        {
            algorithm.AscendDecsend(currentDepth, waypoint.Depth, pref.DescRate);
            TimeSpan ascdescTime = CalcAscDescTime(waypoint.Depth - currentDepth, pref.DescRate);
            int timespent = TimeHelper.MinutesRoundedUp(ascdescTime);
            double cns = CentralNervousSystem.AscendDescend(algorithm.ActiveGas, currentDepth, waypoint.Depth, Math.Abs(pref.DescRate));
            double otu = OxygenToxicityUnit.AscendDescend(algorithm.ActiveGas, currentDepth, waypoint.Depth, Math.Abs(pref.DescRate));

            // Round to complete minute
            double diffTime = Math.Abs(ascdescTime.TotalMinutes - timespent);
            double diffDepth = CalcHalfWayDepth(currentDepth, waypoint.Depth);
            if (Math.Abs(diffTime - 0) > 0.001)
            {
                algorithm.AddRunTimeInMinutes(diffTime, diffDepth);
                ascdescTime = TimeSpan.FromMinutes(timespent);
                cns += CentralNervousSystem.ConstantDepth(algorithm.ActiveGas, diffDepth, diffTime);
                otu += OxygenToxicityUnit.ConstantDepth(algorithm.ActiveGas, diffDepth, diffTime);
            }

            var seg = new DiveSegment(waypoint.Depth, ascdescTime, DiveState.Desend, runTime, runTime + timespent,
                                      algorithm.ActiveGas, cns, otu);
            Logger.Trace("Calc => Segment:" + seg);
            divetable.Add(seg);

            return ascdescTime;
        }
示例#8
0
        private TimeSpan DoDeco(ZH_L16 algorithm, double currentDepth, double finalDepth, int runTime,
            ref Collection<DiveSegment> diveTable)
        {
            if (currentDepth < pref.MiniDepthForDeco)
            {
                Logger.Error("DoDeco => Can't do deco because of current depth is lower than min deco depth");
                throw new ArgumentException("currentDepth can't be smaller then miniDepthForDeco");
            }

            Logger.Trace("DoDeco => currentDepth:{0}, FinalDepth:{1}", currentDepth, finalDepth);

            double minDepthAscent = algorithm.MinDepthAscent(CalcGradient(firstDecoDepth, currentDepth, pref));
            double decoDepth = GetDecoDepth(minDepthAscent, pref);

            if (Math.Abs(currentDepth - decoDepth) > 0.001)
            {
                Logger.Error("DoDeco => Can't do deco because current depth is not deco depth");
                throw new ArgumentException("Can't do deco because current depth is not deco depth");
            }

            firstDecoDepth = decoDepth;

            Logger.Trace("DoDeco => start deco depth:" + decoDepth);

            var timeSpentDeco = new TimeSpan();

            double decoStartDepth = decoDepth;
            while (minDepthAscent > finalDepth)
            {
                decoDepth = GetDecoDepth(minDepthAscent, pref);

                int timespent = GetDecoStopTime(algorithm, decoDepth, pref, CalcGradient(firstDecoDepth, decoDepth, pref));
                TimeSpan decoTime = TimeSpan.FromMinutes(timespent);
                timeSpentDeco += TimeSpan.FromMinutes(timespent);
                double cns = CentralNervousSystem.ConstantDepth(algorithm.ActiveGas, decoDepth, timespent);
                double otu = OxygenToxicityUnit.ConstantDepth(algorithm.ActiveGas, decoDepth, timespent);
                var seg = new DiveSegment(decoDepth, decoTime, DiveState.Deco, runTime, runTime + timespent,
                                          algorithm.ActiveGas, cns, otu);
                Logger.Trace("DoDeco => Segment:" + seg);
                diveTable.Add(seg);
                runTime += timespent;

                if (Math.Abs(decoDepth - pref.MiniDepthForDeco) < 0.001)
                {
                    minDepthAscent = 0;
                }
                else
                {
                    minDepthAscent = decoDepth - pref.DepthBetweenDecoStops;
                }
            }

            return timeSpentDeco;
        }
示例#9
0
        private double ContinueAscend(ZH_L16 algorithm, double finalDepth, double decoDepth)
        {
            double stopDepth;

            double minDepthAscent = algorithm.MinDepthAscent(CalcGradient(firstDecoDepth, decoDepth, pref));

            //// deco was not needed
            if (minDepthAscent <= finalDepth)
            {
                Logger.Trace("DoDeco => Deco not needed");
                algorithm.AscendDecsend(decoDepth, finalDepth, pref.AscRate);
                stopDepth = finalDepth;
            }
            else
            {
                bool done = false;
                //// Check if we during ascent did get rid of deco obligations for that depth
                while (!done)
                {
                    if (minDepthAscent < (decoDepth - pref.DepthBetweenDecoStops))
                    {
                        double oldDecoDepth = decoDepth;
                        decoDepth = GetDecoDepth(minDepthAscent, pref);

                        //To not go to far
                        if (decoDepth < finalDepth)
                        {
                            decoDepth = finalDepth;
                            done = true;
                        }

                        Logger.Trace(
                            "GotoDecoDepth => During ascent to depth:{0} we have changed celling to next deco depth:{1}",
                            oldDecoDepth, decoDepth);
                        algorithm.AscendDecsend(oldDecoDepth, decoDepth, pref.AscRate);
                        minDepthAscent = algorithm.MinDepthAscent(CalcGradient(firstDecoDepth, decoDepth, pref));
                    }
                    else
                    {
                        done = true;
                    }
                }

                stopDepth = decoDepth;
            }
            return stopDepth;
        }
示例#10
0
 private static void StayAtDepth(ZH_L16 algorithm, ref Collection<DiveSegment> divetable, int runTime,
     double depth, double time)
 {
     algorithm.AddRunTimeInMinutes(time, depth);
     double cns = CentralNervousSystem.ConstantDepth(algorithm.ActiveGas, depth, time);
     double otu = OxygenToxicityUnit.ConstantDepth(algorithm.ActiveGas, depth, time);
     var seg = new DiveSegment(depth, TimeSpan.FromMinutes(time), DiveState.Diving, runTime,
                               runTime + TimeHelper.MinutesRoundedUp(TimeSpan.FromMinutes(time)), algorithm.ActiveGas, cns,
                               otu);
     Logger.Trace("Calc => Segment:" + seg);
     divetable.Add(seg);
 }
示例#11
0
        private static int GetDecoStopTime(ZH_L16 alg, double depth, Preference pref, double gradient)
        {
            int timer = 0;
            double goalDepth = depth - pref.DepthBetweenDecoStops;

            //// If goal depth is small the min depth for deco and depth is equal to mino deco depth set next deco depth to 0.
            if (goalDepth < pref.MiniDepthForDeco && Math.Abs(depth - pref.MiniDepthForDeco) < 0.001)
            {
                Logger.Trace(
                    "GetDecoStopTime => Goal depth ({0}) is smaller then mini deco depth {1} for deco, on current depth ({2}) is equal to mini deco depth. Setting goal depth to 0",
                    goalDepth, pref.MiniDepthForDeco, depth);
                goalDepth = 0;
            }

            //// If goal deth is small the min depth for deco and depth is bigger that mini deco depth set next deco depth to mnin deco depth.
            if (goalDepth < pref.MiniDepthForDeco && depth > pref.MiniDepthForDeco)
            {
                Logger.Trace(
                    "GetDecoStopTime => Goal depth ({0}) is smaller then mini deco depth {1} for deco, on current depth ({2}) and depth is bigger than mini deco depth. Setting goal depth to min deco depth",
                    goalDepth, pref.MiniDepthForDeco, depth);
                goalDepth = pref.MiniDepthForDeco;
            }

            double startDepth = depth;
            while (goalDepth < depth)
            {
                timer++;
                alg.AddRunTimeInMinutes(1, startDepth);
                depth = alg.MinDepthAscent(gradient);
            }

            Logger.Trace("GetDecoStopTime => StartDepth:{0}, EndDepth:{1}, Gradient:{2}, Time:{3}", startDepth, depth,
                         gradient, timer);
            return timer;
        }
示例#12
0
        public Collection<DiveSegment> Calc(Collection<WayPoint> waypoints, ZH_L16 algorithm, Preference preference)
        {
            pref = preference;

            var divetable = new Collection<DiveSegment>();
            int runTime = 0;
            double depth = 0;
            if (algorithm.ActiveGas == null)
            {
                algorithm.ActiveGas = waypoints[0].Gas;
            }

            foreach (WayPoint waypoint in waypoints)
            {
                var ascdescTime = new TimeSpan();

                //// Going down
                if (waypoint.Depth > depth)
                {
                    ascdescTime = GoingDown(algorithm, ref divetable, runTime, depth, waypoint);
                }

                //// Going upp
                if (waypoint.Depth < depth)
                {
                    ascdescTime = GoingUp(algorithm, ref divetable, runTime, depth, waypoint);
                }

                int timeSpentAscDesc = TimeHelper.MinutesRoundedUp(ascdescTime);
                runTime += timeSpentAscDesc;

                // Gas swith
                if (!Equals(algorithm.ActiveGas, waypoint.Gas))
                {
                    if (this.pref.TimeToSwitchGas > 0)
                    {
                        algorithm.AddRunTimeInMinutes(pref.TimeToSwitchGas, waypoint.Depth);
                    }

                    double cns = CentralNervousSystem.ConstantDepth(algorithm.ActiveGas, waypoint.Depth, pref.TimeToSwitchGas);
                    double otu = OxygenToxicityUnit.ConstantDepth(algorithm.ActiveGas, waypoint.Depth, pref.TimeToSwitchGas);
                    var seg = new DiveSegment(waypoint.Depth, new TimeSpan(0, 0, (int) pref.TimeToSwitchGas, 0, 0),
                                              DiveState.GasSwitch, runTime, runTime + (int) pref.TimeToSwitchGas,
                                              algorithm.ActiveGas, cns, otu);
                    Logger.Trace("Calc => Segment:" + seg);
                    divetable.Add(seg);
                    runTime += (int) pref.TimeToSwitchGas;
                    algorithm.ActiveGas = waypoint.Gas;
                }

                //// still time left to stay at depth
                if (timeSpentAscDesc < waypoint.Time)
                {
                    double timeLeft = waypoint.Time - timeSpentAscDesc;
                    StayAtDepth(algorithm, ref divetable, runTime, waypoint.Depth, timeLeft);
                    runTime += (int) waypoint.Time - timeSpentAscDesc;
                }

                depth = waypoint.Depth;
            }

            return divetable;
        }
示例#13
0
 public void ZH_L16_AddRunTimeInMinutesTest_NoActiveGas_ThrowException()
 {
     ZH_L16 target = new ZH_L16();
     double time = 10;
     double depth = 30;
     Assert.Throws<ArgumentException>(() => target.AddRunTimeInMinutes(time, depth));
 }