// ------------------------------------------------------------------------------

// ---------------------------------------------------------------------------------
// Retona la part dreta d'una cadena de text.
//
function Right(cText, nQuan)
{
 var l = cText.length;
 var c = cText.substr(l - nQuan);
 return c;
}

// ---------------------------------------------------------------------------------
// Converteix un número a cadena i justifica amb zeros per l'esquerra.
//
function StrZero(nNum, nQuan)
{
 var cTxt = Right("0000000000" + nNum, nQuan);
 return cTxt
}

// -----------------------------------------------------------------------------------------
// Retorna una cadena en format hora a partir de l'hora i els minuts numèrics.
//
function fHora(hores, minuts)
{
 var cTxt = '';
 if (hores==0 && minuts==0)
    {
     cTxt = '';
    }
 else
    {
     cTxt = StrZero(hores, 2) + ':' + StrZero(minuts, 2)
    }
 return cTxt;
}

// -----------------------------------------------------------------------------------------
// Converteix hores a angle com a cadena de text .
//
function fAngle(hores)
{
 var ang = "" + (15 * parseInt(10 * hores) / 10);
 if (ang == parseInt(ang)) ang += ".0";
 return ang;
}

// -----------------------------------------------------------------------------------------
// Converteix hores (o graus) a una cadena de text formatada.
//
function fHMS(hores, tipus)
{
 switch (tipus)
        {
         case (1):
         case (11):
              cSepa1 = ':';
              cSepa2 = ':';
              cSepa3 = '&nbsp;';
              break;
         case (2):
         case (21):
              cSepa1 = 'º';
              cSepa2 = "'";
              cSepa3 = '&quot;';
              break;
        }
 var txt1 = (hores<0 ? '-' : ' ');
 hores = Math.abs(hores);
 var hh = parseInt(hores)
 var hh = (hh<10 ? '0' : '') + hh;
 var mm = Math.abs(parseInt(60 * (hores - hh)));
 var mn = Math.abs(60 * (hores - hh));
 var ss = Math.abs(parseInt(60 * (mn - mm)));
 txt1 += hh + cSepa1 + (mm<10 ? '0' : '') + mm;
 if (tipus==1 || tipus==2)
     txt1 += cSepa2 + (ss<10 ? '0' : '') + ss + cSepa3;
 return txt1
}

// -----------------------------------------------------------------------------------------
// Converteix redians a graus.
//
function fGraus(r)
{
 var g = r * 180 / Math.PI;
 return g;
}

// -----------------------------------------------------------------------------------------
// Converteix graus a radians.
//
function fRadians(g)
{
 var r = g * Math.PI / 180;
 return r;
}

// -----------------------------------------------------------------------------------------
// Retorna la declinació del sol en una certa data.
//
function fDeclinacio(d, m, a)
{
 var nDia = fRadians(360 * (284 + Dia_Any(d, m, a)) / 365);
 var dec = 23.45 * Math.sin(nDia);
 return dec;
}

// -----------------------------------------------------------------------------------------
// Retorna la durada del dia.
//
function durada_dia(d, m, a, lat)
{
 decr = fRadians(fDeclinacio(d, m, a));
 latr = fRadians(lat);
 cosw = -Math.tan(decr) * Math.tan(latr);
 w = 2 * fGraus(Math.acos(cosw)) / 15;
 return w;
}

// -----------------------------------------------------------------------------------------
// Retorna la hora de posta del sol en format numèric.
//
function posta_sol(d, m, a, lat)
{
 sind = Math.sin(fRadians(fDeclinacio(d, m, a)));
 cosd = Math.cos(fRadians(fDeclinacio(d, m, a)));
 sinl = Math.sin(fRadians(lat));
 cosl = Math.cos(fRadians(lat));
 cosw = -(sind * sinl) / (cosd * cosl);
 ps = 12 + fGraus(Math.acos(cosw)) / 15;
 return ps;
}

// -----------------------------------------------------------------------------------------
// Retorna la sortida del sol en format numèric.
//
function sortida_sol(d, m, a, lat)
{
 return posta_sol(d, m, a, lat) - durada_dia(d, m, a, lat);
}

// -----------------------------------------------------------------------------------------
// Retorna l'alçada del sol en una data i hora i latitud.
//
function alcada_sol(d, m, a, h, nLat)
{
   m += 1;
   var nH = fRadians(15 * (h - 12));
   var nD = fRadians(fDeclinacio(d, m, a));
   var nA = Math.sin(Math.sin(nD) * Math.sin(nLat) + Math.cos(nD) * Math.cos(nLat) * Math.cos(nH));
   return nA;
}

// -----------------------------------------------------------------------------------------
// Retorna l'edat de la lluna des de l'última lluna nova.
//
function lluna_edat(d, m, a)
{
 var edat = 0;
 var q, a2, m2, p;
 m += 1;
 if (a < 100)
     a += 1900;
 q = parseInt(a / 19);
 a2 = 11 * (a - (q * 19)) + parseInt(a / 300) + parseInt(a / 400) + 8 - parseInt(a / 100);
 m2 = m - 2;
 if (m2 < 0)
     m2 = 12 - Math.abs(m2);
 a2 = a2 + m2 + d;
 p = 30 * parseInt(a2 / 29.530587962963);
 edat = a2 - p;
 // if (edat < 1) edat = edat + 29;
 while (edat < 1) edat = edat + 29;
 return edat;
}

