Fibonacci en Prolog

Junio 29 2009No Commented

Guardado en: General

% Author:Daniel Doctor
% Date: 05/03/2006
fibonacci(0,1).
fibonacci(1,1).
fibonacci(N,F) :-   N > 1, N1 is N-1, N2 is N-2,
fibonacci(N1,F1), fibonacci(N2,F2), F is F1+F2.
% Imprime el resultado y sale del programa.
imprimir(N) :-write('El numero '),write(N),
write(' de la serie de Fibonacci es: '), fibonacci(N,X), 
write(X), nl, fail.

Cambio de base en C

Junio 29 2009No Commented

Guardado en: General

#include "stdio.h"
#include "conio.h"
#include "string.h"
#include "math.h"
#include "stdlib.h"
void CambioBase (char *num, int baseorigen, int basedestino);
int
main (void)
{
  char *num;
  int baseorigen, basedestino;
  clrscr ();
  printf ("Escribe el numero a convertir: ");
  scanf ("%s", num);
  printf ("Dado en base (2,8,10,16): ");
  scanf ("%d", &baseorigen);
  printf ("Convertir a base (2,8,10.16): ");
  scanf ("%d", &basedestino);
  CambioBase (num, baseorigen, basedestino);
  getch ();
  return 0;
}
 
void
CambioBase (char *num, int baseorigen, int basedestino)
{
  long destino[20];
  char *tmp;
  int n, i, tam = strlen (num) - 1, total = 0;
  for (i = 0, n = tam; n >= 0; i++, n--)
    {
      switch (num[n])
	{
	case 'a':
	  {
	    destino[i] = 10 * pow (baseorigen, i);
	    break;
	  }
	case 'b':
	  {
	    destino[i] = 11 * pow (baseorigen, i);
	    break;
	  }
	case 'c':
	  {
	    destino[i] = 12 * pow (baseorigen, i);
	    break;
	  }
	case 'd':
	  {
	    destino[i] = 13 * pow (baseorigen, i);
	    break;
	  }
	case 'e':
	  {
	    destino[i] = 14 * pow (baseorigen, i);
	    break;
	  }
	case 'f':
	  {
	    destino[i] = 15 * pow (baseorigen, i);
	    break;
	  }
	default:
	  {
	    tmp[0] = num[n];
	    destino[i] = atoi (tmp) * pow (baseorigen, i);
	    break;
	  }
	}
      total += destino[i];
    }
  printf ("EL %s base %d a base %d es: ", num, baseorigen, basedestino);
  if (basedestino == 16 && total >= 0 && total <= 15)
    {
      switch (total)
	{
	case 10:
	  {
	    printf ("a");
	    break;
	  }
	case 11:
	  {
	    printf ("b");
	    break;
	  }
	case 12:
	  {
	    printf ("c");
	    break;
	  }
	case 13:
	  {
	    printf ("d");
	    break;
	  }
	case 14:
	  {
	    printf ("e");
	    break;
	  }
	case 15:
	  {
	    printf ("f");
	    break;
	  }
	default:
	  {
	    printf ("%d", total);
	    break;
	  }
	}
    }
  else
    {
      for (i = 0; total > 0; i++)
	{
	  destino[i] = total % basedestino;
	  total /= basedestino;
	}
      for (i = i - 1; i >= 0; i--)
	{
	  switch (destino[i])
	    {
	    case 10:
	      {
		printf ("a");
		break;
	      }
	    case 11:
	      {
		printf ("b");
		break;
	      }
	    case 12:
	      {
		printf ("c");
		break;
	      }
	    case 13:
	      {
		printf ("d");
		break;
	      }
	    case 14:
	      {
		printf ("e");
		break;
	      }
	    case 15:
	      {
		printf ("f");
		break;
	      }
	    default:
	      {
		printf ("%d", destino[i]);
		break;
	      }
	    }
	}
    }
}

Leer archivo WAV en C.

Junio 29 2009No Commented

Guardado en: Programación

