/// <summary> /// Initializes a new instance of the <see cref="Breathing"/> class starting at the given state. /// A breathing is composed of three state. The first is "inspiration", the second in "holding breath" and the last one is "expiration". /// </summary> /// <param name="startVolume">The volume at which we start the breathing (before inspiration). As all volume, 0 is for empty lungs and 1 for full ones (which in this case: before inspiration; is irrelevant).</param> /// <param name="maxVolume">The volume at which we end the inspiration and start the holding breath. As all volume, 0 is for empty (which in this case: after inspiration; is irrelevant) lungs and 1 for full ones.</param> /// <param name="endVolume">The volume at which we end the breathing (the end of the expiration). As all volume, 0 is for empty lungs and 1 for full ones (which in this case: after expiration; is irrelevant).</param> /// <param name="holdingBreathTime">The time (is seconds) the patient should hold his breath after an inspiration.</param> /// <param name="inspirationTime">The time (is seconds) the patient should inspiring (from <see cref="startVolume"/> to <see cref="maxVolume"/>).</param> /// <param name="expirationTime">The time (is seconds) the patient should expiring (from <see cref="maxVolume"/> to <see cref="endVolume"/>).</param> /// <param name="startState">The state at which this breathing starts.</param> public Breathing(float startVolume, float maxVolume, float endVolume, float inspirationTime, float holdingBreathTime, float expirationTime, BreathingState startState, InputController_I inputController) { this.startVolume = startVolume; this.maxVolume = maxVolume; this.endVolume = endVolume; this.inspirationTime = inspirationTime; this.holdingBreathTime = holdingBreathTime; this.expirationTime=expirationTime; this.inputController = inputController; ResetTo (startState); }
/// <summary> /// Gets the BreathingState : /// expiration if patient is blowing and inspiration is over. /// inspiration if patient wasn't reach the actual breathing's maximum volume. /// holding breath if the patient isn't blowing but is at the actual breathing's maximum volume. /// </summary> public BreathingState GetInputState() { if (isBlowing () && state!=BreathingState.INSPIRATION) { state= BreathingState.EXPIRATION; } else { float deltaFloatComp=0.001f; if(exercice.Volume <= exercice.ActualBreathing.MaxVolume-deltaFloatComp){ state=BreathingState.INSPIRATION; } else { state=BreathingState.HOLDING_BREATH; } } return state; }
/// <summary> /// Check the progress of the patient in this breathing and compute his actual lungs volume. /// </summary> /// <returns>The patient actual lungs volume (0 for empty and 1 for full).</returns> /// <param name="newState">The new breathing state (retrieve from the input controller). Can be the same as the actual state.</param> /// <param name="strength">The strength of the player inhale or exhale (depends on <see cref="newState"/>).</param> /// <param name="volumeRatio">The old volume value which will be updated and returned.</param> /// <param name="deltaTime">The time in seconds elapsed since the last call.</param> public float CheckProgress(BreathingState newState, float strength, float volumeRatio, float volumeMaxCalibrated, float deltaTime) { strength = CallibrateStrength (strength, volumeMaxCalibrated); if (isBreathingEnded) { return volumeRatio; } lastState = state; state = newState; if(lastState==GetSupposedLastState(state)){ if(state==BreathingState.INSPIRATION && hasBreathingStarted){ isBreathingEnded=true; return volumeRatio; } if(!dictStateStartTimes.ContainsKey(state)){ dictStateStartTimes.Add(state, DateTime.Now); } CheckProgress(state, strength, volumeRatio, volumeMaxCalibrated, deltaTime); } else if(lastState == state){ hasBreathingStarted=true; switch (state) { case BreathingState.EXPIRATION://We expire volumeRatio-=strength*deltaTime*ExpirationSpeed; if(volumeRatio<endVolume){ volumeRatio=endVolume; } dictStatePercentages[state]=(volumeRatio-maxVolume)/(endVolume-maxVolume); break; case BreathingState.INSPIRATION://We inspire volumeRatio+=strength*deltaTime*InspirationSpeed; if(volumeRatio>maxVolume){ volumeRatio=MaxVolume; } float newPercentage=(volumeRatio-startVolume)/(maxVolume-startVolume); dictStatePercentages[state]=newPercentage; break; case BreathingState.HOLDING_BREATH://We hold our breath dictStatePercentages[state]=((float)(DateTime.Now-dictStateStartTimes[state]).TotalSeconds)/(holdingBreathTime); if(dictStatePercentages[state]>1.0f){ dictStatePercentages[state]=1.0f; } break; } } else{ state=GetSupposedLastState(state); } return volumeRatio; }
/// <summary> /// Reset this breathing to the given initial state. /// </summary> /// <param name="stateToResetAt">State to reset at.</param> public void ResetTo(BreathingState stateToResetAt) { this.state = stateToResetAt; this.lastState = GetSupposedLastState (stateToResetAt); this.dictStateStartTimes.Clear (); this.dictStateStartTimes [stateToResetAt] = DateTime.Now; this.dictStatePercentages.Clear (); this.dictStatePercentages.Add (BreathingState.INSPIRATION, 0.0f); this.dictStatePercentages.Add (BreathingState.HOLDING_BREATH, 0.0f); this.dictStatePercentages.Add (BreathingState.EXPIRATION, 0.0f); this.hasBreathingStarted = false; this.isBreathingEnded = false; }
/// <summary> /// Gets the usual state that precedes the given one. /// </summary> /// <returns>The usual state that precedes the given one.</returns> /// <param name="state">The state we want to know its prior.</param> public static BreathingState GetSupposedLastState(BreathingState state) { switch (state) { case BreathingState.INSPIRATION: return BreathingState.EXPIRATION; case BreathingState.HOLDING_BREATH: return BreathingState.INSPIRATION; case BreathingState.EXPIRATION: return BreathingState.HOLDING_BREATH; } return BreathingState.INSPIRATION; }