Skip to content
Snippets Groups Projects
Select Git revision
  • 55af28e2fa0935d09988649d770b9daaf94290ab
  • master default
  • JS-based-scroll-rendering
  • Paul_Marius_Level
  • Paul_Marius_2
  • Paul_Marius
  • Andi_Mark
  • be-UnityWebView
  • gitignoreFrameitServer
  • ZimmerBSc
  • Bugfix_StageLoading
  • stages
  • MAZIFAU_Experimental
  • tsc/coneworld
  • tsc/fact-interaction
  • marcel
  • MaZiFAU_TopSort
  • mergeHelper
  • zwischenSpeichern
  • tempAndrToMaster
  • SebBranch
  • 3.0
  • v2.1
  • v2.0
  • v1.0
25 results

FactComparer.cs

Blame
  • FactComparer.cs 8.05 KiB
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using UnityEngine;
    
    /// <summary>
    /// Base class for all FactComparer to be used in conjucntion with <see cref="Stage.solution"/>
    /// <seealso cref="SolutionRecorder"/>
    /// <seealso cref="SolutionRecorder.ValidationSet"/>
    /// <seealso cref="FactRecorder.DynamiclySolved(SolutionRecorder, out System.Collections.Generic.List<System.Collections.Generic.List<string>>, out System.Collections.Generic.List<System.Collections.Generic.List<string>>)"/>
    /// </summary>
    public abstract class FactComparer : EqualityComparer<Fact>
    {
        /// <summary>defines parameter order for <see cref="Equals(Fact, Fact)"/></summary>
        protected bool search_righthanded;
    
        /// <summary>
        /// Implements criteria, by which <paramref name="fact"/> is beeing compared to <paramref name="solution"/>
        /// </summary>
        /// <param name="solution">to be fulfilled</param>
        /// <param name="fact">to be fulfilling</param>
        /// <returns><c>true</c> iff fact is described by solution</returns>
        protected abstract bool Compare (Fact solution, Fact fact);
    
        /// <summary>
        /// Called by <see cref="SetSearchLeft"/> and <see cref="SetSearchRight"/> to initate any class variables.
        /// </summary>
        protected abstract void Init();
    
        /// <summary>
        /// Sets <see cref="search_righthanded"/>, so that parameter order of <see cref="Equals(Fact, Fact)"/> is effectively:
        /// (<see cref="Compare(Fact, Fact).solution"/>, <see cref="Compare(Fact, Fact).fact"/>), 
        /// when a <see cref="ICollection<Fact>"/> is on the right hand side of an <see cref="System.Linq"/> operation
        /// </summary>
        /// <returns><c>this</c> object to be used</returns>
        public FactComparer SetSearchRight()
        {
            Init();
            search_righthanded = true;
            return this;
        }
        /// <summary>
        /// Sets <see cref="search_righthanded"/>, so that parameter order of <see cref="Equals(Fact, Fact)"/> is effectively:
        /// (<see cref="Compare(Fact, Fact).solution"/>, <see cref="Compare(Fact, Fact).fact"/>), 
        /// when a <see cref="ICollection<Fact>"/> is on the left hand side of an <see cref="System.Linq"/> operation
        /// </summary>
        /// <returns><c>this</c> object to be used</returns>
        public FactComparer SetSearchLeft()
        {
            Init();
            search_righthanded = false;
            return this;
        }
    
        /// <summary>
        /// Called by <see cref="System.Linq"/> iff <see cref="GetHashCode(Fact)"/> returns same result for both parameters <paramref name="left"/> and <paramref name="right"/>.
        /// <remarks>Always set correct search order *manually* beforehand, so that <see cref="Compare(Fact, Fact)"/> can return correct results.</remarks>
        /// <seealso cref="SetSearchRight"/>
        /// <seealso cref="SetSearchLeft"/>
        /// </summary>
        /// <param name="left">lefthand parameter</param>
        /// <param name="right">righthand parameter</param>
        /// <returns><c>search_righthanded ? Compare(left, right) : Compare(right, left);</c></returns>
        public override bool Equals(Fact left, Fact right)
        {
            return search_righthanded ? Compare(left, right) : Compare(right, left);
        }
    
        /// <summary>
        /// Called by <see cref="System.Linq"/> to check for possible fulfillment of each parameter before calling <see cref="Equals(Fact, Fact)"/> iff both results are the same.
        /// <remarks>Default implementation checks for sameness of runtime type, but may vary for subclasses.</remarks>
        /// </summary>
        /// <param name="obj">parameter of possible subsequent call of <see cref="Equals(Fact, Fact)"/></param>
        /// <returns></returns>
        public override int GetHashCode(Fact obj)
        {
            return obj.GetType().GetHashCode();
        }
    }
    
    /// <summary>
    /// Checks if both <see cref="Fact">Facts</see> are Equivalent, while accounting for Unity and floating point precission
    /// </summary>
    public class FactEquivalentsComparer : FactComparer
    {
        /// \copydoc FactEquivalentsComparer
        /// \copydoc FactComparer.Compare
        protected override bool Compare (Fact solution, Fact fact)
        {
            return solution.Equivalent(fact);
        }
    
        /// <summary> unused </summary>
        protected override void Init() { }
    }
    
    /// <summary>
    /// Checks <see cref="LineFact">LineFacts</see> if <see cref="Compare(Fact, Fact).fact"/> is of same direction and at least of same length as <see cref="Compare(Fact, Fact).solution"/>, while accounting for Unity and floating point precission
    /// <seealso cref="Math3d.vectorPrecission"/>
    /// </summary>
    class LineFactHightDirectionComparer : FactComparer
    {
        /// \copydoc LineFactHightDirectionComparer
        /// \copydoc FactComparer.Compare
        protected override bool Compare (Fact solution, Fact fact)
        {
            return fact is LineFact factLine && solution is LineFact solutionLine
                && Math3d.IsApproximatelyParallel(factLine.Dir, solutionLine.Dir)
                && factLine.Distance + Math3d.vectorPrecission >= solutionLine.Distance;
            // && Mathf.Approximately(((LineFact) x).Distance, ((LineFact) y).Distance);
        }
    
        /// <summary> unused </summary>
        protected override void Init() { }
    }
    
    /// <summary>
    /// Checks <see cref="LineFact">LineFacts</see> if <see cref="Compare(Fact, Fact).fact"/> is at least of same length as <see cref="Compare(Fact, Fact).solution"/>, while accounting for Unity and floating point precission
    /// <seealso cref="Math3d.vectorPrecission"/>
    /// </summary>
    class LineFactHightComparer : FactComparer
    {
        /// \copydoc LineFactHightDirectionComparer
        /// \copydoc FactComparer.Compare
        protected override bool Compare(Fact solution, Fact fact)
        {
            return fact is LineFact factLine && solution is LineFact solutionLine
                && factLine.Distance + Math3d.vectorPrecission >= solutionLine.Distance;
        }
    
        /// <summary> unused </summary>
        protected override void Init() { }
    }
    
    /// <summary>
    /// Checks <see cref="LineFact">LineFacts</see> if <see cref="Compare(Fact, Fact).fact"/> spanns over (not within) the river in RiverWorld.
    /// Needs a dummy <see cref="Compare(Fact, Fact).solution"/>.
    /// </summary>
    class LineSpanningOverRiverWorldComparer : FactComparer
    {
        /// <summary> Has collider defining area above the River in Riverworld </summary>
        private Collider RiverWallCollider;
    
        /// \copydoc LineFactHightDirectionComparer
        /// \copydoc FactComparer.Compare
        protected override bool Compare(Fact solution, Fact fact)
        {
            if (fact is not LineFact factLine)
                return false;
    
            // get positions of anker points
            Vector3[] point_pos =
                factLine.DependentFactIds
                .Select(id => FactRecorder.AllFacts[id].Position)
                .ToArray();
    
            // check anker points *not within* RiverWall
            if (!point_pos.All(posf => !Physics.OverlapSphere(posf, 0f).Contains(RiverWallCollider)))
                return false;
    
            // look for point left or right of RiverWall
            Physics.Raycast(point_pos[0], Vector3.back, out RaycastHit point_A_back, float.PositiveInfinity, LayerMask.GetMask("TransparentFX"));
            Physics.Raycast(point_pos[0], Vector3.forward, out RaycastHit point_A_forward, float.PositiveInfinity, LayerMask.GetMask("TransparentFX"));
            Physics.Raycast(point_pos[1], Vector3.back, out RaycastHit point_B_back, float.PositiveInfinity, LayerMask.GetMask("TransparentFX"));
            Physics.Raycast(point_pos[1], Vector3.forward, out RaycastHit point_B_forward, float.PositiveInfinity, LayerMask.GetMask("TransparentFX"));
    
            // check for one point left and the other one right of River Wall;
            return (point_A_back.collider == RiverWallCollider && point_B_forward.collider == RiverWallCollider)
                || (point_A_forward.collider == RiverWallCollider && point_B_back.collider == RiverWallCollider);
        }
    
        /// <summary> inits <see cref="RiverWallCollider"/> </summary>
        protected override void Init()
        {
            GameObject RiverWall = GameObject.Find("RiverWall");
            if (RiverWall == null)
                throw new MissingReferenceException("RiverWall not found");
    
            RiverWallCollider = RiverWall.GetComponent<MeshCollider>();
        }
    }