/* Name: ua_temp_cgi.pc Written by: Jeremy Gustrowsky, NCDC contract programmer Modified by: Helen Frederick Last revised: 3/17/99 */ char RootPath[100],TempPath[100],UserInfo[40]; #include "ua_climvis_cgi.h" /* defines the sql error handling code -- borrowed from Oracle C examples (sample1.pc to be exact.)*/ void sql_error(char *msg) { char err_msg[128]; size_t buf_len, msg_len; char error[256]; EXEC SQL WHENEVER SQLERROR CONTINUE; /* printf(error,"\n%s\n", msg);*/ buf_len = sizeof (err_msg); sqlglm(err_msg, &buf_len, &msg_len); sprintf(error,"%.*s\n", msg_len, err_msg); strcat(error,msg); EXEC SQL ROLLBACK RELEASE; /* prints html error message to browser and stops execution */ showError(error); } /*----------------------------- MakeMonthly -------------------------------- The function MakeMonthly creates a temporary data file and an accompanying text files containing every known data value for a chosen month over a user selected number of years. */ MakeMonthly(char* wmo_no, char* station_name, char* country_name, int iselect, int startyear, int startDataThisSet, int endDataThisSet, int endyear, int *high, int *low, int month, int pid, float *percent, int units, char *pstimeStamp, char* psparam, int Ihr_group, int Ipres_lvl, int Iparm_type) { FILE *output,*text; char path[100],query[150],info[16],newinfo[16],year[6],newstatid[12]; char *monthname,*ab_month; int missing,count,yearCounter,rowcount,current_year,read,highest=0,lowest=0; float celsius,fahrenheit,first; int Ppres_lvl=0; char Spres_lvl[11]; char Sparm_type[7]; struct data_month month_data; /* get the full month name -- used at the top of the text file before any data is printed*/ monthname = MonthName(month,'F'); /* get the abbreviated month name -- used to make the database query. columns in the database are lower case three characters, e.g. jan,feb*/ ab_month = MonthName(month,'A'); /* variable "iselect" indicated which dataset is being constructed: first param or second. */ if(iselect == 1) { /*If the user wants more than one year, open temp files for dataset and graph.*/ sprintf(path, "%s/temp.%d.temp",TempPath,pid); output = fopen(path,"w"); if(output == NULL) CARDSFileFailure(path); fflush(output); sprintf(path, "%s/V2.%d.txt",TempPath,pid); text = fopen(path,"w"); if(text == NULL) CARDSFileFailure(path); fflush(text); } else { /*Open the second output file and append to user text file. */ sprintf(path, "%s/temp.%d.temp2",TempPath,pid); output = fopen(path,"w"); if(output == NULL) CARDSFileFailure(path); fflush(output); sprintf(path, "%s/V2.%d.txt",TempPath,pid); text = fopen(path,"a"); if(text == NULL) CARDSFileFailure(path); fflush(text); fprintf(text,"\n\n\n"); } if( (Ipres_lvl==31) || (Ipres_lvl==26) ) { /* set name of parameter type* / if(Iparm_type==1) strcpy(Sparm_type,"temp"); if(Iparm_type==2) strcpy(Sparm_type,"dptemp"); if(Iparm_type==3) strcpy(Sparm_type,"rhum"); if(Iparm_type==4) strcpy(Sparm_type,"sphum"); if(Iparm_type==5) strcpy(Sparm_type,"wind"); if(Iparm_type==6) strcpy(Sparm_type,"uwind"); if(Iparm_type==7) strcpy(Sparm_type,"vwind"); sprintf(query,"SELECT distinct wmo_no,year,%s FROM ua_%s_%sdata WHERE wmo_no = \'%s\' and year between %i and %i and hr_group = %i and lvl_type = %i",ab_month,Sparm_type,psparam,wmo_no,startyear,endyear,Ihr_group,Ipres_lvl); } else { /* set name of parameter type* / if(Iparm_type==1) strcpy(Sparm_type,"temp"); if(Iparm_type==2) strcpy(Sparm_type,"dptemp"); if(Iparm_type==3) strcpy(Sparm_type,"rhum"); if(Iparm_type==4) strcpy(Sparm_type,"sphum"); if(Iparm_type==5) strcpy(Sparm_type,"wind"); if(Iparm_type==6) strcpy(Sparm_type,"uwind"); if(Iparm_type==7) strcpy(Sparm_type,"vwind"); sprintf(query,"SELECT distinct wmo_no,year,%s FROM ua_%s_%sdata WHERE wmo_no = \'%s\' and year between %i and %i and hr_group = %i and pres_lvl = %i",ab_month,Sparm_type,psparam,wmo_no,startyear,endyear,Ihr_group,Ipres_lvl); } printf("IParmtype: %d Sparm_type: %s\n\n", Iparm_type, Sparm_type); printf("%s\n", query); /* register the error handler code */ EXEC SQL WHENEVER SQLERROR DO sql_error("-- CGI/ORACLE error handler ---\n"); /* connect to the database */ EXEC SQL CONNECT :UserInfo; /* prepare the sql query useing the string above (the "query" string).*/ EXEC SQL PREPARE data_select FROM :query; /* delcare a cursor for the prepared query */ EXEC SQL DECLARE data_cursor CURSOR FOR data_select; /* open the cursor for reading */ EXEC SQL OPEN data_cursor; psparam = ParamName(psparam); if( (Ipres_lvl==26) || (Ipres_lvl==31) ) { if(Ipres_lvl==31) strcpy(Spres_lvl,"Surface"); if(Ipres_lvl==26) strcpy(Spres_lvl,"Tropopause"); } else { Ppres_lvl=(Ipres_lvl*.1); sprintf(Spres_lvl,"%dmb",Ppres_lvl); } /*Print the headers at the top of the text files the user will have the opportunity to download */ fprintf(text,"**Note:** This dataset is not for commercial distribution.\n\n"); if(units==0) { if(Iparm_type==1) { fprintf(text, "%s, %s (CARDS WMO# %s)\n%s %s Temperature measured in degrees Celsius\n",station_name,country_name,wmo_no,monthname,psparam); } if(Iparm_type==2) { fprintf(text, "%s, %s (CARDS WMO# %s)\n%s %s Dewpoint Temperature measured in degrees Celsius\n",station_name,country_name,wmo_no,monthname,psparam); } if(Iparm_type==3) { fprintf(text, "%s, %s (CARDS WMO# %s)\n%s %s Relative Humidity Percentage\n",station_name,country_name,wmo_no,monthname,psparam); } if(Iparm_type==4) { fprintf(text, "%s, %s (CARDS WMO# %s)\n%s %s Specific Humidity Percentage\n",station_name,country_name,wmo_no,monthname,psparam); } if(Iparm_type==5) { fprintf(text, "%s, %s (CARDS WMO# %s)\n%s %s Wind Speed measured in Meters per Second\n",station_name,country_name,wmo_no,monthname,psparam); } if(Iparm_type==6) { fprintf(text, "%s, %s (CARDS WMO# %s)\n%s %s Zonal (U) Wind Speed measured in Meters per Second\n",station_name,country_name,wmo_no,monthname,psparam); } if(Iparm_type==7) { fprintf(text, "%s, %s (CARDS WMO# %s)\n%s %s Meridional (V) Wind Speed measured in Meters per Second\n",station_name,country_name,wmo_no,monthname,psparam); } fprintf(text,"%s Pressure Level; %2.2dZ Hour Group\n%s\n\n",Spres_lvl,Ihr_group,pstimeStamp); } else { fprintf(text, "%s, %s (CARDS WMO# %s)\n%s %s Temperature measured in degrees Fahrenheit\n",station_name,country_name,wmo_no,monthname,psparam); fprintf(text,"%s Pressure Level; %2.2dZ Hour Group\n%s\n\n",Spres_lvl,Ihr_group,pstimeStamp); } count = 0; missing = 0; read = 0; rowcount = 0; /* tell the preprocessor what to do when there is no more data in the cursor*/ EXEC SQL WHENEVER NOT FOUND DO break; while(1) { EXEC SQL FETCH data_cursor INTO :month_data; current_year = month_data.current_year; /* Initialize the data to be the highest and lowest on the first pass and check it against the highest value so far if it is not the first pass.*/ if(!read) { /* yearCounter is suppose to store the year IT SHOULD BE. If the data has gaps, then there will be a difference between the current_year variable and yearCounter. (see while(month_data. current_year > yearCounter) loop below which interjects missing data if this discrepancy occurs) However, on startup, the yearCounter needs to be set to either the current year in the cursor, or to the starting year the user wanted -- whichever is smaller. If there is no missing data at the beginning of the time period the user requested, then these two values (start and current_year) should be the same. Otherwise current_year will be larger than the start year and yearCounter will need to reflect this so that the loop below can interject missing values at the beginning of the user text file. */ yearCounter = month_data.current_year; if(startyear < yearCounter) yearCounter = startyear; highest = month_data.data; lowest = month_data.data; read = 1; } else { if(month_data.data > highest) highest = month_data.data; if((month_data.data < lowest) && (month_data.data != -9999)) lowest = month_data.data; if((lowest == -9999) && (month_data.data != -9999)) lowest = month_data.data; } /* interject missing data values if there is a blank spot in the data */ while(month_data.current_year > yearCounter) { if(yearCounter >= startDataThisSet) { count++; missing++; fprintf(text, "%d NO DATA\n",yearCounter++); } else yearCounter++; } /* if the data retrieved for this month is not missing, write it to both the text file, and the ace/gr data file (after converting it to the proper units)*/ if(month_data.data != -9999) { if(units) { /*Change to degrees celsius vs. tenths of degrees celsius*/ celsius = ((float)month_data.data / 10); fprintf(output, "%d %6.1f\n",yearCounter,celsius); fprintf(text, "%d %9.1f\n",yearCounter,celsius); } else { /*Change to degrees fahrenheit vs. tenths of degrees celsius */ fahrenheit = ((((float)month_data.data*9)/50)+32); fprintf(output, "%d %6.2f\n",yearCounter,fahrenheit); fprintf(text, "%d %9.2f\n",yearCounter,fahrenheit); } } else { missing++; fprintf(text, "%d NO DATA\n",yearCounter); } count++; rowcount++; yearCounter++; } /* if the cursor contains nothing, then it means the user comepletely missed all available data. Set the yearCounter to startyear for the loop below */ if(rowcount == 0) yearCounter = startyear; /* Takes care of any missing data from the end of the dataset */ while(yearCounter <= endyear) { if(yearCounter <= endDataThisSet) { count++; missing++; fprintf(text, "%d NO DATA\n",yearCounter++); } else yearCounter++; } /* Calculate percentage of missing data. */ *percent = (float)missing/(float)count; (*high) = highest; (*low) = lowest; EXEC SQL CLOSE data_cursor; fclose(output); fclose(text); } /*----------------------------- MakeSeries --------------------------------- This function is responsible for the creation of the temporary dataset and an accompanying text file that contain data for a user selected period of time (e.g. June 1945 to May 1950)*/ MakeSeries(int iselect, int startyear, int startDataThisSet, int endDataThisSet, int startDataOtherSet, int endyear, int month1, int month2, int pid, int *high, int *low, char *name, float *percent, char *country_name, int units, char* timeStamp, char* psparam, char* wmo_no, int igraph, int Ihr_group, int Ipres_lvl, int Iparm_type) { FILE *output,*text; char path[100],query[250],info[16],newinfo[16],year[6],newstatid[12]; char *monthname,*ab_month,*current_month; int missing,count,yearCounter,rowcount,current_year,read,highest=0,lowest=0; int startat,data,i,missing_count,end_i; float celsius,fahrenheit,first; int Ppres_lvl=0; char Spres_lvl[11]; char Sparm_type[7]; struct data_year year_data; /* get the full month name -- used at the top of the text file before any data is printed*/ monthname = MonthName(month1,'F'); /* get the abbreviated month name -- used to make the database query. columns in the database are lower case three characters, e.g. jan,feb*/ ab_month = MonthName(month1,'A'); /* variable "iselect" indicated which dataset is being constructed: first param or second. */ if(iselect == 1) { /*If the user wants more than one year, open temp files for dataset and graph.*/ sprintf(path, "%s/temp.%d.temp",TempPath,pid); output = fopen(path,"w"); if(output == NULL) CARDSFileFailure(path); fflush(output); sprintf(path, "%s/V2.%d.txt",TempPath,pid); text = fopen(path,"w"); if(text == NULL) CARDSFileFailure(path); fflush(text); } else { /*Open the second output file and append to user text file. */ sprintf(path, "%s/temp.%d.temp2",TempPath,pid); output = fopen(path,"w"); if(output == NULL) CARDSFileFailure(path); fflush(output); sprintf(path, "%s/V2.%d.txt",TempPath,pid); text = fopen(path,"a"); if(text == NULL) CARDSFileFailure(path); fflush(text); fprintf(text,"\n\n\n"); } /* Use Pressure Level to select either by pressure or level type */ if( (Ipres_lvl==31) || (Ipres_lvl==26) ) { /* set name of parameter type* / if(Iparm_type==1) strcpy(Sparm_type,"temp"); if(Iparm_type==2) strcpy(Sparm_type,"dptemp"); if(Iparm_type==3) strcpy(Sparm_type,"rhum"); if(Iparm_type==4) strcpy(Sparm_type,"sphum"); if(Iparm_type==5) strcpy(Sparm_type,"wind"); if(Iparm_type==6) strcpy(Sparm_type,"uwind"); if(Iparm_type==7) strcpy(Sparm_type,"vwind"); sprintf(query,"SELECT distinct * FROM ua_%s_%sdata WHERE wmo_no = \'%s\' and year between %i and %i and hr_group = %i and lvl_type = %i",Sparm_type,psparam,wmo_no,startyear,endyear,Ihr_group,Ipres_lvl); } else { /* set name of parameter type* / if(Iparm_type==1) strcpy(Sparm_type,"temp"); if(Iparm_type==2) strcpy(Sparm_type,"dptemp"); if(Iparm_type==3) strcpy(Sparm_type,"rhum"); if(Iparm_type==4) strcpy(Sparm_type,"sphum"); if(Iparm_type==5) strcpy(Sparm_type,"wind"); if(Iparm_type==6) strcpy(Sparm_type,"uwind"); if(Iparm_type==7) strcpy(Sparm_type,"vwind"); sprintf(query,"SELECT distinct * FROM ua_%s_%sdata WHERE wmo_no = \'%s\' and year between %i and %i and hr_group = %i and pres_lvl = %i",Sparm_type,psparam,wmo_no,startyear,endyear,Ihr_group,Ipres_lvl); } printf("IParmtype: %d Sparm_type: %s\n\n", Iparm_type, Sparm_type); printf("%s\n", query); /* register the error handler code */ EXEC SQL WHENEVER SQLERROR DO sql_error("-- CGI/ORACLE error handler ---\n"); /* connect to the database */ EXEC SQL CONNECT :UserInfo; /* prepare the sql query useing the string above (the "query" string).*/ EXEC SQL PREPARE data_select FROM :query; /* delcare a cursor for the prepared query */ EXEC SQL DECLARE yearly_cursor CURSOR FOR data_select; /* open the cursor for reading */ EXEC SQL OPEN yearly_cursor; /* change the parameter name from an abbreviated version to a full word */ psparam = ParamName(psparam); if( (Ipres_lvl==26) || (Ipres_lvl==31) ) { if(Ipres_lvl==31) strcpy(Spres_lvl,"Surface"); if(Ipres_lvl==26) strcpy(Spres_lvl,"Tropopause"); } else { Ppres_lvl=(Ipres_lvl*.1); sprintf(Spres_lvl,"%dmb",Ppres_lvl); } /*Print the headers at the top of the text files the user will have the opportunity to download */ fprintf(text,"**Note:** This dataset is not for commercial distribution.\n\n"); if(units==0) { if(Iparm_type==1) { fprintf(text,"%s, %s (CARDS WMO# %s)\n%s Monthly Average Temperature measured in degrees Celsius\n",name,country_name,wmo_no,psparam); } if(Iparm_type==2) { fprintf(text,"%s, %s (CARDS WMO# %s)\n%s Monthly Average Dewpoint Temperature measured in degrees Celsius\n",name,country_name,wmo_no,psparam); } if(Iparm_type==3) { fprintf(text,"%s, %s (CARDS WMO# %s)\n%s Monthly Average Relative Humidity Percentage\n",name,country_name,wmo_no,psparam); } if(Iparm_type==4) { fprintf(text,"%s, %s (CARDS WMO# %s)\n%s Monthly Average Specific Humidity Percentage\n",name,country_name,wmo_no,psparam); } if(Iparm_type==5) { fprintf(text,"%s, %s (CARDS WMO# %s)\n%s Monthly Average Wind Speed measured in Meters per Second\n",name,country_name,wmo_no,psparam); } if(Iparm_type==6) { fprintf(text,"%s, %s (CARDS WMO# %s)\n%s Monthly Average Zonal Wind (U) Speed measured in Meters per Second\n",name,country_name,wmo_no,psparam); } if(Iparm_type==7) { fprintf(text,"%s, %s (CARDS WMO# %s)\n%s Monthly Average Meridional (V) Wind Speed measured in Meters per Second\n",name,country_name,wmo_no,psparam); } fprintf(text,"%s Pressure Level; %2.2dZ Hour Group\n%s\n",Spres_lvl,Ihr_group,timeStamp); } else { fprintf(text,"%s, %s (CARDS WMO#%s)\n%s Monthly Temperature measured in degrees Fahrenheit\n",name,country_name,wmo_no,psparam); fprintf(text,"%s Pressure Level; %2.2dZ Hour Group\n%s\n",Spres_lvl,Ihr_group,timeStamp); } /* A variable to count the total number of months the user asked to see. This variable always increments whether the month is within the period of record or not, and whether or not the data is missing. This variable tells the temporary data file where to put tick marks because it tracks the x position of each data point being graphed. If no data is being graphed (empty set) then this variable never gets written to the temp data file and nothing appears on the graph */ count = 0; /*Decide where to start the counting depending on which of the two datasets is longer */ if(startDataThisSet < startDataOtherSet) { if(startyear < startDataThisSet) { startat = startDataThisSet - startyear - 1; startat = ((startat * 12)+(12-month1) + 1); count += startat; } } /* The variable missing keeps track of missing values. The variable missing_ count keeps track of data that should be available. When data is available, missing_count is incremented. When data is not available and it is a month WITHIN the period of record (i.e. it should be there), both variables are incremented. If data is not available and it is a month OUTSIDE the period of record, then neither variable is incremented. */ missing = 0; missing_count = 0; /* switches to 1 after the first row of data is read. Just keeps track of whether it's the first time around or not. */ read = 0; /* increments for each row successfully processed */ rowcount = 0; /* tell the preprocessor what to do when there is no more data in the cursor*/ EXEC SQL WHENEVER NOT FOUND DO break; while(1) { EXEC SQL FETCH data_cursor INTO :year_data; current_year = year_data.current_year; /* Initialize the data to be the highest and lowest on the first pass and check it against the highest value so far if it is not the first pass.*/ if(!read) { /* yearCounter is suppose to store the year IT SHOULD BE. If the data has gaps, then there will be a difference between the current_year variable and yearCounter. (see while(year_data. current_year > yearCounter) loop below which interjects missing data if this discrepancy occurs) However, on startup, the yearCounter needs to be set to either the current year in the cursor, or to the starting year the user wanted -- whichever is smaller. If there is no missing data at the beginning of the time period the user requested, then these two values (start and current_year) should be the same. Otherwise current_year will be larger than the start year and yearCounter will need to reflect this so that the loop below can interject missing values at the beginning of the user text file. */ yearCounter = current_year; if(startyear < yearCounter) yearCounter = startyear; highest = year_data.jan; lowest = year_data.jan; read = 1; } /* interject missing data values if there is a blank spot in the data */ while(current_year > yearCounter) { /* This is data that should be in the set but is not. Mark it as missing */ if(yearCounter >= startDataThisSet) { fprintf(text,"\n %i \nMonth -- Value\n", yearCounter); /* variable end_i tells when to stop writing in missing vaules. This is needed for type four graphs where the month may be something other than January the end something besides Dec. */ if(yearCounter < endyear) end_i = 12; else end_i = month2; for(i=(month1-1); i= highest) highest = data; /* Check each value to see if it is lower than the lowest found so far and is not -9999 */ if((data <= lowest) && (data != -9999)) lowest = data; /* If lowest happens to be -9999, then set it equal to the current data value */ if((lowest == -9999) && (data != -9999)) lowest = data; missing_count++; count++; month1=1; } rowcount++; yearCounter++; } /* if the cursor contains nothing, then it means the user comepletely missed all available data. Set the yearCounter to startyear for the loop below */ if(rowcount == 0) yearCounter = startyear; /* Takes care of any missing data from the end of the dataset */ while(yearCounter <= endyear) { if(yearCounter < endDataThisSet) { fprintf(text,"\n %i \nMonth -- Value\n", yearCounter); /* end_i tells us where to stop interjecting missing data (which month to quit on.) This is necessary for type four graphs */ if(yearCounter < endyear) end_i = 12; else end_i = month2; for(i=0; iCARDS Station Selection\n"); printf("\n

