// ====================================================================================================
// Description:
//	Algorithms for calculation of Moon phases.
//
// Author:
//	Henk Reints
//	http://henk-reints.nl
//
// Version history:			Date:		Version comment:
//	V00.02				Feb 2007	Added function moonAge
//	V00.01				Sep 2000	Extracted moon algorithms from astronomy.js
//							and placed into this separate file.
//	V00.00 (initial development)	Jul 2000	Original version started during holiday in
//							Southern France at the most beautiful camping
//							site of the world...
// Usage:
//	To use this module you must also include astro.js
//	which provides general purpose algorithms also needed here.
//
// Reference:
//	Jean Meeus: Astronomical algorithms, 2nd ed. ISBN 0-943396-61-1
//
// DISCLAIMER:
//	THIS PACKAGE IS PROVIDED AS IS, WITHOUT ANY GUARANTEE FOR ACCURACY OR CORRECTNESS.
//	FOR PLANNING ACTIVITIES, ONE SHOULD NOT RELY ON THE RESULTS OF THIS PACKAGE, BUT
//	ALWAYS VERIFY THEM BY CONSULTING OTHER REFERENCES AS WELL.  THE AUTHOR CANNOT BE HELD
//	RESPONSIBLE FOR ANY CONSEQUENCES OF (TYPING OR PROGRAMMING) ERRORS OR MISCALCULATIONS.
//
// Notes:
//	See file astro.js for more information.
// ====================================================================================================

var	zeroLunation	= JulianDay ('', 2000, 1, 6, 18, 14)	// the 'zero' new moon
var	synodicMonth	= 29.530588861

// next can be customized for other languages:
var moonphaseName = ['New Moon','First Quarter','Full Moon','Last Quarter']
var moonphaseAbbr = ['NM','FQ','FM','LQ']

// ====================================================================================================

function lunation (JDE)
{
	// --------------------------------------------------------------------------------------
	// returns approximate number of lunations since 2000-01-06, rounded to multiple of 0.25,
	// so not applicable for dates between the 4 standard moon phases.
	// Reference:
	//	Meeus, chapter 49.
	// --------------------------------------------------------------------------------------

	return Math.round (4 * (JDE - zeroLunation) / synodicMonth) / 4
}

// ====================================================================================================

function moonphaseValue (lunation)
{
	// -----------------------------------------------------------
	// returns the (nearest) moon phase within the given lunation.
	// Result:
	//	0 = New Moon
	//	1 = First Quarter
	//	2 = Full Moon
	//	3 = Last Quarter
	// -----------------------------------------------------------

	return Math.round ( (lunation - Math.floor (lunation) ) * 4) % 4
}

// ====================================================================================================

function JDEmoonphase (lunation)
{
	// ----------------------------------------------------------------------------
	// returns JDE of the moment of the moon phase specified by lunation,
	// where lunation is the number of lunations since 2000-01-06
	// and it must be an integer multiple of 0.25.
	// the fraction (i.e. the value minus its Math.floor value, so always positive)
	// specifies the moon phase:
	//	0.00 =	New Moon
	//	0.25 =	First Quarter
	//	0.50 =	Full Moon
	//	0.75 =	Last Quarter
	// Reference:
	//	Meeus, chapter 49.
	// ----------------------------------------------------------------------------

	var k	= lunation
	var q	= moonphaseValue (k)
	var T	= k / 1236.85

	var JDE	=             polynomial2 (T,2451550.09766 +  29.530588861 *k, moonphasetable0[0] )
	var E	=             polynomial1 (T,                                  moonphasetable0[1] )
	var M	= normdegrees(polynomial2 (T,      2.5534  +  29.10535670  *k, moonphasetable0[2] ) )
	var M1	= normdegrees(polynomial2 (T,    201.5643  + 385.81693528  *k, moonphasetable0[3] ) )
	var F	= normdegrees(polynomial2 (T,    160.7108  + 390.67050284  *k, moonphasetable0[4] ) )
	var OMG	= normdegrees(polynomial2 (T,    124.7746  +  -1.56375588  *k, moonphasetable0[5] ) )

	if (q == 1 || q == 3)
	{
		var W = 3.06e-3 - 3.8e-4*E*cosd(M) + 2.6e-4*cosd(M1)
		      + 2e-5*cosd(M+M1) - 2e-5*cosd(M-M1) + 2e-5*cosd(2*F)
		JDE += (q == 1 ? W : -W)
	}

	for (var n = 0; n < moonphasetable1.length; n++)
	{
		var i = (q == 0 ? 0 : (q == 2 ? 1 : 7) ), p = moonphasetable1[n][i], r = 0
		i++; if (i == 1) {i++}
		for (var m = 0; m < moonphasetable1[n][i]; m++) {p *= E}
		r += moonphasetable1[n][++i] * M
		r += moonphasetable1[n][++i] * M1
		r += moonphasetable1[n][++i] * F
		r += moonphasetable1[n][++i] * OMG
		JDE += p * sind (r)
	}
	JDE += 325e-6 * sind (normdegrees (polynomial (T, 299.77 +  0.107408 * k, 0, -9.173e-3 )))

	for (var n = 0; n < moonphasetable2.length; n++)
	{
		var a = moonphasetable2[n]
		JDE += a[0] * sind (normdegrees (a[1] + a[2] * k ) )
	}

	return JDE
}

