home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2897 / line.c next >
Encoding:
C/C++ Source or Header  |  1991-03-01  |  7.1 KB  |  357 lines

  1. /*+
  2.  * File: line.c
  3.  *
  4.  * Description: Produce a line graph using pic and troff.
  5.  *
  6.  * This module is the property of McCaw Cellular Communications, Inc
  7.  * Copyright 1990, all rights reserved
  8.  *
  9.  * Audit Trail:
  10.  *   Original Author and Date: Dan Flak - 13 Jul 1990.
  11.  *
  12. -*/
  13. #ifdef VERSION
  14. static char *SCCS = "%Z% %M% %I% %G% %U%"
  15. #endif
  16.  
  17. /* #includes */
  18. #include <stdio.h>
  19.  
  20. /* #defines  */
  21. #define SAY printf
  22. #define BACKSLASH '\134'
  23.  
  24. /* external variables */
  25. extern char *optarg;
  26. extern int  optind;
  27. extern int  opterr;
  28. extern int  optopt;
  29.  
  30. /* referenced external functions */
  31. float atof();
  32.  
  33. /* internal functions */
  34. int basemonth();
  35.  
  36.  
  37. /* global variables   */
  38.  
  39. struct record
  40.     {
  41.     char  mdate[5];
  42.     float f;
  43.     char  m[8];
  44.     } rec[12];
  45.  
  46. float data_x;
  47. float data_x2;
  48. float data_y;
  49. float data_y2;
  50. float data_xy;
  51.  
  52. float newx, newy, oldx, oldy;
  53. float factor1, factor2, factor3;
  54. float m, b, bmonth;
  55.  
  56. float lower = 0, upper = 100, lineat = 10, hbar, eachmo;
  57. char title[80];
  58. int nrecs = 0; int npts = 0;
  59.  
  60. char *month[12] =
  61.     {
  62.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  63.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  64.     };
  65.  
  66. FILE *fin, *fopen();
  67.  
  68.  
  69. /* static variables   */
  70.  
  71.  
  72. /*<
  73.  * Function: main
  74.  *
  75.  * Description: Parse the data and make a pic file
  76.  *
  77.  * Data Type: int
  78.  *
  79.  * Arguments: 
  80.  *   argv[] = input file name
  81.  *
  82.  *    Flags
  83.  *    -l    lower limit
  84.  *    -u    upper limit
  85.  *    -i    increment
  86.  *    -t    title string
  87.  *
  88.  * Returns:
  89.  *
  90.  * Side Effects:
  91.  *
  92.  * Calls:
  93.  *
  94.  * PDL
  95.  *
  96. >*/
  97.  
  98. int
  99. main (argc, argv)
  100. int  argc;
  101. char *argv[];
  102. {
  103. int i, k, nfound;
  104. int c;
  105. float range, perinch;
  106. char linebuf[1000];
  107. *title = '\0';
  108.  
  109. while ((c = getopt (argc, argv, "i:l:u:t:")) != EOF)
  110.     {
  111.     switch (c)
  112.         {
  113.         case 'i':
  114.             lineat = atof (optarg);
  115.         break;
  116.         case 'l':
  117.             lower = atof (optarg);
  118.         break;
  119.         case 'u':
  120.             upper = atof (optarg);
  121.         break;
  122.         case 't':
  123.             sprintf (title, "%s", optarg);
  124.         break;
  125.         default:
  126.             ;
  127.         break;
  128.         }
  129.     }
  130.  
  131. if (argc < 2)
  132.     {
  133.     fprintf (stderr, 
  134. "syntax: %s [-i increment] [-l lower limit] [-u upper limit] [-t title]\n",
  135.     argv[0]);
  136.     fprintf (stderr, "        <data file>\n");
  137.     exit (0);
  138.     }
  139.  
  140. /*  Read data file */
  141. if ((fin = fopen (argv[optind], "r")) == NULL)
  142.     {
  143.     fprintf (stderr, "%s: can't open %s\n", argv[0], argv[1]);
  144.     exit (-1);
  145.     }
  146.  
  147.  
  148. while (fgets (linebuf, 1000, fin) != NULL)
  149.     {
  150.     nfound = sscanf (linebuf, "%[^|]|%[^'\n']",
  151.         rec[nrecs].mdate, rec[nrecs].m);
  152.     /* SAY ("nfound = %d / %2d - %s | %s\n", 
  153.         nfound, nrecs, rec[nrecs].mdate, rec[nrecs].m); */
  154.     if (nfound == 2)
  155.         {
  156.         if (strcmp (rec[nrecs].m, "ND"))
  157.             {
  158.             rec[nrecs].f = atof (rec[nrecs].m);
  159.             }
  160.         else
  161.             {
  162.             rec[nrecs].f = -1;
  163.             }
  164.         nrecs++;
  165.         if (nrecs > 12 )
  166.             {
  167.             fprintf (stderr, 
  168.                 "%s: Can only accomodate a maximum of 12 data points\n",
  169.                 argv[0]);
  170.             exit (-1);    
  171.             }
  172.         }
  173.     }
  174.  
  175. fclose (fin);
  176.  
  177. /*  Check upper and lower bounds  */
  178.  
  179. for (i = 0; i < nrecs; i++)
  180.     {
  181.     if (rec[i].f < lower && rec[i].f != -1)
  182.         {
  183.         fprintf (stderr, "Warning: lower limit exceeded %s\n", 
  184.             rec[i].mdate);
  185.         }
  186.  
  187.     if (rec[i].f > upper)
  188.         {
  189.         fprintf (stderr, "Warning: upper limit exceeded %s\n",
  190.             rec[i].mdate);
  191.         }
  192.     }
  193.  
  194.  
  195. /*  Build the file that will plot the graph  */
  196.  
  197. printf (".de )k\n..\n");
  198. printf (".PH\n");
  199. printf (".ps 12\n");
  200. printf (".vs 12\n");
  201.     data_x = 0; data_x2 = 0; data_y = 0; data_y2 = 0; data_xy = 0;
  202.     printf (".ce 3\n");
  203.     printf ("%cs+4%cfB%s%cfP%cs0\n", 
  204.         BACKSLASH, BACKSLASH, title, BACKSLASH, BACKSLASH);
  205.     printf (".br\n");
  206.     printf (".DS CB\n");
  207.     printf (".PS\n");
  208.     printf ("\n# set invisible refernece box\n");
  209.     printf ("boxht = 3.45; boxwid = 4.65\n");
  210.     printf ("move to (0, -2.5); OB: box invis\n");
  211.     printf ("\n# workaround for bug in 'old' pic\n");
  212.     printf ("%c   %c at OB.nw + (0, .2)\n", '"', '"');
  213.     printf ("%c   %c at OB.sw\n", '"', '"');
  214.     printf ("\n# Print horizontal axis\n");
  215.     printf ("HA: line from OB.sw to OB.se\n");
  216.     printf ("\n# Print vertical axis\n");
  217.     printf ("VA: line from OB.nw to OB.sw\n");
  218.     range = upper - lower;
  219.     if (range == 0)
  220.         {
  221.         fprintf (stderr, 
  222.             "Warning: range = 0. Sorry, Dave, I can't do that\n");
  223.         exit (-1);
  224.         }
  225.     perinch = 3.45 / range;
  226.     SAY ("# range = %f, perinch = %f\n", range, perinch);
  227.     printf ("\n# put in horizontal scale marks\n");
  228.     printf ("%c%4.1f%c rjust at OB.sw + (-.1, 0)\n", '"', lower, '"');
  229.     hbar = lower + lineat;
  230.     eachmo = 4.65 / 11;
  231.     while (hbar <= upper)
  232.         {
  233.         printf ("line right 4.65 at OB.sw + (0, %f) dashed; ", 
  234.             (hbar  - lower) * perinch);
  235.         printf ("%c%4.1f%c rjust at OB.sw + (-.1, %f)\n",
  236.             '"', hbar, '"', (hbar - lower) * perinch);
  237.         hbar += lineat;
  238.         }
  239.     printf ("\n# Put in vertical scale marks\n");
  240.     for (i = 0; i < nrecs; i++)
  241.         {
  242.         k = atoi (rec[i].mdate + 2) - 1;
  243.         printf ("%c%s%c at OB.sw + (%f, -.1); ",
  244.             '"', month[k], '"', i * eachmo);
  245.         printf ("%c%s%c at OB.sw + (%f, 3.60)\n", 
  246.             '"', rec[i].m, '"', i * eachmo);
  247.         }
  248.     putchar ('\n');
  249.     for (i = 1; i < nrecs; i++)
  250.         {
  251.         if (lineat == 0)
  252.             {
  253.             lineat = 1;
  254.             }
  255.         printf ("line from OB.sw + (%f, 0) to OB.sw + (%f, 3.45) dotted %f\n",
  256.             i * eachmo, i * eachmo, perinch * lineat / 10);
  257.         }
  258.     printf ("\n# Drawing Actual lines\n");
  259.     oldx = -1; oldy = -1;
  260.     for (i = 0; i < nrecs; i++)
  261.         {
  262.         if (rec[i].f != -1)
  263.             {
  264.             newx = i * eachmo;
  265.             newy = (rec[i].f - lower) * perinch;
  266.             if (oldx != -1)
  267.                 {
  268.                 printf ("line from OB.sw + (%f, %f) to OB.sw + (%f, %f)\n",
  269.                     oldx, oldy, newx, newy);
  270.                 }
  271.             oldx = newx; oldy = newy;
  272.             }
  273.         }
  274.     printf ("\n# Drawing trend lines\n");
  275.     npts = 0;
  276.     for (i = 0; i < nrecs; i++)
  277.         {
  278.         if (rec[i].f != -1)
  279.             {
  280.             bmonth = basemonth (rec[i].mdate);
  281.             /* SAY ("%s = %d\n", rec[i].mdate, bmonth); */
  282.             data_x  += bmonth;
  283.             data_x2 += bmonth * bmonth;
  284.             data_y  += rec[i].f;
  285.             data_y2 += rec[i].f * rec[i].f;
  286.             data_xy += bmonth * rec[i].f;
  287.             npts++;
  288.             }
  289.         }
  290.     factor1 = npts * data_x2 - data_x * data_x;
  291.     factor2 = npts * data_y2 - data_y * data_y;
  292.     factor3 = npts * data_xy - data_x * data_y;
  293.     if (factor1 != 0)
  294.         {
  295.         m = factor3 / factor1;
  296.         }
  297.     else
  298.         {
  299.         fprintf (stderr, "Warning: slope not calcualted for %d\n");
  300.         m = 0;
  301.         }
  302.  
  303.     if (npts != 0)
  304.         {
  305.         b = (data_y - m * data_x) / npts;
  306.         }
  307.     else
  308.         {
  309.         fprintf (stderr, "Warning: intercept not calculated\n");
  310.         b = (upper - lower) / 2;
  311.         }
  312.     printf ("\n# Slope = %f, Intercept = %f\n", m, b);
  313.     printf ("line from OB.sw + (0, %f) to OB.sw + (4.65, %f) dotted\n",
  314.         (m * basemonth (rec[0].mdate) + b - lower) * perinch,
  315.         (m * basemonth (rec[nrecs - 1].mdate) + b -lower) * perinch);
  316.  
  317.     printf ("\n# Put in ledgend\n");
  318.     printf ("line right 1.0 at HA.start + (0.5, -.333)\n %c Actual%c ljust\n", 
  319.         '"', '"');
  320.     printf ("move right 1.0\n");
  321.     printf ("line right 1.0  dotted\n %c  Trend%c ljust\n", '"', '"');
  322.     printf (".PE\n");
  323.     printf (".DE\n");
  324.     printf (".bp\n");
  325. }
  326.  
  327. /*<
  328.  * Function: basemonth (yymm)
  329.  *
  330.  * Description: Feed it a YYMM and it will give you number of months
  331.  *   since 8901.
  332.  *
  333.  * Data Type: int
  334.  *
  335.  * Arguments:
  336.  *    yymm = the date to convert
  337.  *
  338.  * Returns:
  339.  *    The number of months since 8901
  340.  *
  341.  * Side Effects:
  342.  *
  343.  * Calls:
  344.  *
  345.  * PDL:
  346.  *
  347. >*/
  348.  
  349. int
  350. basemonth (yymm)
  351. char *yymm;
  352. {
  353. int zzzz;
  354. zzzz = atoi (yymm);
  355. return (12 * ((zzzz - 8901) / 100) + (zzzz - 8901) % 100) ;
  356. }
  357.