\n"); printf("

\n"); /* Print list of hidden variables to be passed on as arguments to the next stage in the process */ printf("\n"); printf("\n",graph); /* printf("\n",region1); printf("\n",country1); printf("\n",code1); */ printf("

CARDS Max/Min Temperature

\n"); printf("

\n"); if((graph == 1) || (graph == 4)) printf("

Select a station:

\n"); else printf("

Select stations:

\n"); /*printf("

\n");*/ EXEC SQL WHENEVER SQLERROR DO sql_error("-- CGI/ORACLE error handler ---\n"); EXEC SQL CONNECT :UserInfo; EXEC SQL DECLARE station1_cursor CURSOR FOR SELECT restricted,region,country_name,station_name,wmo_no,latitude,longitude,country_code,start_year,end_year FROM ua_stations WHERE country_name = :country1 ORDER BY station_name; /* Set up selection box for stations */ printf("

From %s:

\n"); if((graph == 2) || (graph == 3)) { EXEC SQL DECLARE station2_cursor CURSOR FOR SELECT DISTINCT restricted,region,country_name,station_name,wmo_no,latitude,longitude,country_code,start_year,end_year FROM ua_stations WHERE country_name = :country2; /* Set up selection box for stations */ printf("

From %s:

\n"); } printf("

\n"); /* Give the user the option to select metric or english units. */ printf("