// ====================================================================================================

function moonAge (JD)								// get true moon age at a given time
{	var JDE = JDEfromJD (JD)
	var L   = Math.floor ( (JDE - zeroLunation) / synodicMonth) + 1		// lunation after given date
	var JDL = roundJD (JDfromJDE (JDEmoonphase (L) ) )			// exact time of this new moon
	for (; JDL > JD; JDL = roundJD (JDfromJDE (JDEmoonphase (--L) ) ) );	// count down until before date
	return JD - JDL								// return age of moon at date
}

// ====================================================================================================
// tables for function JDEmoonphase:	[Meeus, chapter 49]

var moonphasetable0 =
	[[0, 1.5437e-4 ,-1.5e-7  , 7.3e-10]
	,[1,-2.516e-3  ,-7.4e-6           ]
	,[0,-1.4e-6    ,-1.1e-7           ]
	,[0, 1.07582e-2, 1.238e-5,-5.8e-8 ]
	,[0,-1.6118e-3 ,-2.27e-6 , 1.1e-8 ]
	,[0, 2.0672e-3 , 2.15e-6          ]
	]
var moonphasetable1 =
	[[-0.40720,-0.40614,0, 0,1, 0,0,-0.62801,0, 0,1, 0,0]
	,[ 0.17241, 0.17302,1, 1,0, 0,0, 0.17172,1, 1,0, 0,0]
	,[ 0.01608, 0.01614,0, 0,2, 0,0,-0.01183,1, 1,1, 0,0]
	,[ 0.01039, 0.01043,0, 0,0, 2,0, 0.00862,0, 0,2, 0,0]
	,[ 0.00739, 0.00734,1,-1,1, 0,0, 0.00804,0, 0,0, 2,0]
	,[-0.00514,-0.00515,1, 1,1, 0,0, 0.00454,1,-1,1, 0,0]
	,[ 0.00208, 0.00209,2, 2,0, 0,0, 0.00204,2, 2,0, 0,0]
	,[-0.00111,-0.00111,0, 0,1,-2,0,-0.00180,0, 0,1,-2,0]
	,[-0.00057,-0.00057,0, 0,1, 2,0,-0.00070,0, 0,1, 2,0]
	,[ 0.00056, 0.00056,1, 1,2, 0,0,-0.00040,0, 0,3, 0,0]
	,[-0.00042,-0.00042,0, 0,3, 0,0,-0.00034,1,-1,2, 0,0]
	,[ 0.00042, 0.00042,1, 1,0, 2,0, 0.00032,1, 1,0, 2,0]
	,[ 0.00038, 0.00038,1, 1,0,-2,0, 0.00032,1, 1,0,-2,0]
	,[-0.00024,-0.00024,1,-1,2, 0,0,-0.00028,2, 2,1, 0,0]
	,[-0.00017,-0.00017,0, 0,0, 0,1, 0.00027,1, 1,2, 0,0]
	,[-0.00007,-0.00007,0, 2,1, 0,0,-0.00017,0, 0,0, 0,1]
	,[ 0.00004, 0.00004,0, 0,2,-2,0,-0.00005,0,-1,1,-2,0]
	,[ 0.00004, 0.00004,0, 3,0, 0,0, 0.00004,0, 0,2, 2,0]
	,[ 0.00003, 0.00003,0, 1,1,-2,0,-0.00004,0, 1,1, 2,0]
	,[ 0.00003, 0.00003,0, 0,2, 2,0, 0.00004,0,-2,1, 0,0]
	,[-0.00003,-0.00003,0, 1,1, 2,0, 0.00003,0, 1,1,-2,0]
	,[ 0.00003, 0.00003,0,-1,1, 2,0, 0.00003,0, 3,0, 0,0]
	,[-0.00002,-0.00002,0,-1,1, 2,0, 0.00002,0, 0,2,-2,0]
	,[-0.00002,-0.00002,0, 1,3, 0,0, 0.00002,0,-1,1, 2,0]
	,[ 0.00002, 0.00002,0, 0,4, 0,0,-0.00002,0, 1,3, 0,0]
	]
var moonphasetable2 =
	[[165e-6,251.88, 0.016321]
	,[164e-6,251.83,26.651886]
	,[126e-6,349.42,36.412478]
	,[110e-6, 84.66,18.206239]
	,[ 62e-6,141.74,53.303771]
	,[ 60e-6,207.14, 2.453732]
	,[ 56e-6,154.84, 7.306860]
	,[ 47e-6, 34.52,27.261239]
	,[ 42e-6,207.19, 0.121824]
	,[ 40e-6,291.34, 1.844379]
	,[ 37e-6,161.72,24.198154]
	,[ 35e-6,239.56,25.513099]
	,[ 23e-6,331.55, 3.592518]
	]

// ====================================================================================================
// ====================================================================================================
// end of file; Copyright (c) 2000 Henk Reints
