ifraggraph.c
资源名称:ilib [点击查看]
上传用户:changbiao
上传日期:2007-01-13
资源大小:141k
文件大小:10k
源码类别:

图片显示

开发平台:

C/C++

  1. /*
  2.   Report generator for QuakeWorld frag log file
  3.   Usage:
  4.     frag_graph player fraglogfile [fraglogfile ...] > out.gif
  5.   NOTE:
  6.     Player names are case-sensitive!
  7.   18-May-98 Craig Knudsen cknudsen@radix.net
  8. Better error handling of command line args
  9. Don't crash if user not found in logs
  10.   23-May-97 Craig Knudsen cknudsen@radix.net
  11. Created
  12. ***************************************************************************/
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <time.h>
  17. #include <ctype.h>
  18. #include <math.h>
  19. #include <values.h>
  20. #include <sys/types.h>
  21. #include <sys/time.h>
  22. #include <Ilib.h>
  23. #include "helvB18.h"
  24. #include "courR10.h"
  25. #ifndef min
  26. #define min(a,b) ( (a) < (b) ? (a) : (b) )
  27. #define max(a,b) ( (a) > (b) ? (a) : (b) )
  28. #endif
  29. #ifndef TRUE
  30. #define TRUE 1
  31. #define FALSE 0
  32. #endif
  33. #define FRAG 1
  34. #define DEATH 2
  35. #define SUICIDE 3
  36. static void read_file (
  37. #ifndef _NO_PROTO
  38.   char *filename
  39. #endif
  40. );
  41. static void add_stat (
  42. #ifndef _NO_PROTO
  43.   int type
  44. #endif
  45. );
  46. static void generate_gif ();
  47. static int calc_max (
  48. #ifndef _NO_PROTO
  49.   int cur_max
  50. #endif
  51. );
  52. /*
  53. ** Define start and stop times.  Use YYMMDDHHMMSS so that we can just
  54. ** use strcmp() to compare times.
  55. */
  56. static char *player = NULL;
  57. static int *stats = NULL;
  58. static int num_stats = 0; /* total number of frags counted */
  59. static int display_header = TRUE;
  60. static int line_width = 2; /* for line graphs (can use 1-3) */
  61. /*
  62. ** Main
  63. */
  64. int main ( argc, argv )
  65. int argc;
  66. char *argv[];
  67. {
  68.   int loop;
  69.   stats = (int *) malloc ( 1 );
  70.   for ( loop = 1; loop < argc; loop++ ) {
  71.     if ( *argv[loop] == '-' ) {
  72.       fprintf ( stderr, "%s: unrecognized argument "%s"n",
  73.         argv[0], argv[loop] );
  74.       exit ( 1 );
  75.     }
  76.     else if ( player == NULL ) {
  77.       player = argv[loop];
  78.     }
  79.     else {
  80.       read_file ( argv[loop] );
  81.     }
  82.   }
  83.   if ( player == NULL ) {
  84.     fprintf ( stderr, "Usage: frag_frag playername frag_1.log ...n" );
  85.     exit ( 1 );
  86.   }
  87.   /* create output */
  88.   generate_gif ();
  89.   /* exit */
  90.   return ( 0 );
  91. }
  92. /****************************************************************************
  93. *
  94. * Read in the data file
  95. *
  96. ****************************************************************************/
  97. static void read_file ( filename )
  98. char *filename;
  99. {
  100.   FILE *fp;
  101.   char text[1024], *ptr;
  102.   fp = fopen ( filename, "r" );
  103.   if ( ! fp ) {
  104.     fprintf ( stderr, "Unable to open log file %sn", filename );
  105.     return;
  106.   }
  107.   while ( fgets ( text, 10240, fp ) ) {
  108.     ptr = strtok ( text, "\" );
  109.     if ( ! ptr )
  110.       continue;
  111.     if ( strcmp ( player, ptr ) == 0 ) {
  112.       ptr = strtok ( NULL, "\" );
  113.       if ( ! ptr )
  114.         continue;
  115.       if ( strcmp ( player, ptr ) == 0 )
  116.         add_stat ( SUICIDE );
  117.       else
  118.         add_stat ( FRAG );
  119.     } else {
  120.       ptr = strtok ( NULL, "\" );
  121.       if ( ! ptr )
  122.         continue;
  123.       if ( strcmp ( player, ptr ) == 0 )
  124.         add_stat ( DEATH );
  125.     }
  126.   }
  127.   fclose ( fp );
  128. }
  129. static void add_stat ( type )
  130. int type;
  131. {
  132.   num_stats++;
  133.   stats = (int *) realloc ( stats, ( num_stats * sizeof ( int * ) ) );
  134.   stats[num_stats-1] = type;
  135. }
  136. /****************************************************************************
  137. *
  138. * Generate the output image
  139. *
  140. ****************************************************************************/
  141. #define LEFT_PAD 80
  142. #define TOP_PAD 50
  143. #define RIGHT_PAD 50
  144. #define BOTTOM_PAD 75
  145. #define DATA_WIDTH 20
  146. #define DATA_HEIGHT 200
  147. static void generate_gif ()
  148. {
  149.   int loop;
  150.   char temp[200];
  151.   int x, y, lastx, lasty;
  152.   int r_x, r_y, r_lastx, r_lasty;
  153.   IImage im_out; /* output image */
  154.   IFont helvB18, courR10;
  155.   IColor red, green, blue, black, grey;
  156.   IGC gc;
  157.   int height, width;
  158.   int max_gibs;
  159.   int gib_step, column;
  160.   int frags = 0, deaths = 0, suicides = 0;
  161.   int r_frags = 0, r_deaths = 0, r_suicides = 0;
  162.   double eff;
  163.   max_gibs = calc_max ( num_stats );
  164.   gib_step = max_gibs / 20;
  165.   width = LEFT_PAD + ( 20 * DATA_WIDTH ) + RIGHT_PAD;
  166.   height = TOP_PAD + DATA_HEIGHT + BOTTOM_PAD;
  167.   /* allocate image */
  168.   im_out = ICreateImage ( width, height, IOPTION_NONE );
  169.   /* first color is background color */
  170.   black = IAllocColor ( 0, 0, 0 );
  171.   grey = IAllocColor ( 192, 192, 192 );
  172.   ISetTransparent ( im_out, grey );
  173.   red = IAllocColor ( 255, 0, 0 );
  174.   green = IAllocColor ( 0, 150, 0 );
  175.   blue = IAllocColor ( 0, 0, 255 );
  176.   gc = ICreateGC ();
  177.   ISetForeground ( gc, grey );
  178.   IFillRectangle ( im_out, gc, 0, 0, width, height );
  179.   /* draw black border */
  180.   ISetForeground ( gc, black );
  181.   IDrawRectangle ( im_out, gc, 0, 0, width - 1, height - 1 );
  182.   /* draw title */
  183.   sprintf ( temp, "Frag Efficiency Graph 1.0: %s", player );
  184.   ILoadFontFromData ( "courR10", courR10_font, &courR10 );
  185.   ILoadFontFromData ( "helvB18", helvB18_font, &helvB18 );
  186.   
  187.   /* Draw title */
  188.   ISetFont ( gc, helvB18 );
  189.   ISetForeground ( gc, grey );
  190.   IDrawString ( im_out, gc, LEFT_PAD + 31, 31, temp, strlen ( temp ) );
  191.   ISetForeground ( gc, black );
  192.   IDrawString ( im_out, gc, LEFT_PAD + 30, 30, temp, strlen ( temp ) );
  193.   /* write "Efficiency" to the left of the y axis */
  194.   ISetFont ( gc, courR10 );
  195.   IDrawString ( im_out, gc, 5, TOP_PAD + DATA_HEIGHT / 2 - 5,
  196.     "Efficiency", strlen ( "Efficiency" ) );
  197.   /* label the y axis  with the top value */
  198.   strcpy ( temp, "100%" );
  199.   IDrawString ( im_out, gc, 5, TOP_PAD + 3, temp, strlen ( temp ) );
  200.   ISetForeground ( gc, blue );
  201.   IDrawLine ( im_out, gc, LEFT_PAD - 3, TOP_PAD, LEFT_PAD, TOP_PAD );
  202.   /* draw x and y axis in blue */
  203.   IDrawLine ( im_out, gc, LEFT_PAD, TOP_PAD, LEFT_PAD, TOP_PAD + DATA_HEIGHT );
  204.   IDrawLine ( im_out, gc, LEFT_PAD, TOP_PAD + DATA_HEIGHT, width - RIGHT_PAD,
  205.     TOP_PAD + DATA_HEIGHT );
  206.   /* draw dashed lines horizontally */
  207.   ISetLineStyle ( gc, ILINE_ON_OFF_DASH );
  208.   for ( loop = 0; loop <= 10; loop++ ) {
  209.     y = TOP_PAD + ( ( DATA_HEIGHT / 10 ) * loop );
  210.     IDrawLine ( im_out, gc, LEFT_PAD, y, width - RIGHT_PAD, y );
  211.   }
  212.   ISetLineStyle ( gc, ILINE_SOLID );
  213.   ISetForeground ( gc, black );
  214.   IDrawString ( im_out, gc, LEFT_PAD + 80, height - BOTTOM_PAD + 22,
  215.     "Frags + Deaths + Suicides", strlen ( "Frags + Deaths + Suicides" ) );
  216.   column = 0;
  217.   for ( loop = 0; loop <= num_stats; loop++ ) {
  218.     switch ( stats[loop] ) {
  219.       case FRAG: frags++; r_frags++; break;
  220.       case DEATH: deaths++; r_deaths++; break;
  221.       case SUICIDE: suicides++; r_suicides++; break;
  222.     }
  223.     if ( gib_step && loop % gib_step == 0 && loop ) {
  224.       column++;
  225.       r_x = x = LEFT_PAD + ( DATA_WIDTH * column );
  226.       eff = ( (double)frags / (double) loop );
  227.       y = TOP_PAD + (int)
  228.         ( (double)( 1.0 - eff ) * (double)DATA_HEIGHT );
  229.       eff = ( (double)r_frags / (double)gib_step );
  230.       r_y = TOP_PAD + (int)
  231.         ( (double)( 1.0 - eff ) * (double)DATA_HEIGHT );
  232.       /* draw the line graph */
  233.       if ( column > 1 ) {
  234.         ISetForeground ( gc, red );
  235.         ISetLineWidth ( gc, line_width );
  236.         IDrawLine ( im_out, gc, lastx, lasty, x, y );
  237.         ISetLineWidth ( gc, 1 );
  238.         ISetForeground ( gc, green );
  239.         ISetLineWidth ( gc, line_width );
  240.         IDrawLine ( im_out, gc, r_lastx, r_lasty, r_x, r_y );
  241.         ISetLineWidth ( gc, 1 );
  242.       }
  243.       /* draw a tic mark */
  244.       ISetForeground ( gc, blue );
  245.       IDrawLine ( im_out, gc, x, TOP_PAD + DATA_HEIGHT, x, 
  246.         TOP_PAD + DATA_HEIGHT + 3 );
  247.       /* label the x axis */
  248.       if ( column % 2 == 0 ) {
  249.         ISetForeground ( gc, black );
  250.         sprintf ( temp, "%d", loop );
  251.         IDrawString ( im_out, gc, x - 5, TOP_PAD + DATA_HEIGHT + 11,
  252.            temp, strlen ( temp ) );
  253.       }
  254.       /* save x and y for the next point */
  255.       lastx = x;
  256.       lasty = y;
  257.       r_lastx = r_x;
  258.       r_lasty = r_y;
  259.       r_deaths = r_frags = r_suicides = 0;
  260.     }
  261.   }
  262.   if ( display_header ) {
  263.     sprintf ( temp, "Total gibs for interval: %d", num_stats );
  264.     ISetForeground ( gc, black );
  265.     IDrawString ( im_out, gc, 5, height - 38, temp, strlen ( temp ) );
  266.   }
  267.   ISetForeground ( gc, red );
  268.   IFillRectangle ( im_out, gc, 5, height - 33, 10, 10 );
  269.   sprintf ( temp, "Cumulative efficiency" );
  270.   IDrawString ( im_out, gc, 20, height - 23, temp, strlen ( temp ) );
  271.   ISetForeground ( gc, green );
  272.   IFillRectangle ( im_out, gc, 5, height - 20, 10, 10 );
  273.   sprintf ( temp, "Efficiency over last %d gibs", gib_step );
  274.   IDrawString ( im_out, gc, 20, height - 10, temp, strlen ( temp ) );
  275.   /*
  276.   ** make output interlaced
  277.   */
  278.   /*
  279.   ** Write GIF output file.
  280.   */
  281.   IWriteImageFile ( stdout, im_out, IFORMAT_GIF, IOPTION_INTERLACED );
  282.   IFreeImage ( im_out );
  283. }
  284. /****************************************************************************
  285. *
  286. * Calculate a nice round number to use as the maximum for the y axis.
  287. *
  288. ****************************************************************************/
  289. static int calc_max ( cur_max )
  290. int cur_max;  /* the current max value */
  291. {
  292.   int ret_val;
  293.   int next_round, tens, div_val;
  294.   if ( cur_max == 0 )
  295.     return ( 1 );
  296.   tens = (int) log10 ( (double) cur_max );
  297.   next_round = (int) pow ( (double) 10.0, (double) (tens+1) );
  298.   if ( next_round % 10 == 9 )
  299.     next_round++; // strange behavior under Linux
  300.   div_val = (int) ( next_round / (int) cur_max );
  301.   switch ( div_val ) {
  302.     case 10:
  303.     case 9:
  304.     case 8:
  305.     case 7:
  306.     case 6:
  307.     case 5:
  308.     next_round /= 5;
  309.       break;
  310.     case 4:
  311.       next_round /= 4;
  312.       break;
  313.     case 3:
  314.       next_round = (int) ( 0.4 * (float) next_round );
  315.       break;
  316.     case 2:
  317.       next_round /= 2;
  318.       break;
  319.     case 1:
  320.     case 0:
  321.       break;
  322.   }
  323.   ret_val = (int) ( max ( 5.0, (float) next_round ) );
  324.   if ( ret_val < cur_max )
  325.     ret_val = cur_max; /* floating point round error */
  326.   return ( ret_val );
  327. }