From 6073913f51f58f6f422ff2f4190e582b1df3f2be Mon Sep 17 00:00:00 2001
From: MaZiFAU <63099053+MaZiFAU@users.noreply.github.com>
Date: Sun, 24 Sep 2023 17:59:23 +0200
Subject: [PATCH] BugFixes; Performance;

BugFixes;
+ Saving/Loading
+ Fetching Context somtimes skipped a fact

Performance;
+ Dynamic Types will now try to simplify before SendToMMT()
+ Caching of Stages know activated
---
 Assets/Scripts/GlobalBehaviour.cs             |  4 +++
 .../FactHandling/FactRecorder.cs              | 11 +++---
 .../FactHandling/Facts/Fact.cs                | 15 ++++----
 .../FactHandling/Facts/MMTTypes.cs            | 34 ++++++++++++++-----
 .../Scripts/InventoryStuff/ScrollDetails.cs   |  4 +--
 Assets/Scripts/Loading/Stage.cs               | 34 +++++++------------
 .../SOMDocToLambdaExpression.cs               |  3 +-
 Assets/Scripts/StageStatic.cs                 | 14 ++++----
 .../UI/MainMenue/PageLoader/EditLoader.cs     |  7 ----
 9 files changed, 66 insertions(+), 60 deletions(-)

diff --git a/Assets/Scripts/GlobalBehaviour.cs b/Assets/Scripts/GlobalBehaviour.cs
index 05a0495f..9d76c011 100644
--- a/Assets/Scripts/GlobalBehaviour.cs
+++ b/Assets/Scripts/GlobalBehaviour.cs
@@ -137,6 +137,7 @@ IEnumerator _GetScrollsfromServer()
 
     public static FactRecorder Context = new();
     public static IEnumerator InitiateContext = IEnumeratorExtensions.yield_break;
+    public static bool ContextLoaded = false;
 
     private void GetContextfromServer()
     {
@@ -144,6 +145,8 @@ private void GetContextfromServer()
 
         IEnumerator _GetContextfromServer()
         {
+            ContextLoaded = false;
+
             System.DateTime requestTime = System.DateTime.UtcNow;
             UnityWebRequest request = null;
             for (int i = 0; i < this.tryScrollListTimes; i++)
@@ -236,6 +239,7 @@ IEnumerator _GetContextfromServer()
                 $"FactAdding\t{justAddinTime.Millisecond}ms\n" +
                 "");
 
+            ContextLoaded = true;
             yield break;
         }
     }
diff --git a/Assets/Scripts/InteractionEngine/FactHandling/FactRecorder.cs b/Assets/Scripts/InteractionEngine/FactHandling/FactRecorder.cs
index f4e3263b..376c0e8e 100644
--- a/Assets/Scripts/InteractionEngine/FactHandling/FactRecorder.cs
+++ b/Assets/Scripts/InteractionEngine/FactHandling/FactRecorder.cs
@@ -402,11 +402,12 @@ Fact ReInitializeFact(string old_id)
             if (_old_to_new.TryGetValue(old_id, out string newId))
                 return target[newId];
 
-            if (AllFacts.TryGetValue(old_id, out Fact found))
-                return found;
-
             Fact old_Fact = source.JsonFactSpace[old_id];
 
