160 lines
3.6 KiB
JavaScript
160 lines
3.6 KiB
JavaScript
|
|
||
|
let svg = document.querySelector("svg");
|
||
|
|
||
|
let nods = document.createElementNS(svgNamespace, 'g');
|
||
|
let arrows = document.createElementNS(svgNamespace, 'g');
|
||
|
|
||
|
svg.appendChild(arrows);
|
||
|
svg.appendChild(nods);
|
||
|
|
||
|
class Edge {
|
||
|
renderedElement;
|
||
|
end;
|
||
|
trans;
|
||
|
inEdge;
|
||
|
dimension = 1;
|
||
|
constructor(end, trans, inEdge = true) {
|
||
|
this.end = end;
|
||
|
this.trans = trans;
|
||
|
this.inEdge = inEdge;
|
||
|
this.renderedElement = inEdge ? new SVGArrow(end, trans) : new SVGArrow(trans, end);
|
||
|
this.renderedElement.appendIt(arrows);
|
||
|
end.updateList.push(this);
|
||
|
}
|
||
|
canSuck() {
|
||
|
return this.end.marks >= this.dimension;
|
||
|
}
|
||
|
suck() {
|
||
|
this.end.marks -= this.dimension;
|
||
|
this.end.updatePoints();
|
||
|
}
|
||
|
canPush() {
|
||
|
return this.end.capacity >= this.end.marks + this.dimension;
|
||
|
}
|
||
|
push() {
|
||
|
this.end.marks += this.dimension;
|
||
|
this.end.updatePoints();
|
||
|
}
|
||
|
updatePosition() {
|
||
|
this.renderedElement.updatePosition();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class Node {
|
||
|
renderedElement;
|
||
|
x = 0;
|
||
|
y = 0;
|
||
|
name;
|
||
|
capacity = 1;
|
||
|
marks = 0;
|
||
|
|
||
|
updateList = [];
|
||
|
|
||
|
constructor(name, x, y) {
|
||
|
this.name = name;
|
||
|
this.x = x;
|
||
|
this.y = y;
|
||
|
this.renderedElement = new SVGNode(this);
|
||
|
this.renderedElement.appendIt(nods);
|
||
|
}
|
||
|
|
||
|
updatePoints() {
|
||
|
this.renderedElement.setMarks(this.marks, this.capacity);
|
||
|
}
|
||
|
|
||
|
updatePosition(x, y) {
|
||
|
this.x = x;
|
||
|
this.y = y;
|
||
|
this.renderedElement.translate(x, y);
|
||
|
for (const elem of this.updateList) {
|
||
|
elem.updatePosition();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class Transition {
|
||
|
renderedElement;
|
||
|
name = "noname";
|
||
|
inEdges = [];
|
||
|
outEdges = [];
|
||
|
x;
|
||
|
y;
|
||
|
constructor(name, x, y) {
|
||
|
this.name = name;
|
||
|
this.x = x;
|
||
|
this.y = y;
|
||
|
this.renderedElement = new SVGTRansition(this);
|
||
|
this.renderedElement.appendIt(nods);
|
||
|
}
|
||
|
canFire() {
|
||
|
for (const inE of this.inEdges) {
|
||
|
if (!inE.canSuck()) {
|
||
|
this.renderedElement.setCanFire(false);
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
for (const outE of this.outEdges) {
|
||
|
if (!outE.canPush()) {
|
||
|
this.renderedElement.setCanFire(false);
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
this.renderedElement.setCanFire(true);
|
||
|
return true;
|
||
|
}
|
||
|
fire() {
|
||
|
if (!this.canFire()) return false;
|
||
|
for (const inE of this.inEdges) {
|
||
|
inE.suck();
|
||
|
}
|
||
|
for (const outE of this.outEdges) {
|
||
|
outE.push();
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
updatePosition(x, y) {
|
||
|
this.x = x;
|
||
|
this.y = y;
|
||
|
this.renderedElement.translate(x, y);
|
||
|
for (const inE of this.inEdges) {
|
||
|
inE.updatePosition();
|
||
|
}
|
||
|
for (const outE of this.outEdges) {
|
||
|
outE.updatePosition();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let transitions = [];
|
||
|
let nodes = [];
|
||
|
|
||
|
function loop() {
|
||
|
for (const trans of transitions) {
|
||
|
console.log(trans.name, trans.fire());
|
||
|
}
|
||
|
update();
|
||
|
}
|
||
|
|
||
|
function update() {
|
||
|
for (const nod of nodes) {
|
||
|
nod.updatePoints();
|
||
|
}
|
||
|
for (const trans of transitions) {
|
||
|
trans.canFire();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
window.onresize = () => {
|
||
|
svg.setAttribute("viewBox", `0 0 ${window.innerWidth} ${window.innerHeight}`);
|
||
|
}
|
||
|
window.onresize();
|
||
|
|
||
|
|
||
|
let n1 = new Node("n1", 100, 100);
|
||
|
let n2 = new Node("n2", 100, 300);
|
||
|
let t1 = new Transition("t1", 100, 200);
|
||
|
t1.inEdges.push(new Edge(n1, t1, true))
|
||
|
t1.outEdges.push(new Edge(n2, t1, false));
|
||
|
|
||
|
nodes.push(n1, n2);
|
||
|
transitions.push(t1);
|