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