#include <stdio.h>
#include <stdlib.h>
char bufer[500];
typedef struct swav
{
  char Riff[4];
  long longRiff;
  char Wave[4];			// 
  long longWave;
  char Fmt[4];
  long lonFmt;			// LONGITUD DE LOS DATOS 
  //QUE VIENEN A CONTINUACION  
  int catego;			//   2  
  int canales;			//  2  
  unsigned int frecuencia;	//2  
  int alinea;
  unsigned int especifico;
  char bloque[4];
  long cuerpo;
  // LONGITUD DEL CUERPO
} TipoWav;
void
main (void)
{
  FILE *arch;
  TipoWav dato;
  long nleer;
  printf ("%d % d ", sizeof (int), sizeof (long));
  arch = fopen ("iowa.wav", "rb");
  if (arch == NULL)
    {
      printf ("NO PUDE ABRIR \n");
      exit (0);
    }
  fseek (arch, 0L, SEEK_SET);
  fread (&dato, sizeof (TipoWav), 1, arch);
  nleer = dato.longitud - sizeof (TipoWav);
  printf ("VOY A LEER % ld ", nleer);
  fclose (arch);
}

Redireccionamiento stdin en C

Junio 28 2009No Commented

Guardado en: Linux y Software Libre, Programación

/*Este ejemplo muestra como leer un archivo sin usar la funcion fopen o derivados 
para realizar esto haremos uso de stdin para 
mayor informacion "man stdin", queda claro que solo es un ejemplo y 
pueden realizarse muchas mejoras.
La forma de ejecutar este ejemplo es de la siguiente forma:
./redireccionamiento < *.* Compilaciongcc redireccionamiento.c -o redireccionamiento'
Permite leer de un flujo UNIX estandar*/
#include "stdio.h"
int
main (void)
{
  int caracteres = 0, lineas = 0;
//La funcion fgetc toma el siguiente carácter 
//de la entrada estándar stdin=Standart Input
  char c = fgetc (stdin);
  do
    {
      (c) ? caracteres++ : NULL;
      (c == 10) ? lineas++ : NULL;
    }
  while ((c = fgetc (stdin)) != EOF);
  //El bucle continuará hasta que encuentra el final del archivo 
  //EOF=End Of File   
  printf ("Número de caracteres son %d\n", caracteres);
  printf ("Número de líneas son %d\n", lineas);
  return 0;
}

Realizado por Juan Rivero Mercado (vive-libre.org)

Juego del Gato en C

Junio 28 2009No Commented

Guardado en: General

Juego del Gato en C.

/*Juego de Gato Heurístico
  Autor:Jesús M.Olivares Ceja
  Desarrollado para propósitos didácticos de Ingeniería del Conocimiento
  Su copia es libre, si lo utiliza para propósitos no lucrativos.
*/
#include "stdio.h"
#include "dos.h"
#define SI  1
#define NO  0
  // TIPOS
  typedef struct {
  char tablero[9];
  int f;
} TipoTablero;
	//VARIABLES
struct
{
  TipoTablero Tm;
  int g;
  int UTc;
  TipoTablero Tc[7];
} arbol[8];
int UTiradaMaq;
TipoTablero juego;
char Linea[100];
	// PROTOTIPOS
