Last active
December 17, 2015 22:29
-
-
Save nitriques/5682356 to your computer and use it in GitHub Desktop.
How facts are created with Jess: see it http://bl.ocks.org/nitriques/5682356
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<link href="http://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet" type="text/css"> | |
<style> | |
body { | |
font-family: 'Ubuntu', Helvetica, Arial, sans-serif; | |
width: 960px; | |
height: 500px; | |
position: relative; | |
font-size: 14px; | |
} | |
h3 { | |
margin: 6px 0 3px 0; | |
} | |
#root { | |
position: relative; | |
} | |
#output { | |
position: absolute; | |
top: 180px; | |
left: 90px; | |
width: 240px; | |
font-size: 16px; | |
} | |
svg * { | |
-webkit-transition: all 350ms ease-in; | |
-moz-transition: all 350ms ease-in; | |
-ms-transition: all 350ms ease-in; | |
-o-transition: all 350ms ease-in; | |
transition: all 350ms ease-in; | |
} | |
.node { | |
stroke-width: 0px; | |
} | |
.node.selected { | |
stroke-width: 14px; | |
} | |
.label { | |
display: none; | |
text-shadow: 0 0 1px #fff, 0 0 2px #fff, 0 0 3px #fff, 0 0 4px #fff, 0 0 5px #fff; | |
font-size: 16px; | |
} | |
.label.selected { | |
display:block; | |
} | |
.level { | |
font-size: 13px; | |
} | |
.link { | |
stroke-width: 2px; | |
} | |
.link.selected { | |
stroke-width: 6px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="root"> | |
<div id="output"></div> | |
</div> | |
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script> | |
(function ($, d3, undefined) { | |
"use strict"; | |
var | |
WIDTH = 960, | |
HEIGHT = 500, | |
COLORS = d3.scale.category20b(), | |
NODE_SIZE = 10, | |
NODE_SIZE_HALF = NODE_SIZE/2, | |
NODE_SPACING = 30, | |
TRANSLATE = 'translate(-' + NODE_SIZE_HALF + ',-' + NODE_SIZE_HALF + ')', | |
TRANSLATE_TEXT = 'translate(-' + NODE_SIZE + ',-' + NODE_SIZE + ')', | |
facts = [ | |
{id: 0, level:0, text:'seen ?hair at ?time'}, | |
{id: 1, level:0, text:'is ?name ?hair'}, | |
{id: 2, level:0, text:'visit ?dir ?mood'}, | |
{id: 3, level:0, text:'direction ?shop ?dir'}, | |
{id: 4, level:0, text:'sold ?os at ?time'}, | |
{id: 5, level:0, text:'run ?product ?os'}, | |
{id: 6, level:0, text:'has ?head ?mood'}, | |
{id: 7, level:0, text:'wears ?name ?head'}, | |
{id: 8, level:0, text:'goto ?loc ?transport'}, | |
{id: 9, level:0, text:'location ?shop ?loc'}, | |
{id:10, level:0, text:'bought ?os ?job'}, | |
{id:11, level:0, text:'transact ?company ?job'}, | |
{id:12, level:0, text:'company ?payment-type ?company'}, | |
{id:13, level:0, text:'rank ?name ?rank'}, | |
{id:14, level:0, text:'requires ?transport ?rank'}, | |
{id:15, level:0, text:'sex ?name ?sex'}, | |
{id:16, level:0, text:'job-sex ?job ?sex'}, | |
{id:17, level:0, text:'sell ?shop ?os'}, | |
{id:18, level:0, text:'use ?dir ?company'}, | |
{id: 100, level:1, text:'seen-l0 ?name at ?time'}, | |
{id: 101, level:1, text:'visit-l0 ?shop ?mood'}, | |
{id: 102, level:1, text:'sold-l0 ?product at ?time'}, | |
{id: 103, level:1, text:'is-l0 ?name ?mood'}, | |
{id: 104, level:1, text:'goto-l0 ?shop ?transport'}, | |
{id: 105, level:1, text:'bought-l0 ?product ?job'}, | |
{id: 106, level:1, text:'transact-l0 ?payment-type ?job'}, | |
{id: 107, level:1, text:'use-l0 ?name ?transport'}, | |
{id: 108, level:1, text:'job-l0 ?name ?job'}, | |
{id: 109, level:1, text:'sell-l0 ?shop ?product'}, | |
{id: 110, level:1, text:'use-l0 ?shop ?company'}, | |
{id: 200, level:2, text:'visit-l1 ?name ?shop'}, | |
{id: 201, level:2, text:'bought-l1 ?name ?product'}, | |
{id: 202, level:2, text:'via-l1 ?payment-type ?product'}, | |
{id: 203, level:2, text:'transact-l1 ?shop ?payment-type'}, | |
{id: 204, level:2, text:'uses-l1 ?name ?payment-type'}, | |
{id: 300, level:3, text:'sold-l2 ?shop ?product ?payment-type'}, | |
{id: 301, level:3, text:'bought-l2 ?name ?product ?payment-type'}, | |
{id: 302, level:3, text:'seen-l2 ?name ?product ?shop'}, | |
{id: 303, level:3, text:'transact-l2 ?name ?payment-type ?shop'}, | |
{id: 400, level:4, text:'FOUND ?name ?product ?payment-type ?shop'} | |
], | |
relationships = [ | |
{from:0,to:100},{from:1,to:100}, | |
{from:2,to:101},{from:3,to:101}, | |
{from:4,to:102},{from:5,to:102}, | |
{from:6,to:103},{from:7,to:103}, | |
{from:8,to:104},{from:9,to:104}, | |
{from:10,to:105},{from:5,to:105}, | |
{from:11,to:106},{from:12,to:106}, | |
{from:13,to:107},{from:14,to:107}, | |
{from:15,to:108},{from:16,to:108}, | |
{from: 5,to:109},{from:17,to:109}, | |
{from: 3,to:110},{from:18,to:110}, | |
{from:101,to:200},{from:103,to:200}, | |
{from:100,to:201},{from:102,to:201}, | |
{from:105,to:202},{from:106,to:202}, | |
{from:104,to:200},{from:107,to:200}, | |
{from:106,to:204},{from:108,to:204}, | |
{from: 13,to:203},{from:110,to:203}, | |
{from:202,to:300},{from:109,to:300},{from:203,to:300}, | |
{from:202,to:301},{from:201,to:301},{from:204,to:301}, | |
{from:200,to:302},{from:201,to:302},{from:109,to:302}, | |
{from:200,to:303},{from:203,to:303},{from:204,to:303}, | |
{from:300,to:400},{from:301,to:400},{from:302,to:400},{from:303,to:400} | |
], | |
depths = [ | |
'KB','Level 0','Level 1','Level 2','Result (level 3)' | |
], | |
output = $('#output'), | |
_levelCount = function (level) { | |
var res = 0; | |
$.each(facts, function (index, fact) { | |
if (fact.level === level) { | |
res++; | |
} | |
}); | |
return res; | |
}, | |
_getIndex = function (d) { | |
return d.id - (d.level * 100); | |
}, | |
_x = function (d, i) { | |
var | |
one = NODE_SIZE + NODE_SPACING, | |
offset = _getIndex(d) * one, | |
levelCount = _levelCount(d.level), | |
spacing = Math.max(0, ( WIDTH - (one * (levelCount+1)) ) / 2); | |
return offset + spacing; | |
}, | |
_y = function (d, i) { | |
return ((d.level !== undefined ? d.level : i) * 110) + NODE_SIZE * 3; | |
}, | |
_findById = function (key) { | |
var res = null; | |
$.each(facts, function (index, fact) { | |
if (fact.id === key) { | |
res = fact; | |
return false; | |
} | |
}); | |
return res; | |
}, | |
_indexById = function (key) { | |
var res = -1; | |
$.each(facts, function (index, fact) { | |
if (fact.id === key) { | |
res = index; | |
return false; | |
} | |
}); | |
return res; | |
}, | |
_selectText = function (select) { | |
return function selectText(d, i) { | |
var | |
labels = d3.selectAll('.label'), | |
nodes = d3.selectAll('.node'), | |
links = d3.selectAll('.link'), | |
parents = [], | |
filterCurrent = function (ld, li) { | |
return d.id === ld.id; | |
}, | |
filterParent = function (ld, li) { | |
return !!~$.inArray(ld.id, parents); | |
}, | |
filterLinks = function (ld, li) { | |
return d.id === ld.to; | |
}; | |
if (d.id === undefined) { | |
return; | |
} | |
// find parents id | |
$.each(relationships, function (index, rel) { | |
if (rel.to === d.id) { | |
parents.push(rel.from); | |
} | |
}); | |
// select current | |
d3.select(this).classed('selected', select); | |
// find current and select | |
labels.filter(filterCurrent).classed('selected', select); | |
// show parent | |
nodes.filter(filterParent).classed('selected', select); | |
// select link | |
links.filter(filterLinks).classed('selected', select); | |
// output | |
if (!select) { | |
output.empty(); | |
} else { | |
if (!d.level) { | |
output.append('<h3>Known from KB</h3>'); | |
} else { | |
output.append('<h3>Possible parents:</h3>'); | |
$.each(parents, function (index, p) { | |
var fact = _findById(p), | |
$fact = $('<div />').text((index+1) + '. ' + fact.text); | |
output.append($fact); | |
}); | |
output.append('<h3>Selected child:</h3>'); | |
} | |
output.append($('<div />').text(d.text)); | |
} | |
}; | |
}, | |
init = function () { | |
var svg = d3.select('#root') | |
.append("svg:svg") | |
.attr("width", WIDTH) | |
.attr("height", HEIGHT) | |
.attr('id','graph'), | |
vis = svg.append('g').attr('id', 'vis'), | |
levels = vis.selectAll('.level').data(depths), | |
links = vis.selectAll('.link').data(relationships), | |
nodes = vis.selectAll('.node').data(facts), | |
labels = vis.selectAll('.label').data(facts); | |
levels.enter() | |
.append('text') | |
.attr('class','level') | |
.text(function (d) { return d; }); | |
links.enter().append('line') | |
.attr('class','link') | |
.attr('stroke', function (d, i) { return COLORS(_indexById(d.to)); }); | |
nodes.enter().append('circle') | |
.attr('class','node') | |
.attr('r', NODE_SIZE) | |
.attr('fill', function (d, i) { return COLORS(i); }) | |
.attr('stroke', function (d, i) { return COLORS(i); }) | |
.on('mouseenter', _selectText(true)) | |
.on('mouseleave', _selectText(false)); | |
labels.enter() | |
.append('text') | |
.attr('class','label') | |
.attr('transform', TRANSLATE_TEXT) | |
.text(function (d) { return d.text; }); | |
levels | |
.attr('x', 10) | |
.attr('y', function (d, i) { return _y(d, i) + NODE_SIZE/2; }); | |
links | |
.attr('x1', function (d, i) { return _x(_findById(d.from), i); }) | |
.attr('y1', function (d, i) { return _y(_findById(d.from), i); }) | |
.attr('x2', function (d, i) { return _x(_findById(d.to), i); }) | |
.attr('y2', function (d, i) { return _y(_findById(d.to), i); }); | |
nodes | |
.attr('cx', _x) | |
.attr('cy', _y); | |
labels | |
.attr('x', _x) | |
.attr('y', _y); | |
}; | |
$(init); | |
})(window.jQuery, window.d3); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment