/* $Id: biorythm.c,v 1.3 2002/03/02 21:31:53 sverrehu Exp $ */ /*------------------------------------------------------------------------ | FILE biorythm.c | MODULE OF biorythm - simple biorythm calculation program | | DESCRIPTION | | WRITTEN BY Sverre H. Huseby +----------------------------------------------------------------------*/ #include #include #include #include #include #include "date.h" #ifndef M_PI # define M_PI 3.141592654 #endif /* Periods: Physical, Emotional and Intellectual */ #define PHY_PERIOD 23 #define EMO_PERIOD 28 #define INT_PERIOD 33 #define PLOT_PHY 1 #define PLOT_EMO 2 #define PLOT_INT 4 #define PLOT_AVG 8 /*-----------------------------------------------------------------------+ | PRIVATE FUNCTIONS | +-----------------------------------------------------------------------*/ /*------------------------------------------------------------------------ | NAME f | | FUNCTION Calculate a curve sample value. | | INPUT birth date of birth. | day the day to get sample from. | period the period of the curve in days. | | RETURNS A value in [-1, 1]. */ static double f(Date birth, Date day, int period) { int n; n = dateGetNumDays(birth, day) % period; return sin((double) n * 2.0 * M_PI / period); } /*------------------------------------------------------------------------ | NAME round | | FUNCTION Round a double to the nearest integer. | | INPUT x the double to round. | | RETURNS The nearest integer. */ static int round(double x) { return (int) floor(x + 0.5); } /*------------------------------------------------------------------------ | NAME bioTextPlot | | FUNCTION Make a biorythm graph using text characters. | | INPUT birth date of birth. | from date of first day of plot. | ndays number of days to plot. | what what to plot. (PLOT_PHY | PLOT_EMO ...) */ static void bioTextPlot(Date birth, Date from, int ndays, int what) { #define WIDTH 53 int q; char s[WIDTH + 1]; double val, sum; printf("Day of birth: %s\n", dateStr(birth)); if (what & PLOT_PHY) printf("[P]hysical "); if (what & PLOT_EMO) printf("[E]motional "); if (what & PLOT_INT) printf("[I]ntellectual "); if (what & PLOT_AVG) printf("[A]verage"); printf("\n"); for (q = 0; q < 73; q++) printf("-"); printf("\n"); printf("YYYY-MM-DD down%57s\n", "up age"); for (q = 0; q < 73; q++) printf("-"); printf("\n"); while (--ndays >= 0) { for (q = 0; q <= WIDTH; q++) s[q] = ' '; s[q] = '\0'; s[0] = s[WIDTH] = '|'; s[WIDTH / 2] = '.'; printf("%-10.10s ", dateStr(from)); sum = val = f(birth, from, PHY_PERIOD); if (what & PLOT_PHY) s[round(((val + 1.0) / 2.0) * WIDTH)] = 'P'; val = f(birth, from, EMO_PERIOD); sum += val; if (what & PLOT_EMO) s[round(((val + 1.0) / 2.0) * WIDTH)] = 'E'; val = f(birth, from, INT_PERIOD); sum += val; if (what & PLOT_INT) s[round(((val + 1.0) / 2.0) * WIDTH)] = 'I'; if (what & PLOT_AVG) s[round((((sum / 3.0) + 1.0) / 2.0) * WIDTH)] = 'A'; printf("%s %5d\n", s, dateGetNumDays(birth, from)); dateInc(&from); } } /*------------------------------------------------------------------------ | NAME version | | FUNCTION Show the version of this program, and exit. */ static void version(void) { printf( "biorythm " VERSION ", by Sverre H. Huseby\n" ); exit(0); } /*------------------------------------------------------------------------ | NAME usage | | FUNCTION Show the usage of this program, and exit. */ static void usage(void) { printf( "\n" "usage: %s [option] date-of-birth first-day-of-plot number-of-days\n" "\n" " -a, --average plot the average of all three curves\n" " -e, --emotional plot the emotional curve (default)\n" " -h, --help display this help and exit\n" " -i, --intellectual plot the intellectual curve (default)\n" " -p, --physical plot the physical curve (default)\n" " -V, --version output version information and exit\n" "\n" "Dates must be specified as YYYY-MM-DD (ISO date format).\n" "\n", msgGetName() ); exit(0); } /*-----------------------------------------------------------------------+ | PUBLIC FUNCTIONS | +-----------------------------------------------------------------------*/ int main(int argc, char *argv[]) { int ndays = 0, what = 0; int average = 0, emotional = 0, intellectual = 0, physical = 0; Date birth, from; optStruct opt[] = { /* short long type var/func special */ { 'h', "help", OPT_FLAG, usage, OPT_CALLFUNC }, { 'a', "average", OPT_FLAG, &average, 0 }, { 'e', "emotional", OPT_FLAG, &emotional, 0 }, { 'i', "intellectual", OPT_FLAG, &intellectual, 0 }, { 'p', "physical", OPT_FLAG, &physical, 0 }, { 'V', "version", OPT_FLAG, version, OPT_CALLFUNC }, { 0, 0, OPT_END, 0, 0 } /* no more options */ }; msgSetName(argv[0]); optParseOptions(&argc, argv, opt, 0); if (argc != 4) usage(); if (average) what |= PLOT_AVG; if (emotional) what |= PLOT_EMO; if (intellectual) what |= PLOT_INT; if (physical) what |= PLOT_PHY; if (!what) what = PLOT_EMO | PLOT_INT | PLOT_PHY; birth = dateFromStr(argv[1]); from = dateFromStr(argv[2]); ndays = atoi(argv[3]); if (ndays < 1 || ndays > 500) msgFatal("number of days must be in [1, 500]\n"); bioTextPlot(birth, from, ndays, what); return 0; }