void desplegaTablero (void);
int esValida (int tirada);
void generaTiradasMaq (void);
void generaTiradasContrario (int iTiradaMaq);
void creaTiradaMaq (int i);
void creaTc (int iTiradaMaq, int i);
void CalculaF (TipoTablero * t);
int revisaFin (int max);
void
main (void)
{
  int fin, valida, tiradaContrario, i;
  int iTiradaMaq, iTiradaContrario;
  int min, max, cualTm, vacias;
  // INICIALIZA EL TABLERO DE JUEGO
  for (i = 0; i < 9; i++)
    juego.tablero[i] = ' ';
  // MIENTRAS NO SEA FIN JUEGA
  fin = NO;
  while (fin == NO)
    {
      desplegaTablero ();
      // TOMA LA TIRADA DEL CONTRARIO HASTA QUE SEA VALIDA
      valida = NO;
      while (valida == NO)
	{
	  printf ("¿Donde tiras? [1..9]                0 = salir?\n");
	  gets (Linea);
	  tiradaContrario = atoi (Linea) - 1;
	  valida = esValida (tiradaContrario);
	  switch (valida)
	    {
	    case 0:
	      fin = SI;
	      valida = SI;
	      break;
	    case 1:
	      valida = SI;
	      break;
	    case 2:
	      printf ("Posición Ocupada, indica otra\n");
	      valida = NO;
	      break;
	    case 3:
	      printf ("Posición Erronea, indica otra [1..9]\n");
	      valida = NO;
	      break;
	    }
	}			// SI DECIDIO  TERMINAR, SALIRSE        
      if (fin == SI)
	continue;		// COLOCA LA TIRADA DEL CONTRARIO        
      juego.tablero[tiradaContrario] = ' ';
      desplegaTablero ();
      CalculaF (&juego);
      if (juego.f < -9000)
	{
	  printf ("Ganaste\n");
	  fin = SI;
	  continue;
	}			// GENERA POSIBLES TIRADAS DE LA MAQUINA
      UTiradaMaq = 0;
      generaTiradasMaq ();
      // PARA CADA TIRADA DE LA MAQUINA
      for (iTiradaMaq = 0; iTiradaMaq < UTiradaMaq; iTiradaMaq++)
	{
	  // GENERA POSIBLES TIRADAS DEL CONTRARIO            
	  arbol[iTiradaMaq].UTc = 0;
	  generaTiradasContrario (iTiradaMaq);
	  min = 15000;
	  // PARA CADA TIRADA DEL CONTRARIO            
	  for (iTiradaContrario = 0;
	       iTiradaContrario < arbol[iTiradaMaq].UTc; iTiradaContrario++)
	    {
	      // CALCULA F                
	      CalculaF (&arbol[iTiradaMaq].Tc[iTiradaContrario]);
	      // ENCUENTRA LA F MINIMA                
	      if (min > arbol[iTiradaMaq].Tc[iTiradaContrario].f)
		min = arbol[iTiradaMaq].Tc[iTiradaContrario].f;
	    }
	  // CALCULA F'            
	  CalculaF (&arbol[iTiradaMaq].Tm);
	  // CALCULA G            
	  arbol[iTiradaMaq].g = arbol[iTiradaMaq].Tm.f + min;
	}
      max = -15000;
      // ELIGE TM MEDIANTE EL CRITERIO G MAXIMA        
      cualTm = -1;
      for (iTiradaMaq = 0; iTiradaMaq < UTiradaMaq; iTiradaMaq++)
	{
	  if (arbol[iTiradaMaq].g > max)
	    {
	      cualTm = iTiradaMaq;
	      max = arbol[iTiradaMaq].g;
	    }
	}
      // SI LA MAQUINA TIRO        
      if (cualTm > -1)
	{
	  printf ("voy a tirar...\n");
	  delay (1000);
	  // COPIA EL TABLERO CON LA JUGADA DESEADA            
	  for (i = 0; i < 9; i++)
	    juego.tablero[i] = arbol[cualTm].Tm.tablero[i];
	}
      // DETERMINA LA SITUACION ACTUAL DEL JUEGO        
      CalculaF (&juego);
      switch (revisaFin (juego.f))
	{
	case 0:
	  break;		// CONTINUA        
	case 1:
	  desplegaTablero ();
	  printf ("LO SIENTO, Gane!!!!\n");
	  fin = SI;
	  break;
	case 2:
	  desplegaTablero ();
	  printf ("Ganaste\n");
	  fin = SI;
	  break;
	case 3:
	  printf ("Quedamos   G a t o, hagamos otro intento\n");
	  fin = SI;
	  break;
	}
    }
}
 
void
desplegaTablero (void)
{
  int r, c;
  for (r = 0; r < 3; r++)
    {
      for (c = 0; c < 3; c++)
	if (juego.tablero[3 * r + c] == 32)
	  printf ("%d  ", 3 * r + c + 1);
	else
	  printf ("%c  ", juego.tablero[3 * r + c]);
      printf ("\n\n");
    }
}
 
int
esValida (int tirada)
{
  if (tirada == -1)
    return 0;			// NO CONTINUAR    
  if ((tirada > -1) && (tirada < 9))
    if (juego.tablero[tirada] == ' ')
      return 1;
    else
      return 2;
  // POSICION OCUPADA
  else
    return 3;			// POSICION INVALIDA
}
 
void
generaTiradasMaq (void)
{
  int i;
  for (i = 0; i < 9; i++)
    if (juego.tablero[i] == ' ')
      creaTiradaMaq (i);
}
 
void
generaTiradasContrario (int iTiradaMaq)
{
  int i;
  for (i = 0; i < 9; i++)
    if (arbol[iTiradaMaq].Tm.tablero[i] == ' ')
      creaTc (iTiradaMaq, i);
}
 
void
creaTiradaMaq (int i)
{
  int k;
  for (k = 0; k < 9; k++)
    arbol[UTiradaMaq].Tm.tablero[k] = juego.tablero[k];
  arbol[UTiradaMaq].Tm.tablero[i] = 'o';
  UTiradaMaq++;
}
 
