// This program provides daily and monthly climate reports from several West Virginia // stations by accessing data files and providing reports based on parameters selected // by the user. // // by Chris Leonardi - last changed 10/30/01 to change snow label to "24 hour snowfall // ending at 7 AM" // import java.awt.*; import java.awt.event.*; import java.applet.*; import java.util.*; import java.io.*; import java.net.*; public class Climomat extends Applet { Graphics g; // // Variables for the various pieces of climate data. They are stored in strings // in order to make them easier to manipulate. Variable names should be rather // self-explanatory. // String date = " "; String dayMax = " "; String dayMin = " "; String dayMean = " "; String dayDep = " "; String dayPrecip = " "; String monthPrecip = " "; String yearPrecip = " "; String dayHdd = " "; String monthHdd = " "; String seasonHdd = " "; String dayCdd = " "; String monthCdd = " "; String seasonCdd = " "; String dayNormMax = " "; String dayNormMin = " "; String dayNormMean = " "; String dayRecHigh = " "; String dayRecHighYr = " "; String dayRecLow = " "; String dayRecLowYr = " "; String daySunUp = " "; String daySunDown = " "; String daySnowfall = " "; String monthSnowfall = " "; String seasonSnowfall = " "; String daySnowDepth = " "; String dateAgain = " "; String dayNormPrecip = " "; String monthNormPrecip = " "; String yearNormPrecip = " "; String dayNormHdd = " "; String monthNormHdd = " "; String seasonNormHdd = " "; String dayNormCdd = " "; String monthNormCdd = " "; String seasonNormCdd = " "; String monthNormMax = " "; String monthNormMin = " "; String monthNormMean = " "; String monthAvgMax = " "; String monthAvgMin = " "; String monthAvgMean = " "; String junk = " "; String monthDepMax = " "; String monthDepMin = " "; String monthDepMean = " "; String monthDepPrecip = " "; String yearDepPrecip = " "; String monthDepHdd = " "; String seasonDepHdd = " "; String monthDepCdd = " "; String seasonDepCdd = " "; // // Variables used for user-file date comparison. // String s = " "; String test = " "; int index = 1; // // Variables used for drop down lists and resulting selections from them. // String StationChoice = " "; String MonthChoice = " "; String YearChoice = " "; String TypeChoice = " "; Choice Station, Type, Month, Day, Year; // // Variables used in opening the climate data file for the selected station and // month. // RandomAccessFile f; String stationfrag; String monthfrag; String yearfrag; String filename; // // Boolean variables used in exception handling. // boolean dateflag = false; boolean fileflag = false; // // *** START OF INIT() METHOD*** // public void init () { // // Set up applet user interface with drop-down lists and an action button. // Panel p = new Panel(); setLayout(new BorderLayout()); Station = new Choice(); Station.addItem("Charleston"); Station.addItem("Beckley"); Station.addItem("Elkins"); Station.addItem("Huntington"); p.add(Station); Type = new Choice(); Type.addItem("Daily Report"); Type.addItem("Monthly Summary"); p.add(Type); Month = new Choice(); Month.addItem("January"); Month.addItem("February"); Month.addItem("March"); Month.addItem("April"); Month.addItem("May"); Month.addItem("June"); Month.addItem("July"); Month.addItem("August"); Month.addItem("September"); Month.addItem("October"); Month.addItem("November"); Month.addItem("December"); p.add(Month); Day = new Choice(); Day.addItem("1"); Day.addItem("2"); Day.addItem("3"); Day.addItem("4"); Day.addItem("5"); Day.addItem("6"); Day.addItem("7"); Day.addItem("8"); Day.addItem("9"); Day.addItem("10"); Day.addItem("11"); Day.addItem("12"); Day.addItem("13"); Day.addItem("14"); Day.addItem("15"); Day.addItem("16"); Day.addItem("17"); Day.addItem("18"); Day.addItem("19"); Day.addItem("20"); Day.addItem("21"); Day.addItem("22"); Day.addItem("23"); Day.addItem("24"); Day.addItem("25"); Day.addItem("26"); Day.addItem("27"); Day.addItem("28"); Day.addItem("29"); Day.addItem("30"); Day.addItem("31"); p.add(Day); Year = new Choice(); Year.addItem("1990"); Year.addItem("1991"); Year.addItem("1992"); Year.addItem("1993"); Year.addItem("1994"); Year.addItem("1995"); Year.addItem("1996"); Year.addItem("1997"); Year.addItem("1998"); Year.addItem("1999"); Year.addItem("2000"); Year.addItem("2001"); p.add(Year); Button GetIt = new Button("Get the data!"); p.add(GetIt); GetIt.addActionListener(new GetTheData()); add(p, BorderLayout.NORTH); } // // ***END OF INIT() METHOD*** // // // ***START OF GETTHEDATA CLASS*** // // // Start of class that collects the data once the user clicks the // "Get the data!" button. // public class GetTheData implements ActionListener { public void actionPerformed(ActionEvent evt) { // // Get the Station, Month, and Year selections made by the user, and assign // symbolic "fragments" to each choice. These fragments are then assembled // into the appropriate filename for input. // try { dateflag = false; fileflag = false; StationChoice = Station.getSelectedItem(); MonthChoice = Month.getSelectedItem(); YearChoice = Year.getSelectedItem(); if (StationChoice.equals("Charleston")) stationfrag = filename = "crw"; if (StationChoice.equals("Beckley")) stationfrag = filename = "bkw"; if (StationChoice.equals("Huntington")) stationfrag = filename = "hts"; if (StationChoice.equals("Elkins")) stationfrag = filename = "ekn"; if (MonthChoice.equals("January")) monthfrag = "jan"; if (MonthChoice.equals("February")) monthfrag = "feb"; if (MonthChoice.equals("March")) monthfrag = "mar"; if (MonthChoice.equals("April")) monthfrag = "apr"; if (MonthChoice.equals("May")) monthfrag = "may"; if (MonthChoice.equals("June")) monthfrag = "jun"; if (MonthChoice.equals("July")) monthfrag = "jul"; if (MonthChoice.equals("August")) monthfrag = "aug"; if (MonthChoice.equals("September")) monthfrag = "sep"; if (MonthChoice.equals("October")) monthfrag = "oct"; if (MonthChoice.equals("November")) monthfrag = "nov"; if (MonthChoice.equals("December")) monthfrag = "dec"; if (YearChoice.equals("1990")) yearfrag = "90"; if (YearChoice.equals("1991")) yearfrag = "91"; if (YearChoice.equals("1992")) yearfrag = "92"; if (YearChoice.equals("1993")) yearfrag = "93"; if (YearChoice.equals("1994")) yearfrag = "94"; if (YearChoice.equals("1995")) yearfrag = "95"; if (YearChoice.equals("1996")) yearfrag = "96"; if (YearChoice.equals("1997")) yearfrag = "97"; if (YearChoice.equals("1998")) yearfrag = "98"; if (YearChoice.equals("1999")) yearfrag = "99"; if (YearChoice.equals("2000")) yearfrag = "00"; if (YearChoice.equals("2001")) yearfrag = "01"; filename = filename + monthfrag + yearfrag; // // "index" is a boolean variable that is set to 1 initially. It is set to 0 later // when the correct date line requested by the user is found in the input file. // index = 1; while (index != 0) { // // Open the correct file using the filename created above. The program opens an // InputStream from a URL which corresponds to the remote file containing the needed // month's data. A BufferedReader is used in order to read in the data from the file // one line at a time. // URL url = new URL("http://205.156.54.206/er/rlx/climate/" + filename + ".txt"); InputStreamReader stream = new InputStreamReader(url.openStream()); BufferedReader br = new BufferedReader(stream); while ((s = br.readLine()) != null) { // // Each read-in line is broken up into "tokens" in order to ease the process of // reading in each bit of data. The input files are tab-delimited, so the program // can see the break between each token. If there is at least one token in the line, // the program continues. StringTokenizer st = new StringTokenizer(s); int tokens = st.countTokens(); if (tokens != 0) { // // If a Monthly Summary is requested, determine the last day of the requested // month so that certain variables (e.g. monthPrecip, monthHdd) can be used in // the report. The value is stored in "test" in order to compare to the first // "token" of the input line. Even includes a test for leap year 2000! // TypeChoice = Type.getSelectedItem(); if (TypeChoice.equals("Monthly Summary")) { if (monthfrag == "jan" || monthfrag == "mar" || monthfrag == "may" || monthfrag == "jul" || monthfrag == "aug" || monthfrag == "oct" || monthfrag == "dec") test = "31"; if (monthfrag == "apr" || monthfrag == "jun" || monthfrag == "sep" || monthfrag == "nov") test = "30"; if (monthfrag == "feb" && yearfrag == "00") test = "29"; if (monthfrag == "feb" && yearfrag != "00") test = "28"; } // // If a Daily Report is selected, get the user's requested date from the drop // down list. // if (TypeChoice.equals("Daily Report")) test = Day.getSelectedItem(); // // Read the first "token" of the current line. If that token matches the currently // requested date (or the last day of the month if a Monthly Summary), we know // that this is the correct line in the data file. The program then progressively // reads tokens and inputs the values into the appropriate variables. // date = st.nextToken(); index = date.compareTo(test); if (index == 0) { dayMax = st.nextToken(); dayMin = st.nextToken(); dayMean = st.nextToken(); dayDep = st.nextToken(); dayPrecip = st.nextToken(); monthPrecip = st.nextToken(); yearPrecip = st.nextToken(); dayHdd = st.nextToken(); monthHdd = st.nextToken(); seasonHdd = st.nextToken(); dayCdd = st.nextToken(); monthCdd = st.nextToken(); seasonCdd = st.nextToken(); dayNormMax = st.nextToken(); dayNormMin = st.nextToken(); dayNormMean = st.nextToken(); dayRecHigh = st.nextToken(); dayRecHighYr = st.nextToken(); dayRecLow = st.nextToken(); dayRecLowYr = st.nextToken(); daySunUp = st.nextToken(); daySunDown = st.nextToken(); daySnowfall = st.nextToken(); monthSnowfall = st.nextToken(); seasonSnowfall = st.nextToken(); daySnowDepth = st.nextToken(); dateAgain = st.nextToken(); dayNormPrecip = st.nextToken(); monthNormPrecip = st.nextToken(); yearNormPrecip = st.nextToken(); dayNormHdd = st.nextToken(); monthNormHdd = st.nextToken(); seasonNormHdd = st.nextToken(); dayNormCdd = st.nextToken(); monthNormCdd = st.nextToken(); seasonNormCdd = st.nextToken(); // // If a Monthly Summary is requested, continue reading lines from the last day of // the month until a line with at least 3 tokens is read. The next line with 3 tokens // will always be the line containing the normal max, min, and mean for the month. // When this line is found, read the data into appropriate variables, and then read // and process the last 2 lines of the input file. // if (TypeChoice.equals("Monthly Summary")) { s=br.readLine(); st = new StringTokenizer(s); tokens = st.countTokens(); while (tokens < 3) { s=br.readLine(); st = new StringTokenizer(s); tokens = st.countTokens(); } monthNormMax = st.nextToken(); monthNormMin = st.nextToken(); monthNormMean = st.nextToken(); s = br.readLine(); s = br.readLine(); st = new StringTokenizer(s); junk = st.nextToken(); monthAvgMax = st.nextToken(); monthAvgMin = st.nextToken(); monthAvgMean = st.nextToken(); s = br.readLine(); st = new StringTokenizer(s); junk = st.nextToken(); monthDepMax = st.nextToken(); monthDepMin = st.nextToken(); monthDepMean = st.nextToken(); junk = st.nextToken(); monthDepPrecip = st.nextToken(); yearDepPrecip = st.nextToken(); junk = st.nextToken(); monthDepHdd = st.nextToken(); seasonDepHdd = st.nextToken(); junk = st.nextToken(); monthDepCdd = st.nextToken(); seasonDepCdd = st.nextToken(); } // // Request a repaint, which will call the paint() method and display the // data. Then, break out of the loop as the correct data has been found. // repaint(); break; } } } } // // ***END OF GETTHEDATA CLASS*** // // // Exception handling which handles cases of bad dates (e.g. November 31) // or input files which do not exist. Flags are also set to be used when // writing to the applet window. If a Monthly Report is requested for the // current month, the program will report a bad date. // } catch (NoSuchElementException e) { dateflag = true; repaint(); } catch (IOException e) { fileflag = true; repaint(); } } } // // ***START OF PAINT() METHOD*** // // // Start of paint() method, which draws the pertinent information in the applet // window, or notifies the user of an error condition, based on the flags set above. // public void paint(Graphics g) { if (dateflag) g.drawString("You have selected an invalid date. Please try again.", 50, 200); else if (fileflag) g.drawString("Data is not available for the month and/or station selected. Please try again.", 50, 200); // // This "else" clause takes the read-in data and displays it appropriately in the // applet window. The data displayed depends on whether the user requested a "Daily // Report" or a "Monthly Summary," handled in two if statements. // else { if (TypeChoice.equals("Daily Report")) { g.drawString("Daily Report for " + StationChoice + " for " + MonthChoice + " " + date + ", " + YearChoice, 50, 50); g.drawString("TEMPERATURE DATA (degrees F)", 50, 80); g.drawString("Max for day: " + dayMax, 50, 100); g.drawString("Min for day: " + dayMin, 50, 120); g.drawString("Average for day: " + dayMean, 50, 140); g.drawString("Normal Max: " + dayNormMax, 210, 100); g.drawString("Normal Min: " + dayNormMin, 210, 120); g.drawString("Normal Average: " + dayNormMean, 210, 140); g.drawString("Record High: " + dayRecHigh + " , " + dayRecHighYr, 350, 100); g.drawString("Record Low: " + dayRecLow + " , " + dayRecLowYr, 350, 120); g.drawString("DEGREE DAY DATA", 50, 180); g.drawString("Heating degree days: " + dayHdd, 50, 200); g.drawString("Total for month to date: " + monthHdd, 50, 220); g.drawString("Total for season (Jul-Jun): " + seasonHdd, 50, 240); g.drawString("Normal HDD for day: " + dayNormHdd, 250, 200); g.drawString("Normal HDD for month to date: " + monthNormHdd, 250, 220); g.drawString("Normal HDD for season to date: " + seasonNormHdd, 250, 240); g.drawString("Cooling degree days: " + dayCdd, 50, 270); g.drawString("Total for month to date: " + monthCdd, 50, 290); g.drawString("Total for season (Jan-Dec): " + seasonCdd, 50, 310); g.drawString("Normal CDD for day: " + dayNormCdd, 250, 270); g.drawString("Normal CDD for month to date: " + monthNormCdd, 250, 290); g.drawString("Normal CDD for season to date: " + seasonNormCdd, 250, 310); g.drawString("PRECIPITATION DATA (inches)", 50, 350); g.drawString("Liquid equivalent: " + dayPrecip, 50, 370); g.drawString("Total for month: " + monthPrecip, 50, 390); g.drawString("Total for year: " + yearPrecip, 50, 410); g.drawString("Normal for day: " + dayNormPrecip, 250, 370); g.drawString("Normal for month to date: " + monthNormPrecip, 250, 390); g.drawString("Normal for year to date: " + yearNormPrecip, 250, 410); g.drawString("24 hour Snowfall ending 7 AM: " + daySnowfall, 50, 440); g.drawString("Total for month: " + monthSnowfall, 230, 440); g.drawString("Total for season: " + seasonSnowfall, 380, 440); g.drawString("7 AM snow depth: " + daySnowDepth, 50, 460); g.drawString("Sunrise: " + daySunUp + " AM", 100, 500); g.drawString("Sunset: " + daySunDown + " PM", 300, 500); } if (TypeChoice.equals("Monthly Summary")) { g.drawString("Monthly Summary for " + StationChoice + " for " + MonthChoice + ", " + YearChoice, 50, 50); g.drawString("TEMPERATURE DATA (degrees F)", 50, 80); g.drawString("Average max: " + monthAvgMax, 50, 100); g.drawString("Average min: " + monthAvgMin, 50, 120); g.drawString("Monthly mean temp: " + monthAvgMean, 50, 140); g.drawString("Normal average max: " + monthNormMax, 210, 100); g.drawString("Normal average min: " + monthNormMin, 210, 120); g.drawString("Normal monthly mean: " + monthNormMean, 210, 140); g.drawString("Departure of max: " + monthDepMax, 380, 100); g.drawString("Departure of min: " + monthDepMin, 380, 120); g.drawString("Departure of mean: " + monthDepMean, 380, 140); g.drawString("DEGREE DAY DATA", 50, 180); g.drawString("HDD for month: " + monthHdd, 50, 200); g.drawString("HDD for season: " + seasonHdd, 50, 220); g.drawString("Normal for month: " + monthNormHdd, 190, 200); g.drawString("Normal for season: " + seasonNormHdd, 190, 220); g.drawString("Departure for month: " + monthDepHdd, 350, 200); g.drawString("Departure for season: " + seasonDepHdd, 350, 220); g.drawString("CDD for month: " + monthCdd, 50, 250); g.drawString("CDD for season: " + seasonCdd, 50, 270); g.drawString("Normal for month: " + monthNormCdd, 190, 250); g.drawString("Normal for season: " + seasonNormCdd, 190, 270); g.drawString("Departure for month: " + monthDepCdd, 350, 250); g.drawString("Departure for season: " + seasonDepCdd, 350, 270); g.drawString("PRECIPITATION DATA (inches)", 50, 310); g.drawString("Liquid equivalent: " + monthPrecip, 50, 330); g.drawString("Total for year: " + yearPrecip, 50, 350); g.drawString("Normal for month: " + monthNormPrecip, 200, 330); g.drawString("Normal for year: " + yearNormPrecip, 200, 350); g.drawString("Departure for month: " + monthDepPrecip, 340, 330); g.drawString("Departure for year: " + yearDepPrecip, 340, 350); g.drawString("Snowfall for month: " + monthSnowfall, 100, 380); g.drawString("Snowfall for season: " + seasonSnowfall, 300, 380); } } } // // ***END OF PAINT() METHOD*** // } // // ***END OF PROGRAM*** //