-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconsensus.min.js
1 lines (1 loc) · 10.5 KB
/
consensus.min.js
1
async function setup(){createCanvas(windowWidth,windowHeight),background(51),medium=new Medium,cellSize=50;let t=floor(width/cellSize),i=floor(height/cellSize);for(nodeCount=width/20,console.log(nodeCount),grid=new Grid(t,i),grid.randomFill(),grid.setGridNeighborhood(),grid.runAll();;)await medium.update(),await sleep(10)}function draw(){background(51),grid.drawNodes();for(let t=0;t<medium.messageList.length;t++)medium.messageList[t].displayConnection()}function randomColor(){let t=getRandomInt(0,3);return 0==t?color(0,random(100,255),random(100,255)):1==t?color(random(100,255),0,random(100,255)):color(random(100,255),random(100,255),0)}function sleep(t){return new Promise(i=>setTimeout(i,t))}function distanceBetweenTwoPoints(t,i){return dist(t.x,t.y,i.x,i.y)}function getRandomInt(t,i){return t=Math.ceil(t),i=Math.floor(i),Math.floor(Math.random()*(i-t)+t)}function randomRecepient(t,i){let e,o;if(0==i.length)return null;do{e=getRandomInt(0,i.length),e!=t&&(o=i[e])}while(e==t);return o}function arrangeInCircle(t){let i=height/2.3;for(let e=0;e<t.length;e++){let o=map(e,0,t.length,0,TWO_PI),s=createVector(i,0).rotate(o).add(createVector(width/2,height/2));t[e].position=s}}function drawBezier(t,i,e,o){bezier(t.x,t.y,i.x,i.y,e.x,e.y,o.x,o.y)}function drawLine(t,i){line(t.x,t.y,i.x,i.y)}function nullOrUndefined(t){return null==t||null==t}class Connection{constructor(t,i){this.source=t,this.target=i,this.lerpStep=.02,this.beginning=0,this.end=0,this.timer=0,this.timerStep=this.lerpStep/4,this.connected=!1,this.disconnected=!1,this.connecting=!0,this.disconnecting=!1,this.color=t.color,this.strength=.5}display(){this.preDraw(),this.connecting?this.drawConnectionTo(this.end):this.beginning>0?this.drawConnectionFrom(this.beginning):this.drawConnection(),this.postDraw()}connect(){return this.timer+=this.timerStep,this.connecting=!0,this.end>=1?(this.connected=!0,this.connecting=!1):this.end+=this.lerpStep,this.connected}disconnect(){if(this.timer+=this.timerStep,this.disconnecting=!0,this.beginning>=1)this.disconnected=!0,this.disconnecting=!1;else{let t=(1-this.timer)/this.timerStep,i=1/this.lerpStep;t-i<=0&&this.beginning<1&&(this.beginning+=this.lerpStep)}return this.disconnected}preDraw(){noFill();let t=map(this.strength,0,1,20,100);this.color.setAlpha(t),stroke(this.color);let i=map(this.strength,0,1,4,10);strokeWeight(i)}postDraw(){this.color.setAlpha(255)}strengthenConnection(t){this.strength+=null==t?.1:t}transmit(t,i){this.connected?i==this.source||i==this.target?i.receive(t):console.log("Recepient not in connection"):console.log("Not connected")}}class LinearConnection extends Connection{constructor(t,i){super(t,i)}drawConnection(){drawLine(this.source.position,this.target.position)}drawConnectionFrom(t){let i=this.getPosition(t);drawLine(i,this.target.position)}drawConnectionTo(t){let i=this.getPosition(t);drawLine(i,this.source.position)}getPosition(t){return p5.Vector.lerp(this.source.position,this.target.position,t)}}class CurvedConnection extends Connection{constructor(t,i){super(t,i),this.lerpPointOne=this.findControlPoint(),this.lerpPointTwo=this.findControlPoint()}drawConnection(){drawBezier(this.source.position,this.lerpPointOne,this.lerpPointTwo,this.target.position)}drawConnectionFrom(t){let i=this.splitBezierAt(t);drawBezier(i.from[0],i.from[1],i.from[2],i.from[3])}drawConnectionTo(t){let i=this.splitBezierAt(t);drawBezier(i.to[0],i.to[1],i.to[2],i.to[3])}splitBezierAt(t){let i=this.source.position.copy(),e=this.lerpPointOne.copy(),o=this.lerpPointTwo.copy(),s=this.target.position.copy(),n=p5.Vector.sub(e,i).mult(t).add(i),r=p5.Vector.sub(o,e).mult(t).add(e),h=p5.Vector.sub(s,o).mult(t).add(o),d=p5.Vector.sub(r,n).mult(t).add(n),l=p5.Vector.sub(h,r).mult(t).add(r),c=p5.Vector.sub(l,d).mult(t).add(d);return{to:[i,n,d,c],from:[c,l,h,s]}}findControlPoint(){let t=this.source.position,i=this.target.position,e=p5.Vector.lerp(t,i,random()),o=random()<=.5?createVector(e.y,-e.x):createVector(-e.y,e.x);do{o.normalize().mult(random(0,p5.Vector.dist(t,i))).add(e)}while(!this.isWithinBoundary(o));return o}isWithinBoundary(t){return t.x>0&&t.x<width&&t.y>0&&t.y<height}drawBezierBetween(t,i){let e=1-t,o=1-i,s=this.source.position.copy(),n=this.lerpPointOne.copy(),r=this.lerpPointTwo.copy(),h=this.target.position.copy(),d=p5.Vector.mult(s,e*e),l=p5.Vector.mult(n,2*t*e),c=p5.Vector.mult(r,t*t),a=d.add(l).add(c),p=p5.Vector.mult(s,o*o),g=p5.Vector.mult(n,2*i*o),u=p5.Vector.mult(r,i*i),m=p.add(g).add(u),w=p5.Vector.mult(n,e*e),f=p5.Vector.mult(r,2*t*e),y=p5.Vector.mult(h,t*t),V=w.add(f).add(y),x=p5.Vector.mult(n,o*o),b=p5.Vector.mult(r,2*i*o),C=p5.Vector.mult(h,i*i),L=x.add(b).add(C),v=p5.Vector.mult(a,e).add(p5.Vector.mult(V,t)),P=p5.Vector.mult(a,o).add(p5.Vector.mult(V,i)),T=p5.Vector.mult(m,e).add(p5.Vector.mult(L,t)),M=p5.Vector.mult(m,o).add(p5.Vector.mult(L,i));drawBezier(v,P,T,M)}}class Grid{constructor(t,i){this.n=t,this.m=i,this.grid=new Array(t);for(let e=0;e<t;e++)this.grid[e]=new Array(i);this.gridList=[],this.index=0,this.preferredCount=nodeCount,this.count=0}setGridNeighborhood(){for(let t=0;t<this.gridList.length;t++)this.gridList[t].setNeighborhood(this.gridList)}drawNodes(){for(let t=0;t<this.gridList.length;t++)this.gridList[t].display()}drawGrid(){stroke(255,50),strokeWeight(1);for(let t=1;t<this.n;t++){let i=map(t,0,this.n,0,width);line(i,0,i,height)}for(let t=1;t<this.m;t++){let i=map(t,0,this.m,0,height);line(0,i,width,i)}}fillRow(t){for(let i=0;i<this.n;i++){let e=this.grid[i][t];nullOrUndefined(e)&&(this.grid[i][t]=new Node(medium,this.index,this.getX(i),this.getY(t)),this.gridList[this.index]=this.grid[i][t],this.index+=1)}}fillColumn(t){for(let i=0;i<this.m;i++){let e=this.grid[t][i];nullOrUndefined(e)&&(this.grid[t][i]=new Node(medium,this.index,this.getX(t),this.getY(i)),this.gridList[this.index]=this.grid[t][i],this.index+=1)}}fillAll(){for(let t=0;t<this.n;t++)for(let i=0;i<this.m;i++){let e=this.grid[t][i];nullOrUndefined(e)&&(this.grid[t][i]=new Node(medium,this.index,this.getX(t),this.getY(i)),this.gridList[this.index]=this.grid[t][i],this.index+=1)}}runAll(){for(let t=0;t<this.gridList.length;t++)this.gridList[t].run()}getX(t){return map(t,0,this.n,0,width)+cellSize/2}getY(t){return map(t,0,this.m,0,height)+cellSize/2}randomFill(){for(;this.index<this.preferredCount;){let t=getRandomInt(0,this.n),i=getRandomInt(0,this.m),e=this.grid[t][i];nullOrUndefined(e)&&this.checkNeighbors(t,i)&&(this.grid[t][i]=new Node(medium,this.index,this.getX(t),this.getY(i)),this.gridList[this.index]=this.grid[t][i],this.index+=1)}}tryInsert(t,i,e){let o=this.grid[i][e];return!(!nullOrUndefined(o)||!this.checkNeighbors(i,e))&&(this.grid[i][e]=t,!0)}checkNeighbors(t,i){return!0}getCount(){if(0!=this.count)return this.count;for(let t=0;t<this.n;t++)for(let i=0;i<this.m;i++){let e=this.grid[t][i];nullOrUndefined(e)||(this.count+=1)}return this.count}}class Medium{constructor(){this.messageList=[]}async send(t,i,e){this.messageList.push(new Message(t,i,e))}async update(){for(let t=0;t<this.messageList.length;t++)if(this.messageList[t].moveTowardsTarget(),this.messageList[t].arrived){let i=this.messageList.splice(t,1)[0];i.arrive(),0==this.messageList.length&&(this.messageList=[])}}}class Message{constructor(t,i,e){this.source=t,this.target=i,this.message=e,this.position=t.position.copy(),this.arrived=!1,this.radius=10,this.color=t.color,this.lerpFactor=0,this.lerpStep=.005,this.connection=new CurvedConnection(t,i)}moveTowardsTarget(){0==this.connection.connected?this.connection.connect():0==this.connection.disconnected?this.connection.disconnect():this.arrived=!0}curvedMovement(){this.lerpFactor>=1&&(this.arrived=!0);let t=p5.Vector.lerp(this.source.position,this.lerpPointOne,this.lerpFactor),i=p5.Vector.lerp(this.lerpPointOne,this.lerpPointTwo,this.lerpFactor),e=p5.Vector.lerp(this.lerpPointTwo,this.target.position,this.lerpFactor),o=p5.Vector.lerp(t,i,this.lerpFactor),s=p5.Vector.lerp(i,e,this.lerpFactor);this.position=p5.Vector.lerp(o,s,this.lerpFactor),this.lerpFactor+=this.lerpStep}linearAccMovement(){let t=this.target.position.copy();t.sub(this.position);let i=t.copy();i.mag()/100<2?(i.normalize(),i.mult(2)):i.setMag(i.mag()/100),t.normalize(),t.mult(i.mag()),this.position.add(t),distanceBetweenTwoPoints(this.position,this.target.position)<=1&&(this.arrived=!0)}linearConstMovement(){this.position=p5.Vector.lerp(this.source.position,this.target.position,this.lerpFactor),this.lerpFactor+=this.lerpStep,this.lerpFactor>=1&&(this.arrived=!0)}arrive(){this.target.receiveToMulticast(this)}display(){rectMode(CENTER),fill(this.color),noStroke();let t=this.getDerived(),i=t.heading();push(),translate(this.position),rotate(i+PI/2),triangle(0,-this.radius/2,this.radius/2,this.radius/2,-this.radius/2,this.radius/2),pop()}getDerived(){let t=this.lerpFactor,i=-3*Math.pow(t,2)+6*t-3,e=9*Math.pow(t,2)-12*t+3,o=-9*Math.pow(t,2)+6*t,s=3*Math.pow(t,2),n=p5.Vector.mult(this.source.position,i),r=p5.Vector.mult(this.lerpPointOne,e),h=p5.Vector.mult(this.lerpPointTwo,o),d=p5.Vector.mult(this.target.position,s),l=n.add(r).add(h).add(d);return l.normalize(),l}displayConnection(){this.connection.display()}}class Node{constructor(t,i,e,o){null!=e&&null!=o||(e=random(20,width-20),o=random(20,height-20)),this.neighborhood=[],this.position=createVector(e,o),this.medium=t,this.index=i,this.diameter=20,this.color=randomColor(),this.messageBuffer=[],this.isRunning,this.counter=0,this.direction=createVector(),this.speed=2}run(){if(0==this.index){let t=randomRecepient(this.index,this.neighborhood);this.reliableMulticast(t.index,this.neighborhood)}}async reliableMulticast(t,i){for(let e=0;e<i.length;e++)e!=this.index&&(this.medium.send(this,i[e],t),await sleep(1))}async receiveToMulticast(t){if(t.message==this.index){if(this.counter+=1,this.counter==this.neighborhood.length-1){let t=randomRecepient(this.index,this.neighborhood);this.reliableMulticast(t.index,this.neighborhood),this.counter=0}}else this.medium.send(this,this.neighborhood[t.message],t.message)}async receiveToRandomSingle(t){let i=randomRecepient(this.index,this.neighborhood);this.medium.send(this,i,t.message)}async receiveToRandomNeighbor(t){}setNeighborhood(t){this.neighborhood=t}display(){fill(this.color),noStroke(),ellipse(this.position.x,this.position.y,this.diameter,this.diameter)}move(){let t=.01;random(0,1)<.5?this.direction.x+=random(-t,t):this.direction.y+=random(-t,t),this.direction.normalize().mult(this.speed),this.position.add(this.direction),(this.position.x<=0||this.position.x>=width)&&(this.direction=createVector(-this.direction.x,this.direction.y)),(this.position.y<=0||this.position.y>=height)&&(this.direction=createVector(this.direction.x,-this.direction.y))}}