svn commit: r201718 - user/edwin/calendar

Edwin Groothuis edwin at FreeBSD.org
Thu Jan 7 06:59:16 UTC 2010


Author: edwin
Date: Thu Jan  7 06:59:16 2010
New Revision: 201718
URL: http://svn.freebsd.org/changeset/base/201718

Log:
  Add support for phase of the moon.

Added:
  user/edwin/calendar/pom.c
Modified:
  user/edwin/calendar/Makefile
  user/edwin/calendar/calendar.h
  user/edwin/calendar/io.c
  user/edwin/calendar/parsedata.c

Modified: user/edwin/calendar/Makefile
==============================================================================
--- user/edwin/calendar/Makefile	Thu Jan  7 06:20:07 2010	(r201717)
+++ user/edwin/calendar/Makefile	Thu Jan  7 06:59:16 2010	(r201718)
@@ -5,13 +5,17 @@ CFLAGS=	 -pipe  -g -std=gnu99 -fstack-pr
 
 PROG=	calendar
 SRCS=   calendar.c locale.c events.c dates.c parsedata.c io.c day.c \
-	ostern.c paskha.c
+	ostern.c paskha.c pom.c
+LDADD=	-lm
 INTER=          de_AT.ISO_8859-15 de_DE.ISO8859-1 fr_FR.ISO8859-1 \
 		hr_HR.ISO8859-2 hu_HU.ISO8859-2 ru_RU.KOI8-R uk_UA.KOI8-U
 DE_LINKS=       de_DE.ISO8859-15
 FR_LINKS=       fr_FR.ISO8859-15
 TEXTMODE?=	444
 