// -----------------------------------------------------------------------------------------
// Retorna la fase de la lluna en text.
//
function lluna_fase(d, m, a, tip)
{
 var cFase, a2;
 cFase = '';
 a2 = lluna_edat(d, m, a);
 a2 = moonfx(a, m, d, 1);
 cFase = a2;
 if (a2 >= 0 && a2 < 3) cFase = (tip==1 ? "Nova" : "LlN");
 if (a2 > 2 && a2 < 14) cFase = (tip==1 ? "Creixent" : "QC");
 if (a2 > 13 && a2 < 17) cFase = (tip==1 ? "Plena" : "LlP");
 if (a2 > 16) cFase = (tip==1 ? "Minvant" : "QM");
 return cFase;
}

// -----------------------------------------------------------------------------------------
// Arctangent d'un angle.
//
function Math_atan (num)
{
 // return fGraus(Math.atan(num));
 return Math.atan(num);
}

// -----------------------------------------------------------------------------------------
// Sinus d'unangle.
//
function Math_sin (num)
{
 // return Math.sin(fRadians(num));
 return Math.sin(num);
}

// -----------------------------------------------------------------------------------------
// Cosinus d'un angle.
//
function Math_cos (num)
{
 // return Math.cos(fRadians(num));
 return Math.cos(num);
}

// -----------------------------------------------------------------------------------------
// Signe d'un valor numèric.
//
function Math_sgn (num)
{
 if (num >  0) nsgn = 1;
 if (num == 0) nsgn = 0;
 if (num <  0) nsgn = -1;
 return nsgn
}