Select the type of units you prefer

\n"); printf(" English Standard\n"); printf(" Metric

\n"); printf("\n"); /* If the graph variable is 1, show the selections for one month over a period of years */ switch(graph) { case 1: { printf("

Make your selections

\n"); /* printf("\n\n"); */ printf("
First ParameterSecond ParameterMonthStart YearEnd Year
\n\n"); /* Put start and end date text windows in a small table */ printf("\n"); /* Set up small windows for entering dates */ printf("\n"); printf("\n
First ParameterSecond ParameterPressure LevelMonthStart YearEnd Year
"); printf("\n"); printf("
"); printf("
\n"); printf("

\n

\n"); printf("

\n\n"); break; } case 2: { printf("

Make your selections

\n"); printf("\n\n"); /* Put start and end date text windows in a small table */ printf("\n"); /* Set up small windows for entering dates */ printf("\n"); printf("\n
ParameterPressure LevelMonthStart YearEnd Year
"); printf("
"); printf("
\n"); printf("

\n

\n"); printf("

\n\n"); break; } case 3: { printf("

Make your selections

\n"); printf("\n\n"); /* Put start and end date text windows in a small table */ printf("\n"); /* Set up small windows for entering dates */ printf("\n"); printf("\n
ParameterPressure LevelMonthStart YearEnd Year
"); printf("
"); printf("
\n"); printf("

