<!-- Hide from non-JavaScript browsers

// Javascript code for the Hitchhiker's Guide to the Moon,
// http://www.shallowsky.com/moon
// Copyright 1998-2002 by Akkana Peck.

function charSub(oldstr, oldchar, newchar)
{
    var str = new String(oldstr);
    // Replace all the '+'s with spaces:
    var idx = str.indexOf(oldchar);
    if (idx == -1)
	return str;
    var newdatestr = str.substring(0, idx);
    while (1) {
	var oldidx = idx;
	idx = str.indexOf(oldchar, idx+1);
	if (idx == -1)
	    return newdatestr + newchar + str.substring(oldidx+1);
	newdatestr = newdatestr + newchar + str.substring(oldidx+1, idx);
    }
    return 0;	// should never get here
}

function readUserDate()
{
    var datestr = new String(document.location);
    var idx = datestr.indexOf("?");
    if (idx == -1)
	return "";
    idx = datestr.indexOf("date=", idx);
    if (idx == -1)
	return "";
    var idx2 = datestr.indexOf("&");
    if (idx2 != -1)
        datestr = datestr.substr(idx + 5, idx2);
    else
        datestr = datestr.substr(idx + 5);

    return charSub(datestr, "+", " ");
}

// Global variable: curdate. 
// Read from document.location or set to current date.
var newdate = readUserDate();
var curdate;
if (newdate != "")
    curdate = new Date(newdate);
else
    curdate = new Date();

// Last chart in each line:
var chartLines = new Array(7, 16, 27, 38, 49, 60, 69, 76);

// and information about how many spaces to leave blank on each line:
var blanks = new Array(2, 1, 0, 0, 0, 0, 1, 2);

// eastern longitude limits of each chart:
var ll = new Array (-90, -50, -30, -10, 30, 70, 80, 90,
                    -50, -40, -20, -10, 0, 20, 40, 70, 90,
                    -60, -50, -30, -20, -10, 0, 10, 30, 40, 70, 90,
                    -60, -40, -30, -20, -10, 0, 10, 20, 40, 50, 90,
                    -60, -40, -30, -20, -10, 0, 10, 20, 40, 50, 90,
                    -60, -50, -30, -20, -10, 0, 10, 30, 40, 70, 90,
                    -50, -40, -20, -10, 0, 20, 40, 70, 90,
                    -50, -30, -10, 30, 70, 80, 90);

function getLunotineSize(chartno)
{
    var width=24;
    var height=28;

    if (typeof(chartno) == "number") {
        var modulo;
        if (chartno < 8)
            modulo = chartno + 2;
        else if (chartno < 17)
            modulo = chartno - 7;
        else if (chartno > 69)
            modulo = chartno - 68;
        else if (chartno > 60)
            modulo = chartno - 60;
        else
            modulo = (chartno - 17) % 11;
        if (modulo < 3) width = 24;
        else if (modulo < 5) width = 21;
        else if (modulo < 7) width = 21;
        else if (modulo < 10) width = 17;
        else width = 16;
    }
    else if (chartno == "I" || chartno == "VIII"
             || chartno == "VII" || chartno == "VI")
        width = 24;
    else if (chartno == "II" || chartno == "V")
        width = 17;
    else width = 16;

    return "width=" + width + " height=" + height;
}

function showNum(chartno)
{
    window.status = "Chart #" + chartno;
}

function hideNum(chartno)
{
    //window.status = location.search;
    window.status = "Out " + chartno;
}

function printchart(chartno, colorstring, moonEphem)
{
    if (colorstring == "")
        colorstring = "light";
    var extension;
    if (typeof(chartno) == "number")
        extension = ".jpg";
    else
        extension = ".gif";

    document.write("<td>");
    // Eventually we might want to do some mouseover effects:
    //document.write("<td name=\"cell" + chartno);
    //document.write(" onMouseOver=\"showNum('" + chartno
    //                + "')\" onMouseOut=\"hideNum('" + chartno + "')
    //document.write(\">");

    if (typeof(chartno) == "number" && chartno < 10)
        document.write("<a href=\"rukl0");
    else
        document.write("<a href=\"rukl");

    document.write(chartno + ".html\" target=\"_top\"" );
    //document.write(" onMouseOver=\"showNum(111)\");
    document.write(">" );

    document.write("<img alt=\"" + chartno + "\" src=\"lunotine/"
                   + colorstring + "/lunotine-"
    		   + chartno + extension + "\" border=1 "
		   + getLunotineSize(chartno)
		   + ">");

    document.write("</a>\n</td>\n");
}