// -----------------------------------------------------------------------------------------
// Sortida i posta de la lluna en variables globals.
//
function flluna (ndia, nmes, nany, nlat, nlong)
{
   // hora i minut de sortida i posta de la lluna
   // data gregoriana
   // latitud i longitud en graus
   b5 = nlat; // latitud
   l5 = nlong;// longitud
   h = 0;     // zona horaria -->>  -val(cfus$)
   d = ndia;  // dia
   m = nmes+1;  // mes
   y = nany;  // any
   nhsurt = 0;
   nmsurt = 0;
   nhpost = 0;
   nmpost = 0;
   // dim m(3, 3)
   p1 = 3.14159265;
   p2 = 2 * p1
   r1 = p1 / 180;
   k1 = 15 * r1 * 1.0027379
   l5 = l5 / 360;
   z0 = h / 24
   // calendar --> jd
   g = 1;
   if (y < 1582) g = 0;
   d1 = parseInt(d);
   f = d - d1 - .5
   j = -parseInt(7 * (parseInt((m + 9) / 12) + y) / 4)
   if (g != 0)
      {
       s = Math_sgn(m - 9)
       a = Math.abs(m - 9)
       j3 = parseInt(y + s * parseInt(a / 7))
       j3 = -parseInt((parseInt(j3 / 100) + 1) * 3 / 4)
      }
   j = j + parseInt(275 * m / 9) + d1 + g * j3
   j = j + 1721027 + 2 * g + 367 * y
   if (f < 0)
      {
       f = f + 1;
       j = j - 1;
      }
   t = (j - 2451545) + f
   // lst at 0h zone time
   t0 = t / 36525
   s = 24110.5 + 8640184.812999999 * t0
   s = s + 86636.6 * z0 + 86400 * l5
   s = s / 86400; s = s - parseInt(s)
   t0 = s * 360 * r1
   t = t + z0	
   // position loop
   for (var i = 1; i<=3; i++)
       {
        // gosub sarguments
	    // fundamental arguments
	    l = .606434 + .03660110129 * t
	    m = .374897 + .03629164709 * t
	    f = .259091 + .0367481952 * t
	    d = .827362 + .03386319198 * t
	    n = .347343 - .00014709391 * t
	    g = .993126 + .0027377785 * t
	    l = l - parseInt(l); m = m - parseInt(m)
	    f = f - parseInt(f); d = d - parseInt(d)
	    n = n - parseInt(n); g = g - parseInt(g)
	    l = l * p2; m = m * p2; f = f * p2
	    d = d * p2; n = n * p2; g = g * p2
	    v = .39558 * Math_sin(f + n)
	    v = v + .082 * Math_sin(f)
	    v = v + .03257 * Math_sin(m - f - n)
	    v = v + .01092 * Math_sin(m + f + n)
	    v = v + .00666 * Math_sin(m - f)
	    v = v - .00644 * Math_sin(m + f - 2 * d + n)
	    v = v - .00331 * Math_sin(f - 2 * d + n)
	    v = v - .00304 * Math_sin(f - 2 * d)
	    v = v - .0024 * Math_sin(m - f - 2 * d - n)
	    v = v + .00226 * Math_sin(m + f)
	    v = v - .00108 * Math_sin(m + f - 2 * d)
	    v = v - .00079 * Math_sin(f - n)
	    v = v + .00078 * Math_sin(f + 2 * d + n)
	    u = 1 - .10828 * Math_cos(m)
	    u = u - .0188 * Math_cos(m - 2 * d)
	    u = u - .01479 * Math_cos(2 * d)
	    u = u + .00181 * Math_cos(2 * m - 2 * d)
	    u = u - .00147 * Math_cos(2 * m)
	    u = u - .00105 * Math_cos(2 * d - g)
	    u = u - .00075 * Math_cos(m - 2 * d + g)
	    w = .10478 * Math_sin(m)
	    w = w - .04105 * Math_sin(2 * f + 2 * n)
	    w = w - .0213 * Math_sin(m - 2 * d)
	    w = w - .01779 * Math_sin(2 * f + n)
	    w = w + .01774 * Math_sin(n)
	    w = w + .00987 * Math_sin(2 * d)
	    w = w - .00338 * Math_sin(m - 2 * f - 2 * n)
	    w = w - .00309 * Math_sin(g)
	    w = w - .0019 * Math_sin(2 * f)
	    w = w - .00144 * Math_sin(m + n)
	    w = w - .00144 * Math_sin(m - 2 * f - n)
	    w = w - .00113 * Math_sin(m + 2 * f + 2 * n)
	    w = w - .00094 * Math_sin(m - 2 * d + g)
	    w = w - .00092 * Math_sin(2 * m - 2 * d)
	    //    compute ra, dec, dist
	    s = w / Math.sqrt(u - v * v)
	    a5 = l + Math_atan(s / Math.sqrt(1 - s * s))
	    s = v / Math.sqrt(u);
	    d5 = Math_atan(s / Math.sqrt(1 - s * s))
	    r5 = 60.40974 * Math.sqrt(u)
        if (i==1)
           {
            m11 = a5
            m12 = d5;
            m13 = r5;
           }
        if (i==2)
           {
            m21 = a5
            m22 = d5;
            m23 = r5;
           }
        if (i==3)
           {
            m31 = a5
            m32 = d5;
            m33 = r5;
           }
        t = t + .5
       }
   if (m21 < m11) m21 = m21 + p2
   if (m31 <= m21) m31 = m31 + p2
   z1 = r1 * (90.567 - 41.685 / m23)
   s = Math_sin(b5 * r1);
   c = Math_cos(b5 * r1);
   z = Math_cos(z1);
   m8 = 0;
   w8 = 0;
   a0 = m11;
   d0 = m12;
   for (var c0 = 0; c0<=23; c0++)
       {
        p = (c0 + 1) / 24;
        f0 = m11;
        f1 = m21;
        f2 = m31;
        a = f1 - f0;
        b = f2 - f1 - a;
        f = f0 + p * (2 * a + b * (2 * p - 1));
        a2 = f;
        f0 = m12;
        f1 = m22;
        f2 = m32;
        a = f1 - f0;
        b = f2 - f1 - a;
        f = f0 + p * (2 * a + b * (2 * p - 1));
        d2 = f;
        // gosub shora
	    // test an hour for an event
	    l0 = t0 + c0 * k1;
	    l2 = l0 + k1;
	    if (a2 < a0) a2 = a2 + 2 * p1;
	    h0 = l0 - a0;
	    h2 = l2 - a2;
	    h1 = (h2 + h0) / 2; // rem  hour angle
	    d1 = (d2 + d0) / 2; // rem  dec
	    if (c0 <= 0) v0 = s * Math_sin(d0) + c * Math_cos(d0) * Math_cos(h0) - z
	    v2 = s * Math_sin(d2) + c * Math_cos(d2) * Math_cos(h2) - z
	    if (Math_sgn(v0) != Math_sgn(v2))
	      {
	       v1 = s * Math_sin(d1) + c * Math_cos(d1) * Math_cos(h1) - z
	       a = 2 * v2 - 4 * v1 + 2 * v0;
	       b = 4 * v1 - 3 * v0 - v2;
	       d = b * b - 4 * a * v0;
	       if (d >= 0)
	         {
	          d = Math.sqrt(d)
	          if (v0 < 0 && v2 > 0) m8 = 1;
	          if (v0 > 0 && v2 < 0) w8 = 1;
	          e = (-b + d) / (2 * a);
	          if (e > 1 || e < 0) e = (-b - d) / (2 * a);
	          t3 = c0 + e + 1 / 120; //  round off
	          h3 = parseInt(t3);
	          m3 = parseInt((t3 - h3) * 60);
                  if (v0<0 && v2>0)     {nhsurt = h3; nmsurt = m3;}
	          if (v0 > 0 && v2 < 0) {nhpost = h3; nmpost = m3}
	          h7 = h0 + e * (h2 - h0)
	          n7 = -Math_cos(d1) * Math_sin(h7)
	          d7 = c * Math_sin(d1) - s * Math_cos(d1) * Math_cos(h7)
	          a7 = Math_atan(n7 / d7) / r1
	          if (d7 < 0) a7 = a7 + 180;
	          if (a7 < 0) a7 = a7 + 360;
	          if (a7 > 360) a7 = a7 - 360;
	         }
	      }
        a0 = a2;
        d0 = d2;
        v0 = v2;
       }
   // if (nhsurt < 0) nhsurt = 0;
   // if (nhpost < 0) nhpost = 0;
   // if (nhsurt==0 && nmsurt==0) {nhsurt = ""; nmsurt = "";};
   // if (nhpost==0 && nmpost==0) {nhpost = ""; nmpost = "";};
}