void
creaTc (int iTiradaMaq, int i)
{
  int k;
  for (k = 0; k < 9; k++)
    arbol[iTiradaMaq].Tc[arbol[iTiradaMaq].UTc].tablero[k] =
      arbol[iTiradaMaq].Tm.tablero[k];
  arbol[iTiradaMaq].Tc[arbol[iTiradaMaq].UTc].tablero[i] = 'x';
  arbol[iTiradaMaq].UTc++;
}
 
void
CalculaF (TipoTablero * t)
{
  int v, h, d;
  int r, c, ctaO, ctaE, ctaX;
  // SUMA LAS VERTICALES MAQUINA
  v = 0;
  for (c = 0; c < 3; c++)
    {
      ctaO = 0;
      ctaE = 0;
      for (r = 0; r < 3; r++)
	{
	  if (t->tablero[3 * r + c] == 'o')
	    ctaO++;
	  if (t->tablero[3 * r + c] == ' ')
	    ctaE++;
	}
      if (ctaO == 3)
	{
	  t->f = 9999;
	  return;
	}
      if ((ctaO + ctaE) == 3)
	v++;
    }
  h = 0;
  for (r = 0; r < 3; r++)
    {
      ctaO = 0;
      ctaE = 0;
      for (c = 0; c < 3; c++)
	{
	  if (t->tablero[3 * r + c] == 'o')
	    ctaO++;
	  if (t->tablero[3 * r + c] == ' ')
	    ctaE++;
	}
      if (ctaO == 3)
	{
	  t->f = 9999;
	  return;
	}
      if ((ctaO + ctaE) == 3)
	h++;
    }				// SUMA LAS DIAGONALES MAQUINA    
  d = 0;
  ctaO = 0;
  ctaE = 0;
  for (c = 0; c < 9; c += 4)
    {
      if (t->tablero[c] == 'o')
	ctaO++;
      if (t->tablero[c] == ' ')
	ctaE++;
    }
 
  if (ctaO == 3)
    {
      t->f = 9999;
      return;
    }
  if ((ctaO + ctaE) == 3)
    d++;
  ctaO = 0;
  ctaE = 0;
  for (c = 2; c < 7; c += 2)
    {
      if (t->tablero[c] == 'o')
	ctaO++;
      if (t->tablero[c] == ' ')
	ctaE++;
    }
 
  if (ctaO == 3)
    {
      t->f = 9999;
      return;
    }
  if ((ctaO + ctaE) == 3)
    d++;
  // SUMA LAS VERTICALES CONTRARIO    
  for (c = 0; c < 3; c++)
    {
      ctaX = 0;
      ctaE = 0;
      for (r = 0; r < 3; r++)
	{
	  if (t->tablero[3 * r + c] == 'x')
	    ctaX++;
	  if (t->tablero[3 * r + c] == ' ')
	    ctaE++;
	}
      if (ctaX == 3)
	{
	  t->f = -9999;
	  return;
	}
      if ((ctaX + ctaE) == 3)
	v--;
    }
 
  // SUMA LAS HORIZONTALES CONTRARIO    
  for (r = 0; r < 3; r++)
    {
      ctaX = 0;
      ctaE = 0;
      for (c = 0; c < 3; c++)
	{
	  if (t->tablero[3 * r + c] == 'x')
	    ctaX++;
	  if (t->tablero[3 * r + c] == ' ')
	    ctaE++;
	}
      if (ctaX == 3)
	{
	  t->f = -9999;
	  return;
	}
      if ((ctaX + ctaE) == 3)
	h--;
    }
 
  // SUMA LAS DIAGXNALES CONTRARIO    
  ctaX = 0;
  ctaE = 0;
  for (c = 0; c < 9; c += 4)
    {
      if (t->tablero[c] == 'x')
	ctaX++;
      if (t->tablero[c] == ' ')
	ctaE++;
    }
 
  if (ctaX == 3)
    {
      t->f = -9999;
      return;
    }
  if ((ctaX + ctaE) == 3)
    d--;
  ctaX = 0;
  ctaE = 0;
  for (c = 2; c < 7; c += 2)
    {
      if (t->tablero[c] == 'x')
	ctaX++;
      if (t->tablero[c] == ' ')
	ctaE++;
    }
 
  if (ctaX == 3)
    {
      t->f = -9999;
      return;
    }
  if ((ctaX + ctaE) == 3)
    d--;
  // ASIGNA F    
  t->f = v + h + d;
}
 
