< Summary

Information
Class: GridForge.Diagnostics.GridDiagnosticChange
Assembly: GridForge
File(s): /home/runner/work/GridForge/GridForge/src/GridForge/Diagnostics/GridDiagnosticChange.cs
Line coverage
100%
Covered lines: 71
Uncovered lines: 0
Coverable lines: 71
Total lines: 188
Line coverage: 100%
Branch coverage
100%
Covered branches: 44
Total branches: 44
Branch coverage: 100%
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(...)100%1414100%
Equals(...)100%1414100%
Equals(...)100%22100%
GetHashCode()100%11100%
GetScopeOrder(...)100%88100%
CompareVector(...)100%44100%
CompareFixed(...)100%22100%

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 System;
 9using FixedMathSharp;
 10using GridForge.Spatial;
 11using SwiftCollections.Utility;
 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 long 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 long 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        long worldSpawnToken,
 69        ushort gridIndex,
 70        long gridSpawnToken,
 71        WorldVoxelIndex worldIndex,
 72        VoxelIndex voxelIndex,
 73        Vector3d boundsMin,
 74        Vector3d boundsMax)
 75    {
 7076        Kind = kind;
 7077        WorldSpawnToken = worldSpawnToken;
 7078        GridIndex = gridIndex;
 7079        GridSpawnToken = gridSpawnToken;
 7080        WorldIndex = worldIndex;
 7081        VoxelIndex = voxelIndex;
 7082        BoundsMin = boundsMin;
 7083        BoundsMax = boundsMax;
 7084    }
 85
 86    internal GridDiagnosticChange WithKind(GridDiagnosticChangeKind kind) =>
 3087        new(
 3088            kind,
 3089            WorldSpawnToken,
 3090            GridIndex,
 3091            GridSpawnToken,
 3092            WorldIndex,
 3093            VoxelIndex,
 3094            BoundsMin,
 3095            BoundsMax);
 96
 97    /// <inheritdoc/>
 98    public int CompareTo(GridDiagnosticChange other)
 99    {
 31100        int result = WorldSpawnToken.CompareTo(other.WorldSpawnToken);
 31101        if (result != 0)
 2102            return result;
 103
 29104        result = GetScopeOrder(this).CompareTo(GetScopeOrder(other));
 29105        if (result != 0)
 7106            return result;
 107
 22108        result = GridIndex.CompareTo(other.GridIndex);
 22109        if (result != 0)
 2110            return result;
 111
 20112        result = GridSpawnToken.CompareTo(other.GridSpawnToken);
 20113        if (result != 0)
 2114            return result;
 115
 18116        result = VoxelIndex.CompareTo(other.VoxelIndex);
 18117        if (result != 0)
 3118            return result;
 119
 15120        result = CompareVector(BoundsMin, other.BoundsMin);
 15121        if (result != 0)
 6122            return result;
 123
 9124        result = CompareVector(BoundsMax, other.BoundsMax);
 9125        if (result != 0)
 6126            return result;
 127
 3128        return ((int)Kind).CompareTo((int)other.Kind);
 129    }
 130
 131    /// <inheritdoc/>
 132    public bool Equals(GridDiagnosticChange other) =>
 20133        Kind == other.Kind
 20134        && WorldSpawnToken == other.WorldSpawnToken
 20135        && GridIndex == other.GridIndex
 20136        && GridSpawnToken == other.GridSpawnToken
 20137        && WorldIndex.Equals(other.WorldIndex)
 20138        && VoxelIndex.Equals(other.VoxelIndex)
 20139        && BoundsMin.Equals(other.BoundsMin)
 20140        && BoundsMax.Equals(other.BoundsMax);
 141
 142    /// <inheritdoc/>
 3143    public override bool Equals(object? obj) => obj is GridDiagnosticChange other && Equals(other);
 144
 145    /// <inheritdoc/>
 146    public override int GetHashCode()
 147    {
 42148        int hash = SwiftHashTools.CombineHashCodes((int)Kind, WorldSpawnToken.GetHashCode());
 42149        hash = SwiftHashTools.CombineHashCodes(hash, GridIndex);
 42150        hash = SwiftHashTools.CombineHashCodes(hash, GridSpawnToken.GetHashCode());
 42151        hash = SwiftHashTools.CombineHashCodes(hash, WorldIndex.GetHashCode());
 42152        hash = SwiftHashTools.CombineHashCodes(hash, VoxelIndex.GetHashCode());
 42153        hash = SwiftHashTools.CombineHashCodes(hash, BoundsMin.GetHashCode());
 42154        return SwiftHashTools.CombineHashCodes(hash, BoundsMax.GetHashCode());
 155    }
 156
 157    private static int GetScopeOrder(GridDiagnosticChange change)
 158    {
 58159        if ((change.Kind & GridDiagnosticChangeKind.WorldReset) != 0)
 1160            return 0;
 161
 57162        if (change.WorldIndex.WorldSpawnToken != 0 || change.WorldIndex.VoxelIndex.IsAllocated)
 8163            return 2;
 164
 49165        if ((change.Kind & GridDiagnosticChangeKind.SparseAddressChanged) != 0)
 3166            return 3;
 167
 46168        return 1;
 169    }
 170
 171    private static int CompareVector(Vector3d left, Vector3d right)
 172    {
 24173        int result = CompareFixed(left.X, right.X);
 24174        if (result != 0)
 4175            return result;
 176
 20177        result = CompareFixed(left.Y, right.Y);
 20178        return result != 0 ? result : CompareFixed(left.Z, right.Z);
 179    }
 180
 181    private static int CompareFixed(Fixed64 left, Fixed64 right)
 182    {
 60183        if (left < right)
 6184            return -1;
 185
 54186        return left > right ? 1 : 0;
 187    }
 188}