From owner-svn-src-user@FreeBSD.ORG Thu Jan 7 06:59:16 2010 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 534E0106568F; Thu, 7 Jan 2010 06:59:16 +0000 (UTC) (envelope-from edwin@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 40CD98FC0C; Thu, 7 Jan 2010 06:59:16 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o076xGP9073608; Thu, 7 Jan 2010 06:59:16 GMT (envelope-from edwin@svn.freebsd.org) Received: (from edwin@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o076xGf2073602; Thu, 7 Jan 2010 06:59:16 GMT (envelope-from edwin@svn.freebsd.org) Message-Id: <201001070659.o076xGf2073602@svn.freebsd.org> From: Edwin Groothuis Date: Thu, 7 Jan 2010 06:59:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r201718 - user/edwin/calendar X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 07 Jan 2010 06:59:16 -0000 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 +__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 +#include +#include +#include +#include +#include +#include + +#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; +}