www.pudn.com > ilib > iwebreprt.c
/*
Report generator for WWW access.log file
Usage:
httpgraph [options] [-tod|-dom|-dow|-moy] accesslogfile [accesslogfile ...]
Default action is to generate a day of the month usage graph to stdout.
-tod Display a time of day report indicating what
hours of the day get the most usage.
[THIS IS THE DEFAULT]
-dom Display a day of month report indicating what
days of the month get the most usage.
-dow Display a day of week report indicating what
days of the week get the most usage.
-moy Displays month report indicating usage by month
options what it does
---------------- ------------------------------------------------
-all Use all data [default]
-today Use data from today only
-yesterday Use data from yesterday only
-lastweek Use data from the Mon-Sun week prior to this one
-thisweek Use data for this Mon-Sun week
-thismonth Use data for the the current month
-lastmonth Use data for the month prior to this one
-bar Use a bar graph instead of a line graph.
-line Use line graph [default]
-nohdr Do not display title and summary at bottom
21-Sep-94 Craig Knudsen cknudsen@radix.net
Created
29-May-96 Craig Knudsen cknudsen@radix.net
29-May-96 Craig Knudsen cknudsen@radix.net
Converted from gd library to Ilib.
***************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "helvB18.h"
#include "courR10.h"
#ifndef min
#define min(a,b) ( (a) < (b) ? (a) : (b) )
#define max(a,b) ( (a) > (b) ? (a) : (b) )
#endif
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
static void read_file (
#ifndef _NO_PROTO
char *filename
#endif
);
static void add_time (
#ifndef _NO_PROTO
char *text
#endif
);
static int is_in_time_range (
#ifndef _NO_PROTO
char *text
#endif
);
static void set_times_today ();
static void set_times_yesterday ();
static void set_times_last_week ();
static void set_times_this_week ();
static void set_times_this_month ();
static void set_times_last_month ();
static void generate_gif ();
static int calc_max (
#ifndef _NO_PROTO
int cur_max
#endif
);
/*
** Define start and stop times. Use YYMMDDHHMMSS so that we can just
** use strcmp() to compare times.
*/
static char start_time[20]; /* in YYMMDDHHMMSS format */
static char stop_time[20]; /* in YYMMDDHHMMSS format */
static char pretty_start[30]; /* in human readable format */
static char pretty_stop[30]; /* in human readable format */
static char *months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
};
static char *wdays[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
};
static int days_in_month[] =
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
static int days_in_lmonth[] =
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
static int tod[24]; /* count by time of day */
static int dow[7]; /* couny by day of week */
static int dom[31]; /* count by day of month */
static int moy[12]; /* count by month */
#define SUNDAY 0
#define MONDAY 1
#define TUESDAY 2
#define WEDNESDAY 3
#define THURSDAY 4
#define FRIDAY 5
#define SATURDAY 6
static int total = 0; /* total number of requests counted */
typedef enum {
DAY_OF_MONTH,
DAY_OF_WEEK,
TIME_OF_DAY,
MONTH_OF_YEAR
} OutputType;
typedef enum {
BAR,
LINE
} GraphType;
static OutputType output_type = DAY_OF_MONTH;
static GraphType graph_type = LINE;
static int display_header = TRUE;
static int line_width = 2; /* for line graphs (can use 1-3) */
/* String to use in place of "Retrievals" */
static char *retrievals = "Retrievals";
/*
** Main
*/
int main ( argc, argv )
int argc;
char *argv[];
{
int loop;
/* default is to use all data */
start_time[0] = stop_time[0] = '\0';
for ( loop = 0; loop < 24; loop++ )
tod[loop] = 0;
for ( loop = 0; loop < 7; loop++ )
dow[loop] = 0;
for ( loop = 0; loop < 31; loop++ )
dom[loop] = 0;
for ( loop = 0; loop < 12; loop++ )
moy[loop] = 0;
/* process command line arguments */
for ( loop = 1; loop < argc; loop++ ) {
if ( strcmp ( argv[loop], "-bar" ) == 0 )
graph_type = BAR;
else if ( strcmp ( argv[loop], "-line" ) == 0 )
graph_type = LINE;
else if ( strcmp ( argv[loop], "-tod" ) == 0 )
output_type = TIME_OF_DAY;
else if ( strcmp ( argv[loop], "-dom" ) == 0 )
output_type = DAY_OF_MONTH;
else if ( strcmp ( argv[loop], "-dow" ) == 0 )
output_type = DAY_OF_WEEK;
else if ( strcmp ( argv[loop], "-moy" ) == 0 )
output_type = MONTH_OF_YEAR;
else if ( strcmp ( argv[loop], "-today" ) == 0 )
set_times_today ();
else if ( strcmp ( argv[loop], "-yesterday" ) == 0 )
set_times_yesterday ();
else if ( strcmp ( argv[loop], "-lastweek" ) == 0 )
set_times_last_week ();
else if ( strcmp ( argv[loop], "-thisweek" ) == 0 )
set_times_this_week ();
else if ( strcmp ( argv[loop], "-thismonth" ) == 0 )
set_times_this_month ();
else if ( strcmp ( argv[loop], "-lastmonth" ) == 0 )
set_times_last_month ();
else if ( strcmp ( argv[loop], "-noheader" ) == 0 ||
strcmp ( argv[loop], "-nohdr" ) == 0 )
display_header = FALSE;
else if ( strcmp ( argv[loop], "-rstring" ) == 0 ) {
if ( argv[++loop] == NULL ) {
fprintf ( stderr, "%s : -rstring requires another parameter\n",
argv[0] );
exit ( 1 );
}
retrievals = argv[loop];
}
else if ( *argv[loop] == '-' ) {
fprintf ( stderr, "%s: unrecognized argument \"%s\"\n",
argv[0], argv[loop] );
exit ( 1 );
}
else {
read_file ( argv[loop] );
}
}
/* create output */
generate_gif ();
/* exit */
return ( 0 );
}
/****************************************************************************
*
* Set the time range variables so that we look at data from today only.
*
****************************************************************************/
static void set_times_today ()
{
time_t now;
struct tm *tm;
time ( &now );
tm = localtime ( &now );
sprintf ( start_time, "%02d%02d%02d%02d%02d%02d",
tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 0, 0, 0 );
sprintf ( pretty_start, "%s %02d %s %d %02d:%02d:%02d",
wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
0, 0, 0 );
sprintf ( stop_time, "%02d%02d%02d%02d%02d%02d",
tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 23, 59, 59 );
sprintf ( pretty_stop, "%s %02d %s %d %02d:%02d:%02d",
wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
23, 59, 59 );
}
/****************************************************************************
*
* Set the time range variables so that we look at data from yesterday only.
*
****************************************************************************/
static void set_times_yesterday ()
{
time_t now, yest;
struct tm *tm;
time ( &now );
yest = now - ( 24 * 3600 );
tm = localtime ( &yest );
sprintf ( start_time, "%02d%02d%02d%02d%02d%02d",
tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 0, 0, 0 );
sprintf ( pretty_start, "%s %02d %s %d %02d:%02d:%02d",
wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
0, 0, 0 );
sprintf ( stop_time, "%02d%02d%02d%02d%02d%02d",
tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 23, 59, 59 );
sprintf ( pretty_stop, "%s %02d %s %d %02d:%02d:%02d",
wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
23, 59, 59 );
}
/****************************************************************************
*
* Set the time range variables so that we look at data from last week
* where the week starts on Monday and finishes on Sunday.
*
****************************************************************************/
static void set_times_last_week ()
{
time_t now, lastweek, lastweekstop;
struct tm *tm;
time ( &now );
tm = localtime ( &now );
switch ( tm->tm_wday ) {
case MONDAY:
lastweek = now - ( 7 * ( 24 * 3600 ) ); break;
case TUESDAY:
lastweek = now - ( 8 * ( 24 * 3600 ) ); break;
case WEDNESDAY:
lastweek = now - ( 9 * ( 24 * 3600 ) ); break;
case THURSDAY:
lastweek = now - ( 10 * ( 24 * 3600 ) ); break;
case FRIDAY:
lastweek = now - ( 11 * ( 24 * 3600 ) ); break;
case SATURDAY:
lastweek = now - ( 12 * ( 24 * 3600 ) ); break;
case SUNDAY:
lastweek = now - ( 13 * ( 24 * 3600 ) ); break;
}
tm = localtime ( &lastweek );
sprintf ( start_time, "%02d%02d%02d%02d%02d%02d",
tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 0, 0, 0 );
sprintf ( pretty_start, "%s %02d %s %d %02d:%02d:%02d",
wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
0, 0, 0 );
lastweekstop = lastweek + ( 7 * 24 * 3600 );
tm = localtime ( &lastweekstop );
sprintf ( stop_time, "%02d%02d%02d%02d%02d%02d",
tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 23, 59, 59 );
sprintf ( pretty_stop, "%s %02d %s %d %02d:%02d:%02d",
wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
23, 59, 59 );
}
/****************************************************************************
*
* Set the time range variables so that we look at data from this week
* where the week starts on Monday and finishes on Sunday.
*
****************************************************************************/
static void set_times_this_week ()
{
time_t now, thisweek, thisweekstop;
struct tm *tm;
time ( &now );
tm = localtime ( &now );
switch ( tm->tm_wday ) {
case MONDAY:
thisweek = now - ( 0 * ( 24 * 3600 ) ); break;
case TUESDAY:
thisweek = now - ( 1 * ( 24 * 3600 ) ); break;
case WEDNESDAY:
thisweek = now - ( 2 * ( 24 * 3600 ) ); break;
case THURSDAY:
thisweek = now - ( 3 * ( 24 * 3600 ) ); break;
case FRIDAY:
thisweek = now - ( 4 * ( 24 * 3600 ) ); break;
case SATURDAY:
thisweek = now - ( 5 * ( 24 * 3600 ) ); break;
case SUNDAY:
thisweek = now - ( 6 * ( 24 * 3600 ) ); break;
}
tm = localtime ( &thisweek );
sprintf ( start_time, "%02d%02d%02d%02d%02d%02d",
tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 0, 0, 0 );
sprintf ( pretty_start, "%s %02d %s %d %02d:%02d:%02d",
wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
0, 0, 0 );
thisweekstop = thisweek + ( 7 * 24 * 3600 );
tm = localtime ( &thisweekstop );
sprintf ( stop_time, "%02d%02d%02d%02d%02d%02d",
tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 23, 59, 59 );
sprintf ( pretty_stop, "%s %02d %s %d %02d:%02d:%02d",
wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
23, 59, 59 );
}
/****************************************************************************
*
* Set the time range variables so that we look at data from this month only.
*
****************************************************************************/
static void set_times_this_month ()
{
time_t now, first, last;
struct tm *tm;
/* Figure out the first of the month */
time ( &now );
tm = localtime ( &now );
first = now - ( ( tm->tm_mday - 1 ) * ( 24 * 3600 ) );
/* start of month */
tm = localtime ( &first );
sprintf ( start_time, "%02d%02d%02d%02d%02d%02d",
tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 0, 0, 0 );
sprintf ( pretty_start, "%s %02d %s %d %02d:%02d:%02d",
wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
0, 0, 0 );
/* end of month */
if ( tm->tm_year % 4 == 0 ) {
/* leap year */
last = first + ( ( days_in_lmonth[tm->tm_mon] - 1 ) * 24 * 3600 );
}
else {
last = first + ( ( days_in_month[tm->tm_mon] - 1 ) * 24 * 3600 );
}
tm = localtime ( &last );
sprintf ( stop_time, "%02d%02d%02d%02d%02d%02d",
tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 23, 59, 59 );
sprintf ( pretty_stop, "%s %02d %s %d %02d:%02d:%02d",
wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
23, 59, 59 );
}
/****************************************************************************
*
* Set the time range variables so that we look at data from the month
* prior to the current month.
*
****************************************************************************/
static void set_times_last_month ()
{
time_t now, first, last;
struct tm *tm;
int prev_month;
/* Figure out the 1st of the current month */
time ( &now );
tm = localtime ( &now );
first = now - ( ( tm->tm_mday - 1 ) * ( 24 * 3600 ) );
/* move to the 1st of previous month */
prev_month = tm->tm_mon - 1;
if ( prev_month < 0 )
prev_month = 12;
if ( tm->tm_year % 4 == 0 ) {
/* leap year */
first -= days_in_lmonth[prev_month] * 24 * 3600;
}
else {
first -= days_in_month[prev_month] * 24 * 3600;
}
/* start */
tm = localtime ( &first );
sprintf ( start_time, "%02d%02d%02d%02d%02d%02d",
tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 0, 0, 0 );
sprintf ( pretty_start, "%s %02d %s %d %02d:%02d:%02d",
wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
0, 0, 0 );
/* end of month */
if ( tm->tm_year % 4 == 0 ) {
/* leap year */
last = first + ( ( days_in_lmonth[tm->tm_mon] - 1 ) * 24 * 3600 );
}
else {
last = first + ( ( days_in_month[tm->tm_mon] - 1 ) * 24 * 3600 );
}
tm = localtime ( &last );
sprintf ( stop_time, "%02d%02d%02d%02d%02d%02d",
tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 23, 59, 59 );
sprintf ( pretty_stop, "%s %02d %s %d %02d:%02d:%02d",
wdays[tm->tm_wday], tm->tm_mday, months[tm->tm_mon], tm->tm_year + 1900,
23, 59, 59 );
}
/****************************************************************************
*
* Read in the data file
*
****************************************************************************/
static void read_file ( filename )
char *filename;
{
FILE *fp;
char text[10240];
fp = fopen ( filename, "r" );
if ( ! fp ) {
fprintf ( stderr, "Unable to open log file %s\n", filename );
return;
}
while ( fgets ( text, 10240, fp ) ) {
if ( is_in_time_range ( text ) ) {
/* get hour of day, day of week, and day of month */
add_time ( text );
total++;
}
}
fclose ( fp );
}
/*
** Add the time information so we can report time of day, day of month.
*/
static void add_time ( text )
char *text;
{
char *ptr;
char temp[10];
int int1, loop, month, year, day, hour, weekday, y, m, d;
static int dlook[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
temp[2] = '\0';
/* first get the day of month */
ptr = strstr ( text, "[" );
day = -1;
if ( ! ptr ) {
/* very unexpected. (but expect the unexpected, right?) */
return;
}
strncpy ( temp, ptr + 1, 2 );
if ( isdigit ( temp[0] ) && isdigit ( temp[1] ) ) {
int1 = atoi ( temp );
if ( int1 >= 1 && int1 <= 31 )
day = int1 -1;
}
if ( day < 0 )
return;
/* now get the month */
temp[3] = '\0';
month = -1;
strncpy ( temp, ptr + 4, 3 );
for ( loop = 0; loop < 12; loop++ ) {
if ( strcmp ( months[loop], temp ) == 0 ) {
month = loop; /* remember: Jan=0 */
break;
}
}
if ( month < 0 )
return;
/* now get the year */
temp[4] = '\0';
year = -1;
strncpy ( temp, ptr + 8, 4 );
if ( isdigit ( temp[0] ) && isdigit ( temp[1] ) &&
isdigit ( temp[2] ) && isdigit ( temp[3] ) ) {
int1 = atoi ( temp );
if ( int1 >= 1900 && int1 <= 9999 )
year = int1;
}
if ( year < 0 )
return;
/* now get the hour of day */
temp[2] = '\0';
strncpy ( temp, ptr + 13, 2 );
if ( isdigit ( temp[0] ) && isdigit ( temp[1] ) ) {
int1 = atoi ( temp );
if ( int1 >= 0 && int1 <= 23 )
hour = int1;
}
if ( hour < 0 )
return;
/* determine day of week from a nifty algorithm */
m = month + 1;
y = year;
d = day + 1;
if ( m < 3 )
y--;
weekday = ( y + ( y/4 ) - ( y/100 ) + ( y/400 ) + dlook[m-1] + d ) % 7;
/*
fprintf ( stderr, "%sdow=%s\tmonth=%s\tdom=%d\ttod=%d\n",
text, wdays[weekday], months[month], day + 1, hour );
*/
dow[weekday]++;
tod[hour]++;
moy[month]++;
dom[day]++;
}
/****************************************************************************
*
* Generate the output image
*
****************************************************************************/
#define LEFT_PAD 80
#define TOP_PAD 50
#define RIGHT_PAD 50
#define BOTTOM_PAD 55
#define DATA_WIDTH 15
#define DATA_HEIGHT 200
static void generate_gif ()
{
int loop;
char temp[200];
int maxval;
int lastday;
int x, y, lastx, lasty;
IImage im_out; /* output image */
IFont helvB18, courR10;
IColor red, blue, black, grey;
IGC gc;
int height, width;
/*
** Display day of month data
*/
if ( output_type == DAY_OF_MONTH ) {
/* get max value and last day we have data for */
for ( maxval = 0, loop = 0; loop < 31; loop++ ) {
maxval = max ( maxval, dom[loop] );
if ( dom[loop] )
lastday = loop;
}
maxval = calc_max ( maxval );
/* Create graph output */
width = LEFT_PAD + ( ( lastday + 1 ) * DATA_WIDTH ) + RIGHT_PAD;
width = max ( width, 500 );
height = TOP_PAD + DATA_HEIGHT + BOTTOM_PAD;
}
else if ( output_type == TIME_OF_DAY ) {
/* get max value */
for ( maxval = 0, loop = 0; loop < 24; loop++ ) {
maxval = max ( maxval, tod[loop] );
}
maxval = calc_max ( maxval );
/* Create graph output */
width = LEFT_PAD + ( 24 * DATA_WIDTH ) + RIGHT_PAD;
height = TOP_PAD + DATA_HEIGHT + BOTTOM_PAD;
}
else if ( output_type == DAY_OF_WEEK ) {
/* get max value */
for ( maxval = 0, loop = 0; loop < 7; loop++ ) {
maxval = max ( maxval, dow[loop] );
}
maxval = calc_max ( maxval );
/* Create graph output */
width = LEFT_PAD + ( 7 * DATA_WIDTH * 3 ) + RIGHT_PAD;
height = TOP_PAD + DATA_HEIGHT + BOTTOM_PAD;
}
else if ( output_type == MONTH_OF_YEAR ) {
/* get max value */
for ( maxval = 0, loop = 0; loop < 12; loop++ ) {
maxval = max ( maxval, moy[loop] );
}
maxval = calc_max ( maxval );
/* Create graph output */
width = LEFT_PAD + ( 24 * DATA_WIDTH ) + RIGHT_PAD;
width = max ( width, 500 );
height = TOP_PAD + DATA_HEIGHT + BOTTOM_PAD;
}
/* allocate image */
im_out = ICreateImage ( width, height, IOPTION_NONE );
/* first color is background color */
black = IAllocColor ( 0, 0, 0 );
grey = IAllocColor ( 192, 192, 192 );
ISetTransparent ( im_out, grey );
red = IAllocColor ( 255, 0, 0 );
blue = IAllocColor ( 0, 0, 255 );
gc = ICreateGC ();
ISetForeground ( gc, grey );
IFillRectangle ( im_out, gc, 0, 0, width, height );
/* draw black border */
ISetForeground ( gc, black );
IDrawRectangle ( im_out, gc, 0, 0, width - 1, height - 1 );
/* draw title */
if ( display_header ) {
sprintf ( temp, "WebReport 1.0" );
}
ILoadFontFromData ( "courR10", courR10_font, &courR10 );
ILoadFontFromData ( "helvB18", helvB18_font, &helvB18 );
/* Draw title */
ISetFont ( gc, helvB18 );
ISetForeground ( gc, grey );
IDrawString ( im_out, gc, LEFT_PAD + 81, 31, temp, strlen ( temp ) );
ISetForeground ( gc, black );
IDrawString ( im_out, gc, LEFT_PAD + 80, 30, temp, strlen ( temp ) );
/* write "Retrievals" to the left of the y axis */
ISetFont ( gc, courR10 );
IDrawString ( im_out, gc, 5, TOP_PAD + DATA_HEIGHT / 2 - 5,
retrievals, strlen ( retrievals ) );
/* label the y axis with the top value */
sprintf ( temp, "%12d", maxval );
IDrawString ( im_out, gc, 5, TOP_PAD + 3, temp, strlen ( temp ) );
ISetForeground ( gc, blue );
IDrawLine ( im_out, gc, LEFT_PAD - 3, TOP_PAD, LEFT_PAD, TOP_PAD );
/* draw x and y axis in blue */
IDrawLine ( im_out, gc, LEFT_PAD, TOP_PAD, LEFT_PAD, TOP_PAD + DATA_HEIGHT );
if ( graph_type == LINE )
IDrawLine ( im_out, gc, LEFT_PAD, TOP_PAD + DATA_HEIGHT, width - RIGHT_PAD,
TOP_PAD + DATA_HEIGHT );
else
IDrawLine ( im_out, gc, LEFT_PAD, TOP_PAD + DATA_HEIGHT,
width - RIGHT_PAD + ( DATA_WIDTH / 2 ),
TOP_PAD + DATA_HEIGHT );
/* draw dashed lines horizontally */
ISetLineStyle ( gc, ILINE_ON_OFF_DASH );
for ( loop = 0; loop <= 4; loop++ ) {
y = TOP_PAD + ( ( DATA_HEIGHT / 5 ) * loop );
if ( graph_type == LINE )
IDrawLine ( im_out, gc, LEFT_PAD, y, width - RIGHT_PAD, y );
else
IDrawLine ( im_out, gc, LEFT_PAD, y,
width - RIGHT_PAD + ( DATA_WIDTH / 2 ), y );
}
ISetLineStyle ( gc, ILINE_SOLID );
if ( output_type == DAY_OF_MONTH ) {
/* label this as day of month on x axis */
ISetForeground ( gc, black );
IDrawString ( im_out, gc, LEFT_PAD + 80, height - 35,
"Day of the Month", strlen ( "Day of the Month" ) );
/* now draw a line for each point */
lastx = LEFT_PAD + DATA_WIDTH;
lasty = TOP_PAD + (int)
( ( (double)(maxval - dom[0]) / (double)maxval )
* (double)DATA_HEIGHT );
if ( graph_type == BAR ) {
ISetForeground ( gc, red );
IFillRectangle ( im_out, gc, lastx - ( DATA_WIDTH / 2 ) + 1, lasty,
DATA_WIDTH - 2, ( TOP_PAD + DATA_HEIGHT ) - lasty );
}
/* draw a tic mark */
ISetForeground ( gc, blue );
IDrawLine ( im_out, gc, lastx, TOP_PAD + DATA_HEIGHT, lastx,
TOP_PAD + DATA_HEIGHT + 3 );
ISetForeground ( gc, black );
IDrawString ( im_out, gc, lastx - 2, TOP_PAD + DATA_HEIGHT + 11,
"1", 1 );
for ( loop = 1; loop <= lastday; loop++ ) {
x = LEFT_PAD + ( ( loop + 1 ) * DATA_WIDTH );
y = TOP_PAD + (int)
( ( (double)(maxval - dom[loop]) / (double)maxval )
* (double)DATA_HEIGHT );
/* draw the line graph */
ISetForeground ( gc, red );
if ( graph_type == LINE ) {
ISetLineWidth ( gc, line_width );
IDrawLine ( im_out, gc, lastx, lasty, x, y );
ISetLineWidth ( gc, 1 );
}
else
IFillRectangle ( im_out, gc, x - ( DATA_WIDTH / 2 ) + 1, y,
DATA_WIDTH - 2, ( TOP_PAD + DATA_HEIGHT ) - y );
/* draw a tic mark */
ISetForeground ( gc, blue );
IDrawLine ( im_out, gc, x, TOP_PAD + DATA_HEIGHT, x,
TOP_PAD + DATA_HEIGHT + 3 );
/* label the x axis */
ISetForeground ( gc, black );
sprintf ( temp, "%d", loop + 1 );
if ( loop < 9 )
IDrawString ( im_out, gc, x - 2, TOP_PAD + DATA_HEIGHT + 11,
temp, strlen ( temp ) );
else
IDrawString ( im_out, gc, x - 5, TOP_PAD + DATA_HEIGHT + 11,
temp, strlen ( temp ) );
/* save x and y for the next point */
lastx = x;
lasty = y;
}
}
else if ( output_type == TIME_OF_DAY ) {
/* label this as time of day on x axis */
ISetForeground ( gc, black );
IDrawString ( im_out, gc, LEFT_PAD + 80, height - 35,
"Hour of the Day", strlen ( "Hour of the Day" ) );
/* now draw a line for each point */
lastx = LEFT_PAD + DATA_WIDTH;
lasty = TOP_PAD + (int)
( ( (double)(maxval - tod[0]) / (double)maxval )
* (double)DATA_HEIGHT );
if ( graph_type == BAR ) {
ISetForeground ( gc, red );
IFillRectangle ( im_out, gc, lastx - ( DATA_WIDTH / 2 ) + 1, lasty,
DATA_WIDTH - 2, ( TOP_PAD + DATA_HEIGHT ) - lasty );
}
/* draw a tic mark */
ISetForeground ( gc, blue );
IDrawLine ( im_out, gc, lastx, TOP_PAD + DATA_HEIGHT, lastx,
TOP_PAD + DATA_HEIGHT + 3 );
ISetForeground ( gc, black );
IDrawString ( im_out, gc, lastx - 2, TOP_PAD + DATA_HEIGHT + 11,
"1", 1 );
for ( loop = 1; loop < 24; loop++ ) {
x = LEFT_PAD + ( ( loop + 1 ) * DATA_WIDTH );
y = TOP_PAD + (int)
( ( (double)(maxval - tod[loop]) / (double)maxval )
* (double)DATA_HEIGHT );
/* draw the line graph */
ISetForeground ( gc, red );
if ( graph_type == LINE ) {
ISetLineWidth ( gc, line_width );
IDrawLine ( im_out, gc, lastx, lasty, x, y );
ISetLineWidth ( gc, 1 );
}
else
IFillRectangle ( im_out, gc, x - ( DATA_WIDTH / 2 ) + 1, y,
DATA_WIDTH - 2, ( TOP_PAD + DATA_HEIGHT ) - y );
/* draw a tic mark */
ISetForeground ( gc, blue );
IDrawLine ( im_out, gc, x, TOP_PAD + DATA_HEIGHT, x,
TOP_PAD + DATA_HEIGHT + 3 );
/* label the x axis */
sprintf ( temp, "%d", loop + 1 );
ISetForeground ( gc, black );
if ( loop < 9 )
IDrawString ( im_out, gc, x - 2, TOP_PAD + DATA_HEIGHT + 11,
temp, strlen ( temp ) );
else
IDrawString ( im_out, gc, x - 5, TOP_PAD + DATA_HEIGHT + 11,
temp, strlen ( temp ) );
/* save x and y for the next point */
lastx = x;
lasty = y;
}
}
else if ( output_type == DAY_OF_WEEK ) {
/* label this as time of day on x axis */
ISetForeground ( gc, black );
IDrawString ( im_out, gc, LEFT_PAD + 80, height - 35,
"Day of Week", strlen ( "Day of Week" ) );
/* now draw a line for each point */
lastx = LEFT_PAD + DATA_WIDTH * 3;
lasty = TOP_PAD + (int)
( ( (double)(maxval - tod[0]) / (double)maxval )
* (double)DATA_HEIGHT );
if ( graph_type == BAR ) {
ISetForeground ( gc, red );
IFillRectangle ( im_out, gc, lastx - ( DATA_WIDTH / 2 ) + 1, lasty,
DATA_WIDTH - 2, ( TOP_PAD + DATA_HEIGHT ) - lasty );
}
/* draw a tic mark */
ISetForeground ( gc, blue );
IDrawLine ( im_out, gc, lastx, TOP_PAD + DATA_HEIGHT, lastx,
TOP_PAD + DATA_HEIGHT + 3 );
ISetForeground ( gc, black );
IDrawString ( im_out, gc, lastx - 2, TOP_PAD + DATA_HEIGHT + 11,
"Sun", 3 );
for ( loop = 1; loop < 7; loop++ ) {
x = LEFT_PAD + ( ( loop + 1 ) * DATA_WIDTH * 3 );
y = TOP_PAD + (int)
( ( (double)(maxval - dow[loop]) / (double)maxval )
* (double)DATA_HEIGHT );
/* draw the line graph */
ISetForeground ( gc, red );
if ( graph_type == LINE ) {
ISetLineWidth ( gc, line_width );
IDrawLine ( im_out, gc, lastx, lasty, x, y );
ISetLineWidth ( gc, 1 );
}
else
IFillRectangle ( im_out, gc, x - ( DATA_WIDTH / 2 ) + 1, y,
DATA_WIDTH - 2, ( TOP_PAD + DATA_HEIGHT ) - y );
/* draw a tic mark */
ISetForeground ( gc, blue );
IDrawLine ( im_out, gc, x, TOP_PAD + DATA_HEIGHT, x,
TOP_PAD + DATA_HEIGHT + 3 );
/* label the x axis */
sprintf ( temp, "%s", wdays[loop] );
ISetForeground ( gc, black );
if ( loop < 9 )
IDrawString ( im_out, gc, x - 9, TOP_PAD + DATA_HEIGHT + 11,
temp, strlen ( temp ) );
else
IDrawString ( im_out, gc, x - 12, TOP_PAD + DATA_HEIGHT + 11,
temp, strlen ( temp ) );
/* save x and y for the next point */
lastx = x;
lasty = y;
}
}
else if ( output_type == MONTH_OF_YEAR ) {
/* label this as time of day on x axis */
ISetForeground ( gc, black );
IDrawString ( im_out, gc, LEFT_PAD + 80, height - 35,
"Month of Year", strlen ( "Month of Year" ) );
/* now draw a line for each point */
lastx = LEFT_PAD + DATA_WIDTH * 2;
lasty = TOP_PAD + (int)
( ( (double)(maxval - moy[0]) / (double)maxval )
* (double)DATA_HEIGHT );
if ( graph_type == BAR ) {
ISetForeground ( gc, red );
IFillRectangle ( im_out, gc, lastx - ( DATA_WIDTH / 2 ) + 1, lasty,
DATA_WIDTH - 2, ( TOP_PAD + DATA_HEIGHT ) - lasty );
}
/* draw a tic mark */
ISetForeground ( gc, blue );
IDrawLine ( im_out, gc, lastx, TOP_PAD + DATA_HEIGHT, lastx,
TOP_PAD + DATA_HEIGHT + 3 );
ISetForeground ( gc, black );
IDrawString ( im_out, gc, lastx - 2, TOP_PAD + DATA_HEIGHT + 11,
months[0], strlen ( months[0] ) );
for ( loop = 1; loop < 12; loop++ ) {
x = LEFT_PAD + ( ( loop + 1 ) * DATA_WIDTH * 2 );
y = TOP_PAD + (int)
( ( (double)(maxval - moy[loop]) / (double)maxval )
* (double)DATA_HEIGHT );
/* draw the line graph */
ISetForeground ( gc, red );
if ( graph_type == LINE ) {
ISetLineWidth ( gc, line_width );
IDrawLine ( im_out, gc, lastx, lasty, x, y );
ISetLineWidth ( gc, 1 );
}
else
IFillRectangle ( im_out, gc, x - ( DATA_WIDTH / 2 ) + 1, y,
DATA_WIDTH - 2, ( TOP_PAD + DATA_HEIGHT ) - y );
/* draw a tic mark */
ISetForeground ( gc, blue );
IDrawLine ( im_out, gc, x, TOP_PAD + DATA_HEIGHT, x,
TOP_PAD + DATA_HEIGHT + 3 );
/* label the x axis */
sprintf ( temp, "%s", months[loop] );
ISetForeground ( gc, black );
if ( loop < 9 )
IDrawString ( im_out, gc, x - 9, TOP_PAD + DATA_HEIGHT + 11,
temp, strlen ( temp ) );
else
IDrawString ( im_out, gc, x - 12, TOP_PAD + DATA_HEIGHT + 11,
temp, strlen ( temp ) );
/* save x and y for the next point */
lastx = x;
lasty = y;
}
}
if ( display_header ) {
sprintf ( temp, "Total retrievals for interval: %d", total );
ISetForeground ( gc, black );
IDrawString ( im_out, gc, 5, height - 13, temp, strlen ( temp ) );
if ( strlen ( start_time ) && ! strlen ( stop_time ) )
sprintf ( temp, "Time range: after %s", pretty_start );
else if ( strlen ( stop_time ) && ! strlen ( start_time ) )
printf ( temp, "Time range: prior to %s", pretty_stop );
else if ( strlen ( start_time ) && strlen ( stop_time ) )
sprintf ( temp, "Time range: %s through %s",
pretty_start, pretty_stop );
else
sprintf ( temp, "Time range: all" );
IDrawString ( im_out, gc, 5, height - 23, temp, strlen ( temp ) );
}
/*
** make output interlaced
*/
/*
** Write GIF output file.
*/
IWriteImageFile ( stdout, im_out, IFORMAT_GIF, IOPTION_INTERLACED );
IFreeImage ( im_out );
}
/****************************************************************************
*
* Calculate a nice round number to use as the maximum for the y axis.
*
****************************************************************************/
static int calc_max ( cur_max )
int cur_max; /* the current max value */
{
int ret_val;
int next_round, tens, div_val;
if ( cur_max == 0 )
return ( 1 );
tens = (int) log10 ( (double) cur_max );
next_round = (int) pow ( (double) 10.0, (double) (tens+1) );
div_val = (int) ( next_round / (int) cur_max );
switch ( div_val ) {
case 10:
case 9:
case 8:
case 7:
case 6:
case 5:
next_round /= 5;
break;
case 4:
next_round /= 4;
break;
case 3:
next_round = (int) ( 0.4 * (float) next_round );
break;
case 2:
next_round /= 2;
break;
case 1:
case 0:
break;
}
ret_val = (int) ( max ( 5.0, (float) next_round ) );
if ( ret_val < cur_max )
ret_val = cur_max; /* floating point round error */
return ( ret_val );
}
/****************************************************************************
*
* Check to see if the entry is within our time window
*
****************************************************************************/
static int is_in_time_range ( entry )
char *entry;
{
char *ptr;
int is_after_start, is_before_stop;
int loop;
char entry_time[30];
ptr = strstr ( entry, "[" );
if ( ! ptr )
return ( FALSE );
ptr++;
/* Get year */
strncpy ( entry_time, ptr + 9, 2 );
/* Get month */
for ( loop = 0; loop < 12; loop++ ) {
if ( strncmp ( months[loop], ptr + 3, 3 ) == 0 ) {
sprintf ( entry_time + 2, "%02d", loop + 1 );
break;
}
}
/* Get day */
strncpy ( entry_time + 4, ptr, 2 );
/* Get hour */
strncpy ( entry_time + 6, ptr + 12, 2 );
/* Get minute */
strncpy ( entry_time + 8, ptr + 15, 2 );
/* Get second */
strncpy ( entry_time + 10, ptr + 18, 2 );
/* terminate string */
entry_time[12] = '\0';
if ( ! strlen ( start_time ) ) {
is_after_start = TRUE;
}
else {
is_after_start = ( strcmp ( entry_time, start_time ) > 0 );
}
if ( ! strlen ( stop_time ) ) {
is_before_stop = TRUE;
}
else {
is_before_stop = ( strcmp ( stop_time, entry_time ) > 0 );
}
if ( is_after_start && is_before_stop ) {
return ( TRUE );
}
else
return ( FALSE );
}