< Summary

Information
Class: Trailblazer.Pathing.HybridWaypointFlattener
Assembly: Trailblazer
File(s): /home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Search/Hybrid/Support/HybridWaypointFlattener.cs
Line coverage
92%
Covered lines: 89
Uncovered lines: 7
Coverable lines: 96
Total lines: 190
Line coverage: 92.7%
Branch coverage
78%
Covered branches: 50
Total branches: 64
Branch coverage: 78.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
TryBuild(...)100%1616100%
TryAppendSegmentWaypoints(...)75%121294.11%
ReturnBorrowedGuide(...)41.66%191263.63%
AppendWaypoints(...)66.66%6688.88%
AddChartKeys(...)75%8885.71%
AppendWaypoint(...)100%1010100%

File(s)

/home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Pathing/Search/Hybrid/Support/HybridWaypointFlattener.cs

#LineLine coverage
 1using SwiftCollections;
 2using System;
 3
 4namespace Trailblazer.Pathing;
 5
 6/// <summary>
 7/// Flattens staged hybrid route steps into a single waypoint stream for cached hybrid guides.
 8/// </summary>
 9internal static class HybridWaypointFlattener
 10{
 11    public static bool TryBuild(
 12        HybridRoutePlan routePlan,
 13        out AStarWaypoint[]? flattenedWaypoints,
 14        out string[] chartKeys)
 15    {
 2716        flattenedWaypoints = null;
 2717        chartKeys = Array.Empty<string>();
 2718        if (routePlan == null)
 119            return false;
 20
 2621        SwiftList<AStarWaypoint> waypoints = new();
 2622        SwiftList<IGuide> borrowedGuides = new();
 2623        SwiftList<string> utilizedCharts = new();
 2624        SwiftHashSet<string> utilizedChartSet = new();
 2625        int pathCostOffset = 0;
 26
 27        try
 28        {
 23829            for (int i = 0; i < routePlan.Steps.Length; i++)
 30            {
 9531                HybridRouteStep step = routePlan.Steps[i];
 9532                switch (step.Kind)
 33                {
 34                    case HybridRouteStepKind.Waypoint:
 7735                        pathCostOffset += step.AdditionalCost;
 7736                        AppendWaypoint(
 7737                            waypoints,
 7738                            new AStarWaypoint
 7739                            {
 7740                                Position = step.WaypointPosition,
 7741                                PathCost = pathCostOffset
 7742                            });
 7743                        break;
 44
 45                    case HybridRouteStepKind.PathSegment:
 1846                        if (!TryAppendSegmentWaypoints(
 1847                            step,
 1848                            waypoints,
 1849                            borrowedGuides,
 1850                            utilizedCharts,
 1851                            utilizedChartSet,
 1852                            ref pathCostOffset))
 53                        {
 254                            return false;
 55                        }
 56                        break;
 57                }
 58            }
 59
 2460            if (waypoints.Count == 0)
 161                return false;
 62
 2363            flattenedWaypoints = waypoints.ToArray();
 22664            for (int i = 0; i < flattenedWaypoints.Length; i++)
 9065                flattenedWaypoints[i].IsGoal = false;
 66
 2367            flattenedWaypoints[^1].IsGoal = true;
 2368            chartKeys = utilizedCharts.ToArray();
 2369            return true;
 70        }
 71        finally
 72        {
 7673            for (int i = 0; i < borrowedGuides.Count; i++)
 1274                ReturnBorrowedGuide(borrowedGuides[i]);
 2675        }
 2676    }
 77
 78    private static bool TryAppendSegmentWaypoints(
 79        HybridRouteStep step,
 80        SwiftList<AStarWaypoint> destination,
 81        SwiftList<IGuide> borrowedGuides,
 82        SwiftList<string> utilizedCharts,
 83        SwiftHashSet<string> utilizedChartSet,
 84        ref int pathCostOffset)
 85    {
 1886        AddChartKeys(utilizedCharts, utilizedChartSet, step.SegmentChartKeys);
 87
 1888        switch (step.SegmentRequest)
 89        {
 90            case AStarPathRequest aStarRequest:
 591                AStarSurveyResult aStarResult = aStarRequest.Context.Pathing.State.GuideState.AStarSurveyor.FindPath(aSt
 592                if (!aStarResult.HasPath)
 193                    return false;
 94
 495                AddChartKeys(utilizedCharts, utilizedChartSet, aStarResult.ChartsUtilized);
 496                AppendWaypoints(destination, aStarResult.Waypoints, ref pathCostOffset);
 497                return true;
 98
 99            case VolumePathRequest volumeRequest:
 12100                if (!volumeRequest.Context.Guides.RequestGuide(volumeRequest, out VolumeGuide? volumeGuide)
 12101                    || volumeGuide == null)
 0102                    return false;
 103
 12104                borrowedGuides.Add(volumeGuide);
 12105                if (volumeGuide.TrailMap != null)
 12106                    AddChartKeys(utilizedCharts, utilizedChartSet, volumeGuide.TrailMap.ChartsUtilized);
 107
 12108                AppendWaypoints(destination, volumeGuide.ActiveWaypoints, ref pathCostOffset);
 12109                return true;
 110
 111            default:
 1112                return false;
 113        }
 114    }
 115
 116    private static void ReturnBorrowedGuide(IGuide guide)
 117    {
 12118        TrailblazerWorldContext? context = guide switch
 12119        {
 0120            AStarGuide aStarGuide => aStarGuide.TrailMap.Context,
 0121            FlowFieldGuide flowFieldGuide => flowFieldGuide.FlowMap?.Context,
 12122            VolumeGuide volumeGuide => volumeGuide.TrailMap?.Context,
 0123            _ => null
 12124        };
 125
 12126        if (context == null)
 0127            throw new InvalidOperationException("Borrowed guide is missing its TrailblazerWorldContext.");
 128
 12129        context.Guides.ReturnGuide(guide);
 12130    }
 131
 132    private static void AppendWaypoints(
 133        SwiftList<AStarWaypoint> destination,
 134        AStarWaypoint[] waypoints,
 135        ref int pathCostOffset)
 136    {
 16137        if (waypoints == null)
 0138            return;
 139
 122140        for (int i = 0; i < waypoints.Length; i++)
 141        {
 45142            AStarWaypoint waypoint = waypoints[i];
 45143            waypoint.PathCost += pathCostOffset;
 45144            AppendWaypoint(destination, waypoint);
 145        }
 146
 16147        if (destination.Count > 0)
 16148            pathCostOffset = destination[destination.Count - 1].PathCost;
 16149    }
 150
 151    private static void AddChartKeys(
 152        SwiftList<string> destination,
 153        SwiftHashSet<string> utilizedChartSet,
 154        string[] charts)
 155    {
 34156        if (charts == null)
 0157            return;
 158
 214159        for (int i = 0; i < charts.Length; i++)
 160        {
 73161            string chart = charts[i];
 73162            if (string.IsNullOrEmpty(chart) || !utilizedChartSet.Add(chart))
 163                continue;
 164
 38165            destination.Add(chart);
 166        }
 34167    }
 168
 169    private static void AppendWaypoint(
 170        SwiftList<AStarWaypoint> destination,
 171        AStarWaypoint waypoint)
 172    {
 122173        if (destination.Count > 0)
 174        {
 99175            AStarWaypoint last = destination[destination.Count - 1];
 99176            if (last.GlobalIndex.HasValue
 99177                && waypoint.GlobalIndex.HasValue
 99178                && last.GlobalIndex.Value.Equals(waypoint.GlobalIndex.Value))
 179            {
 1180                return;
 181            }
 182
 98183            if (last.Position == waypoint.Position)
 31184                return;
 185        }
 186
 90187        waypoint.IsGoal = false;
 90188        destination.Add(waypoint);
 90189    }
 190}