/*  2007-11-11  Moonphases.js JavaScript functions. Moonphases are for Time zone 0 (UTC)!

    Dr. Rolf Schröder
    Möörkenweg 37
    21029 Hamburg, Germany
    http://rschr.de

    The algorithm of the functions are mainly taken from the book:
  
    Astronomical Algorithms, Jean Meeus, 1991, First English Edition
*/

function dT(year)   // dT [days] = TD - UT  = Dynamical Time - Universal Time
//       ##                                   (Atomic Clocks - Earth Rotation)
//
//  This function is delicate: I used only a long time approximation given by Stephenson and Morrison (1995),
//  derived from 700 BCE to 1600 CE, which might give more or less large deviations for future dates.
//  Exchange or complete this function if better formulas are known.
{
  var y = year - 1820;
  return (-20 + 0.0031*y*y)/86400;
}

function moonPhaseDates(year) // Returns array of arrays of all New Moons, First Quaters, Full Moons, Last Quaters;
//       ##############          dArray[i] = [month,day,phase] (UTC) for entire year.
//                               Phase: 0|.25|.5|.75 for years >= 2000, 0|-.75|-.5|-.25 for years < 2000. 
//
// Note: dArray[2] contains the decimal day of Moon phase (UTC). Due to Meeus the mean error for the period
// 1980 to 2020 should be 3.8 seconds plus the error introduced by the uncertainness of function dT() (look
// at top of file).
// This function 'moonPhaseDates()' returns only the integer part of the day, it is truncated by Math.floor()
// (look at the end of this function).
//
{
  var MP = ["&#x263B;","&#x263D;","&#x263A;","&#x263E;"]; // Moon Phase Characters.: New Moon, 1st Quarter,...
//var MP = ["&#x25CF;","&#x25D0;","&#x25CB;","&#x25D1;"]; // Moon Phase Characters.: alternative character set  
  var flag, dy, i, j, k, n, m, y, JDE, T, Tq, E, M, M1, F, Om, sum, W;
  var Deg2Rad = Math.PI/180;
  var dArray = new Array(3);
  var moonDatesArray = new Array();
  var A = new Array();
  var B = [ 0.000325,                       // Additional corrections (Meeus)
            0.000165,
            0.000164,
            0.000126,
            0.000110,
            0.000062,
            0.000060,
            0.000056,
            0.000047,
            0.000042,
            0.000040,
            0.000037,
            0.000035,
            0.000023];
  y = Math.floor(year);
  k = Math.floor((y - 2000)*12.3685);      // (47.2)   (Meeus)
  for( flag=0; flag < 2; flag++)           // Two steps to evaluate adequate start value for k in 'while'-loop.
  { j = 0;                                 // Index for moonDatesArray[]; look at end of while-loop
    while(1)
    { T  = k/1236.85;                      // (47.3)
      Tq = T*T;
      JDE = 2451550.09765 + 29.530588853*k + Tq*(0.0001337 + T*(-0.000000150 + T*0.00000000073)); // (47.1)
      E  = 1 - T*(0.002516 + T*0.0000074);   // (45.6)
      M  = 2.5534 + 29.10535669*k - Tq*(0.0000218 + T*0.00000011);  // (47.4)
      M %= 360;
      M *= Deg2Rad;
      Ms = 201.5643 + 385.81693528*k + Tq*(0.0107438 + T*(0.00001239 - T*0.000000058)); // (47.5)
      Ms %= 360;
      Ms *= Deg2Rad;
      F  = 160.7108 + 390.67050274*k - Tq*(0.0016341 +T*(0.00000227 -T*0.000000011));   // (47.6)
      F %= 360;
      F *= Deg2Rad;
      Om = 124.7746 - 1.56375580*k + Tq*(0.0020691 + T*0.00000215);                     // (47.7)
      Om %= 360;
      Om *= Deg2Rad;
      A = [299.77 +  0.107408*k - Tq*0.009173,   // Planetary arguments   (Meeus)
           251.88 +  0.016312*k,
           251.83 + 26.651886*k,
           349.42 + 36.412478*k,
            84.66 + 18.206239*k,
           141.74 + 53.303771*k,
           207.14 +  2.435732*k,
           154.84 +  7.306860*k,
            34.52 + 27.261239*k,
           207.19 +  0.121824*k,
           291.34 +  1.844379*k,
           161.72 + 24.198154*k,
           239.56 + 25.513099*k,
           331.55 +  3.592518*k];
      for( i = 0; i < A.length; i++ )
      { A[i] %= 360;
        A[i] *= Deg2Rad;
      }
      W = 0;
      n = k%1;     // n: 0, +-0.25, +-0.5, +-0.75 (New Moon, 1st|3rd Quarter, Full Moon, 3rd|1st Quarter)
      switch(n)
      { case  0.5:  // Full Moon
        case -0.5:
          sum = -0.40614     * Math.sin(Ms)         // 1   (Meeus)
                +0.17302 * E * Math.sin(M)
                +0.01614     * Math.sin(2*Ms)
                +0.01043     * Math.sin(2*F)
                +0.00734 * E * Math.sin(Ms-M)       // 5
                -0.00515 * E * Math.sin(Ms+M)
                +0.00209 *E*E* Math.sin(2*M)
                -0.00111     * Math.sin(Ms-2*F)
                -0.00057     * Math.sin(Ms+2*F)
                +0.00056 * E * Math.sin(2*Ms+M)     // 10
                -0.00042     * Math.sin(3*Ms)
                +0.00042 * E * Math.sin(M+2*F) 
                +0.00038 * E * Math.sin(M-2*F)
                -0.00024 * E * Math.sin(2*Ms-M)
                -0.00017     * Math.sin(Om)         // 15
                -0.00007     * Math.sin(Ms+2*M)
                +0.00004     * Math.sin(2*Ms-2*F)
                +0.00004     * Math.sin(3*M)
                +0.00003     * Math.sin(Ms+M-2*F)
                +0.00003     * Math.sin(2*Ms+2*F)   // 20
                -0.00003     * Math.sin(Ms+M+2*F)
                +0.00003     * Math.sin(Ms-M+2*F)
                -0.00002     * Math.sin(Ms-M-2*F)
                -0.00002     * Math.sin(3*Ms+M)
                +0.00002     * Math.sin(4*Ms);      //25
        break;
        case  0.25:  //  First Quarters
        case -0.25:  //  Last Quarters
        case  0.75:  //  Last Quarters
        case -0.75:  //  First Quarters
          sum = -0.62801     * Math.sin(Ms)         // 1   (Meeus)
                +0.17172 * E * Math.sin(M)
                -0.01183 * E * Math.sin(Ms+M)
                +0.00862     * Math.sin(2*Ms)
                +0.00804     * Math.sin(2*F)        // 5
                +0.00454 * E * Math.sin(Ms-M)
                +0.00204 *E*E* Math.sin(2*M)
                -0.00180     * Math.sin(Ms-2*F)
                -0.00070     * Math.sin(Ms+2*F)
                -0.00040     * Math.sin(3*Ms)       // 10
                -0.00034 * E * Math.sin(2*Ms-M) 
                +0.00032 * E * Math.sin(M+2*F)  
                +0.00032 * E * Math.sin(M-2*F)
                -0.00028 *E*E* Math.sin(Ms+2*M)
                +0.00027 * E * Math.sin(2*Ms+M)     // 15
                -0.00017     * Math.sin(Om)
                -0.00005     * Math.sin(Ms-M-2*F)
                +0.00004     * Math.sin(2*Ms+2*F)
                -0.00004     * Math.sin(Ms+M+2*F)
                +0.00004     * Math.sin(Ms-2*M)     // 20
                +0.00003     * Math.sin(Ms+M-2*F)
                +0.00003     * Math.sin(3*M)
                +0.00002     * Math.sin(2*Ms-2*F)
                +0.00002     * Math.sin(Ms-M+2*F)
                -0.00002     * Math.sin(3*Ms+M);    //25
          W = 0.00306 - 0.00038*E*Math.cos(M) + 0.00026*Math.cos(Ms) -
              0.00002*Math.cos(Ms-M) + 0.00002*Math.cos(Ms+M) + 0.00002*Math.cos(2*F);
        break;
        default:    // New Moon (n == 0)	
          sum = -0.40720     * Math.sin(Ms)         // 1   (Meeus)
                +0.17241 * E * Math.sin(M)
                +0.01608     * Math.sin(2*Ms)
                +0.01039     * Math.sin(2*F)
                +0.00739 * E * Math.sin(Ms-M)       // 5
                -0.00514 * E * Math.sin(Ms+M)
                +0.00208 *E*E* Math.sin(2*M)
                -0.00111     * Math.sin(Ms-2*F)
                -0.00057     * Math.sin(Ms+2*F)
                +0.00056 * E * Math.sin(2*Ms+M)     // 10
                -0.00042     * Math.sin(3*Ms)
                +0.00042 * E * Math.sin(M+2*F) 
                +0.00038 * E * Math.sin(M-2*F)
                -0.00024 * E * Math.sin(2*Ms-M)
                -0.00017     * Math.sin(Om)         // 15
                -0.00007     * Math.sin(Ms+2*M)
                +0.00004     * Math.sin(2*Ms-2*F)
                +0.00004     * Math.sin(3*M)
                +0.00003     * Math.sin(Ms+M-2*F)
                +0.00003     * Math.sin(2*Ms+2*F)   // 20
                -0.00003     * Math.sin(Ms+M+2*F)
                +0.00003     * Math.sin(Ms-M+2*F)
                -0.00002     * Math.sin(Ms-M-2*F)
                -0.00002     * Math.sin(3*Ms+M)
                +0.00002     * Math.sin(4*Ms);      //25
        break;
      }
      for( i = 0; i < A.length; i++ ) sum += B[i] * Math.sin(A[i]); // look definition for A and B
      JDE += sum - dT(y);                        // For New and Full Moon
      if( n ==  0.25 || n == -0.75 ) JDE += W;   // Add if Lirst Quarter
      if( n == -0.25 || n ==  0.75 ) JDE -= W;   // Sub if Last  Quarter
      dArray = julday2dArray(JDE);
      if( flag == 0 )                            // set k to adequate start value
      { dy = (dArray2julday([y,1,1.0]) - dArray2julday(dArray))/365;
             // Note: ACCIDENTLY dArray2julday(dArray) works also for the year -4712!
        k += Math.floor(dy*12.3685)-1;
        break;                                   // break 'while'-loop in this step (flag==0).
      }
      if( dArray[0] >  y ) break;
      n = ( n < 0 ) ? 4*(1 + n) : 4*n;  //  Index for Moon Symbol; Correction for negative k
      if( dArray[0] > y-1 && dArray[0] <= y) moonDatesArray[j++] = [dArray[1],Math.floor(dArray[2]),MP[n]];
      k += 0.25;
    }  
  }
  return moonDatesArray;
}