+            if (AllFacts.TryGetValue(old_id, out Fact found)
+             && found.Equivalent(old_Fact))
+                return found;
+
             if (!old_Fact.DependentFactIds.All(id => _old_to_new.ContainsKey(id)))
             {
                 Debug.LogWarningFormat("Could not Instantiate " /*Immutable*/+ "Fact: {0}. Trying to compensate...", old_Fact);
@@ -579,8 +580,8 @@ public string Add(Fact value, out bool exists, bool samestep, Gadget gadget, str
             if (AllFacts.TryGetValue(value.Id, out Fact found))
                 value = found;
             //else
-            if (value._LastLabel != value.GetLabel(this) // Dirty Fix for Server caching wrong label
-             || !value.HasServerTwin)
+            if (!value.HasServerTwin
+             || value._LastLabel != value.GetLabel(this)) // Dirty Fix for Server caching wrong label
             {
                 value.GetLabel(this); // initialize label
                 value.SendToMMT();
diff --git a/Assets/Scripts/InteractionEngine/FactHandling/Facts/Fact.cs b/Assets/Scripts/InteractionEngine/FactHandling/Facts/Fact.cs
index ce4e25ba..698b1fe3 100644
--- a/Assets/Scripts/InteractionEngine/FactHandling/Facts/Fact.cs
+++ b/Assets/Scripts/InteractionEngine/FactHandling/Facts/Fact.cs
@@ -117,7 +117,7 @@ public Expression CompileBase
         get
         {
             if (_CompileBase == null)
-                CompileValue();
+                CompileValue(HasServerTwin ? Defines() : ServerDefinition);
             return _CompileBase;
         }
 
@@ -132,15 +132,13 @@ public object CompiledValue
         protected set => _CompiledValue = value;
     }
     private object _CompiledValue;
-    protected virtual object GetCompiledValue() => CompileValue(); // put to abstract, once we know what to do with every Fact
+    protected virtual object GetCompiledValue()  // put to abstract, once we know what to do with every Fact
+        => CompileValue(HasServerTwin ? Defines() : ServerDefinition);
 
-    protected object CompileValue()
+    protected object CompileValue(SOMDoc compile_me)
     {
         Func<object[], object[]> builder =
-            (HasServerTwin // otherwise: self-referencing
-            ? Defines()
-            : ServerDefinition)
-            .PartialInvokeCastingLambdaExpression(out _CompileBase, out Type[] Signature);
+            compile_me.PartialInvokeCastingLambdaExpression(out _CompileBase, out Type[] Signature);
 
         if (Signature.Length != 1)
             throw new InvalidCastException($"{nameof(ServerDefinition)} does not compile to constant!");
@@ -468,10 +466,11 @@ public void freeAutoLabel(FactRecorder name_space)
         }
     }
 
-    private static List<Type> ServerBlacklist = new()
+    private static readonly List<Type> ServerBlacklist = new()
     {
         typeof(FunctionFact),
         typeof(FunctionCallFact),
+        //typeof(DynamicListFact),
     };
 
     private bool SendedToMMT = false;
diff --git a/Assets/Scripts/InteractionEngine/FactHandling/Facts/MMTTypes.cs b/Assets/Scripts/InteractionEngine/FactHandling/Facts/MMTTypes.cs
index 9b3fdc9d..5042da9c 100644
--- a/Assets/Scripts/InteractionEngine/FactHandling/Facts/MMTTypes.cs
+++ b/Assets/Scripts/InteractionEngine/FactHandling/Facts/MMTTypes.cs
@@ -16,7 +16,7 @@
 /// <remarks>Needed to refere to lists serverside</remarks>
 public class ListFact : FactWrappedCRTP<ListFact>
 {
-    protected override object GetCompiledValue() => CompileValue();
+    protected override object GetCompiledValue() => CompileValue(Defines());
 
     public string[] lids = new string[0];
 
@@ -168,7 +168,7 @@ protected override bool EquivalentWrapped(ListFact f1, ListFact f2)
 
 public class DynamicListFact : FactWrappedCRTP<DynamicListFact>, IUnpackable
 {
-    protected override object GetCompiledValue() => CompileValue();
+    protected override object GetCompiledValue() => CompileValue(indirect_payload);
 
     [JsonIgnore]
     public List<object> payload;
@@ -231,7 +231,7 @@ public static List<Fact> MMTFactory(List<dynamic> payload, SOMDoc indirect_paylo
             ListType = ListType,
         }};
 
-        if(CompileBase != null)
+        if (CompileBase != null)
             (ret[0] as DynamicListFact).CompileBase = CompileBase;
 
         if (_ServerDefinition != null)
@@ -246,7 +246,16 @@ public override MMTFact MakeMMTDeclaration()
         : new MMTGeneralFact(_LastLabel, ListType, Defines());
 
     public override SOMDoc Defines()
-        => indirect_payload;
+    {
+        try
+        {
+            return SOMDoc.SOMDocObject(CompiledValue);
+        }
+        catch (Exception)
+        {
+            return indirect_payload;
+        }
+    }
 
     public new static IEnumerator parseFact(List<Fact> ret, MMTFact fact)
     {
@@ -284,7 +293,7 @@ protected override string[] GetDependentFactIds()
     protected override void RecalculateTransform() { }
 
     protected override Fact _ReInitializeMe(Dictionary<string, string> old_to_new)
-        => MMTFactory(payload, indirect_payload?.MapURIs(old_to_new), ListType, ServerDefinition)
+        => MMTFactory(payload, indirect_payload?.MapURIs(old_to_new), ListType) //, ServerDefinition?.MapURIs(old_to_new))
             .FirstOrDefault();
 
     public IEnumerator UnpackMe(List<Fact> ret, bool BypassServer)
@@ -304,7 +313,7 @@ public IEnumerator UnpackMe(List<Fact> ret, bool BypassServer)
 /// <remarks>Needed to refere to tupels serverside</remarks>
 public class TupleFact : FactWrappedCRTP<TupleFact>
 {
-    protected override object GetCompiledValue() => CompileValue();
+    protected override object GetCompiledValue() => CompileValue(Defines());
 
     public string[] lids = new string[0];
 
@@ -492,7 +501,16 @@ public override MMTFact MakeMMTDeclaration()
         : new MMTGeneralFact(_LastLabel, GetMMTType(), Defines());
 
     public override SOMDoc Defines()
-        => indirect_payload;
+    {
+        try
+        {
+            return SOMDoc.SOMDocObject(CompiledValue);
+        }
+        catch (NotSupportedException)
+        {
+            return indirect_payload;
+        }
+    }
 
     public override SOMDoc GetMMTType()
         => TupleType;
@@ -615,7 +633,7 @@ protected override Fact _ReInitializeMe(Dictionary<string, string> old_to_new)
 
 public class GeneralFact : FactWrappedCRTP<GeneralFact>
 {
-    protected override object GetCompiledValue() => CompileValue();
+    protected override object GetCompiledValue() => CompileValue(Defines());
 
     public MMTFact Raw { get; private set; }
 
diff --git a/Assets/Scripts/InventoryStuff/ScrollDetails.cs b/Assets/Scripts/InventoryStuff/ScrollDetails.cs
index 9e26a9fb..b5651ac5 100644
--- a/Assets/Scripts/InventoryStuff/ScrollDetails.cs
+++ b/Assets/Scripts/InventoryStuff/ScrollDetails.cs
@@ -44,9 +44,7 @@ public static ScrollDetails Instance
     private bool MagicInQue = false;
 
     private readonly IReadOnlyList<string> NoDynamicScroll = new List<string>() {
-        MMTConstants.ScrollCannonBall2D,
-        MMTConstants.ScrollCannonBall3D,
-        MMTConstants.ScrollCannonBallT3D,
+        // Insert ScrollURIS that are poorly optimized
     };
 
     void Awake()
diff --git a/Assets/Scripts/Loading/Stage.cs b/Assets/Scripts/Loading/Stage.cs
index 6c81cf64..9e00f966 100644
--- a/Assets/Scripts/Loading/Stage.cs
+++ b/Assets/Scripts/Loading/Stage.cs
@@ -74,6 +74,8 @@ public PlayerRecord player_record
         }
     }
 
+    private string record_index;
+
     /// <summary>
     /// A list containing all saved player progress. <br/>
     /// - Key: name of file
@@ -256,7 +258,8 @@ public bool set_record(string record_index)
         player_record.name = record_name;
 
         player_record.solved = false;
-        store(false);
+        this.record_index = record_index;
+        //store(false);
         return true;
     }
 
@@ -373,8 +376,9 @@ public static bool ShallowLoad(out Stage set, string path)
 
         DateTime t_PP = DateTime.Now;
 
-        // ignore output:
-        IJSONsavable<Stage>.load_children(null /*hierarchie*/, set.name, ref set, post_process: false);
+        if(!IJSONsavable<Stage>.load_children(null /*hierarchie*/, set.name, ref set, post_process: true))
+            _ = set.player_record; //init
+        set.player_record.CopyExposedSolutionFacts(set);
 
         Debug.Log("Raw: " + path + "\n\t " + (t_R - t_0).TotalMilliseconds + "ms\n" +
             "PostProcess:\n\t " + (t_PP - t_R).TotalMilliseconds + "ms\n" +
@@ -382,22 +386,6 @@ public static bool ShallowLoad(out Stage set, string path)
         return true;
     }
 
-    /// <summary>
-    /// Loads every member decorated with <see cref="JSONsavable.JsonSeparateAttribute"/>: <see cref="savegame"/>.
-    /// </summary>
-    /// <returns><see langword="false"/> iff <see cref="savegame"/> could not be loaded.</returns>
-    public bool LoadSavegames()
-    {
-        Stage cpy = this;
-        bool ret = IJSONsavable<Stage>.load_children(null /*hierarchie*/, name, ref cpy);
-
-        if (!ret)
-            _ = player_record; //init
-        player_record.CopyExposedSolutionFacts(this);
-
-        return ret;
-    }
-
     /// <summary>
     /// Calls <see cref="ClearPlay"/> and <see cref="store(bool)">store(true)</see>.
     /// </summary>
@@ -453,6 +441,10 @@ public class SaveGame : IJSONsavable<SaveGame>
         public string name { get; set; }
         public string path { get; set; }
 
+        [JsonIgnore]
+        public bool IsEmpty 
+            => (player_record_list ??= new()).Count == 0;
+
         [JsonIgnore]//[JSONsavable.JsonAutoPreProcess, JSONsavable.JsonAutoPostProcess]
         public PlayerRecord player_record = null;
 
@@ -468,7 +460,7 @@ public SaveGame() { }
         string IJSONsavable<SaveGame>._IJGetName(string name) => name + "_save";
         SaveGame IJSONsavable<SaveGame>._IJPostProcess(SaveGame payload)
         {
-            if ((payload.player_record_list ??= new()).Count == 0)
+            if (payload.IsEmpty)
                 payload.player_record = null;
             return payload;
         }
@@ -479,7 +471,7 @@ SaveGame IJSONsavable<SaveGame>._IJPreProcess(SaveGame payload)
                 player_record_list_processed.Add(record.Key, IJSONsavable<PlayerRecord>.preprocess(record.Value));
 
             payload.player_record_list = player_record_list_processed;
-            if (payload.player_record_list.Count == 0)
+            if (payload.IsEmpty)
                 payload.player_record = null;
             return payload;
         }
diff --git a/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocToLambdaExpression.cs b/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocToLambdaExpression.cs
index 88e2f338..e919909e 100644
--- a/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocToLambdaExpression.cs
+++ b/Assets/Scripts/MMTServer/CommunicationProtocoll/SOMDocToLambdaExpression.cs
@@ -6,7 +6,6 @@
 using System.Reflection;
 using UnityEditor;
 using System.Collections.ObjectModel;
-using Unity.Burst.Intrinsics;
 
 namespace REST_JSON_API
 {
@@ -351,6 +350,7 @@ void ThrowArgumentException(ExpressionType expression_cast, int expected)
                 throw new NotImplementedException("Could not map URI: \"" + URI + "\"");
             }
 
+#pragma warning disable IDE0060 // Nicht verwendete Parameter entfernen // Signatures given by CustomFunction
             public static LambdaExpression PartialInvoke(LambdaExpression[] lambda_applicant, LambdaExpression[] lambda_arguments, ParameterExpression[] bound_params)
                 => _PartialInvoke(lambda_applicant[0].Body, lambda_arguments, bound_params);
 
@@ -890,6 +890,7 @@ public static CustomFunction IntCastedIndexer(string property_name)
                             lambda_applicant.Skip(1).Select(l => Expression.Convert(l.Body, typeof(int))).ToArray()),
                         bound_params
                     );
