Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions FBVis/Crawler.pde
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
class Crawler {
PVector pos;
PVector prev_pos;

Node target;

// Appearance
float travel_lerp;
float travel_y_lerp_mult;

public Crawler(Node source, Node target)
{
this.pos = source.pos.copy();
this.prev_pos = source.pos.copy();
this.target = target;

this.travel_lerp = random(CONFIG.payloadSegmentLerpMin, CONFIG.payloadSegmentLerpMax);
this.travel_y_lerp_mult = random(0.5, 0.8);

// if the source is personnode
if (source instanceof PersonNode) {
((PersonNode) source).refresh();
}
}

private void update() {
// Move towards target lerp
this.prev_pos.set(this.pos);
// this.pos = PVector.lerp(this.pos, this.target.pos, 0.1);
this.pos.x = lerp(this.pos.x, this.target.pos.x, this.travel_lerp);
this.pos.y = lerp(this.pos.y, this.target.pos.y, this.travel_lerp * this.travel_y_lerp_mult);
}

public boolean hasArrived() {
if (this.getArrived()) {

if (target instanceof PersonNode) {
((PersonNode) target).refresh();
}
return true;
}

return false;
}

protected boolean getArrived() {
// Return true if close enough to target
return (this.pos.dist(this.target.pos) < 10);
}
}

class Crawlers {
public ArrayList<Crawler> inboundCrawlers;
public ArrayList<Crawler> outboundCrawlers;

public Crawlers() {
this.inboundCrawlers = new ArrayList<Crawler>();
this.outboundCrawlers = new ArrayList<Crawler>();
}

public void addCrawler(Node source, Node target, boolean inbound) {
if (inbound) {
this.inboundCrawlers.add(new Crawler(source, target));
} else {
this.outboundCrawlers.add(new Crawler(source, target));
}
}

public void update() {
// Update crawlers
this.inboundCrawlers.forEach(Crawler::update);
this.outboundCrawlers.forEach(Crawler::update);

// Remove crawlers that have arrived
this.inboundCrawlers.removeIf(Crawler::hasArrived);
this.outboundCrawlers.removeIf(Crawler::hasArrived);
}

public int getNumCrawlers() {
return this.inboundCrawlers.size() + this.outboundCrawlers.size();
}
}
37 changes: 37 additions & 0 deletions FBVis/CrawlerRender.pde
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
class RenderCrawlerLayer extends RenderLayer {

private Crawlers crawlers;

public RenderCrawlerLayer(Crawlers crawlers) {
super();
this.crawlers = crawlers;
}

private void updateCrawlers() {
this.crawlers.update();
}

@Override
protected void renderGraphics() {
this.pg.clear();
this.pg.pushMatrix();
this.pg.translate(width/2, height/2);
this.pg.blendMode(SCREEN);
this.pg.strokeWeight(1);

// Draw inbound crawlers
this.pg.stroke(160, 80, 80);
for (Crawler c : this.crawlers.inboundCrawlers) {
this.pg.line(c.pos.x, c.pos.y, c.prev_pos.x, c.prev_pos.y);
}

// Draw outbound crawlers
this.pg.stroke(80, 160, 80);
for (Crawler c : this.crawlers.outboundCrawlers) {
this.pg.line(c.pos.x, c.pos.y, c.prev_pos.x, c.prev_pos.y);
}
this.pg.popMatrix();

this.updateCrawlers();
}
}
11 changes: 5 additions & 6 deletions Exceptions.pde → FBVis/Exceptions.pde
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
public class NotDirectoryException extends Exception {
public NotDirectoryException(String errorMessage) {
super(errorMessage);
}
}

public class NotDirectoryException extends Exception {
public NotDirectoryException(String errorMessage) {
super(errorMessage);
}
}
169 changes: 169 additions & 0 deletions FBVis/FBVis.pde
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import java.util.Map;



// ============ application states enum ============
enum AppState {
INIT, RUNNING, PAUSED
}
AppState state = AppState.INIT;

// ============ data ============

FBVisConfig CONFIG;

MessageManager msgManager;
MessageScheduler msgScheduler;