function isLit(chart, moonEphem)
{
    if (typeof (chart) != "number")
	return false;

    var eastof = (ll[chart] >= moonEphem.terminator);
    if (moonEphem.phaseAngle >= 0 && moonEphem.phaseAngle <= 180)
        return eastof;
    else
        return !eastof;
}

function libColor(majorlib, minorlib)
{
    var lib = 3*majorlib + minorlib;
    //document.write(" " + lib + ": ");
    if (lib > 17)
	return "biglib";
    else if (lib > 5.5)
	return "lib";
    else
	return "dark";
}

function drawMoonTbl(moonEphem)
{
    var terminator = moonEphem.terminator;
    var color;

    document.writeln("<table align=right bgcolor='#444444'>\n");

    for (var chart=1; chart <= 76; ++chart)
    {
	if (chart == 1) {
	    document.write("<tr>\n");
	    document.write("<td> </td>\n");

	    color = libColor(moonEphem.libNorth, -moonEphem.libEast);
	    printchart("I", color);
	}
	else if (chart == 8) {
	    color = libColor(-moonEphem.libEast, moonEphem.libNorth);
	    printchart("VIII", color);
	}
	else if (chart == 61) {
	    color = libColor(-moonEphem.libEast, -moonEphem.libNorth);
	    printchart("VII", color);
	}
	else if (chart == 70) {
	    document.write("<td> </td>\n");

	    color = libColor(-moonEphem.libNorth, moonEphem.libEast);
	    printchart("VI", color);
	}

	if (isLit(chart, moonEphem))
	    color = "light";
	else
	    color = "dark";
	printchart(chart, color);

	if (chart == 7) {
	    color = libColor(moonEphem.libNorth, moonEphem.libEast);
	    printchart("II", color);

	    document.write("<td> </td>\n");
	}
	else if (chart == 16) {
	    color = libColor(moonEphem.libEast, moonEphem.libNorth);
	    printchart("III", color);
	}
	else if (chart == 69) {
	    color = libColor(moonEphem.libEast, -moonEphem.libNorth);
	    printchart("IV", color);
	}
	else if (chart == 76) {
	    color = libColor(-moonEphem.libNorth, -moonEphem.libEast);
	    printchart("V", color);

	    document.write("<td> </td>\n");
	}

	// If we're at the end of a line, start a new table row.
	if (chart == 7 || chart == 16 || chart == 27 || chart == 38
	    || chart == 49 || chart == 60 || chart == 69 || chart == 76)
	    document.write("\n</tr>\n");
    }

    document.writeln("\n</table>");
}

var DEG2RAD = Math.PI / 180;
var TwoPi = Math.PI * 2;

// convert degrees to a valid angle in radians:
function angle(deg)
{
    while (deg >= 360.)
        deg -= 360.;
    while (deg < 0.)
        deg += 360.;
    return deg * DEG2RAD;
}

function modrad(rad)
{
    while (rad > TwoPi)
        rad -= TwoPi;
    while (rad < 0)
        rad += TwoPi;
    return rad;
}

function decimalYears(date)
{
    return date.getTime() / 365.242191 / (24*60*60*1000);
}

