Skip to content
Snippets Groups Projects
FunctionFact.cs 12.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • using System;
    using System.Collections.Generic;
    using UnityEngine;
    using Newtonsoft.Json;
    using static SOMDocManager;
    using System.Linq.Expressions;
    
    using System.Linq;
    using MoreLinq;
    using MoreLinq.Extensions;
    
    
    /// <summary>
    /// Represents a function taking Parameters (<typeparam name="T0">) and Returning <typeparam name="TResult">
    /// </summary>
    public class FunctionFact<T0, TResult> : FactWrappedCRTP<FunctionFact<T0, TResult>>
    {
        /// \copydoc Fact.s_type
        [JsonProperty]
        protected new string s_type = "FunctionFact<" + typeof(T0) + ", " + typeof(TResult) + ">";
    
        public SOMDoc Function_SOMDoc;
    
        //TODO: doc
        [JsonIgnore]
        public LambdaExpression Function_expression;
    
        [JsonIgnore]
        public Func<T0, TResult> Function;
    
        //TODO
        public (T0 t_0, T0 t_n) Domain = (default, default);
    
        /// <summary> \copydoc Fact.Fact </summary>
        public FunctionFact() : base() { }
    
        /// <summary>
        /// Copies <paramref name="fact"/> by initiating new MMT %Fact.
        /// </summary>
        /// <param name="fact">Fact to be copied</param>
        /// <param name="old_to_new"><c>Dictionary</c> mapping <paramref name="fact"/>.<see cref="getDependentFactIds"/> in <paramref name="fact"/>.<see cref="Fact._Facts"/> to corresponding <see cref="Fact.Id"/> in <paramref name="organizer"/> </param>
        /// <param name="organizer">sets <see cref="_Facts"/></param>
        public FunctionFact(FunctionFact<T0, TResult> fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, organizer)
    
            => init(fact.Function_SOMDoc.MapURIs(old_to_new), fact.Domain);
    
    
        /// <summary>
        /// Standard Constructor
        /// </summary>
        /// <param name="Function_MMT">sets <see cref="Function_SOMDoc"/> and contains the Abstract Syntax Tree</param>
        /// <param name="organizer">sets <see cref="Fact._Facts"/></param>
        public FunctionFact(SOMDoc Function_MMT, (T0, T0) domain, FactOrganizer organizer) : base(organizer)
            => init(Function_MMT, domain);
    
        /// <summary>
        /// Bypasses initialization of new MMT %Fact by using existend URI, _which is not checked for existence_.
        /// </summary>
        /// <param name="function_expression">sets <see cref="Function_expression"/> and contains the Abstract Syntax Tree</param>
        /// <param name="uri">MMT URI</param>
        /// <param name="organizer">sets <see cref="Fact._Facts"/></param>
    
        public FunctionFact(SOMDoc Function_SOMDoc, (T0, T0) domain, string uri, FactOrganizer organizer) : base(organizer)
    
            this.Function_SOMDoc = Function_SOMDoc;
            this.Domain = domain;
    
            this.Function_expression = Function_SOMDoc.GetReducedLambdaExpression();
            ////TODO: catch
            //string debug_tostring = Function_expression.ToString();
            //dynamic debug_function = Function_expression.Compile();
            this.Function = this.Function_expression.Compile() as Func<T0, TResult>;
    
        }
    
        /// <summary>
        /// Initiates <see cref="Function_SOMDoc"/>, <see cref="Function_expression"/>, <see cref="Function"/>, <see cref="Fact._URI"/> and creates MMT %Fact Server-Side
        /// </summary>
        /// <param name="Function_SOMDoc">sets <see cref="Function_SOMDoc"/> and contains the Abstract Syntax Tree</param>
        private void init(SOMDoc Function_SOMDoc, (T0, T0) domain)
        {
            this.Function_SOMDoc = Function_SOMDoc;
            this.Domain = domain;
    
            this.Function_expression = Function_SOMDoc.GetReducedLambdaExpression();
            ////TODO: catch
            //string debug_tostring = Function_expression.ToString();
            //dynamic debug_function = Function_expression.Compile();
            this.Function = this.Function_expression.Compile() as Func<T0, TResult>;
    
            //ducktaped:
            _URI = this.Function_expression.ToString() + domain.ToString();
    
            ////TODO: Function_SOMDoc+domain
    
            //MMTTerm tp = new OMS(JSONManager.MMTURIs.Point);
            //MMTTerm df = new OMA(new OMS(JSONManager.MMTURIs.Tuple), arguments);
    
            //AddFactResponse.sendAdd(new MMTSymbolDeclaration(Label, tp, df), out _URI);
    
            //ParsingDictionary.parseTermsToId[df.ToString()] = _URI;
    
    MaZiFAU's avatar
    MaZiFAU committed
        protected override void RecalulateTransform() { }
    
    
        /// \copydoc Fact.parseFact(Scroll.ScrollFact)
        public new static FunctionFact<T0, TResult> parseFact(Scroll.ScrollFact fact)
        {// TODO Correctness
    
            OMA df = (OMA)((Scroll.ScrollSymbolFact)fact).df;
    
            if (df == null)
                return null;
    
            string parse_id = df.ToString();
            if (!ParsingDictionary.parseTermsToId.ContainsKey(parse_id))
                ParsingDictionary.parseTermsToId[parse_id] = uri;
    
    
            return new FunctionFact<T0, TResult>(df, (default, default), uri, StageStatic.stage.factState);
    
        }
    
        /// \copydoc Fact.hasDependentFacts
        public override bool hasDependentFacts()
            => false;
    
        /// \copydoc Fact.getDependentFactIds
        public override string[] getDependentFactIds()
            => new string[] { };
    
        /// \copydoc Fact.GetHashCode
        public override int GetHashCode()
            => Function_expression.GetHashCode();
    
        /// \copydoc Fact.instantiateDisplay(GameObject, Transform)
        public override GameObject instantiateDisplay(GameObject prefab, Transform transform)
        {
            var obj = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity, transform);
            //obj.transform.GetChild(0).gameObject.GetComponent<TextMeshProUGUI>().text = this.Label;
            //obj.GetComponent<FactWrapper>().fact = this;
            return obj;
        }
    
        /// \copydoc Fact.EquivalentWrapped
        protected override bool EquivalentWrapped(FunctionFact<T0, TResult> f1, FunctionFact<T0, TResult> f2)
            //=> f1.Function_SOMDoc.Equivalent(f2.Function_SOMDoc);
            => false;
        //  && f1.domain.Equals(f2.domain); // no! => exact instead of similar => CRTP
    }
    
    /// <summary>
    /// Implements CRTP for <see cref="FunctionFact"/>; Escalates constructors;
    /// </summary>
    
    /// <typeparam name="CRTP">class, which inherits from FunctionFactCRTP</typeparam>
    
    public abstract class FunctionFactCRTP<CRTP, T0, TResult> : FunctionFact<T0, TResult> where CRTP : FunctionFactCRTP<CRTP, T0, TResult>
    {
        /// <summary> \copydoc FunctionFact.FunctionFact </summary>
        protected FunctionFactCRTP() : base() { }
    
        /// <summary> \copydoc FunctionFact.FunctionFact(FunctionFact{T0, TResult} fact, Dictionary{string, string} old_to_new, FactOrganizer organizer) </summary>
        protected FunctionFactCRTP(FunctionFactCRTP<CRTP, T0, TResult> fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, old_to_new, organizer) { }
    
        /// <summary> \copydoc FunctionFact.FunctionFact(SOMDoc, Tuple{T0, T0}, FactOrganizer) </summary>
        protected FunctionFactCRTP(SOMDoc Function_MMT, (T0, T0) domain, FactOrganizer organizer) : base(Function_MMT, domain, organizer) { }
    
        /// <summary> \copydoc FunctionFact.FunctionFact(LambdaExpression, string, FactOrganizer) </summary>
    
        protected FunctionFactCRTP(SOMDoc Function_MMT, (T0, T0) domain, string uri, FactOrganizer organizer) : base(Function_MMT, domain, uri, organizer) { }
    
    
        /// \copydoc Fact.Equivalent(Fact, Fact)
        protected override bool EquivalentWrapped(FunctionFact<T0, TResult> f1, FunctionFact<T0, TResult> f2)
            => EquivalentWrapped((CRTP)f1, (CRTP)f2)
            && base.EquivalentWrapped(f1, f2);
    
        /// <summary>CRTP step of <see cref="EquivalentWrapped(FunctionFact{T0, TResult}, AbstractLineFact{T0, TResult})"/></summary>
        protected abstract bool EquivalentWrapped(CRTP f1, CRTP f2);
    }
    
    /// <summary>
    /// Used to overrite FunctionFact.EquivalentWrapped for special case T0 = float
    /// </summary>
    public class FunctionFactFloat<TResult> : FunctionFactCRTP<FunctionFactFloat<TResult>, float, TResult>
    {
        /// <summary> \copydoc FunctionFact.FunctionFact </summary>
        public FunctionFactFloat() : base() { }
    
        /// <summary> \copydoc FunctionFact.FunctionFact(FunctionFact{T0, TResult} fact, Dictionary{string, string} old_to_new, FactOrganizer organizer) </summary>
        public FunctionFactFloat(FunctionFactFloat<TResult> fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, old_to_new, organizer) { }
    
        /// <summary> \copydoc FunctionFact.FunctionFact(SOMDoc, Tuple{T0, T0}, FactOrganizer) </summary>
        public FunctionFactFloat(SOMDoc Function_MMT, (float, float) domain, FactOrganizer organizer) : base(Function_MMT, domain, organizer) { }
    
        /// <summary> \copydoc FunctionFact.FunctionFact(LambdaExpression, string, FactOrganizer) </summary>
    
        public FunctionFactFloat(SOMDoc Function_MMT, (float, float) domain, string uri, FactOrganizer organizer) : base(Function_MMT, domain, uri, organizer) { }
    
    
        /// \copydoc Fact.EquivalentWrapped
        protected override bool EquivalentWrapped(FunctionFactFloat<TResult> f1, FunctionFactFloat<TResult> f2)
    
    MaZiFAU's avatar
    MaZiFAU committed
            => f1.Function_SOMDoc.Equivalent(f2.Function_SOMDoc)
            && f1.Domain.t_0.IsApproximatelyEqual(f2.Domain.t_0)
    
            && f1.Domain.t_n.IsApproximatelyEqual(f2.Domain.t_n);
    }
    
    
    public class AttachedPositionFunction : FactWrappedCRTP<AttachedPositionFunction>
    {
        public string fid;
    
        public string[] funcids;
    
        [JsonIgnore]
    
    MaZiFAU's avatar
    MaZiFAU committed
        public Fact Fact { get => FactOrganizer.AllFacts[fid]; }
    
        [JsonIgnore]
        public FunctionFact<float, Vector3>[] FunctionFacts { 
    
    MaZiFAU's avatar
    MaZiFAU committed
            get => funcids.Select(f => FactOrganizer.AllFacts[f] as FunctionFact<float, Vector3>).ToArray(); 
    
        }
    
        /// <summary>\copydoc Fact.Fact()</summary>
        public AttachedPositionFunction() : base() { }
    
        /// <summary>\copydoc Fact.Fact(Fact, FactOrganizer)</summary>
        public AttachedPositionFunction(AttachedPositionFunction fact, Dictionary<string, string> old_to_new, FactOrganizer organizer) : base(fact, organizer)
            => init(old_to_new[fact.fid], fact.funcids.Select(id => old_to_new[id]).ToArray());
    
        /// <summary>\copydoc Fact.Fact(FactOrganizer)</summary>
        public AttachedPositionFunction(string fid, string[] funcids, FactOrganizer organizer) : base(organizer)
            => init(fid, funcids);
    
        private void init(string fid, string[] funcids)
        {
            this.fid = fid;
    
            this.funcids = new string[funcids.Length];
            funcids.CopyTo(this.funcids, 0);
    
            //TODO: call MMT, set URI
            _URI = Fact.Id + "{" + string.Join(", ", FunctionFacts.Select(f => f.Id)) + "}";
    
            RecalulateTransform();
        }
    
        protected AttachedPositionFunction(string fid, string[] funcids, string uri, FactOrganizer organizer) : base(organizer)
        {
            this.fid = fid;
    
            this.funcids = new string[funcids.Length];
            funcids.CopyTo(this.funcids, 0);
    
            _URI = uri;
    
            RecalulateTransform();
        }
    
        public new static AttachedPositionFunction parseFact(Scroll.ScrollFact fact)
        {// TODO Correctness
            string uri = fact.@ref.uri;
            OMA df = (OMA)((Scroll.ScrollSymbolFact)fact).df;
    
            if (df == null)
                return null;
    
            string parse_id = df.ToString();
            if (!ParsingDictionary.parseTermsToId.ContainsKey(parse_id))
                ParsingDictionary.parseTermsToId[parse_id] = uri;
    
            return new AttachedPositionFunction(default, default, uri, StageStatic.stage.factState);
        }
    
        public override string[] getDependentFactIds()
        {
            string[] ret = new string[1 + funcids.Length];
            funcids.CopyTo(ret, 1);
            ret[0] = fid;
    
            return ret;
        }
    
        public override int GetHashCode()
            => Fact.GetHashCode() ^ FunctionFacts.GetHashCode();
    
        public override bool hasDependentFacts()
            => true;
    
        public override GameObject instantiateDisplay(GameObject prefab, Transform transform)
        {
            var obj = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity, transform);
            //obj.transform.GetChild(0).gameObject.GetComponent<TextMeshProUGUI>().text = this.Label;
            //obj.GetComponent<FactWrapper>().fact = this;
            return obj;
        }
    
        protected override bool EquivalentWrapped(AttachedPositionFunction f1, AttachedPositionFunction f2)
    
    MaZiFAU's avatar
    MaZiFAU committed
            => DependentFactsEquivalent(f1, f2);
    
    
        protected override void RecalulateTransform()
        {
            Position = Fact.Position;
            Rotation = Fact.Rotation;
            LocalScale = Fact.LocalScale;
        }
    }