diff --git a/htroot/processing/domaingraph/applet/domaingraph.jar b/htroot/processing/domaingraph/applet/domaingraph.jar index 9cb521ca7..db614ad8f 100755 Binary files a/htroot/processing/domaingraph/applet/domaingraph.jar and b/htroot/processing/domaingraph/applet/domaingraph.jar differ diff --git a/htroot/processing/domaingraph/applet/domaingraph.java b/htroot/processing/domaingraph/applet/domaingraph.java index 98f521cf2..4443793f7 100755 --- a/htroot/processing/domaingraph/applet/domaingraph.java +++ b/htroot/processing/domaingraph/applet/domaingraph.java @@ -12,77 +12,124 @@ import processing.core.*; import traer.physics.*; import traer.animation.*; impo final float NODE_SIZE = 6; -final float EDGE_LENGTH = 50; -final float EDGE_STRENGTH = 0.01f; -final float SPACER_STRENGTH = 10; +final float EDGE_LENGTH = 30; +final float EDGE_STRENGTH = 0.001f; +final float SPACER_STRENGTH = 250; ParticleSystem physics; Smoother3D centroid; PFont font; +float x = 0.0f; +float y = 0.0f; +float z = 1.0f; Client myClient; Particle center0, center1; // two gravity centers to support object ordering for non-quadratic fields String parsingHostName = ""; String parsingHostID = ""; HashMap nodes = new HashMap(); // map that holds host objects +String host; +int port; +float a = 0.0f; +long lastUpdate = Long.MAX_VALUE; +boolean initTime = true; public void setup() { String[] fontList = PFont.list(); //println(fontList); font = createFont(fontList[0], 32); //just take any, should be mostly Arial - textFont(font, 12); + textFont(font, 9); size(660, 400); smooth(); - frameRate( 24 ); - strokeWeight( 2 ); + frameRate( 12 ); + strokeWeight( 1 ); ellipseMode( CENTER ); physics = new ParticleSystem( 0, 0.25f ); centroid = new Smoother3D( 0.8f ); initializePhysics(); - initRequest(); + URL url = null; + try { + url = getDocumentBase(); + } catch (NullPointerException e) {} + if (url == null) { + host="localhost"; + port=8080; + } else { + host=url.getHost(); + port=url.getPort(); + } + //println("CodeBase: " + url); + //println("host: " + host); + //println("port: " + port); + + initRequest(false); } -public void initRequest() { - myClient = new Client(this, "localhost", 8080); - myClient.write("GET /xml/webstructure.xml HTTP/1.1\n"); - myClient.write("Host: localhost\n\n"); +public void initializePhysics() { + physics.clear(); + center0 = physics.makeParticle(1.0f, -EDGE_LENGTH * 10, 0, 0); + center0.makeFixed(); + center1 = physics.makeParticle(1.0f, EDGE_LENGTH * 10, 0, 0); + center1.makeFixed(); + centroid.setValue( 0, 0, 1.0f ); } -public void processRequestResponse() { - if (myClient.available() > 0) { - String line = myClient.readStringUntil((byte) 10); - //println("Line: " + line); - if (line == null) line = ""; else line = line.trim(); - if (line.startsWith(" 1) updateCentroid(invisible); + centroid.tick(); + + background( 0 ); + translate( width/2 , height/2 ); + scale( centroid.z() ); + translate( -centroid.x(), -centroid.y() ); + + drawNetwork(invisible); } -public HashMap parseProps(String s) { - String[] l = s.split(" "); - HashMap map = new HashMap(); - int p; - String z; - for (int i = 0; i < l.length; i++) { - p = l[i].indexOf("="); - if (p > 0) { - z = l[i].substring(p + 1).trim(); - if (z.charAt(0) == '"') z = z.substring(1); - if (z.charAt(z.length() - 1) == '"') z = z.substring(0, z.length() - 1); - map.put(l[i].substring(0, p), z); +public void initRequest(boolean update) { + myClient = new Client(this, host, port); + myClient.write((update) ? "GET /xml/webstructure.xml?latest= HTTP/1.1\n" : "GET /xml/webstructure.xml HTTP/1.1\n"); + myClient.write("Host: localhost\n\n"); +} + +public void processRequestResponse(int steps) { + if (((myClient == null) || (myClient.available() <= 0)) && (System.currentTimeMillis() - lastUpdate > 10000)) { + initRequest(true); + lastUpdate = Long.MAX_VALUE; + return; + } + for (int i = 0; i < steps; i++) { + if (myClient.available() > 0) { + String line = myClient.readStringUntil((byte) 10); + //println("Line: " + line); + if (line == null) line = ""; else line = line.trim(); + if (line.startsWith(" TWO_PI) a -= TWO_PI; nodes.put(parsingHostID, h); addAttraction(h.node); } @@ -97,113 +144,160 @@ public void processCitation(HashMap props) { } catch (NumberFormatException e) {} // find the two nodes that have a relation host h = (host) nodes.get(id); - if (h == null) return; // host is not known TODO: store these and create relation later + if (h == null) { + return; /* + h = new host(host, physics.makeParticle(1.0, EDGE_LENGTH * 20 * cos(a), -EDGE_LENGTH * 10 * sin(a), 0)); + a += TWO_PI/256.0 + TWO_PI / 2; if (a > TWO_PI) a -= TWO_PI; + nodes.put(id, h); + addAttraction(h.node);*/ + } + h.time = System.currentTimeMillis(); host p = (host) nodes.get(parsingHostID); // this should be successful - addRelation(h.node, p.node); + // prevent that a spring is made twice + for ( int i = 0; i < physics.numberOfSprings(); ++i ) { + Spring e = physics.getSpring(i); + Particle a = e.getOneEnd(); + Particle b = e.getTheOtherEnd(); + if (((a == h.node) && (b == p.node)) || ((b == h.node) && (a == p.node))) return; + } + physics.makeSpring(h.node, p.node, EDGE_STRENGTH, EDGE_STRENGTH, EDGE_LENGTH ); } -public void draw() { - processRequestResponse(); - - physics.tick( 1.0f ); - if (physics.numberOfParticles() > 1) updateCentroid(); - centroid.tick(); +public HashMap parseProps(String s) { + String[] l = s.split(" "); + HashMap map = new HashMap(); + int p; + String z; + for (int i = 0; i < l.length; i++) { + p = l[i].indexOf("="); + if (p > 0) { + z = l[i].substring(p + 1).trim(); + if (z.charAt(0) == '"') z = z.substring(1); + if (z.charAt(z.length() - 1) == '"') z = z.substring(0, z.length() - 1); + map.put(l[i].substring(0, p), z); + } + } + return map; +} - background( 0 ); - translate( width/2 , height/2 ); - scale( centroid.z() ); - translate( -centroid.x(), -centroid.y() ); - - drawNetwork(); +public HashSet invisibleParticles() { + // get nodes that have no edges + HashSet particles = new HashSet(); + Iterator j = nodes.values().iterator(); + host h; + long t = 0, n = System.currentTimeMillis(); + while (j.hasNext()) { + h = (host) j.next(); + t += n - h.time; + particles.add(h.node); + } + t = t / (nodes.size() + 1); + for ( int i = 0; i < physics.numberOfSprings(); ++i ) { + Spring e = physics.getSpring(i); + particles.remove(e.getOneEnd()); + particles.remove(e.getTheOtherEnd()); + } + // add more nodes if the number is too large + if (nodes.size() > 80) { + j = nodes.values().iterator(); + while (j.hasNext()) { + h = (host) j.next(); + if (n - h.time > 15000) particles.add(h.node); + if (nodes.size() - particles.size() < 80) break; + } + } + return particles; } -public void drawNetwork() { - fill( 100, 255, 100 ); +public void drawNetwork(HashSet invisible) { // draw vertices + fill( 120, 255, 120 ); noStroke(); String name; - Iterator j = nodes.values().iterator(); host h; + Iterator j = nodes.values().iterator(); while (j.hasNext()) { h = (host) j.next(); Particle v = h.node; + if (invisible.contains(v)) continue; ellipse(v.position().x(), v.position().y(), NODE_SIZE, NODE_SIZE); name = h.name; text(name, v.position().x() - (name.length() * 26 / 10), v.position().y() + 14); } - + // draw center - /* - ellipse( center0.position().x(), center0.position().y(), NODE_SIZE * 2, NODE_SIZE * 2 ); - name = "Center0"; - text(name, center0.position().x() - (name.length() * 26 / 10), center0.position().y() + 14); - ellipse( center1.position().x(), center1.position().y(), NODE_SIZE * 2, NODE_SIZE * 2 ); - name = "Center1"; - text(name, center1.position().x() - (name.length() * 26 / 10), center1.position().y() + 14); - */ - + //fill( 255, 0, 0 ); + //ellipse( center0.position().x(), center0.position().y(), NODE_SIZE * 2, NODE_SIZE * 2 ); + //ellipse( center1.position().x(), center1.position().y(), NODE_SIZE * 2, NODE_SIZE * 2 ); + // draw edges - stroke( 160 ); - beginShape( LINES ); + stroke( 200 ); for ( int i = 0; i < physics.numberOfSprings(); ++i ) { Spring e = physics.getSpring( i ); Particle a = e.getOneEnd(); + if (invisible.contains(a)) continue; Particle b = e.getTheOtherEnd(); - vertex( a.position().x(), a.position().y() ); - vertex( b.position().x(), b.position().y() ); + if (invisible.contains(b)) continue; + line(a.position().x(), a.position().y(), b.position().x(), b.position().y()); } - endShape(); + } public void keyPressed() { - if ( key == 'c' ) { - initializePhysics(); - return; - } - - if ( key == ' ' ) { - Particle p = physics.makeParticle(); - addRelation(p, physics.getParticle( (int) random( 0, physics.numberOfParticles()-1) )); - addAttraction(p); + if ( key == 'c' ) initializePhysics(); + if ( key == 'a' ) x = Math.max(-1.0f, x - 0.1f); + if ( key == 'd' ) x = Math.min( 1.0f, x + 0.1f); + if ( key == 'w' ) y = Math.max(-1.0f, y - 0.1f); + if ( key == 's' ) y = Math.min( 1.0f, y + 0.1f); + if ( key == '-' ) z = Math.max( 1.0f, z - 1.0f); + if ( key == '+' ) z = Math.min(10.0f, z + 1.0f); + if ( key == '0' ) { x = 0.0f; y = 0.0f; z = 1.0f; } + if ( key == 't' ) { + HashSet hs = new HashSet(); + for (int i = 0; i < physics.numberOfParticles(); ++i ) { + hs.add(physics.getParticle(i)); + } + for (int i = 0; i < physics.numberOfSprings(); ++i ) { + hs.remove(physics.getSpring(i).getOneEnd()); + hs.remove(physics.getSpring(i).getTheOtherEnd()); + } + Iterator i = hs.iterator(); + while (i.hasNext()) { + ((Particle) i.next()).kill(); + } return; } } -public void updateCentroid() { +public void updateCentroid(HashSet invisible) { float xMax = Float.NEGATIVE_INFINITY, xMin = Float.POSITIVE_INFINITY, yMin = Float.POSITIVE_INFINITY, yMax = Float.NEGATIVE_INFINITY; - for ( int i = 0; i < physics.numberOfParticles(); ++i ) { - Particle p = physics.getParticle( i ); + for (int i = 0; i < physics.numberOfParticles(); ++i) { + Particle p = physics.getParticle(i); + if ((i >= 2) && ((p == center0) || (p == center1) || (invisible.contains(p)))) continue; xMax = max( xMax, p.position().x() ); xMin = min( xMin, p.position().x() ); yMin = min( yMin, p.position().y() ); yMax = max( yMax, p.position().y() ); } + float deltaX = xMax-xMin; float deltaY = yMax-yMin; - if ( deltaY > deltaX ) - centroid.setTarget( xMin + 0.5f*deltaX, yMin +0.5f*deltaY, height/(deltaY+50) ); - else - centroid.setTarget( xMin + 0.5f*deltaX, yMin +0.5f*deltaY, width/(deltaX+50) ); -} - -public void initializePhysics() { - physics.clear(); - center0 = physics.makeParticle(1.0f, 0, 0, 0); - center0.makeFixed(); - center1 = physics.makeParticle(1.0f, EDGE_LENGTH * 30, 0, 0); - center1.makeFixed(); - centroid.setValue( 0, 0, 1.0f ); + centroid.setTarget( + xMin + (x + 1) * 0.5f * deltaX, + yMin + (y + 1) * 0.5f * deltaY, + z * ((deltaY > deltaX) ? height / (deltaY + 50) : width / (deltaX + 50)) + ); } public void addAttraction(Particle p) { - physics.makeAttraction(center0, p, 5000.0f, 3 * EDGE_LENGTH); - physics.makeAttraction(center1, p, 5000.0f, 3 * EDGE_LENGTH); + physics.makeAttraction(center0, p, SPACER_STRENGTH * 10000.0f, 100 * EDGE_LENGTH); + physics.makeAttraction(center1, p, SPACER_STRENGTH * 10000.0f, 100 * EDGE_LENGTH); // spacers for ( int i = 0; i < physics.numberOfParticles(); ++i ) { @@ -212,17 +306,14 @@ public void addAttraction(Particle p) { } } -public void addRelation(Particle p, Particle other) { - physics.makeSpring( p, other, EDGE_STRENGTH, EDGE_STRENGTH, EDGE_LENGTH ); - //p.moveTo( q.position().x() + random( -1, 1 ), q.position().y() + random( -1, 1 ), 0 ); -} - static class host { String name; Particle node; + long time; public host(String name, Particle node) { this.name = name; this.node = node; + this.time = System.currentTimeMillis(); } } diff --git a/htroot/processing/domaingraph/applet/domaingraph.pde b/htroot/processing/domaingraph/applet/domaingraph.pde index e79f083e7..4805b93be 100755 --- a/htroot/processing/domaingraph/applet/domaingraph.pde +++ b/htroot/processing/domaingraph/applet/domaingraph.pde @@ -12,77 +12,124 @@ import traer.animation.*; import processing.net.*; final float NODE_SIZE = 6; -final float EDGE_LENGTH = 50; -final float EDGE_STRENGTH = 0.01; -final float SPACER_STRENGTH = 10; +final float EDGE_LENGTH = 30; +final float EDGE_STRENGTH = 0.001; +final float SPACER_STRENGTH = 250; ParticleSystem physics; Smoother3D centroid; PFont font; +float x = 0.0; +float y = 0.0; +float z = 1.0; Client myClient; Particle center0, center1; // two gravity centers to support object ordering for non-quadratic fields String parsingHostName = ""; String parsingHostID = ""; HashMap nodes = new HashMap(); // map that holds host objects +String host; +int port; +float a = 0.0; +long lastUpdate = Long.MAX_VALUE; +boolean initTime = true; void setup() { String[] fontList = PFont.list(); //println(fontList); font = createFont(fontList[0], 32); //just take any, should be mostly Arial - textFont(font, 12); + textFont(font, 9); size(660, 400); smooth(); - frameRate( 24 ); - strokeWeight( 2 ); + frameRate( 12 ); + strokeWeight( 1 ); ellipseMode( CENTER ); physics = new ParticleSystem( 0, 0.25 ); centroid = new Smoother3D( 0.8 ); initializePhysics(); - initRequest(); + URL url = null; + try { + url = getDocumentBase(); + } catch (NullPointerException e) {} + if (url == null) { + host="localhost"; + port=8080; + } else { + host=url.getHost(); + port=url.getPort(); + } + //println("CodeBase: " + url); + //println("host: " + host); + //println("port: " + port); + + initRequest(false); } -void initRequest() { - myClient = new Client(this, "localhost", 8080); - myClient.write("GET /xml/webstructure.xml HTTP/1.1\n"); - myClient.write("Host: localhost\n\n"); +void initializePhysics() { + physics.clear(); + center0 = physics.makeParticle(1.0, -EDGE_LENGTH * 10, 0, 0); + center0.makeFixed(); + center1 = physics.makeParticle(1.0, EDGE_LENGTH * 10, 0, 0); + center1.makeFixed(); + centroid.setValue( 0, 0, 1.0 ); } -void processRequestResponse() { - if (myClient.available() > 0) { - String line = myClient.readStringUntil((byte) 10); - //println("Line: " + line); - if (line == null) line = ""; else line = line.trim(); - if (line.startsWith(" 1) updateCentroid(invisible); + centroid.tick(); + + background( 0 ); + translate( width/2 , height/2 ); + scale( centroid.z() ); + translate( -centroid.x(), -centroid.y() ); + + drawNetwork(invisible); } -HashMap parseProps(String s) { - String[] l = s.split(" "); - HashMap map = new HashMap(); - int p; - String z; - for (int i = 0; i < l.length; i++) { - p = l[i].indexOf("="); - if (p > 0) { - z = l[i].substring(p + 1).trim(); - if (z.charAt(0) == '"') z = z.substring(1); - if (z.charAt(z.length() - 1) == '"') z = z.substring(0, z.length() - 1); - map.put(l[i].substring(0, p), z); +void initRequest(boolean update) { + myClient = new Client(this, host, port); + myClient.write((update) ? "GET /xml/webstructure.xml?latest= HTTP/1.1\n" : "GET /xml/webstructure.xml HTTP/1.1\n"); + myClient.write("Host: localhost\n\n"); +} + +void processRequestResponse(int steps) { + if (((myClient == null) || (myClient.available() <= 0)) && (System.currentTimeMillis() - lastUpdate > 10000)) { + initRequest(true); + lastUpdate = Long.MAX_VALUE; + return; + } + for (int i = 0; i < steps; i++) { + if (myClient.available() > 0) { + String line = myClient.readStringUntil((byte) 10); + //println("Line: " + line); + if (line == null) line = ""; else line = line.trim(); + if (line.startsWith(" TWO_PI) a -= TWO_PI; nodes.put(parsingHostID, h); addAttraction(h.node); } @@ -97,113 +144,160 @@ void processCitation(HashMap props) { } catch (NumberFormatException e) {} // find the two nodes that have a relation host h = (host) nodes.get(id); - if (h == null) return; // host is not known TODO: store these and create relation later + if (h == null) { + return; /* + h = new host(host, physics.makeParticle(1.0, EDGE_LENGTH * 20 * cos(a), -EDGE_LENGTH * 10 * sin(a), 0)); + a += TWO_PI/256.0 + TWO_PI / 2; if (a > TWO_PI) a -= TWO_PI; + nodes.put(id, h); + addAttraction(h.node);*/ + } + h.time = System.currentTimeMillis(); host p = (host) nodes.get(parsingHostID); // this should be successful - addRelation(h.node, p.node); + // prevent that a spring is made twice + for ( int i = 0; i < physics.numberOfSprings(); ++i ) { + Spring e = physics.getSpring(i); + Particle a = e.getOneEnd(); + Particle b = e.getTheOtherEnd(); + if (((a == h.node) && (b == p.node)) || ((b == h.node) && (a == p.node))) return; + } + physics.makeSpring(h.node, p.node, EDGE_STRENGTH, EDGE_STRENGTH, EDGE_LENGTH ); } -void draw() { - processRequestResponse(); - - physics.tick( 1.0 ); - if (physics.numberOfParticles() > 1) updateCentroid(); - centroid.tick(); +HashMap parseProps(String s) { + String[] l = s.split(" "); + HashMap map = new HashMap(); + int p; + String z; + for (int i = 0; i < l.length; i++) { + p = l[i].indexOf("="); + if (p > 0) { + z = l[i].substring(p + 1).trim(); + if (z.charAt(0) == '"') z = z.substring(1); + if (z.charAt(z.length() - 1) == '"') z = z.substring(0, z.length() - 1); + map.put(l[i].substring(0, p), z); + } + } + return map; +} - background( 0 ); - translate( width/2 , height/2 ); - scale( centroid.z() ); - translate( -centroid.x(), -centroid.y() ); - - drawNetwork(); +HashSet invisibleParticles() { + // get nodes that have no edges + HashSet particles = new HashSet(); + Iterator j = nodes.values().iterator(); + host h; + long t = 0, n = System.currentTimeMillis(); + while (j.hasNext()) { + h = (host) j.next(); + t += n - h.time; + particles.add(h.node); + } + t = t / (nodes.size() + 1); + for ( int i = 0; i < physics.numberOfSprings(); ++i ) { + Spring e = physics.getSpring(i); + particles.remove(e.getOneEnd()); + particles.remove(e.getTheOtherEnd()); + } + // add more nodes if the number is too large + if (nodes.size() > 80) { + j = nodes.values().iterator(); + while (j.hasNext()) { + h = (host) j.next(); + if (n - h.time > 15000) particles.add(h.node); + if (nodes.size() - particles.size() < 80) break; + } + } + return particles; } -void drawNetwork() { - fill( 100, 255, 100 ); +void drawNetwork(HashSet invisible) { // draw vertices + fill( 120, 255, 120 ); noStroke(); String name; - Iterator j = nodes.values().iterator(); host h; + Iterator j = nodes.values().iterator(); while (j.hasNext()) { h = (host) j.next(); Particle v = h.node; + if (invisible.contains(v)) continue; ellipse(v.position().x(), v.position().y(), NODE_SIZE, NODE_SIZE); name = h.name; text(name, v.position().x() - (name.length() * 26 / 10), v.position().y() + 14); } - + // draw center - /* - ellipse( center0.position().x(), center0.position().y(), NODE_SIZE * 2, NODE_SIZE * 2 ); - name = "Center0"; - text(name, center0.position().x() - (name.length() * 26 / 10), center0.position().y() + 14); - ellipse( center1.position().x(), center1.position().y(), NODE_SIZE * 2, NODE_SIZE * 2 ); - name = "Center1"; - text(name, center1.position().x() - (name.length() * 26 / 10), center1.position().y() + 14); - */ - + //fill( 255, 0, 0 ); + //ellipse( center0.position().x(), center0.position().y(), NODE_SIZE * 2, NODE_SIZE * 2 ); + //ellipse( center1.position().x(), center1.position().y(), NODE_SIZE * 2, NODE_SIZE * 2 ); + // draw edges - stroke( 160 ); - beginShape( LINES ); + stroke( 200 ); for ( int i = 0; i < physics.numberOfSprings(); ++i ) { Spring e = physics.getSpring( i ); Particle a = e.getOneEnd(); + if (invisible.contains(a)) continue; Particle b = e.getTheOtherEnd(); - vertex( a.position().x(), a.position().y() ); - vertex( b.position().x(), b.position().y() ); + if (invisible.contains(b)) continue; + line(a.position().x(), a.position().y(), b.position().x(), b.position().y()); } - endShape(); + } void keyPressed() { - if ( key == 'c' ) { - initializePhysics(); - return; - } - - if ( key == ' ' ) { - Particle p = physics.makeParticle(); - addRelation(p, physics.getParticle( (int) random( 0, physics.numberOfParticles()-1) )); - addAttraction(p); + if ( key == 'c' ) initializePhysics(); + if ( key == 'a' ) x = Math.max(-1.0, x - 0.1); + if ( key == 'd' ) x = Math.min( 1.0, x + 0.1); + if ( key == 'w' ) y = Math.max(-1.0, y - 0.1); + if ( key == 's' ) y = Math.min( 1.0, y + 0.1); + if ( key == '-' ) z = Math.max( 1.0, z - 1.0); + if ( key == '+' ) z = Math.min(10.0, z + 1.0); + if ( key == '0' ) { x = 0.0; y = 0.0; z = 1.0; } + if ( key == 't' ) { + HashSet hs = new HashSet(); + for (int i = 0; i < physics.numberOfParticles(); ++i ) { + hs.add(physics.getParticle(i)); + } + for (int i = 0; i < physics.numberOfSprings(); ++i ) { + hs.remove(physics.getSpring(i).getOneEnd()); + hs.remove(physics.getSpring(i).getTheOtherEnd()); + } + Iterator i = hs.iterator(); + while (i.hasNext()) { + ((Particle) i.next()).kill(); + } return; } } -void updateCentroid() { +void updateCentroid(HashSet invisible) { float xMax = Float.NEGATIVE_INFINITY, xMin = Float.POSITIVE_INFINITY, yMin = Float.POSITIVE_INFINITY, yMax = Float.NEGATIVE_INFINITY; - for ( int i = 0; i < physics.numberOfParticles(); ++i ) { - Particle p = physics.getParticle( i ); + for (int i = 0; i < physics.numberOfParticles(); ++i) { + Particle p = physics.getParticle(i); + if ((i >= 2) && ((p == center0) || (p == center1) || (invisible.contains(p)))) continue; xMax = max( xMax, p.position().x() ); xMin = min( xMin, p.position().x() ); yMin = min( yMin, p.position().y() ); yMax = max( yMax, p.position().y() ); } + float deltaX = xMax-xMin; float deltaY = yMax-yMin; - if ( deltaY > deltaX ) - centroid.setTarget( xMin + 0.5*deltaX, yMin +0.5*deltaY, height/(deltaY+50) ); - else - centroid.setTarget( xMin + 0.5*deltaX, yMin +0.5*deltaY, width/(deltaX+50) ); -} - -void initializePhysics() { - physics.clear(); - center0 = physics.makeParticle(1.0, 0, 0, 0); - center0.makeFixed(); - center1 = physics.makeParticle(1.0, EDGE_LENGTH * 30, 0, 0); - center1.makeFixed(); - centroid.setValue( 0, 0, 1.0 ); + centroid.setTarget( + xMin + (x + 1) * 0.5 * deltaX, + yMin + (y + 1) * 0.5 * deltaY, + z * ((deltaY > deltaX) ? height / (deltaY + 50) : width / (deltaX + 50)) + ); } void addAttraction(Particle p) { - physics.makeAttraction(center0, p, 5000.0, 3 * EDGE_LENGTH); - physics.makeAttraction(center1, p, 5000.0, 3 * EDGE_LENGTH); + physics.makeAttraction(center0, p, SPACER_STRENGTH * 10000.0, 100 * EDGE_LENGTH); + physics.makeAttraction(center1, p, SPACER_STRENGTH * 10000.0, 100 * EDGE_LENGTH); // spacers for ( int i = 0; i < physics.numberOfParticles(); ++i ) { @@ -212,16 +306,13 @@ void addAttraction(Particle p) { } } -void addRelation(Particle p, Particle other) { - physics.makeSpring( p, other, EDGE_STRENGTH, EDGE_STRENGTH, EDGE_LENGTH ); - //p.moveTo( q.position().x() + random( -1, 1 ), q.position().y() + random( -1, 1 ), 0 ); -} - static class host { String name; Particle node; + long time; public host(String name, Particle node) { this.name = name; this.node = node; + this.time = System.currentTimeMillis(); } } diff --git a/htroot/processing/domaingraph/domaingraph.pde b/htroot/processing/domaingraph/domaingraph.pde index 5c38a76d9..4805b93be 100755 --- a/htroot/processing/domaingraph/domaingraph.pde +++ b/htroot/processing/domaingraph/domaingraph.pde @@ -12,77 +12,124 @@ import traer.animation.*; import processing.net.*; final float NODE_SIZE = 6; -final float EDGE_LENGTH = 50; +final float EDGE_LENGTH = 30; final float EDGE_STRENGTH = 0.001; -final float SPACER_STRENGTH = 500; +final float SPACER_STRENGTH = 250; ParticleSystem physics; Smoother3D centroid; PFont font; +float x = 0.0; +float y = 0.0; +float z = 1.0; Client myClient; Particle center0, center1; // two gravity centers to support object ordering for non-quadratic fields String parsingHostName = ""; String parsingHostID = ""; HashMap nodes = new HashMap(); // map that holds host objects +String host; +int port; +float a = 0.0; +long lastUpdate = Long.MAX_VALUE; +boolean initTime = true; void setup() { String[] fontList = PFont.list(); //println(fontList); font = createFont(fontList[0], 32); //just take any, should be mostly Arial - textFont(font, 12); + textFont(font, 9); size(660, 400); smooth(); - frameRate( 24 ); - strokeWeight( 2 ); + frameRate( 12 ); + strokeWeight( 1 ); ellipseMode( CENTER ); physics = new ParticleSystem( 0, 0.25 ); centroid = new Smoother3D( 0.8 ); initializePhysics(); - initRequest(); + URL url = null; + try { + url = getDocumentBase(); + } catch (NullPointerException e) {} + if (url == null) { + host="localhost"; + port=8080; + } else { + host=url.getHost(); + port=url.getPort(); + } + //println("CodeBase: " + url); + //println("host: " + host); + //println("port: " + port); + + initRequest(false); } -void initRequest() { - myClient = new Client(this, "localhost", 8080); - myClient.write("GET /xml/webstructure.xml HTTP/1.1\n"); - myClient.write("Host: localhost\n\n"); +void initializePhysics() { + physics.clear(); + center0 = physics.makeParticle(1.0, -EDGE_LENGTH * 10, 0, 0); + center0.makeFixed(); + center1 = physics.makeParticle(1.0, EDGE_LENGTH * 10, 0, 0); + center1.makeFixed(); + centroid.setValue( 0, 0, 1.0 ); } -void processRequestResponse() { - if (myClient.available() > 0) { - String line = myClient.readStringUntil((byte) 10); - //println("Line: " + line); - if (line == null) line = ""; else line = line.trim(); - if (line.startsWith(" 1) updateCentroid(invisible); + centroid.tick(); + + background( 0 ); + translate( width/2 , height/2 ); + scale( centroid.z() ); + translate( -centroid.x(), -centroid.y() ); + + drawNetwork(invisible); } -HashMap parseProps(String s) { - String[] l = s.split(" "); - HashMap map = new HashMap(); - int p; - String z; - for (int i = 0; i < l.length; i++) { - p = l[i].indexOf("="); - if (p > 0) { - z = l[i].substring(p + 1).trim(); - if (z.charAt(0) == '"') z = z.substring(1); - if (z.charAt(z.length() - 1) == '"') z = z.substring(0, z.length() - 1); - map.put(l[i].substring(0, p), z); +void initRequest(boolean update) { + myClient = new Client(this, host, port); + myClient.write((update) ? "GET /xml/webstructure.xml?latest= HTTP/1.1\n" : "GET /xml/webstructure.xml HTTP/1.1\n"); + myClient.write("Host: localhost\n\n"); +} + +void processRequestResponse(int steps) { + if (((myClient == null) || (myClient.available() <= 0)) && (System.currentTimeMillis() - lastUpdate > 10000)) { + initRequest(true); + lastUpdate = Long.MAX_VALUE; + return; + } + for (int i = 0; i < steps; i++) { + if (myClient.available() > 0) { + String line = myClient.readStringUntil((byte) 10); + //println("Line: " + line); + if (line == null) line = ""; else line = line.trim(); + if (line.startsWith(" TWO_PI) a -= TWO_PI; nodes.put(parsingHostID, h); addAttraction(h.node); } @@ -97,72 +144,116 @@ void processCitation(HashMap props) { } catch (NumberFormatException e) {} // find the two nodes that have a relation host h = (host) nodes.get(id); - if (h == null) return; // host is not known TODO: store these and create relation later + if (h == null) { + return; /* + h = new host(host, physics.makeParticle(1.0, EDGE_LENGTH * 20 * cos(a), -EDGE_LENGTH * 10 * sin(a), 0)); + a += TWO_PI/256.0 + TWO_PI / 2; if (a > TWO_PI) a -= TWO_PI; + nodes.put(id, h); + addAttraction(h.node);*/ + } + h.time = System.currentTimeMillis(); host p = (host) nodes.get(parsingHostID); // this should be successful - addRelation(h.node, p.node); + // prevent that a spring is made twice + for ( int i = 0; i < physics.numberOfSprings(); ++i ) { + Spring e = physics.getSpring(i); + Particle a = e.getOneEnd(); + Particle b = e.getTheOtherEnd(); + if (((a == h.node) && (b == p.node)) || ((b == h.node) && (a == p.node))) return; + } + physics.makeSpring(h.node, p.node, EDGE_STRENGTH, EDGE_STRENGTH, EDGE_LENGTH ); } -void draw() { - processRequestResponse(); - - physics.tick( 1.0 ); - if (physics.numberOfParticles() > 1) updateCentroid(); - centroid.tick(); +HashMap parseProps(String s) { + String[] l = s.split(" "); + HashMap map = new HashMap(); + int p; + String z; + for (int i = 0; i < l.length; i++) { + p = l[i].indexOf("="); + if (p > 0) { + z = l[i].substring(p + 1).trim(); + if (z.charAt(0) == '"') z = z.substring(1); + if (z.charAt(z.length() - 1) == '"') z = z.substring(0, z.length() - 1); + map.put(l[i].substring(0, p), z); + } + } + return map; +} - background( 0 ); - translate( width/2 , height/2 ); - scale( centroid.z() ); - translate( -centroid.x(), -centroid.y() ); - - drawNetwork(); +HashSet invisibleParticles() { + // get nodes that have no edges + HashSet particles = new HashSet(); + Iterator j = nodes.values().iterator(); + host h; + long t = 0, n = System.currentTimeMillis(); + while (j.hasNext()) { + h = (host) j.next(); + t += n - h.time; + particles.add(h.node); + } + t = t / (nodes.size() + 1); + for ( int i = 0; i < physics.numberOfSprings(); ++i ) { + Spring e = physics.getSpring(i); + particles.remove(e.getOneEnd()); + particles.remove(e.getTheOtherEnd()); + } + // add more nodes if the number is too large + if (nodes.size() > 80) { + j = nodes.values().iterator(); + while (j.hasNext()) { + h = (host) j.next(); + if (n - h.time > 15000) particles.add(h.node); + if (nodes.size() - particles.size() < 80) break; + } + } + return particles; } -void drawNetwork() { - fill( 100, 255, 100 ); +void drawNetwork(HashSet invisible) { // draw vertices + fill( 120, 255, 120 ); noStroke(); String name; - Iterator j = nodes.values().iterator(); host h; + Iterator j = nodes.values().iterator(); while (j.hasNext()) { h = (host) j.next(); Particle v = h.node; + if (invisible.contains(v)) continue; ellipse(v.position().x(), v.position().y(), NODE_SIZE, NODE_SIZE); name = h.name; text(name, v.position().x() - (name.length() * 26 / 10), v.position().y() + 14); } - + // draw center - /* - ellipse( center0.position().x(), center0.position().y(), NODE_SIZE * 2, NODE_SIZE * 2 ); - name = "Center0"; - text(name, center0.position().x() - (name.length() * 26 / 10), center0.position().y() + 14); - ellipse( center1.position().x(), center1.position().y(), NODE_SIZE * 2, NODE_SIZE * 2 ); - name = "Center1"; - text(name, center1.position().x() - (name.length() * 26 / 10), center1.position().y() + 14); - */ - + //fill( 255, 0, 0 ); + //ellipse( center0.position().x(), center0.position().y(), NODE_SIZE * 2, NODE_SIZE * 2 ); + //ellipse( center1.position().x(), center1.position().y(), NODE_SIZE * 2, NODE_SIZE * 2 ); + // draw edges - stroke( 160 ); - beginShape( LINES ); + stroke( 200 ); for ( int i = 0; i < physics.numberOfSprings(); ++i ) { Spring e = physics.getSpring( i ); Particle a = e.getOneEnd(); + if (invisible.contains(a)) continue; Particle b = e.getTheOtherEnd(); - vertex( a.position().x(), a.position().y() ); - vertex( b.position().x(), b.position().y() ); + if (invisible.contains(b)) continue; + line(a.position().x(), a.position().y(), b.position().x(), b.position().y()); } - endShape(); + } void keyPressed() { - if ( key == 'c' ) { - initializePhysics(); - return; - } - - if ( key == 'd' ) { + if ( key == 'c' ) initializePhysics(); + if ( key == 'a' ) x = Math.max(-1.0, x - 0.1); + if ( key == 'd' ) x = Math.min( 1.0, x + 0.1); + if ( key == 'w' ) y = Math.max(-1.0, y - 0.1); + if ( key == 's' ) y = Math.min( 1.0, y + 0.1); + if ( key == '-' ) z = Math.max( 1.0, z - 1.0); + if ( key == '+' ) z = Math.min(10.0, z + 1.0); + if ( key == '0' ) { x = 0.0; y = 0.0; z = 1.0; } + if ( key == 't' ) { HashSet hs = new HashSet(); for (int i = 0; i < physics.numberOfParticles(); ++i ) { hs.add(physics.getParticle(i)); @@ -177,49 +268,36 @@ void keyPressed() { } return; } - - if ( key == ' ' ) { - Particle p = physics.makeParticle(); - addRelation(p, physics.getParticle( (int) random( 0, physics.numberOfParticles()-1) )); - addAttraction(p); - return; - } } -void updateCentroid() { +void updateCentroid(HashSet invisible) { float xMax = Float.NEGATIVE_INFINITY, xMin = Float.POSITIVE_INFINITY, yMin = Float.POSITIVE_INFINITY, yMax = Float.NEGATIVE_INFINITY; - for ( int i = 0; i < physics.numberOfParticles(); ++i ) { - Particle p = physics.getParticle( i ); + for (int i = 0; i < physics.numberOfParticles(); ++i) { + Particle p = physics.getParticle(i); + if ((i >= 2) && ((p == center0) || (p == center1) || (invisible.contains(p)))) continue; xMax = max( xMax, p.position().x() ); xMin = min( xMin, p.position().x() ); yMin = min( yMin, p.position().y() ); yMax = max( yMax, p.position().y() ); } + float deltaX = xMax-xMin; float deltaY = yMax-yMin; - if ( deltaY > deltaX ) - centroid.setTarget( xMin + 0.5*deltaX, yMin +0.5*deltaY, height/(deltaY+50) ); - else - centroid.setTarget( xMin + 0.5*deltaX, yMin +0.5*deltaY, width/(deltaX+50) ); -} - -void initializePhysics() { - physics.clear(); - center0 = physics.makeParticle(1.0, 0, 0, 0); - center0.makeFixed(); - center1 = physics.makeParticle(1.0, EDGE_LENGTH * 30, 0, 0); - center1.makeFixed(); - centroid.setValue( 0, 0, 1.0 ); + centroid.setTarget( + xMin + (x + 1) * 0.5 * deltaX, + yMin + (y + 1) * 0.5 * deltaY, + z * ((deltaY > deltaX) ? height / (deltaY + 50) : width / (deltaX + 50)) + ); } void addAttraction(Particle p) { - physics.makeAttraction(center0, p, 5000.0, 3 * EDGE_LENGTH); - physics.makeAttraction(center1, p, 5000.0, 3 * EDGE_LENGTH); + physics.makeAttraction(center0, p, SPACER_STRENGTH * 10000.0, 100 * EDGE_LENGTH); + physics.makeAttraction(center1, p, SPACER_STRENGTH * 10000.0, 100 * EDGE_LENGTH); // spacers for ( int i = 0; i < physics.numberOfParticles(); ++i ) { @@ -228,16 +306,13 @@ void addAttraction(Particle p) { } } -void addRelation(Particle p, Particle other) { - physics.makeSpring( p, other, EDGE_STRENGTH, EDGE_STRENGTH, EDGE_LENGTH ); - //p.moveTo( q.position().x() + random( -1, 1 ), q.position().y() + random( -1, 1 ), 0 ); -} - static class host { String name; Particle node; + long time; public host(String name, Particle node) { this.name = name; this.node = node; + this.time = System.currentTimeMillis(); } } diff --git a/htroot/xml/webstructure.java b/htroot/xml/webstructure.java index 6d1f08994..4b5f339d3 100644 --- a/htroot/xml/webstructure.java +++ b/htroot/xml/webstructure.java @@ -41,7 +41,8 @@ public class webstructure { public static serverObjects respond(httpHeader header, serverObjects post, serverSwitch env) { serverObjects prop = new serverObjects(); plasmaSwitchboard sb = (plasmaSwitchboard) env; - Iterator i = sb.webStructure.structureEntryIterator(); + boolean latest = ((post == null) ? false : post.containsKey("latest")); + Iterator i = sb.webStructure.structureEntryIterator(latest); int c = 0, d; plasmaWebStructure.structureEntry sentry; Map.Entry refentry; @@ -71,6 +72,7 @@ public class webstructure { } prop.put("domains", c); prop.put("maxref", plasmaWebStructure.maxref); + if (latest) sb.webStructure.joinOldNew(); // return rewrite properties return prop; diff --git a/source/de/anomic/crawler/NoticeURLImporter.java b/source/de/anomic/crawler/NoticeURLImporter.java index 36356dc1b..de1c46881 100644 --- a/source/de/anomic/crawler/NoticeURLImporter.java +++ b/source/de/anomic/crawler/NoticeURLImporter.java @@ -21,7 +21,7 @@ public class NoticeURLImporter extends AbstractImporter implements Importer { private CrawlProfile activeCrawls; private ImporterManager dbImportManager; - public NoticeURLImporter(File crawlerPath, CrawlQueues crawlQueues, CrawlProfile activeCrawls, ImporterManager dbImportManager) throws ImporterException { + public NoticeURLImporter(File crawlerPath, CrawlQueues crawlQueues, CrawlProfile activeCrawls, ImporterManager dbImportManager) { super("NURL"); this.crawlQueues = crawlQueues; this.activeCrawls = activeCrawls; diff --git a/source/de/anomic/plasma/plasmaSwitchboardQueue.java b/source/de/anomic/plasma/plasmaSwitchboardQueue.java index a8e86bdbf..24168e631 100644 --- a/source/de/anomic/plasma/plasmaSwitchboardQueue.java +++ b/source/de/anomic/plasma/plasmaSwitchboardQueue.java @@ -392,7 +392,7 @@ public class plasmaSwitchboardQueue { } public String referrerHash() { - return referrerHash; + return (referrerHash == null) ? "" : referrerHash; } public String anchorName() { diff --git a/source/de/anomic/plasma/plasmaWebStructure.java b/source/de/anomic/plasma/plasmaWebStructure.java index 9916696ac..536facae6 100644 --- a/source/de/anomic/plasma/plasmaWebStructure.java +++ b/source/de/anomic/plasma/plasmaWebStructure.java @@ -54,7 +54,7 @@ public class plasmaWebStructure { private serverLog log; private File rankingPath, structureFile; private String crlFile, crgFile; - TreeMap structure; // ',' to {}* + TreeMap structure_old, structure_new; // ',' to {}* public plasmaWebStructure(serverLog log, File rankingPath, String crlFile, String crgFile, File structureFile) { this.log = log; @@ -62,27 +62,28 @@ public class plasmaWebStructure { this.crlFile = crlFile; this.crgFile = crgFile; this.crg = new StringBuffer(maxCRGDump); - this.structure = new TreeMap(); + this.structure_old = new TreeMap(); + this.structure_new = new TreeMap(); this.structureFile = structureFile; // load web structure Map loadedStructure = (this.structureFile.exists()) ? serverFileUtils.loadHashMap(this.structureFile) : new TreeMap(); - if (loadedStructure != null) this.structure.putAll(loadedStructure); + if (loadedStructure != null) this.structure_old.putAll(loadedStructure); - // delete outdated entries in case the structure is too big - if (this.structure.size() > maxhosts) { + // delete out-dated entries in case the structure is too big + if (this.structure_old.size() > maxhosts) { // fill a set with last-modified - dates of the structure TreeSet delset = new TreeSet(); String key, value; - for (Map.Entry entry : this.structure.entrySet()) { + for (Map.Entry entry : this.structure_old.entrySet()) { key = entry.getKey(); value = entry.getValue(); delset.add(value.substring(0, 8) + key); } - int delcount = this.structure.size() - (maxhosts * 9 / 10); + int delcount = this.structure_old.size() - (maxhosts * 9 / 10); Iterator j = delset.iterator(); while ((delcount > 0) && (j.hasNext())) { - this.structure.remove(j.next().substring(8)); + this.structure_old.remove(j.next().substring(8)); delcount--; } } @@ -216,46 +217,78 @@ public class plasmaWebStructure { public Map references(String domhash) { // returns a map with a domhash(String):refcount(Integer) relation assert domhash.length() == 6; - synchronized(structure) { - SortedMap tailMap = structure.tailMap(domhash); - if ((tailMap == null) || (tailMap.isEmpty())) return new HashMap(); - String key = tailMap.firstKey(); - if (key.startsWith(domhash)) { - return refstr2map(tailMap.get(key)); - } else { - return new HashMap(); + SortedMap tailMap; + Map h = new HashMap(); + synchronized (structure_old) { + tailMap = structure_old.tailMap(domhash); + if (!tailMap.isEmpty()) { + String key = tailMap.firstKey(); + if (key.startsWith(domhash)) { + h = refstr2map(tailMap.get(key)); + } + } + } + synchronized (structure_new) { + tailMap = structure_new.tailMap(domhash); + if (!tailMap.isEmpty()) { + String key = tailMap.firstKey(); + if (key.startsWith(domhash)) { + h.putAll(refstr2map(tailMap.get(key))); + } } } + return h; } public int referencesCount(String domhash) { // returns the number of domains that are referenced by this domhash assert domhash.length() == 6 : "domhash = " + domhash; - synchronized(structure) { - SortedMap tailMap = structure.tailMap(domhash); - if ((tailMap == null) || (tailMap.isEmpty())) return 0; - String key = tailMap.firstKey(); - if (key.startsWith(domhash)) { - return refstr2count(tailMap.get(key)); - } else { - return 0; + SortedMap tailMap; + int c = 0; + synchronized (structure_old) { + tailMap = structure_old.tailMap(domhash); + if (!tailMap.isEmpty()) { + String key = tailMap.firstKey(); + if (key.startsWith(domhash)) { + c = refstr2count(tailMap.get(key)); + } + } + } + synchronized (structure_new) { + tailMap = structure_new.tailMap(domhash); + if (!tailMap.isEmpty()) { + String key = tailMap.firstKey(); + if (key.startsWith(domhash)) { + c += refstr2count(tailMap.get(key)); + } } } + return c; } public String resolveDomHash2DomString(String domhash) { // returns the domain as string, null if unknown assert domhash.length() == 6; - synchronized(structure) { - SortedMap tailMap = structure.tailMap(domhash); - if ((tailMap == null) || (tailMap.isEmpty())) return null; - String key = tailMap.firstKey(); - if (key.startsWith(domhash)) { - return key.substring(7); - } else { - return null; + SortedMap tailMap; + synchronized(structure_old) { + tailMap = structure_old.tailMap(domhash); + if (!tailMap.isEmpty()) { + String key = tailMap.firstKey(); + if (key.startsWith(domhash)) { + return key.substring(7); + } } } + synchronized(structure_new) { + tailMap = structure_new.tailMap(domhash); + if (!tailMap.isEmpty()) { + String key = tailMap.firstKey(); + if (key.startsWith(domhash)) { + return key.substring(7); + } + } + } + return null; } private void learn(yacyURL url, StringBuffer reference /*string of b64(12digits)-hashes*/) { @@ -297,15 +330,42 @@ public class plasmaWebStructure { } // store the map back to the structure - synchronized(structure) { - structure.put(domhash + "," + url.getHost(), map2refstr(refs)); + synchronized(structure_new) { + structure_new.put(domhash + "," + url.getHost(), map2refstr(refs)); + } + } + + private static final void joinStructure(TreeMap into, TreeMap from) { + for (Map.Entry e: from.entrySet()) { + if (into.containsKey(e.getKey())) { + Map s0 = refstr2map(into.get(e.getKey())); + Map s1 = refstr2map(e.getValue()); + for (Map.Entry r: s1.entrySet()) { + if (s0.containsKey(r.getKey())) { + s0.put(r.getKey(), s0.get(r.getKey()).intValue() + r.getValue().intValue()); + } else { + s0.put(r.getKey(), r.getValue().intValue()); + } + } + into.put(e.getKey(), map2refstr(s0)); + } else { + into.put(e.getKey(), e.getValue()); + } + } + } + + public void joinOldNew() { + synchronized(structure_new) { + joinStructure(this.structure_old, this.structure_new); + this.structure_new.clear(); } } public void saveWebStructure() { + joinOldNew(); try { - synchronized(structure) { - serverFileUtils.saveMap(this.structureFile, this.structure, "Web Structure Syntax: ',' to {}*"); + synchronized(structure_old) { + serverFileUtils.saveMap(this.structureFile, this.structure_old, "Web Structure Syntax: ',' to {}*"); } } catch (IOException e) { e.printStackTrace(); @@ -316,8 +376,9 @@ public class plasmaWebStructure { // find domain with most references String maxhost = null; int refsize, maxref = 0; - synchronized(structure) { - for (Map.Entry entry : structure.entrySet()) { + joinOldNew(); + synchronized(structure_new) { + for (Map.Entry entry : structure_old.entrySet()) { refsize = entry.getValue().length(); if (refsize > maxref) { maxref = refsize; @@ -328,9 +389,9 @@ public class plasmaWebStructure { return maxhost; } - public Iterator structureEntryIterator() { + public Iterator structureEntryIterator(boolean latest) { // iterates objects of type structureEntry - return new structureIterator(); + return new structureIterator(latest); } public class structureIterator implements Iterator { @@ -338,8 +399,8 @@ public class plasmaWebStructure { private Iterator> i; private structureEntry nextentry; - public structureIterator() { - i = structure.entrySet().iterator(); + public structureIterator(boolean latest) { + i = ((latest) ? structure_new : structure_old).entrySet().iterator(); next0(); }