// Get the current colongitude, librations and other data:
function MoonEphem(date)
{
    // Time measured in Julian centuries from epoch J2000.0:
    // This used to be 10:35 (why?) but it gives better numbers
    // with this value.
    // I really need to figure out where I got that date ...
    //var Tepoch = new Date("2000 January 1 22:35 GMT");
    // Used to specify the date like this:
    //var Tepoch = new Date("2000 January 1 10:35 GMT");
    // but iCab can't handle it (though every other browser can)
    // so for iCab we specify it like this:
    var Tepoch = new Date("January 1, 2000 10:35 GMT");

    var T = (decimalYears(date) - decimalYears(Tepoch)) / 100.;
//    document.writeln("Tepoch1: " + Tepoch1.getTime() + ", Tepoch: "
//		     + Tepoch.getTime() + "\n");
//    document.writeln("seconds different: "
//		     + ((date.getTime() - Tepoch.getTime())/1000) + "\n");
    var T2 = T*T;
    var T3 = T2*T;
    var T4 = T3*T;

    // Mean elongation of the moon:
    var D = angle
	( 297.8502042
	 + 445267.1115168 * T
	 - 0.0016300 * T2
	 + T3 / 545868
	 + T4 / 113065000 );
    // Sun's mean anomaly:
    var M = angle
	( 357.5291092
	 + 35999.0502909 * T
	 - 0.0001536 * T2
	 + T3 / 24490000 );
    // Moon's mean anomaly:
    var Mprime = angle
	( 134.9634114
	 + 477198.8676313 * T
	 + 0.0089970 * T2
	 - T3 / 3536000
	 + T4 / 14712000 );

    this.phaseAngle = ( 180 - (D/DEG2RAD)
		    - 6.289 * Math.sin(Mprime)
		    + 2.100 * Math.sin(M)
		    - 1.274 * Math.sin(2*D - Mprime)
		    - 0.658 * Math.sin(2*D)
		    - 0.214 * Math.sin(2*Mprime)
		    - 0.110 * Math.sin(D) );

    // Get the selenographic longitude of the terminator
    // if phase is between 0 and 180,
    // it's waxing and we want the sunrise terminator:
    if (this.phaseAngle >= 0 && this.phaseAngle <= 180)
	this.terminator = this.phaseAngle - 90;
    else if (this.phaseAngle > 180)
	this.terminator = this.phaseAngle - 270;
    else
	this.terminator = this.phaseAngle + 90;

    // Done getting the phase angle; now calculate the position
    // and librations:

    // Moon's mean longitude:
    var Lprime = angle(218.3164591 + 481267.88134236 * T
                       - .0013268 * T2 + T3 / 538841 - T4 / 65194000);

    // Moon's argument of latitude (mean distance from ascending node):
    var F = angle(93.2720993 + 483202.0175273 * T
                  - .0034029 * T2 - T3 / 3526000 + T4 / 863310000);

    // Now, the fearsome neverending tables!
    var DcA = new Array(0, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 1, 0, 2, 0, 0,
                    4, 0, 4, 2, 2, 1, 1, 2, 2, 4, 2, 0, 2, 2, 1, 2,
                    0, 0, 2, 2, 2, 4, 0, 3, 2, 4, 0, 2, 2, 2, 4, 0,
                    4, 1, 2, 0, 1, 3, 4, 2, 0, 1, 2, 2);
    var McA = new Array(0, 0, 0, 0, 1, 0, 0, -1, 0, -1, 1, 0, 1, 0, 0, 0,
                    0, 0, 0, 1, 1, 0, 1, -1, 0, 0, 0, 1, 0, -1, 0, -2,
                    1, 2, -2, 0, 0, -1, 0, 0, 1, -1, 2, 2, 1, -1, 0,
                    0, -1, 0, 1, 0, 1, 0, 0, -1, 2, 1, 0, 0);
    var MpcA = new Array(1, -1, 0, 2, 0, 0, -2, -1, 1, 0, -1, 0, 1, 0, 1,
                     1, -1, 3, -2, -1, 0, -1, 0, 1, 2, 0, -3, -2,
                     -1, -2, 1, 0,
                     2, 0, -1, 1, 0, -1, 2, -1, 1, -2, -1, -1, -2, 0,
                     1, 4, 0, -2, 0, 2, 1, -2, -3, 2, 1, -1, 3, -1);
    var FcA = new Array(0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, -2, 2, -2,
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
                    0, 0, 0, -2, 2, 0, 2, 0, 0, 0, 0, 0, 0, -2, 0, 0,
                    0, 0, -2, -2, 0, 0, 0, 0, 0, 0, 0, -2);
    var ScA = new Array(6288774, 1274027, 658314, 213618, -185116, -114332,
                    58793, 57066, 53322, 45758, -40923, -34720, -30383,
                    15327, -12528, 10980, 10675, 10034, 8548, -7888,
                    -6766, -5163, 4987, 4036, 3994, 3861, 3665, -2689,
                    -2602, 2390, -2348, 2236,
                    -2120, -2069, 2048, -1773, -1595, 1215, -1110, -892,
                    -810, 759, -713, -700, 691, 596, 549, 537, 520,
                    -487, -399, -381, 351, -340, 330, 327, -323, 299, 294);

    var DcB = new Array(0, 0, 0, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0,
                    4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, 4,
                    0, 4, 2, 2, 2, 2, 0, 2, 2, 2, 2, 4, 2, 2, 0, 2, 1, 1,
                    0, 2, 1, 2, 0, 4, 4, 1, 4, 1, 4, 2);
    var McB = new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, -1, -1, -1,
                    1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0,
                    0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 1, 0, -1, -2, 0, 1, 1,
                    1, 1, 1, 0, -1, 1, 0, -1, 0, 0, 0, -1, -2);
    var MpcB = new Array(0, 1, 1, 0, -1, -1, 0, 2, 1, 2, 0, -2, 1, 0, -1, 0,
                     -1, -1, -1, 0, 0, -1, 0, 1, 1, 0, 0, 3, 0, -1,
                     1, -2, 0, 2, 1, -2, 3, 2, -3, -1, 0, 0, 1, 0, 1, 1, 0,
                     0, -2, -1, 1, -2, 2, -2, -1, 1, 1, -1, 0, 0);
    var FcB = new Array(1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1,
                    1, -1, -1, -1, 1, 3, 1, 1, 1, -1, -1, -1, 1, -1, 1,
                    -3, 1, -3, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 3, -1,
                    -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1);
    var ScB = new Array(5128122, 280602, 277693, 173237, 55413, 46271, 32573,
                    17198, 9266, 8822, 8216, 4324, 4200, -3359, 2463, 2211,
                    2065, -1870, 1828, -1794, -1749, -1565, -1492, -1475,
                    -1410, -1344, -1335, 1107, 1021, 833,
                    777, 671, 607, 596, 491, -451, 439, 422, 421, -366,
                    -351, 331, 315, 302, -283, -229, 223, 223, -220, -220,
                    -185, 181, -177, 176, 166, -164, 132, -119, 115, 107);

    // term involving the decreasing eccentricity of the earth's orbit:
    var E = 1 - .002516 * T - .0000074 * T2;
    var E2 = E*E;

    var sigma_l = 0.;
    var sigma_b = 0.;
    var ME;
    var i;
    for (i=0; i < ScA.length; ++i)
    {
        ME = 1;
        if (MpcA[i] == 1 || MpcA[i] == -1)
            ME = E;
        else if (MpcA[i] == 2 || MpcA[i] == -2)
            ME = E2;
        sigma_l += ScA[i] *
            Math.sin(DcA[i] * D + McA[i] * ME * M + MpcA[i] * Mprime
                     + FcA[i] * F);
    }
    for (i=0; i < ScB.length; ++i)
    {
        ME = 1;
        if (MpcB[i] == 1 || MpcB[i] == -1)
            ME = E;
        else if (MpcB[i] == 2 || MpcB[i] == -2)
            ME = E2;
        sigma_b += ScB[i] *
            Math.sin(DcB[i] * D + McB[i] * ME * M + MpcB[i] * Mprime
                     + FcB[i] * F);
    }

    // Three intermediate arguments, in radians:
    var A1 = angle(119.75 + 131.849*T);        // effect of Venus
    var A2 = angle(53.09 + 479264.29*T);       // effect of Jupiter
    var A3 = angle(313.45 + 481266*T);         // ??

    sigma_l += 3958 * Math.sin(A1) + 1962 * Math.sin(Lprime - F)
        + 318 * Math.sin(A2);
    sigma_b += 382 * Math.sin(A3) - 2235 * Math.sin(Lprime)
        + 175 * Math.sin(A1 - F) + 175 * Math.sin(A1 + F)
        + 127 * Math.sin(Lprime-Mprime) - 115 * Math.sin(Lprime+Mprime);
    // Note: sigmas are still in DEGREES (actually millions of degrees)

    // Finally, we can calculate the coordinates of the moon (in radians):
    this.lambda = modrad(Lprime + angle(sigma_l / 1000000));
    this.beta = angle(sigma_b / 1000000);
    // don't calculate delta, 'cause I didn't type in the coefficients

    var I = angle(1.5424167);      // inclination of lunar equator

    // calculate mean long. of ascending node of lunar orbit:
    var omega = angle(125.044555 - 1934.1361849 * T + .0020762 * T2
                      + T3 / 467410 - T4 / 60616000);

    // Fudge: don't count nutation in longitude for now:
    var delpsi = 0.;

    var W = modrad(this.lambda - delpsi - omega);
    var A = modrad(Math.atan2( (Math.sin(W)*Math.cos(this.beta)*Math.cos(I)
                                - Math.sin(this.beta)*Math.sin(I)),
                               (Math.cos(W) * Math.cos(this.beta))));

    // Calculate optical librations (also in radians) then convert to degrees:
    // libL is longitude (east), libB is latitude (north)
    this.libEast = (A - F)/DEG2RAD;
    if (this.libEast > 180) this.libEast -= 360;

    this.libNorth = Math.asin(-Math.sin(W) * Math.cos(this.beta)
				   * Math.sin(I)
                              - Math.sin(this.beta) * Math.cos(I));
    this.libNorth /= DEG2RAD;

    // skip the physical librations for now,
    // 'cause I don't want to type in another long table ...

    // Add the libration to the terminator position:
    this.terminator += this.libEast;
}

