viernes, 18 de marzo de 2016

Cálculo de las fases lunares



Poniéndole el lazo al calendario de MyFamilyServer (V2) incluí en el calendario la posibilidad de ver las temperaturas y precipitaciones previstas para los próximos días, el santo del día y también la fase en la que estará la luna.

Hoy escribo acerca del cálculo de la fase de la luna.

Solo os presento cálculo, ya que la presentación de la luna como un icono (una fuente) ya está explicado en publicaciones anteriores de este blog.

Me he basado únicamente en dos datos que (según mi información) son correctos y con esos dos datos he realizado todos los cálculos.

  • Primer dato: Una fecha /hora en la que ha habido luna llena.
  • Segundo dato: Cuánto tiempo dura un ciclo lunar completo.
Primer dato. Cuándo ha sido luna llena. He tomado la primera luna llena de 2016, Ha habido luna llena el 24 de enero de 2016 a las 02:46:20.
Segundo dato. Cuánto dura un ciclo lunar. Un ciclo lunar completo dura 29 días, 12 horas, 43 minutos y 12 segundos.

Con estos dos datos la cosa es sencilla, a partir del 24 de enero, cada 29 días y medio tendremos luna llena de nuevo.

Los cálculos los realizo en segundos, que es la forma natural de trabajar con fechas para el servidor.

El cálculo es el siguiente:

Ha habido luna llena el 24 de enero de 2016 a las 02:46:20

A partir de esta momento, cada 29 días, 12 horas, 43 minutos y 12 segundos sera de nuevo luna llena.

    29 días en segundos es:    29 * 24 * 60 * 60 = 2.505.600
    12 horas en segundos es:         12 * 60 * 60 =      43.200
    43 minutos en segundos es:             43 * 60 =        2.580
    12 segundos en segundos:                       12 =             12
                                                                  + _____________
    Resultado:                        Cada ciclo lunar son  2.551.392 segundos.

Debemos también conocer cuántos segundos han pasado desde el 24 de enero hasta la fecha en la que queremos conocer la fase lunar. Esto es una simple resta (recordar que estamos operando en segundos y obtenemos el resultado en segundos).

El resultado de esa resta es el número de segundos entre la luna llena que conocemos y la fecha actual. Ahora dividimos esa cantidad de segundos entre el tiempo que dura un ciclo lunar (también en segundos) y nos quedamos con el resto de la división. Con esa operación no sé (no me interesa) cuántos ciclos lunares completos han pasado pero SI sé cuánto tiempo en segundos ha pasado del ultimo ciclo lunar (el de la fecha que queremos conocer).

Supongamos que quiero dividir el ciclo lunar en 8 fases:

Luna-llena, Luna-gibosa-menguante, Cuarto-menguante, Luna-menguante, Luna-nueva, Luna-nueva-visible, Cuarto-creciente y Luna-gibosa-creciente.

A partir del resto de la división anterior, si el resto que he obtenido está comprendido entre 1 y 318.924 segundos estamos en la primera fase.
Si el resto que he obtenido está comprendido entre 318.925 y 637.858 estamos en la segunda fase.
Si el resto que he obtenido está comprendido entre 637.859 y 956.782 estamos en la tercera fase y así sucesivamente.

Básicamente esto es todo, hay una operación más que es restar algo de tiempo al inicio, ya tengo el momento exacto de luna llena del 24 de enero, debo restarle la mitad del tiempo de una fase (159.462 segundos) para considerar que la fase de luna llena comienza media fase antes y termina media fase después.

Ahora os muestro el código utilizado para el cálculo, curiosamente es más fácil codificarlo que explicarlo. Veréis que el código es sencillo.



function calcula_fase_lunar($fecha){
#   $lunallena = mktime(hora, minuto, segundo, mes, dia , año );
    $lunallena = mktime(02, 46, 20, 01, 24, 2016);
#   24 de enero de 2016 a las 02:46:20
#   inicio de la luna llena es :
    $iniciolunallena = $lunallena - 159462;
    $fecha = strtotime($fecha);
    $year = date('Y', $fecha);
    $month = date('n', $fecha);
    $day = date('j', $fecha);
    $estanoche = mktime(23, 50, 00, $month, $day, $year);
#   calculamos la luna que de esta noche. El dia entregado a las 23:50:00
    $segundosentrelllen = $estanoche - $iniciolunallena;
#   Segundos entre luna llena y esta noche
#   resto de la division entre el tiempo de un ciclo y los segundos desde luna llena hasta ahora
    $resto = $segundosentrelllen % 2551392;
#   Si es entre      1 y 318924  - Primera fase
#   Si es entre 318924 y 637858  - Segunda fase
#   Si es entre 637858 y 956782  - Tercera fase y asi sucesivamente
    for ($fase = 0; $fase <= 8; $fase++) {
        if ($resto >= 318924) {
            $resto = $resto - 318924;
        } else {
            break;
        }
    }
#  ahora ponemos el calculo en letras (el array debe estar bien ordenado)
    $fase_array = array(
        'Luna-llena', 'Luna-gibosa-menguante', 'Cuarto-menguante', 'Luna-menguante',
        'Luna-nueva', 'Luna-nueva-visible', 'Cuarto-creciente', 'Luna-gibosa-creciente'
    );
    $fase = $fase_array[$fase];
    return $fase;
}

