/**
* Web Site Hits Count Graph Generator
* @author Robert J Morton <robmorton@clara.net>
* @version 26 April 2000 */
import java.applet.*; //all the gubbins to make the applet work
import java.awt.*; //for graphics operations (GUI)
import java.net.*; //for downloading data from the remote server
import java.io.*; //for stream handling for the above
public class hc extends Applet implements Runnable {
AppletContext ac; //get details of HTML document this applet is running in
String cb; //code base URL - where this applet's class file came from
URL url; //url of current HTML file
InputStream I; //input stream for downloading index or current HTML file
int L = 0; //length of the remote item being loaded
int l = 0; //number of bytes of the above successfully downloaded
byte B[]; //gigantic byte array to hold the downloaded index data
int w; //weeks counter used on horizontal axis of graph
Thread TH; //reference for a separate Internet Data Transfer thread
int lp = 1, LP = 1; //indicates current and previous download phases
String E; //for Exception during downloading + method where it occurred
int X = 30; //horizontal bias from left edge of applet to start of x-axis
int Y = 125; //vertical bias from top edge of applet to start of y-axis
int n = 25; //off-set from start mark of year to start of its name eg 1999
Color bg1 = new Color(210, 210, 210); //main background colour
Color bg2 = new Color(208, 176, 176); //graph background colour ideally with a 24-bit system
Color bg3 = new Color(128, 128, 128); //graticule colour
String year[] = {"1998", "1999", "2000", "2001", "2002", "2003", "2004"}; //year name
int weeks[] = { 52, 52, 52, 52, 52, 52, 52 }; //weeks in year
String hits[] = {"00", "10", "20", "30", "40", "50"}; //hits scale
public void init() {
bg1 = getBackground();
setBackground(bg1);
ac = getAppletContext(); //get details of HTML document this applet is running in
cb = getCodeBase().toString(); //URL (less file name) from where this applet came
if(!cb.endsWith("/")) { //workaround re Hotjava re Microsoft intranet machine names
int x = cb.lastIndexOf('/'); //where getCodeBase() wrongly seems to return the
if(x != -1) cb = cb.substring(0, x + 1); //document base (cira Nov 1999)
}
TH = new Thread(this); //create a thread for downloading data from server
setBackground(bg1); //set the applet's background colour
}
public void paint(Graphics g) {
g.setColor(bg1); g.fillRect(0, 0, 450, 150); //clear the graph panel
g.setColor(bg2); g.fillRect(X, Y-100, 364, 100); //clear the graph area
g.setColor(Color.black);
w = 0;
for(int i = 0; i < weeks.length; i++) { //for each year shown
g.drawString(year[i], X + 13 + w, Y + 20); //year number
g.drawLine(X + w, Y + 5, X + w, Y + 10); //year boundary mark
g.setColor(bg3);
g.drawLine(X + w, Y, X + w, Y - 100); //annotation mark
w += weeks[i]; //accumulated number of weeks
g.setColor(Color.black);
}
g.setColor(bg3);
g.drawLine(X + w, Y, X + w, Y - 100); //annotation mark
g.setColor(Color.black);
g.drawLine(X + w, Y + 5, X + w, Y + 10); //final year boundary mark
g.drawLine(X, Y + 5, X + w, Y + 5); //horizontal axis
int z = 0;
for(int i = 0; i < hits.length; i++) { //for each 10-hit graduation
g.drawString(hits[i], X - n, Y + 5 - z); //annotation
g.drawLine(X - 10, Y - z, X - 5, Y - z); //annotation mark
g.setColor(bg3);
g.drawLine(X, Y - z, X + w, Y - z); //annotation mark
z += 20; //accumulated number of hits
g.setColor(Color.black);
}
g.drawLine(X - 5, Y, X - 5, Y - 100); //vertical axis
g.drawString("Hits per week:", X - n, Y - 110);
g.drawString("Year:", X - n, Y + 20);
update(g); //paint/repaint the graph bars
}
public void update(Graphics g) {
g.setColor(Color.blue); //set trace colour to blue
if(lp == 3) { //provided hit count data download completed
int h = 0; //number of hits for a given week
w = X; //initial x-bias for week number
int W = 0; //number of weeks for which there is valid data
int H = 0; //hits total accumulator
for(int i = 0; i < L; i++) {
if((h = (int)B[i]) > 0) { //aviod displaying zero values before start date
g.drawLine(w, Y, w, Y - (h << 1)); //display it as a vertical bar on the chart
H += h; //add this week's hits to the total
W++; //increment the number of weeks for which there is valid data
}
w++; //increment the week number
}
g.setColor(Color.black);
g.drawString("Total to Date " + H, 105, 15);
g.drawString("Weekly Average " + (H / W)), 230, 15);
}
}
public void start() { TH.start(); } //resume execution of Internet data transfer thread
public void run() { //MANAGE INTERNET DATA TRANSFERS ON A SEPARATE THREAD
while(TH.isAlive()) { //while this thread exists
switch(lp) { //THE 2 DOWNLOADING PHASES
case 1: fileConnect(); break; //connect to index resource on server
case 2: fileLoad(); break; //manage the downloading of its content
}
if(lp != LP) { //if loading of hits data has finished
LP = lp; //latch the current load state
repaint(); //display the bars
}
try {
Thread.currentThread().sleep(250); //sleep to allow other things to take place
} catch (InterruptedException e) {} //catch interrupt from GUI or browser
}
}
public void stop() { TH.stop(); } //freeze execution of thread while away from host HTML page
public void destroy() { //called after stop() before applet is removed from memory
if(TH != null) { //if the Internet data transfer thread object still exists
TH.stop(); //stop it running
TH = null; //and jettison its object into limbo
}
}
void fileConnect() { //CONNECT TO THE HITS DATA FILE ON THE SERVER
try {
url = new URL(cb + "hc.dat"); //form the url of the hits data file
URLConnection u = url.openConnection(); //open a connection to the remote file
L = u.getContentLength(); //length of the remote file (bytes)
l = 0; //number of bytes so far successfully downloaded
I = u.getInputStream(); //create an input stream object to access the file
B = new byte[L]; //create the gigantic buffer for the data
lp = 2; //advance to the index loading phase
} catch(Exception e) {
lp = 0; //set unrecoverable error status
E = "fileConnect() " + e; //note the exception and where it occurred
}
}
void fileLoad() { //DOWNLOAD THE HITS DATA
int k; //current byte being read()
try { //if read() hasn't hit the current end of input stream
while(l < L && (k = I.read()) != -1) //and the entire file has not yet been downloaded
B[l++] = (byte)k; //add its new byte to the array big byte array
if(l >= L) { //if the whole of the index has now been downloaded
I.close(); //close the URL Connection's input stream
lp = 3; //indicate file loading completed successfully
}
} catch(Exception e) {
lp = 0; //set error condition
E = "fileLoad() " + e + L + " " + l; //note the exception and where it occurred
}
}
}
/* Robert J Morton, the author of this program,
is a poor but Right Honourable Fellow of the
Ancient and Noble Order of the Long-term Unemployed.
Offers of work please to: robmorton@clara.net */