// Copyright (C) 2023 Nicholas Maltbie // // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and // associated documentation files (the "Software"), to deal in the Software without restriction, // including without limitation the rights to use, copy, modify, merge, publish, distribute, // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using UnityEngine; namespace nickmaltbie.OpenKCC.Utils { /// /// Smoothed window of some value. /// Also, unity cannot detect code coverage stats for generic classes. Going /// to ignore metrics for this class. /// [ExcludeFromCodeCoverage] public class SmoothedWindow { /// /// Gets the sample values. /// protected E[] Samples { get; private set; } /// /// Gets the current selected index. /// protected int CurrentIdx { get; private set; } /// /// Get values for debugging. /// internal IEnumerable Values => Enumerable.Range(0, Count).Select(index => Samples[(CurrentIdx + index) % Count]); /// /// Count of /// /// public int Count { get; protected set; } /// /// Create a smoothed window. /// /// Size of smoothing window. public SmoothedWindow(int size) { Samples = new E[size]; } /// /// Adds a sample to the smoothing window at the next /// available space. Will overwrite data if any data /// is there. /// /// Value to add. /// Previous value removed. public virtual E AddSample(E value) { E previous = Samples[CurrentIdx]; Samples[CurrentIdx] = value; Count = Mathf.Max(Count, ++CurrentIdx); CurrentIdx %= Samples.Length; return previous; } } /// /// Smoothed window for a Vector3 value. /// public class SmoothedVector : SmoothedWindow { /// /// Running sum of the values stored in samples. /// protected Vector3 sum = Vector3.zero; /// /// Create a smoothed vector with a given number of samples.. /// /// Size of smoothing window. public SmoothedVector(int size) : base(size) { } /// /// Returns the average of all samples in the window. /// public Vector3 Average() { if (Count == 0) { return Vector3.zero; } return sum / Count; } /// public override Vector3 AddSample(Vector3 value) { Vector3 previous = base.AddSample(value); sum += value; sum -= previous; return previous; } } }