int
revisaFin (int max)
{
  int i, vacias;
  if (max > 9000)
    return 1;
  // GANO LA MAQUINA
  if (max < -9000)
    return 2;
  // GANO EL CONTRARIO
  vacias = 0;
  for (i = 0; i < 9; i++)
    if (juego.tablero[i] == ' ')
      vacias++;
  if (vacias > 0)
    return 0;
  // PUEDEN CONTINUAR
  return 3;
  // SE ACABO EL JUEGO FUE GATO
}
 
	// fin del archivo

BugCon 2009 del 12 al 14 de Agosto.

Junio 28 2009No Commented

Guardado en: Eventos, Linux y Software Libre, Social / Internet

BugCON ‘09 una de las conferencias de seguridad más importantes del mundo, será realizada del 12 de Agosto al 14 de Agoto en el Instituto Politécnico Nacional (IPN).

Si tienes un blog, o un sitio web dedica una entrada al evento, puedes poner el siguiente cartel.

Puedes ver la infomación su sitio web: http://www.bugcon.org, estaremos haciendo un seguimiento del evento, con las noticias más importantes relacionadas al evento.

Como llegar:

Se realizará en el Centro Formación e Innovación Educativa (CFIE): Avenida Wilfrido Massieu , s/n esquina con Luis Enrique Erro , Unidad Profesional “Adolfo López Mateos”, Zacatenco, en la ciudad de México , C.P. 07738.
Teléfonos: +52 (55) 5729 6000 extensiones 57166 y 57167 | cfie@ipn.mx.

Croquis para BugCon 2009

Croquis para BugCon 2009

Recuperar estadísticas de un sitio con Ruby

Junio 28 2009No Commented

Guardado en: Linux y Software Libre, Programación, Social / Internet

Muchas ocasiones hemos tenido la necesidad de integrar información que está en otro sitio web dentro del nuestro.
En este ejemplo integraremos las estadísticas del sitio clustermaps, dentro del contenido de un sitio web.
Utilizaremos Ruby como lenguaje de scripting, dado que es más portable que usar bash o powershell, además de ser más potente dado que es un lenguaje de programación completo.

require 'open-uri'
require 'hpricot'
url = 'http://www2.clustrmaps.com/es/counter/maps.php?url=http://www.misitio.com'
#Abrimos el archivo desde el sitio web.
parser = Hpricot(open(url))
table = (parser/"html/body/form/div/div[2]/table[2]/tr/td[2]/")
#Quitamos comentarios y demas cosas (scripts)
html = table.inner_html.gsub(/<!--[.]*-->/,'')
html = html.gsub(/<!--|google_.*|\/\/.*/,'').strip
puts html = '
<table class="estadisticas"><tr><td>'+html.gsub(/2[0-9]+/,'\0')+"</table>"
#Tenemos nuestro archivo de estadísticas
stats = File.new("stats.htm", "w")
#Guardamos y cerramos.
stats.write(html)
stats.close
#html listo para ser añadido con Ajax.

Explicaré un poco la líneas

require 'open-uri'
require 'hpricot'

open-uri permite extender las funciones de manejo de archivos para poder utilizar URL’s en ellas.

hpricot es un parser de html muy sencillo de utilizar que permite utilizar selectores CSS y XPath.
Para obtener una consulta XPath fácilmente al contenido del elemento que buscamos, podemos usar la extensión de Firefox Firebug que permite copiar el camino XPath a un determinado elemento, y con el método inner_html se puede obtener su contenido.
El método gsub de la clase String, permite reemplazar un patrón especificado con una expresión regular, y en este caso lo utilizamos para eliminar tanto los comentarios, como la publicidad que estaban embebidas en la tabla.
Espero les sirva y puedan adaptarlo.

Subir videos con Ruby on Rails

Junio 24 2009No Commented

Guardado en: General, Linux y Software Libre, Programación, Social / Internet

Uno de los grandes beneficios de trabajar con una plataforma de desarrollo como es Ruby on Rails es que nos permite ahorrarnos líneas de código que en otras plataformas o frameworks nos llevaría tiempo y esfuerzo hacer que funcionara correctamente.

