Select Git revision
FunctionFact.cs
FunctionFact.cs 11.21 KiB
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
/// </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>;
this._URI = uri;
_ = this.Label;
RecalculateTransform();
}
/// <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;
RecalculateTransform();
return;
}
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);
}
/// <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);
}