< Summary

Information
Class: Trailblazer.Pathing.NavigationFlowFieldWorkspace
Assembly: Trailblazer
File(s): /home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Search/Flow/NavigationFlowFieldWorkspace.cs
Line coverage
100%
Covered lines: 81
Uncovered lines: 0
Coverable lines: 81
Total lines: 175
Line coverage: 100%
Branch coverage
100%
Covered branches: 18
Total branches: 18
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%88100%
get_NodeCapacity()100%11100%
get_DependencyPageCapacity()100%11100%
get_DependencyComponentCapacity()100%11100%
get_DependencyPages()100%11100%
get_DependencyComponents()100%11100%
get_DependencyPageCount()100%11100%
get_DependencyComponentCount()100%11100%
Reset()100%11100%
ResetSearch()100%22100%
TryGetSlot(...)100%44100%
TryGetOrAdd(...)100%44100%
GetRecord(...)100%11100%
GetNode(...)100%11100%
TryRecordComponent(...)100%11100%
TryRecordPage(...)100%11100%

File(s)

/home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Search/Flow/NavigationFlowFieldWorkspace.cs

#LineLine coverage
 1//=======================================================================
 2// NavigationFlowFieldWorkspace.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;
 10
 11namespace Trailblazer.Pathing;
 12
 13internal struct NavigationFlowFieldSearchNode
 14{
 15    internal NavigationCellAddress Address;
 16    internal Fixed64 IntegrationCost;
 17    internal NavigationSelectedEdgeRef SelectedEdge;
 18    internal int HeapIndex;
 19    internal bool SelectedIsTransition;
 20    internal bool Closed;
 21}
 22
 23/// <summary>Owns reusable fixed-capacity buffers for one exclusive flow query.</summary>
 24internal sealed class NavigationFlowFieldWorkspace
 25{
 26    private readonly NavigationMediumStateRef[] _keys;
 27    private readonly NavigationFlowFieldSearchNode[] _records;
 28    private readonly long[] _stamps;
 29    private readonly int[] _activeSlots;
 30    private readonly int _mask;
 31    private readonly int _nodeCapacity;
 32    private int _nodeCount;
 850233    private long _generation = 1;
 34
 850235    internal NavigationFlowFieldWorkspace(
 850236        int mapCapacity,
 850237        int dependencyPageCapacity,
 850238        int dependencyComponentCapacity,
 850239        int nodeCapacity,
 850240        int rayCoveredAddressCapacity,
 850241        int rayTraceIntervalCapacity)
 42    {
 850243        SwiftThrowHelper.ThrowIfNegative(
 850244            dependencyPageCapacity,
 850245            nameof(dependencyPageCapacity));
 850246        SwiftThrowHelper.ThrowIfNegative(
 850247            dependencyComponentCapacity,
 850248            nameof(dependencyComponentCapacity));
 850249        SwiftThrowHelper.ThrowIfNegative(nodeCapacity, nameof(nodeCapacity));
 850250        int tableSize = 1;
 850251        int required = checked(Math.Max(1, nodeCapacity * 2));
 11510752        while (tableSize < required)
 10660553            tableSize = checked(tableSize * 2);
 850254        _keys = new NavigationMediumStateRef[tableSize];
 850255        _records = new NavigationFlowFieldSearchNode[tableSize];
 850256        _stamps = new long[tableSize];
 850257        _activeSlots = nodeCapacity == 0 ? Array.Empty<int>() : new int[nodeCapacity];
 850258        _mask = tableSize - 1;
 850259        _nodeCapacity = nodeCapacity;
 850260        HeapSlots = nodeCapacity == 0 ? Array.Empty<int>() : new int[nodeCapacity];
 850261        SettledSlots = nodeCapacity == 0 ? Array.Empty<int>() : new int[nodeCapacity];
 850262        EndpointWorkspace = new NavigationEndpointWorkspace(
 850263            mapCapacity,
 850264            dependencyPageCapacity,
 850265            dependencyComponentCapacity);
 850266        RayWorkspace = new NavigationRayWorkspace(
 850267            mapCapacity,
 850268            dependencyPageCapacity,
 850269            dependencyComponentCapacity,
 850270            rayCoveredAddressCapacity,
 850271            rayTraceIntervalCapacity);
 850272    }
 73
 74    internal NavigationEndpointWorkspace EndpointWorkspace { get; }
 75
 76    internal NavigationRayWorkspace RayWorkspace { get; }
 77
 78    internal int[] HeapSlots { get; }
 79
 80    internal int[] SettledSlots { get; }
 81
 4282    internal int NodeCapacity => _nodeCapacity;
 83
 4284    internal int DependencyPageCapacity => DependencyPages.Length;
 85
 4286    internal int DependencyComponentCapacity => DependencyComponents.Length;
 87
 145288    internal GraphPageDependencyAddress[] DependencyPages => EndpointWorkspace.Pages;
 89
 90    internal NavigationSurfaceComponentKey[] DependencyComponents =>
 145291        EndpointWorkspace.Components;
 92
 93    internal int HeapCount { get; set; }
 94
 95    internal int SettledCount { get; set; }
 96
 211897    internal int DependencyPageCount => EndpointWorkspace.PageCount;
 98
 211899    internal int DependencyComponentCount => EndpointWorkspace.ComponentCount;
 100
 101    internal void Reset()
 102    {
 2103        ResetSearch();
 2104        EndpointWorkspace.Reset();
 2105        RayWorkspace.Reset();
 2106    }
 107
 108    internal void ResetSearch()
 109    {
 1650110        for (int i = 0; i < _nodeCount; i++)
 111        {
 86112            int slot = _activeSlots[i];
 86113            _keys[slot] = default;
 86114            _records[slot] = default;
 86115            _activeSlots[i] = 0;
 116        }
 117        unchecked
 118        {
 739119            _generation++;
 120        }
 739121        _nodeCount = 0;
 739122        HeapCount = 0;
 739123        SettledCount = 0;
 739124    }
 125
 126    internal bool TryGetSlot(NavigationMediumStateRef node, out int slot)
 127    {
 6915128        slot = node.GetHashCode() & _mask;
 6921129        while (_stamps[slot] == _generation)
 130        {
 2996131            if (_keys[slot].Equals(node))
 2990132                return true;
 6133            slot = (slot + 1) & _mask;
 134        }
 3925135        return false;
 136    }
 137
 138    internal bool TryGetOrAdd(
 139        NavigationMediumStateRef node,
 140        out int slot,
 141        out bool added)
 142    {
 6914143        if (TryGetSlot(node, out slot))
 144        {
 2990145            added = false;
 2990146            return true;
 147        }
 3924148        if (_nodeCount >= _nodeCapacity)
 149        {
 5150            added = false;
 5151            return false;
 152        }
 3919153        _keys[slot] = node;
 3919154        _records[slot] = default;
 3919155        _stamps[slot] = _generation;
 3919156        _activeSlots[_nodeCount++] = slot;
 3919157        added = true;
 3919158        return true;
 159    }
 160
 161    internal ref NavigationFlowFieldSearchNode GetRecord(int slot) =>
 35193162        ref _records[slot];
 163
 9965164    internal NavigationMediumStateRef GetNode(int slot) => _keys[slot];
 165
 166    internal bool TryRecordComponent(NavigationSurfaceComponentKey key)
 167    {
 6914168        return EndpointWorkspace.TryRecordComponent(key);
 169    }
 170
 171    internal bool TryRecordPage(string mapId, int pageIndex)
 172    {
 7648173        return EndpointWorkspace.TryRecordPage(mapId, pageIndex);
 174    }
 175}