La importancia de la velocidad en el desarrollo de nuestras aplicaciones es cada vez más importante y Rails nos ofrece un desarrollo con menos esfuerzo y mucho mayor rapidez.

A continuación mostraré de qué forma se puede subir un video con formato FLV al servidor.

El primer paso, asumiendo que ya se encuentra instalado Rails en nuestro sistema, será crear un nuevo proyecto, para ello bastará con utilizar el comando rails seguido del nombre que queremos darle a nuestro proyecto.

rails subirVideo

Lo cual nos creará un nuevo directorio subirVideo en nuestro directorio actual, por lo que es importante estar en el directorio donde queremos crear nuestro proyecto.

Dentro de nuestro proyecto crearemos nuestro controlador videos que será el encargado de gestionar la subida del vídeo,para tal propósito se utiliza el comando generate que se encuentra dentro del directorio script de nuestro proyecto, la forma para crear el controlador es:

script/generate controller videos

Al ejecutar este comando se creará una serie de archivos y directorios:

 exists  app/controllers/
 exists  app/helpers/
 create  app/views/videos
 exists  test/functional/
 exists  test/unit/helpers/
 create  app/controllers/videos_controller.rb
 create  test/functional/videos_controller_test.rb
 create  app/helpers/videos_helper.rb
 create  test/unit/helpers/videos_helper_test.rb

A partir de este momento podemos empezar a desarrollar nuestra aplicación, abrimos el archivo videos_controller.rb y crearemos una nueva acción llamada index la cual será la endargada de mostrar el formulario que permitirá al usuario escoger el archivo que quiere subir. Nuestro archivo queda de la siguiente manera:

class VideosController &lt; ApplicationController
 
  def index
  end
end

Lo siguiente que haremos será crear una vista en el directorio app/views/videos on el nombre index.html.erb para esa acción que creamos, en ésta se encontrará todo el código HTML que se mostrará en el navegador, lo que haremos será crear un archivo con el siguiente contenido:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
 
 <title>Subir Video</title>
 </head>
 <body>
 <div>
 <% form_tag 'videos/upload', :id => 'subir', :multipart => true do %>
 <h4>Escoja un video</h4>
 <p>El video debe tener la extensión flv</p>
 <%= file_field_tag "video" %><br />
 <%= submit_tag "Subir video" %>
 <% end %>
 
 </div>
 
 </body>
</html>

Que nos mostrará una pantalla como esta:

Formulario

la línea:

<% form_tag 'videos/upload', :id => 'subir', :multipart => true do %>

nos ayuda a crear un formulario, la función form_tag es de los llamados helpers que nos ayudan a reducir la cantidad de lineas de código haciendo que nuestras vistas sean prácticamente sólo HTML, ‘videos/upload’ es la dirección en donde se realizará la acción con los datos enviados por el formulario, :multipart => true indica que será un formulario que permitirá enviar archivos al servidor, :id => ’subir’ es el id que se le da al formulario cualquier otro atributo se podría asignar usando la notación :atributo => ‘valor’

 <%= file_field_tag "video" %> y <%= submit_tag "Subir video" %>

son al igual que form_tag helpers para definir inputs del tipo file y del tipo submit respectivamente, para file_field_tag, “video” es el name y el id que tendrá el campo y para submit_tag, “Subir video” será el valor que se mostrará en el botón.

Ya teniendo nuestra vista es necesario crear otra acción llamada upload que será donde se realicen las operaciones con el video una vez esté en el servidor.

def upload
 if request.post?
 
     #asigna la información del video en archivo
     archivo = params[:video]
 
     #nombre original del archivo
     name =  archivo.original_filename
 
     #ruta donde se guardará el video
     directory = "public/flv"
 
     # crear la ruta del archivo
     path = File.join(directory, name)
 
     extensionArchivo = name.slice(name.rindex("."), name.length).downcase
 
     #verifica que la extensión sea la correcta
     if extensionArchivo == '.flv'
 
         # crear el archivo
         File.open(path, "wb") { |f| f.write(archivo.read) }
 
         #guarda la información que se mostrará
         @archivoGuardado = true
         @nombreArchivo = name
     else
 
         #en caso de que no sea correcta la extensión muestra un mensaje de error
render :text => '<p>El archivo debe tener la extensión flv</p> de click <a href="../videos"> aquí</a> para volver a intentarlo'
     end
 end
end

Lo primero que hacemos es verificar que se haya enviado el formulario mediante post utilizando:

request.post?

Sí el archivo se envio lo primero que hacemos es asignar el video que subimos a una variable en estea caso archivo params nos permite acceder a los datos enviados mediante POST y para acceder a cada campo enviado utilizamos params[:nombreDelCampo] en este caso params[:video], utilizaremos en nombre que tenía el archivo al ser subido por el usuario así que almacenamos el nombre original en la variable name y en directory almacenamos la ruta donde se guardará el archivo en el servidor (”public/flv”), en path tendremos la ruta completa del archivo por ejemplo: public/flv/miVideo.flv, hasta ahora no hemos almacenado el archivo en el servidor, primero debemos saber si la extensión es la correcta para eso la obtenemos mediante:

extensionArchivo = name.slice(name.rindex("."), name.length).downcase

que lo que hace es extraer la cadena que se forma a partir del útimo punto a la derecha del nombre del archivo hasta el final del nombre del archivo y lo convierte en minúsculas, así no importa que la extensión sea .flv o .FLV.

Si la extensión es la correcta entonces pasamos el archivo al directorio public/flv mediante:

File.open(path, "wb") { |f| f.write(archivo.read) }

que crea un archivo en la ruta path (incluyendo el nombre) a partir del contenido del archivo que subimos almacenado en archivo, wb nos indica que el archivo se abre para escritura en modo binario.

Después de crear el archivo guardamos los datos en variables que podremos utilizar en la vista upload, que es el nombre y una variable que nos indica si el archivo se guardó.

La vista que nos mostrará que el archivo se guardó correctamente como se mencionó antes tendrá el nombre upload y tendra el siguiente contenido:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
   <title>Archivo procesado</title>
 </head>
 <body>
   <% if @archivoGuardado %>
      <p>El archivo <%= @nombreArchivo %> se subio correctamente</p>
   <%end%>
 </body>
</html>

Que comprueba que el archivo se haya guardado corectamente para mostrar un mensaje como este:

El archivo miVideo.flv se subio corectamente

En caso de que la extensión del archivo no fuera ni .flv ni .FLV entonces inmediatamente nos mostrará un mensaje de error como este:

Error al subir archivoPara hacer esto hacemos uso de render :text para mostrar el mensaje.

Hasta ahora la aplicación funciona correctamente pero sería mejor que la subida del archivo se realizara en segundo plano para que el usuario no crea que la página está congelada, para hacer esto haremos uso de Javascript y un iframe oculto.

Agregaremos un iframe a la vista index y un área para los posibles mensajes de error, entonces nuestra vista quedará de la siguiente forma:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
 <%= stylesheet_link_tag 'estilos' %>
 <%= javascript_include_tag :defaults %>
 <%= javascript_include_tag "validar" %>
 
 <title>Subir Video</title>
 </head>
 <body>
 <div>
 <% form_tag 'videos/upload', :id => 'subir', :multipart => true do %>
 <h4>Escoja un video</h4>
 <p>El video debe tener la extensión flv</p>
 <%= file_field_tag "video" %><br />
 <%= submit_tag "Subir video" %>
 <% end %>
 
 </div>
 <div id="mensajes">
 </div>
 <div id="contenedorIframe">
 <iframe name="Upload" id="Upload"></iframe>
 </div>
 </body>
</html>

Debemos ocultar el iframe a la vista del usuario para ello creamos una hoja de estilos en la carpeta public/stylesheets llamada estilos.css con el siguiente contenido:

#Upload{
 display:none;
}

Se pudo evitar esto haciendo:

<iframe name="Upload" id="Upload" style="display:none"></iframe>

pero es mejor separar el contenido de la presentación.

Para incluir la hoja de estilos usamos el helper stylesheet_link_tag con el nombre de nuestra hoja de estilos, la única condicion es que esté en el directorio stylesheets:

 <%= stylesheet_link_tag 'estilos' %>

Cargamos las librerías de javascript necesarias para realizar las nuestras acciones, utilizamos e l helper javascript_include_tag con la misma condicion que las hojas de estilo, debe estar en el directorio javascripts, utilizo :defaults para que todas las librerias incluidas por defecto en Rails se carguen pero basta con ‘prototype’ ya que es la única que se utiliza, crearemos un archivo llamado validar.js en public/javascripts y lo incluimos:

 <%= javascript_include_tag "validar" %>

en este archivo pondremos lo siguiente:

window.onload = function()
{
 
 var formulario = $('subir');
 formulario.target = "Upload";
 
 formulario.onsubmit = function(){
 
 var listoEnvio = true;
 
 var archivo = $('video').value;
 var extension = (archivo.substring(archivo.lastIndexOf("."))).toLowerCase();
 
 if(extension == '')
 {
    $('mensajes').update("Seleccione un archivo");
    listoEnvio = false;
 }
 else
 {
    //Si existe archivo se comprueba que sea .flv
    if(extension != '.flv')
   {
//En caso de que no sea esa la extensión se muestra un mensaje y
// listoEnvio se vuelve false
     $('mensajes').update("Seleccione un archivo del tipo correcto");
     listoEnvio = false;
   }
   else
   {
     //En caso de que sea la extensión correcta se muestra un gif 
//mientras se sube el archivo
     $('mensajes').update('<img src="/images/cargando.gif" />');
   }
 }
 //En caso de error no se envía el archivo al servidor
 return listoEnvio;
 
 }
 
}

Asignamos nuestro formulario subir a la variable formulario y cambiamos el target hacia el iframe que creamos antes

 formulario.target = "Upload";

Lo cambiamos mediante javascript sobre todo por accesisbilidad, para que aquellos que tengan javascript desactivado puedan utilizar normalmente el formulario, ahora debemos hacer la validación de la extensión al momento de que se envie el formulario y al igual que hicimos con Rails comprobamos la extensión y mostramos los mensajes en el área que destinamos a los posibles mensajes que quisieramos mostrar

Error

En caso de error asignamos false a listoEnvio para evitar que se envíe el formulario, si todo marcha bien entonces se enviará al servidor y mostrará una imagen aanimada mientras se sube el archivo.

subiendo

El siguiente paso es hacer que la vista upload responda a la página principal mediante javascript, debemos agregar algunas lineas de código para adaptarlo:

<% if @archivoGuardado %>
 <noscript>
 <p>El archivo <%= @nombreArchivo %> se subio correctamente</p>
 </noscript>
 <script type="text/javascript">
 if(parent.document.getElementById("contenedorIframe"))
 {
 parent.$("subir").reset();
 parent.$("mensajes").update("El archivo se subio correctamente")
 }
 </script>
 <%end%>

Lo ahora lo que hace es que si Javascript no está activado mostrará el mensaje en pantalla pero si está activado y upload se está ejecutando en el iframe el formulario se reiniciará y se mostrará un mensaje indicando que el archivo se subio correctamente, se utiliza parent porque el iframe “Upload” es hijo de la ventana principal entonces si llegara a ejecutar esta accion por separado comprobaría que esista el elemento contenedorIframe para hace la acción si no no hará nada.

Se subio

Y listo, tenemos un formulario que sube un video en formato FLV con Javascript no obstrusivo.

Presentando SquirrelFish

Junio 21 2009No Commented

Guardado en: Programación, Social / Internet, Tecnología

El núcleo del navegador Safari -WebKit -tiene ahora un nuevo intérprete de Javascript SquirrelFish.

Webkit logoSquirrelFish es un compilador basado en registros, multihilo, y generador de bytecode.
Genera los bytecodes sobre la marcha de base el árbol sintáctico, usando un compilador de una sola pasada.

SquirrelFish debe mucho de su diseño a algunas de las últimas investigaciones en el campo de las máquinas virtuales eficientes, incluyendo el trabajo realizado por ek Profesor M. Anton Ertl, et al, Profesor David Gregg, et al, y los desarrolladores del lenguaje de programación Lua.

Algunas referencias introductorias para comprender como funciona:

Lisp en Javascript

Junio 3 2009No Commented

Guardado en: Programación

Visto en http://www.joeganley.com/code/jslisp.html

Para demostrar que tan potente puede ser JavaScript como un lenguaje de programación (a lo opuesto de un lenguaje de scripting embebido), Joe Ganley escribió un intérprete de Lisp en Javascript

Resultó ser bastante bueno, para este proyecto, dado que es flexible – los arreglos de tamaño dinámico son usados ampliamente- y los arreglos asociativos funcionan como una buena tabla de símbolos.

Un número de instrucciones de Lisp son implementadas, la sintaxis es estándar y solamente maneja aritmética de enteros.

Sin embargo eso no le quita el mérito y lo interesante que puede ser tanto Javascript como Lisp.

Visto en http://www.joeganley.com/code/jslisp.html