\n

\n"); printf("

\n\n"); break; } case 4: { /* If the user chose option four, set up options for period of record*/ printf("

\n\n"); printf(""); printf("\n"); printf("\n"); printf("\n"); printf("\n
ParameterPressuer LevelMonthStart YearMonthEnd Year
"); printf("
\n"); printf("

\n

\n"); printf("

\n"); break; } } /* Disconnect from the Oracle DBMS. */ EXEC SQL COMMIT WORK RELEASE; printf("

"); exit(1); } /*----------------------------- SelectCountry --------------------------------- "SelectCountry" is a function that prints a list of countries found within the region(s) the user selected from the image map. If there are none within that region, no list will be printed. */ SelectCountry(int numRegions, int graph, char *region1, char *region2, char restricted) { int first; char query[160]; struct region_data region_info; if(restricted == 'Y') { strcpy(query,"SELECT DISTINCT region,country_name FROM ua_stations WHERE region = :r1 and restricted = \'N\' ORDER BY country_name"); } else { strcpy(query,"SELECT DISTINCT region,country_name FROM ua_stations WHERE region = :r1 ORDER BY country_name"); } /* writeTestInfo(RootPath,"test",query,'w'); exit(0); */ EXEC SQL WHENEVER SQLERROR DO sql_error("-- CGI/ORACLE error handler ---\n"); EXEC SQL CONNECT :UserInfo; /*showError(UserInfo);*/ /* Set up new HTML page */ printf("CARDS Country Selection\n"); printf("
\n

