Rides/TrackRides/TrackElementFilter.cs
using System;
namespace HC3.Rides;
#nullable enable
/// <summary>
/// Used by <see cref="TrackBuilder"/> to search for track elements.
/// </summary>
/// <param name="Direction">Should the track turn left / right, or go straight?</param>
/// <param name="Banking">What angle should the track bank at?</param>
/// <param name="Incline">What angle should the track climb / descend at?</param>
/// <param name="Feature">Should the track have a special feature, like a lift hill?</param>
public readonly record struct TrackElementFilter(
TurnDirection Direction = TurnDirection.Straight,
TrackBanking Banking = TrackBanking.None,
TrackIncline Incline = TrackIncline.None,
TrackFeature Feature = TrackFeature.None ) : IComparable<TrackElementFilter>
{
/// <summary>
/// Test if the given <paramref name="element"/> matches this filter.
/// </summary>
public bool IsMatch( TrackElement element ) =>
element.Definition.Feature == Feature &&
element.Direction == Direction &&
element.EndBanking == Banking &&
element.GetInclineCategory( TrackBuildKind.Append ) == Incline;
/// <summary>
/// Comparison for sorting track elements, ranking flat level track first.
/// </summary>
public int CompareTo( TrackElementFilter other )
{
var inclineComparison = Incline.Ordinal().CompareTo( other.Incline.Ordinal() );
if ( inclineComparison != 0 )
{
return inclineComparison;
}
var directionComparison = Direction.Ordinal().CompareTo( other.Direction.Ordinal() );
if ( directionComparison != 0 )
{
return directionComparison;
}
var bankingComparison = Banking.Ordinal().CompareTo( other.Banking.Ordinal() );
if ( bankingComparison != 0 )
{
return bankingComparison;
}
return Feature.CompareTo( other.Feature );
}
/// <summary>
/// How different is <paramref name="other"/> from this filter?
/// Weighted to prefer similar inclines, then turn directions, then banking, and cares least about features.
/// </summary>
public int GetDistance( TrackElementFilter other )
{
var dist = 0;
dist += Feature == other.Feature ? 0 : 1;
dist += Math.Abs( Banking.CompareTo( other.Banking ) ) * 2;
dist += Math.Abs( Direction.CompareTo( other.Direction ) ) * 4;
dist += Math.Abs( Incline.CompareTo( other.Incline ) ) * 8;
return dist;
}
/// <summary>
/// Find the filter that would match the given <paramref name="element"/>.
/// </summary>
public static TrackElementFilter FromElement( TrackElement element, TrackBuildKind kind = TrackBuildKind.Append )
{
return kind == TrackBuildKind.Append
? new TrackElementFilter(
element.Direction,
element.EndBanking,
element.GetInclineCategory( kind ),
element.Definition.Feature )
: new TrackElementFilter(
element.Direction.Inverse(),
element.StartBanking.Inverse(),
element.GetInclineCategory( kind ),
element.Definition.Feature );
}
}