public override void OnUpdate() { base.OnUpdate(); if (!TestFlightEnabled) { return; } // NEW RELIABILITY CODE float operatingTime = core.GetOperatingTime(); if (operatingTime < lastCheck + 1f) { return; } lastCheck = operatingTime; double baseFailureRate = core.GetBaseFailureRate(); MomentaryFailureRate momentaryFailureRate = core.GetWorstMomentaryFailureRate(); double currentFailureRate; if (momentaryFailureRate.valid && momentaryFailureRate.failureRate > baseFailureRate) { currentFailureRate = momentaryFailureRate.failureRate; } else { currentFailureRate = baseFailureRate; } // Given we have been operating for a given number of seconds, calculate our chance of survival to that time based on currentFailureRate // This is *not* an exact science, as the real calculations are much more complex than this, plus technically the momentary rate for // *each* second should be accounted for, but this is a simplification of the system. It provides decent enough numbers for fun gameplay // with chance of failure increasing exponentially over time as it approaches the *current* MTBF // S() is survival chance, f is currentFailureRate // S(t) = e^(-f*t) float reliability = Mathf.Exp((float)-currentFailureRate * (float)operatingTime); // double survivalChance = Mathf.Pow(Mathf.Exp(1), (float)currentFailureRate * (float)operatingTime * -0.693f); double survivalChance = reliability / lastReliability; lastReliability = reliability; // float failureRoll = Mathf.Min(UnityEngine.Random.Range(0f, 1f), UnityEngine.Random.Range(0f, 1f)); // float failureRoll = UnityEngine.Random.Range(0f, 1f); double failureRoll = core.RandomGenerator.NextDouble(); Log(String.Format("Survival Chance at Time {0:F2} is {1:f4}. Rolled {2:f4}", (float)operatingTime, survivalChance, failureRoll)); if (failureRoll > survivalChance) { // Debug.Log(String.Format("TestFlightReliability: Survival Chance at Time {0:F2} is {1:f4} -- {2:f4}^({3:f4}*{0:f2}*-1.0)", (float)operatingTime, survivalChance, Mathf.Exp(1), (float)currentFailureRate)); Log(String.Format("Part has failed after {1:F1} secodns of operation at MET T+{2:F2} seconds with roll of {0:F4}", failureRoll, operatingTime, this.vessel.missionTime)); core.TriggerFailure(); } }
public MomentaryFailureRate GetBestMomentaryFailureRate() { MomentaryFailureRate bestMFR; bestMFR = new MomentaryFailureRate(); bestMFR.valid = false; bestMFR.failureRate = float.MaxValue; foreach (MomentaryFailureRate mfr in momentaryFailureRates) { if (mfr.failureRate < bestMFR.failureRate) { bestMFR = mfr; } } return bestMFR; }
// Get the momentary (IE current dynamic) failure rates (Can vary per reliability/failure modules) // These methods will let you get a list of all momentary rates or you can get the best (lowest chance of failure)/worst (highest chance of failure) rates public MomentaryFailureRate GetWorstMomentaryFailureRate() { MomentaryFailureRate worstMFR; worstMFR = new MomentaryFailureRate(); worstMFR.valid = false; worstMFR.failureRate = TestFlightUtil.MIN_FAILURE_RATE; foreach (MomentaryFailureRate mfr in momentaryFailureRates) { if (mfr.failureRate > worstMFR.failureRate) { worstMFR = mfr; } } return worstMFR; }
public MomentaryFailureRate GetBestMomentaryFailureRate() { MomentaryFailureRate bestMFR; bestMFR = new MomentaryFailureRate(); bestMFR.valid = false; bestMFR.failureRate = double.MaxValue; for (int i = 0, momentaryFailureRatesCount = momentaryFailureRates.Count; i < momentaryFailureRatesCount; i++) { MomentaryFailureRate mfr = momentaryFailureRates[i]; if (mfr.failureRate >= bestMFR.failureRate) continue; bestMFR = mfr; } return bestMFR; }