From dde7624c6bbf9df02fe251c6706a4625344271d6 Mon Sep 17 00:00:00 2001 From: Paul Janzen Date: Sun, 6 Sep 1998 12:29:26 +0000 Subject: Use formulae from newer edition of Duffett-Smith's book (and acknowledge in man page) Allow command-line selection of dates other than now Use M_PI Fix bug occurring just before a new or full moon. --- games/pom/pom.6 | 24 +++++++- games/pom/pom.c | 187 +++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 164 insertions(+), 47 deletions(-) (limited to 'games/pom') diff --git a/games/pom/pom.6 b/games/pom/pom.6 index 3529a465bde..69140130819 100644 --- a/games/pom/pom.6 +++ b/games/pom/pom.6 @@ -1,4 +1,4 @@ -.\" $NetBSD: pom.6,v 1.4 1995/03/23 08:35:35 cgd Exp $ +.\" $OpenBSD: pom.6,v 1.2 1998/09/06 12:29:23 pjanzen Exp $ .\" .\" Copyright (c) 1989, 1993 .\" The Regents of the University of California. All rights reserved. @@ -40,10 +40,28 @@ .Nm pom .Nd display the phase of the moon .Sh SYNOPSIS -.Nm pom +.Nm +.Op [[[[[cc]yy]mm]dd]HH] .Sh DESCRIPTION The -.Nm pom +.Nm utility displays the current phase of the moon. Useful for selecting software completion target dates and predicting managerial behavior. +.Pp +.Bl -tag -width [[[[[cc]yy]mm]dd]HH] +.It Ar [[[[[cc]yy]mm]dd]HH] +Display the phase of the moon for a given time. The format is similar to +the canonical representation used by +.Xr date 1 . +.El +.Sh SEE ALSO +.Xr date 1 +.Sh BUGS +Times must be within range of the +.Ux +epoch. +.Sh ACKNOWLEDGEMENTS +This program is based on routines from +.%B Practical Astronomy with Your Calculator, Third Edition +by Peter Duffett-Smith. diff --git a/games/pom/pom.c b/games/pom/pom.c index 50201e4cf2c..d05529306c8 100644 --- a/games/pom/pom.c +++ b/games/pom/pom.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pom.c,v 1.5 1998/07/26 06:27:39 pjanzen Exp $ */ +/* $OpenBSD: pom.c,v 1.6 1998/09/06 12:29:25 pjanzen Exp $ */ /* $NetBSD: pom.c,v 1.6 1996/02/06 22:47:29 jtc Exp $ */ /* @@ -46,7 +46,7 @@ static char copyright[] = #if 0 static char sccsid[] = "@(#)pom.c 8.1 (Berkeley) 5/31/93"; #else -static char rcsid[] = "$NetBSD: pom.c,v 1.6 1996/02/06 22:47:29 jtc Exp $"; +static char rcsid[] = "$OpenBSD: pom.c,v 1.6 1998/09/06 12:29:25 pjanzen Exp $"; #endif #endif /* not lint */ @@ -58,50 +58,74 @@ static char rcsid[] = "$NetBSD: pom.c,v 1.6 1996/02/06 22:47:29 jtc Exp $"; * * -- Keith E. Brandt VIII 1984 * + * Updated to the Third Edition of Duffett-Smith's book, IX 1998 + * */ #include +#include +#include #include #include -#include #include -#include +#include +#include +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif -#define PI 3.141592654 -#define EPOCH 85 -#define EPSILONg 279.611371 /* solar ecliptic long at EPOCH */ -#define RHOg 282.680403 /* solar ecliptic long of perigee at EPOCH */ -#define ECCEN 0.01671542 /* solar orbit eccentricity */ -#define lzero 18.251907 /* lunar mean long at EPOCH */ -#define Pzero 192.917585 /* lunar mean long of perigee at EPOCH */ -#define Nzero 55.204723 /* lunar mean long of node at EPOCH */ +#define EPOCH 90 +#define EPSILONg 279.403303 /* solar ecliptic long at EPOCH */ +#define RHOg 282.768422 /* solar ecliptic long of perigee at EPOCH */ +#define ECCEN 0.016713 /* solar orbit eccentricity */ +#define lzero 318.351648 /* lunar mean long at EPOCH */ +#define Pzero 36.340410 /* lunar mean long of perigee at EPOCH */ +#define Nzero 318.510107 /* lunar mean long of node at EPOCH */ -double dtor(), potm(), adj360(); +void adj360 __P((double *)); +double dtor __P((double)); +double potm __P((double)); +time_t parsetime __P((char *)); +void badformat __P((void)); -main() +int +main(argc, argv) + int argc; + char *argv[]; { struct timeval tp; struct timezone tzp; - struct tm *GMT, *gmtime(); + struct tm *GMT; time_t tmpt; double days, today, tomorrow; int cnt; + char buf[1024]; /* revoke */ setegid(getgid()); setgid(getgid()); - if (gettimeofday(&tp,&tzp)) { - (void)fprintf(stderr, "pom: %s\n", strerror(errno)); - exit(1); + if (argc > 1) { + tmpt = parsetime(argv[1]); + strftime(buf, sizeof(buf), "%a %Y %b %e %H:%M:%S (%Z)", + localtime(&tmpt)); + printf("%s: ", buf); + } else { + if (gettimeofday(&tp,&tzp)) + err(1, "gettimeofday"); + tmpt = tp.tv_sec; } - tmpt = tp.tv_sec; GMT = gmtime(&tmpt); days = (GMT->tm_yday + 1) + ((GMT->tm_hour + (GMT->tm_min / 60.0) + (GMT->tm_sec / 3600.0)) / 24.0); for (cnt = EPOCH; cnt < GMT->tm_year; ++cnt) - days += isleap(cnt + 1900) ? 366 : 365; - today = potm(days) + .5; + days += isleap(cnt + TM_YEAR_BASE) ? 366 : 365; + /* Selected time could be before EPOCH */ + for (cnt = GMT->tm_year; cnt < EPOCH; ++cnt) + days -= isleap(cnt + TM_YEAR_BASE) ? 366 : 365; + today = potm(days) + 0.5; (void)printf("The Moon is "); if ((int)today == 100) (void)printf("Full\n"); @@ -112,7 +136,11 @@ main() if ((int)today == 50) (void)printf("%s\n", tomorrow > today ? "at the First Quarter" : "at the Last Quarter"); + /* today is 0.5 too big, but it doesn't matter here + * since the phase is changing fast enough + */ else { + today -= 0.5; /* Now it might matter */ (void)printf("%s ", tomorrow > today ? "Waxing" : "Waning"); if (today > 50) @@ -137,30 +165,30 @@ potm(days) double N, Msol, Ec, LambdaSol, l, Mm, Ev, Ac, A3, Mmprime; double A4, lprime, V, ldprime, D, Nm; - N = 360 * days / 365.2422; /* sec 42 #3 */ + N = 360.0 * days / 365.242191; /* sec 46 #3 */ adj360(&N); - Msol = N + EPSILONg - RHOg; /* sec 42 #4 */ + Msol = N + EPSILONg - RHOg; /* sec 46 #4 */ adj360(&Msol); - Ec = 360 / PI * ECCEN * sin(dtor(Msol)); /* sec 42 #5 */ - LambdaSol = N + Ec + EPSILONg; /* sec 42 #6 */ + Ec = 360 / M_PI * ECCEN * sin(dtor(Msol)); /* sec 46 #5 */ + LambdaSol = N + Ec + EPSILONg; /* sec 46 #6 */ adj360(&LambdaSol); - l = 13.1763966 * days + lzero; /* sec 61 #4 */ + l = 13.1763966 * days + lzero; /* sec 65 #4 */ adj360(&l); - Mm = l - (0.1114041 * days) - Pzero; /* sec 61 #5 */ + Mm = l - (0.1114041 * days) - Pzero; /* sec 65 #5 */ adj360(&Mm); - Nm = Nzero - (0.0529539 * days); /* sec 61 #6 */ + Nm = Nzero - (0.0529539 * days); /* sec 65 #6 */ adj360(&Nm); - Ev = 1.2739 * sin(dtor(2*(l - LambdaSol) - Mm)); /* sec 61 #7 */ - Ac = 0.1858 * sin(dtor(Msol)); /* sec 61 #8 */ + Ev = 1.2739 * sin(dtor(2*(l - LambdaSol) - Mm)); /* sec 65 #7 */ + Ac = 0.1858 * sin(dtor(Msol)); /* sec 65 #8 */ A3 = 0.37 * sin(dtor(Msol)); - Mmprime = Mm + Ev - Ac - A3; /* sec 61 #9 */ - Ec = 6.2886 * sin(dtor(Mmprime)); /* sec 61 #10 */ - A4 = 0.214 * sin(dtor(2 * Mmprime)); /* sec 61 #11 */ - lprime = l + Ev + Ec - Ac + A4; /* sec 61 #12 */ - V = 0.6583 * sin(dtor(2 * (lprime - LambdaSol))); /* sec 61 #13 */ - ldprime = lprime + V; /* sec 61 #14 */ - D = ldprime - LambdaSol; /* sec 63 #2 */ - return(50 * (1 - cos(dtor(D)))); /* sec 63 #3 */ + Mmprime = Mm + Ev - Ac - A3; /* sec 65 #9 */ + Ec = 6.2886 * sin(dtor(Mmprime)); /* sec 65 #10 */ + A4 = 0.214 * sin(dtor(2 * Mmprime)); /* sec 65 #11 */ + lprime = l + Ev + Ec - Ac + A4; /* sec 65 #12 */ + V = 0.6583 * sin(dtor(2 * (lprime - LambdaSol))); /* sec 65 #13 */ + ldprime = lprime + V; /* sec 65 #14 */ + D = ldprime - LambdaSol; /* sec 67 #2 */ + return(50.0 * (1 - cos(dtor(D)))); /* sec 67 #3 */ } /* @@ -171,22 +199,93 @@ double dtor(deg) double deg; { - return(deg * PI / 180); + return(deg * M_PI / 180); } /* * adj360 -- * adjust value so 0 <= deg <= 360 */ -double +void adj360(deg) double *deg; { for (;;) - if (*deg < 0) - *deg += 360; - else if (*deg > 360) - *deg -= 360; + if (*deg < 0.0) + *deg += 360.0; + else if (*deg > 360.0) + *deg -= 360.0; else break; } + +#define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2; +time_t +parsetime(p) + char *p; +{ + struct tm *lt; + int bigyear; + int yearset = 0; + time_t tval; + char *t; + + for (t = p; *t; ++t) { + if (isdigit(*t)) + continue; + badformat(); + } + + tval = time(NULL); + lt = localtime(&tval); + lt->tm_sec = 0; + lt->tm_min = 0; + + switch (strlen(p)) { + case 10: /* yyyy */ + bigyear = ATOI2(p); + lt->tm_year = bigyear * 100 - TM_YEAR_BASE; + yearset = 1; + /* FALLTHROUGH */ + case 8: /* yy */ + if (yearset) { + lt->tm_year += ATOI2(p); + } else { + lt->tm_year = ATOI2(p) + 1900 - TM_YEAR_BASE; + if (lt->tm_year < 69) /* hack for 2000 */ + lt->tm_year += 100; + } + /* FALLTHROUGH */ + case 6: /* mm */ + lt->tm_mon = ATOI2(p); + if ((lt->tm_mon > 12) || !lt->tm_mon) + badformat(); + --lt->tm_mon; /* time struct is 0 - 11 */ + /* FALLTHROUGH */ + case 4: /* dd */ + lt->tm_mday = ATOI2(p); + if ((lt->tm_mday > 31) || !lt->tm_mday) + badformat(); + /* FALLTHROUGH */ + case 2: /* HH */ + lt->tm_hour = ATOI2(p); + if (lt->tm_hour > 23) + badformat(); + break; + default: + badformat(); + } + /* The calling code needs a valid tm_ydays and this is the easiest + * way to get one */ + if ((tval = mktime(lt)) == -1) + errx(1, "specified date is outside allowed range"); + return (tval); +} + +void +badformat() +{ + warnx("illegal time format"); + (void)fprintf(stderr, "usage: pom [[[[[cc]yy]mm]dd]HH]\n"); + exit(1); +} -- cgit v1.2.3