using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("EndGameStats.Core")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("EndGameStats.Core")] [assembly: AssemblyTitle("EndGameStats.Core")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace EndGameStats.Core { public sealed class PlayerRunStats { public string PlayerId { get; } public string DisplayName { get; private set; } public int Deaths { get; private set; } public int TeammatesRescued { get; private set; } public int EnemyKills { get; private set; } public double HaulWork { get; private set; } public double ExtractedValue { get; private set; } public double ValuableDamage { get; private set; } public PlayerRunStats(string playerId, string displayName) { if (string.IsNullOrWhiteSpace(playerId)) { throw new ArgumentException("A stable player ID is required.", "playerId"); } PlayerId = playerId; DisplayName = displayName ?? string.Empty; } public void Rename(string displayName) { DisplayName = displayName ?? string.Empty; } public void RecordDeath() { Deaths++; } public void RecordRescue() { TeammatesRescued++; } public void RecordEnemyKill() { EnemyKills++; } public void AddHaulWork(double currentValue, double distanceMetres, int grabberCount = 1) { if (!IsFiniteNonNegative(currentValue)) { throw new ArgumentOutOfRangeException("currentValue"); } if (!IsFiniteNonNegative(distanceMetres)) { throw new ArgumentOutOfRangeException("distanceMetres"); } if (grabberCount < 1) { throw new ArgumentOutOfRangeException("grabberCount"); } HaulWork += currentValue * distanceMetres / (double)grabberCount; } public void AddValuableDamage(double valueLost) { if (!IsFiniteNonNegative(valueLost)) { throw new ArgumentOutOfRangeException("valueLost"); } ValuableDamage += valueLost; } public void AddExtractedValue(double value) { if (!IsFiniteNonNegative(value)) { throw new ArgumentOutOfRangeException("value"); } ExtractedValue += value; } private static bool IsFiniteNonNegative(double value) { if (!double.IsNaN(value) && !double.IsInfinity(value)) { return value >= 0.0; } return false; } } public sealed class RunStatsBoard { private readonly Dictionary _players = new Dictionary(StringComparer.Ordinal); public IReadOnlyCollection Players => _players.Values; public double UnattributedValuableDamage { get; private set; } public double UnattributedExtractedValue { get; private set; } public PlayerRunStats GetOrAddPlayer(string playerId, string displayName) { if (_players.TryGetValue(playerId, out PlayerRunStats value)) { value.Rename(displayName); return value; } value = new PlayerRunStats(playerId, displayName); _players.Add(playerId, value); return value; } public void AddUnattributedDamage(double valueLost) { if (double.IsNaN(valueLost) || double.IsInfinity(valueLost) || valueLost < 0.0) { throw new ArgumentOutOfRangeException("valueLost"); } UnattributedValuableDamage += valueLost; } public void AddUnattributedExtractedValue(double value) { if (double.IsNaN(value) || double.IsInfinity(value) || value < 0.0) { throw new ArgumentOutOfRangeException("value"); } UnattributedExtractedValue += value; } public IReadOnlyList Leaders(Func value, bool lowerIsBetter = false, Func? eligible = null) { PlayerRunStats[] array = _players.Values.Where(eligible ?? ((Func)((PlayerRunStats _) => true))).ToArray(); if (array.Length == 0) { return Array.Empty(); } double best = (lowerIsBetter ? array.Min(value) : array.Max(value)); return array.Where((PlayerRunStats player) => NearlyEqual(value(player), best)).OrderBy((PlayerRunStats player) => player.DisplayName, StringComparer.OrdinalIgnoreCase).ToArray(); } private static bool NearlyEqual(double left, double right) { double num = Math.Max(1.0, Math.Max(Math.Abs(left), Math.Abs(right))); return Math.Abs(left - right) <= 1E-09 * num; } } }