< Summary

Information
Class: Trailblazer.Pathing.PathQueryRecord
Assembly: Trailblazer
File(s): /home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Navigation/Steering/Serialization/PathQueryRecord.cs
Line coverage
100%
Covered lines: 120
Uncovered lines: 0
Coverable lines: 120
Total lines: 228
Line coverage: 100%
Branch coverage
100%
Covered branches: 24
Total branches: 24
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%
.ctor(...)100%11100%
Capture(...)100%11100%
TryCreateQuery(...)100%1818100%
RecordData(...)100%66100%

File(s)

/home/runner/work/Trailblazer/Trailblazer/src/Trailblazer/Navigation/Steering/Serialization/PathQueryRecord.cs

#LineLine coverage
 1//=======================================================================
 2// PathQueryRecord.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 Chronicler;
 10using FixedMathSharp;
 11using Trailblazer.Navigation;
 12
 13namespace Trailblazer.Pathing;
 14
 15/// <summary>Records exact durable graph-query intent.</summary>
 16public sealed class PathQueryRecord : IRecordable
 17{
 18    private const int CurrentSchemaVersion = 1;
 19
 20    private int SchemaVersion;
 21
 22    private Vector3d StartPosition;
 23
 24    private string? StartMapId;
 25
 26    private EndpointResolutionPolicy StartResolution;
 27
 28    private Fixed64 StartMaxResolutionDistance;
 29
 30    private Vector3d EndPosition;
 31
 32    private string? EndMapId;
 33
 34    private EndpointResolutionPolicy EndResolution;
 35
 36    private Fixed64 EndMaxResolutionDistance;
 37
 4638    private NavigationAgentProfileRecord Agent = new();
 39
 40    private string? AreaPolicyId;
 41
 42    private long AreaPolicyRevision;
 43
 44    private TraversalMedium StartMedium;
 45
 46    private TraversalMedia TargetMedia;
 47
 48    private PathAlgorithm Algorithm;
 49
 50    private int MaxLookupProbes;
 51
 52    private int MaxEndpointCandidates;
 53
 54    private int MaxExpandedNodes;
 55
 56    private int MaxEvaluatedEdges;
 57
 58    private int MaxConnectionLegs;
 59
 60    private int MaxTransitionCandidates;
 61
 62    private int MaxTransitionPairs;
 63
 64    private int MaxStagedLegAttempts;
 65
 66    private int MaxTraceIntervals;
 67
 68    private int MaxCoveredVoxelIntervals;
 69
 70    private int MaxSimplificationRays;
 71
 72    private bool AllowTransitions;
 73
 74    private Fixed64 ExtraIntegrationCost;
 75
 76    /// <summary>Creates an empty shell for a populate-existing-instance Chronicler load.</summary>
 677    public PathQueryRecord()
 78    {
 679    }
 80
 81    /// <summary>Creates a record containing one exact immutable query.</summary>
 8082    public PathQueryRecord(PathQuery query) => Capture(query);
 83
 84    /// <summary>Gets the exact query after construction or a successful load.</summary>
 85    public PathQuery? Query { get; private set; }
 86
 87    private void Capture(PathQuery query)
 88    {
 6289        SchemaVersion = CurrentSchemaVersion;
 6290        PathQuery value = query;
 6291        Query = value;
 6292        StartPosition = value.Start.Position;
 6293        StartMapId = value.Start.MapId;
 6294        StartResolution = value.Start.Resolution;
 6295        StartMaxResolutionDistance = value.Start.MaxResolutionDistance;
 6296        EndPosition = value.End.Position;
 6297        EndMapId = value.End.MapId;
 6298        EndResolution = value.End.Resolution;
 6299        EndMaxResolutionDistance = value.End.MaxResolutionDistance;
 62100        Agent.Capture(value.Agent);
 62101        AreaPolicyId = value.AreaPolicy.PolicyId;
 62102        AreaPolicyRevision = value.AreaPolicy.Revision;
 62103        StartMedium = value.Traversal.StartMedium;
 62104        TargetMedia = value.Traversal.TargetMedia;
 62105        Algorithm = value.Algorithm;
 62106        MaxLookupProbes = value.Budget.MaxLookupProbes;
 62107        MaxEndpointCandidates = value.Budget.MaxEndpointCandidates;
 62108        MaxExpandedNodes = value.Budget.MaxExpandedNodes;
 62109        MaxEvaluatedEdges = value.Budget.MaxEvaluatedEdges;
 62110        MaxConnectionLegs = value.Budget.MaxConnectionLegs;
 62111        MaxTransitionCandidates = value.Budget.MaxTransitionCandidates;
 62112        MaxTransitionPairs = value.Budget.MaxTransitionPairs;
 62113        MaxStagedLegAttempts = value.Budget.MaxStagedLegAttempts;
 62114        MaxTraceIntervals = value.Budget.MaxTraceIntervals;
 62115        MaxCoveredVoxelIntervals = value.Budget.MaxCoveredVoxelIntervals;
 62116        MaxSimplificationRays = value.Budget.MaxSimplificationRays;
 62117        AllowTransitions = value.AllowTransitions;
 62118        ExtraIntegrationCost = value.FlowField.ExtraIntegrationCost;
 62119    }
 120
 121    private bool TryCreateQuery(out PathQuery? query)
 122    {
 22123        query = null;
 22124        if (SchemaVersion != CurrentSchemaVersion
 22125            || Algorithm is not PathAlgorithm.AStar and not PathAlgorithm.FlowField
 22126            || !TraversalTransitionDefinition.IsKnownMedium(StartMedium)
 22127            || TargetMedia == TraversalMedia.None
 22128            || (TargetMedia & ~NavigationCell.KnownMedia) != 0
 22129            || string.IsNullOrWhiteSpace(AreaPolicyId)
 22130            || !Agent.TryCreate(out NavigationAgentProfile profile))
 131        {
 16132            return false;
 133        }
 134
 135        try
 136        {
 6137            query = new PathQuery(
 6138                new NavigationEndpoint(
 6139                    StartPosition,
 6140                    StartMapId,
 6141                    StartResolution,
 6142                    StartMaxResolutionDistance),
 6143                new NavigationEndpoint(
 6144                    EndPosition,
 6145                    EndMapId,
 6146                    EndResolution,
 6147                    EndMaxResolutionDistance),
 6148                profile,
 6149                new NavigationAreaPolicyKey(AreaPolicyId!, AreaPolicyRevision),
 6150                new TraversalIntent(StartMedium, TargetMedia),
 6151                Algorithm,
 6152                new NavigationWorkBudget(
 6153                    MaxLookupProbes,
 6154                    MaxEndpointCandidates,
 6155                    MaxExpandedNodes,
 6156                    MaxEvaluatedEdges,
 6157                    MaxConnectionLegs,
 6158                    MaxTransitionCandidates,
 6159                    MaxTransitionPairs,
 6160                    MaxStagedLegAttempts,
 6161                    MaxTraceIntervals,
 6162                    MaxCoveredVoxelIntervals,
 6163                    MaxSimplificationRays),
 6164                AllowTransitions,
 6165                Algorithm == PathAlgorithm.FlowField
 6166                    ? new FlowFieldQueryOptions(ExtraIntegrationCost)
 6167                    : default);
 4168            return true;
 169        }
 2170        catch (ArgumentException)
 171        {
 2172            return false;
 173        }
 6174    }
 175
 176    /// <inheritdoc />
 177    public void RecordData(IChronicler chronicler)
 178    {
 46179        bool isLoading = chronicler.Mode == SerializationMode.Loading;
 46180        if (!isLoading)
 181        {
 24182            PathQuery? query = Query;
 24183            SwiftThrowHelper.ThrowIfTrue(
 24184                !query.HasValue,
 24185                message: "PathQueryRecord must contain a query before it can be serialized.");
 186
 22187            Capture(query.Value);
 188        }
 189
 44190        RecordValues.Look(chronicler, ref SchemaVersion, "SchemaVersion", 0);
 44191        RecordValues.Look(chronicler, ref StartPosition, "StartPosition", Vector3d.Zero);
 44192        RecordValues.Look(chronicler, ref StartMapId, "StartMapId", null);
 44193        RecordValues.Look(chronicler, ref StartResolution, "StartResolution", EndpointResolutionPolicy.Strict);
 44194        RecordValues.Look(chronicler, ref StartMaxResolutionDistance, "StartMaxResolutionDistance", Fixed64.Zero);
 44195        RecordValues.Look(chronicler, ref EndPosition, "EndPosition", Vector3d.Zero);
 44196        RecordValues.Look(chronicler, ref EndMapId, "EndMapId", null);
 44197        RecordValues.Look(chronicler, ref EndResolution, "EndResolution", EndpointResolutionPolicy.Strict);
 44198        RecordValues.Look(chronicler, ref EndMaxResolutionDistance, "EndMaxResolutionDistance", Fixed64.Zero);
 44199        RecordDeep.Look(chronicler, ref Agent, "Agent");
 44200        RecordValues.Look(chronicler, ref AreaPolicyId, "AreaPolicyId", null);
 44201        RecordValues.Look(chronicler, ref AreaPolicyRevision, "AreaPolicyRevision", 0L);
 44202        RecordValues.Look(chronicler, ref StartMedium, "StartMedium", TraversalMedium.Unknown);
 44203        RecordValues.Look(chronicler, ref TargetMedia, "TargetMedia", TraversalMedia.None);
 44204        RecordValues.Look(chronicler, ref Algorithm, "Algorithm", PathAlgorithm.AStar);
 44205        RecordValues.Look(chronicler, ref MaxLookupProbes, "MaxLookupProbes", 0);
 44206        RecordValues.Look(chronicler, ref MaxEndpointCandidates, "MaxEndpointCandidates", 0);
 44207        RecordValues.Look(chronicler, ref MaxExpandedNodes, "MaxExpandedNodes", 0);
 44208        RecordValues.Look(chronicler, ref MaxEvaluatedEdges, "MaxEvaluatedEdges", 0);
 44209        RecordValues.Look(chronicler, ref MaxConnectionLegs, "MaxConnectionLegs", 0);
 44210        RecordValues.Look(chronicler, ref MaxTransitionCandidates, "MaxTransitionCandidates", 0);
 44211        RecordValues.Look(chronicler, ref MaxTransitionPairs, "MaxTransitionPairs", 0);
 44212        RecordValues.Look(chronicler, ref MaxStagedLegAttempts, "MaxStagedLegAttempts", 0);
 44213        RecordValues.Look(chronicler, ref MaxTraceIntervals, "MaxTraceIntervals", 0);
 44214        RecordValues.Look(chronicler, ref MaxCoveredVoxelIntervals, "MaxCoveredVoxelIntervals", 0);
 44215        RecordValues.Look(chronicler, ref MaxSimplificationRays, "MaxSimplificationRays", 0);
 44216        RecordValues.Look(chronicler, ref AllowTransitions, "AllowTransitions", false);
 44217        RecordValues.Look(chronicler, ref ExtraIntegrationCost, "ExtraIntegrationCost", Fixed64.Zero);
 218
 44219        if (isLoading)
 220        {
 22221            SwiftThrowHelper.ThrowIfTrue(
 22222                !TryCreateQuery(out PathQuery? query) || !query.HasValue,
 22223                message: "Serialized PathQuery is missing, invalid, or unsupported.");
 224
 4225            Query = query.Value;
 226        }
 26227    }
 228}