Es así de fácil, ya podéis calcular la fase lunar y utilizarla en cualquier sitio con un sencillo cálculo matemático.

La verdad es que no sé si hay desviaciones a largo plazo, yo lo he validado con fechas de los próximos 10 años y me ha resultado correcto. Si conocéis mejoras en el calculo, no dejéis de comentar.

miércoles, 9 de marzo de 2016

Incorporar el santoral a tu web



En anteriores publicaciones he explicado como incorporar datos del tiempo o de la fase lunar a tu web (o a tu calendario).
Yo, para completar mi calendario le he incorporado el santo del día.
He realizado varios intentos buscando algún API del santoral (un sitio donde un ordenador pueda hacer una llamada pasando algo de información -la fecha por ejemplo- y recibir el santo correspondiente a esa fecha) y no lo he conseguido, no he encontrado ningún API del santoral, SI he encontrado varios widgets y he sacado la información de los mismos.

En este articulo te explico como extraer la información del widget del santoral para integrarla en tu web o tu calendario, y además podrás utilizar esta idea para trabajar con cualquiera otra integración.

A modo de ejemplo, aquí tienes varias direcciones de componentes para integrar en tu web el santo del día:




Si lo que necesitas es un widget, encontrarás documentación fácil en las webs respectivas de cómo integrarlo, en este post quiero explicar como trabajar con el contenido que te proporcionan para extraerlo y darle otros usos.

Esta función recupera el string (el nombre) del widget que proporciona santopedia.com.


function recuperar_santoral($fecha) {
    # Aqui voy a recuperar el santoral desde http://www.santopedia.com
    $url = "http://www.santopedia.com/widget.html";
    $widgetsantoral = file_get_contents($url);
    $posini = strpos($widgetsantoral, 'target="_blank">');
    if (!($posini === false)) {
        $santo = substr($widgetsantoral, $posini + 16, 150);
        $posfin = strpos($santo, '</a>');
        if (!($posfin === false)) {
            $santo = substr($santo, 0, $posfin);
        }
    }
    return $santo;
}

Vamos a explicarlo un poco:
En la definición de la función recibo una fecha (que no utilizo para nada, ya que el widget te da el santo de hoy, sin que le pases parámetros).
Defino la variable $url con la url que voy a invocar.
y utilizo la instrucción 'file_get_content'. Con esta instrucción en vez de presentar en pantalla el resultado que me entrega el widget, lo que hago es almacenarlo en una variable, ahora busco dentro del contenido de esa variable el santo de hoy.
Hay que analizar el contenido (hay que poner la url en el navegador, ejecutarlo y con el widget en pantalla seleccionar 'view page source').

Esto es lo que presenta el widget:










Y esta es la información que te entrega 'view page source':




















Entre la información, hay que buscar dentro del <body> el texto que estamos buscando, en este caso 'San Juan de Dios', e identificar el string constante anterior que le precede. El string que encuentras delante es 'target="_blank">'.
Con esto ya sabemos donde buscar.
A continuación identificar el string constante que encuentras detrás de 'San Juan de Dios' , que es '</a>' y ya lo tenemos.
Ahora identifico en que posición aparece el string anterior y recorto a partir de ese punto (16 caracteres más ya que mi string de búsqueda es de 16 caracteres), Elimino también los caracteres a partir de </a> y finalmente en la variable $santo me queda el texto 'San Juan de Dios'.

Los comandos clave que he utilizado son sencillos: 
  • file_get_contents para obtener y mantener la información que me entrega la web del santoral.
  • strpos para identificar en que posición esta la información que busco.
  • substr para recortar de toda la página la información necesaria.

¿Como he utilizado esta función?:
Estoy presentando, en la cabecera de mi calendario diario, algo de información adicional (Santoral, fase lunar, tiempo actual), esta información la presento en un cuadro, justo por encima de la agenda del día.
En el calendario es configurable qué información se presenta en este cuadro.
Toda la información la compongo en una variable llamada '$contenido' que finalmente presento en pantalla.

