< Summary

Information
Class: GridForge.Diagnostics.GridDiagnosticChange
Assembly: GridForge
File(s): /home/runner/work/GridForge/GridForge/src/GridForge/Diagnostics/GridDiagnosticChange.cs
Line coverage
50%
Covered lines: 36
Uncovered lines: 35
Coverable lines: 71
Total lines: 188
Line coverage: 50.7%
Branch coverage
29%
Covered branches: 13
Total branches: 44
Branch coverage: 29.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
WithKind(...)100%11100%
CompareTo(...)42.85%321454.54%
Equals(...)0%210140%
Equals(...)0%620%
GetHashCode()100%210%
GetScopeOrder(...)87.5%8885.71%
CompareVector(...)0%2040%
CompareFixed(...)0%620%

File(s)

/home/runner/work/GridForge/GridForge/src/GridForge/Diagnostics/GridDiagnosticChange.cs

#LineLine coverage
 1//=======================================================================
 2// GridDiagnosticChange.cs
 3//=======================================================================
 4// MIT License, Copyright (c) 2024-present David Oravsky (mrdav30)
 5// See LICENSE file in the project root for full license information.
 6//=======================================================================
 7
 8using FixedMathSharp;
 9using GridForge.Spatial;
 10using SwiftCollections.Utility;
 11using System;
 12
 13namespace GridForge.Diagnostics;
 14
 15/// <summary>
 16/// Immutable descriptor for one diagnostic dirty change captured by a session.
 17/// </summary>
 18public readonly struct GridDiagnosticChange :
 19    IEquatable<GridDiagnosticChange>,
 20    IComparable<GridDiagnosticChange>
 21{
 22    /// <summary>
 23    /// Kind flags coalesced for this dirty change.
 24    /// </summary>
 25    public readonly GridDiagnosticChangeKind Kind;
 26
 27    /// <summary>
 28    /// Runtime token of the world that produced the change.
 29    /// </summary>
 30    public readonly int WorldSpawnToken;
 31
 32    /// <summary>
 33    /// World-local grid slot affected by the change, or
 34    /// <see cref="ushort.MaxValue"/> for world-scoped changes.
 35    /// </summary>
 36    public readonly ushort GridIndex;
 37
 38    /// <summary>
 39    /// Runtime token of the grid instance affected by the change.
 40    /// </summary>
 41    public readonly int GridSpawnToken;
 42
 43    /// <summary>
 44    /// World-scoped voxel identity for cell-scoped changes.
 45    /// </summary>
 46    public readonly WorldVoxelIndex WorldIndex;
 47
 48    /// <summary>
 49    /// Topology-local voxel index for cell or sparse address-range changes.
 50    /// </summary>
 51    public readonly VoxelIndex VoxelIndex;
 52
 53    /// <summary>
 54    /// Minimum world-space bounds affected by grid or range-scoped changes.
 55    /// </summary>
 56    public readonly Vector3d BoundsMin;
 57
 58    /// <summary>
 59    /// Maximum world-space bounds affected by grid or range-scoped changes.
 60    /// </summary>
 61    public readonly Vector3d BoundsMax;
 62
 63    /// <summary>
 64    /// Initializes a diagnostic dirty-change descriptor.
 65    /// </summary>
 66    public GridDiagnosticChange(
 67        GridDiagnosticChangeKind kind,
 68        int worldSpawnToken,
 69        ushort gridIndex,
 70        int gridSpawnToken,
 71        WorldVoxelIndex worldIndex,
 72        VoxelIndex voxelIndex,
 73        Vector3d boundsMin,
 74        Vector3d boundsMax)
 75    {
 2376        Kind = kind;
 2377        WorldSpawnToken = worldSpawnToken;
 2378        GridIndex = gridIndex;
 2379        GridSpawnToken = gridSpawnToken;
 2380        WorldIndex = worldIndex;
 2381        VoxelIndex = voxelIndex;
 2382        BoundsMin = boundsMin;
 2383        BoundsMax = boundsMax;
 2384    }
 85
 86    internal GridDiagnosticChange WithKind(GridDiagnosticChangeKind kind) =>
 487        new(
 488            kind,
 489            WorldSpawnToken,
 490            GridIndex,
 491            GridSpawnToken,
 492            WorldIndex,
 493            VoxelIndex,
 494            BoundsMin,
 495            BoundsMax);
 96
 97    /// <inheritdoc/>
 98    public int CompareTo(GridDiagnosticChange other)
 99    {
 4100        int result = WorldSpawnToken.CompareTo(other.WorldSpawnToken);
 4101        if (result != 0)
 0102            return result;
 103
 4104        result = GetScopeOrder(this).CompareTo(GetScopeOrder(other));
 4105        if (result != 0)
 3106            return result;
 107
 1108        result = GridIndex.CompareTo(other.GridIndex);
 1109        if (result != 0)
 0110            return result;
 111
 1112        result = GridSpawnToken.CompareTo(other.GridSpawnToken);
 1113        if (result != 0)
 0114            return result;
 115
 1116        result = VoxelIndex.CompareTo(other.VoxelIndex);
 1117        if (result != 0)
 1118            return result;
 119
 0120        result = CompareVector(BoundsMin, other.BoundsMin);
 0121        if (result != 0)
 0122            return result;
 123
 0124        result = CompareVector(BoundsMax, other.BoundsMax);
 0125        if (result != 0)
 0126            return result;
 127
 0128        return ((int)Kind).CompareTo((int)other.Kind);
 129    }
 130
 131    /// <inheritdoc/>
 132    public bool Equals(GridDiagnosticChange other) =>
 0133        Kind == other.Kind
 0134        && WorldSpawnToken == other.WorldSpawnToken
 0135        && GridIndex == other.GridIndex
 0136        && GridSpawnToken == other.GridSpawnToken
 0137        && WorldIndex.Equals(other.WorldIndex)
 0138        && VoxelIndex.Equals(other.VoxelIndex)
 0139        && BoundsMin.Equals(other.BoundsMin)
 0140        && BoundsMax.Equals(other.BoundsMax);
 141
 142    /// <inheritdoc/>
 0143    public override bool Equals(object? obj) => obj is GridDiagnosticChange other && Equals(other);
 144
 145    /// <inheritdoc/>
 146    public override int GetHashCode()
 147    {
 0148        int hash = SwiftHashTools.CombineHashCodes((int)Kind, WorldSpawnToken);
 0149        hash = SwiftHashTools.CombineHashCodes(hash, GridIndex);
 0150        hash = SwiftHashTools.CombineHashCodes(hash, GridSpawnToken);
 0151        hash = SwiftHashTools.CombineHashCodes(hash, WorldIndex.GetHashCode());
 0152        hash = SwiftHashTools.CombineHashCodes(hash, VoxelIndex.GetHashCode());
 0153        hash = SwiftHashTools.CombineHashCodes(hash, BoundsMin.GetHashCode());
 0154        return SwiftHashTools.CombineHashCodes(hash, BoundsMax.GetHashCode());
 155    }
 156
 157    private static int GetScopeOrder(GridDiagnosticChange change)
 158    {
 8159        if ((change.Kind & GridDiagnosticChangeKind.WorldReset) != 0)
 0160            return 0;
 161
 8162        if (change.WorldIndex.WorldSpawnToken != 0 || change.WorldIndex.VoxelIndex.IsAllocated)
 5163            return 2;
 164
 3165        if ((change.Kind & GridDiagnosticChangeKind.SparseAddressChanged) != 0)
 2166            return 3;
 167
 1168        return 1;
 169    }
 170
 171    private static int CompareVector(Vector3d left, Vector3d right)
 172    {
 0173        int result = CompareFixed(left.X, right.X);
 0174        if (result != 0)
 0175            return result;
 176
 0177        result = CompareFixed(left.Y, right.Y);
 0178        return result != 0 ? result : CompareFixed(left.Z, right.Z);
 179    }
 180
 181    private static int CompareFixed(Fixed64 left, Fixed64 right)
 182    {
 0183        if (left < right)
 0184            return -1;
 185
 0186        return left > right ? 1 : 0;
 187    }
 188}