// -----------------------------------------------------------------------------------------
// Data i hora d'inici de les estacions, en variables globals.
//
function estacions(aa)
{
    JD = 0.22976 + 1721139.2855 + 365.2421376*aa + Math.pow(.067919*(aa/1000), 2) - Math.pow(.0027879*(aa/1000), 3);
    T1 = JD;
    GD = Gregoria_Dia(JD); // GOSUB 350
    DY = parseInt(GD);
    HR = parseInt((GD - DY) * 24);
    MN = parseInt(((GD - DY) * 24 - HR) * 60);
    pdi = StrZero(DY, 2) + '.03 - ' + StrZero(HR, 2) + ':' + StrZero(MN, 2) + 'Z';

    JD = -0.1250 + 1721233.2486 + 365.2417284*aa - Math.pow(.053018*(aa/1000), 2) + Math.pow(.009332*(aa/1000),3);
    T2 = JD;
    GD = Gregoria_Dia(JD); // GOSUB 350
    DY = parseInt(GD);
    HR = parseInt((GD - DY) * 24);
    MN = parseInt(((GD - DY) * 24 - HR) * 60);
    edi = StrZero(DY, 2) + '.06 - ' +StrZero(HR, 2) + ':' + StrZero(MN, 2) + 'Z';

    JD = -0.4166 + 1721325.6978 + 365.2425055*aa - Math.pow(.126689*(aa/1000), 2) + Math.pow(.0019401*(aa/1000), 3);
    T3 = JD;
    GD = Gregoria_Dia(JD); // GOSUB 350
    DY = parseInt(GD);
    HR = parseInt((GD - DY) * 24);
    MN = parseInt(((GD - DY) * 24 - HR) * 60);
    tdi = StrZero(DY, 2) + '.09 - ' + StrZero(HR, 2) + ':' + StrZero(MN,2) + 'Z';

    JD = -0.1041 + 1721414.392 + 365.2428898*aa - Math.pow(.010965*(aa/1000), 2) - Math.pow(8.488501E-03*(aa/1000), 3);
    T4 = JD;
    GD = Gregoria_Dia(JD); // GOSUB 350
    DY = parseInt(GD);
    HR = parseInt((GD - DY) * 24);
    MN = parseInt(((GD - DY) * 24 - HR) * 60);
    hdi = StrZero(DY, 2) + '.12 - ' + StrZero(HR, 2) + ':' + StrZero(MN, 2) + 'Z';

    pdu = T2 - T1; pdu = parseInt(pdu * 100) / 100;
    edu = T3 - T2; edu = parseInt(edu * 100) / 100;
    tdu = T4 - T3; tdu = parseInt(tdu * 100) / 100;
    hdu = T1 + 365.2422 - T4; hdu = parseInt(hdu * 100) / 100;
}

// -----------------------------------------------------------------------------------------
// Passa d'un dia julià a una data gregoriana.
// 
function Gregoria_Dia(JD)
{
    //  DIA JULIANO A FECHA CALENDARIO GREGORIANO  *
    JZ = JD + .5;
    JI = parseInt(JZ);
    JF = JZ - JI;
    if (JI < 2299161) JA = JI;
    if (JI >= 2299161)
       {
        AL = parseInt((JI - 1867216.25)/36524.25);
        JA = JI + 1 + AL - parseInt(AL / 4);
       }
    JB = JA + 1524;
    JC = parseInt((JB - 122.1) / 365.25);
    KD = parseInt(365.25 * JC);
    JE = parseInt((JB - KD) / 30.6001);
    GD = JB - KD - parseInt(30.6001 * JE) + JF;
    if (JE < 13.5)
        GM = JE - 1
    else
        GM = JE - 13;
    if (GM > 2.5) 
        GY = JC - 4716
    else
        GY = JC - 4715;
    return GD;
}

// -----------------------------------------------------------------------------------------
// Dia i hora de diverses pluges d'estels.
//
function meteor_shower(Y, tipus)
{
 // METEOR SHOWERS
 // *******************************
 //  FOR ANY GIVEN YEAR, THIS PROGRAM LISTS THE MAJOR METEOR SHOWERS
 //  AND THE UT DATES OF MAXIMUM ACTIVITY.
 //  FROM SKY & TELESCOPE, AUG '89, P. 195.
 // *******************************
 var cRetorn = '';
 var R1=3.1415927/180;
 var MS = new Array(12);
 var NS = new Array(9);
 var S0 = new Array(9);
 var S1 = new Array(9);
 var J5 = new Array(9);
 var hrs = 0;
 var hr = 0;
 var mn = 0;

 NS [1] = "Quadràntides";    S0[1] = 282.9; S1[1] = -0.4; J5[1] = 285.3;
 NS [2] = "Lírides";         S0[2] =  31.7; S1[2] =  0.06;J5[2] = 393.9;
 NS [3] = "Eta Aquàrides";   S0[3] =  44.0; S1[3] =  0.3; J5[3] = 406.6;
 NS [4] = "Delta Aquàrides"; S0[4] = 125.0; S1[4] = -1.0; J5[4] = 491.2;
 NS [5] = "Persèides";       S0[5] = 139.2; S1[5] =  0.03;J5[5] = 506.0;
 NS [6] = "Oriònides";       S0[6] = 207.7; S1[6] =  0.4; J5[6] = 576.2;
 NS [7] = "Tàurides";        S0[7] = 220.0; S1[7] =  0.44;J5[7] = 588.5;
 NS [8] = "Leònides";        S0[8] = 234.3; S1[8] =  1.5; J5[8] = 602.7;
 NS [9] = "Gemínides";       S0[9] = 261.4; S1[9] =  0;   J5[9] = 629.5;

 if (tipus == 1)
    {
     for (I=1;I<=9;I++)
          {
           cRetorn += '&nbsp;&nbsp;' + NS[I] + '<br>';
          }
     return cRetorn;
    }

 T5 = (Y-1950)/100;
 for (I=1;I<=9;I++)
     {
      if (Math.abs(T5)>=1.5)
          if (I==1 || I==4 || I==9) continue;
      S = S0[I] + S1[I] * T5;
      S = S + 1.39663 * T5 + .0003 * T5 * T5;
      S = S - 360 * parseInt(S / 360);
      J = J5[I] + 36525.636 * T5 + S1[I] * T5;
      for (K=1; K<=2; K++)
          {
           T = (J + 2433000 - 2415020) / 36525;
           L = 279.7 + 36000.769 * T + .0003 * T * T;
           M = 358.48 + 35999.05 * T - .0002 * T * T;
           S5 = L + (1.92 - .005 * T) * Math.sin(M * R1);
           S5 = S5 + .02 * Math.sin(2 * M * R1);
           S5 = S5 - 360 * parseInt(S5 / 360);
           J = J - (S5 - S) / (.986 + .033 * Math.cos(M * R1));
          }
      F = J - parseInt(J);
      J = parseInt(J) + 2433000;

      G = 1;
      if (J<2299161) G=0;
      F = F + .5
      if (F>=1)
          {
           F = F - 1;
           J = J + 1;
          }
      if (G!=1)
          A = J
      else
          {
           A1 = parseInt((J / 36524.25) - 51.12264);
           A = J + 1 + A1 - parseInt(A1 / 4);
          }
      B = A + 1524;
      C = parseInt((B / 365.25) - .3343);
      D = parseInt(365.25 * C);
      E = parseInt((B - D) / 30.61);
      D = B - D - parseInt(30.61 * E) + F;
      M = E - 1;
      Y = C - 4716;
      if (E>13.5) M = M - 12;
      if (M<2.5) Y = Y + 1;

      D = D + 0.5;
      hrs = D - parseInt(D);
      D = parseInt(D);
      hr = parseInt(hrs * 24);
      mn = parseInt((hrs*24 - parseInt(hrs*24))*60);

      cRetorn += (D<10 ? '0' : '') + D + '.' + (M<10 ? '0' : '') + M + '.' + Y;
      cRetorn += '&nbsp;&nbsp;';
      cRetorn += (hr<10 ? '0' : '') + hr + '.' + (mn<10 ? '0' : '') + mn + 'Z';
      cRetorn += '<br>';
     }
 return cRetorn;
}

