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> /// Standard Constructor: /// Initiates members and creates MMT %Fact Server-Side /// </summary> /// <param name="Function_SOMDoc">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_SOMDoc, (T0, T0) domain, FactOrganizer organizer) : base(organizer) { this.Function_SOMDoc = Function_SOMDoc; this.Domain = domain; this.Function_expression = this.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; RecalculateTransform(); return; } /// <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>; this._URI = uri; _ = this.Label; RecalculateTransform(); } protected override void RecalculateTransform() { } /// \copydoc Fact.parseFact(Scroll.ScrollFact) public new static FunctionFact<T0, TResult> 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 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); // && f1.domain.Equals(f2.domain); // no! => exact instead of similar => CRTP => false; protected override Fact _ReInitializeMe(Dictionary<string, string> old_to_new, FactOrganizer organizer) => new FunctionFact<T0, TResult>(this.Function_SOMDoc.MapURIs(old_to_new), this.Domain, organizer); protected override MMTDeclaration MakeMMTDeclaration() { throw new NotImplementedException(); } } /// <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(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}, FunctionFact{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(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) => 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); protected override Fact _ReInitializeMe(Dictionary<string, string> old_to_new, FactOrganizer organizer) => new FunctionFactFloat<TResult>(this.Function_SOMDoc.MapURIs(old_to_new), this.Domain, organizer); } public class AttachedPositionFunction : FactWrappedCRTP<AttachedPositionFunction> { public string fid; public string[] funcids; [JsonIgnore] public Fact Fact { get => FactOrganizer.AllFacts[fid]; } [JsonIgnore] public FunctionFact<float, Vector3>[] FunctionFacts { get => funcids.Select(f => FactOrganizer.AllFacts[f] as FunctionFact<float, Vector3>).ToArray(); } /// <summary>\copydoc Fact.Fact()</summary> public AttachedPositionFunction() : base() { } /// <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)) + "}"; RecalculateTransform(); } 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; RecalculateTransform(); } 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) => DependentFactsEquivalent(f1, f2); protected override void RecalculateTransform() { Position = Fact.Position; Rotation = Fact.Rotation; LocalScale = Fact.LocalScale; } protected override Fact _ReInitializeMe(Dictionary<string, string> old_to_new, FactOrganizer organizer) => new AttachedPositionFunction(old_to_new[this.fid], this.funcids.Select(id => old_to_new[id]).ToArray(), organizer); protected override MMTDeclaration MakeMMTDeclaration() { throw new NotImplementedException(); } }