+#pragma warning restore IDE0060 // Nicht verwendete Parameter entfernen // Signatures given by CustomFunction
         }
     }
 }
\ No newline at end of file
diff --git a/Assets/Scripts/StageStatic.cs b/Assets/Scripts/StageStatic.cs
index 5c157f5a..c7e3cead 100644
--- a/Assets/Scripts/StageStatic.cs
+++ b/Assets/Scripts/StageStatic.cs
@@ -23,7 +23,7 @@ public static class StageStatic
     /// </summary>
     public static IReadOnlyDictionary<string, Stage> StageLocal => StageChapters[1];
 
-    private static List<Dictionary<string, Stage>> StageChapters = new() { new(), new() };
+    private static readonly List<Dictionary<string, Stage>> StageChapters = new() { new(), new() };
 
     /// <summary>
     /// Used to map <see cref="StageOfficial"/> <see cref="Stage.category">categories</see> into a ordered list for the StageMenue.
@@ -163,7 +163,7 @@ public struct StageErrorStruct
         /// <summary>
         /// stores all boolish members, to iterate over
         /// </summary>
-        private bool[] state;
+        private readonly bool[] state;
 
         /// <summary>
         /// <see langword="true"/> iff no error occures.
@@ -306,7 +306,7 @@ public static bool ContainsNumber(string category, int i, bool local)
             .Contains(i);
     }
 
