xxxxxxxxxx
// BitTorrent Visualization
// created by http://www.aphid.org/btsim/
//
// Posted on medium by @torrent_mx
// https://torrent.mx
float angle = 0;
ArrayList peers = new ArrayList();
ArrayList tmp = new ArrayList();
ArrayList connections = new ArrayList();
float rot = -1;
Torrent testTorrent = new Torrent(30);
int initialSeeders = 2;
int initialPeers = 8;
void setup()
{
size(450,450);
fill(255);
fill(0);
textAlign(CENTER);
// establish initial seeds/peers
for (int i = 0; i < initialSeeders; i++)
{
addSeeder();
}
for (int i = 0; i < initialPeers; i++)
{
addPeer();
}
}
void addPeer()
{
int cc = peers.size();
Peer k = new Peer(random(0,1));
peers.add(k);
}
void addSeeder()
{
int cc = peers.size();
Peer p = new Peer(random(0,1));
peers.add(p);
for (int i = 0; i < testTorrent.bits.size(); i++)
{
p.myBits.add(testTorrent.bits.get(i));
}
p.needBits = new ArrayList();
}
void removePeer()
{
int i = int(random(0,peers.size() - 1));
((Peer)peers.get(i)).removing = 1;
}
void keyPressed()
{
if (key == '+') {
addPeer();
}
if (key == 's') {
addSeeder();
}
if (key == '-') {
removePeer();
}
}
void draw()
{
background(0);
// rotate peers and seeds (disabled by default)
if (rot >= 0)
{
if (rot < 360)
{
rot += .2;
}
else
{
rot = rot - 360;
}
}
for (int i = 0; i < connections.size(); i++)
{
Connection c = (Connection)connections.get(i);
c.manageKibbles();
if ( c.kibbles.isEmpty() && c.stream == false )
{
if (c.to.removing >= 1)
{
c.to.removing++;
}
if (c.from.removing >= 1)
{
c.from.removing++;
}
c.from.knex.remove(c.from.knex.indexOf(c.to));
c.to.myBits.add(c.theBit);
if (c.to.needBits.indexOf(c.theBit) != -1)
{
c.to.needBits.remove(c.to.needBits.indexOf(c.theBit));
}
if (c.to.knex.indexOf(c.theBit) != -1)
{
c.to.knex.remove(c.to.knex.indexOf(c.theBit));
}
connections.remove(i);
}
}
for (int i = 0; i < peers.size(); i++)
{
Peer p = (Peer)peers.get(i);
p.moveSelf();
p.drawSelf();
p.reConfigure(i);
if (p.removing > 1)
{
peers.remove(i);
}
}
ArrayList tmp = shuffle(peers);
for (int i = 0; i < tmp.size(); i++)
{
Peer cpeer = (Peer)tmp.get(i);
if (cpeer.lastcheck < millis() - cpeer.pwait)
{
cpeer.findPeer();
cpeer.lastcheck = millis();
}
}
}
class Peer
{
int index;
float pwait = random(1,9)*1000;
float sxpos; // x of peer
float sypos; // y of peer
float expos; // x of where peer should be
float eypos; // y of where peer should be
float cxpos;
float cypos;
float smovetime;
float emovetime;
float percent;
ArrayList knex = new ArrayList();
ArrayList actBits = new ArrayList();
float chue;
float ehue;
float shue;
color ccolor;
int removing;
int lastcheck;
ArrayList myBits = new ArrayList();
ArrayList needBits = new ArrayList();
Peer(float pct)
{
int szv = peers.size();
if (szv == 0)
{
szv++;
}
pushMatrix();
translate(width / 2, height / 2);
ellipseMode(CENTER);
float angle = 3 ;
rotate(radians(angle));
expos = screenX(0, 230);
eypos = screenY(0, 230);
sxpos = width / 2;
sypos = height / 2;
smovetime = millis();
emovetime = smovetime + 1250;
percent = pct;
colorMode(HSB);
lastcheck = millis();
chue = 5;
popMatrix();
setupBits();
}
void setupBits()
{
for (int i = 0; i < testTorrent.bits.size(); i++)
{
if (!myBits.contains(testTorrent.bits.get(i)))
{
needBits.add(testTorrent.bits.get(i));
}
}
}
void findPeer()
{
for (int i = 0; i < needBits.size(); i++)
{
needBits = shuffle(needBits);
Bit b = (Bit)needBits.get(i);
for (int o = 0; o < peers.size(); o++)
{
Peer p = (Peer)peers.get(o);
if (p.myBits.contains(b) && !(p.removing > 0) && !(removing > 0)
&& !p.knex.contains((Peer)peers.get(index)) && p.index != index &&
!actBits.contains(b))
{
bitRequest(p,b);
}
}
}
}
void bitRequest(Peer k, Bit j)
{
if (k.knex.size() < 4)
{
Connection mz = new Connection(k, (Peer)peers.get(index), j);
k.knex.add(peers.get(index));
actBits.add(j);
connections.add(mz);
}
}
void reConfigure(int i)
{
int k;
pushMatrix();
translate(width / 2, height / 2);
ellipseMode(CENTER);
if (peers.size() == 0)
{
k = 1;
}
else
{
k = peers.size();
}
index = i;
float angle = ((360 / k) * i) + rot;
rotate(radians(angle));
sxpos = cxpos;
sypos = cypos;
expos = screenX(0, 180);
eypos = screenY(0, 180);
smovetime= millis();
emovetime= smovetime + 3000;
popMatrix();
shue = chue;
ehue = (255 / peers.size() - 1) * i;
ccolor = color(chue, 255, 255, 133);
}
void moveSelf()
{
if (millis() > emovetime)
{
cxpos = expos;
cypos = eypos;
chue = ehue;
}
else
{
float diff = (millis() - smovetime) / (emovetime - smovetime);
cxpos = sxpos * (1 - diff) + expos * diff;
cypos = sypos * (1 - diff) + eypos * diff;
chue = shue * (1 - diff) + ehue * diff;
}
}
void drawSelf()
{
fill(ccolor);
stroke(myBits.size());
strokeWeight(1);
ellipseMode(CENTER);
ellipse(cxpos, cypos, 50, 50);
fill(0);
float w = testTorrent.bits.size() - 1;
rect(cxpos - w/2, cypos - 5, w, 10);
for(int i = 0; i < myBits.size(); i++)
{
Bit k = (Bit)myBits.get(i);
colorMode(HSB);
stroke(k.bitHue, 255, 255);
line(cxpos - w/2 + (1 * k.id), cypos - 5, cxpos - w / 2 + (1 * k.id), cypos + 5);
}
}
}
class Kibble
{
float starttime;
float endtime;
float big;
Kibble()
{
starttime = 0;
endtime = 0;
big = (random(0,4));
}
}
class Connection
{
int lastdraw;
Peer from;
Peer to;
boolean stream;
ArrayList kibbles = new ArrayList();
int deadkibbles;
int speed;
Bit theBit;
Connection(Peer f, Peer t, Bit b)
{
theBit = (Bit)b;
from = f;
to = t;
stream = true;
lastdraw = millis();
deadkibbles = 0;
speed = int(random(30,500));
}
int getIdxTo()
{
return to.index;
}
int getIdxFrom()
{
return from.index;
}
void manageKibbles()
{
if ( from.removing >= 1 || to.removing >= 1 || deadkibbles > 125 )
{
stream = false;
}
else
{
if (lastdraw < millis() - speed)
{
newKibble();
}
}
drawKibbles();
}
void newKibble()
{
Kibble k = new Kibble();
k.starttime = millis();
k.endtime = k.starttime + 5000;
kibbles.add(k);
lastdraw = millis();
}
void drawKibbles()
{
for (int i = 0; i < kibbles.size(); i++)
{
Kibble k = (Kibble)kibbles.get(i);
if(millis() > k.endtime)
{
kibbles.remove(i);
deadkibbles++;
}
else
{
float diff = (millis() - k.starttime) / (k.endtime - k.starttime);
float xpos = from.cxpos * (1 - diff) + (to.cxpos) * diff;
float ypos = from.cypos * (1 - diff) + (to.cypos) * diff;
colorMode(HSB);
fill(theBit.bitHue, 255, 255);
stroke(theBit.bitHue, 255, 255);
strokeWeight(k.big);
ellipse(xpos, ypos, k.big, k.big);
}
}
}
}
class Bit
{
int id;
int bitHue;
Bit(int i, int hu)
{
id = i;
bitHue = hu;
}
}
class Torrent
{
ArrayList bits = new ArrayList();
Torrent(int totbits)
{
for (int i=0; i < totbits; i ++)
{
int ll = (255 / totbits) * i;
Bit k = new Bit(i, ll);
bits.add(k);
}
}
}
ArrayList shuffle(ArrayList input)
{
ArrayList yin = new ArrayList();
for (int i = 0; i < input.size(); i++)
{
yin.add(input.get(i));
}
ArrayList temp = new ArrayList();
while (yin.size() > 0)
{
int x = int(random(0, yin.size()));
temp.add(yin.get(x));
yin.remove(x);
}
return(temp);
}