// -----------------------------------------------------------------------------------------
// Posició X Y Z del sol, a una data i hora concreta.
//
function sol_xyz(an, me, di, ho, mi, se)
{
// REM    X,Y,Z OF THE SUN
// REM    (EQUINOX 1950.0)
// REM
// 503 INPUT "J,F ";J,F
 J  = Dia_Julia(di, me, an)
 F  = (ho + mi/60)/24;
 J8 = J - 2415020;
 R1 = 3.14159265 / 180;
 T  = (J8 + F) / 36525;
 P0 = 1.396041 + 0.000308 * (T + 0.5);
 P0 = P0 * (T - 0.499998);
 A  = 100;
 A = 360 * (A * T - parseInt(A * T)); // GOSUB 529
 G0 = A + 358.475833;
 L0 = A + 279.696678 - P0;
 A  = 1336;
 A = 360 * (A * T - parseInt(A * T)); // GOSUB 529  
 C0 = A + 270.434164 - P0;
 A  = 162;
 A = 360 * (A * T - parseInt(A * T)); // GOSUB 529  
 V0 = A + 212.603219;
 A  = 53;
 A = 360 * (A * T - parseInt(A * T)); // GOSUB 529
 M0 = A + 319.529425;
 A  = 8;
 A = 360 * (A * T - parseInt(A * T)); // GOSUB 529
 J0 = A + 225.444651;
 G  = G0 + T * (-0.950250 - 0.000150 * T);
 C  = C0 + T * (307.883142 - 0.001133 * T);
 L  = L0 + T * (0.768920 + 0.000303 * T);
 V  = V0 + T * (197.803875 + 0.001286 * T);
 M  = M0 + T * (59.8585 + 0.000181 * T);
 J  = J0 + T * 154.906654;
 G  = G * R1;
 C  = C * R1;
 L  = L * R1;
 V  = V * R1;
 M  = M * R1;
 J  = J * R1;
 X = 0.000011 * Math_cos(2*G-L-2*J);
 X = X + 0.000011 * Math_cos(2*G+L-2*V);
 X = X - 0.000012 * Math_cos(G+L-V);
 X = X - 0.000012 * Math_cos(4*G-L-8*M+3*J);
 X = X + 0.000012 * Math_cos(4*G+L-8*M+3*J);
 X = X - 0.000014 * Math_cos(C-2*L);
 X = X + 0.000017 * Math_cos(C);
 X = X + 0.000018 * Math_sin(2*G+L-2*V);
 X = X - 0.000021 * T*Math_cos(G+L);
 X = X - 0.000026 * Math_sin(G-L-J);
 X = X + 0.000035 * Math_cos(2*G-L);
 X = X + 0.000063 * T*Math_cos(G-L);
 X = X + 0.000105 * Math_cos(2*G+L);
 X = X + 0.008374 * Math_cos(G+L);
 X = X - 0.025127 * Math_cos(G-L);
 X = X + 0.999860 * Math_cos(L);
 Y = 0.000010 * Math_sin(2*G+L-2*V);
 Y = Y - 0.000010 * Math_sin(2*G-L-2*J);
 Y = Y - 0.000011 * Math_sin(G+L-V);
 Y = Y + 0.000011 * Math_sin(4*G-L-8*M+3*J);
 Y = Y + 0.000011 * Math_sin(4*G+L-8*M+3*J);
 Y = Y + 0.000013 * Math_sin(C-2*L);
 Y = Y + 0.000016 * Math_sin(C);
 Y = Y - 0.000017 * Math_cos(2*G+L-2*V);
 Y = Y - 0.000019 * T*Math_sin(G+L);
 Y = Y - 0.000024 * Math_cos(G-L-J);
 Y = Y - 0.000032 * Math_sin(2*G-L);
 Y = Y - 0.000057 * T*Math_sin(G-L);
 Y = Y + 0.000097 * Math_sin(2*G+L);
 Y = Y + 0.007683 * Math_sin(G+L);
 Y = Y + 0.023053 * Math_sin(G-L);
 Y = Y + 0.917308 * Math_sin(L);
 Z = -0.000010 * Math_cos(G-L-J);
 Z = Z - 0.000014 * Math_sin(2*G-L);
 Z = Z - 0.000025 * T*Math_sin(G-L);
 Z = Z + 0.000042 * Math_sin(2*G+L);
 Z = Z + 0.003332 * Math_sin(G+L);
 Z = Z + 0.009998 * Math_sin(G-L);
 Z = Z + 0.397825 * Math_sin(L);
 // PRINT "X: ";X
 // PRINT "Y: ";Y
 // PRINT "Z: ";Z
 //END

// 529 REM   NORMALIZATION
// 530 A=360*(A*T-INT(A*T)): RETURN

 retorn  = 'x = ' + decimals(fGraus(X), 2) + '<br>';
 retorn += 'y = ' + decimals(fGraus(Y), 2) + '<br>';
 retorn += 'z = ' + decimals(fGraus(Z), 2);
return retorn;
}

