// MIT License - Copyright (c) 2025 wallstop // Full license text: https://github.com/wallstop/unity-helpers/blob/main/LICENSE namespace WallstopStudios.UnityHelpers.Core.Random { using System; using WallstopStudios.UnityHelpers.Core.Helper; /// /// Coarse statistical quality ratings for RNG implementations. /// public enum RandomQuality { Unknown = 0, Excellent, VeryGood, Good, Fair, Poor, Experimental, } /// /// Describes statistical quality metadata that can be attached to implementations. /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public sealed class RandomGeneratorMetadataAttribute : Attribute { public RandomGeneratorMetadataAttribute( RandomQuality quality, string notes, string reference = "", string referenceUrl = "" ) { Quality = quality; Notes = notes ?? string.Empty; Reference = reference ?? string.Empty; ReferenceUrl = referenceUrl ?? string.Empty; } public RandomQuality Quality { get; } public string Notes { get; } public string Reference { get; } public string ReferenceUrl { get; } public int QualitySortValue => (int)Quality; } /// /// Static helpers to retrieve metadata from RNG implementations. /// public static class RandomGeneratorMetadataRegistry { public static RandomGeneratorMetadata Snapshot(IRandom random) { if (random == null) { return RandomGeneratorMetadata.Empty; } return Snapshot(random.GetType()); } public static RandomGeneratorMetadata Snapshot(Type randomType) { if (randomType == null) { return RandomGeneratorMetadata.Empty; } if ( !ReflectionHelpers.TryGetAttributeSafe( randomType, out RandomGeneratorMetadataAttribute attribute, inherit: false ) ) { return new RandomGeneratorMetadata( randomType, RandomQuality.Unknown, "Not annotated.", string.Empty, string.Empty ); } return new RandomGeneratorMetadata( randomType, attribute.Quality, attribute.Notes, attribute.Reference, attribute.ReferenceUrl ); } } public readonly struct RandomGeneratorMetadata { public static readonly RandomGeneratorMetadata Empty = new( typeof(object), RandomQuality.Unknown, string.Empty, string.Empty, string.Empty ); public RandomGeneratorMetadata( Type type, RandomQuality quality, string notes, string reference, string referenceUrl ) { Type = type; Quality = quality; Notes = notes ?? string.Empty; Reference = reference ?? string.Empty; ReferenceUrl = referenceUrl ?? string.Empty; } public Type Type { get; } public RandomQuality Quality { get; } public string Notes { get; } public string Reference { get; } public string ReferenceUrl { get; } public string QualityLabel { get { return Quality switch { RandomQuality.Excellent => "Excellent", RandomQuality.VeryGood => "Very Good", RandomQuality.Good => "Good", RandomQuality.Fair => "Fair", RandomQuality.Poor => "Poor", RandomQuality.Experimental => "Experimental", _ => "Unknown", }; } } public int QualitySortValue => (int)Quality; public string ReferenceDisplay { get { if (string.IsNullOrWhiteSpace(ReferenceUrl)) { return string.IsNullOrWhiteSpace(Reference) ? string.Empty : Reference; } string label = string.IsNullOrWhiteSpace(Reference) ? ReferenceUrl : Reference; return $"[{label}]({ReferenceUrl})"; } } } }