Así es como incorporo el santo del día a mi cabecera del calendario:


$santo = recuperar_santoral($identificador);
$contenido = $contenido . '. Santo de hoy: ' .
      '<acronym title="Informacion gracias a www.santopedia.com">' .
      $santo . ' </acronym>';
Es importante, SI, es importante, mantener la información de la fuente o vínculos que el widget nos estaba entregando, nuestra intención no es robar la información, solo es adaptarla a nuestro formato, por lo tanto debemos presentarla en nuestra pantalla también con la referencia a su origen, tal como nos la han entregado en el widget. En este caso he definido el santo como un acrónimo, con esta definición aparece subrayado (seleccionable) y al poner el ratón encima nos muestra la información contenida en title. Esta información es importante mantenerla.

Cualquier duda... comentar.

miércoles, 2 de marzo de 2016

Incorporar la previsión del tiempo a tu web (II)


Hace unos días, publiqué una entrada acerca de como incorporar los datos del tiempo a tu web, en esa idea he estado trabajando para incorporar los datos del tiempo y la fase lunar en MyFamilyserver V2...
He pasado unos días buscando iconos (fuentes en realidad) que me gustaran para incorporar los datos del tiempo a MyFamilyServer y hacer una pequeña representación de la fase de la luna, la verdad es que no he encontrado nada que me haya convencido completamente, así es que he creado una fuente específica para ello, con los signos del tiempo que me gustan y las fases lunares y lo he codificado con la misma codificación que entrega Openweathermap de tal modo que sean fáciles de utilizar (en la medida de lo posible). También he creado una hoja de estilos sencilla para utilizar las fuentes (y un procedimiento para cachear los datos del tiempo en un fichero .json y hacer llamadas sólo cuando la información de previsión del tiempo en el servidor es más antigua de una hora, pero del procedimiento de cacheo no hablo en esta publicación ya que me extiendo demasiado) .

En este post os explico cómo hacer todo esto paso a paso para que podáis incorporarlo también a vuestras aplicaciones (podéis utilizar las fuentes que he creado o generar nuevas con herramientas gratuitas que os propongo).

Vamos a verlo como siempre muy muy despacio.