\n"); printf("

\n"); printf("\n"); printf("\n",graph); printf("

CARDS Max/Min Temperature

\n"); printf("

\n"); if(numRegions == 1) { RegionIsValid(region1); printf("

Select a country or state from the list

\n

\n"); EXEC SQL PREPARE region_select FROM :query; EXEC SQL DECLARE country1_cursor CURSOR FOR region_select; /* Set up the station selection list */ printf("

\n"); } else { /* Make sure regions have something in them */ RegionIsValid(region1); RegionIsValid(region2); printf("

Select a country or state from each list

\n

\n"); EXEC SQL PREPARE region2a_select FROM :query; EXEC SQL DECLARE country2a_cursor CURSOR FOR region2a_select; EXEC SQL OPEN country2a_cursor USING :region1; /* Set up the station selection list */ printf("

\n"); /* Set up the station selection list */ printf("

\n"); EXEC SQL CLOSE country2b_cursor; } /* Disconnect from the Oracle DBMS. */ EXEC SQL COMMIT WORK RELEASE; printf("

\n"); printf("

"); exit(1); } /*----------------------------- DisplayGraph --------------------------------- The function "DisplayGraph" is responsible for managing the creation of the datasets requested by the user, the creation of the accompanying parameter file, the creation of the graph itself, and the finally displaying the graph to the user. */ DisplayGraph(int num_stations, char *station1_number, char *station2_number, int igraph, char *firstParam, char *secondParam, int firstMonth,int secondMonth, int units, int start, int end, int pid, char* time, char restricted, int Ihr_group, int Ipres_lvl, int Iparm_type) { char path1[150],path2[150],location1[22],location2[22],query[300]; int i=0,a,high1,low1,high2,low2,icall; float fpercent1,fpercent2; /* Stuctures that will contain station metadata and their associated indicator structures. */ struct meta_data station1,station2; struct meta_data_ind station1_ind,station2_ind; EXEC SQL WHENEVER SQLERROR DO sql_error("-- CGI/ORACLE error handler ---\n"); EXEC SQL WHENEVER NOT FOUND DO sql_error("-- Error found in function DisplayGraph --\n"); EXEC SQL CONNECT :UserInfo; /* Get station metadata for the first station */ EXEC SQL SELECT restricted,region,country_name,station_name,wmo_no,latitude,longitude,country_code,start_year,end_year INTO :station1 INDICATOR :station1_ind FROM ua_stations WHERE wmo_no = :station1_number; RemoveSpaces(station1.station_name); RemoveSpaces(station1.country_name); RemoveSpaces(station1.region); RemoveSpaces(station1.wmo_no); PrintLatLong(atof(station1.latitude),atof(station1.longitude),location1); if(num_stations == 2) { /* Get station metadata for the second station */ EXEC SQL SELECT restricted,region,country_name,station_name,wmo_no,latitude,longitude,country_code,start_year,end_year INTO :station2 INDICATOR :station2_ind FROM ua_stations WHERE wmo_no = :station2_number; RemoveSpaces(station2.station_name); RemoveSpaces(station2.country_name); RemoveSpaces(station2.region); RemoveSpaces(station2.wmo_no); PrintLatLong(atof(station2.latitude),atof(station2.longitude),location2); } CheckDates(igraph,start,end,station1.start_year,station2.start_year); /* Create the text files the user will see and prepare the datasets for xmgr*/ switch(igraph) { case 1: { /*Display two parameters for one station.*/ /*If the month the user selected is anything but zero, it means they wanted to create a plot of temperature for that month over a number of years. Otherwise they want a plot of temperature for every month for a period of years.*/ if(firstMonth) { /*MakeMonthly(char* wmo_no, char* station_name, char* country_name, int iselect, int startyear, int startDataThisSet, int startDataOtherSet, int endyear, int *high, int *low, int month, int pid, float *percent, int units, char *pstimeStamp, char* psparam)*/ /*Create a dataset for each parameter by running the "MakeMonthly" function twice with both sets of information */ MakeMonthly(station1.wmo_no,station1.station_name, station1.country_name,1,start,station1.start_year,station1.end_year,end,&high1,&low1,firstMonth,pid,&fpercent1,units,time,firstParam, Ihr_group, Ipres_lvl, Iparm_type); MakeMonthly(station1.wmo_no,station1.station_name, station1.country_name,0,start,station1.start_year,station1.end_year,end,&high2,&low2,firstMonth,pid,&fpercent2,units,time,secondParam, Ihr_group, Ipres_lvl, Iparm_type); } else { /*MakeSeries(int iselect, int startyear, int startDataThisSet, int endDataThisSet, int startDataOtherSet, int endyear, int month1, int month2, int pid, int *high, int *low, char *name, float *percent, char *country_name, int units, char* timeStamp, char* psparam, char* wmo_no, int igraph)*/ MakeSeries(1, start, station1.start_year, station1.end_year, station1.start_year, end, 1, 12, pid, &high1, &low1, station1.station_name, &fpercent1, station1.country_name, units, time, firstParam, station1.wmo_no, igraph, Ihr_group, Ipres_lvl, Iparm_type); MakeSeries(0, start, station1.start_year, station1.end_year, station1.start_year, end, 1, 12, pid, &high2, &low2, station1.station_name, &fpercent2, station1.country_name, units, time, secondParam, station1.wmo_no, igraph, Ihr_group, Ipres_lvl, Iparm_type); } break; } case 2: { if(firstMonth) { /*MakeMonthly(char* wmo_no, char* station_name, char* country_name, int iselect, int startyear, int startDataThisSet, int startDataOtherSet, int endyear, int *high, int *low, int month, int pid, float *percent, int units, char *pstimeStamp, char* psparam)*/ /*Create a dataset for each parameter by running the "MakeMonthly" function twice with both sets of information */ MakeMonthly(station1.wmo_no,station1.station_name, station1.country_name,1,start,station1.start_year,station1.end_year,end,&high1,&low1,firstMonth,pid,&fpercent1,units,time,firstParam,Ihr_group, Ipres_lvl, Iparm_type); MakeMonthly(station2.wmo_no,station2.station_name, station2.country_name,0,start,station2.start_year,station2.end_year,end,&high2,&low2,firstMonth,pid,&fpercent2,units,time,firstParam,Ihr_group, Ipres_lvl, Iparm_type); } else { /*MakeSeries(int iselect, int startyear, int startDataThisSet, int endDataThisSet, int startDataOtherSet, int endyear, int month1, int month2, int pid, int *high, int *low, char *name, float *percent, char *country_name, int units, char* timeStamp, char* psparam, char* wmo_no, int igraph)*/ MakeSeries(1, start, station1.start_year, station1.end_year, station2.start_year, end, 1, 12, pid, &high1, &low1, station1.station_name, &fpercent1, station1.country_name, units, time, firstParam, station1.wmo_no, igraph, Ihr_group, Ipres_lvl, Iparm_type); MakeSeries(0, start, station2.start_year, station2.end_year, station1.start_year, end, 1, 12, pid, &high2, &low2, station2.station_name, &fpercent2, station2.country_name, units, time, firstParam, station2.wmo_no, igraph, Ihr_group, Ipres_lvl, Iparm_type); } break; } case 3: { if(firstMonth) { /*MakeMonthly(char* wmo_no, char* station_name, char* country_name, int iselect, int startyear, int startDataThisSet, int startDataOtherSet, int endyear, int *high, int *low, int month, int pid, float *percent, int units, char *pstimeStamp, char* psparam)*/ /*Create a dataset for each parameter by running the "MakeMonthly" function twice with both sets of information */ MakeMonthly(station1.wmo_no,station1.station_name, station1.country_name,1,start,station1.start_year,station1.end_year,end,&high1,&low1,firstMonth,pid,&fpercent1,units,time,firstParam,Ihr_group, Ipres_lvl, Iparm_type); MakeMonthly(station2.wmo_no,station2.station_name, station2.country_name,0,start,station2.start_year,station2.end_year,end,&high2,&low2,firstMonth,pid,&fpercent2,units,time,firstParam,Ihr_group, Ipres_lvl, Iparm_type); } else { /*MakeSeries(int iselect, int startyear, int startDataThisSet, int endDataThisSet, int startDataOtherSet, int endyear, int month1, int month2, int pid, int *high, int *low, char *name, float *percent, char *country_name, int units, char* timeStamp, char* psparam, char* wmo_no, int igraph)*/ MakeSeries(1, start, station1.start_year, station1.end_year, station2.start_year, end, 1, 12, pid, &high1, &low1, station1.station_name, &fpercent1, station1.country_name, units, time, firstParam, station1.wmo_no, igraph, Ihr_group, Ipres_lvl, Iparm_type); MakeSeries(0, start, station2.start_year, station2.end_year, station1.start_year, end, 1, 12, pid, &high2, &low2, station2.station_name, &fpercent2, station2.country_name, units, time, firstParam, station2.wmo_no, igraph, Ihr_group, Ipres_lvl, Iparm_type); } break; } case 4: { MakeSeries(1, start, station1.start_year, station1.end_year, station2.start_year, end, firstMonth, secondMonth, pid, &high1, &low1, station1.station_name, &fpercent1, station1.country_name, units, time, firstParam, station1.wmo_no, igraph, Ihr_group, Ipres_lvl, Iparm_type); break; } default: { showError("Incorrect graph type."); break; } } /* Make sure high1 and low1 store the highest and the lowest temps that will be displayed on the graph.*/ if(igraph != 4) { if(high1 < high2) high1 = high2; if(low1 > low2) low1 = low2; } /* Multiply by 100 to get the actual percent missing for each set of data.*/ fpercent1*=100; fpercent2*=100; /* Create the paramter file that will be used by xmgr to display the information in a pleasing format. sprintf(query,"%s, %i, %c, %s, %s, %s, %s, %i, %i, %i, %i, %f, %f, %i, %i, %i, %s, %s, i, s, s, s",station1.region, igraph, restricted, station1.country_name, station2.country_name, station1.station_name, station2.station_name, start, end, high1, low1, fpercent1, fpercent2, firstMonth, secondMonth, pid, firstParam, secondParam); ,igraph,restricted,station1.country_name,station2.country_name,station1.station_name,station2.station_name,start,end,high1,low1,fp showError(query);*/ MakeParam(station1.region,igraph,restricted,station1.country_name,station2.country_name,station1.station_name,station2.station_name,start,end,high1,low1,fpercent1,fpercent2,firstMonth,secondMonth,pid,firstParam,secondParam,units,location1,location2,time,Ihr_group,Ipres_lvl,Iparm_type); /*Set up call to graphing shell "graph.temp" (or "graph" shell from precip.ghcncgi for type four graphs) to create the graph. Use the "path" string as a temporary string. */ if(igraph != 4) sprintf(path1,"/WWW/oracle-web/cgi-bin/climvis/cards/ua_graph.sh temp.%d.par temp.%d.temp temp.%d.temp2 V2.%d.gif V2.%d.ps",pid,pid,pid,pid,pid); else sprintf(path1,"/WWW/oracle-web/cgi-bin/climvis/cards/ua_graph temp.%d.temp V2.%d.gif V2.%d.ps temp.%d.par",pid,pid,pid,pid); icall=system(path1); /* If the call to the graphing shell was completed, then display the graph and various links on a new page for the user to see. Otherwise display an error message. */ if(icall == 0) { /* CountHits(igraph); */ /*Display graph for the user on the browser */ printf("Upper Air Climate Visualization\n"); printf("

