/** * Web Site Hits Count Graph Generator * @author Robert John Morton UK-YE572246C * @version 27 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 InputStream I; // input stream for downloading index or current HTML file URL url; // url of current HTML file int L = 0, // length of the remote item being loaded l = 0, // number of bytes of the above successfully downloaded w, // weeks counter used on horizontal axis of graph X = 30, // horizontal bias from left edge of applet to start of x-axis Y = 145, // vertical bias from top edge of applet to start of y-axis n = 25, // off-set from start mark of year to start of its name lp = 1, // indicates current and previous download phases LP = 1, weeks[] = {52,52,52,52,52,52,52}; // weeks per year String year[] = {"1998","1999","2000","2001","2002","2003","2004"}, hits[] = {"0","20","40","60","80","100","110"}, // hits scale cb; // code base URL - where this applet's class file came from byte B[]; // gigantic byte array to hold the downloaded index data Thread TH; // reference for a separate Internet Data Transfer thread String E; // for Exception during downloading + method where it occurred Color bg1 = new Color(210,210,210), // main background colour bg2 = new Color(210,195,195), // graph background colour bg3 = new Color(180,180,180); // graticule colour public void init() { bg1 = getBackground(); // Get HTML page's backround colour and setBackground(bg1); // set it as the applet's background colour. /* Get the details of the HTML document this applet is running in and its codebase: the URL (less file name) from where this applet came.*/ ac = getAppletContext(); cb = getCodeBase().toString(); if(!cb.endsWith("/")) { // Workaround re Hotjava re Microsoft int x = cb.lastIndexOf('/'); // intranet machine names where if(x != -1) // getCodeBase() wrongly returns cb = cb.substring(0,x + 1); // the document base (cira Nov 1999). } TH = new Thread(this); // a thread for downloading data from server } public void paint(Graphics g) { g.setColor(bg1); // Clear the panel and the graph area g.fillRect(0,0,450,170); // to respective background colours. g.setColor(bg2); g.fillRect(X,Y-120,364,120); w = 0; // total number of weeks for(int i = 0; i < weeks.length; i++) { // for each year shown g.setColor(Color.black); // set to paint in black g.drawString(year[i],X + 13 + w,Y + 20); // show year number g.drawLine(X + w,Y + 5,X + w,Y + 10); // and boundary mark g.setColor(bg3); // set appropriate colour g.drawLine(X + w,Y,X + w,Y - 120); // and show annotation mark w += weeks[i]; // accumulated number of weeks } g.setColor(bg3); // Show final annotation mark g.drawLine(X + w,Y,X + w,Y - 120); g.setColor(Color.black); // Display in black g.drawLine(X + w,Y + 5,X + w,Y + 10); // the final year boundary g.drawLine(X,Y + 5,X + w,Y + 5); // and the horizontal axis. int z = 0; for(int i = 0; i < hits.length; i++) { // for each 10-hit graduation rightString(g,hits[i],X - 10,Y + 5 - z); // annotation g.drawLine(X - 10,Y - z,X - 5,Y - z); // annotation mark g.setColor(bg3); // Show final annotation mark g.drawLine(X,Y - z,X + w,Y - z); z += 20; // accumulated number of hits g.setColor(Color.black); } g.drawLine(X - 5,Y,X - 5,Y - 120); //vertical axis g.drawString("Hits per week:",X - n,Y - 130); g.drawString("Year:",X - n,Y + 20); update(g); // paint/repaint the graph bars } public void update(Graphics g) { if(lp == 3) { //provided hit count data download completed w = X; //initial x-bias for week number int h = 0, //number of hits for a given week W = 0, //number of weeks for which there is valid data H = 0; //hits total accumulator g.setColor(Color.blue); //set trace colour to blue for(int i = 0; i < L; i++) { /* For every week covered by graph Provided the number of hits is not zero [to avoid displaying zero values before start date]: */ if((h = (int)B[i]) > 0) { g.drawLine(w,Y,w,Y - h); // display it as a vertical bar on chart, H += h; // 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); } } // Start execution of the Internet data transfer thread. public void start() { TH.start(); } // MANAGE THE INTERNET DATA TRANSFERS ON A SEPARATE THREAD public void run() { while(TH != null) { // while this thread exists switch(lp) { // THE 2 DOWNLOADING PHASES: case 1: fileConnect(); // connect to index resource on server break; case 2: fileLoad(); // 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 } /* Put the thread to sleep for 250 milliseconds. Catch any exceptions which may occur while the thread is asleep but take no action. */ try { TH.sleep(250); } catch (InterruptedException e) { } } } // Freeze execution of thread while away from host HTML page. public void stop() {TH = null;} /* Called after stop() before applet is removed from memory. If the Internet data transfer thread object still exists and jettison its object into limbo. */ public void destroy() { if(TH != null) { TH = null; } } void fileConnect() { // CONNECT TO THE HITS DATA FILE ON THE SERVER try { // for loading from a jar file I = getClass().getResourceAsStream("hc.dat"); L = 512; // cannot find the current file length easily l = 0; // number of bytes so far successfully downloaded B = new byte[L]; // create the gigantic buffer for the data lp = 2; // advance to the index loading phase } /* If an exception occurs while connecting, set unrecoverable error status and note the type of exception and where it occurred. */ catch(Exception e) { lp = 0; E = "fileConnect() " + e; } } void fileLoad() { // DOWNLOAD THE HITS DATA int k; //current byte being read() try { /* While read() hasn't hit current end of input stream and the entire file has not yet been downloaded: */ while((k = I.read()) != -1) B[l++] = (byte)k; // add its new byte to the big byte array I.close(); // close the URL Connection's input stream lp = 3; // indicate file loading completed successfully } /* If an exception occurs while loading, set unrecoverable error status and note the type of exception and where it occurred. */ catch(Exception e) { lp = 0; E = "fileLoad() " + e + L + " " + l; } } // DRAW A RIGHT-JUSTIFIED STRING void rightString(Graphics g, String s, int x, int y) { FontMetrics // get character dimensions fm = g.getFontMetrics(); // for current font g.drawString(s,x - fm.stringWidth(s),y); // display the string } }