+pom: pom.c
+	gcc -g -Wall -o pom pom.c -lm
+
 beforeinstall:
 	${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${TEXTMODE} \
 	    ${.CURDIR}/calendars/calendar.* ${DESTDIR}${SHAREDIR}/calendar

Modified: user/edwin/calendar/calendar.h
==============================================================================
--- user/edwin/calendar/calendar.h	Thu Jan  7 06:20:07 2010	(r201717)
+++ user/edwin/calendar/calendar.h	Thu Jan  7 06:59:16 2010	(r201718)
@@ -47,28 +47,32 @@ extern struct tm tp1, tp2;
 extern time_t t1, t2;
 extern const char *calendarFile;
 extern int yrdays;
-extern struct fixs neaster, npaskha, ncny;
+extern struct fixs neaster, npaskha, ncny, nfullmoon, nnewmoon;
 
 #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
 
 /* Flags to determine the returned values by determinestyle() in parsedata.c */
-#define	F_NONE			0x000
-#define	F_MONTH			0x001
-#define	F_DAYOFWEEK		0x002
-#define	F_DAYOFMONTH		0x004
-#define	F_MODIFIERINDEX		0x008
-#define	F_MODIFIEROFFSET	0x010
-#define	F_SPECIALDAY		0x020
-#define	F_ALLMONTH		0x040
-#define	F_ALLDAY		0x080
-#define	F_VARIABLE		0x100
-#define	F_EASTER		0x200
-#define	F_CNY			0x400
-#define	F_PASKHA		0x800
+#define	F_NONE			0x0000
+#define	F_MONTH			0x0001
+#define	F_DAYOFWEEK		0x0002
+#define	F_DAYOFMONTH		0x0004
+#define	F_MODIFIERINDEX		0x0008
+#define	F_MODIFIEROFFSET	0x0010
+#define	F_SPECIALDAY		0x0020
+#define	F_ALLMONTH		0x0040
+#define	F_ALLDAY		0x0080
+#define	F_VARIABLE		0x0100
+#define	F_EASTER		0x0200
+#define	F_CNY			0x0400
+#define	F_PASKHA		0x0800
+#define	F_NEWMOON		0x1000
+#define	F_FULLMOON		0x2000
 
 #define	STRING_EASTER	"Easter"
 #define	STRING_PASKHA	"Paskha"
 #define	STRING_CNY	"ChineseNewYear"
+#define STRING_NEWMOON	"NewMoon"
+#define STRING_FULLMOON	"FullMoon"
 
 extern int	debug;		/* show parsing of the input */
 extern int	f_dayAfter;	/* days after current date */
@@ -143,3 +147,8 @@ int	first_dayofweek_of_year(int y);
 int	first_dayofweek_of_month(int y, int m);
 int	walkthrough_dates(struct event **e);
 void	addtodate(struct event *e, int year, int month, int day);
+
+/* pom.c */
+#define	MAXMOONS	15
+void	pom(int year, int *fms, int *nms);
+

Modified: user/edwin/calendar/io.c
==============================================================================
--- user/edwin/calendar/io.c	Thu Jan  7 06:20:07 2010	(r201717)
+++ user/edwin/calendar/io.c	Thu Jan  7 06:59:16 2010	(r201718)
@@ -69,7 +69,7 @@ const char *calendarNoMail = "nomail";	/
 
 char	path[MAXPATHLEN];
 
-struct fixs neaster, npaskha, ncny;
+struct fixs neaster, npaskha, ncny, nfullmoon, nnewmoon;
 
 struct iovec header[] = {
 	{"From: ", 6},
@@ -152,6 +152,22 @@ cal(void)
 			ncny.len = strlen(buf + 15);
 			continue;
 		}
+		if (strncasecmp(buf, "NewMoon=", 8) == 0 && buf[8]) {
+			if (nnewmoon.name != NULL)
+				free(nnewmoon.name);
+			if ((nnewmoon.name = strdup(buf + 8)) == NULL)
+				errx(1, "cannot allocate memory");
+			nnewmoon.len = strlen(buf + 8);
+			continue;
+		}
+		if (strncasecmp(buf, "FullMoon=", 9) == 0 && buf[9]) {
+			if (nfullmoon.name != NULL)
+				free(nfullmoon.name);
+			if ((nfullmoon.name = strdup(buf + 9)) == NULL)
+				errx(1, "cannot allocate memory");
+			nfullmoon.len = strlen(buf + 9);
+			continue;
+		}
 
 		/*
 		 * If the line starts with a tab, the data has to be

Modified: user/edwin/calendar/parsedata.c
==============================================================================
--- user/edwin/calendar/parsedata.c	Thu Jan  7 06:20:07 2010	(r201717)
+++ user/edwin/calendar/parsedata.c	Thu Jan  7 06:59:16 2010	(r201718)
@@ -121,6 +121,14 @@ determinestyle(char *date, int *flags,
 			CHECKSPECIAL(date, STRING_CNY, strlen(STRING_CNY),
 			    F_CNY);
 			CHECKSPECIAL(date, ncny.name, ncny.len, F_CNY);
+			CHECKSPECIAL(date, STRING_NEWMOON,
+			    strlen(STRING_NEWMOON), F_NEWMOON);
+			CHECKSPECIAL(date, nnewmoon.name, nnewmoon.len,
+			    F_NEWMOON);
+			CHECKSPECIAL(date, STRING_FULLMOON,
+			    strlen(STRING_FULLMOON), F_FULLMOON);
+			CHECKSPECIAL(date, nfullmoon.name, nfullmoon.len,
+			    F_FULLMOON);
 			CHECKSPECIAL(date, STRING_PASKHA,
 			    strlen(STRING_PASKHA), F_PASKHA);
 			CHECKSPECIAL(date, npaskha.name, npaskha.len, F_PASKHA);
@@ -321,7 +329,9 @@ parsedaymonth(char *date, int *yearp, in
 	char month[100], dayofmonth[100], dayofweek[100], modifieroffset[100];
 	char modifierindex[100], specialday[100];
 	int idayofweek, imonth, idayofmonth, year, index;
+
 	int ieaster, ipaskha;
+	int ifullmoon[MAXMOONS], inewmoon[MAXMOONS];
 
 	int *mondays, d, m, dow, rm, rd, offset;
 
@@ -358,6 +368,7 @@ parsedaymonth(char *date, int *yearp, in
 	for (year = year1; year <= year2; year++) {
 		mondays = mondaytab[isleap(year)];
 		ieaster = easter(year);
+		pom(year, ifullmoon, inewmoon);
 
 		/* Same day every year */
 		if (*flags == (F_MONTH | F_DAYOFMONTH)) {
@@ -486,6 +497,40 @@ parsedaymonth(char *date, int *yearp, in
 			continue;
 		}
 
+		/* FullMoon */
+		if ((*flags & ~F_MODIFIEROFFSET) ==
+		    (F_SPECIALDAY | F_VARIABLE | F_FULLMOON)) {
+			int i;
+
+			offset = 0;
+			if ((*flags & F_MODIFIEROFFSET) != 0)
+				offset = parseoffset(modifieroffset);
+			for (i = 0; ifullmoon[i] != 0; i++) {
+				if (remember_yd(year, ifullmoon[i] + offset,
+				    &rm, &rd))
+					remember(index++, yearp, monthp, dayp,
+						year, rm, rd);
+			}
+			continue;
+		}
+
+		/* NewMoon */
+		if ((*flags & ~F_MODIFIEROFFSET) ==
+		    (F_SPECIALDAY | F_VARIABLE | F_NEWMOON)) {
+			int i;
+
+			offset = 0;
+			if ((*flags & F_MODIFIEROFFSET) != 0)
+				offset = parseoffset(modifieroffset);
+			for (i = 0; ifullmoon[i] != 0; i++) {
+				if (remember_yd(year, inewmoon[i] + offset,
+				    &rm, &rd))
+					remember(index++, yearp, monthp, dayp,
+						year, rm, rd);
+			}
+			continue;
+		}
+
 		printf("Unprocessed:\n");
 		debug_determinestyle(2, date, *flags, month, imonth,
 		    dayofmonth, idayofmonth, dayofweek, idayofweek,
@@ -526,6 +571,10 @@ showflags(int flags)
 		strcat(s, "paskha ");
 	if ((flags & F_EASTER) != 0)
 		strcat(s, "easter ");
+	if ((flags & F_FULLMOON) != 0)
+		strcat(s, "fullmoon ");
+	if ((flags & F_NEWMOON) != 0)
+		strcat(s, "newmoon ");
 
 	return s;
 }

Added: user/edwin/calendar/pom.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/edwin/calendar/pom.c	Thu Jan  7 06:59:16 2010	(r201718)
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software posted to USENET.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1989, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static const char sccsid[] = "@(#)pom.c       8.1 (Berkeley) 5/31/93";
+#endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/games/pom/pom.c 201613 2010-01-05 21:14:48Z edwin $");
+
+/*
+ * Phase of the Moon.  Calculates the current phase of the moon.
+ * Based on routines from `Practical Astronomy with Your Calculator',
+ * by Duffett-Smith.  Comments give the section from the book that
+ * particular piece of code was adapted from.
+ *
+ * -- Keith E. Brandt  VIII 1984
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <sysexits.h>
+#include <time.h>
+#include <unistd.h> 
+
+#ifndef	PI
+#define	PI	  3.14159265358979323846
+#endif
+#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 isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+
+static void	adj360(double *);
+static double	dtor(double);
+static double	potm(double);
+
+void
+pom(int year, int *fms, int *nms)
+{
+	time_t tt;
+	struct tm GMT, tmd_today, tmd_tomorrow;
+	double days_today, days_tomorrow, today, tomorrow;
+	int cnt, d;
+	int yeardays;
+	int olddir, newdir;
+	int *pnms, *pfms;
+
+	pnms = nms;
+	pfms = fms;
+
+	/*
+	 * We take the phase of the moon one second before and one second
+	 * after midnight.
+	 */
+	memset(&tmd_today, 0, sizeof(tmd_today));
+	tmd_today.tm_year = year - 1900;
+	tmd_today.tm_mon = 0;
+	tmd_today.tm_mday = 0;		/* 31 December */
+	tmd_today.tm_hour = 23;
+	tmd_today.tm_min = 59;
+	tmd_today.tm_sec = 59;
+	memset(&tmd_tomorrow, 0, sizeof(tmd_tomorrow));
+	tmd_tomorrow.tm_year = year - 1900;
+	tmd_tomorrow.tm_mon = 0;
+	tmd_tomorrow.tm_mday = 1;	/* 1 January */
+	tmd_tomorrow.tm_hour = 0;
+	tmd_tomorrow.tm_min = 0;
+	tmd_tomorrow.tm_sec = 1;
+
+	tt = mktime(&tmd_today);
+	gmtime_r(&tt, &GMT);
+	yeardays = 0;
+	for (cnt = EPOCH; cnt < GMT.tm_year; ++cnt)
+		yeardays += isleap(1900 + cnt) ? 366 : 365;
+	days_today = (GMT.tm_yday + 1) + ((GMT.tm_hour +
+	    (GMT.tm_min / 60.0) + (GMT.tm_sec / 3600.0)) / 24.0);
+	days_today += yeardays;
+
+	tt = mktime(&tmd_tomorrow);
+	gmtime_r(&tt, &GMT);
+	yeardays = 0;
+	for (cnt = EPOCH; cnt < GMT.tm_year; ++cnt)
+		yeardays += isleap(1900 + cnt) ? 366 : 365;
+	days_tomorrow = (GMT.tm_yday + 1) + ((GMT.tm_hour +
+	    (GMT.tm_min / 60.0) + (GMT.tm_sec / 3600.0)) / 24.0);
+	days_tomorrow += yeardays;
+
+	today = potm(days_today);		/* 30 December 23:59:59 */
+	tomorrow = potm(days_tomorrow);		/* 31 December 00:00:01 */
+	olddir = today > tomorrow ? -1 : +1;
+
+	yeardays = isleap(year) ? 366 : 365;	/* reuse */
+	for (d = 0; d <= yeardays; d++) {
+		today = potm(days_today);
+		tomorrow = potm(days_tomorrow);
+		newdir = today > tomorrow ? -1 : +1;
+		if (olddir == -1 && newdir == +1) {
+			*pnms = d;
+			pnms++;
+		}
+		if (olddir == +1 && newdir == -1) {
+			*pfms = d;
+			pfms++;
+		}
+		olddir = newdir;
+		days_today++;
+		days_tomorrow++;
+	}
+	*pfms = 0;
+	*pnms = 0;
+}
+
+/*
+ * potm --
+ *	return phase of the moon
+ */
+static double
+potm(double 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 */
+	adj360(&N);
+	Msol = N + EPSILONg - RHOg;				/* sec 42 #4 */
+	adj360(&Msol);
+	Ec = 360 / PI * ECCEN * sin(dtor(Msol));		/* sec 42 #5 */
+	LambdaSol = N + Ec + EPSILONg;				/* sec 42 #6 */
+	adj360(&LambdaSol);
+	l = 13.1763966 * days + lzero;				/* sec 61 #4 */
+	adj360(&l);
+	Mm = l - (0.1114041 * days) - Pzero;			/* sec 61 #5 */
+	adj360(&Mm);
+	Nm = Nzero - (0.0529539 * days);			/* sec 61 #6 */
+	adj360(&Nm);
+	Ev = 1.2739 * sin(dtor(2*(l - LambdaSol) - Mm));	/* sec 61 #7 */
+	Ac = 0.1858 * sin(dtor(Msol));				/* sec 61 #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 */
+}
+
+/*
+ * dtor --
+ *	convert degrees to radians
+ */
+static double
+dtor(double deg)
+{
+
+	return(deg * PI / 180);
+}
+
+/*
+ * adj360 --
+ *	adjust value so 0 <= deg <= 360
+ */
+static void
+adj360(double *deg)
+{
+
+	for (;;)
+		if (*deg < 0)
+			*deg += 360;
+		else if (*deg > 360)
+			*deg -= 360;
+		else
+			break;
+}


More information about the svn-src-user mailing list