\n\n",pid); printf("\n\n\n",pid); printf("\n\n
View the datasetView the graph
\n",pid); printf("

\n"); /* printf("

\nReturn to CARDS Region Selection to plot a new graph\n"); */ /* printf("

\nReturn to Climvis Dataset Selection"); */ printf("\n"); } else { printf("CARDS Failure\n

"); printf("

Our software was unable to create your graph.\n"); printf("

Please make a note of your graphing selections and contact the "); printf("webmaster@ncdc.noaa.gov as soon as possible.\n

Thankyou."); printf("

\n"); } /* Disconnect from the Oracle DBMS. */ EXEC SQL COMMIT WORK RELEASE; } main() { entry entries[MAX_ENTRIES]; char *psfirstRegion,*pssecondRegion,scountryName1[70],stemp[100]; char scountryName2[70],sstationInfo1[100],sstationInfo2[100],*psparam1; char *station1_number,*station2_number; char sstationName1[50],sstationName2[50],slatLong1[10],slatLong2[10],*psparam2; char sidNum1[15],sidNum2[15],stimeString[30],host[60],restricted,*test; int istage,pid,igraphType,i,j,x,cl,nextscreen,xval=100,yval=100; int icode1,icode2,iunits,start,iend,imonth1,imonth2, Ihr_group, Ipres_lvl; int Iparm_type; int startData1,iendData1,startData2,iendData2; struct tm *ptr; time_t lt; pid=getpid(); sprintf(host, "%s",getenv("REMOTE_HOST")); test=strstr(host,"ncdc.noaa.gov"); /* This code is not longer in use -- this code has to do with NCDC's policy on WMO resolution 40. See webmaster for details.*/ /* If the user host does not have "ncdc.noaa.gov" in it somewhere, then this IS a restricted user -- therefore the user is restricted to only those regions where the "restricted" field in metadata table is 'N' if(test == NULL) restricted = 'Y'; else restricted = 'N';*/ /* all data is unrestricted */ restricted = 'N'; /* There MUST be two newline characters here! */ printf("Content-type: text/html\n\n"); /* read the paths file and establish global root and temporary paths. */ getPaths(TempPath,RootPath); /*showError(RootPath);*/ /* get user/password info and set it globally. This is read from the access file in the cgi's root directory */ getOracleAccess(RootPath,UserInfo); /* Get the time. */ lt = time(NULL); ptr = localtime(<); sprintf(stimeString,asctime(ptr)); /* Get rid of the \n at the end of this string */ stimeString[24]='\0'; /* * This algorithm takes the incoming URL encoded data and places each piece * of information into a structure of type "entry." (See global definitions.) * The data coming in must be of type "Post" or the whole program will not * work properly. */ cl = atoi(getenv("CONTENT_LENGTH")); for(x=0; cl && (!feof(stdin)); x++) { ++j; entries[x].val = fmakeword(stdin,'&',&cl); plustospace(entries[x].val); unescape_url(entries[x].val); entries[x].name = makeword(entries[x].val,'='); /* debugging: prints out name/value pairs to stdout printf("entry[%i].name = %s\t\t",x,entries[x].name); printf("entry[%i].val = %s\n

