Skip to content
Snippets Groups Projects
ScrollDetails.cs 12.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • using System.Collections;
    using System.Collections.Generic;
    
    using UnityEngine;
    
    using TMPro;
    
    using UnityEngine.Networking;
    
    using Newtonsoft.Json;
    
    using System.Linq;
    
    MaZiFAU's avatar
    MaZiFAU committed
    using static CommunicationEvents;
    
    using static SOMDocManager;
    
    MaZiFAU's avatar
    MaZiFAU committed
    using System;
    using static Scroll;
    
    
    public class ScrollDetails : MonoBehaviour
    {
    
    MaZiFAU's avatar
    MaZiFAU committed
        public static ScrollDetails Instance
        {
            get => _Instance;
            set
            {
                if (_Instance == null)
                    _Instance = value;
                else
                    Destroy(value);
            }
        }
        private static ScrollDetails _Instance;
    
    
    Richard Marcus's avatar
    Richard Marcus committed
        public WorldCursor cursor;
    
        public GameObject parameterDisplayPrefab;
    
        public Scroll ActiveScroll;
    
        public GameObject mmtAnswerPopUp;
    
    MaZiFAU's avatar
    MaZiFAU committed
        private PopupBehavior Popup;
    
    MaZiFAU's avatar
    MaZiFAU committed
        public static List<RenderedScrollFact> ParameterDisplays;
    
    MaZiFAU's avatar
    MaZiFAU committed
        private static List<ScrollAssignment> LatestCompletions;
    
        private static List<Fact> LatestRenderedHints;
    
    MaZiFAU's avatar
    MaZiFAU committed
        public bool DynamicScrollDescriptionsActive = true;
        public bool AutomaticHintGenerationActive = true;
    
    
    MaZiFAU's avatar
    MaZiFAU committed
        private bool DynamicScrollDone = true;
    
    MaZiFAU's avatar
    MaZiFAU committed
        void Awake()
    
    MaZiFAU's avatar
    MaZiFAU committed
            Instance = this;
    
    
    MaZiFAU's avatar
    MaZiFAU committed
            if (cursor == null)
                cursor = FindObjectOfType<WorldCursor>();
    
    
    MaZiFAU's avatar
    MaZiFAU committed
            Popup = mmtAnswerPopUp.GetComponent<PopupBehavior>();
            Popup.gameObject.SetActive(true); // force Awake
    
    Richard Marcus's avatar
    Richard Marcus committed
    
    
        private void OnEnable()
        {
    
            ScrollFactHintEvent.AddListener(animateHint);
    
    MaZiFAU's avatar
    MaZiFAU committed
            NewAssignmentEvent.AddListener(NewAssignmentTrigger);
    
        private void OnDisable()
        {
            ScrollFactHintEvent.RemoveListener(animateHint);
    
    MaZiFAU's avatar
    MaZiFAU committed
            NewAssignmentEvent.RemoveListener(NewAssignmentTrigger);
    
    MaZiFAU's avatar
    MaZiFAU committed
        private void OnDestroy()
        {
            _Instance = null;
        }
    
    
    MaZiFAU's avatar
    MaZiFAU committed
        public void SetScroll(Scroll scroll_to_set)
    
    BenniHome's avatar
    BenniHome committed
        {
    
    MaZiFAU's avatar
    MaZiFAU committed
            ActiveScroll = scroll_to_set;
    
            Transform originalScroll = gameObject.transform.GetChild(1);
    
            Transform originalScrollView = originalScroll.GetChild(1);
            Transform originalViewport = originalScrollView.GetChild(0);
    
    
            //Clear all current ScrollFacts
    
            originalViewport.GetChild(0).gameObject.DestroyAllChildren();
    
    MaZiFAU's avatar
    MaZiFAU committed
            originalScroll.GetChild(0).GetComponent<TextMeshProUGUI>().text = ActiveScroll.description;
    
            //ParameterDisplays.ForEach(gameObj => Destroy(gameObj));
            ParameterDisplays = new();
            for (int i = 0; i < ActiveScroll.requiredFacts.Count; i++)
    
    BenniHome's avatar
    BenniHome committed
            {
    
    MaZiFAU's avatar
    MaZiFAU committed
                GameObject originalObj =
                    Instantiate(parameterDisplayPrefab, originalViewport.GetChild(0));
    
    MaZiFAU's avatar
    MaZiFAU committed
                RenderedScrollFact originalRSF =
                    originalObj.GetComponentInChildren<RenderedScrollFact>();
    
    MaZiFAU's avatar
    MaZiFAU committed
                ParameterDisplays.Add(originalRSF);
    
                originalRSF.Populate(ActiveScroll, i);
    
            foreach (int i in PrePopulateActiveScroll())
                ParameterDisplays[i].gameObject.SetActive(false);
    
    
            //set active scroll for ErrorMessagePopup
    
    MaZiFAU's avatar
    MaZiFAU committed
            Popup.ActiveScroll = ActiveScroll;
            Popup.ParameterDisplays = ParameterDisplays;
    
    MaZiFAU's avatar
    MaZiFAU committed
        public bool SetNextEmptyTo(FactObjectUI activator)
        {
            RenderedScrollFact check = ParameterDisplays
                .Find(RSF => RSF != null
                          && RSF.Payload != null
                          && RSF.Payload.Equals(activator)
            );
    
            if (check != null)
            {
                check.URI = null;
                return false;
            }
    
            RenderedScrollFact empty = ParameterDisplays
                .Find(RSF => !RSF.IsSet);
    
            if (empty == null)
                return false;
    
            empty.SetByFactObject(activator);
            return true;
        }
    
    
        /// <summary>
        /// Secretly populates <see cref="Scroll"/>s
        /// </summary>
        /// <returns><c>Array</c> containing indicis of <see cref="Scroll.requiredFacts"/> to be hidden.</returns>
        private int[] PrePopulateActiveScroll()
        {
            switch (ActiveScroll.@ref)
            {
    
    MaZiFAU's avatar
    MaZiFAU committed
                case MMT_OMS_URI.ScrollCannonBall:
                    return new int[] { 2 };
    
    
                default:
                    return new int[0];
            }
        }
    
    
    MaZiFAU's avatar
    MaZiFAU committed
        public void MagicButtonTrigger()
    
    MaZiFAU's avatar
    MaZiFAU committed
            StartCoroutine(_MagicButton());
    
    MaZiFAU's avatar
    MaZiFAU committed
            IEnumerator _MagicButton()
    
    BenniHome's avatar
    BenniHome committed
            {
    
    MaZiFAU's avatar
    MaZiFAU committed
                while (!DynamicScrollDone)
                    yield return null; // Wait for last assignment
    
                DynamicScrollDone = false;
    
    MaZiFAU's avatar
    MaZiFAU committed
                yield return SendView("/scroll/apply");
    
    MaZiFAU's avatar
    MaZiFAU committed
                DynamicScrollDone = true;
    
    MaZiFAU's avatar
    MaZiFAU committed
    
    
                if (currentMmtAnswer == null)
                {
    
    MaZiFAU's avatar
    MaZiFAU committed
                    Debug.LogError("Magic FAILED");
    
    MaZiFAU's avatar
    MaZiFAU committed
                    ScrollApplicationCheckingErrorEvent.Invoke(null);
    
    MaZiFAU's avatar
    MaZiFAU committed
                    if (VerboseURI)
                        Debug.Log("Magic answers:\n" + currentMmtAnswer);
    
    
    MaZiFAU's avatar
    MaZiFAU committed
                    ScrollApplicationInfo pushout = JsonConvert.DeserializeObject<ScrollApplicationInfo>(currentMmtAnswer);
    
    MaZiFAU's avatar
    MaZiFAU committed
    
    
    MaZiFAU's avatar
    MaZiFAU committed
                    if (pushout.acquiredFacts.Count == 0
                     || pushout.errors.Length > 0)
                    {
                        ScrollApplicationCheckingErrorEvent.Invoke(pushout.errors);
                        PushoutFactFailEvent.Invoke();
                    }
    
    MaZiFAU's avatar
    MaZiFAU committed
    
                    ReadPushout(pushout.acquiredFacts);
    
    John Schihada's avatar
    John Schihada committed
    
    
    MaZiFAU's avatar
    MaZiFAU committed
        public void NewAssignmentTrigger()
    
    MaZiFAU's avatar
    MaZiFAU committed
            if (AutomaticHintGenerationActive || DynamicScrollDescriptionsActive)
                StartCoroutine(_NewAssignment());
    
    MaZiFAU's avatar
    MaZiFAU committed
            IEnumerator _NewAssignment()
    
    MaZiFAU's avatar
    MaZiFAU committed
                while (!DynamicScrollDone)
                    yield return null; // if we dont wait => server will crash
    
                DynamicScrollDone = false;
    
    MaZiFAU's avatar
    MaZiFAU committed
                yield return SendView("/scroll/dynamic");
    
    MaZiFAU's avatar
    MaZiFAU committed
                DynamicScrollDone = true;
    
    
                if (currentMmtAnswer == null)
                {
    
    MaZiFAU's avatar
    MaZiFAU committed
                    Debug.LogError("Dynamic Scroll FAILED");
    
    MaZiFAU's avatar
    MaZiFAU committed
                    ScrollDynamicInfo scrollDynamicInfo;
                    try
                    {
                        scrollDynamicInfo = JsonConvert.DeserializeObject<ScrollDynamicInfo>(currentMmtAnswer);
                    }
                    catch (JsonSerializationException ex)
                    {
                        Debug.LogException(ex);
                        Debug.LogError("Could not Deserialize MMT aswer for /scroll/dynamic\n" + currentMmtAnswer);
                        yield break;
                    }
    
                    ScrollApplicationCheckingError[] errors = scrollDynamicInfo.errors
                        .Where(err => err.kind != "nonTotal") // expected
                        .ToArray();
    
                    if (errors.Length > 0)
                        ScrollApplicationCheckingErrorEvent.Invoke(errors);
    
    
                    processScrollDynamicInfo(scrollDynamicInfo);
                }
    
    MaZiFAU's avatar
    MaZiFAU committed
        private IEnumerator SendView(string endpoint)
    
    BenniHome's avatar
    BenniHome committed
        {
    
            while (ParameterDisplays == null) // Wait for server
    
    MaZiFAU's avatar
    MaZiFAU committed
                yield return null;
    
    
            string body = prepareScrollAssignments();
    
    BenniHome's avatar
    BenniHome committed
    
    
            using UnityWebRequest www = UnityWebRequest.Put(ServerAdress + endpoint, body);
    
    BenniHome's avatar
    BenniHome committed
            www.method = UnityWebRequest.kHttpVerbPOST;
    
            www.SetRequestHeader("Content-Type", "application/json");
    
    MaZiFAU's avatar
    MaZiFAU committed
            System.DateTime sendTime = System.DateTime.UtcNow;
            yield return www.SendWebRequest();
            if (VerboseURI)
                Debug.LogFormat("Server answerd in : {0}ms"
                    , (System.DateTime.UtcNow - sendTime).TotalMilliseconds);
    
    BenniHome's avatar
    BenniHome committed
    
    
            if (www.result == UnityWebRequest.Result.ConnectionError
    
             || www.result == UnityWebRequest.Result.ProtocolError)
    
    BenniHome's avatar
    BenniHome committed
            {
                Debug.Log(www.error);
    
    Benjamin Bösl's avatar
    Benjamin Bösl committed
            }
    
                string answer = www.downloadHandler.text;
    
    MaZiFAU's avatar
    MaZiFAU committed
            string prepareScrollAssignments()
            {
    
    MaZiFAU's avatar
    MaZiFAU committed
                List<ScrollAssignment> assignmentList = new();
    
    MaZiFAU's avatar
    MaZiFAU committed
                for (int i = 0; i < ParameterDisplays.Count; i++)
                {
                    Fact tempFact = ParameterDisplays[i].Fact;
                    if (tempFact != null)
    
    MaZiFAU's avatar
    MaZiFAU committed
                        assignmentList.Add(new ScrollAssignment(ActiveScroll.requiredFacts[i].@ref.uri, tempFact.Id));
    
    MaZiFAU's avatar
    MaZiFAU committed
                }
    
    MaZiFAU's avatar
    MaZiFAU committed
                return JsonConvert.SerializeObject(new FilledScroll(ActiveScroll.@ref, assignmentList));
    
    MaZiFAU's avatar
    MaZiFAU committed
        private void ReadPushout(List<MMTDeclaration> pushoutFacts)
    
    MaZiFAU's avatar
    MaZiFAU committed
            Popup.HidePopUp(); //close error Window
    
    MaZiFAU's avatar
    MaZiFAU committed
            for (int i = 0; i < pushoutFacts.Count; i++)
    
            {
                Fact newFact = ParsingDictionary.parseFactDictionary[pushoutFacts[i].getType()].Invoke(pushoutFacts[i]);
    
                if (newFact != null)
    
    MaZiFAU's avatar
    MaZiFAU committed
                {
    
                    AnimateExistingFactEvent.Invoke
                        (FactManager.AddFactIfNotFound(newFact, out _, samestep, null, ActiveScroll.label).Id
                        , FactWrapper.FactMaterials.Solution);
    
    MaZiFAU's avatar
    MaZiFAU committed
    
                    samestep = true;
                }
    
                    Debug.Log("Parsing on pushout-fact returned null -> One of the dependent facts does not exist");
    
    MaZiFAU's avatar
    MaZiFAU committed
        private void processScrollDynamicInfo(ScrollDynamicInfo scrollDynamicInfo)
    
    MaZiFAU's avatar
    MaZiFAU committed
            LatestCompletions = scrollDynamicInfo.completions.Count > 0
                ? scrollDynamicInfo.completions[0]
    
    MaZiFAU's avatar
    MaZiFAU committed
                : new List<ScrollAssignment>();
    
    MaZiFAU's avatar
    MaZiFAU committed
            List<string> hintUris = LatestCompletions
                .Select(completion => completion.fact.uri)
                .ToList();
    
            //Update Scroll, process data for later hints and update Uri-List for which hints are available
    
    MaZiFAU's avatar
    MaZiFAU committed
            _processRenderedScroll(scrollDynamicInfo.rendered, hintUris);
    
    MaZiFAU's avatar
    MaZiFAU committed
            if (AutomaticHintGenerationActive)
    
                //Show that Hint is available for ScrollParameter
                HintAvailableEvent.Invoke(hintUris);
    
    MaZiFAU's avatar
    MaZiFAU committed
            return;
    
    MaZiFAU's avatar
    MaZiFAU committed
            void _processRenderedScroll(Scroll rendered, List<string> hintUris)
    
    MaZiFAU's avatar
    MaZiFAU committed
                if (DynamicScrollDescriptionsActive)
                { // Update scroll-description
                    Transform scroll = gameObject.transform.GetChild(1).transform;
                    scroll.GetChild(0).GetComponent<TextMeshProUGUI>().text = rendered.description;
    
    MaZiFAU's avatar
    MaZiFAU committed
                LatestRenderedHints = new();
                for (int i = 0; i < rendered.requiredFacts.Count; i++)
    
    MaZiFAU's avatar
    MaZiFAU committed
                    RenderedScrollFact RenderedScrollFact = ParameterDisplays
    
                        .Find(RSF => RSF.ScrollFactURI == rendered.requiredFacts[i].@ref.uri);
    
    MaZiFAU's avatar
    MaZiFAU committed
                    if (DynamicScrollDescriptionsActive)
                        //Update ScrollParameter label
                        RenderedScrollFact.Scroll = rendered;
    
    MaZiFAU's avatar
    MaZiFAU committed
                    //If ScrollFact is assigned -> No Hint
    
    MaZiFAU's avatar
    MaZiFAU committed
                    if (!RenderedScrollFact.IsSet)
    
                        Fact HintFact =
                            ParsingDictionary.parseFactDictionary[rendered.requiredFacts[i].getType()]
                            .Invoke(rendered.requiredFacts[i]);
    
    MaZiFAU's avatar
    MaZiFAU committed
    
                        //If the fact could not be parsed -> Therefore not all dependent Facts exist -> No Hint
    
                        if (HintFact != null)
                        {
    
    MaZiFAU's avatar
    MaZiFAU committed
                            hintUris.Add(HintFact.Id);
                            LatestRenderedHints.Add(HintFact);
                        }
    
    MaZiFAU's avatar
    MaZiFAU committed
                return;
            }
    
    MaZiFAU's avatar
    MaZiFAU committed
        public void animateHint(string scrollParameterUri)
    
            if (FactOrganizer.AllFacts.ContainsKey(scrollParameterUri))
                AnimateExistingFactEvent.Invoke(
                        scrollParameterUri,
                        FactWrapper.FactMaterials.Hint
                    );
    
    
    MaZiFAU's avatar
    MaZiFAU committed
            Fact hintFact = LatestRenderedHints.Find(x => x.Id == scrollParameterUri);
    
            ScrollAssignment suitableCompletion =
    
                LatestCompletions.Find(x => x.fact.uri == scrollParameterUri);
    
            if (suitableCompletion != null)
            {
    
    MaZiFAU's avatar
    MaZiFAU committed
                if (FactOrganizer.AllFacts.ContainsKey(suitableCompletion.assignment.uri))
    
                    AnimateExistingFactEvent.Invoke(
                        suitableCompletion.assignment.uri,
                        FactWrapper.FactMaterials.Hint
                    );
    
    MaZiFAU's avatar
    MaZiFAU committed
            else if (hintFact != null)
    
    MaZiFAU's avatar
    MaZiFAU committed
                if (FactOrganizer.FindEquivalent(StageStatic.stage.factState.MyFactSpace, hintFact, out string found_key, out Fact _, out bool _, false))
    
                    // existing fact -> Animate that
                    AnimateExistingFactEvent.Invoke(
    
    MaZiFAU's avatar
    MaZiFAU committed
                        found_key,
    
                        FactWrapper.FactMaterials.Hint
                    );
    
    MaZiFAU's avatar
    MaZiFAU committed
                {   // Generate new FactRepresentation and animate it
                    AnimateNonExistingFactEvent.Invoke(hintFact);
    
                    AnimateExistingFactEvent.Invoke(
                        scrollParameterUri,
                        FactWrapper.FactMaterials.Hint
                    );