// -----------------------------------------------------------------------------------------
// Retorna diferents paràmetres de la lluna, segons valor d'entrada.
//
function moonfx(nAny, nMes, nDia, nTip)
{
  // '    MOON EFFECTS by Bradley E. Schaefer
  // '    This program helps anyone who needs to know the Moon's 
  // '    phase (age), distance, and position along the ecliptic on
  // '    any date within several thousand years in the past or future.
  // '    To illustrate its application, Bradley Schaefer applied it 
  // '    to a number of famous events influenced by the Moon in 
  // '    World War II.  His article appeared in Sky & Telescope for
  // '    April 1994, page 86.
  var P2, YY, MxM, K1, K2, K3, J, V, IP, AG, DP, DI, NP, LA, RP, LO, nRetorn;
  //
  nMes += 1;
  P2 = 2*3.14159;
  YY = nAny - parseInt((12 - nMes) / 10);
  MxM = nMes + 9;
  if (MxM>=12) MxM = MxM - 12;
  K1 = parseInt(365.25 * (YY + 4712));
  K2 = parseInt(30.6 * MxM + .5);
  K3 = parseInt(parseInt((YY / 100) + 49) * .75) - 38;
  J  = K1 + K2 + nDia + 59; // '  JD for dates in Julian calendar
  if (J>2299160) J = J - K3; // ' For Gregorian calendar
  // '  J is the Julian date at 12h UT on day in question
  // '  Calculate illumination (synodic) phase
  V = (J - 2451550.1) / 29.530588853;
  V = V - parseInt(V);
  if (V<0) V = V + 1;
  IP = V;
  AG = IP * 29.53; // ' Moon's age in days
  IP = IP * P2; //  '    Convert phase to radians
  // '  Calculate distance from anomalistic phase
  V = (J-2451562.2) / 27.55454988;
  V = V - parseInt(V);
  if (V<0) V = V + 1;
  DP = V;
  DP = DP * P2; // '  Convert to radians
  DI = 60.4 - 3.3 * Math.cos(DP) - .6 * Math.cos(2 * IP - DP) - .5 * Math.cos(2 * IP);
  // '  Calculate latitude from nodal (draconic) phase
  V = (J - 2451565.2) / 27.212220817;
  V = V - parseInt(V);
  if (V<0) V = V + 1;
  NP = V;
  NP = NP * P2; // ' Convert to radians
  LA = 5.1 * Math.sin(NP);
  // '  Calculate longitude from sidereal motion
  V = (J - 2451555.8) / 27.321582241;
  V = V - parseInt(V);
  if (V<0) V = V + 1;
  RP = V;
  LO = 360 * RP + 6.3 * Math.sin(DP) + 1.3 * Math.sin(2 * IP - DP) + .7 * Math.sin(2 * IP);
  nRetorn = 0;
  switch(nTip)
        {
         case (1):
              // PRINT USING "Moon's age from new (days):   ###";AG
              nRetorn = AG;
              break;
         case (2):
              // PRINT USING "Distance (Earth radii):       ###";DI
              nRetorn = DI;
              break;
         case (3):
              // PRINT USING "Ecliptic latitude (degrees):  ###";LA
              nRetorn = LA;
              break;
         case (4):
              // PRINT USING "Ecliptic longitude (degrees): ###";LO
              nRetorn = LO;
              break;
        }
  return nRetorn;
}

