diff --git a/hai.html b/hai.html new file mode 100644 index 0000000..86c2175 --- /dev/null +++ b/hai.html @@ -0,0 +1,255 @@ + + + + + + + + + + + +
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/js/SentenceParser.js b/js/SentenceParser.js new file mode 100644 index 0000000..0217b07 --- /dev/null +++ b/js/SentenceParser.js @@ -0,0 +1,132 @@ +/* + * A parser that creates links for not only words + * but also sentences and paragraphs. + */ + +class SentenceParser { + constructor() { + this.text = ""; + this.tokens = []; + this.data = {}; + } + + /* load a json from a path */ + readJson(path, callback) { + + var json = path || './data/data1.json'; + + function loadJSON(path, callback2) { + var httpRequest = new XMLHttpRequest(); + httpRequest.onreadystatechange = function() { + if (httpRequest.readyState === 4) { + if (httpRequest.status === 200) { + var data = JSON.parse(httpRequest.responseText); + if (callback2) { + callback2(data); + } + if (callback) { + callback(); + } + } + } + }; + httpRequest.open('GET', path); + httpRequest.send(); + } + + /* parse json file*/ + loadJSON(json, this.parseData.bind(this)); + } + + /** + * parse a json file + */ + parseData(data) { + /* first get string tokens from the syntaxData */ + this.text = data.syntaxData.text; + + const offsets = {}; + this.tokens = data.syntaxData.entities + .map(x => x[2][0]) + .sort((a, b) => a[0] - b[0]) + .map((interval, i) => { + offsets[interval[0]] = i; + return this.text.substring(interval[0], interval[1]); + }); + + /* parse the event data: entities, triggers, events, and relations */ + const e = data.eventData; + const entities = e.entities.map(arr => { + return { + id: arr[0], + type: arr[1], + tokenIndex: offsets[arr[2][0][0]], + string: e.text.substring(arr[2][0][0], arr[2][0][1]) + }; + }); + + const triggers = e.triggers.map(arr => { + return { + id: arr[0], + type: arr[1], + tokenIndex: offsets[arr[2][0][0]], + string: e.text.substring(arr[2][0][0], arr[2][0][1]) + }; + }); + + const events = e.events.map(arr => { + return { + id: arr[0], + trigger: arr[1], + arguments: arr[2].map(argument => { + return { + id: argument[1], + type: argument[0] + }; + }) + }; + }); + + const relations = e.relations.map(arr => { + return { + id: arr[0], + type: arr[1], + arguments: arr[2].map(argument => { + return { + id: argument[1], + type: argument[0] + }; + }) + }; + }); + + + // Generate data for sentences so semantic zoom can be + // implemented for the staircase + var sentence = this.text.split("."); + console.log("Sentences: \n" + sentence); + + // Go through the entities array and add links to the sentence + // that the entity belongs to + var sentenceCounter = 0; + var currentSentence = ""; + for (var i = 0; i < entities.length; i++) { + var entityId = parseInt(entities[i].id.substring(1)); + if (entityId < sentence[sentenceCounter].split(" ").length) { // entityId smaller than number of words in the sentence + currentSentence += entities[i].string + " "; + } else { + console.log(currentSentence); + sentenceCounter++; + currentSentence = ""; + } + } + + + this.data = { + entities, + triggers, + events, + relations + }; + } +} diff --git a/js/staircase.js b/js/staircase.js new file mode 100644 index 0000000..39c8cb2 --- /dev/null +++ b/js/staircase.js @@ -0,0 +1,86 @@ +class Staircase { + constructor(el) { + // container element + this.div = el; + + // dimensions & properties + this.bounds = this.div.getBoundingClientRect(); + + // d3 dom references + this.svg = d3.select(this.div).append('svg') + .attr('width', this.bounds.width) + .attr('height', this.bounds.height); + this.g = this.svg.append('g'); + + this.steps = this.g.append("g") + .attr("class", "steps"); + + // margins and drag event for positioning svg + this.leftMargin = 0; + this.topMargin = 0; + + this.dx = 0; + this.dy = 0; + this.svg + .call(d3.drag() + .on('drag', () => { + this.dx += d3.event.dx; + this.dy += d3.event.dy; + this.adjustMargins(this.dx, this.dy); + }) + ) + .on('dblclick', () => { + if (d3.event.target === this.svg.node()) { + this.dx = this.dy = 0; + this.adjustMargins(); + } + }); + this.resize(); + + // selected words to generate graph around + this.words = []; + + } + + resize() { + this.bounds = this.div.getBoundingClientRect(); + this.svg + .attr('width', this.bounds.width) + .attr('height', this.bounds.height); + + this.adjustMargins(); + } + + adjustMargins(dx = 0, dy = 0) { + this.g.attr('transform','translate(' + (20 + dx + this.leftMargin) + ', ' + (10 + dy + this.topMargin) + ')'); + } + + clear() { + this.words = []; + this.steps.selectAll('*').remove(); + } + + graph(words) { + this.words = words; + console.log(this.words); + + this.data = this.words.map(word => { + }); + + this.updateGraph(); + } + + updateGraph() { + let steps = this.steps.selectAll('.stepGroup') + .data(this.data); + steps.exit().remove(); + + steps.enter().append('g') + .attr('class','stepGroup') + .merge(steps) + .each((d, i, el) => { + el = d3.select(el[i]) + .attr('transform', 'translate(10, 0)'); + }); + } +}//end class Staircase