",x,entries[x].val); */ } istage=atoi(entries[0].val); igraphType=atoi(entries[1].val); /* Variable "istage" controls which stage of the process will be run next. This variable is pass along on each html page created as a hidden variable. */ switch(istage) { case 2: { xval=atoi(entries[2].val); yval=atoi(entries[3].val); psfirstRegion=GetRegion(xval,yval); switch(igraphType) { case 1: { SelectCountry(1,1,psfirstRegion,pssecondRegion,restricted); break; } case 2: { SelectCountry(1,2,psfirstRegion,pssecondRegion,restricted); break; } case 3: { /* Give user the opportunity to select another region */ printf("CARDS Region Selection\n"); printf("

\n

\n"); printf("

\n"); printf("\n"); printf("\n",igraphType); printf("\n",psfirstRegion); printf("

Select another region

"); printf("

\n"); printf("

\n"); printf("

\n"); printf("

"); break; } case 4: { SelectCountry(1,4,psfirstRegion,pssecondRegion,restricted); break; } } break; } case 25: { psfirstRegion=entries[2].val; xval=atoi(entries[3].val); yval=atoi(entries[4].val); pssecondRegion=GetRegion(xval,yval); SelectCountry(2,3,psfirstRegion,pssecondRegion,restricted); break; } case 3: { switch(igraphType) { case 1: { strcpy(scountryName1,entries[2].val); SelectStation(1,scountryName1,scountryName2); break; } case 2: { strcpy(scountryName1,entries[2].val); SelectStation(2,scountryName1,scountryName1); break; } case 3: { strcpy(scountryName1,entries[2].val); strcpy(scountryName2,entries[3].val); SelectStation(3,scountryName1,scountryName2); break; } case 4: { strcpy(scountryName1,entries[2].val); SelectStation(4,scountryName1,scountryName2); break; } break; } } case 4: { switch(igraphType) { case 1: { Iparm_type=atoi(entries[2].val); station1_number=entries[3].val; iunits=atoi(entries[4].val); psparam1=entries[5].val; psparam2=entries[6].val; imonth1=atoi(entries[7].val); Ihr_group=atoi(entries[8].val); start=atoi(entries[9].val); iend=atoi(entries[10].val); Ipres_lvl=atoi(entries[11].val); imonth2=12; /* station1_number=entries[2].val; iunits=atoi(entries[3].val); psparam1=entries[4].val; psparam2=entries[5].val; imonth1=atoi(entries[6].val); Ihr_group=atoi(entries[7].val); start=atoi(entries[8].val); iend=atoi(entries[9].val); Ipres_lvl=atoi(entries[10].val); imonth2=12; */ DisplayGraph(1,station1_number,station2_number,igraphType,psparam1,psparam2,imonth1,imonth2,iunits,start,iend,pid,stimeString,restricted,Ihr_group, Ipres_lvl, Iparm_type); break; } case 2: { station1_number=entries[2].val; station2_number=entries[3].val; iunits=atoi(entries[4].val); psparam1=entries[5].val; psparam2 = psparam1; imonth1=atoi(entries[6].val); start=atoi(entries[7].val); iend=atoi(entries[8].val); imonth2=12; /*DisplayGraph(int num_stations, char *station1_number, char *station2_number, int igraph, char *firstParam, char *secondParam, int firstMonth,int secondMonth, int units, int start, int end, int pid, char* time, char restricted)*/ DisplayGraph(2,station1_number,station2_number,igraphType,psparam1,psparam2,imonth1,imonth2,iunits,start,iend,pid,stimeString,restricted,Ihr_group, Ipres_lvl, Iparm_type); break; } case 3: { station1_number=entries[2].val; station2_number=entries[3].val; iunits=atoi(entries[4].val); psparam1=entries[5].val; psparam2 = psparam1; imonth1=atoi(entries[6].val); start=atoi(entries[7].val); iend=atoi(entries[8].val); imonth2=12; DisplayGraph(2,station1_number,station2_number,igraphType,psparam1,psparam2,imonth1,imonth2,iunits,start,iend,pid,stimeString,restricted,Ihr_group, Ipres_lvl, Iparm_type); break; } case 4: { station1_number=entries[2].val; iunits=atoi(entries[3].val); psparam1=entries[4].val; psparam2 = psparam1; imonth1=atoi(entries[5].val); start=atoi(entries[6].val); imonth2 = atoi(entries[7].val); iend=atoi(entries[8].val); DisplayGraph(1,station1_number,station2_number,igraphType,psparam1,psparam2,imonth1,imonth2,iunits,start,iend,pid,stimeString,restricted,Ihr_group, Ipres_lvl, Iparm_type); break; } } break; } } }