// -----------------------------------------------------------------------------------------
// Data i hora els eclipsis de lluna d'un any determinat.
//
function lluna_eclipsis(Y)
{
  // REM ***********************
  // REM THIS IS THE *COMPLETE* PROGRAM FOR PREDICTING LUNAR ECLIPSES
  // REM (SEE SKY & TELESCOPE, JUNE, 1988, PAGE 640)
  // REM ***********************
  // REM NEW AND FULL MOONS
  // INPUT "YEAR ";Y
  var cRetorn = '';
  var nAny = Y;
  var D1=0, M=0;
  R1 = 3.14159265 / 180;
  U  = 0;
  G  = 1;
  if (Y<1583) G = 0;
  K0 = parseInt((Y - 1900) * 12.3685);
  T  = (Y - 1899.5) / 100;
  T2 = T * T;
  T3 = T * T * T;
  J0 = 2415020 + 29 * K0;
  F0 = 0.0001178 * T2 - 0.000000155 * T3;
  F0 = F0 + 0.75933 + 0.53058868 * K0;
  F0 = F0 - 0.000837 * T - 0.000335 * T2;
  J0 = J0 + parseInt(F0);
  F0 = F0 - parseInt(F0);
  M0 = K0 * 0.08084821133;
  M0 = 360 * (M0 - parseInt(M0)) + 359.2242;
  M0 = M0 - 0.0000333 * T2;
  M0 = M0 - 0.00000347 * T3;
  M1 = K0 * 0.07171366128;
  M1 = 360 * (M1 - parseInt(M1)) + 306.0253;
  M1 = M1 + 0.0107306 * T2;
  M1 = M1 + 0.00001236 * T3;
  B1 = K0 * 0.08519585128;
  B1 = 360 * (B1 - parseInt(B1)) + 21.2964;
  B1 = B1 - 0.0016528 * T2;
  B1 = B1 - 0.00000239 * T3;
  for (K9=1;K9<=27;K9+=2)
      {
       J  = J0 + 14 * K9;
       F  = F0 + 0.765294 * K9;
       K  = K9 / 2;
       M5 = (M0 + K * 29.10535608) * R1;
       M6 = (M1 + K * 385.81691806) * R1;
       B6 = (B1 + K * 390.67050646) * R1;
       F  = F - 0.4068 * Math.sin(M6);
       F  = F + (0.1734 - 0.000393 * T) * Math.sin(M5);
       F  = F + 0.0161 * Math.sin(2 * M6);
       F  = F - 0.0104 * Math.sin(2 * B6);
       F  = F - 0.0074 * Math.sin(M5 - M6);
       F  = F - 0.0051 * Math.sin(M5 + M6);
       F  = F + 0.0021 * Math.sin(2 * M5);
       F  = F + 0.5 / 1440;
       J  = J + parseInt(F);
       F  = F - parseInt(F);
       // LUNAR ECLIPSE SUBROUTINE
       D7 = 0;
       if (Math.abs(Math.sin(B6))<=0.36)
          {
           S = 5.19595 - 0.0048 * Math.cos(M5);
           S = S + 0.0020 * Math.cos(2 * M5);
           S = S - 0.3283 * Math.cos(M6);
           S = S - 0.0060 * Math.cos(M5 + M6);
           S = S + 0.0041 * Math.cos(M5 - M6);
           C1= 0.2070 * Math.sin(M5);
           C1= C1 + 0.0024 * Math.sin(2 * M5);
           C1= C1 - 0.0390 * Math.sin(M6);
           C1= C1 + 0.0115 * Math.sin(2 * M6);
           C1= C1 - 0.0073 * Math.sin(M5 + M6);
           C1= C1 - 0.0067 * Math.sin(M5 - M6);
           C1= C1 + 0.0117 * Math.sin(2 * B6);
           D9= Math.abs(S * Math.sin(B6) + C1 * Math.cos(B6));
           U = 0.0059 + 0.0046 * Math.cos(M5);
           U = U - 0.0182 * Math.cos(M6);
           U = U + 0.0004 * Math.cos(2 * M6);
           U = U - 0.0005 * Math.cos(M5 + M6);
           RP= 1.2847 + U;
           RU= 0.7404 - U;
           MP= (1.5572 + U - D9) / 0.545;
           if (MP>=0)
               {
                MU= (1.0129 - U - D9) / 0.545;
                D5= 1.5572 + U;
                D6= 1.0129 - U;
                D7= 0.4679 - U;
                N = (0.5458 + 0.04 * Math.cos(M6)) / 60;
                D5= Math.sqrt(D5 * D5 - D9 * D9) / N;
                if (MU>0)
                   {
                    D6 = Math.sqrt(D6 * D6 - D9 * D9) / N;
                    if (MU>1)
                       {
                        D7 = Math.sqrt(D7 * D7 - D9 * D9) / N;
                       }
                   }
                // JD --> CALENDAR
                F = F + 0.5;
                if (F>=1)
                   {
                    F = F - 1;
                    J = J + 1;
                   }
                if (G=1)
                   {
                    A1 = parseInt((J / 36524.25) - 51.12264);
                    A  = J + 1 + A1 - parseInt(A1 / 4);
                   }
                else
                   {
                    A = J;
                   }
                B = A + 1524;
                C = parseInt((B / 365.25) - 0.3343);
                D = parseInt(365.25 * C);
                E = parseInt((B - D) / 30.61);
                D = B - D - parseInt(30.61 * E) + F;
                M = E - 1;
                Y = C - 4716;
                if (E>13.5) M = M - 12;
                if (M<2.5) Y = Y + 1;
                D1= parseInt(D);
                H = 24 * (D - D1);
                H1= parseInt(H);
                M9= parseInt(60 * (H - H1));
                MP= parseInt(1000 * MP + 0.5) / 1000;
                if (MU>0)
                   {
                    MU= parseInt(1000 * MU + 0.5) / 1000;
                   }
                D5= parseInt(D5 + 0.5);
                if (MU>=0)
                   {
                    D6= parseInt(D6 + 0.5);
                    D7= parseInt(D7 + 0.5);
                   }
                // cRetorn += 'Data : ' + (D1<10?'0':'') + D1 + '.' + (M<10?'0':'') + M + '.' + nAny + '<br>';
                // cRetorn += 'Fase màxima : ' + H1 + 'h ' + M9 + 'm UTC<br>';
                // cRetorn += 'Magnitud penombra : ' + MP + '<br>';
                // cRetorn += 'Magnitud ombra : ' + MU + '<br>';
                // cRetorn += ' Durada penombra : ' + D5 + 'm<br>';
                // cRetorn += ' Durada ombra : ' + D6 + 'm<br>';
                // cRetorn += ' Durada totalitat : ' + D7 + 'm<br>';
                // cRetorn += '<br>';
                cRetorn += (D1<10?'0':'') + D1 + '.' + (M<10?'0':'') + M + '.' + nAny;
                cRetorn += '&nbsp;&nbsp;';
                cRetorn += (H1<10?'0':'') + H1 + ':' + (M9<10?'0':'') + M9 + 'Z';
                cRetorn += '<br>';
               }
          }
      }
  return cRetorn;
}

