diff --git a/Assets/Scripts/GenerateDemoFiles.cs b/Assets/Scripts/GenerateDemoFiles.cs index 09e7b0958acb842855f5546fbe62327246fda9b2..f30520b4d57f3306f0ff738de1164569a2b27c7e 100644 --- a/Assets/Scripts/GenerateDemoFiles.cs +++ b/Assets/Scripts/GenerateDemoFiles.cs @@ -25,13 +25,13 @@ public static void GenerateDemoA() // TODO? use constructor Stage demo = new Stage { - number = 0, + number = 1, category = "Demo Category", name = "TechDemo A", scene = "RiverWorld", description = "Tree Stage", use_install_folder = true, - hierarchie = new List<Directories> { /*Directories.Stages*/ } + //hierarchie = new List<Directories> { /*Directories.Stages*/ } }; // needed to generate facts @@ -58,6 +58,7 @@ public static void GenerateDemoA() { new SolutionOrganizer.SubSolution(new HashSet<string> { target_Id }, null, null, new LineFactHightDirectionComparer()) }; // Save + StageStatic.SetMode(StageStatic.Mode.Create); StageStatic.stage.store(); } @@ -70,13 +71,13 @@ public static void GenerateDemoB() // TODO? use constructor Stage demo = new Stage { - number = 0, + number = 2, category = "Demo Category", name = "TechDemo B", scene = "RiverWorld", description = "River Stage", use_install_folder = true, - hierarchie = new List<Directories> { /*Directories.Stages*/ } + //hierarchie = new List<Directories> { /*Directories.Stages*/ } }; // needed to generate facts @@ -106,6 +107,7 @@ public static void GenerateDemoB() }; // Save + StageStatic.SetMode(StageStatic.Mode.Create); StageStatic.stage.store(); } } diff --git a/Assets/Scripts/GlobalBehaviour.cs b/Assets/Scripts/GlobalBehaviour.cs index a356eaa98c1ad2a2e41098f2faf7e90d1c539940..f51ac1698f99234db8fe9e277136fcd512c853d0 100644 --- a/Assets/Scripts/GlobalBehaviour.cs +++ b/Assets/Scripts/GlobalBehaviour.cs @@ -36,7 +36,7 @@ public class GlobalBehaviour : MonoBehaviour void Awake() { - // GenerateDemoFiles.GenerateAll(); + GenerateDemoFiles.GenerateAll(); hintAnimationStartColor = _hintAnimationStartColor; hintAnimationEndColor = _hintAnimationEndColor; diff --git a/Assets/Scripts/InteractionEngine/CommunicationEvents.cs b/Assets/Scripts/InteractionEngine/CommunicationEvents.cs index b6b836d828f324d9cb75153d5636d1cf0d7ba0d0..0006129c45f449f7272e4a673299c964f3647313 100644 --- a/Assets/Scripts/InteractionEngine/CommunicationEvents.cs +++ b/Assets/Scripts/InteractionEngine/CommunicationEvents.cs @@ -108,6 +108,7 @@ public enum Directories { misc, Stages, + SaveGames, ValidationSets, FactStateMachines, } diff --git a/Assets/Scripts/InteractionEngine/FactHandling/Fact.cs b/Assets/Scripts/InteractionEngine/FactHandling/Fact.cs index fe135fe9efa4c8cc576afd430a77aca57d4f94fa..bf35f56333cb709d5f585ca674d5d07c3d12ba25 100644 --- a/Assets/Scripts/InteractionEngine/FactHandling/Fact.cs +++ b/Assets/Scripts/InteractionEngine/FactHandling/Fact.cs @@ -104,7 +104,7 @@ public abstract class Fact /// Also add JsonSubtypes.KnownSubType decorator for deserialization to Fact! /// </value> [JsonProperty] - protected static readonly /*new*/ string s_type = "ERROR: set s_type in T:Fact"; // In the subtype! NOT here! + protected static /*new*/ string s_type = "ERROR: set s_type in T:Fact"; // In the subtype! NOT here! /// <value> /// Unique Id. e.g.: MMT URI @@ -125,9 +125,10 @@ public string Id { /// </value> public string Label { get { // in case of renamed dependables - return hasCustomLabel && _CustomLabel != null ? - _CustomLabel : - generateLabel(); + return _Facts.FactDict.Count == 0 + || (hasCustomLabel && _CustomLabel != null) + ? _CustomLabel + : generateLabel(); } set { rename(value); } } @@ -486,7 +487,7 @@ public class PointFact : FactWrappedCRTP<PointFact> { /// \copydoc Fact.s_type [JsonProperty] - protected static readonly new string s_type = "PointFact"; + protected static new string s_type = "PointFact"; /// <summary> Position </summary> public Vector3 Point; @@ -620,7 +621,7 @@ public class LineFact : AbstractLineFactWrappedCRTP<LineFact> { /// \copydoc Fact.s_type [JsonProperty] - protected static readonly new string s_type = "LineFact"; + protected static new string s_type = "LineFact"; /// <summary> Distance between <see cref="AbstractLineFact.Pid1"/> and <see cref="AbstractLineFact.Pid2"/></summary> public float Distance; @@ -746,7 +747,7 @@ public class RayFact : AbstractLineFactWrappedCRTP<RayFact> { /// \copydoc Fact.s_type [JsonProperty] - protected static readonly new string s_type = "RayFact"; + protected static new string s_type = "RayFact"; /// <summary> \copydoc Fact.Fact </summary> public RayFact() : base() { } @@ -850,7 +851,7 @@ public class OnLineFact : FactWrappedCRTP<OnLineFact> { /// \copydoc Fact.s_type [JsonProperty] - protected static readonly new string s_type = "OnLineFact"; + protected static new string s_type = "OnLineFact"; public string /// <summary> <see cref="PointFact"/>.<see cref="Fact.Id">Id</see> </summary> @@ -1008,7 +1009,7 @@ public class AngleFact : FactWrappedCRTP<AngleFact> { /// \copydoc Fact.s_type [JsonProperty] - protected static readonly new string s_type = "AngleFact"; + protected static new string s_type = "AngleFact"; /// @{ <summary> /// One <see cref="Fact.Id">Id</see> of three <see cref="PointFact">PointFacts</see> defining Angle [<see cref="Pid1"/>, <see cref="Pid2"/>, <see cref="Pid3"/>]. diff --git a/Assets/Scripts/InteractionEngine/FactHandling/FactOrganizer.cs b/Assets/Scripts/InteractionEngine/FactHandling/FactOrganizer.cs index b480dd2047bc14dac0b707eba26bfd3eff459125..4dcc1769bbf7ad7e6983aaeb417f0da87a878a8f 100644 --- a/Assets/Scripts/InteractionEngine/FactHandling/FactOrganizer.cs +++ b/Assets/Scripts/InteractionEngine/FactHandling/FactOrganizer.cs @@ -91,6 +91,7 @@ public class FactOrganizer : IJSONsavable<FactOrganizer> /// @{ <summary> /// For <see cref="store(string, List<Directories>, bool, bool)"/> and <see cref="load(ref FactOrganizer, bool, string, List<Directories>, bool, out Dictionary<string, string>)"/> /// </summary> + public string name { get; set; } = null; public string path { get; set; } = null; /// @} @@ -215,7 +216,7 @@ public FactOrganizer(bool invoke = false) /// <param name="source">instance to be parsed</param> /// <param name="invoke">see <see cref="invoke"/></param> /// <param name="old_to_new">generated to map <c>Key</c> <see cref="Fact.Id"/> of <paramref name="source"/> to corresponding <c>Value</c> <see cref="Fact.Id"/> of <paramref name="target"/></param>. - protected static T ReInitializeFactOrganizer<T> + public static T ReInitializeFactOrganizer<T> (FactOrganizer source, bool invoke, out Dictionary<string, string> old_to_new) where T : FactOrganizer, new() { diff --git a/Assets/Scripts/JSONManager.cs b/Assets/Scripts/JSONManager.cs index f25499f2e112065eb38b257fef277a64c0670f01..afb7adfd623d55f05fbb5bd4a2c4fcde32932c7d 100644 --- a/Assets/Scripts/JSONManager.cs +++ b/Assets/Scripts/JSONManager.cs @@ -14,35 +14,50 @@ // static methods cannot be overwritten -> virtual public interface IJSONsavable<T> where T : IJSONsavable<T>, new() { - // stand in for non static methods - public static readonly IJSONsavable<T> Instance = new T(); + // stand-in for non static methods + public static readonly IJSONsavable<T> Instance = new T(); + public static readonly FieldInfo[] JsonSeperateFields = + typeof(T) + .GetFields( + BindingFlags.Instance | + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Static ) + .Where((field) + => field.GetCustomAttributes().Any((attribute) + => attribute.GetType() == typeof(JSONManager.JsonSeparateAttribute)) + && field.FieldType.GetInterfaces().Any((inter) + => inter.IsGenericType && inter.GetGenericTypeDefinition() == typeof(IJSONsavable<>))) + .ToArray(); + + // TODO: this? + public string name { get; set; } public string path { get; set; } protected static List<Directories> hierarchie = new List<Directories> { Directories.misc }; #region OverridableMethods - protected virtual string _IJGetName(string name) => name; - protected virtual List<Directories> _IJGetHierarchie(List<Directories> hierarchie_base) + public virtual string _IJGetName(string name) => name; + public virtual List<Directories> _IJGetHierarchie(List<Directories> hierarchie_base) { hierarchie_base ??= new List<Directories>(); return hierarchie_base.Concat(hierarchie).ToList(); } - protected virtual T _IJGetRawObject(string path) => JSONManager.ReadFromJsonFile<T>(path); - protected virtual T _IJPreProcess(T payload) => payload; - protected virtual T _IJPostProcess(T payload) => payload; + public virtual bool _IJGetRawObject(out T payload, string path) => JSONManager.ReadFromJsonFile<T>(out payload, path); + public virtual T _IJPreProcess(T payload) => payload; + public virtual T _IJPostProcess(T payload) => payload; #endregion OverridableMethods + #region MethodTemplates - public bool store(List<Directories> hierarchie, string name, bool use_install_folder = false, bool overwrite = true) - { - return store(hierarchie, name, (T) this, use_install_folder, overwrite); - } + public bool store(List<Directories> hierarchie, string name, bool use_install_folder = false, bool overwrite = true, bool deep_store = true) + => store(hierarchie, name, (T) this, use_install_folder, overwrite, deep_store); - public static bool store(List<Directories> hierarchie, string name, T payload, bool use_install_folder = false, bool overwrite = true) + public static bool store(List<Directories> hierarchie, string name, T payload, bool use_install_folder = false, bool overwrite = true, bool deep_store = true) { var new_hierarchie = Instance._IJGetHierarchie(hierarchie); @@ -53,6 +68,12 @@ public static bool store(List<Directories> hierarchie, string name, T payload, b if (exists && !overwrite) return false; + // store fields decorated with JsonSeparateAttribute and implementing IJSONsavable<> separately + if (deep_store + && !store_children(hierarchie, name, payload, use_install_folder: false, overwrite, deep_store: true)) + return false; + + // store this string path_o = payload.path; payload.path = path; @@ -64,23 +85,114 @@ public static bool store(List<Directories> hierarchie, string name, T payload, b JSONManager.WriteToJsonFile(path, new_payload); return true; } + + public bool store_children(List<Directories> hierarchie, string name, bool use_install_folder = false, bool overwrite = true, bool deep_store = true) + => store_children(hierarchie, name, (T) this, use_install_folder, overwrite, deep_store); + + public static bool store_children(List<Directories> hierarchie, string name, T payload, bool use_install_folder = false, bool overwrite = true, bool deep_store = true) + { + var new_hierarchie = + Instance._IJGetHierarchie(hierarchie); + var new_name = + Instance._IJGetName(name); + + for ((int max_i, bool success) = (0, true); max_i < JsonSeperateFields.Count(); max_i++) + { + var field = JsonSeperateFields[max_i]; + dynamic save_me = field.GetValue(payload); // is S:IJSONsavable<S> + + Type interface_type = typeof(IJSONsavable<>).MakeGenericType(field.FieldType); + Type[] store_args_type = new Type[] { typeof(List<Directories>), typeof(string), field.FieldType, typeof(bool), typeof(bool), typeof(bool) }; + object[] store_args = new object[] { new_hierarchie, new_name, save_me, use_install_folder, overwrite, deep_store }; + + var method = interface_type.GetMethod("store", store_args_type); + success &= (bool)method.Invoke(null, store_args); + + // in case of no success: delete it again + if (!success) + { + delete_children(hierarchie, name, use_install_folder, JsonSeperateFields.Count() - max_i); + return false; + } + } + + return true; + } + + public static bool load_children(List<Directories> hierarchie, string name, ref T raw_payload, bool use_install_folder = false, bool deep_load = true, bool post_process = true) + { + var new_hierarchie = + Instance._IJGetHierarchie(hierarchie); + var new_name = + Instance._IJGetName(name); + + bool success = true; + for (int max_i = 0; max_i < JsonSeperateFields.Count(); max_i++) + { + var field = JsonSeperateFields[max_i]; + + Type interface_type = typeof(IJSONsavable<>).MakeGenericType(field.FieldType); + Type[] load_args_type = new Type[] { typeof(List<Directories>), typeof(string), field.FieldType.MakeByRefType(), typeof(bool), typeof(bool), typeof(bool) }; + object[] load_args = new object[] { new_hierarchie, new_name, null, use_install_folder, deep_load, post_process }; + + var method = interface_type.GetMethod("load", BindingFlags.Public | BindingFlags.Static, null, load_args_type, null); + bool success_i = (bool)method.Invoke(null, load_args); + + field.SetValue(raw_payload, success_i ? load_args[2] : Activator.CreateInstance(field.FieldType)); + success &= success_i; + } + + return success; + } - public static bool load(List<Directories> hierarchie, string name, out T payload, bool use_install_folder = false) + public static bool load(List<Directories> hierarchie, string name, out T payload, bool use_install_folder = false, bool deep_load = true, bool post_process = true) { payload = default(T); + bool success = true; + var new_hierarchie = Instance._IJGetHierarchie(hierarchie); + var new_name = + Instance._IJGetName(name); - string path = CreatePathToFile(out bool loadable, name, "JSON", new_hierarchie, use_install_folder); + string path = CreatePathToFile(out bool loadable, new_name, "JSON", new_hierarchie, use_install_folder); if (!loadable) return false; - var raw_payload = - Instance._IJGetRawObject(path); - payload = - Instance._IJPostProcess(raw_payload); + if (!Instance._IJGetRawObject(out T raw_payload, path)) + return false; + raw_payload.name = new_name; - return true; + // load fields decorated with JsonSeparateAttribute and implementing IJSONsavable<> separately + if (deep_load + && !load_children(hierarchie, name, ref raw_payload, false /*use_install_folder*/)) + success = false; + + payload = post_process + ? Instance._IJPostProcess(raw_payload) + : raw_payload; + + return success; + } + + public static void delete_children(List<Directories> hierarchie, string name, bool use_install_folder = false, int skip_last_children = 0) + { + var new_hierarchie = + Instance._IJGetHierarchie(hierarchie); + var new_name = + Instance._IJGetName(name); + + for(int i = 0; i < JsonSeperateFields.Count() - skip_last_children; i++) + { + var field = JsonSeperateFields[i]; + + Type interface_type = typeof(IJSONsavable<>).MakeGenericType(field.FieldType); + Type[] delete_args_type = new Type[] { typeof(List<Directories>), typeof(string), typeof(bool) }; + object[] delete_args = new object[] { new_hierarchie, new_name, use_install_folder }; + + var method = interface_type.GetMethod("delete", delete_args_type); + method.Invoke(null, delete_args); + } } public static bool delete(List<Directories> hierarchie, string name, bool use_install_folder = false) @@ -91,11 +203,15 @@ public static bool delete(List<Directories> hierarchie, string name, bool use_in Instance._IJGetName(name); string path = CreatePathToFile(out bool _, new_name, "JSON", new_hierarchie, use_install_folder); + if (!delete(path)) + return false; - return delete(path); + delete_children(hierarchie, name, use_install_folder); + return true; } - public static bool delete(string path) + // does not delete children! + private static bool delete(string path) { if (!File.Exists(path)) return false; @@ -104,10 +220,7 @@ public static bool delete(string path) return true; } - public bool delete() - { - return delete(path); - } + // public bool delete() => delete(hierarchie, name); #endregion MethodTemplates @@ -259,6 +372,11 @@ public MMTValueDeclaration(string label, MMTTerm lhs, MMTTerm valueTp, MMTTerm v } } + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] + public sealed class JsonSeparateAttribute : Attribute + { + public JsonSeparateAttribute() { } + } // TODO? /// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [JsonIgnore] attribute.</para> @@ -270,104 +388,32 @@ public MMTValueDeclaration(string label, MMTTerm lhs, MMTTerm valueTp, MMTTerm v /// <param name="filePath">The file path to write the object instance to.</param> /// <param name="objectToWrite">The object instance to write to the file.</param> /// <param name="max_depth">The depth recursion will occur. Default = 0.</param> - public static void WriteToJsonFile(string filePath, object objectToWrite, int max_depth = 0) + public static bool WriteToJsonFile(string filePath, object objectToWrite, int max_depth = 0) { - int current_depth = 0; - // This tells your serializer that multiple references are okay. var settings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }; - BindingFlags bindFlags = - BindingFlags.Instance | - BindingFlags.Public | - BindingFlags.NonPublic | - BindingFlags.Static; - TextWriter writer = null; try { - string payload = RecursiveStep(objectToWrite); + string payload = JsonConvert.SerializeObject(objectToWrite, settings); writer = new StreamWriter(filePath); writer.Write(payload); + return true; + } + catch (Exception e) + { + Debug.LogError(e); + return false; } finally { if (writer != null) writer.Close(); } - - - // ======= local methods ======= - // TODO? more stable depths (see next todo) - // TODO? respect IgnoreJson tags - - string RecursiveStep<S>(S objectToWrite) where S : new() - { - string json; - - if (current_depth >= max_depth - || Type.GetTypeCode(objectToWrite.GetType()) != TypeCode.Object - || objectToWrite == null) - json = JsonConvert.SerializeObject(objectToWrite, settings/*, new JsonInheritenceConverter<object>()*/); - else - { - current_depth++; - json = IntrusiveRecursiveJsonGenerator(objectToWrite); - current_depth--; - } - - return json; - } - - string IntrusiveRecursiveJsonGenerator<S>(S objectToWrite) where S : new() - // private convention? more like private suggestion! - { - bool is_enum = IsEnumerableType(objectToWrite.GetType()); - - string json = is_enum ? "[" : "{"; - foreach (object field in is_enum ? (objectToWrite as IEnumerable) : objectToWrite.GetType().GetFields(bindFlags)) - { - object not_so_private; - if (is_enum) - { - not_so_private = field; - } - else - { - not_so_private = ((FieldInfo)field).GetValue(objectToWrite); - json += ((FieldInfo)field).Name + ":"; - } - - json += RecursiveStep(not_so_private); - - json += ","; - } - json = json.TrimEnd(',') + (is_enum ? "]" : "}"); - - return json; - - - // ======= local methods ======= - - bool IsEnumerableType(Type type) - { - if (type.IsInterface && type.GetGenericTypeDefinition() == typeof(IEnumerable<>)) - return true; - - foreach (Type intType in type.GetInterfaces()) - { - if (intType.IsGenericType - && intType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) - { - return true; - } - } - return false; - } - } } /// <summary> @@ -377,14 +423,22 @@ bool IsEnumerableType(Type type) /// <typeparam name="T">The type of object to read from the file.</typeparam> /// <param name="filePath">The file path to read the object instance from.</param> /// <returns>Returns a new instance of the object read from the Json file.</returns> - public static T ReadFromJsonFile<T>(string filePath) where T : new() + public static bool ReadFromJsonFile<T>(out T payload, string filePath) where T : new() { + payload = default(T); TextReader reader = null; + try { reader = new StreamReader(filePath); var fileContents = reader.ReadToEnd(); - return JsonConvert.DeserializeObject<T>(fileContents/*, new JsonInheritenceConverter<object>()*/); + payload = JsonConvert.DeserializeObject<T>(fileContents); + return true; + } + catch (Exception e) + { + Debug.LogError(e); + return false; } finally { @@ -392,37 +446,4 @@ bool IsEnumerableType(Type type) reader.Close(); } } - - // tutorial @https://www.codeproject.com/Articles/1201466/Working-with-JSON-in-Csharp-VB#data_structure_types - // unused - // TODO: check for actual type in ReadJson - // TODO: avoid self-referencing-loop-error in WriteJson - public sealed class JsonInheritenceConverter<T> : JsonConverter - { - public override bool CanConvert(Type objectType) - { - return typeof(T).IsAssignableFrom(objectType); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - JObject jo = JObject.Load(reader); - var element = jo.Properties().First(); - return element.Value.ToObject(Type.GetType(element.Name)); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - if (value == null) - { - serializer.Serialize(writer, null); - return; - } - - writer.WriteStartObject(); - writer.WritePropertyName(value.GetType().FullName); - serializer.Serialize(writer, value); - writer.WriteEndObject(); - } - } } diff --git a/Assets/Scripts/Loading/Stage.cs b/Assets/Scripts/Loading/Stage.cs index 6a324659007245c3b0df2c4f77774d250db49db3..4da3ed348565e1148a3080cfd34c0d420a35d483 100644 --- a/Assets/Scripts/Loading/Stage.cs +++ b/Assets/Scripts/Loading/Stage.cs @@ -5,9 +5,13 @@ using UnityEngine; using Newtonsoft.Json; using static CommunicationEvents; +using System.Reflection; -public class Stage +//using static IJSONsavable<Stage>; + +public class Stage: IJSONsavable<Stage> { + /// <summary> Which category this <see cref="Stage"/> should be displayed in. </summary> public string category = null; /// <summary> Where to display this <see cref="Stage"/> within a <see cref="category"/> relative to others. </summary> @@ -16,7 +20,9 @@ public class Stage /// The name this <see cref="Stage"/> will be displayed with. /// Also defines names of save files of <see cref="player_record_list">stage progress</see>, <see cref="solution"/> /// </summary> - public string name = null; + public string name { set; get; } = null; + public string path { set; get; } = null; + /// <summary> The description this <see cref="Stage"/> will be displayed with.</summary> public string description = null; @@ -25,8 +31,9 @@ public class Stage /// <summary> Wether this <see cref="Stage"/> is located in installation folder or user data (a.k.a. !local).</summary> public bool use_install_folder = false; - /// <summary> TODO? interface </summary> - public List<Directories> hierarchie = null; + + [JsonIgnore, JSONManager.JsonSeparate] + public SaveGame savegame = null; /// <summary> /// <see langword="true"/> iff there is at least one element in <see cref="player_record_list"/> where <see cref="PlayerRecord.solved"/> == <see langword="true"/>. @@ -39,13 +46,17 @@ public class Stage /// - Key: name of file /// - Value: <see cref="PlayerRecord"/> /// </summary> - public Dictionary<string, PlayerRecord> player_record_list = null; + [JsonIgnore] + public Dictionary<string, PlayerRecord> player_record_list { + get => savegame?.player_record_list; + set => (savegame ??= new()) + .player_record_list = value; + } /// <summary> /// Defining when this <see cref="Stage.player_record"/> is considered as solved. /// <seealso cref="FactOrganizer.DynamiclySolved(SolutionOrganizer, out List{List{string}}, out List{List{string}})"/> /// </summary> - [JsonIgnore] public SolutionOrganizer solution = null; /// <summary> @@ -56,19 +67,17 @@ public class Stage /// </summary> [JsonIgnore] public FactOrganizer factState { - get { - if (player_record == null) - return null; - return player_record.factState; - } - set { - if (player_record == null) - player_record = new PlayerRecord(record_name); - player_record.factState = value; - } + get => player_record?.factState; + set => (player_record ??= new(record_name)) + .factState = value; } /// <summary> Current Stage progress.</summary> - public PlayerRecord player_record = null; + [JsonIgnore] + public PlayerRecord player_record { + get => savegame?.player_record; + set => (savegame ??= new()) + .player_record = value; + } /// <summary> Returns a name for <see cref="player_record.name"/> which needs to be uniquified once put into <see cref="player_record_list"/> (e.g. by <see cref="push_record(double, bool) adding '_i'"/>).</summary> private string record_name { get { return name + "_save"; } } @@ -76,17 +85,14 @@ public FactOrganizer factState { [JsonIgnore] public bool creatorMode = false; - /// @{ <summary> - /// TODO? interafce - /// </summary> - private string path = null; - private static List<Directories> - hierStage = new List<Directories> { Directories.Stages }; - /// @} - /// <summary> Tempory variable storing <see cref="factState"/> when <see cref="creatorMode"/> == <see langword="true"/>. </summary> private FactOrganizer hiddenState; + static Stage() + { + IJSONsavable<Stage>.hierarchie = new List<Directories> { Directories.Stages }; + } + /// <summary> /// Initiates all parameterless members. <br/> /// Used by <see cref="JsonConverter"/> to initate empty <c>class</c>. @@ -115,48 +121,14 @@ public Stage(string category, int number, string name, string description, strin InitOOP(); } - /// <summary> - /// Copy Constructor. <br/> - /// <seealso cref="InitOOP"/> - /// <seealso cref="InitFields(string, int, string, string, string, bool)"/> - /// </summary> - /// <param name="get">to be copied</param> - /// <param name="category">sets <see cref="category"/></param> - /// <param name="number">sets <see cref="number"/></param> - /// <param name="name">sets <see cref="name"/></param> - /// <param name="description">sets <see cref="description"/></param> - /// <param name="scene">sets <see cref="scene"/></param> - /// <param name="local">sets !<see cref="use_install_folder"/></param> - public Stage(Stage get, string category, int number, string name, string description, string scene, bool local = true) - { - InitOOP(); - Stage cpy = new Stage(); - // "DeepCopy" of ref-types, 'cause screw c# and ICloneable - load(ref cpy, get.name, null, get.use_install_folder); - this.hierarchie = cpy.hierarchie; - this.solution = cpy.solution; - this.player_record = cpy.player_record; - - InitFields(category, number, name, description, scene, local); - hierarchie ??= new List<Directories>(); - hierarchie.AddRange(hierStage.AsEnumerable()); - - player_record.load(hierarchie); - player_record.name = player_record.name.Replace(get.record_name, record_name); - player_record.store(hierarchie, false); - - //this.player_record_list = cpy.player_record_list; - foreach (var record in cpy.player_record_list.Values) - { - record.load(hierarchie); - record.name = record.name.Replace(get.record_name, record_name); - record.store(hierarchie, false); - player_record_list.Add(record.name, record); - } + Stage IJSONsavable<Stage>._IJPostProcess(Stage payload) + { + payload.solution = IJSONsavable<SolutionOrganizer>.Instance._IJPostProcess(payload.solution ?? new()); + // // savegame is saved separately + // payload.savegame = IJSONsavable<SaveGame>.Instance._IJPostProcess(payload.savegame ?? new()); - hierarchie.RemoveRange(hierarchie.Count - hierStage.Count, hierStage.Count); - store(false); + return payload; } /// <summary> @@ -184,8 +156,8 @@ public void InitFields(string category, int number, string name, string descript private void InitOOP() { solution = new SolutionOrganizer(); + savegame = new(); player_record = new PlayerRecord(record_name); - player_record_list = new Dictionary<string, PlayerRecord>(); } /// <summary> @@ -227,7 +199,7 @@ public void ClearPlay() /// </summary> public void ClearALLRecords() { - foreach (var record in player_record_list.Values.ToList()) + foreach (var record in player_record_list.Values) deletet_record(record, false); player_record_list = new Dictionary<string, PlayerRecord>(); @@ -242,17 +214,12 @@ public void ClearALLRecords() /// <param name="b_store">iff <see langword="true"/> <see cref="store(bool)">stores</see> changes made to this <see cref="Stage"/></param> public void deletet_record(PlayerRecord record, bool b_store = true) { - hierarchie ??= new List<Directories>(); - hierarchie.AddRange(hierStage.AsEnumerable()); - - if (record.factState != null) - record.factState.hardreset(); - record.delete(hierarchie); - player_record_list.Remove(record.name); + record.factState.hardreset(); - hierarchie.RemoveRange(hierarchie.Count - hierStage.Count, hierStage.Count); - if(b_store) + if (b_store) { + player_record_list.Remove(record.name); store(); + } } /// <summary> @@ -262,39 +229,24 @@ public void deletet_record(PlayerRecord record, bool b_store = true) /// <param name="record">to be set or <see langword="null"/></param> /// <returns><see langword="false"/> iff <paramref name="record"/> not found in <see cref="player_record_list"/> <br/> /// or <see cref="PlayerRecord.load(List<Directories>)"/> fails.</returns> - public bool set_record(PlayerRecord record) + public bool set_record(string record_index) { - hierarchie ??= new List<Directories>(); - hierarchie.AddRange(hierStage.AsEnumerable()); + if (record_index == null) + return false; - if (record != null) - { - if (!player_record_list.ContainsKey(record.name)) - { - hierarchie.RemoveRange(hierarchie.Count - hierStage.Count, hierStage.Count); - return false; - } - - else if (!record.load(hierarchie)) - { - deletet_record(record); - hierarchie.RemoveRange(hierarchie.Count - hierStage.Count, hierStage.Count); - return false; - } - } + if (!player_record_list.ContainsKey(record_index)) + return false; - player_record = record == null ? new PlayerRecord(record_name) : record.Clone(hierarchie); + player_record = player_record_list[record_index].Clone(); player_record.name = record_name; - hierarchie.RemoveRange(hierarchie.Count - hierStage.Count, hierStage.Count); - store(false); - return true; } /// <summary> /// Adds current <see cref="player_record"/> to <see cref="player_record_list"/> incrementing <see cref="PlayerRecord.seconds"/> beforehand. + /// <remarks> IMPACTS SERVER PERFORMANCE: Increases number of <see cref="Fact"/>s at the Server for every <see cref="Fact"/> in current <see cref="player_record"/> </remarks> /// </summary> /// <param name="seconds_s">time in seconds to be added to <see cref="player_record.seconds"/> before pushing. <br/> /// Iff set to <c>-1</c> <see cref="Time.timeSinceLevelLoadAsDouble"/> will be used.</param> @@ -305,25 +257,14 @@ public void push_record(double seconds_s = -1, bool force_push = false) if(!force_push && StageStatic.mode == StageStatic.Mode.Create && creatorMode) // store solution space { - SetMode(false); store(false); - //push_record(seconds_s, false); - SetMode(true); return; } - hierarchie ??= new List<Directories>(); - hierarchie.AddRange(hierStage.AsEnumerable()); - - if (seconds_s == -1) - seconds_s = Time.timeSinceLevelLoadAsDouble; - player_record.seconds += seconds_s; + player_record.seconds += seconds_s != -1 ? seconds_s : Time.timeSinceLevelLoadAsDouble; + var push = player_record.Clone(); - var push = player_record.Clone(hierarchie); - - hierarchie.RemoveRange(hierarchie.Count - hierStage.Count, hierStage.Count); - - int i = 0; + int i = 1; push.name = record_name + "_" + i.ToString(); for (; player_record_list.ContainsKey(push.name); i++) push.name = record_name + "_" + i.ToString(); @@ -369,84 +310,26 @@ public void SetMode(bool create) /// Clears and deletes all files associated with this <see cref="Stage"/>. /// </summary> /// <param name="player_record_list_too">iff set <see langword="false"/>, all files regarding <see cref="player_record_list"/> will be spared.</param> - public void delete(bool player_record_list_too) + public void delete() { - hierarchie ??= new List<Directories>(); - hierarchie.AddRange(hierStage.AsEnumerable()); - - ClearSolution(); - ClearPlay(); - (solution as IJSONsavable<SolutionOrganizer>).delete(); - player_record.delete(hierarchie); - - foreach (var record in player_record_list.Values.ToList()) - record.factState.hardreset(false); - if (player_record_list_too) - ClearALLRecords(); - - if (File.Exists(path)) - File.Delete(path); - - hierarchie.RemoveRange(hierarchie.Count - hierStage.Count, hierStage.Count); + ClearAll(); + IJSONsavable<Stage>.delete(null, name); } /// <summary> /// Stores and overwrites this <see cref="Stage"/>, <see cref="player_record"/>, every element in <see cref="player_record_list"/> and <see cref="solution"/> (no overwrite for latter if empty). /// </summary> /// <param name="reset_player">wether to clear current <see cref="player_record"/></param> - public void store(bool reset_player = false) + public void store(bool reset_player = false, bool force_stage_file = false) { - hierarchie ??= new List<Directories>(); - hierarchie.AddRange(hierStage.AsEnumerable()); - player_record.name = record_name; if (reset_player) player_record = new PlayerRecord(record_name); - //if (creatorMode || StageStatic.devel) - { - string path_o = path; - path = CreatePathToFile(out bool exists, name, "JSON", hierarchie, use_install_folder); - hierarchie.RemoveRange(hierarchie.Count - hierStage.Count, hierStage.Count); - - JSONManager.WriteToJsonFile(path, this, 0); - path = path_o; - - hierarchie.AddRange(hierStage.AsEnumerable()); - if(solution != null) - (solution as IJSONsavable<SolutionOrganizer>).store(hierarchie, name, use_install_folder, - overwrite: solution.ValidationSet.Count > 0 && !solution.ValidationSet.Aggregate(true, (last, next) => last && next.IsEmpty())); - } - - if (player_record != null) - player_record.store(hierarchie, true); - - foreach (var track in player_record_list) - track.Value.store(hierarchie, false); - - hierarchie.RemoveRange(hierarchie.Count - hierStage.Count, hierStage.Count); - } - - /// <summary> - /// Loads a Stage complete using: - /// - <see cref="ShallowLoad(ref Stage, string, List<Directories>, bool)"/> - /// - <see cref="DeepLoad"/> - /// </summary> - /// \copydetails ShallowLoad(ref Stage, string, List<Directories>, bool) - public static bool load(ref Stage set, string name, List<Directories> hierarchie = null, bool use_install_folder = false) - { - Stage ret = new Stage(); - - bool loadable = ShallowLoad(ref ret, name, hierarchie, use_install_folder); - if (!loadable) - return false; - - loadable = ret.DeepLoad(); - if (!loadable) - return false; - - set = ret; - return true; + if (force_stage_file || StageStatic.mode == StageStatic.Mode.Create) + (this as IJSONsavable<Stage>).store (null, name, use_install_folder, deep_store: false); + else + (this as IJSONsavable<Stage>).store_children(null, name, false , deep_store: true ); } /// <summary> @@ -456,42 +339,14 @@ public static bool load(ref Stage set, string name, List<Directories> hierarchie /// <param name="set">to be written in</param> /// <param name="path">file location</param> /// <returns><see langword="true"/> iff succeeded</returns> - public static bool ShallowLoad(ref Stage set, string path) + public static bool ShallowLoad(out Stage set, string path) { - if (!System.IO.File.Exists(path)) + if (!IJSONsavable<Stage>.Instance._IJGetRawObject(out set, path)) return false; - set = JSONManager.ReadFromJsonFile<Stage>(path); + set = IJSONsavable<Stage>.Instance._IJPostProcess(set); set.path = path; - - set.hierarchie ??= new List<Directories>(); - set.hierarchie.AddRange(hierStage.AsEnumerable()); - //if (!set.player_record.load(set.hierarchie)) - // set.player_record = new PlayerRecord(set.record_name); - set.hierarchie.RemoveRange(set.hierarchie.Count - hierStage.Count, hierStage.Count); - - return true; - } - - /// <summary> - /// Determines path via <paramref name="hierarchie"/> and <paramref name="use_install_folder"/> and calls <see cref="ShallowLoad(ref Stage, string)"/>. - /// <seealso cref="ShallowLoad(ref Stage, string)"/> - /// </summary> - /// <param name="set">see <see cref="ShallowLoad(ref Stage, string)"/></param> - /// <param name="name">see <see cref="ShallowLoad(ref Stage, string)"/></param> - /// <param name="hierarchie">see <see cref="hierarchie"/> // TODO? Interface</param> - /// <param name="use_install_folder">see <see cref="use_install_folder"/></param> - /// <returns><see langword="true"/> iff succeeded</returns> - public static bool ShallowLoad(ref Stage set, string name, List<Directories> hierarchie = null, bool use_install_folder = false) - { - hierarchie ??= new List<Directories>(); - hierarchie.AddRange(hierStage.AsEnumerable()); - - string path = CreatePathToFile(out bool loadable, name, "JSON", hierarchie, use_install_folder); - hierarchie.RemoveRange(hierarchie.Count - hierStage.Count, hierStage.Count); - - if (!loadable || !ShallowLoad(ref set, path)) - return false; + IJSONsavable<Stage>.load_children(null /*hierarchie*/, set.name, ref set, post_process: false); return true; } @@ -502,23 +357,13 @@ public static bool ShallowLoad(ref Stage set, string name, List<Directories> hie /// <returns><see langword="false"/> iff <see cref="solution"/> could not be <see cref="SolutionOrganizer.load(ref SolutionOrganizer, bool, string, List<Directories>, bool)">loaded</see>.</returns> public bool DeepLoad() { - hierarchie ??= new List<Directories>(); - hierarchie.AddRange(hierStage.AsEnumerable()); - - bool loadable; - - loadable = IJSONsavable<SolutionOrganizer>.load(hierarchie, name, out solution,use_install_folder); - if (!loadable) - return false; - - player_record.load(hierarchie); - - hierarchie.RemoveRange(hierarchie.Count - hierStage.Count, hierStage.Count); + Stage cpy = this; + IJSONsavable<Stage>.load_children(null /*hierarchie*/, name, ref cpy); return true; } /// <summary> - /// Looks for saved <see cref="Stage">Stages</see> in parametised directories and calls on them <see cref="ShallowLoad(ref Stage, string)"/>. + /// Looks for saved <see cref="Stage">Stages</see> in parametised directories and calls on them <see cref="ShallowLoad(out Stage, string)"/>. /// </summary> /// <param name="hierarchie">see <see cref="hierarchie"/> //TODO? Interface</param> /// <param name="use_install_folder">see <see cref="use_install_folder"/></param> @@ -527,25 +372,16 @@ public static Dictionary<string, Stage> Grup(List<Directories> hierarchie = null { Dictionary<string, Stage> ret = new Dictionary<string, Stage>(); - hierarchie ??= new List<Directories>(); - hierarchie.AddRange(hierStage.AsEnumerable()); - - string path = CreatePathToFile(out _, "", "", hierarchie, use_install_folder); - hierarchie.RemoveRange(hierarchie.Count - hierStage.Count, hierStage.Count); - - string ending = ".JSON"; + var new_hierarchie = IJSONsavable<Stage>.Instance._IJGetHierarchie(hierarchie); + string path = CreatePathToFile(out _, "", "", new_hierarchie, use_install_folder); - var info = new DirectoryInfo(path); - var fileInfo = info.GetFiles(); - foreach(var file in fileInfo) + foreach(var file in new DirectoryInfo(path).GetFiles()) { - if (0 != string.Compare(ending, 0, file.Name, file.Name.Length - ending.Length, ending.Length)) + if (file.Extension != ".JSON") continue; - Stage tmp = new Stage(); - if (ShallowLoad(ref tmp, file.FullName)) + if (ShallowLoad(out Stage tmp, file.FullName)) ret.Add(tmp.name, tmp); - } return ret; @@ -605,10 +441,38 @@ public bool CheckSolved() } +public class SaveGame : IJSONsavable<SaveGame> +{ + public string name { get; set; } + public string path { get; set; } + + public PlayerRecord player_record = new(); + public Dictionary<string, PlayerRecord> player_record_list = new(); + + static SaveGame() + { + IJSONsavable<SaveGame>.hierarchie = new() { Directories.SaveGames }; + } + public SaveGame() { } + + string IJSONsavable<SaveGame>._IJGetName(string name) => name + "_save"; + SaveGame IJSONsavable<SaveGame>._IJPostProcess(SaveGame payload) + { + payload.player_record = IJSONsavable<PlayerRecord>.Instance._IJPostProcess(payload.player_record ?? new()); + + // // player_record_list entries are "PostProcess"ed when accessed/Cloned + //payload.player_record_list = new (payload.player_record_list.Select((v) => new KeyValuePair<string, PlayerRecord> + // (v.Key, IJSONsavable<PlayerRecord>.Instance._IJPostProcess(v.Value)))); + + return payload; + } +} + + /// <summary> /// Represents a save slot. /// </summary> -public class PlayerRecord +public class PlayerRecord: IJSONsavable<PlayerRecord> { /// <summary> Wether this save has solved the <see cref="Stage"/> which contains it. </summary> public bool solved = false; @@ -618,13 +482,16 @@ public class PlayerRecord public double seconds = 0; /// <summary> Stage progress. </summary> - [JsonIgnore] - public FactOrganizer factState = null; + public FactOrganizer factState = new(); /// <summary> save game file name </summary> - public string name = null; + public string name { get; set; } = null; + + public string path { get; set; } - private static List<Directories> - hierStage = new List<Directories> { /*Directories.FactStateMachines*/ }; + static PlayerRecord(/*static!*/) + { + IJSONsavable<PlayerRecord>.hierarchie = new List<Directories> { /*Directories.FactStateMachines*/ }; + } /// <summary> /// Empty constructor for <see cref="JsonConverter"/> @@ -640,41 +507,10 @@ public PlayerRecord(string name) { factState = new FactOrganizer(); } - public void store(List<Directories> hierarchie, bool force_write) - { - hierarchie ??= new List<Directories>(); - hierarchie.AddRange(hierStage.AsEnumerable()); - - if (factState != null) - (factState as IJSONsavable<FactOrganizer>).store(hierarchie, name, false, force_write); - - hierarchie.RemoveRange(hierarchie.Count - hierStage.Count, hierStage.Count); - } - - - public bool load(List<Directories> hierarchie) - { - hierarchie ??= new List<Directories>(); - hierarchie.AddRange(hierStage.AsEnumerable()); - - factState = new FactOrganizer(false); - bool loadable = IJSONsavable<FactOrganizer>.load(hierarchie, name, out factState, false); - hierarchie.RemoveRange(hierarchie.Count - hierStage.Count, hierStage.Count); - if (!loadable) { - return false; - } - - return true; - } - - public void delete(List<Directories> hierarchie) + PlayerRecord IJSONsavable<PlayerRecord>._IJPostProcess(PlayerRecord payload) { - hierarchie ??= new List<Directories>(); - hierarchie.AddRange(hierStage.AsEnumerable()); - - IJSONsavable<FactOrganizer>.delete(hierarchie, name, false); - - hierarchie.RemoveRange(hierarchie.Count - hierStage.Count, hierStage.Count); + payload.factState = IJSONsavable<FactOrganizer>.Instance._IJPostProcess(payload.factState); + return payload; } /// <summary> @@ -682,21 +518,15 @@ public void delete(List<Directories> hierarchie) /// </summary> /// <param name="hierarchie">// TODO:</param> /// <returns>a copied <see cref="PlayerRecord"/></returns> - public PlayerRecord Clone(List<Directories> hierarchie) + public PlayerRecord Clone() { - this.store(hierarchie, true); - - hierarchie ??= new List<Directories>(); - hierarchie.AddRange(hierStage.AsEnumerable()); - var ret = new PlayerRecord(this.name) { solved = this.solved, seconds = this.seconds }; - ret.load(hierarchie); + ret.factState = FactOrganizer.ReInitializeFactOrganizer<FactOrganizer>(this.factState, false, out _); - hierarchie.RemoveRange(hierarchie.Count - hierStage.Count, hierStage.Count); return ret; } } \ No newline at end of file diff --git a/Assets/Scripts/StageBehaviour.cs b/Assets/Scripts/StageBehaviour.cs index a508070d7aea727ab411f655155cbf4cea0e74aa..d77a56253e113b8524d7527d9f93bf9c5529a0ff 100644 --- a/Assets/Scripts/StageBehaviour.cs +++ b/Assets/Scripts/StageBehaviour.cs @@ -22,8 +22,8 @@ void Start() private void OnDestroy() { StageStatic.SetMode(Mode.Play); // no Mode.Create - StageStatic.stage.solution.hardreset(); - StageStatic.stage.factState.hardreset(); + StageStatic.stage.solution.hardreset(invoke_event: false); + StageStatic.stage.factState.hardreset(invoke_event: false); } /// <summary> diff --git a/Assets/Scripts/StageStatic.cs b/Assets/Scripts/StageStatic.cs index 49c0d653d0149c778bd088ea1bfb11830c4f09d0..1af549119cdc99b3c5dfe155c9aeddcbbc3b6937 100644 --- a/Assets/Scripts/StageStatic.cs +++ b/Assets/Scripts/StageStatic.cs @@ -64,8 +64,6 @@ public static Stage stage { (local_stage ? StageLocal : StageOfficial).Remove(current_name); (local_stage ? StageLocal : StageOfficial).Add(current_name, value); - - value.store(); } } @@ -234,11 +232,8 @@ public static StageErrorStruct LoadNewStage(string category, int id, string name if (!ret.pass) return ret; - stage = new Stage(category, id, name, description, scene, true) - { - creatorMode = true - }; - stage.store(); + stage = new Stage(category, id, name, description, scene, true); + stage.store(force_stage_file: true); LoadCreate(); return ret; @@ -294,7 +289,7 @@ public static bool ContainsNumber(string category, int i, bool local) } /// <summary> - /// Looks for and initial loads (see <see cref="Stage.ShallowLoad(ref Stage, string)"/>) <see cref="Stage">Stages</see> in <see cref="local_stage"/> and !<see cref="local_stage"/>. + /// Looks for and initial loads (see <see cref="Stage.ShallowLoad(out Stage, string)"/>) <see cref="Stage">Stages</see> in <see cref="local_stage"/> and !<see cref="local_stage"/>. /// </summary> public static void ShallowLoadStages() { @@ -326,12 +321,12 @@ public static Stage GetStage(string name, bool local) /// <summary> /// Deletes a <see cref="Stage"/> and all its associated files (including save games). - /// <seealso cref="Stage.delete(bool)"/> + /// <seealso cref="Stage.delete()"/> /// </summary> /// <param name="stage">to be deleted</param> public static void Delete(Stage stage) { - GetStage(stage.name, !stage.use_install_folder).delete(true); + GetStage(stage.name, !stage.use_install_folder).delete(); (!stage.use_install_folder ? StageLocal : StageOfficial).Remove(stage.name); } @@ -379,13 +374,13 @@ public static bool LoadInitStage(bool restore_session, GameObject gameObject = n else { stage.ResetPlay(); - if(mode == Mode.Create) // block saving "player" progress - stage.player_record.seconds = -1; + //if(mode == Mode.Create) // block saving "player" progress + // stage.player_record.seconds = -1; } if(gameObject != null) gameObject.UpdateTagActive("DevelopingMode", mode == Mode.Create); - SetMode(stage.creatorMode ? Mode.Create : Mode.Play); + SetMode(mode); return true; } diff --git a/Assets/Scripts/UI/MainMenue/CollapsableStage/CollapsableStage.cs b/Assets/Scripts/UI/MainMenue/CollapsableStage/CollapsableStage.cs index 0c63522aff41d184a843f31efeaed48db2d2b3f4..9f9b04d767553b05e137717d1bf1c4988c034e49 100644 --- a/Assets/Scripts/UI/MainMenue/CollapsableStage/CollapsableStage.cs +++ b/Assets/Scripts/UI/MainMenue/CollapsableStage/CollapsableStage.cs @@ -72,7 +72,7 @@ public void DrawChildren() // button Action to load a record UnityAction loadRecord = delegate () { // redraw this, when unable to find record - if (!stage.set_record(stage.player_record_list[index])) { + if (!stage.set_record(index)) { this.Init(); return; } diff --git a/Assets/Scripts/UI/MainMenue/PageLoader/EditLoader.cs b/Assets/Scripts/UI/MainMenue/PageLoader/EditLoader.cs index c1a3491e90f31d9dd1cbcf9159868ba6ab488068..139c8e1a8a71597089b96aa90b8dc936bbb3fe67 100644 --- a/Assets/Scripts/UI/MainMenue/PageLoader/EditLoader.cs +++ b/Assets/Scripts/UI/MainMenue/PageLoader/EditLoader.cs @@ -63,11 +63,15 @@ private bool _Clone(bool overwrite) return false; } - Stage new_stage = new Stage(original_stage, category, id, name, description, scene, true); + IJSONsavable<Stage>.load(null /*original_stage.hierarchie*/, original_stage.name, out Stage new_stage, original_stage.use_install_folder, true); + new_stage.InitFields(category, id, name, description, scene, true); + if (!overwrite) new_stage.ResetSaves(); StageStatic.stage = new_stage; + new_stage.store(force_stage_file: true ); + new_stage.store(force_stage_file: false); return true; } diff --git a/Assets/Stages/FactStateMachines.meta b/Assets/Stages/FactStateMachines.meta deleted file mode 100644 index debf5ea4e5e4c133644ea1901cafeceec3d4ecba..0000000000000000000000000000000000000000 --- a/Assets/Stages/FactStateMachines.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 7d43c521d7312964cb72014365bd183e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Stages/FactStateMachines/TechDemo A.JSON b/Assets/Stages/FactStateMachines/TechDemo A.JSON deleted file mode 100644 index 44fda086c9377bf6388b2b00c979f9b52a24565d..0000000000000000000000000000000000000000 --- a/Assets/Stages/FactStateMachines/TechDemo A.JSON +++ /dev/null @@ -1 +0,0 @@ -{"ValidationSet":[{"MasterIDs":["http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2844"],"SolutionIndex":[],"RelationIndex":[],"ComparerString":"LineFactHightDirectionComparer"}],"FactDict":{"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2842":{"s_type":"PointFact","Point":{"x":0.0,"y":0.0,"z":0.0,"magnitude":0.0,"sqrMagnitude":0.0},"Normal":{"x":0.0,"y":1.0,"z":0.0,"magnitude":1.0,"sqrMagnitude":1.0},"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2842","Label":"A","hasCustomLabel":false,"LabelId":1},"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2843":{"s_type":"PointFact","Point":{"x":0.0,"y":6.0,"z":0.0,"normalized":{"x":0.0,"y":1.0,"z":0.0,"magnitude":1.0,"sqrMagnitude":1.0},"magnitude":6.0,"sqrMagnitude":36.0},"Normal":{"x":0.0,"y":1.0,"z":0.0,"magnitude":1.0,"sqrMagnitude":1.0},"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2843","Label":"B","hasCustomLabel":false,"LabelId":2},"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2844":{"s_type":"LineFact","Distance":6.0,"Pid1":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2842","Pid2":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2843","Dir":{"x":0.0,"y":1.0,"z":0.0,"magnitude":1.0,"sqrMagnitude":1.0},"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2844","Label":"[AB]","hasCustomLabel":false,"LabelId":0}},"MetaInf":{"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2842":{"workflow_id":0,"active":true},"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2843":{"workflow_id":1,"active":true},"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2844":{"workflow_id":2,"active":true}},"Workflow":[{"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2842","samestep":false,"steplink":3,"creation":true},{"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2843","samestep":true,"steplink":0,"creation":true},{"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2844","samestep":true,"steplink":0,"creation":true}],"marker":3,"worksteps":1,"backlog":0,"soft_resetted":false,"invoke":false,"MaxLabelId":2,"UnusedLabelIds":[],"path":null} \ No newline at end of file diff --git a/Assets/Stages/FactStateMachines/TechDemo A.JSON.meta b/Assets/Stages/FactStateMachines/TechDemo A.JSON.meta deleted file mode 100644 index 7a7991a639facce43bdf9d684bd967ade8d15383..0000000000000000000000000000000000000000 --- a/Assets/Stages/FactStateMachines/TechDemo A.JSON.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: b9f66b56bf429ad42a19258696330fa3 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Stages/FactStateMachines/TechDemo B.JSON b/Assets/Stages/FactStateMachines/TechDemo B.JSON deleted file mode 100644 index 41312506fd24bfceb0dcf18c3545b1225e4022ac..0000000000000000000000000000000000000000 --- a/Assets/Stages/FactStateMachines/TechDemo B.JSON +++ /dev/null @@ -1 +0,0 @@ -{"ValidationSet":[{"MasterIDs":["http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2847"],"SolutionIndex":[],"RelationIndex":[],"ComparerString":"LineFactHightDirectionComparer"},{"MasterIDs":["http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2847"],"SolutionIndex":[],"RelationIndex":[],"ComparerString":"LineSpanningOverRiverWorldComparer"},{"MasterIDs":[],"SolutionIndex":[1],"RelationIndex":[0],"ComparerString":"LineFactHightComparer"}],"FactDict":{"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2845":{"s_type":"PointFact","Point":{"x":0.0,"y":0.0,"z":0.0,"magnitude":0.0,"sqrMagnitude":0.0},"Normal":{"x":0.0,"y":1.0,"z":0.0,"magnitude":1.0,"sqrMagnitude":1.0},"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2845","Label":"A","hasCustomLabel":false,"LabelId":1},"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2846":{"s_type":"PointFact","Point":{"x":0.0,"y":6.0,"z":0.0,"normalized":{"x":0.0,"y":1.0,"z":0.0,"magnitude":1.0,"sqrMagnitude":1.0},"magnitude":6.0,"sqrMagnitude":36.0},"Normal":{"x":0.0,"y":1.0,"z":0.0,"magnitude":1.0,"sqrMagnitude":1.0},"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2846","Label":"B","hasCustomLabel":false,"LabelId":2},"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2847":{"s_type":"LineFact","Distance":6.0,"Pid1":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2845","Pid2":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2846","Dir":{"x":0.0,"y":1.0,"z":0.0,"magnitude":1.0,"sqrMagnitude":1.0},"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2847","Label":"[AB]","hasCustomLabel":false,"LabelId":0}},"MetaInf":{"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2845":{"workflow_id":0,"active":true},"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2846":{"workflow_id":1,"active":true},"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2847":{"workflow_id":2,"active":true}},"Workflow":[{"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2845","samestep":false,"steplink":3,"creation":true},{"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2846","samestep":true,"steplink":0,"creation":true},{"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2847","samestep":true,"steplink":0,"creation":true}],"marker":3,"worksteps":1,"backlog":0,"soft_resetted":false,"invoke":false,"MaxLabelId":2,"UnusedLabelIds":[],"path":null} \ No newline at end of file diff --git a/Assets/Stages/FactStateMachines/TechDemo B.JSON.meta b/Assets/Stages/FactStateMachines/TechDemo B.JSON.meta deleted file mode 100644 index 8c36ca7bb7a99b5398b33cb4302eff4b77c8eefe..0000000000000000000000000000000000000000 --- a/Assets/Stages/FactStateMachines/TechDemo B.JSON.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 6c3c72bfe0bce2d4dbc7bfa537c6c2bf -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Stages/TechDemo A.JSON b/Assets/Stages/TechDemo A.JSON index ac6246f475c836f183a48e3d7a577e7a77bb3a36..11ae46691be69ffd3f5ef11855d6131515950ae6 100644 --- a/Assets/Stages/TechDemo A.JSON +++ b/Assets/Stages/TechDemo A.JSON @@ -1 +1 @@ -{"category":"Demo Category","number":0,"name":"TechDemo A","description":"Tree Stage","scene":"RiverWorld","use_install_folder":true,"hierarchie":[],"player_record_list":{},"player_record":{"solved":false,"date":-8585436724597716289,"seconds":0.0,"name":"TechDemo A_save"}} \ No newline at end of file +{"category":"Demo Category","number":1,"description":"Tree Stage","scene":"RiverWorld","use_install_folder":true,"solution":{"ValidationSet":[{"MasterIDs":["http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2885"],"SolutionIndex":[],"RelationIndex":[],"ComparerString":"LineFactHightDirectionComparer"}],"FactDict":{"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2883":{"s_type":"PointFact","Point":{"x":0.0,"y":0.0,"z":0.0,"magnitude":0.0,"sqrMagnitude":0.0},"Normal":{"x":0.0,"y":1.0,"z":0.0,"magnitude":1.0,"sqrMagnitude":1.0},"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2883","Label":"A","hasCustomLabel":false,"LabelId":1},"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2884":{"s_type":"PointFact","Point":{"x":0.0,"y":6.0,"z":0.0,"normalized":{"x":0.0,"y":1.0,"z":0.0,"magnitude":1.0,"sqrMagnitude":1.0},"magnitude":6.0,"sqrMagnitude":36.0},"Normal":{"x":0.0,"y":1.0,"z":0.0,"magnitude":1.0,"sqrMagnitude":1.0},"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2884","Label":"B","hasCustomLabel":false,"LabelId":2},"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2885":{"s_type":"LineFact","Distance":6.0,"Pid1":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2883","Pid2":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2884","Dir":{"x":0.0,"y":1.0,"z":0.0,"magnitude":1.0,"sqrMagnitude":1.0},"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2885","Label":"[AB]","hasCustomLabel":false,"LabelId":0}},"MetaInf":{"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2883":{"workflow_id":0,"active":true},"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2884":{"workflow_id":1,"active":true},"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2885":{"workflow_id":2,"active":true}},"Workflow":[{"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2883","samestep":false,"steplink":3,"creation":true},{"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2884","samestep":true,"steplink":0,"creation":true},{"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2885","samestep":true,"steplink":0,"creation":true}],"marker":3,"worksteps":1,"backlog":0,"soft_resetted":false,"invoke":true,"MaxLabelId":2,"UnusedLabelIds":[],"name":null,"path":null},"name":"TechDemo A","path":null} \ No newline at end of file diff --git a/Assets/Stages/TechDemo B.JSON b/Assets/Stages/TechDemo B.JSON index c52c06871b52696cb33544ed4b9b16c3353139a2..93bff977f35c30d27eecab9672864d64513b3a64 100644 --- a/Assets/Stages/TechDemo B.JSON +++ b/Assets/Stages/TechDemo B.JSON @@ -1 +1 @@ -{"category":"Demo Category","number":0,"name":"TechDemo B","description":"River Stage","scene":"RiverWorld","use_install_folder":true,"hierarchie":[],"player_record_list":{},"player_record":{"solved":false,"date":-8585436724595934380,"seconds":0.0,"name":"TechDemo B_save"}} \ No newline at end of file +{"category":"Demo Category","number":2,"description":"River Stage","scene":"RiverWorld","use_install_folder":true,"solution":{"ValidationSet":[{"MasterIDs":["http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2888"],"SolutionIndex":[],"RelationIndex":[],"ComparerString":"LineFactHightDirectionComparer"},{"MasterIDs":["http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2888"],"SolutionIndex":[],"RelationIndex":[],"ComparerString":"LineSpanningOverRiverWorldComparer"},{"MasterIDs":[],"SolutionIndex":[1],"RelationIndex":[0],"ComparerString":"LineFactHightComparer"}],"FactDict":{"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2886":{"s_type":"PointFact","Point":{"x":0.0,"y":0.0,"z":0.0,"magnitude":0.0,"sqrMagnitude":0.0},"Normal":{"x":0.0,"y":1.0,"z":0.0,"magnitude":1.0,"sqrMagnitude":1.0},"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2886","Label":"A","hasCustomLabel":false,"LabelId":1},"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2887":{"s_type":"PointFact","Point":{"x":0.0,"y":6.0,"z":0.0,"normalized":{"x":0.0,"y":1.0,"z":0.0,"magnitude":1.0,"sqrMagnitude":1.0},"magnitude":6.0,"sqrMagnitude":36.0},"Normal":{"x":0.0,"y":1.0,"z":0.0,"magnitude":1.0,"sqrMagnitude":1.0},"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2887","Label":"B","hasCustomLabel":false,"LabelId":2},"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2888":{"s_type":"LineFact","Distance":6.0,"Pid1":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2886","Pid2":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2887","Dir":{"x":0.0,"y":1.0,"z":0.0,"magnitude":1.0,"sqrMagnitude":1.0},"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2888","Label":"[AB]","hasCustomLabel":false,"LabelId":0}},"MetaInf":{"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2886":{"workflow_id":0,"active":true},"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2887":{"workflow_id":1,"active":true},"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2888":{"workflow_id":2,"active":true}},"Workflow":[{"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2886","samestep":false,"steplink":3,"creation":true},{"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2887","samestep":true,"steplink":0,"creation":true},{"Id":"http://mathhub.info/FrameIT/frameworld/integrationtests?SampleSituationSpace/Root?fact2888","samestep":true,"steplink":0,"creation":true}],"marker":3,"worksteps":1,"backlog":0,"soft_resetted":false,"invoke":true,"MaxLabelId":2,"UnusedLabelIds":[],"name":null,"path":null},"name":"TechDemo B","path":null} \ No newline at end of file