En la anterior publicación, os expliqué cómo realizar la llamada a la web del tiempo para recuperar la previsión de hoy o de los próximos días.
(ver entrada: 
Supongo que has leído y comprendes lo que se explica en esa publicación, por lo tanto, ya dispones de un procedimiento para llamar a la web del tiempo y recuperar la información que necesitas, ahora vamos a plantear cómo ponerla en fuentes. (Es decir, este post es más de fuentes que de tiempo).
En este caso intervienen dos componentes más: un fichero con la definición de una fuente y una hoja de estilo que te ayuda a trabajar con la fuente.
El fichero de definición de fuentes es un fichero .ttf que he generado con la herramienta FontForge.
La hoja de estilos para trabajar con la fuente que debes incorporar a tu desarrollo es un fichero del tipo .css .
Con las fuentes y la hoja de estilo ya lo tienes todo resuelto.

Parte 1: Las fuentes.
Por supuesto, en internet encontrarás diversas herramientas para trabajar con fuentes, más sencillas, más complejas con más y menos funciones. Yo he elegido FontForge. Es muy completa, se puede instalar en Linux, Windows y Mac, y permite la definición de las fuentes al 100% trazo por trazo y con múltiples opciones y además es gratuita. Os explico un poco cómo utilizarla para que podáis trastear con las fuentes que he creado (o no, y utilizarlas tal cual que están muy monas).
Esta es una imagen de las fuentes que he creado para el tiempo:


Si quieres cambiarlas o necesitas crear otras fuentes SI tienes que utilizar la herramienta FontForge, si estas te gustan, no necesitas ninguna herramienta (y puedes pasar al paso 2).
Fontforge tiene sus sitios web donde descargar y también mucha documentación disponible. En este ejemplo vamos a utilizar poquitas cosas (para no liarnos).
1.1 FontForge: Instalación.... seguir los pasos de instalación según el sistema operativo (siento no dar más instrucciones, pero es así).
1.2 Abrir el fichero mfs-owf1.tff (el nombre viene de las iniciales MyFamilyServer -OpenWeatherFonts 1. El fichero lo podéis descargar de mi cuenta de dropbox, no necesitas registrarte, solo sigue el enlace al pie del post) que contiene estas fuentes y trastear.
Las fuentes están codificadas igual que la codificación del tiempo de OWM (openWeatherMaps.org) con una C delante (C200 es buen tiempo, C321 es tormenta y C601 es nieve)
Las fases de la luna están codificadas de forma consecutiva desde C370 hasta C377.
Vale, ya tienes la herramienta instalada, y te has descargado las fuentes en el mismo directorio donde ejecutas tus programas en php (lo ordenado es tener un directorio especifico de fuentes, pero para empezar vamos a tener los tres ficheros: fuentes, css y php juntos). Ejecutas la herramienta FontForge y lo primero que te pide es el archivo de fuentes con el que vas a trabajar, buscas por tu disco donde lo has dejado (se llama mfs-owf1.tt) y seleccionas OK. Verás una cuadricula con todas las fuentes (recuerda están en el rango de las C200 -C900, es decir mucho mas abajo). Si seleccionas, por ejemplo, la fuente C370 (Luna menguante) verás un cuadro de trabajo como este.


En este cuadro de trabajo puedes añadir, quitar, cambiar romper... de todo, debes leer el manual de la herramienta disponible en:  http://designwithfontforge.com/en-US/index.html
Vale, ya has trasteado un poco, lo has estirado, colocado, añadido, quitado... al final tienes que hacer dos acciones: grabar (en File - Save all. y lo grabas con el mismo nombre de fichero) y a continuación generar las fuentes (en File - Generate Fonts), por ahora vamos a generar TrueType (debes seleccionar True Type en el cuadro que hay bajo la lista de ficheros y generarlas con el mismo nombre, el programa te propondrá un fichero del tipo .ttf al seleccionar TrueType, como ves hay muchos formatos de fuentes, tu trabajas con la herramienta y generas los formatos que necesites, por ahora vamos a generar solo .ttf). Al grabar es posible que te avise de que hay algunos errores en las fuentes, dale a grabar en todo caso.
Ok, genial ya tienes tu fichero de fuentes como tu lo quieras, ahora vamos a utilizarlo.
Para utilizar este fichero de fuentes a nuestro antojo, necesitamos de una hoja de estilo (css).

Parte 2. La hoja de estilo.
La hoja de estilo es un fichero del tipo .css que acompaña a las aplicaciones web para dar formato a las páginas web, en general en las páginas .html se define el contenido y en los ficheros .css se define el formato.
Tu hoja de estilo debe contener:
La instrucción @font-face, que define que nombre le das a la fuente y donde encontrar el fichero de fuentes.
La propiedad font: donde se especifica el formato de la fuente definida en @font-face.
Tantas definiciones de fuentes como necesites.
Aquí va un ejemplo muy muy sencillo:
Fichero mfs-owftest.css para mostrar una de nuestras fuentes:


@font-face {
  font-family: 'mfsowfont';
  src:  url('mfs-owf1.ttf') format('truetype');
}
.mfsowf { font: normal normal normal 14px/1 mfsowfont;  }
/*  Luna menguante   */
.mfsowf-370:before
{ content: "\C370"; }
Un poco de explicación:
En @font-face definimos un nombre (atributo font-family) y definimos donde encontrar nuestro fichero de fuentes, en este ejemplo los tres ficheros -fuentes, css y html - están en el mismo directorio, por eso sólo se especifica el nombre del fichero, si lo cambias de directorio debes especificar ruta y nombre de fichero.
En la siguiente declaración definimos una clase con la definición de atributos de la fuente, los atributos de una fuente son: font-style font-variant font-weight font-size/line-height font-family y hemos definido todos ellos 'normal' para la fuente declarada anteriormente.
Finalmente le damos un 'nombre' a cada fuente (en este ejemplo solo para la fuente C370).


Vamos a completar el ejemplo con un .php que utiliza esta hoja de estilo para mostrar el icono de la luna (es una mezcla .html y .php para hacer un ejemplo en pocos pasos, no debes mezclar presentación y lenguaje de programación, no es una buena práctica):
Fichero HelloWorldWeathertest.php:


<html lang="es" >
    <head>
        <meta http-equiv="Content-Type" content="text/html" charset="utf-8">
        <link href="mfs-owftest.css" rel="stylesheet" type="text/css">
        <title>Hello WeatherFonts</title>
    </head>
    <body>
        <?php
        $icono = "mfsowf mfsowf-370";
        echo '<i class="' . $icono . '"></i>';
        ?>
    </body>
</html>
Un poquito de explicación para este programa:
En la cuarta linea, definimos que la hoja de estilo a utilizar es mfs-owftest.css (la que hemos definido un poco más arriba), es bueno que en un programa puede haber más de una hoja de estilo, así que puede utilizar una para estas fuentes y otra para el resto de estilos que ya estabas utilizando, sin tener que mezclarlas.
En el cuerpo defino la variable $icono con el valor de la clase y la fuente definida y con el comando echo lo presento en pantalla.

La ejecución de este programa solo muestra una luna menguante (en el hemisferio norte, creciente en el hemisferio sur) en pantalla, la luna es una fuente (un carácter), no una imagen o una foto.
Si ves una pequeña luna en pantalla YA LO TIENES!! genial, has conseguido definir fuentes, declararlas en una hoja de estilos y utilizarlas en un programa. Muy Bien.
Ya que todo va bien, vamos a complicarlo un poquito más.

En la hoja de estilos, define tamaños. Añade las líneas:

/* Definición de tamaños  */
.mfsowf-2x { font-size: 2em;}
.mfsowf-3x { font-size: 3em;}
.mfsowf-4x { font-size: 4em;}
Y en tu programa utiliza estos tamaños:

$icono = "mfsowf mfsowf-370";
echo '<i class="' . $icono . '"></i>';
echo '<i class="' . $icono . ' mfsowf-2x"></i>';
echo '<i class="' . $icono . ' mfsowf-3x"></i>';
echo '<i class="' . $icono . ' mfsowf-4x"></i>';
(Atención a las comillas y los espacios)

Puedes ponerle un cuadrito a los caracteres, en la hoja de estilos, define borde. Añade las lineas:

/* Definición de borde */
.mfsowf-border {
    padding: .2em .2em .2em;
    border: solid 0.08em #eeeeee;
    border-radius: .1em;
}
Y en tu programa utiliza estos nuevos bordes (y ya que te pones, también color):

$icono = "mfsowf mfsowf-370";
echo '<i class="' . $icono . '"></i>';
echo '<i class="' . $icono . ' mfsowf-2x"></i>';
echo '<i class="' . $icono . ' mfsowf-3x"></i>';
echo '<i class="' . $icono . ' mfsowf-4x"></i>';
echo '<i class="' . $icono . ' mfsowf-2x mfsowf-border"></i>';
echo '<i class="' . $icono . ' mfsowf-3x mfsowf-border"></i>';
echo '<i class="' . $icono . ' mfsowf-4x mfsowf-border" style="color:#FF0000"></i>';
Y finalmente define la lista completa de fuentes: (Aquí solo un ejemplo, en anexo la lista completa).

/* thunderstorm with light rain */
.mfsowf-200:before { content: "\C200";}
/* thunderstorm with rain */
.mfsowf-201:before { content: "\C201";}
/* thunderstorm with heavy rain */
.mfsowf-202:before { content: "\C202";}
/*  light thunderstorm  */
.mfsowf-210:before { content: "\C210";}
/*  thunderstorm  */
.mfsowf-211:before { content: "\C211";}

Bueno, con esto puedes definir fuentes, definir bordes, tamaños, colores, y también utilizar con confianza otras fuentes chulas, como por ejemplo las fuentes de Font-Awesome (https://fortawesome.github.io/Font-Awesome/) o cualquiera otras que te gusten. En anexo dejo la hoja css con todas las fuentes definidas (para el tiempo y la luna), el fichero ttf con las fuentes en si y un sencillo programa que te muestra todas las fuentes en pantalla.

Seguro que te será de gran utilidad.

(Los anexos se encuentran en Dropbox, el vinculo que dejo aquí te permite descargarlos libremente)
Anexo1: Fuentes  mfs-owf1.ttf
Anexo2: Hoja de estilo mfs-owfandnight.css
Anexo3. Sencillo programa para mostrar las fuentes HelloWorldWeather.php


Finalmente unos consejos:
Cuando hagas pruebas verás que los servidores 'cachean' de todo, la hoja de estilo, las fuentes... si has cambiado algo pero no cambia la ejecución, vas a tener que reiniciar para que todo vuelva a leerse (yo uso un pequeño truco que es llamar a la hoja de estilo con un parámetro cualquiera que cambio cada vez que necesito asegurarme de que se carga de nuevo la hoja de estilo, href="mfs-owftest.css?a=3", el parámetro 'a' no lo utilizo para nada, solo cambio el 3 por un 4 y así sucesivamente cuando quiero asegurarme de que se carga de nuevo la hoja de estilos).
PD. si necesitáis conocer la fase de la luna, encontré un cálculo en internet que funciona bien, si no lo encontráis, escribirme y lo busco y re-publico.