-    private static int MaxTriesOfShallowLoadStages = 2;
+    private static readonly int MaxTriesOfShallowLoadStages = 2;
     private static int TriesOfShallowLoadStages = 0;
 
     /// <summary>
@@ -349,14 +349,16 @@ public static void ShallowLoadStages(bool force = false)
                 }
             }
 
-        if (!force && GlobalBehaviour.InitiateContext.MoveNext()) // active wait at start instead?
+        if (!GlobalBehaviour.ContextLoaded) // active wait at start instead?
             GlobalBehaviour.Instance.StartCoroutine(_WaitForContext());
 
         return;
 
         static IEnumerator _WaitForContext()
         {
-            yield return GlobalBehaviour.InitiateContext;
+            while(!GlobalBehaviour.ContextLoaded)
+                yield return null;
+
             ShallowLoadStages(true);
         }
     }
@@ -430,8 +432,6 @@ public static bool LoadInitStage(bool restore_session, GameObject gameObject = n
         if (!ContainsKey(current_name, local_stage))
             return false;
 
-        stage.LoadSavegames();
-
         if (restore_session)
         {
             stage.factState.invoke = true;
diff --git a/Assets/Scripts/UI/MainMenue/PageLoader/EditLoader.cs b/Assets/Scripts/UI/MainMenue/PageLoader/EditLoader.cs
index d02bf2ae..d713dae0 100644
--- a/Assets/Scripts/UI/MainMenue/PageLoader/EditLoader.cs
+++ b/Assets/Scripts/UI/MainMenue/PageLoader/EditLoader.cs
@@ -1,7 +1,3 @@
-using System.Collections;
-using System.Collections.Generic;
-using UnityEngine;
-
 public class EditLoader : CreateLoader
 {
     private Stage original_stage;
@@ -16,9 +12,6 @@ public void SetStage(string name, bool local)
         StageStatic.SetStage(name, local);
         original_stage = StageStatic.stage;
 
-        if (!original_stage.LoadSavegames())
-            Error(StageStatic.StageErrorStruct.NotLoadable);
-
         category = original_stage.category;
         id = original_stage.number;
         this.name = original_stage.name;
-- 
GitLab