import java.applet.*; import java.net.*; import java.io.*; import java.awt.*; import java.lang.*; import java.util.*; import java.text.*; public class WormWatchApplet extends Applet { static final int W = 380; static final int H = 620; int nquakes = 0, nlist = 0 ; // number actual quakes, number eq's listed static final int MAX_QUAKES = 800; // total number allowable quakes. String MapImageFile; // int oxpos=1, oypos=1, xpos=0, ypos=0; // mouse up down positions Image offScrImage; Graphics offscreen; Image mapImage; MediaTracker mytracker; // Track this image, wait until image loaded before redraw QuakeChecker quakechecker; Quake quakes[] = new Quake[MAX_QUAKES]; List mylist; Panel p; public void init() { setLayout( new BorderLayout() ); p = new Panel(); mylist = new List(9,true); p.add( mylist ); add( "South", p ); try { offScrImage = createImage(W, H); offscreen = offScrImage.getGraphics(); setBackground(Color.white); resize(W, H); } catch (Exception e) { offscreen = null; } mytracker = new MediaTracker(this); MapImageFile = getParameter("MapImageFile"); if( MapImageFile == null ) { MapImageFile = "topo3.gif"; } mapImage = getImage(getCodeBase(), MapImageFile); mytracker.addImage(mapImage,0); try { // mytracker.waitForID(0); mytracker.waitForAll(); } catch ( InterruptedException e ) { } } /* Start the threads for each part of the applet */ public void start() { nquakes = 0; try { quakechecker = new QuakeChecker(this); } catch (Exception e) { System.out.println("Failed in reading quakes"); return; } } public void addquake(Quake q) { quakes[nquakes++] = q; } /* when applet is stopped, stop individual threads */ public void stop() { } /* override the update method to reduce flashing */ public void update(Graphics g) { paint(g); } /* Use double buffering to reduce flashing */ public void paint(Graphics g) { if (offscreen != null) { paintApplet(offscreen); g.drawImage(offScrImage,0,0,this); } else { paintApplet(g); } } /* call each thing's paint method */ public void paintApplet(Graphics g) { boolean changed = false; /* clear text area */ g.setColor(Color.white); g.fillRect(0, 0, W, H); g.drawImage(mapImage,0,0,this); if ( nquakes == 0 ) { g.setFont(new Font("Helvetica",Font.BOLD,12)); g.setColor(Color.black); g.drawString("Error: Please Reload Page.", 1, 455); } for(int i=0; i < nquakes; i++) { if( quakes[i].IsThisMonth() ) quakes[i].PlotCircle(g); if( quakes[i].IsThisWeek() ) quakes[i].PlotSquare(g); if( quakes[i].IsToday() ) quakes[i].PlotSolidSquare(g); g.setFont(new Font("Helvetica",Font.BOLD,12)); g.setColor(Color.black); if( xpos < oxpos && ypos < oypos ) { g.drawString("Use mouse To pick corners on map to get listing", 1, 455); } else { g.drawString("OriginTime (UT) Lat, Lon Z=(km) Md [#phases] Location", 1, 455); g.setFont(new Font("Helvetica",Font.PLAIN,12)); if( quakes[i].InsideBox(oxpos,oypos,xpos,ypos) ) { if( quakes[i].MagGreater4() ) { g.setColor(Color.red); } mylist.addItem( quakes[i].list() ); nlist++; } /* draw a bounding box */ g.setColor(Color.white); g.drawLine( oxpos, oypos, oxpos+(xpos-oxpos), oypos ); g.drawLine( oxpos+(xpos-oxpos), oypos, oxpos+(xpos-oxpos), oypos+(ypos-oypos) ); g.drawLine( oxpos+(xpos-oxpos), oypos+(ypos-oypos), oxpos, oypos+(ypos-oypos) ); g.drawLine( oxpos, oypos+(ypos-oypos), oxpos, oypos); } } nlist = 0; } /* print a list of events */ public boolean mouseDown(Event e, int x, int y) { oxpos = x; oypos = y; if( mylist.countItems() > 0 ) mylist.clear(); // System.out.println("MouseDown oxpos=" + oxpos + " oypos=" + oypos); return(true); } public boolean mouseUp(Event e, int x, int y ) { Graphics g = getGraphics(); xpos = x; ypos = y; nlist=0; // System.out.println("MouseUp xpos=" + xpos + " ypos=" + ypos); paint(g); return(true); } // public boolean action(Event e, Object o) { // Dimension d = size(); // if( e.target.equals(big) ) // resize(d.width+10, d.height+50); // else if ( e.target.equals(small) ) // resize(d.width-10, d.height-50); // return true; // } } class Quake { int orid, nph; Location loc; double mag, depth; String comment; Date time; int splatrad; static int MagScale = 4; Quake(int a_orid, double a_lat, double a_lon, double a_depth, double a_mag, int a_ph, String a_comment, Date a_time ) { orid = a_orid; this.loc = new Location(a_lat,a_lon); depth = a_depth; mag = a_mag; nph = a_ph; comment = a_comment; time = a_time; } public void plotpoints(int x0, int y0, int x, int y, Graphics g) { g.drawLine(x0+x,y0+y,x0+x,y0+y); g.drawLine(x0+y,y0+x,x0+y,y0+x); g.drawLine(x0+y,y0-x,x0+y,y0-x); g.drawLine(x0+x,y0-y,x0+x,y0-y); g.drawLine(x0-x,y0-y,x0-x,y0-y); g.drawLine(x0-y,y0-x,x0-y,y0-x); g.drawLine(x0-y,y0+x,x0-y,y0+x); g.drawLine(x0-x,y0+y,x0-x,y0+y); } public void circle(int x0, int y0, int r, Graphics g) { int x,y; float d; x=0; y=r; d=5/4-r; plotpoints(x0,y0,x,y,g); while (y>x){ if (d<0) { d=d+2*x+3; x++; } else { d=d+2*(x-y)+5; x++; y--; } plotpoints(x0,y0,x,y,g); } } public void box(int x0, int y0, int r, Graphics g) { int x1,x2,y1,y2; x1 = x0 - r; x2 = x0 + r; y1 = y0 - r; y2 = y0 + r; g.drawLine(x1, y1, x2, y1); g.drawLine(x2, y1, x2, y2); g.drawLine(x2, y2, x1, y2); g.drawLine(x1, y2, x1, y1); } public void list(int dy, Graphics g) { SimpleDateFormat utcformatter = new SimpleDateFormat("yy MM dd HH:mm:ss "); SimpleTimeZone utc = new SimpleTimeZone(0 * 60 * 60 * 1000, "UTC"); utcformatter.setTimeZone(utc); g.setFont( new Font("Dialog", Font.PLAIN,10)); if( this.mag >= 4.0 ) g.setColor(Color.red); else g.setColor(Color.black); g.drawString(utcformatter.format(this.time) + this.depth + " M" + this.mag + " [" + nph + "]" + this.comment, 1, 470+(dy*12) ); } public String list() { String str; SimpleDateFormat utcformatter = new SimpleDateFormat("yyyy MMMM dd HH:mm:ss "); SimpleTimeZone utc = new SimpleTimeZone(0 * 60 * 60 * 1000, "UTC"); utcformatter.setTimeZone(utc); str = utcformatter.format(this.time) + this.loc.lat + "N " + -this.loc.lon + "W " + " Z=" + this.depth + " Md=" + this.mag + " [" + nph + "] " + this.comment; return(str); } public boolean MagGreater4() { if( this.mag >= 4.0 ) return(true); else return(false); } public boolean IsToday() { Date Otime = this.time; int yr, mo, da, hr, mn; SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, "PST"); pdt.setStartRule(3, 1, 1, 2*60*60*1000); pdt.setEndRule(9, -1, 1, 2*60*60*1000); GregorianCalendar current = new GregorianCalendar(pdt); yr = current.get(Calendar.YEAR)-1900; mo = current.get(Calendar.MONTH); da = current.get(Calendar.DAY_OF_MONTH); hr = current.get(Calendar.HOUR_OF_DAY); mn = current.get(Calendar.MINUTE); Date Time = new Date(yr, mo, da-1, hr, mn, 0); if( Otime.after(Time) ) return(true); else return(false); } public boolean IsThisMonth() { Date Otime = this.time; int yr, mo, da, hr, mn; SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, "PST"); pdt.setStartRule(3, 1, 1, 2*60*60*1000); pdt.setEndRule(9, -1, 1, 2*60*60*1000); GregorianCalendar current = new GregorianCalendar(pdt); yr = current.get(Calendar.YEAR)-1900; mo = current.get(Calendar.MONTH); da = current.get(Calendar.DAY_OF_MONTH); hr = current.get(Calendar.HOUR_OF_DAY); mn = current.get(Calendar.MINUTE); Date Time1 = new Date(yr, mo-1, da, hr, mn, 0); Date Time2 = new Date(yr, mo, da-7, hr, mn, 0); if( Otime.before(Time2) && Otime.after(Time1) ) return(true); else return(false); } public boolean IsThisWeek() { Date Otime = this.time; int yr, mo, da, hr, mn; SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, "PST"); pdt.setStartRule(3, 1, 1, 2*60*60*1000); pdt.setEndRule(9, -1, 1, 2*60*60*1000); GregorianCalendar current = new GregorianCalendar(pdt); yr = current.get(Calendar.YEAR)-1900; mo = current.get(Calendar.MONTH); da = current.get(Calendar.DAY_OF_MONTH); hr = current.get(Calendar.HOUR_OF_DAY); mn = current.get(Calendar.MINUTE); Date Time1 = new Date(yr, mo, da-7, hr, mn, 0); Date Time2 = new Date(yr, mo, da, hr-24, mn, 0); if( Otime.before(Time2) && Otime.after(Time1) ) return(true); else return(false); } public void PlotSquare(Graphics g) { PixelCoord pc; pc = this.loc.pix(); g.setColor(Color.yellow); splatrad = MagScale * (int)mag - 4; if( splatrad == 0 ) splatrad = 1; box(pc.x, pc.y, splatrad, g); } public void PlotSolidSquare(Graphics g) { PixelCoord pc; pc = this.loc.pix(); g.setColor(Color.black); splatrad = MagScale * (int)mag - 4; if( splatrad == 0 ) splatrad = 1; box(pc.x, pc.y, splatrad, g); for( int i=splatrad-1; i>=0; i-=1) { g.setColor(Color.red); box(pc.x, pc.y, i, g); } } public void PlotCircle(Graphics g) { PixelCoord pc; pc = this.loc.pix(); g.setColor(Color.cyan); splatrad = MagScale * (int)mag - 4; if( splatrad == 0 ) splatrad = 1;; circle(pc.x,pc.y,splatrad,g); } public boolean InsideBox(int ulx, int uly , int lrx, int lry) { int ulxdist, ulydist, lrxdist, lrydist, uldist, lrdist; PixelCoord pc; pc = this.loc.pix(); ulxdist = pc.x - ulx; ulydist = pc.y - uly; lrxdist = lrx - pc.x; lrydist = lry - pc.y; if( ulxdist > 0 && ulydist > 0 && lrxdist > 0 && lrydist > 0 ) { return(true); } else { return(false); } } } class PixelCoord { int x, y; PixelCoord(int a_x,int a_y) { x = a_x; y = a_y; } } class Location { double lat, lon; static int MapXCtr = 203; static int MapYCtr = 217; static int PixPerLatDeg = 68; static int PixPerLonDeg = 54; static double MapLatCtr = 38.0; static double MapLonCtr = -119.0; Location(double a_lat, double a_lon) { lat = a_lat; lon = a_lon; }; public PixelCoord latlon2pix(Location loc) { int x,y; double lat,lon,xdist,ydist,dist,az,pixdist; lat = loc.lat; lon = loc.lon; ydist = PixPerLatDeg * ( lat - MapLatCtr ); xdist = PixPerLonDeg * ( lon - MapLonCtr ); az = Math.atan(ydist/xdist); if(xdist<0.) az += Math.PI; dist = (xdist*xdist) + (ydist*ydist); pixdist = Math.sqrt(dist); x = (int) (MapXCtr + pixdist*Math.cos(az)); y = (int) (MapYCtr - pixdist*Math.sin(az)); return new PixelCoord(x,y); } PixelCoord pix() { return latlon2pix(this); } } class QuakeChecker { double lat = 0, lon = 0, depth = 0, ml = 0; int orid = 0, ndef = 0; int year = 0, month = 0, day = 0, hourmin = 0; int hour=0, min=0, second = 0; Date time; String comment; Quake q; URL u; InputStream is; StreamTokenizer st; WormWatchApplet applet; public QuakeChecker(WormWatchApplet applet) throws java.io.IOException { this.applet = applet; try { u = new URL("http://134.197.33.40/ftp/pub/ichinose/JavaWorm/nbe.html"); } catch ( MalformedURLException e ) { System.out.println("MalformedURLException"); } is = u.openStream(); st = new StreamTokenizer(is); st.eolIsSignificant(true); st.commentChar('#'); st.quoteChar('"'); st.nextToken(); while(st.ttype != StreamTokenizer.TT_EOF) { orid++; year = (int) st.nval ; st.nextToken(); month = (int) st.nval - 1; st.nextToken(); day = (int) st.nval; st.nextToken(); hourmin = (int) st.nval; hour = (int) Math.floor((double)hourmin/100.0) ; min = hourmin - hour*100; st.nextToken(); second = (int) st.nval; st.nextToken(); lat = st.nval; st.nextToken(); lon = st.nval; st.nextToken(); depth = st.nval; st.nextToken(); ml = st.nval; st.nextToken(); ndef = (int) st.nval; st.nextToken(); comment = st.sval; st.nextToken(); st.nextToken(); // get a calendar with current Pacific Standard // zone and daylight savings hour offset // SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, "PST"); pdt.setStartRule(3, 1, 1, 2*60*60*1000); pdt.setEndRule(9, -1, 1, 2*60*60*1000); GregorianCalendar current = new GregorianCalendar(pdt); int zone = current.get(Calendar.ZONE_OFFSET)/(60*60*1000); int dst = current.get(Calendar.DST_OFFSET)/(60*60*1000); // now convert GMT time to PDT time // Date time = new Date( year - 1900, month, day, hour+zone+dst, min, second ); q = new Quake(orid,lat,lon,depth,ml,ndef,comment,time); applet.addquake(q); } } }