Archive | December 2013

Premios “Cristalab tiene razón” a lo mejor del 2013

Porque Cristalab, otro año más, tiene la razón. Les traemos los premios a lo mejor en tecnología, videojuegos, web, libros, películas, anime, etc.

Mejor Videojuego

Puff… muchos…

Bioshock Infinite

GTA V

The Last of Us

Badland iOS

Mejor cámara del mundo mundial

GoPro

Subcampeon: Cualquier smartphone, en serio ¿Qué otra cámara ha tomado tantas fotos como un teléfono?

Mejor gadget chiquito

Chromecast

Subcampeon: Fitbit

Mejor tecnología disruptiva

Dogecoin

very currency so crypto wow much coin

Subcampeón: Bitcoin (Bitcoin es la primera tecnología del 2013 realmente disruptiva, nadie se lo esperaba)

Mejor tecnología de la que NADIE habló NADA

Flash

No, en serio ¿Qué pasó con Flash este año? Nada. Nada.

Mejor decisión del año

Pagar por Netflix, Crunchyroll y en general dejar de piratear. Con VPN eso sí.

Subcampeón: Pagar por manicure, es fabuloso.

Mejor nave interestelar de combate ultradimensional

Tesla Model S

Subcampeón: El metro de México

Mejor superhéroe

Edward Snowden

Subcampeón: Batman.

Mejor película

Gravity

Pacific Rim
Star Trek Into Darkness

Subcampeones: Thor the Dark World, Ender’s Game, The Hobbit 2, Lincoln
No nos hemos visto: Her, 12 years a slave, Mud,

Mi libro favorito del 2014

Hmmm, son demasiados, así que:
Nexus – Crux
Ready Player One
Little Brother – Homeland

Mejor serie de TV

Breaking Bad

Subcampeón: Game of Thrones, Orange is the New Black, Arrested Development

Mejor serie de TV britanica, por ende el premio anterior no cuenta

Doctor Who

Subcampeón: ¿¡¡POR QUE NO HAY SHERLOCK TODAVIA MOFFAT!??

Premio especial a Escritores que Usan Drogas Duras para

El final de Dexter, ¿Qué carajo pasó?

Mejor tech demo que me cambió la vida

Oculus Rift

Subcampeón: Google Glass, caro pero aun impresionante.

Mejor tech demo ultra caro que nadie comprará en el mundo real

Galaxy Gear

Subcampeón: Google Glass, que sigue en US$1500 y nadie comprará.

Mejor juguete del infierno

Furby

Subcampeón: Furby.

Mejor serie animada que devolvió la fe en Japón al mundo

Kill la Kill

Subcampeón: Attack on Titan
(Sword Art Online es del 2012, Madoka Magica del 2012 y Steins:Gate del 2011, superemoslas)

Mejores cursos online no relacionados con nosotros no son publicidad lo juro

Los 14 cursos al precio de 3 de Mejorando.la Navidad

Subcampeón: Cómo doblar camisetas en un paso.

Mejor agencia que no nos enviará a una prisión secreta y que no nos está forzando a darles este premio

NSA

Subcampeón: Glorioso ministerio de la verdad de Corea del Norte

Mejor tecnología web

¿A QUIEN LE IMPORTA? ¿Estás haciendo cosas increibles, creando apps mágicas? Eso sí que importa. Excepto si son en ASP 3.0. Entonces necesitas ayuda profesional.

Enviar comentario

via Cristalab http://feeds.cristalab.com/~r/clab/~3/0nEB1TCR73I/

Colores, gradientes y texto 3D con Sass y Compass

Hola a todos, en este tutorial quiero mostrarles las posibilidades de generar CSS dinámico usando sass y compass. Si no los tienes instalados, revisa la Introducción a Sass y Compass donde explico el proceso de instalación. Veremos como usar las propiedades de CSS3 como text-shadows, gradientes, transiciones, border-radius, box-shadow, de manera sencilla y sin extensiones propietarias de diferentes navegadores.

Crear nuestro proyecto con Compass

Código :

compass create myproyecto

Con esto Compass creará el proyecto, y entramos a la carpeta "myproyecto" por medio del cmd.

Código :

 cd myproyecto

Ahora necesitamos mantener el archivo vigilado para cuando cambiemos el css , se compile de una vez , y no estar compilando manualmente!

Código :

compass watch

Y ahora que falta? Creamos nuestro index.html dentro de la carpeta myproyecto, pero fuera de las demás y vinculados nuestros index con screen.css que está dentro la carpeta stylesheets.

Quedaria así:
[css:1:163dc0f53e]<linl rel="stylesheet" href="stylesheets/screen.css">[/css:1:163dc0f53e]

Ahora bien tenemos que editar el archivo screen.css que está dentro de la carpeta Sass!

Funciones de Sass

[css:1:163dc0f53e]
$color:#333; /*variables sass*/

P{
font-size:16px;
color:$color;
}
p:hover{
color:darken($color,5%) /* la funcion darken oscurece los colores*/
}
[/css:1:163dc0f53e]

Todos los que han visto Less, saben estas funciones, aquí mostraré las básicas y pondré un ejemplo concreto en cada elemento, donde veremos cómo acalarar, oscurecer, saturar, desaturar, manejar escalas de gris, invertir y mezclar colores a un elemento.

Código :

<!Doctype html>
<html lang="es">
   <head>
        <meta charset="utf-8">
         <title>-COMPASS-CSS3-EASY</title>
       <link rel="stylesheet" href="stylesheets/normalize.css">
       <link rel="stylesheet" href="stylesheets/screen.css">
   </head>
   <body>
   <div class="funciones">
      <div class="divuno">
      <p>lighten</p>
      </div>
      <div class="divdos">
      <p>darken</p>
      </div>
      <div class="divtres">
      <p>saturate</p>
      </div>
      <div class="divcuatro">
      </p>desaturate</p>
      </div>
      <div class="divcinco">
      <p>grayscale</p>
      </div>
      <div class="divseis">
      <p>complement</p>
      </div>
      <div class="divsiete">
      <p>invert</p>
      </div>
      <div class="divocho">
      <p>mix</p>
      </div>
   </div>
   </body>
</html>