MasterPersonNode root;
HashMap<Integer, Node> personNodes;

// Crawers
Crawlers crawlers;

// ============ render layers ============

RenderPeopleLayer peopleLayer;
RenderCrawlerLayer crawlerLayer;
String RENDERER = P2D;

// ============ Sprites ============

Sprites sprites;

// ============ visualization ============

void settings() {
size(1920, 1080, RENDERER);
// fullScreen(RENDERER);
}

void setup() {
CONFIG = new FBVisConfig();
thread("initializeData");
thread("preRender");
frameRate(144);
}

void initializeData() {
// Start timer
int startTime = millis();
msgManager = new MessageManager(CONFIG.dataRootPath);
int duration = millis() - startTime;
println("Done loading data");
println(msgManager.organizedMessagesList.size()); //<>//
println("Took " + duration + "ms");

msgScheduler = new MessageScheduler(msgManager);

// Initialize the person nodes map with root
personNodes = new HashMap<Integer, Node>(); //<>// //<>//
int root_id = msgManager.nameToIdMap.get(CONFIG.masterName); //<>//
root = new MasterPersonNode(root_id, CONFIG.masterName);
personNodes.put(root_id, root);

// Initialize visualization
peopleLayer = new RenderPeopleLayer(root);

crawlers = new Crawlers();
crawlerLayer = new RenderCrawlerLayer(crawlers);

state = AppState.RUNNING;
}

void preRender() {
sprites = new Sprites();
}

void draw() {
if (state == AppState.INIT) {
background(255);
} else if (state == AppState.RUNNING) {
background(30);
fill(255);

// Do something with msg data every turn
ArrayList<MessageData> msgs = msgScheduler.nextTimeStep();
for (int i = 0; i < msgs.size(); i++) {
MessageData msg = msgs.get(i);
if (msg == null) {
state = AppState.PAUSED;
return;
}
updateIdNodeMap(msg);
updateCrawlers(msg);
}

image(peopleLayer.getRender(), 0, 0);
blendMode(ADD);
image(crawlerLayer.getRender(), 0, 0);
text(frameRate, 10, 10);
text(msgScheduler.getCurrentTime(), 10, 30);
text("Crawlers: " + crawlers.getNumCrawlers(), 10, 50);

if (msgScheduler.finished()) {
state = AppState.PAUSED;
}

} else if (state == AppState.PAUSED) {
background(30);
fill(255);

image(peopleLayer.getRender(), 0, 0);
blendMode(ADD);
image(crawlerLayer.getRender(), 0, 0);
text(frameRate, 10, 10);
text(msgScheduler.getCurrentTime(), 10, 30);
}

if (frameCount % 60 == 0) {
println(frameRate);
}
}

// ============ data processing ============

void updateIdNodeMap(MessageData msg) {
int sender_id = msg.sender_id;
int[] receiver_ids = msg.receiver_ids;

if (personNodes.containsKey(sender_id) == false) {
PersonNode senderNode = new PersonNode(sender_id, msgManager.idToNameMap.get(sender_id));
personNodes.put(sender_id, senderNode);
root.addNode(senderNode);
}

for (int i = 0; i < receiver_ids.length; i++) {
int receiver_id = receiver_ids[i];
if (personNodes.containsKey(receiver_id) == false) {
PersonNode receiverNode = new PersonNode(receiver_id, msgManager.idToNameMap.get(receiver_id));
personNodes.put(receiver_id, receiverNode);
root.addNode(receiverNode);
}
}
}

void updateCrawlers(MessageData msg) {
for (int i = 0; i < msg.receiver_ids.length; i++) {
crawlers.addCrawler(
personNodes.get(msg.sender_id),
personNodes.get(msg.receiver_ids[i]),

// inbound? (if sender is not root, then it's inbound)
(msg.sender_id != root.id)
);
}
}


// ============ input ============

void keyPressed() {
if (key == ' ') {
if (state == AppState.RUNNING) {
state = AppState.PAUSED;
} else if (state == AppState.PAUSED) {
state = AppState.RUNNING;
}
}
}
Loading