// ---------------------------------------------------------------------------------
// Funció de suport de la funció planetes.
//
function fplanetes_a(s, c)
{
 var x = Math.atan(s / c) - Math.PI * (c<0 ? -1 : 0) - 2*Math.PI * (c>=0 && s<0 ? -1 : 0);
 return x;
}

// ---------------------------------------------------------------------------------
// Dades dels planetes. Retorna HTML.
//
function planetes(lat, lon, d, m, a)
{
 var quants_planetes = 8;
 var nom = new Array("Sol", "Mercuri", "Venus",   "Mart",    "Jupiter", "Saturn",  "Urà",    "Neptú", "Plutó");
 var  e1 = new Array(0,     0.24085,   0.61521,   1.88089,   11.86224,  29.45771,  84.01247, 165,     248);
 var  e2 = new Array(0,     4.036899,  6.208721,  2.204488,   2.565047,  2.850511,  3.980587,  0,       0);
 var  e3 = new Array(0,     0.3870986, 0.7233316, 1.5236883,  5.202561,  9.554747, 19.21814,  30.06,   39.44);
 var rlat = lat * Math.PI/180;
 var rlon = lon * Math.PI/180;
 var bis, diany, na, n4, nr, dd, tsl;
 var txt = '';
 txt += '<table width="100%" border="0">';
 txt += '<tr><td width="40%" class="fontExplica"></td>';
 txt += '<td width="15%" class="fontExplica" align="right">A.R.</td>';
 txt += '<td width="15%" class="fontExplica" align="right">Dec</td>';
 txt += '<td width="15%" class="fontExplica" align="right">H.S.</td>';
 txt += '<td width="15%" class="fontExplica" align="right">H.P.</td>';
 txt += '</tr>';
 m = m + 1;
 // Dia de l'any.
 bis = (leapyear(a) ? 1 : 0);
 if (m > 2)
     diany = parseInt((m + 1) * 30.6) - 63 + bis + d
 else
     diany = parseInt(((m - 1) + (62 + bis)) / 2) + d;
 // Dies des de 1980
 na = a - 1980;
 if (na < 0)
    {
     n4 = -parseInt(-na / 4);
     nr = na - 4 * n4;
     dd = n4 * (4 * 365 + 1) + 365 * nr + diany;
    }
 else
    {
     n4 = parseInt(na / 4);
     nr = na - 4 * n4;
     dd = n4 * (4 * 365 + 1) + 365 * nr - (nr>0 ? -1 : 0) + diany;
    }
 // Temps sideri local a les 12Z
 tsl = 0.01720279299 * dd;
 while (tsl > 2 * Math.PI) tsl -= 2 * Math.PI;
 while (tsl < 0) tsl += 2 * Math.PI;
 tsl += -4.558313 + rlon;
 for (ip = 0; ip <= quants_planetes; ip++)
     {
      // Window.status = 'Planeta : ' + nom[ip];
      txt += '<tr><td width="40%" class="fontExplica">';
      txt += nom[ip];
      if (ip == 0)
         {
          // Sol
          lsol = 2 * Math.PI * (dd + 0.5) / 365.2422 + 4.866563;
          sinl = Math.sin(lsol);
          cosl = Math.cos(lsol);
          l    = lsol + 2 * 0.016718 * Math.sin(lsol - 4.932238);
         }
      else
         {
          // Planetes
          lp  = 2 * Math.PI * dd / (365.2422 * e1[ip] + e2[ip]);
          slp = e3[ip] * Math.sin(lp) + sinl;
          clp = e3[ip] * Math.cos(lp) + cosl;
          l   = fplanetes_a(slp, clp);
         }
      // Coordenades equatorials
      sl  = Math.sin(l);
      ar  = fplanetes_a(sl * 0.9175234, Math.cos(l));
      s   = sl * 0.3976818;
      dec = Math.atan(s / Math.sqrt(1 - s * s));

      // Ascensió recta
      ang = ar * 12 / Math.PI;
      txt += '</td><td width="15%" class="fontDadesCalend" align="right">';
      txt += fHMS(ang, 11) + '&nbsp;&nbsp;';
      txt += '</td>';

      // Declinació
      ang = dec * 180 / Math.PI;
      txt += '</td><td width="15%" class="fontDadesCalend" align="right">';
      txt += fHMS(ang, 21) + '&nbsp;&nbsp;';
      txt += '</td>';

      // Sortida i posta
      cosh   = -Math.tan(dec) * Math.tan(rlat);
      salpos = (Math.abs(cosh>1 ? 0 : 1));
      if (salpos != 0)
         {
          h    = fplanetes_a(Math.sqrt(1 - cosh * cosh), cosh);
          hp   = h;
          hs   = -hp;
          tsor = (hs + ar - tsl) / 1.002738;
          tpos = (hp + ar - tsl) / 1.002738;
          while (tsor > 2 * Math.PI) tsor -= 2 * Math.PI;
          while (tsor < 0) tsor += 2 * Math.PI;
          tsor = tsor * 12 / Math.PI;
          while (tpos > 2 * Math.PI) tpos -= 2 * Math.PI;
          while (tpos < 0) tpos += 2 * Math.PI;
          tpos = tpos * 12 / Math.PI;

          txt += '</td><td width="15%" class="fontDadesCalend" align="right">';
          txt += fHMS(tsor, 11) + '&nbsp;&nbsp;';
          txt += '</td>';

          txt += '</td><td width="15%" class="fontDadesCalend" align="right">';
          txt += fHMS(tpos, 11) + '&nbsp;&nbsp;';
          // txt += decimals(tpos-tsor, 2);
          txt += '</td>';
         }
      else
          txt += '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
      txt += '</td></tr>';
     }
 txt += '</table>';

 return txt;
}
