From 893fe709cd064c6b9460693535d56ae537f31308 Mon Sep 17 00:00:00 2001 From: baletiballo <75846481+baletiballo@users.noreply.github.com> Date: Sat, 1 Mar 2025 20:26:57 +0100 Subject: [PATCH] Parser for Objects from the backend --- .../ScrollView_Server/build/API_Parsers.js | 51 +++++++++++ .../ScrollView_Server/build/Facts.js | 68 +++++++++++++++ .../build/SetScrollContent.js | 79 ++--------------- .../ScrollView_Server/scrollView.html | 16 ++-- .../ScrollView_Server/src/API_Parsers.ts | 58 +++++++++++++ .../ScrollView_Server/src/Facts.ts | 80 +++++++++++++++++ .../ScrollView_Server/src/SetScrollContent.ts | 86 ++----------------- 7 files changed, 277 insertions(+), 161 deletions(-) create mode 100644 Assets/StreamingAssets/ScrollView_Server/build/API_Parsers.js create mode 100644 Assets/StreamingAssets/ScrollView_Server/src/API_Parsers.ts diff --git a/Assets/StreamingAssets/ScrollView_Server/build/API_Parsers.js b/Assets/StreamingAssets/ScrollView_Server/build/API_Parsers.js new file mode 100644 index 00000000..2c213fd6 --- /dev/null +++ b/Assets/StreamingAssets/ScrollView_Server/build/API_Parsers.js @@ -0,0 +1,51 @@ +"use strict"; +// A hack to make a list of strings on type level. +// If you add another type to be parsable i.e. implement a parser for it, also add its name here +const parsable = ["string", "MathMLElement", "HTMLElement", "SVGElement"]; +function is_primitive(a) { + return "parseAs" in a + && parsable.includes(a.parseAs) + && "content" in a + && typeof a.content === "string"; +} +function backendObject_fromJSON(json_object) { + const parser = new DOMParser; + // just a shorthand we will need several times + const parse = function (s) { + const element = parser.parseFromString(s, "text/xml").childNodes[0]; + return element; + }; + // the Backend_Object to be + const bo = {}; + for (let i in json_object) { + const member = json_object[i]; + if (is_primitive(member)) { + switch (member.parseAs) { + case "string": + bo[i] = member.content; + break; + case "MathMLElement": + bo[i] = parse(member.content); + break; + case "HTMLElement": + bo[i] = parse(member.content); + break; + case "SVGElement": + bo[i] = parse(member.content); + break; + } + } + else { + bo[i] = backendObject_fromJSON(member); + } + } + if (bo.label instanceof MathMLElement + && typeof bo.uri === "string" + && typeof bo.type === "string") { + return bo; + } + else { + console.error(`This is not a Backend_Object:`, json_object); + throw new TypeError(`This is not a Backend_Object: \n ${json_object}`); + } +} diff --git a/Assets/StreamingAssets/ScrollView_Server/build/Facts.js b/Assets/StreamingAssets/ScrollView_Server/build/Facts.js index 70f7fa2b..a4e7678c 100644 --- a/Assets/StreamingAssets/ScrollView_Server/build/Facts.js +++ b/Assets/StreamingAssets/ScrollView_Server/build/Facts.js @@ -1,4 +1,14 @@ "use strict"; +/** + * A {@link Backend_Object} without any further properties known to us + */ +class Pure_Reference { + constructor(label, uri, type) { + this.label = label; + this.uri = uri; + this.type = type ? type : "none"; + } +} /** * A fact without any value known to us */ @@ -174,3 +184,61 @@ class Ray_Fact extends Line_Fact { this.type = "Ray_Fact"; } } +//#endregion Facts +/** + * A Slot is an interface that can stand in for either + * - a {@link Fact}, or + * - the {@link Backend_Object} used to define the {@link Scroll} (in the backend) + * + * depending on what is needed. + * + * If all Slots of a {@link Scroll} are assigned, it can compute its {@link Scroll.acquiredFacts}. + */ +class Slot { + /** + * @param default_label The default label of the Slot. Fallback if no Fact is assigned. + * @param uri The uri of the Slot + * @param type The expected type of the assigned Fact + * @param assignedFact The Fact assigned to this Slot (may not exist yet) + */ + constructor(default_label, uri, type, assignedFact) { + this.default_label = default_label; + this.uri = uri; + this.type = type; + this.assignedFact = assignedFact; + } + /** + * The MathML element to display when this Slot is referenced. + * + * This is either the label of the {@link assignedFact}, or {@link default_label} if the former doesn't exist. + */ + get label() { + if (this.assignedFact) { + return this.assignedFact.label; + } + else { + return this.default_label; + } + } +} +/** + * A Scroll, as it is implemented in the backend. + * + * Can do fancy stuff elsewhere, here we only want display its {@link description} and (possibly) {@link depiction}. + * Both will reference the {@link slots}, and need dynamic adaption to the {@link Fact}s assigned to them. + * The {@link acquiredFacts} referenced do not change, but they are semantically important and deserve special treatment. + */ +class Scroll { + constructor(label, uri, slots, acquiredFacts, description, depiction) { + this.label = label; + this.uri = uri; + this.slots = slots; + this.acquiredFacts = acquiredFacts; + this.description = description; + this.depiction = depiction; + this.type = "Scroll"; + } +} +function isScroll(s) { + return s.type === "Scroll"; +} diff --git a/Assets/StreamingAssets/ScrollView_Server/build/SetScrollContent.js b/Assets/StreamingAssets/ScrollView_Server/build/SetScrollContent.js index 06388b36..a07e9945 100644 --- a/Assets/StreamingAssets/ScrollView_Server/build/SetScrollContent.js +++ b/Assets/StreamingAssets/ScrollView_Server/build/SetScrollContent.js @@ -1,76 +1,4 @@ "use strict"; -/** - * A MMT..whatever. Somewhere between the first and second "meta-" MMT had to leave common nomenclature behind - * @typedef {{kind : string, uri: string}} MMTReference - */ -/** - * Facts, as they are send by MMT. Not *quite* the same format as Unity uses \*sigh\*, and everything has shortened names to avoid five additional letters \*double sigh\* - * @typedef {Object} MMTFact - * @property {MMTReference} ref the reference MMT uses to identify this fact - * @property {string} label the human readable lable to display this fact. - * @property {?any} df the definition of the Fact. May be null for {@link MMTScroll.requiredFacts} - * @property {?MMTReference} tp the MMT type of this fact - * @property {string} kind since a Fact is a MMTThingy, they also have a {@link MMTReference.kind} - */ -/** - * A Slot is an interface that can stand in for either - * - a {@link Fact}, or - * - the {@link Backend_Object} used to define the {@link Scroll} (in the backend) - * - * depending on what is needed. - * - * If all Slots of a {@link Scroll} are assigned, it can compute its {@link Scroll.acquiredFacts}. - */ -class Slot { - /** - * @param default_label The default label of the Slot. Fallback if no Fact is assigned. - * @param uri The uri of the Slot - * @param type The expected type of the assigned Fact - * @param assignedFact The Fact assigned to this Slot (may not exist yet) - */ - constructor(default_label, uri, type, assignedFact) { - this.default_label = default_label; - this.uri = uri; - this.type = type; - this.assignedFact = assignedFact; - this.assignedFact = assignedFact; - } - /** - * The MathML element to display when this Slot is referenced. - * - * This is either the label of the {@link assignedFact}, or {@link default_label} if the former doesn't exist. - */ - get label() { - if (this.assignedFact) { - return this.assignedFact.label; - } - else { - return this.default_label; - } - } -} -/** - * A Scroll, as it is implemented in the backend. - * - * Can do fancy stuff elsewhere, here we only want display its {@link description} and (possibly) {@link depiction}. - * Both will reference the {@link slots}, and need dynamic adaption to the {@link Fact}s assigned to them. - * The {@link acquiredFacts} referenced do not change, but they are semantically important and deserve special treatment. - */ -class Scroll { - constructor(label, uri, slots, acquiredFacts, description, depiction) { - this.label = label; - this.uri = uri; - this.slots = slots; - this.acquiredFacts = acquiredFacts; - this.description = description; - this.depiction = depiction; - this.type = "Scroll"; - } - /** TODO */ - static fromString(scrollString) { - throw new Error("Not implemented."); - } -} let currentScrollRef = ""; // ref of the scroll currently displayed function RenderScroll() { const dataSource = document.querySelector("#Unity-Data-Interface"); @@ -80,7 +8,12 @@ function RenderScroll() { console.error("No Scroll found in the Unity-Data-Interface"); return; } - const scroll = Scroll.fromString(dataSource.dataset.scrollDynamic); + const scroll_json = JSON.parse(dataSource.dataset.scrollDynamic); + const scroll = backendObject_fromJSON(scroll_json); + if (!isScroll(scroll)) { + console.error("The Scroll in the Unity-Data-Interface cannot be parsed"); + return; + } //console.log(scroll.requiredFacts); const scrollContainer = document.querySelector("#scrollContainer"); // replace the description if the scroll changed, otherwise only its content needs update diff --git a/Assets/StreamingAssets/ScrollView_Server/scrollView.html b/Assets/StreamingAssets/ScrollView_Server/scrollView.html index 4cc7c05e..8e6eaea4 100644 --- a/Assets/StreamingAssets/ScrollView_Server/scrollView.html +++ b/Assets/StreamingAssets/ScrollView_Server/scrollView.html @@ -161,18 +161,18 @@ } loadScript("./build/Drop_facts.js") + loadScript("./build/API_Parsers.js") loadScript("./build/SetScrollContent.js") //loadScript("./scroll_interaction/webgl-demo.js") </script> - <script src="./build/Math_Mind.js" type="module"></script> + <!-- <script src="./build/Math_Mind.js" type="module"></script> --> <data id="Unity-Data-Interface" hidden data-assignments='{"http://mathhub.info/FrameIT/frameworld?TriangleProblem?A":{"Item1":"(C)","Item2":"http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact310"},"http://mathhub.info/FrameIT/frameworld?TriangleProblem?B":{"Item1":"(B)","Item2":"http://mathhub.info/FrameIT/frameworld?DefaultSituationSpace/SituationTheory1?fact309"},"http://mathhub.info/FrameIT/frameworld?TriangleProblem?C":{"Item1":"C","Item2":""},"http://mathhub.info/FrameIT/frameworld?TriangleProblem_RightAngleAtC?rightAngleC":{"Item1":"⊾C","Item2":""},"http://mathhub.info/FrameIT/frameworld?OppositeLen/Problem?distanceBC":{"Item1":"BC","Item2":""},"http://mathhub.info/FrameIT/frameworld?TriangleProblem_AngleAtB?angleB":{"Item1":"∠ABC","Item2":""},"http://mathhub.info/FrameIT/frameworld?OppositeLen/Solution?deducedLineCA":{"Item1":"CA","Item2":""}}' data-scroll-dynamic='{ - "ref": "http://mathhub.info/FrameIT/frameworld?OppositeLen", - "label": "OppositeLen", - "description": "<scroll-description title='OppositeLenScroll' alt='Given a triangle △ABC right-angled at ⊾C, the opposite side has length CA = tan(∠ABC) ⋅ BC.'> <span>Given a triangle</span> <math> <mi>△<!-- △ --></mi> <mi data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?A'></mi> <mi data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?B'></mi> <mi data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?C'></mi> </math> <span>right-angled at</span> <math> <!--<mi>⦝</mi>--><!-- ⦝ --> <mi data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem_RightAngleAtC?rightAngleC'></mi> </math>,<br /> <span>the opposite side has length</span> <math> <mi data-solution-id='http://mathhub.info/FrameIT/frameworld?OppositeLen/Solution?deducedLineCA'></mi> <mo>=</mo> <mrow> <mi>tan</mi> <!--<mo>⁡</mo>--> <mo>(</mo> <mi data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem_AngleAtB?angleB'></mi> <mo>)</mo> </mrow> <mo>⁢</mo> <mi data-slot-id='http://mathhub.info/FrameIT/frameworld?OppositeLen/Problem?distanceBC'></mi> </math> <span>.</span> <div> <svg width='50mm' height='45mm' viewBox='35 0 90 70' version='1.1' id='triangle' xmlns='http://www.w3.org/2000/svg' xmlns:svg='http://www.w3.org/2000/svg'> <g id='shape'> <path style='fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' d='M 42.871972,64.67128 H 84.290656 V 7.6297578 Z' id='triangle' /> <path id='angleABC' style='fill:none;stroke:#000000;stroke-width:0.265;stroke-dasharray:none;stroke-opacity:1' d='m 46.024276,60.304806 a 5.3589964,5.3589964 0 0 1 2.252109,4.366474 h -5.358996 z' /> <g id='angleBCA'> <path style='fill:none;stroke:#000000;stroke-width:0.264999;stroke-dasharray:none;stroke-opacity:1' id='rightAngle' d='m 78.972396,64.665062 a 5.3308268,5.3308268 0 0 1 5.330827,-5.330827 v 5.330827 z' /> <circle style='fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-dasharray:none;stroke-opacity:1' id='rightAngleDot' cx='82.081886' cy='62.813831' r='0.32113415' /> </g> </g> <g id='labels' style='font-size:4.23333px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583' > <text xml:space='preserve' x='39.242592' y='67.117035' id='pointB' style='fill:#0000ff' data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?B'>B</text> <text xml:space='preserve' x='85.100548' y='68.080437' id='pointC' style='fill:#0000ff' data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?C'>C</text> <text xml:space='preserve' x='84.650963' y='6.551136' id='pointA' style='fill:#0000ff' data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?A'>A</text> <text xml:space='preserve' x='48.234348' y='62.492699' id='angleAtB' style='fill:#ffcc00' data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem_AngleAtB?angleB'>∠ABC</text> <text xml:space='preserve' x='71.548683' y='60.951256' id='rightAngleAtC' style='fill:#ffcc00' data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem_RightAngleAtC?rightAngleC'>⊾C</text> <text xml:space='preserve' x='59.409813' y='68.273117' id='distanceBC' style='fill:#008000' data-slot-id='http://mathhub.info/FrameIT/frameworld?OppositeLen/Problem?distanceBC'>BC</text> <text xml:space='preserve' x='84.972092' y='35.260529' id='solutionCA' style='fill:#008000' data-solution-id='http://mathhub.info/FrameIT/frameworld?OppositeLen/Solution?deducedLineCA'>CA</text> </g> </svg> </div> </scroll-description>", - "requiredFacts": [ + "uri": "http://mathhub.info/FrameIT/frameworld?OppositeLen", + "label": "<mtext>OppositeLen</mtext>", + "slots": [ { "tp": { "kind": "OMS", @@ -499,9 +499,9 @@ "label": "CA" } ], - "name": "http://mathhub.info/FrameIT/frameworld?OppositeLen", - "path": null - }'>hi</data> + "description": "<scroll-description title='OppositeLenScroll' alt='Given a triangle △ABC right-angled at ⊾C, the opposite side has length CA = tan(∠ABC) ⋅ BC.'> <span>Given a triangle</span> <math> <mi>△<!-- △ --></mi> <mi data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?A'></mi> <mi data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?B'></mi> <mi data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?C'></mi> </math> <span>right-angled at</span> <math> <!--<mi>⦝</mi>--><!-- ⦝ --> <mi data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem_RightAngleAtC?rightAngleC'></mi> </math>,<br /> <span>the opposite side has length</span> <math> <mi data-solution-id='http://mathhub.info/FrameIT/frameworld?OppositeLen/Solution?deducedLineCA'></mi> <mo>=</mo> <mrow> <mi>tan</mi> <!--<mo>⁡</mo>--> <mo>(</mo> <mi data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem_AngleAtB?angleB'></mi> <mo>)</mo> </mrow> <mo>⁢</mo> <mi data-slot-id='http://mathhub.info/FrameIT/frameworld?OppositeLen/Problem?distanceBC'></mi> </math> <span>.</span> </scroll-description>", + "depiction": "<div> <svg width='50mm' height='45mm' viewBox='35 0 90 70' version='1.1' id='triangle' xmlns='http://www.w3.org/2000/svg' xmlns:svg='http://www.w3.org/2000/svg'> <g id='shape'> <path style='fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1' d='M 42.871972,64.67128 H 84.290656 V 7.6297578 Z' id='triangle' /> <path id='angleABC' style='fill:none;stroke:#000000;stroke-width:0.265;stroke-dasharray:none;stroke-opacity:1' d='m 46.024276,60.304806 a 5.3589964,5.3589964 0 0 1 2.252109,4.366474 h -5.358996 z' /> <g id='angleBCA'> <path style='fill:none;stroke:#000000;stroke-width:0.264999;stroke-dasharray:none;stroke-opacity:1' id='rightAngle' d='m 78.972396,64.665062 a 5.3308268,5.3308268 0 0 1 5.330827,-5.330827 v 5.330827 z' /> <circle style='fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264999;stroke-dasharray:none;stroke-opacity:1' id='rightAngleDot' cx='82.081886' cy='62.813831' r='0.32113415' /> </g> </g> <g id='labels' style='font-size:4.23333px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583' > <text xml:space='preserve' x='39.242592' y='67.117035' id='pointB' style='fill:#0000ff' data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?B'>B</text> <text xml:space='preserve' x='85.100548' y='68.080437' id='pointC' style='fill:#0000ff' data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?C'>C</text> <text xml:space='preserve' x='84.650963' y='6.551136' id='pointA' style='fill:#0000ff' data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem?A'>A</text> <text xml:space='preserve' x='48.234348' y='62.492699' id='angleAtB' style='fill:#ffcc00' data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem_AngleAtB?angleB'>∠ABC</text> <text xml:space='preserve' x='71.548683' y='60.951256' id='rightAngleAtC' style='fill:#ffcc00' data-slot-id='http://mathhub.info/FrameIT/frameworld?TriangleProblem_RightAngleAtC?rightAngleC'>⊾C</text> <text xml:space='preserve' x='59.409813' y='68.273117' id='distanceBC' style='fill:#008000' data-slot-id='http://mathhub.info/FrameIT/frameworld?OppositeLen/Problem?distanceBC'>BC</text> <text xml:space='preserve' x='84.972092' y='35.260529' id='solutionCA' style='fill:#008000' data-solution-id='http://mathhub.info/FrameIT/frameworld?OppositeLen/Solution?deducedLineCA'>CA</text> </g> </svg> </div>" + }'>hi</data> <!--<script src="visualiseCursor.mjs" defer type="module"></script>--> <!--<script> diff --git a/Assets/StreamingAssets/ScrollView_Server/src/API_Parsers.ts b/Assets/StreamingAssets/ScrollView_Server/src/API_Parsers.ts new file mode 100644 index 00000000..5d7f39fa --- /dev/null +++ b/Assets/StreamingAssets/ScrollView_Server/src/API_Parsers.ts @@ -0,0 +1,58 @@ +// A hack to make a list of strings on type level. +// If you add another type to be parsable i.e. implement a parser for it, also add its name here +const parsable = ["string", "MathMLElement", "HTMLElement", "SVGElement"] as const +type Primitive = string | MathMLElement | HTMLElement | SVGElement +type Parsable_Primitive = { parseAs: typeof parsable[number], content: string }; +function is_primitive(a: any): a is Parsable_Primitive { + return "parseAs" in a + && parsable.includes(a.parseAs) + && "content" in a + && typeof a.content === "string" +} + +type Parsable_BO = {[key: string]: Parsable_Primitive | Parsable_BO}; + +function backendObject_fromJSON(json_object: Parsable_BO): Backend_Object { + const parser = new DOMParser; + // just a shorthand we will need several times + const parse = function <E extends Element>(s: string): E { + const element = parser.parseFromString(s, "text/xml").childNodes[0] + return element as E + } + + // the Backend_Object to be + const bo: { + [key: keyof typeof json_object]: Primitive | Backend_Object + } = { } + for (let i in json_object) { + const member = json_object[i] + if (is_primitive(member)) { + switch (member.parseAs) { + case "string": + bo[i] = member.content + break; + case "MathMLElement": + bo[i] = parse<MathMLElement>(member.content) + break; + case "HTMLElement": + bo[i] = parse<HTMLElement>(member.content) + break; + case "SVGElement": + bo[i] = parse<SVGElement>(member.content) + break; + } + } + else { + bo[i] = backendObject_fromJSON(member) + } + } + if (bo.label instanceof MathMLElement + && typeof bo.uri === "string" + && typeof bo.type === "string") { + return bo as unknown as Backend_Object + } + else { + console.error(`This is not a Backend_Object:`, json_object) + throw new TypeError(`This is not a Backend_Object: \n ${json_object}`) + } +} \ No newline at end of file diff --git a/Assets/StreamingAssets/ScrollView_Server/src/Facts.ts b/Assets/StreamingAssets/ScrollView_Server/src/Facts.ts index 28176475..8bbc8f66 100644 --- a/Assets/StreamingAssets/ScrollView_Server/src/Facts.ts +++ b/Assets/StreamingAssets/ScrollView_Server/src/Facts.ts @@ -12,6 +12,22 @@ interface Backend_Object{ readonly type: string } +/** + * A {@link Backend_Object} without any further properties known to us + */ +class Pure_Reference implements Backend_Object{ + readonly type: string + constructor( + readonly label: MathMLElement, + readonly uri: string, + type?: string, + ) { + this.type = type ? type : "none" + } +} + +//#region Facts + /** * A Fact is an instance (witness) of a `Backend_Object`, and as such it also has a value. * @see representations Internal storage of possible MathML elements to display to the user when the value is referenced. For access using {@link show_value} is preferable, as it can have a default value and alike. @@ -241,3 +257,67 @@ class Ray_Fact extends Line_Fact { super(label,uri,p1,p2,_representations) } } + +//#endregion Facts + +/** + * A Slot is an interface that can stand in for either + * - a {@link Fact}, or + * - the {@link Backend_Object} used to define the {@link Scroll} (in the backend) + * + * depending on what is needed. + * + * If all Slots of a {@link Scroll} are assigned, it can compute its {@link Scroll.acquiredFacts}. + */ +class Slot implements Backend_Object{ + /** + * @param default_label The default label of the Slot. Fallback if no Fact is assigned. + * @param uri The uri of the Slot + * @param type The expected type of the assigned Fact + * @param assignedFact The Fact assigned to this Slot (may not exist yet) + */ + constructor( + readonly default_label: MathMLElement, + readonly uri: string, + readonly type: string, + public assignedFact?: Fact + ) { } + + /** + * The MathML element to display when this Slot is referenced. + * + * This is either the label of the {@link assignedFact}, or {@link default_label} if the former doesn't exist. + */ + get label(): MathMLElement{ + if (this.assignedFact) { + return this.assignedFact.label + } + else { + return this.default_label + } + } + +} + +/** + * A Scroll, as it is implemented in the backend. + * + * Can do fancy stuff elsewhere, here we only want display its {@link description} and (possibly) {@link depiction}. + * Both will reference the {@link slots}, and need dynamic adaption to the {@link Fact}s assigned to them. + * The {@link acquiredFacts} referenced do not change, but they are semantically important and deserve special treatment. + */ +class Scroll implements Backend_Object{ + readonly type: string = "Scroll" + constructor( + readonly label: MathMLElement, + readonly uri: string, + readonly slots: Slot[], + readonly acquiredFacts: Backend_Object[], + readonly description: HTMLElement, + readonly depiction?: HTMLElement, + ) { } +} + +function isScroll(s: any): s is Scroll{ + return s.type === "Scroll" +} \ No newline at end of file diff --git a/Assets/StreamingAssets/ScrollView_Server/src/SetScrollContent.ts b/Assets/StreamingAssets/ScrollView_Server/src/SetScrollContent.ts index fa608daf..cd913a59 100644 --- a/Assets/StreamingAssets/ScrollView_Server/src/SetScrollContent.ts +++ b/Assets/StreamingAssets/ScrollView_Server/src/SetScrollContent.ts @@ -1,82 +1,3 @@ - -/** - * A MMT..whatever. Somewhere between the first and second "meta-" MMT had to leave common nomenclature behind - * @typedef {{kind : string, uri: string}} MMTReference - */ -/** - * Facts, as they are send by MMT. Not *quite* the same format as Unity uses \*sigh\*, and everything has shortened names to avoid five additional letters \*double sigh\* - * @typedef {Object} MMTFact - * @property {MMTReference} ref the reference MMT uses to identify this fact - * @property {string} label the human readable lable to display this fact. - * @property {?any} df the definition of the Fact. May be null for {@link MMTScroll.requiredFacts} - * @property {?MMTReference} tp the MMT type of this fact - * @property {string} kind since a Fact is a MMTThingy, they also have a {@link MMTReference.kind} - */ - -/** - * A Slot is an interface that can stand in for either - * - a {@link Fact}, or - * - the {@link Backend_Object} used to define the {@link Scroll} (in the backend) - * - * depending on what is needed. - * - * If all Slots of a {@link Scroll} are assigned, it can compute its {@link Scroll.acquiredFacts}. - */ -class Slot implements Backend_Object{ - /** - * @param default_label The default label of the Slot. Fallback if no Fact is assigned. - * @param uri The uri of the Slot - * @param type The expected type of the assigned Fact - * @param assignedFact The Fact assigned to this Slot (may not exist yet) - */ - constructor( - readonly default_label: MathMLElement, - readonly uri: string, - readonly type: string, - public assignedFact?: Fact - ) { this.assignedFact = assignedFact } - - /** - * The MathML element to display when this Slot is referenced. - * - * This is either the label of the {@link assignedFact}, or {@link default_label} if the former doesn't exist. - */ - get label(): MathMLElement{ - if (this.assignedFact) { - return this.assignedFact.label - } - else { - return this.default_label - } - } - -} - -/** - * A Scroll, as it is implemented in the backend. - * - * Can do fancy stuff elsewhere, here we only want display its {@link description} and (possibly) {@link depiction}. - * Both will reference the {@link slots}, and need dynamic adaption to the {@link Fact}s assigned to them. - * The {@link acquiredFacts} referenced do not change, but they are semantically important and deserve special treatment. - */ -class Scroll implements Backend_Object{ - readonly type: string = "Scroll" - constructor( - readonly label: MathMLElement, - readonly uri: string, - readonly slots: Slot[], - readonly acquiredFacts: Backend_Object[], - readonly description: HTMLElement, - readonly depiction?: HTMLElement, - ) { } - - /** TODO */ - static fromString(scrollString: string): Scroll { - - throw new Error("Not implemented."); - } -} - let currentScrollRef = "" // ref of the scroll currently displayed function RenderScroll() { @@ -88,7 +9,12 @@ function RenderScroll() { console.error("No Scroll found in the Unity-Data-Interface") return } - const scroll = Scroll.fromString(dataSource.dataset.scrollDynamic); + const scroll_json = JSON.parse(dataSource.dataset.scrollDynamic); + const scroll = backendObject_fromJSON(scroll_json) + if (!isScroll(scroll)) { + console.error("The Scroll in the Unity-Data-Interface cannot be parsed") + return + } //console.log(scroll.requiredFacts); const scrollContainer = document.querySelector("#scrollContainer"); -- GitLab