// Display an angle: convert to degrees and truncate significant digits
function deangle(num)
{
    return (Math.round(num / DEG2RAD * 100)) / 100.;
}

function roundit(num, precision)
{
    var pow10;
    if (precision == 1)
        pow10 = 10;
    else
        pow10 = 100;
    return Math.abs(Math.floor(num * pow10 + .5) / pow10);
}

function printWhatsUp(date, doc)
{
    /* Nav 3.0 gives "Not a number" for next comparison.  Sigh!
    if (doc == 0)
	doc = document;
    */

    // Observer's Handbook
    // December 15 has libration longitude +6 == east limb exposed
    // December 27 has lat=-7 == south limb exposed, long=-5 == west limb
    var moonEphem = new MoonEphem(date);
    drawMoonTbl(moonEphem);

    doc.writeln("<h2>What's Up on the Moon Tonight?</h2>");
    doc.writeln("<font color=\"orange\"><b>" + date + "</b></font><br>");
    doc.writeln("<p>The diagram at right represents the moon as it appears");
    doc.writeln("on the date shown, with grey showing the areas which are in sunlight,");
    doc.writeln("black showing the areas not lit.\n");
    doc.writeln("Usually, you'll see the most detail at the terminator, "
		+ "the edge of the lit area.\n<br>");
    doc.writeln("The links around the edges represent the libration charts, "
		+ "areas of the far side which are sometimes visible "
		+ "edge-on to observers on earth.<br>");

    var direc, whichterm, waxwane;
    if (moonEphem.terminator < 0)
        direc = "west";
    else
        direc = "east";
    if (moonEphem.phaseAngle >= 0 && moonEphem.phaseAngle <= 180) {
        whichterm = "sunrise";
        waxwane = "waxing"
    } else {
        whichterm = "sunset";
        waxwane = "waning"
    }

    // How many days old is the moon? 
    // Note, I'm not sure whether this should be -.5 or +.5.
    var day = Math.floor((180-moonEphem.phaseAngle) * 29.5 / 360 + .5);
    doc.writeln("<p>");
    doc.writeln(day + "-day old " + waxwane + " moon.<br>");
    doc.writeln("<font color=orange>");
    doc.writeln("The " + whichterm
		+ " terminator is at selenographic longitude ");
    doc.writeln(roundit(moonEphem.terminator, 1) + " degrees " + direc + ".");
    doc.writeln("</font>");

    var imday;
    if (day == 14 || day == 15)
	imday = "fm";
    else if (day < 10)
	imday = "0" + day;
    else
	imday = day;

    doc.writeln("<p>On libration charts (roman numerals),");
    doc.writeln("<font color=\"#ff99ff\">purple</font> indicates a favorable libration;");
    doc.writeln("<font color=\"#aaaaff\">blue</font> indicates a very favorable libration.");
    doc.writeln("In most cases the terminator has to be nearby ");
    doc.writeln("in order to see much detail in a libration zone.");
    doc.writeln("<br clear=all>");

    doc.writeln("<table align=center border=1>");
    doc.writeln("<tr><td rowspan=3 align=center>Current Ephemeris of the Moon<br>(degrees):");
    doc.writeln("<th colspan=1><th>latitude <th>longitude");
    doc.writeln("<tr><th>Geocentric Position: <td>" + deangle(moonEphem.beta)
		     + " <td>" + deangle(moonEphem.lambda));
    var EWlib, EWmag;
    EWlib = " ";
    EWmag = roundit(moonEphem.libEast, 2);
    if (moonEphem.libEast > 0) {
        EWlib = " E";
    } else if (moonEphem.libEast < 0) {
        EWlib = " W";
    }

    var NSlib, NSmag;
    NSlib = " ";
    NSmag = roundit(moonEphem.libNorth, 2);
    if (moonEphem.libNorth > 0)
        NSlib = " N";
    else if (moonEphem.libNorth < 0) {
        NSlib = " S";
    }

    doc.writeln("<tr><th>Optical Libration: <td>"
		     + NSmag + NSlib
		     + " <td>" + EWmag + EWlib);
    doc.writeln("</table><br clear=all>");

    doc.writeln("If you don't find what you want here, you might try today's ");
    doc.writeln("<a href=\"http://www.inconstantmoon.com/day_"
	        + imday
		+ ".htm\" target = \"_top\">Inconstant Moon</a>.");
}

// end hiding -->

