using System.Collections; using System.Collections.Generic; using UnityEngine; using TMPro; using UnityEngine.Networking; using Newtonsoft.Json; using static CommunicationEvents; using System.Linq; using static SOMDocManager; public class ScrollDetails : MonoBehaviour { public WorldCursor cursor; public GameObject parameterDisplayPrefab; public Scroll ActiveScroll; public GameObject mmtAnswerPopUp; public static List<GameObject> ParameterDisplays; private static List<Scroll.ScrollAssignment> LatestCompletions; private static List<Fact> LatestRenderedHints; public string currentMmtAnswer; public bool dynamicScrollDescriptionsActive = true; public bool automaticHintGenerationActive = true; // Start is called before the first frame update void Start() { cursor ??= GameObject.FindObjectOfType<WorldCursor>(); mmtAnswerPopUp.GetComponent<PopupBehavior>().hidePopUp(); } private void OnEnable() { ScrollFactHintEvent.AddListener(animateHint); NewAssignmentEvent.AddListener(newAssignmentTrigger); RemoveFactEvent.AddListener(removeFactFromAssignment); } private void OnDisable() { ScrollFactHintEvent.RemoveListener(animateHint); NewAssignmentEvent.RemoveListener(newAssignmentTrigger); RemoveFactEvent.RemoveListener(removeFactFromAssignment); } public void setScroll(Scroll s) { Transform originalScroll = gameObject.transform.GetChild(1).transform; Transform originalScrollView = originalScroll.GetChild(1); Transform originalViewport = originalScrollView.GetChild(0); this.ActiveScroll = s; originalScroll.GetChild(0).GetComponent<TextMeshProUGUI>().text = s.description; //Clear all current ScrollFacts originalViewport.GetChild(0).gameObject.DestroyAllChildren(); ParameterDisplays = new List<GameObject>(); for (int i = 0; i < s.requiredFacts.Count; i++) { var originalObj = Instantiate(parameterDisplayPrefab, Vector3.zero, Quaternion.identity, transform); var originalScrollFact = originalObj.transform.GetChild(0).GetComponent<RenderedScrollFact>(); originalScrollFact.ID = i; originalScrollFact.Label = s.requiredFacts[i].label; originalScrollFact.factUri = s.requiredFacts[i].@ref.uri; originalObj.transform.SetParent(originalViewport.GetChild(0)); ParameterDisplays.Add(originalObj); } //set active scroll for ErrorMessagePopup PopupBehavior popup = mmtAnswerPopUp.GetComponent<PopupBehavior>(); popup.setScroll(this.ActiveScroll); popup.setParameterDisplays(ParameterDisplays); } public void magicButtonTrigger() { StartCoroutine(magicButton()); IEnumerator magicButton() { //Non blocking wait till sendView() is finished yield return sendView("/scroll/apply"); if (currentMmtAnswer == null) { Debug.Log("DAS HAT NICHT GEKLAPPT"); PushoutFactFailEvent.Invoke(null, null); } else { Debug.Log(currentMmtAnswer); Scroll.ScrollApplicationInfo pushout = JsonConvert.DeserializeObject<Scroll.ScrollApplicationInfo>(currentMmtAnswer); if (pushout.acquiredFacts.Count == 0) PushoutFactFailEvent.Invoke(null, pushout); readPushout(pushout.acquiredFacts); } } } public void newAssignmentTrigger() { if (this.automaticHintGenerationActive || this.dynamicScrollDescriptionsActive) StartCoroutine(newAssignment()); IEnumerator newAssignment() { //Non blocking wait till sendView() is finished yield return sendView("/scroll/dynamic"); if (currentMmtAnswer == null) { Debug.Log("DAS HAT NICHT GEKLAPPT"); } else { // Todo delte maybe Debug.Log("Current mmt answer: " + currentMmtAnswer); Scroll.ScrollDynamicInfo scrollDynamicInfo = JsonConvert.DeserializeObject<Scroll.ScrollDynamicInfo>(currentMmtAnswer); processScrollDynamicInfo(scrollDynamicInfo); } } } IEnumerator sendView(string endpoint) { string body = prepareScrollAssignments(); System.DateTime startTime = System.DateTime.UtcNow; using UnityWebRequest www = UnityWebRequest.Put(ServerAdress + endpoint, body); www.method = UnityWebRequest.kHttpVerbPOST; www.SetRequestHeader("Content-Type", "application/json"); yield return www.SendWebRequest(); System.DateTime twoTime = System.DateTime.UtcNow; if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError) { Debug.Log(www.error); currentMmtAnswer = null; } else { string answer = www.downloadHandler.text; currentMmtAnswer = answer; } System.DateTime endTime = System.DateTime.UtcNow; string diffInSeconds = (endTime - startTime).TotalMilliseconds.ToString(); string diff = (twoTime - startTime).TotalMilliseconds.ToString(); } private string prepareScrollAssignments() { List<Scroll.ScrollAssignment> assignmentList = new(); for (int i = 0; i < ParameterDisplays.Count; i++) { Fact tempFact = ParameterDisplays[i].GetComponentInChildren<DropHandling>().currentFact; if (tempFact != null) assignmentList.Add(new Scroll.ScrollAssignment(ActiveScroll.requiredFacts[i].@ref.uri, tempFact.Id)); } return JsonConvert.SerializeObject(new Scroll.FilledScroll(ActiveScroll.@ref, assignmentList)); } private void readPushout(List<MMTDeclaration> pushoutFacts) { mmtAnswerPopUp.GetComponent<PopupBehavior>().hidePopUp(); //close error Window bool samestep = false; for (int i = 0; i < pushoutFacts.Count; i++, samestep = true) { Fact newFact = ParsingDictionary.parseFactDictionary[pushoutFacts[i].getType()].Invoke(pushoutFacts[i]); if (newFact != null) PushoutFactEvent.Invoke(FactManager.AddFactIfNotFound(newFact, out _, samestep, null, ActiveScroll.label), FactObject.FactMaterials.Solution); else Debug.Log("Parsing on pushout-fact returned null -> One of the dependent facts does not exist"); } } public void processScrollDynamicInfo(Scroll.ScrollDynamicInfo scrollDynamicInfo) { LatestCompletions = scrollDynamicInfo.completions.Count > 0 ? scrollDynamicInfo.completions[0] : new List<Scroll.ScrollAssignment>(); 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 hintUris = processRenderedScroll(scrollDynamicInfo.rendered, hintUris); if (automaticHintGenerationActive) //Show that Hint is available for ScrollParameter HintAvailableEvent.Invoke(hintUris); } public List<string> processRenderedScroll(Scroll rendered, List<string> hintUris) { Transform scroll = gameObject.transform.GetChild(1).transform; if (this.dynamicScrollDescriptionsActive) //Update scroll-description scroll.GetChild(0).GetComponent<TextMeshProUGUI>().text = rendered.description; LatestRenderedHints = new List<Fact>(); for (int i = 0; i < rendered.requiredFacts.Count; i++) { GameObject obj = ParameterDisplays.Find(x => x.transform.GetChild(0).GetComponent<RenderedScrollFact>().factUri.Equals(rendered.requiredFacts[i].@ref.uri)); if (this.dynamicScrollDescriptionsActive) { //Update ScrollParameter label obj.transform.GetChild(0).GetComponent<RenderedScrollFact>().Label = rendered.requiredFacts[i].label; } //Check Hint Informations //If ScrollFact is assigned -> No Hint if (obj.transform.GetChild(0).GetComponent<DropHandling>().currentFact == null) { // Debug.Log(" print out " + rendered.requiredFacts[i].getType()); Fact currentFact = ParsingDictionary.parseFactDictionary[rendered.requiredFacts[i].getType()].Invoke(rendered.requiredFacts[i]); //If currentFact could be parsed: this fact maybe not yet exists in the global fact-list but there must be a fact // of the same type and the same dependent facts in the fact-list, otherwise currentFact could not have been parsed //If the fact could not be parsed -> Therefore not all dependent Facts exist -> No Hint //AND if fact has no dependent facts -> No Hint if (currentFact != null && currentFact.HasDependentFacts) { //Hint available for abstract-problem uri hintUris.Add(currentFact.Id); LatestRenderedHints.Add(currentFact); } } } return hintUris; } public void animateHint(GameObject scrollParameter, string scrollParameterUri) { Scroll.ScrollAssignment suitableCompletion = LatestCompletions.Find(x => x.fact.uri.Equals(scrollParameterUri)); Fact fact; if (suitableCompletion != null) { if (StageStatic.stage.factState.ContainsKey(suitableCompletion.assignment.uri)) { fact = FactOrganizer.AllFacts[suitableCompletion.assignment.uri]; //Animate ScrollParameter scrollParameter.GetComponentInChildren<ImageHintAnimation>().AnimationTrigger(); //Animate Fact in FactPanel AnimateExistingFactEvent.Invoke(fact, FactObject.FactMaterials.Hint); } } else if (LatestRenderedHints.Exists(x => x.Id.Equals(scrollParameterUri))) { fact = LatestRenderedHints.Find(x => x.Id.Equals(scrollParameterUri)); var factId = fact.Id; //If there is an equal existing fact -> Animate that fact AND ScrollParameter if (StageStatic.stage.factState.ContainsKey(factId)) { Fact existingFact = FactOrganizer.AllFacts[factId]; //Animate ScrollParameter scrollParameter.GetComponentInChildren<ImageHintAnimation>().AnimationTrigger(); //Animate Fact in FactPanel AnimateExistingFactEvent.Invoke(existingFact, FactObject.FactMaterials.Hint); } //If not -> Generate a Fact-Representation with such dependent facts else { //Animate ScrollParameter scrollParameter.GetComponentInChildren<ImageHintAnimation>().AnimationTrigger(); //Generate new FactRepresentation and animate it AnimateNonExistingFactEvent.Invoke(fact); } } } //this is called whenever a Fact is Deleted in the world, to make sure it is removed from the scroll public void removeFactFromAssignment(Fact fact) { Transform originalScroll = gameObject.transform.GetChild(1).transform; Transform originalScrollView = originalScroll.GetChild(1); Transform originalViewport = originalScrollView.GetChild(0); for (int i = 0; i < originalViewport.GetChild(0).childCount; i++) { RenderedScrollFact scrollFact = originalViewport.GetChild(0).transform.GetChild(i).GetChild(0).gameObject.GetComponent<RenderedScrollFact>(); if (scrollFact.Label == fact.Label) { DropHandling dropHandling = originalViewport.GetChild(0).transform.GetChild(i).GetChild(0).gameObject.GetComponent<DropHandling>(); dropHandling.OnPointerClick(null); } } } }