[css:1:163dc0f53e]
/* sass scss*/
/*variable*/
$color-func:#049cdb;
/*[END]*/
@mixin divs{
color:#fff;
display:inline-block;
border:1px solid rgba(#333,0.5);
font-size:22px;
margin:10px 10px;
padding:10px 10px;
text-align:center;
width:100px;
}
div.divuno{
background:lighten($color-func,20%); /* acalara*/
@include divs;
}
div.divdos{
background:darken($color-func,20%); /*oscurece*/
@include divs;
}
div.divtres{
background:saturate($color-func,20%); /*satura*/
@include divs;
}
div.divcuatro{
background:desaturate($color-func,20%); /*desatura*/
@include divs;
}
div.divcinco{
background:grayscale($color-func); /*escala de gris , no necesita porcentaje*/
@include divs;
}
div.divseis{
background:complement($color-func); /*complementa no necesita procentaje*/
@include divs;
}
div.divsiete{
background:invert($color-func); /* invierte no necesita porcentaje*/
@include divs;
}
div.divocho{
background:mix($color-func,red); /*mezcla cualquier color */
@include divs;
}
[/css:1:163dc0f53e]

Texto 3D

Para lograr esto pues necesitamos ir oscureciendo el texto, así que la función darken sería perfecta. Aquí va un ejemplo concreto!

Código :


<!Doctype html>
<html lang="es">
   <head>
      <meta charset="utf-8">
      <title>-COMPASS-CSS3-EASY</title>
       <link rel="stylesheet" href="stylesheets/normalize.css">
      <link rel="stylesheet" href="stylesheets/screen.css">
   </head>
   <body>
      <header id="header">
         <h1>compass y sass text shadow</h1>
      </header>
   </body>
</html>

[css:1:163dc0f53e]
/* sass scss*/

#header{
backgroynd:#fff;
border:1px solid rgba(#555,0.5);
padding:10px 0px;
}
@mixin textshadow($color){
color:$color;
text-shadow:1px 1px 0px darken($color,4%),
2px 2px 0px darken($color,8%),
3px 3px 0px darken($color,12%),
4px 4px 0px darken($color,18%),
5px 5px 0px darken($color,22%),
5px 5px 2px #333;
}

header > h1{
font-family:Arial;
font-size:50px;
@include textshadow(#8ac90c);
}

[/css:1:163dc0f53e]

Nos queda esto!

Agregar prefijos en CSS3

Ahora bien, todo diseñador web se aburre de los prefijos propietarios de diferentes navegadores, Compass nos ayuda con eso con la filosofía del Easy CSS3! Veamos un ejemplo:

Código :

<!Doctype html>
<html lang="es">
   <head>
      <meta charset="utf-8">
      <title>-COMPASS-CSS3-EASY</title>
           <link rel="stylesheet" href="stylesheets/normalize.css">
           <link rel="stylesheet" href="stylesheets/screen.css">
   </head>
   <body>
   <div class="easycss3">
    <h2>los prefijos propietarios cansan!</h2>
   </div>
   </body>
</html>

[css:1:163dc0f53e]
/* sass css*/
.easycss3{
@include background-image(linear-gradient(top,tomato,darken(tomato,15%)));
border:1px solid rgba(#333,0.5);
@include box-shadow(2px 2px 2px rgba(10,10,10,0.5));
@include border-radius(5px);
margin:50px auto;
padding:100px;
text-align:center;
@include transition(all 0.2s ease-in-out);
width:50%;
}
.easycss3 > h2{
color:#fff;
font-size:30px;
@include text-shadow;
}
.easycss3:hover{
width:60%;
}

[/css:1:163dc0f53e]
Veamos cómo estas líneas de código adquieren todos los prefijos en el css compilado:
[css:1:163dc0f53e]
.easycss3 {
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ff6347), color-stop(100%, #f92600));
background-image: -webkit-linear-gradient(top, #ff6347, #f92600);
background-image: -moz-linear-gradient(top, #ff6347, #f92600);
background-image: -o-linear-gradient(top, #ff6347, #f92600);
background-image: linear-gradient(top, #ff6347, #f92600);
border: 1px solid rgba(51, 51, 51, 0.5);
-webkit-box-shadow: 2px 2px 2px rgba(10, 10, 10, 0.5);
-moz-box-shadow: 2px 2px 2px rgba(10, 10, 10, 0.5);
box-shadow: 2px 2px 2px rgba(10, 10, 10, 0.5);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
margin: 50px auto;
padding: 100px;
text-align: center;
-webkit-transition: all 0.2s ease-in-out;
-moz-transition: all 0.2s ease-in-out;
-o-transition: all 0.2s ease-in-out;
transition: all 0.2s ease-in-out;
width: 50%;
}

/* line 84, ../sass/screen.scss */
.easycss3 > h2 {
color: #fff;
font-size: 30px;
text-shadow: 0px 0px 1px #aaaaaa;
}

/* line 89, ../sass/screen.scss */
.easycss3:hover {
width: 60%;
}
[/css:1:163dc0f53e]

Generar gradientes

Juguemos con los gradientes, que les parece?. En este ejemplo he hecho unos botones.

Código :

<html lang="es">
   <head>
      <meta charset="utf-8">
      <title>-COMPASS-CSS3-EASY</title>
       <link rel="stylesheet" href="stylesheets/normalize.css">
      <link rel="stylesheet" href="stylesheets/screen.css">
   </head>
   <body>
          <div class="botones">
      <a href="#" class="btn-uno">linear top<a>
           <a href="#" class="btn-dos">radial center<a>
           <a href="#" class="btn-tres">linear bottom<a>
           <a href="#" class="btn-cuatro">linear mitad<a>
           <a href="#" class="btn-cinco">linear vertical<a>
      <a href="#" class="btn-seis">radial desenfocado<a>
   </div>
   </body>
</html>

Ahora el css
[css:1:163dc0f53e]
@mixin btn{
border:1px solid rgba(#333,0.4);
@include border-radius(5px);
@include box-shadow(0px 2px 0px rgba(#fff,0.5)inset);
margin:10px;
color:white;
display:inline-block;
font-size:18px;
font-weight:bold;
padding:25px 25px;
text-align:center;
text-decoration:none;
white-space:nowarap;
width:25%;
}
.btn-uno{
@include background-image(linear-gradient(top,#f89406,darken(#f89406,18%)));
@include btn;
}
.btn-dos{
@include background-image(radial-gradient(center,#9d261d,darken(#9d261d,15%)));
@include btn;
}
.btn-tres{
@include background-image(linear-gradient(right,#c3325f,lighten(#c3325f,20%)));
@include btn;
}
.btn-cuatro{
@include background-image(linear-gradient(top,#049cdb,rgba(#049cdb,0.8)50%,rgba(#049cdb,0.6)55%));
@include btn;
}
.btn-cinco{
@include background-image(linear-gradient(left,#46a546,rgba(#46a546,0.9)49%,rgba(#46a546,0.7)51%));
@include btn;
}
.btn-seis{
@include background-image(radial-gradient(center,#7a43b6,rgba(#7a43b6,0.7)50%,rgba(#7a43b6,1)));
@include btn;
}
[/css:1:163dc0f53e]

Ahora veamos cómo nos compila en CSS.
[css:1:163dc0f53e]
.btn-uno {
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #f89406), color-stop(100%, #9e5f04));
background-image: -webkit-linear-gradient(top, #f89406, #9e5f04);
background-image: -moz-linear-gradient(top, #f89406, #9e5f04);
background-image: -o-linear-gradient(top, #f89406, #9e5f04);
background-image: linear-gradient(top, #f89406, #9e5f04);
border: 1px solid rgba(51, 51, 51, 0.4);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
-webkit-box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
-moz-box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
margin: 10px;
color: white;
display: inline-block;
font-size: 18px;
font-weight: bold;
padding: 25px 25px;
text-align: center;
text-decoration: none;
white-space: nowarap;
width: 25%;
}

/* line 114, ../sass/screen.scss */
.btn-dos {
background-image: -webkit-gradient(radial, 50%, 0, 50%, 100, color-stop(0%, #9d261d), color-stop(100%, #5c1611));
background-image: -webkit-radial-gradient(center, #9d261d, #5c1611);
background-image: -moz-radial-gradient(center, #9d261d, #5c1611);
background-image: -o-radial-gradient(center, #9d261d, #5c1611);
background-image: radial-gradient(center, #9d261d, #5c1611);
border: 1px solid rgba(51, 51, 51, 0.4);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
-webkit-box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
-moz-box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
margin: 10px;
color: white;
display: inline-block;
font-size: 18px;
font-weight: bold;
padding: 25px 25px;
text-align: center;
text-decoration: none;
white-space: nowarap;
width: 25%;
}

/* line 118, ../sass/screen.scss */
.btn-tres {
background-image: -webkit-gradient(linear, 100% 50%, 0% 50%, color-stop(0%, #c3325f), color-stop(100%, #de7d9b));
background-image: -webkit-linear-gradient(right, #c3325f, #de7d9b);
background-image: -moz-linear-gradient(right, #c3325f, #de7d9b);
background-image: -o-linear-gradient(right, #c3325f, #de7d9b);
background-image: linear-gradient(right, #c3325f, #de7d9b);
border: 1px solid rgba(51, 51, 51, 0.4);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
-webkit-box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
-moz-box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
margin: 10px;
color: white;
display: inline-block;
font-size: 18px;
font-weight: bold;
padding: 25px 25px;
text-align: center;
text-decoration: none;
white-space: nowarap;
width: 25%;
}

/* line 122, ../sass/screen.scss */
.btn-cuatro {
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #049cdb), color-stop(50%, rgba(4, 156, 219, 0.8)), color-stop(55%, rgba(4, 156, 219, 0.6)));
background-image: -webkit-linear-gradient(top, #049cdb, rgba(4, 156, 219, 0.8) 50%, rgba(4, 156, 219, 0.6) 55%);
background-image: -moz-linear-gradient(top, #049cdb, rgba(4, 156, 219, 0.8) 50%, rgba(4, 156, 219, 0.6) 55%);
background-image: -o-linear-gradient(top, #049cdb, rgba(4, 156, 219, 0.8) 50%, rgba(4, 156, 219, 0.6) 55%);
background-image: linear-gradient(top, #049cdb, rgba(4, 156, 219, 0.8) 50%, rgba(4, 156, 219, 0.6) 55%);
border: 1px solid rgba(51, 51, 51, 0.4);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
-webkit-box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
-moz-box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
margin: 10px;
color: white;
display: inline-block;
font-size: 18px;
font-weight: bold;
padding: 25px 25px;
text-align: center;
text-decoration: none;
white-space: nowarap;
width: 25%;
}

/* line 126, ../sass/screen.scss */
.btn-cinco {
background-image: -webkit-gradient(linear, 0% 50%, 100% 50%, color-stop(0%, #46a546), color-stop(49%, rgba(70, 165, 70, 0.9)), color-stop(51%, rgba(70, 165, 70, 0.7)));
background-image: -webkit-linear-gradient(left, #46a546, rgba(70, 165, 70, 0.9) 49%, rgba(70, 165, 70, 0.7) 51%);
background-image: -moz-linear-gradient(left, #46a546, rgba(70, 165, 70, 0.9) 49%, rgba(70, 165, 70, 0.7) 51%);
background-image: -o-linear-gradient(left, #46a546, rgba(70, 165, 70, 0.9) 49%, rgba(70, 165, 70, 0.7) 51%);
background-image: linear-gradient(left, #46a546, rgba(70, 165, 70, 0.9) 49%, rgba(70, 165, 70, 0.7) 51%);
border: 1px solid rgba(51, 51, 51, 0.4);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
-webkit-box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
-moz-box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
margin: 10px;
color: white;
display: inline-block;
font-size: 18px;
font-weight: bold;
padding: 25px 25px;
text-align: center;
text-decoration: none;
white-space: nowarap;
width: 25%;
}

/* line 130, ../sass/screen.scss */
.btn-seis {
background-image: -webkit-gradient(radial, 50%, 0, 50%, 100, color-stop(0%, #7a43b6), color-stop(50%, rgba(122, 67, 182, 0.7)), color-stop(100%, #7a43b6));
background-image: -webkit-radial-gradient(center, #7a43b6, rgba(122, 67, 182, 0.7) 50%, #7a43b6);
background-image: -moz-radial-gradient(center, #7a43b6, rgba(122, 67, 182, 0.7) 50%, #7a43b6);
background-image: -o-radial-gradient(center, #7a43b6, rgba(122, 67, 182, 0.7) 50%, #7a43b6);
background-image: radial-gradient(center, #7a43b6, rgba(122, 67, 182, 0.7) 50%, #7a43b6);
border: 1px solid rgba(51, 51, 51, 0.4);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
-webkit-box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
-moz-box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
box-shadow: 0px 2px 0px rgba(255, 255, 255, 0.5) inset;
margin: 10px;
color: white;
display: inline-block;
font-size: 18px;
font-weight: bold;
padding: 25px 25px;
text-align: center;
text-decoration: none;
white-space: nowarap;
width: 25%;
}
[/css:1:163dc0f53e]

Como vemos el CSS comilado se hizo bastante extenso!. Veamos los resultados:

Enviar comentario

via Cristalab http://feeds.cristalab.com/~r/clab/~3/VfOpLnacwAs/

Lo mejor del Software Libre en el 2013

Como parte del apoyo al software libre y con la llegada del fin de año, recopilamos los sucesos que marcaron pauta en todo lo concerniente al software libre y el movimiento de código abierto (Open Source). El 2013 trajo muchas novedades, sobre todo para el proyecto Linux, vimos nuevos sistemas operativos móviles basados en Linux, grandes inversiones, juegos, servicios y tantas cosas que hacen este 2013 muy especial.

Steam llega a Linux con su catálogo de juegos, incentivando el desarrollo de los drivers propietarios para las tarjetas gráficas AMD y Nvidia. Mozilla estrena sistema operativo móvil, apoyado en tecnología web HTML5, la estación espacial internacional abandona Windows por Linux, ciudades migrando a Linux y muchas cosas que hace 5 años eran inimaginables, ¡hoy son realidad!

Basándonos en el crecimiento del software libre, nos preguntamos: ¿Está el movimiento de software libre y código abierto tomando fuerza y penetrando los mercados más reacios a estos movimientos? ¿En la actualidad hay algo que no use software libre directa o indirectamente?

A continuación lo que este 2013 nos dejó:

La guerra de los sistemas operativos móviles

Hace cinco años uno era feliz con un Nokia Symbian OS, ¿hoy en día comprarían un Nokia con Windows Phone? Al menos mas del 80% diría que no. Hoy Android es el rey por gran ventaja en la cuota del mercado, con un crecimiento sostenido desde hace ya 3 años, dando un vuelco al mercado de móviles. Ya Nokia con Symbian OS es historia, Blackberry OS está quedando atrás, el único sistema operativo móvil que ha mantenido su mercado es IOS.

Pero en este año, de la mano de Mozilla Foundation nació Firefox OS (Nombre clave: Boot to Gecko), un sistema operativo basado en Linux que pretende revolucionar el mercado de móviles de gama media y baja, que ademas usa tecnología abierta como lo es HTML5, CSS3 y JavaScript; Mozilla Foundation hizo el lanzamiento junto a Telefónica en países de Latinoamérica y España. Lo peculiar de Firefox OS, es que las aplicaciones se pueden usar tanto en el navegador web Firefox de escritorio o móvil, como en los móviles que usen este sistema operativo.

Otro sistema operativo, del cual no se habla mucho pero al cual Samsung ve mucho potencial es Tizen, otro sistema operativo con núcleo Linux, que usa HTML5, CSS3 y JavaScript como lenguaje de programación; Tizen ha tenido problemas en su implementación en teléfonos móviles, ocasionando retrasos en el lanzamiento del Samsung Tizen Z9005. Este sistema operativo será tarde o temprano el reemplazo de Android en los terminales de la empresa sur-coreana Samsung.

Google en pro a al rendimiento de Android, lanza Android 4.4 Kit Kat, introduciendo ART en lugar de Dalvik como máquina virtual, y se espera que en versiones posteriores digamos adiós a Dalvik.

Y como último punto en esta guerra de sistemas operativos móviles, queda Ubuntu Phone, un sistema operativo de Canonical, que ademas quería realizar una terminal que no pudo hacer realidad, por no obtener el capital necesario para fabricarlos. Ubuntu Phone es muy similar a Tizen y Firefox OS en las tecnologías que usa, Linux y lenguajes web antes mencionados.

¿Linux para gamers?

Linux por mucho tiempo tuvo una mala imagen para los gamers, por la poca cantidad de juegos disponibles. Además, se decía que Linux no servía para jugar, esto no era del todo cierto, el problema radicaba en que los desarrolladores de juegos y las grandes empresas no veían hacia Linux sino hacia Windows y otros a Mac OS X.

Pero hace un año Valve (la empresa desarrolladora de Halt Life), anunciaba su cliente Steam y Left 4 Dead 2 para Linux, llegando la versión final en los primeros meses de este año. Al día de hoy hay más de 400 juegos portados a Linux, incluyendo grandes juegos como Football Manager 2014, Counter-Strike, Half Life 1 y 2, Dota 2 y más.

Valve no dejó todo allí, y trajo muchas mas sorpresas a los usuarios de Linux con Steam OS, una distribución Linux basado en Debian, totalmente optimizada para jugar, y como si esto fuera poco anunciaron Steam Machine una nueva consola de videos juegos con Steam OS, su lanzamiento será en el año 2014.

Grandes inversiones en Software Libre

IBM, realizó una inversión de 1.000 millones para promocionar Linux, algo muy sorprendente, por la cifra, buscando promocionar y ayudar al desarrollo de aplicaciones para cloud computing que corran bajo el kernel Linux.

Otras empresas que han apostado durante este año al software libre son Facebook y Twitter, la primera con desarrollos de software como HHVM (HipHop Virtual Machine), para ejecutar programas escritos en PHP, otros dos proyectos interesantes de Facebook a nivel de bases de datos Presto (SQL + BigData) y RocksDB (NoSQL). Por su parte Twitter que tiene un mensaje interesante en sus repositorios “Twitter is built on open source software.” ha aportado, liberando muchos proyectos de software libre que usan en su plataforma (Pueden ver el listado en http://twitter.github.io/).

Google no se queda atrás, y con la llegada de Google Glass, liberó el código del kernel que usa este dispositivo (https://code.google.com/p/google-glass-kernel-source/), permitiendo a los desarrolladores “meter mano” y crear Mods, para estos lentes.

Linux llega al espacio

La Estación Espacial Internacional (ISS), le dió un duro golpe a Microsoft, tomando la decisión de usar Linux en todos los equipos que se encuentran en la ISS. Keith Chuvala señala que el cambio a Linux hará mas fácil el control interno: "Si tenemos que solucionar, ajustar o adaptar algo, lo podemos hacer nosotros”.

Nueva Zelanda no permite las patentes de software

Las patentes son el peor enemigo de los desarrolladores independientes, por lo tanto Nueva Zelanda anuncio que no se realizarán más enmiendas al Proyecto de Ley de Patentes.

Top 5 de proyectos de Software Libre en este 2013

Koha

Koha es un sistema integrado de gestión de bibliotecas, único por ser el primero de código fuente abierto, liberado bajo la GNU General Public License. Koha fue creado en 1999 por Katipo Communications para la Horowhenua Library Trust en Nueva Zelanda. La primera instalación se logró en enero del 2000. Koha proviene del maorí, y quiere decir obsequio, o donación.

OpenStack

OpenStack es un proyecto de computación en la nube para proporcionar una infraestructura como servicio (IaaS). Es un software libre y de código abierto distribuido bajo los términos de la licencia Apache. El proyecto está gestionado por la Fundación OpenStack, una persona jurídica sin fines de lucro creada en septiembre de 2012 para promover el software OpenStack y su comunidad.

CourseFork

CourseFork conecta profesores con materiales de código abierto en una comunidad de colaboración en línea.

DocHive

Este software permite extraer información desde archivos escaneados en PDF usando XML.

Project Libre

Project Libre es un software de administración de proyectos de código abierto, similar a Microsoft Project.

Enviar comentario

via Cristalab http://feeds.cristalab.com/~r/clab/~3/OsxlKVHNunM/

Módulo de Usuarios (IV):Validar formulario y guardar datos con Laravel

En este nuevo tutorial veremos cómo validar un formulario y guardar datos con Laravel 4. En los capítulos anteriores ya vimos los siguientes temas:

[nota:e2ef4d6c4d]Además, para hacer este tutorial es necesario que hayan completado: Configurar base de datos y crear tablas con Laravel dado que necesitaremos una tabla users con los campos: email, password, full_name, created_at y updated_at tal como explica dicho tutorial.[/nota:e2ef4d6c4d]

Validar los datos enviados en el formulario

Esta es una tarea tan común que todos los frameworks incluyen clases dispuestas a asistir al usuario en la validación de datos. Laravel por supuesto no es la excepción.

Volvamos a la función store donde quedamos anteriormente:

Código :

    public function store()
    {
        return Input::all();
    }

Acá haremos todo el proceso.

Primero que nada, vamos a crear un nuevo usuario (new User)

En Laravel los registros de la base de datos se pueden manejar como objetos gracias al ORM de Laravel: Eloquent.

[nota:e2ef4d6c4d]Sé que es primera vez que les hablo de Eloquent, por lo tanto voy a mantener todo el código muy sencillo y en, digamos, posteriores tutoriales sí les hablaré de temas un poco más avanzados. La idea es que todos puedan seguir este tutorial[/nota:e2ef4d6c4d]

Dado que, como les dije, cada registro (fila de la tabla users) es manejado como si fuera un nuevo objeto, y aquí intentamos crear un nuevo usuario, pues:

Código :

$user = new User

Esto funciona sólo porque Laravel viene con un modelo User.php ya predefinido en:

Código :

app/models/User.php

Ve a darle un vistazo y regresa cuando estés listo.

Ok, un gusto tenerte de vuelta.

Lo que haremos a continuación es interactuar con nuestro controlador Admin_UserController y nuestro modelo User para validar y guardar el usuario.

Recuerda que como vimos en otro tutorial, el controlador debe apoyarse en los modelos y otras clases lo más posible, de manera que la programación del controlador sea limpia y la “lógica de negocio” o dicho de otra forma, el “código pesado” esté en nuestro modelo.

Nosotros, en otras palabras, queremos que la acción store de nuestro controlador luzca así:

Código :

   /**
    * Store a newly created resource in storage.
    *
    * @return Response
    */
    public function store()
    {
        // Creamos un nuevo objeto para nuestro nuevo usuario
        $user = new User;
        // Obtenemos la data enviada por el usuario
        $data = Input::all();
        
        // Revisamos si la data es válido
        if ($user->isValid($data))
        {
            // Si la data es valida se la asignamos al usuario
            $user->fill($data);
            // Guardamos el usuario
            $user->save();
            // Y Devolvemos una redirección a la acción show para mostrar el usuario
            return Redirect::route('admin.users.show', array($user->id));
        }
        else
        {
            // En caso de error regresa a la acción create con los datos y los errores encontrados
return Redirect::route('admin.users.create')->withInput()->withErrors($user->errors);
        }
    }

El código se explica solo, de todas formas:

  • Creamos un nuevo usuario (new User).
  • Tomamos los datos enviados por el usuario (Input::all()).
  • Si son válidos se lo asignamos al usuario, guardamos el usuario y redireccionamos a “show”.
  • Si no son válidos redireccionamos a la pantalla anterior pero llevándonos de regreso la data y los errores generados en la validación, para mostrárselos al usuario.

¿Qué nos hace falta acá?

Bueno, básicamente nunca le dijimos a Laravel qué o cómo validar, de hecho la función User::isValid() no existe, si presionamos el botón “Crear usuario” nos va a arrojar lo siguiente:

Código :

Call to undefined method Illuminate\Database\Query\Builder::isValid()

¿Ahora qué?

Vamos al modelo (app/models/User.php) y agregamos lo siguiente:

Código :

    public $errors;
    
    public function isValid($data)
    {
        $rules = array(
            'email'     => 'required|email|unique:users'',
            'full_name' => 'required|min:4|max:40',
            'password'  => 'required|min:8|confirmed'
        );
        
        $validator = Validator::make($data, $rules);
        
        if ($validator->passes())
        {
            return true;
        }
        
        $this->errors = $validator->errors();
        
        return false;
    }

Primero definimos una propiedad dentro del modelo User que servirá para almacenar los errores (en caso de que haya alguno), la coloqué pública para simplificar el ejemplo:

Código :

public $errors;

Lo segundo es definir el método isValid, que acepta como parámetro la data enviada por el usuario. Dentro fíjense que defino un array con las reglas de validación “rules”.

Este array $rules es procesado por la clase de validación de Laravel (Validator) cuyo método Validator::make acepta, como primer parámetro un array de datos ($data) y como segundo parámetro un array de reglas ($rules).

Fíjense que las claves de ambos arrays coinciden y se refieren a los nombres de los campos (en nuestro ejemplo: email, full_name y password):

Entonces llamamos al método:

Código :

$validator = Validator::make($data, $rules)

Así se crea un nuevo objeto almacenado en $validator que contiene toda la data y las reglas de validación. Ahora todo lo que hace falta es ejecutar la validación:

Código :

$validator->passes() //devuelve TRUE si la validación pasa

Código :

$validator->fails() //Método pesimista, devuelve TRUE si la validación falla

Si la validación pasa, retornamos TRUE en nuestro método isValid, si falla entonces almacenamos en la propiedad $errors los errores para decirle al usuario qué salió mal:

Código :

$this->errors = $validator->errors();

Y retornamos FALSE.

Prácticamente siempre que necesitemos validar algo con Laravel, usaremos este método, lo que cambia son las reglas que tenemos que definir.

Como pueden ver en el ejemplo anterior, las reglas se definen escribiendo un array asociativo, donde la llave (key) es el nombre del campo, y el valor es las reglas asignadas a ese campo separadas con barra | y si la regla necesita un parámetro adicional se define con : y si son varios parámetros es separan por coma, así:

Código :

'nombre_de_campo' => 'regla1|regla2|regla_con_parametros:parametro1,parametro2'

Reglas de validación de Laravel

Según usamos en el ejemplo:

  • required sirve para indicar que un campo es obligatorio.
  • email indica que el campo es de tipo email.
  • min:value exige que el campo tenga un mínimo de “value” caracteres.
  • max al contrario del anterior, delimita el máximo posible.
  • confirmed útil para confirmar email o contraseña, exige que haya un campo con el mismo nombre pero con el sufijo “_confirmation” y que ambos tengan el mismo valor (ej: password y password_confirmation).
  • unique:table exige que el campo sea único en la tabla “table” (útil para campos como username e e-mail).

[nota:e2ef4d6c4d]Más adelante veremos más sobre la regla “unique”[/nota:e2ef4d6c4d]

Si quieren ver todas las reglas de validación de Laravel vean la documentación oficial

Penúltimo paso:

Indicarle a Laravel qué campos se pueden llenar por “asignación masiva”

Volviendo al controlador, cuando hacemos:

Código :

$user->fill($data)

Estamos haciendo algo llamado en Laravel “Massive assignment” (asignación masiva), es decir llenar todas las propiedades del modelo a través de un array de datos. Esto puede traer varios problemas, por ello Laravel nos permite indicarle al modelo qué campos son “llenables” (fillable) a través de métodos como User::fill:

En el modelo (app/models/User.php) agreguen esta otra propiedad:

Código :

protected $fillable = array('email', 'full_name', 'password');

Ahora aunque algún aprendiz de hacker intente enviar campos adicionales no conseguirá romper la funcionalidad dado que sólo esos 3 campos son tomados en cuenta, más aún, tampoco se intentará grabar el campo oculto “_token” ni el campo “password_confirmation” que no hace falta en la tabla “users”.

Y ahora un último paso:

Si llenamos nuestro formulario de forma inválida, digamos, escribieron “pepito” en el campo email, la aplicación es redireccionada de vuelta al formulario (ruta admin.users.create) pero no se muestran los errores ni nada, esto está muy mal…

[nota:e2ef4d6c4d]Hay muchas, muchas aplicaciones “funcionando” en producción que no muestran ningún error si algo sale mal, nunca le hagan esto a los pobres usuarios…[/nota:e2ef4d6c4d]

Cómo mostrar los errores de una validación fallida:

Laravel parece ser un poco pesimista, porque siempre, en nuestras vistas, se encuentra definida una variable llamada $errors con un objeto de tipo MessageBag que tiene algunos métodos bastante básicos, uno de ellos es any() que revisa si de verdad hay algún error, otro es all() que devuelve el array con todos los posibles errores.

Agreguemos esto a la vista app/views/admin/users/form.blade.php justo debajo del título:

Código :

  @if ($errors->any())
    <div class="alert alert-danger">
      <button type="button" class="close" data-dismiss="alert">&times;</button>
      <strong>Por favor corrige los siguentes errores:</strong>
      <ul>
      @foreach ($errors->all() as $error)
        <li>{{ $error }}</li>
      @endforeach
      </ul>
    </div>
  @endif

Ahora intenten re-enviar el formulario nuevamente con el email “pepito” y verán una lista de mensajes en rojo diciéndote qué salió mal:

¡Excelente!

[nota:e2ef4d6c4d]Para colocar los mensajes de error en español hay que hacer 3 pasos:

  1. Cambiar en app/config/app.php la variable “locale” a “es” (actualmente tiene en).
  2. Ir al directorio app/lang/ copiar la carpeta en/ y pegarla en el mismo directorio, renombrándola a es/
  3. Abrir la carpeta app/lang/es recién duplicada y traducir todos los mensajes a español.

Es posible que estos mensajes ya estén disponibles si buscan en Google, por ahora esto se escapa un poco del alcance de nuestro tutorial.[/nota:e2ef4d6c4d]

Mantener los valores especificados por el usuario

El problema con esto es que aunque ya estamos mostrando la data no estamos devolviendo los valores al usuario, aunque sea un error, el campo email debería decir “pepito” y no estar en blanco, de forma que el usuario pueda completar pepito@gmail.com sin tener que reescribir todo de nuevo, por ejemplo.

Esto se puede resolver de forma muy simple con Laravel:

Modifiquemos nuestro método create de manera que quede así:

Código :

   public function create()
   {
        // Creamos un nuevo objeto User para ser usado por el helper Form::model
        $user = new User;
      return View::make('admin/users/form')->with('user', $user);
   }

Básicamente lo mismo que teníamos antes, sólo que instanciamos un nuevo objeto User.

En nuestro form app/views/admin/users/form.blade.php vamos a cambiar Form::open por otro helper llamado Form::model, que es muy parecido, sólo que como primer parámetro acepta un modelo, y lo demás queda igual:

Código :

{{-- Reemplazamos Form::open por Form::model: --}}
{{ Form::model($user, array('route' => 'admin.users.store', 'method' => 'POST'), array('role' => 'form')) }}

¡Listo! Ahora prueben registrarse con email pepito por última vez, verán que no sólo se muestran los errores sino que Laravel ahora rebota los datos nuevamente al formulario.

¡Excelente!

Por último veamos un gráfico de lo que sucede entre el usuario y el servidor cuando el usuario pone “pepito” u otro email o campo no-válido:

Esto nos ilustra las diferentes redirecciones que se llevan a cabo de manera casi transparente.

Ahora si escriben todos los datos de forma válida, verán cómo Laravel los redirecciona a la vista “show” que por ahora sólo muestra algo así:

Código :

Aqui mostramos la info del usuario: 1

Y este sería el gráfico si todo va bien:

En próximos tutoriales por supuesto mejoraremos esto, también mostraremos la lista de los usuarios que vayamos agregando.

Si van a PHPMyAdmin observarán que un nuevo registro fue agregado a la tabla “users” de la base de datos pruebalaravel:

[nota:e2ef4d6c4d]No es recomendable guardar las claves como texto plano[/nota:e2ef4d6c4d]

Espero que les haya gustado y hayan aprendido bastante con este tutorial. Dudas y preguntas en los comentarios.

Nos vemos la próxima semana.

Enviar comentario

via Cristalab http://feeds.cristalab.com/~r/clab/~3/HLUnYMxdqcA/

Instalar Laravel en Ubuntu

Aquí les dejo un breve tutorial de cómo instalar Laravel en Ubuntu, ya que como soy nuevo en Ubuntu me hizo pasar ratos buscando cómo solucionar algunos problemas.

Para poder usar Laravel necesitas tener instalado LAMP (Linux, Apache, Mysql y PHP), en este link pueden encontrar las instrucciones para instalarlo.

Además necesitan tener instalado Composer y para eso necesitamos Curl. Primero instalamos curl, para eso vamos a la terminal y tecleamos el siguiente comando:

Código :

sudo apt-get install php5-curl
sudo apt-get install curl

Y después ya procedemos a instalar composer:

Código :

curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

Laravel, como lo indica su documentación, necesita MCrypt PHP Extension, entonces procedemos a instalarlo:

Código :

sudo apt-get install php5-mcrypt

Ahora vamos a probar que mcrypt está incluido en PHP. Ejecutamos el siguiente comando:

Código :

    /usr/bin/env php --ri mcrypt

Si nos muestra un mensaje como el siguiente:

Código :

Extension 'mcrypt' not present

Quiere decir que no está incluido, entonces hacemos lo siguiente; buscamos el archivo php.ini que debe estar en una ruta similar a:
/etc/php5/cli/php.ini
Y procedemos a editar el archivo php.ini, con su editor favorito.

Código :

    sudo gedit php.ini

Agregamos la siguiente línea:
extension=mcrypt.so
Y reiniciamos Apache:

Código :

    sudo service apache2 restart

Ahora ya podemos descargar e instalar Laravel. Primero nos ubicamos en la raíz de donde queremos que quede nuestro proyecto, por ejemplo:

Código :

    cd /var/www

Y ejecutando el siguiente comando:

Código :

composer create-project laravel/laravel [NombreProyecto] --prefer-dist

Ahora debemos configurar Apache para que funcionen las URLs amigables, para eso vamos a buscar el archivo donde esta configurado nuestro host:

Código :

cd /etc/apache2/sites-available/

En mi caso mi archivo de configuración default se llama: 000-default.conf
Procedemos a editarlo y agregamos las siguientes líneas (No olvides cambiar la ruta):

Código :

<Directory /var/www/TuProyecto/>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>

Ejecutamos el siguiente comando:

Código :

sudo a2enmod rewrite

Reinicia Apache una vez más:

Código :

    sudo service apache2 restart

Accedan desde su navegador a esta URL: localhost/miProyecto/public, Si sale un error similar a este o una pantalla en blanco:

file_put_contents(/Users/winas/workspace/media_unified_url/media_unified_url/app/storage/meta/services.json) [function.file-put-contents]: failed to open stream: Permission denied.

Ejecuta el siguiente comando dentro de la raíz de tu proyecto:

Código :

sudo chown -R www-data:www-data app/storage

Si todo sale bien debe mostrarnos esta pantalla en su navegador en la URL: localhost/miProyecto/public (Lo más recomendado es que configuren un dominio virtual para que sea más cómodo, pero eso lo subiré en otro tutorial).

Espero que les sirva, si se me paso algo tratare de actualizarlo. Saludos.

Enviar comentario

via Cristalab http://feeds.cristalab.com/~r/clab/~3/DAIKjJOMwdE/

Mover personajes con teclado en AS3

Existe un error frecuente con el uso del teclado en la creación de juegos en AS3. Lo sé porque me ha ocurrido, y, aunque pueda parecer tonto, hizo que uno de mis juegos no sea tan bueno como pudo haber llegado a ser. Pero, ¿cuál es éste error?

He aquí un ejemplo

Una práctica errónea

El control "malo" es un código que muchos reconoceremos, que se puede poner así:

Código :

private function init(e:Event = null):void 
{
   // Código Automatizado de FlashDevelop...
         
   // Dibuja al círculo...
         
   // Escucha Eventos
               stage.addEventListener( KeyboardEvent.KEY_DOWN, alPresionarTecla );
         
} // Fin de función init

private function alPresionarTecla( k:KeyboardEvent ):void
{
      switch ( k.keyCode ) 
      {
         case Keyboard.UP:
            círculo.y -= velocidad;
            break;
                  
         case Keyboard.DOWN:
            círculo.y += velocidad;
            break;
                  
         case Keyboard.LEFT:
            círculo.x -= velocidad;
            break;
                  
         case Keyboard.RIGHT:
            círculo.x += velocidad;
            break;
               
      } // Fín switch k.keycode

} // Final de función alPresionarTecla
            

Como nos podemos dar cuenta, el personaje se mueve primero un poco, y luego comienza a moverse "uniformemente". y, peor todavía, esto ocurre a diferente velocidad dependiendo de cada computadora, y uno sólo puede moverse en una sola dirección. ¿Por qué ocurre esto? Abre Word o cualquier editor de texto. Presiona una tecla, y déjala presionada. Verás cómo primero se escribe una letra, y luego se empiezan a escribir varias seguidas. ¡Esto es lo que ocurre con nuestro juego!

Trucos para corregir el defecto

Ahora bien, ¿Cómo podemos corregirlo? Este es uno de los trucos:

  1. Creamos una Lista con las teclas que están presionadas.
  2. Cada vez que presionamos una tecla, la añadimos a la Lista si no estaba ya en ella.
  3. Cada vez que dejemos de presionar una tecla, la quitamos de la lista.
  4. En Cada Frame, si está la tecla presionada, movemos el personaje.

El paso cuatro es importante, ya que, si lo hacemos cada frame en vez de cada vez que recibimos un "estímulo" del teclado, la velocidad será la misma para todos los jugadores (Siempre y cuando el framrate sea el mismo).

Éste sería el código:

1) Primero, hacemos nuestra lista, llamada "teclas", que será de la clase "Vector.<int>". Los Vectores son básicamente Arrays con un solo tipo de objetos, en este caso, números enteros ((Recuerda que las teclas tienen un código en un número entero)).

Código :

private var teclas:Vector.<int> = new Vector.<int>();

2) En segundo lugar, añadimos las teclas que vienen de KeybordEvent.KEY_DOWN. Para hacer esto, usamos la función indexOf y push de los Vectores (y Arrays). La primera nos dice el índice del elemento que buscamos, o "-1" si el elemento no está en el Vector. La segunda añade un elemento a un Vector.

Código :

private function alPresionarTecla( k:KeyboardEvent ):void
{      
   if ( teclas.indexOf( k.keyCode ) == -1 )
   {
      teclas.push( k.keyCode );
   }
   
} // Final de función alPresionarTecla

3) En tercer lugar, quitaremos una tecla de la lista cuando es levantada, en otras palabras, cuando recibims el evento de KeyboardEvent.KEY_UP. Para eso, usaremos indexOf de nuevo, pero esta vez con "splice", que quita unos elementos dados sus índices.

Código :

private function alLevantarTecla( k:KeyboardEvent ):void
{
   teclas.splice( teclas.indexOf( k.keyCode ), 1 );
      
} // Final de función alLevantarTecla

4) Usamos la lista en cada frame para mover el círculo. Para esto, volvemos a usar indexOf para saber si está o no está una tecla en la lista.

Código :

private function alEntrarAFrame( e:Event ):void
{      
   // Mueve al círculo si la tecla eestá presionada
   if ( teclas.indexOf( Keyboard.UP    ) != -1 ) { círculo.y -= velocidad; }
   if ( teclas.indexOf( Keyboard.DOWN  ) != -1 ) { círculo.y += velocidad; }
   if ( teclas.indexOf( Keyboard.LEFT  ) != -1 ) { círculo.x -= velocidad; }
   if ( teclas.indexOf( Keyboard.RIGHT ) != -1 ) { círculo.x += velocidad; }
   
} // Final de función alEntrarAFrame

5) Hay que recordar escuchar los eventos!

Código :

private function init(e:Event = null):void 
{
        // Código Automatizado de Flash Develop
   
   // Dibuja al círculo
   
   // Escucha Eventos
   this .addEventListener( Event.ENTER_FRAME,      alEntrarAFrame   );
   stage.addEventListener( KeyboardEvent.KEY_DOWN, alPresionarTecla );
   stage.addEventListener( KeyboardEvent.KEY_UP,   alLevantarTecla  );
   
} // Fin de función init

Para concluir

Me gustaría comentar que no hay que usar este código para todos los casos. Por ejemplo, si es para una cosa puntual (como atacar, saltar((en algunos juegos)), poner pausa o enmudecer el juego), este código es más contraproducente que beneficioso, ya que pondría pausa y la quitaría alternativamente a un ritmo incontrolable, por ejemplo. Es importante saber, entonces, cuándo usar este código, y cuándo usar el de siempre.

Aquí está el código completo. Acabo de comentar todo a excepción de los modos (versión buena o mala), cómo dibujar el círculo y cómo crear el botón (y cambiar de modo al hacerle click), lo cual debería ser o fácil de entender, o quizá ya haya sido explicado en otro tutorial.

Código :

package 
{
   import flash.display.Shape;
   import flash.display.Sprite;
   import flash.events.Event;
   import flash.events.KeyboardEvent;
   import flash.events.MouseEvent;
   import flash.text.TextField;
   import flash.ui.Keyboard;
   
   /**
    * ...
    * @author Agecaf
    */
   public class Main extends Sprite 
   {
      // Base
      private var modo:int = 0;
      
      // Gráficos
      private var círculo:Shape;
      private var botón:TextField;
      
      // Movimiento
      private var velocidad:int = 5;
      
      // Teclas
      private var teclas:Vector.<int> = new Vector.<int>();
      
      
      public function Main():void 
      {
         if (stage) init();
         else addEventListener(Event.ADDED_TO_STAGE, init);
         
      } // Fin de constructor
      
      private function init(e:Event = null):void 
      {
         removeEventListener(Event.ADDED_TO_STAGE, init);
         // entry point
         
         // Dibuja al círculo
         círculo = new Shape();
         círculo.graphics.beginFill( 0x000000 );
         círculo.graphics.drawCircle(0, 0, 30);
         círculo.graphics.endFill();
         círculo.x = 200;
         círculo.y = 200;
         addChild( círculo );
         
         // Crea Botón
         botón = new TextField();
         botón.text = "Cambiar!";
         botón.scaleX = 4;
         botón.scaleY = 4;
         botón.selectable = false;
         botón.x = 250;
         botón.y = 300;
         addChild( botón );
         botón.addEventListener( MouseEvent.CLICK, alCambiarDeModo );
         
         // Escucha Eventos
         this .addEventListener( Event.ENTER_FRAME,      alEntrarAFrame   );
         stage.addEventListener( KeyboardEvent.KEY_DOWN, alPresionarTecla );
         stage.addEventListener( KeyboardEvent.KEY_UP,   alLevantarTecla  );
         
      } // Fin de función init

      private function alEntrarAFrame( e:Event ):void
      {
         if ( modo == 1 ) { // BUENO!!!
            
            // Mueve al círculo si la tecla está presionada
            if ( teclas.indexOf( Keyboard.UP    ) != -1 ) { círculo.y -= velocidad; }
            if ( teclas.indexOf( Keyboard.DOWN  ) != -1 ) { círculo.y += velocidad; }
            if ( teclas.indexOf( Keyboard.LEFT  ) != -1 ) { círculo.x -= velocidad; }
            if ( teclas.indexOf( Keyboard.RIGHT ) != -1 ) { círculo.x += velocidad; }
            
         } // Fín de "si modo igual a 1"
         
      } // Final de función alEntrarAFrame
      
      private function alPresionarTecla( k:KeyboardEvent ):void
      {
         if ( modo == 0 ) { // MALO!!!
            switch ( k.keyCode ) 
            {
               case Keyboard.UP:
                  círculo.y -= velocidad;
                  break;
                  
               case Keyboard.DOWN:
                  círculo.y += velocidad;
                  break;
                  
               case Keyboard.LEFT:
                  círculo.x -= velocidad;
                  break;
                  
               case Keyboard.RIGHT:
                  círculo.x += velocidad;
                  break;
               
            } // Fín switch k.keycode
            
         } // Fín "si modo igual a 0"
         
         if ( modo == 1 ) { // BUENO!!!
            
            if ( teclas.indexOf( k.keyCode ) == -1 )
            {
               teclas.push( k.keyCode );
            }
            
         } // Fín "si modo igual a 1"
         
      } // Final de función alPresionarTecla
      
      private function alLevantarTecla( k:KeyboardEvent ):void
      {
         if ( modo == 1 ) { // BUENO!!!
            
            teclas.splice( teclas.indexOf( k.keyCode ), 1 );
            
         } // Fín de "si modo igual a 1"
         
      } // Final de función alLevantarTecla
      
      private function alCambiarDeModo( e:MouseEvent ):void
      {
         // Cambia de Modo
         if ( modo == 0 ) modo = 1;
         else if ( modo == 1 ) modo = 0;
         
         // Limpia Teclas
         teclas.length = 0;
         
         // Mueve el círculo
         círculo.x = 200;
         círculo.y = 200;
         
      } // Final de función alCambiarDeModo
      
   } // Fin de clase
   
} // Fin de package

Enviar comentario

via Cristalab http://feeds.cristalab.com/~r/clab/~3/RMwqK1tWDtk/

Guido Muchiutti creador de Incendilumen, una tableta para no videntes

Guido Muchiutti es de Chajarí, Entre ríos, Argentina y es uno de los creadores del proyecto Incendilumen, una tableta para personas no videntes. La idea nace de la charla que el y su compañero en el proyecto, Juan Manuel Franzante tuvieron con Marcos Ramírez, un amigo no vidente que estudia a distancia y día a día se enfrenta con la dificultad de usar una computadora y acceder a los materiales de estudio.

Incendilumen significa “encender la luz” y bajo ese concepto está pensado para resolver la necesidad de una gran población de usuarios no videntes, que actualmente están por fuera de los planes de las empresas de tecnología.

El proyecto Incendilumen trabaja como intermediario entre el usuario no vidente y la PC, proporcionándole información, pero más que eso, de información contextualizada. Imágenes, botones e interfaces gráficas ahora podrían ser leídas y entendidas gracias a INCENDILUMEN.

En esta entrevista Guido nos contará acerca de él y su proyecto.

Contanos acerca de tu amigo Marcos Ramírez y de cómo surge darle una respuesta a su problema.

Marcos tiene 20 años y es ciego. Se inscribió en la modalidad a distancia de la carrera de Derecho, en la sede de la UCASAL de Concordia, Entre Ríos, con la esperanza de que la bibliografía de estudio le llegue digitalizada, para que el programa que utiliza en la PC, que lee los archivos, lea esta bibliografía. En breve se encontró con la dificultad de que el programa no podía leer gran parte del material de estudio, así que recurrió a la hermana y a un grabador, para que ella le lea los apuntes para poder grabarlos, y luego reproducirlos cada vez que quisiera estudiar.

Todo eso, pero con lujo de detalles, me contó en 15 minutos un día que estábamos esperando para rendir una materia. Además me contó con orgullo que le encanta hablar, toca el piano, la guitarra y compone canciones que él mismo canta después, que trabaja en una radio de Concordia y de que le gustan las chicas con voz dulce y clara. Enseguida de que lo conocí me di cuenta de que la luz que faltaba en sus ojos estaba toda en su corazón.

¿Cuál es la realidad de las personas no videntes con respecto a la tecnología que usamos día a día?

Naturalmente, gran parte, por no decir toda la tecnología que se desarrolla hoy en día, está hecha específicamente para un mercado que puede ver sin dificultades. Es por eso que el sector de los no videntes y de tantas otras áreas de la discapacidad, están muy abandonadas en cuanto accesibilidad a la tecnología. No soy economista, pero entiendo que las empresas buscan ganancias y el mercado de los no videntes no es tan numeroso como el de los usuarios de móviles celulares. Aun así existen empresas que se dedican a adaptar computadoras o generar instrumentos para que los ciegos puedan utilizar una computadora, pero siempre se trata de que ellos se adapten a nuestro paradigma, nunca antes, se creó algo que les brinde una conexión directa con el mundo, sin traducciones ni adaptaciones.

El mejor ejemplo de esto son los programas que hoy por hoy ellos usan, que leen y describen la pantalla del monitor. Lo que hacen es ir saltando de botón en botón, como cuando uno presiona la tecla TABS y el programa va leyendo lo que dice el botón. Claro que un botón, propiamente dicho, es solo una abstracción de la realidad, para ellos no tienen ningún sentido. Nosotros lo vemos como un rectángulo con un poco de relieve, pero la esencia del botón, no es esa, sino que es una interfaz que al presionar genera un evento, lo gráfico es meramente accidental. Estos programas que leen, tienen muchas dificultades, además de que al convertir lo gráfico en audio, se pierde una dimensión de la información. Por ejemplo, las personas que podemos ver utilizamos mucho las tablas para resumir información:

En esta tabla se puede ver fácilmente el crecimiento de la población de las ciudades en los distintos censos. Si ahora cerramos los ojos y le pedimos a alguien que nos lea esta tabla, podremos darnos cuenta de que pierde totalmente el sentido que tiene, que es el de presentar información de manera simple y resumida. Al leerla, sin poder verla, perdemos la dimensión espacial de la información que se está mostrando, la estructura que tiene y que hace que sea fácil de interpretar y procesar.

Este ejemplo puede generalizarse a todo el paradigma gráfico y cuando un programa les lee la pantalla a las personas no videntes está descartando la dimensión espacial de las aplicaciones y programas que corren en la PC, por lo cual, hace que la experiencia con el uso de la PC no sea la necesaria como para trabajar o estudiar, por ejemplo.

La Asociación de Personas con Discapacidad Visual (Aperdivi) de Concepción del Uruguay los asistió desde un principio con este proyecto: cómo fue la experiencia de trabajo y qué te ha dejado a vos en lo personal y profesional.

La primera entrevista que tuvimos con la gente de Aperdivi fue la que más nos motivó a seguir adelante. Ese día estábamos Juan Manuel Franzante y yo, ya que al comienzo estábamos nosotros dos, y había tres personas ciegas, Leandro, Maria Julia y Simón y estaba Roxana Zuzunegui, que es la directora del área de discapacidad del municipio de Concepción del Uruguay, (persona que nos ayudó muchísimo).

Leandro es el presidente de Aperdivi, María Julia es docente, ciega de nacimiento y enseña [url=http://es.wikipedia.org/wiki/Braille_(lectura)]braille [/url]en la escuela Ponce de León, que es una escuela para chicos con discapacidades visuales y auditivas. Simón es Ingeniero Agrónomo y perdió la vista paulatinamente.

Ni bien les presentamos la maqueta de madera que habíamos armado y les explicamos un poco en qué consiste la idea, ellos nos entendieron y comenzaron a preguntarnos “cuándo iba a estar terminado el dispositivo”, enseguida empezaron a imaginar el uso que le darían: Maria Julia dijo que seria muy cómodo y fácil enseñar braille a los chicos, Simón dijo que podría volver a trabajar ya que tendría acceso a la computadora. Todas estas especulaciones que hacían nos dieron la pauta de que la idea tenía un gran impacto social y nos alegró el corazón saber que nosotros podíamos mejorar la calidad de vida de algunas personas. Desde ese día sé que hacer el bien causa placer.

¿Cuáles fueron las áreas que debieron investigar para iniciar el proyecto?

La investigación que desarrollamos fue y es muy compleja y mantiene varias ramas paralelas:

  • La tecnológica: relacionada con el desarrollo del dispositivo en sí y los mecanismos que lo integran.
  • La pedagógica: relacionada con el modo y la forma en que las personas ciegas perciben y aprenden. En esta etapa nos ayuda muchísimo la escuela Ponce de León y sus maestras.
  • La sensitiva y relativa a la percepción: estudia las características que debe tener el dispositivo para que todas las personas ciegas, ya sea de nacimiento o no, puedan percibir el relieve que se genera.
  • La de la estandarización: Investigamos y generamos un estándar para representar todas aquellas estructuras útiles y necesarias para transmitir la información, por ejemplo, las tablas, listas, cuadros sinópticos.

¿Cuál fué la organización del equipo de trabajo? Cuántos son y qué abarca cada uno?

Conmigo somos siete en total:

  • Leonardo Hoet
  • Gaston Revori
  • Luis Echazarreta
  • Nicolas Marquizo
  • Exequien Chesini
  • Juan Manuel Franzante

Leonardo es el que más experiencia tiene en la parte de electrónica así que guía al equipo de desarrollo y participa activamente en él. El equipo de desarrollo somos todos, pero los que más intervienen son Exequiel, Nicolas, Luis y Gaston. Gastón, además, es el encargado de desarrollar el driver que maneja el dispositivo.

Juan y yo diseñamos, yo particularmente diseño lo estructural, él, además, está encargado de investigar la estandarización de figuras. Yo me encargo de investigar y hacer las pruebas pedagógicas y de tacto.
Cabe aclarar que esto es una separación en grandes razgos, pero en realidad, todos estamos participando en todo, no somos muchos para el amplio campo que estamos abarcando y casi siempre surge alguna traba que terminamos atacándola entre todos.

Además, hay algunas etapas a las cuales aún no hemos podido llegar, y todavía no sabemos bien quién las va a encarar, o si vamos a ser todos, por ejemplo el desarrollo de las librerías de software de alto nivel para el uso del dispositivo.

¿Cuáles son las dinámicas de trabajo para poder explotar al máximo la creatividad de cada integrante en pos de una solución?

Actualmente utilizamos una metodología ágil como las que se usan para el desarrollo de software, hacemos reuniones semanales, tenemos un gran pizarrón donde anotamos las ideas y dificultades que van surgiendo y al lado anotamos los integrantes que están encargados de afrontarlas.

Además utilizamos una comunidad privada en internet para mantenernos comunicados todo el tiempo. Todas las cosas que van surgiendo, por insignificantes que parezcan, ni bien se nos ocurren, las publicamos en esa comunidad para no olvidarnos, después en las reuniones vamos viendo esas publicaciones y las trabajamos.

Al comienzo de este proyecto decidimos adoptar y respetar el famoso principio de la navaja de Ockham, “La solución más simple suele ser la correcta” y creo que es esto lo que hace que nuestra idea y diseño sea lo que es. Además estamos abiertos a sugerencias y críticas de todos los que quieran hacerlas, sabemos que el mundo de las ideas es de todos, así que conscientes de eso, si viene alguien con alguna buena idea, lo reconocemos y la aceptamos.

Contanos brevemente (o lo que puedas contar) en qué consiste el producto.

El dispositivo es una interfaz hombre-máquina, es decir, es mediadora entre la PC y los usuarios, en este caso una persona ciega. Básicamente se conecta a una PC y convierte la información a relieve. La idea es simple, la complejidad está en el mecanismo que genera relieve. El primer prototipo que hicimos, es electromecánico, es grande, pesado y poco eficiente, pero es perfecto para mostrar y transmitir la idea y sobre todo, para hacer las pruebas al tacto y las pedagógicas. Este prototipo, que era lo único que podíamos hacer en su momento, funciona con servomotores y una placa Arduino que los maneja. El driver está hecho en el lenguaje nativo del arduino y creamos algunas librerías simples en C++, pero solo para hacer las pruebas.

Todavía no dedicamos recursos a la programación, porque la mayor complejidad esta en lo electrónico y una vez obtenido el dispositivo en sí, la programación es lo más simple.

Si uno quiere imaginar el producto, debe pensar en una superficie rectangular de 30 por 50 centímetros que posee una matriz de agujeros de un milímetro de diámetro y separados por dos coma cinco milímetros. Por estos agujeros salen cilindros que suben y bajan y de esta forma generamos el relieve en el prototipo electromecánico. Una idea simple, como la rueda.

¿Bajo qué lenguaje de programación están desarrollando el framework para facilitar el desarrollo a las aplicaciones que se adapten a este dispositivo?

Si bien no abordamos este aspecto aún, sabemos que para el desarrollo de librerías de alto nivel, que utilizarán en el futuro los desarrolladores que quieran que sus programas tengan una salida en el dispositivo, tendremos que abordar dos caminos, las librerías para lenguajes de aplicaciones, (aquí entran tanto las aplicaciones de escritorio como las móviles) y la librería para aplicaciones web, en esta última tenemos pensado hacer un intérprete XML. Es por esto que hacemos énfasis en generar un estándar para representar las entidades y estamos trabajando en ellos.

Voy a dar un ejemplo, para que este aspecto quede un poco más claro.
Cuando se muestre una página web en el dispositivo, las típicas etiquetas <input> tendrán una representación directa, será un espacio donde se podrá ingresar texto. Las personas que podemos ver, percibimos una caja con un color que generalmente contrasta con el resto de la aplicación y un cursor que titila, indicando que podemos ingresar texto. Una persona ciega, lo que percibirá, en este caso, será un contorno de relieve:

Para indicar que se puede ingresar texto en él, se puede hacer que un punto de relieve interno suba y baje continuamente.

¿Cuál es el interés de las empresas de tecnología en el proyecto?

Varias empresas se acercaron con intenciones muy variadas. Por ejemplo, un día nos escribió Lucas Fares, encargado de responsabilidad social de Globant con la historia de que ellos habían empezado con un proyecto similar y que cuando buscaron en Google antecedentes se encontraron con el nuestro. Luego hicimos una videoconferencia pero no nos convenció el acuerdo que nos propuso y la presión que intentaron hacer. Así que les dijimos que en esos términos no podíamos seguir, porque básicamente, nosotros tenemos un compromiso directo con muchas personas no videntes que se interesaron y que participaron activamente en el proyecto y queremos que el dispositivo esté al alcance de todas las personas, principalmente que sea economico.

No nos interesa que sea un mero proyecto para mostrar chapa de empresa altruista, Incendilumen va más allá del mercado, de la oferta y de la demanda. No digo que lo vamos a regalar, porque no podemos. Estamos teniendo dificultades en la variable económica hasta para armar los prototipos, pero tampoco empezamos y abordamos esto para hacernos millonarios. Todos pensamos lo mismo, todos en el equipo vemos la sociedad y a las personas desde otra perspectiva, confiamos en la gente y en las empresas y esquivamos a los que no ponen todas las cartas sobre la mesa.

Por suerte hemos dado con una empresa que fabrica tablets y es argentina, se llama Saikano Technology con la cual estamos en proceso de crear un consorcio cooperativo para fabricar el primer prototipo electrónico e intentar reproducir algunos ejemplares. Esta gente tuvo un trato diferente al resto de las empresas que golpearon nuestras puertas, creo que porque es una empresa que empezó como una emprendimiento familiar y todavía no se olvidó de las buenas prácticas y costumbres.
Por el momento creemos que hemos dado en buen puerto y estamos contentos de que así sea.

¿Cómo fue el paso de INCENDILUMEN por INNOVAR 2012 (Concurso Nacional de Innovaciones)?

La experiencia fue muy satisfactoria, conocimos a mucha gente que se acercó a dar su opinión, hasta nos recomendaron muchas cosas para que probemos. En esa época todo lo que nos sugerían valía muchísimo, porque solo teníamos una idea, un concepto, y aún no habíamos armado el prototipo electromecánico.

Si bien no obtuvimos ningún reconocimiento, seguramente porque había muchos proyectos muy interesantes, nos sirvió muchísimo por las personas que conocimos. Con muchas de ellas hoy seguimos en contacto.

Por cierto, invito a la gente a que vea los proyectos que ganaron en 2012 en la categoría “concepto innovador”, que es en donde estaba inscripto el proyecto Incendilumen.


Juan Manuel Franzante y Guido Muchiutti presentando el proyecto en INNOVAR 2012

El gobierno argentino ha tomado la bandera de llevar lo digital y tecnológico a las áreas más necesitadas de la población con el proyecto “Conectar Igualdad”. Sabés si tienen una política similar en puerta para personas con discapacidad?

No estoy seguro si hay una política exclusiva para personas con discapacidad, pero si se que la política de integración que adopto este gobierno es favorable y está abierta a este tipo de proyectos, ya que el objetivo principal es que desaparezca el muro que hay entre la tecnología y las personas no videntes, básicamente acercarlos a ella, proporcionarles una herramienta que les permite recibir la información directamente y sin adaptaciones, de forma autónoma e independiente.

Voy a realizar una aclaración que no se si va en esta pregunta. las personas ciegas, hoy en día, necesitan siempre de otra persona que pueda ver para empezar a usar la computadora. Debido a que el programa que lee la pantalla presupone que la persona que lo usa ya tiene conocimientos del paradigma gráfico, de esta manera, cuando el programa dice, por ejemplo, “Botón Aceptar”, la persona debe saber lo que es un botón y qué esperar de él. Así es que una persona que sí conoce el paradigma debe enseñarle primero al ciego, lo que es un botón una ventana, una lista.

Generalmente se recortan cuadraditos de goma eva y se le va explicando a medida que él toca estas figuras. De esta forma el ciego genera una abstracción y un concepto de lo que son estas entidades. Un niño de 6 años que puede ver, no requiere de nadie para empezar a jugar con la computadora, y las abstracciones las va generando solo a medida que ve e interactúa. Es por esto que los ciegos no son autónomos ni independientes a la hora de usar la PC.

Tengo entendido que en un inicio la propuesta del proyecto no fue “interesante” para las autoridades de tu Universidad. ¿Cuáles fueron los obstáculos que tuvieron para llevar adelante el proyecto?

Sí, en un principio, poca gente se interesó por este proyecto. Creo que es natural, por lo menos en Argentina no jugar las fichas hasta ver los resultados. Acá nos manejamos así. Así que no juzgo la actitud de nadie, no soy quien, aunque yo me maneje diferente. Pero bueno, lo importante es que hoy por hoy, sí tenemos el apoyo de la facultad que nos brinda el espacio para reunirnos y nos dejó a disposición la oficina de vinculación tecnológica para que podamos gestionar un subsidio y nos pongamos en contacto con empresas.

Con respecto a los obstáculos, siempre fue la variable económica la que tuvimos que acotar y la que nos sigue costando despejar. Pero bueno, quizás es por esto que hemos priorizado la economía en el desarrollo y el resultado es un dispositivo económico.

¿Cuántos prototipos llevan desarrollando?

En total son dos terminados y uno en desarrollo. El primero fue el electromecánico, el segundo es una mezcla de electromecánico y otros componentes que nos permiten resaltar distintas partes de la superficie de relieve y el tercero, es el electrónico que está hecho con materiales muy modernos.

¿En qué etapa está el proyecto hoy? Cuáles son los desafíos próximos que deberán sobrellevar?

Hoy estamos investigando una serie de materiales muy modernos que no se consiguen en Argentina, lo hacemos en conjunto con la empresa con la que estamos tramitando el consorcio y tenemos planificado terminar el prototipo electrónico para mediados de 2015.

Al mismo tiempo estamos definiendo un estándar y seguimos haciendo pruebas con personas ciegas para mejorar la experiencia sensitiva del nuevo prototipo.

Innovar, inventar, emprender y sobre todo crear: ¿Qué significan estas características en una realidad como la de Argentina?

Mi humilde opinión, la de un hombre libre y de buenas costumbres, que acaba de terminar su carrera de ingeniería, (no la de un estadista, economista o politólogo), es que cualquier país que en verdad cumpla con esas características es un país próspero, con un futuro prometedor y con un pueblo laborioso. En la medida que Argentina apunte el timón a cumplir con esas características, que no solo son características, sino que son requerimientos que demanda la comunidad internacional, vamos estar bien y vamos a ser mejores cada día.

Claro que para innovar, inventar, emprender y crear, hay que tener un pueblo educado y motivado, sin fanatismos, ni complicidades, sin amiguismo y en donde el rango vaya acompañado del mérito. Todo depende de todos.

Pero esa es mi humilde opinión, nada más, no digo que hoy no se cumplan estas características ni nada de eso, son cosas que siempre pueden estar mejor.

Para ser creativo hay que pensar “por fuera de la caja”. ¿Cuáles son tus actividades por fuera de la carrera de Ingeniería en Sistemas de Información?

Particularmente me gusta mucho leer, no siempre tengo el tiempo que quisiera para hacerlo, pero leer me ayuda mucho a pensar con claridad. Leo muy variado, desde novelas hasta libros en general que no tienen nada que ver con la carrera. Me gusta mucho la política, pero no la política partidaria, la política de verdad, así que la mayoría de mis lecturas son clásicos o no tan clásicos de política: La República, El Príncipe, El Leviatán, El espíritu de las Leyes, El Contrato Social, El Manifiesto, etc.

Más que la politica me gusta la sociedad, así que también leo mucho a Mario Bunge y José Ingenieros, libros como El Hombre Mediocre o Las Fuerzas Morales, hacen que un hombre suelte lágrimas. También hago gimnasio, porque cuando el cuerpo y la mente no están en equilibrio se hace difícil pensar, por lo menos en mi caso.

También me apasiona reunirme con mis amigos, con los cuales solucionamos el mundo en cuestión de horas, diagramamos proyectos mundiales, extinguimos el hambre, erradicamos el fanatismo, etc.

Con respecto a la creatividad, cuando voy a alguna escuela a hablar sobre el proyecto, mi consejo para los chicos es que no se acuesten pensando en qué pueden inventar, sino que piensen qué pueden solucionar. Si detectan una necesidad, es cuestión de tiempo inventar. Una necesidad de la sociedad o particular es una solución en potencia. Luego para dar una solución, se tendrá que mejorar algo existente o, el caso más raro, inventar algo desde cero. La creatividad de cada uno encontrará una mejor o una peor solución a esa necesidad, así que posiblemente vendrá otro que dará una solución mejor a la misma necesidad, así es el ciclo inventivo.

Muchas gracias Guido por tu tiempo. Te deseamos mucho éxito con Incendilumen para el futuro.

De nada, Feliz Navidad y Año nuevo. Salud por el gran pueblo latinoamericano.

Enviar comentario

via Cristalab http://feeds.cristalab.com/~r/clab/~3/xscDBSeIb0g/