Está en la página 1de 87

AO ----------- 0

NMERO -------- 3
FECHA: 2013-01-28

#3
ELVIS

HD DEVELOPERS
+
Hackers &

Magazine digital de distribucin


mensual sobre Software Libre, Hacking y Programacin
para profesionales del sector de Tecnologas de la Informacin

Staff
Eugenia Bahit
Indira Burga
Laura Mora
Mara Jos Montes Daz
Milagros Infante Montero

Arquitecta GLAP & Agile Coach


Ingeniera de Sistemas
Administradora de Redes y Sistemas
Tcnica en Informtica de Gestin
Est. Ingeniera de Sistemas

Hackers & Developers Magazine se distribuye bajo una licencia Creative Commons Atribucin
NoComercial CompartirIgual 3.0 Unported . Eres libre de copiar, distribuir y compartir este material.

FREE AS IN FREEDOM!

Hackers &

HD DEVELOPERS
+

Hackers & Developers Magazine, es


una iniciativa sin fines de lucro
destinada al fomento y difusin de
las tecnologas libres presentes o
futuras, bajo una clara ptica
docente y altruista, que resulte de
inters tcnico y/o cientfico a
profesionales del sector de
Tecnologas de la Informacin.
Hackers & Developers Magazine se
sostiene econmicamente con el
apoyo de la comunidad, no
recibiendo subvencin alguna de
ninguna empresa, organizacin u
organismo
de
Gobierno.
Necesitamos de tu apoyo para
poder mantener este proyecto.

Aydanos a continuar
con este proyecto
Puedes hacer un donativo ahora,
de 10, 15, 25, 50, 100 o 150 USD
para ayudar a que Hackers &
Developers Magazine pueda seguir
publicndose de forma gratuita,
todos los meses. Puedes donar con
PayPal o Tarjeta de Crdito a travs
del siguiente enlace:
www.hdmagazine.org/donar

#3

Hacker es alguien que disfruta


jugando con la inteligencia
Richard Stallman
Free Software, Free Society
(Pg. 97), GNU Press 2010-2012

En esta edicin:
Twitter Bootstrap: un elegante, intuitivo y poderoso framework..........4
Web Scraping: excavando en la red......................................................10
Cmo empiezo con JavaScript?...........................................................17
Conociendo a DOM: Parte I..................................................................26
Manual de MVC: (3) Los objetos View..................................................32
Mis primeros pasos con MongoDB.......................................................40
Introduccin a Perl (Parte I).................................................................45
Introduccin al desarrollo dirigido por pruebas..................................51
IPv6, el presente.................................................................................. 57
Psate a GNU/Linux con Arch: Gestores de ventanas y escritorios........69
Invitacin al proyecto GcalcTool: GNOME Calculator...........................79
Ubuntu Rookie: Toma 3........................................................................84

CON TU DONACIN DE USD 150

RECIBES DE REGALO,
UNA FUNDA DE
NEOPRENE PARA TU
ORDENADOR PORTTIL
VALUADA EN USD 25.(Origen: Estados Unidos)

Y LAS SECCIONES DE SIEMPRE:


ASCII Art...................................................................... Pg. 86
Este mes: Homenaje Rock & Roll con Elvis Presley
Zona U!........................................................................ Pg. 87
La comunidad de nuestros lectores y lectoras

Crditos
Hackers & Developers Magazine es posible gracias al compromiso de:

Responsable de Proyecto

Eugenia Bahit
Responsables de Comunicacin
Indira Burga (Atencin al Lector) - Milagros Infante (Difusin)

Staff Permanente
Eugenia Bahit
Arquitecta GLAMP & Agile Coach
www.eugeniabahit.com
Indira Burga
Ingeniera de Sistemas
about.me/indirabm

Laura Mora
Administradora de Redes y
Sistemas GNU/Linux
blackhold.nusepas.com
Mara Jos Montes Daz
Tcnica en Informtica de Gestin
archninfa.blogspot.com.es

Milagros Infante Montero


Estudiante de Ingeniera en Sistemas
www.milale.net

Colaboradores Estables
Elizabeth Ramrez
(Ingeniera Electrnica)

Redactores Voluntarios

Sergio Infante Montero


(Ingeniero Informtico)

Celia Cintas
Eliana Caraballo

Yecely Daz
(Maestra en Inteligencia Artificial)

Difusin
Hackers & Developers Magazine agradece a los portales que nos ayudan con la difusin del proyecto:

www.debianhackers.net

www.desarrolloweb.com

E-mail de Contacto:
contacto@hdmagazine.org

www.desdelinux.net

Twitter Bootstrap: un
elegante, intuitivo y
poderoso framework

4
RESPONSIVE WEB DESIGN

Hackers & Developers Magazine Ao 0, Nmero 3

Buscas un framework que te permita hacer magia en


tus desarrollos? Conoce a Twitter Bootstrap y
sorprndete con la cantidad de cosas geniales que
puedes hacer. Cmo el Responsive Web Design
combinado con esta herramienta te da a entender
grficamente como puedes obtener un diseo para
gobernar a todos.

Escrito por: Milagros Alessandra Infante Montero (Est. Ing. Informtica)


Estudiante de Ingeniera Informtica. Miembro de APESOL
(Asociacin Peruana de Software Libre) y de la comunidad de software
libre Lumenhack. Miembro del equipo de traduccin al espaol de
GNOME. Apasionada por el desarrollo de software, tecnologa y
gadgets. Defensora de tecnologas basadas en software libre y de
cdigo abierto.
Webs:
Blog: www.milale.net
Redes sociales:
Twitter / Identi.ca: @milale

n los primeros das de Twitter, se usaban muchas libreras que fueran familiares
con los requerimientos del front-end pero haba inconsistencias que dificultaban el
poder mantenerlos; y es cuando Bootstrap naci y creci significativamente.

Twitter Bootstrap es Software Libre con licencia Apache 2.0

Por qu Twitter Bootstrap?


Al inicio Bootstrap solo era CSS, pero a medida que pas el tiempo gan un rango de
caractersticas como declaraciones identadas, variables, operaciones y funciones de

color. Las ventajas ms resultantes que tiene es su fcil implementacin con solo
ponerlo en tu cdigo y el poderoso CSS que contiene y cubre las necesidades del
desarrollo de la web.
Al ver en profundidad a Bootstrap encontraremos 7 archivos diferentes:
1. reset.less: Un restablecimiento CSS creado por Eric Meyer y modificado para
nuestro uso eliminando elementos innecesarios.
2. preboot.less: Variables de color y mixins para gradientes, transparencias y
transiciones.
3. scaffolding.less: Estilos bsicos y globales para generar un sistema de red,
diseo estructural y plantillas de pgina.
4. type.less: Cabeceras, texto del cuerpo, listas, cdigo y un sistema de tipografa
verstil y durable.
5. patterns.less: Elementos de interfaz repetibles como navegacin, modales e
informacin sobre herramientas para llevarlo ms all de los estilos
predeterminados.
6. forms.less: Estilos duraderos para diversos tipos de entrada, diseo de
formularios y estados de control.
7. tables.less: Estilos para datos tabulares en pantallas variadas.

Bootstrap funciona dando una solucin clara y uniforme a las tareas de de interfaz de
cada da de los desarrolladores; se ha convertido en una de las muchas herramientas del
front-end en nuevas aplicaciones y sitios Web. Se usa para arrojar prototipos rpidos y
gua la ejecucin de diseos mas sofisticados y esfuerzos de ingeniera ms grandes. Es
el camino simple para aplicaciones altamente usables, limpias y rpidas.

Responsive web design con Twitter Bootstrap


Responsive web design es un enfoque, el cual debe cambiar tu manera de pensar. La
idea bsica detrs es: un diseo para gobernarlos a todos (s, como en el Seor de los
anillos, un anillo para gobernar a todos).
No m.tu-dominio.com; no touch.tu-dominio.com; no 3 archivos de CSS separados; no 7
archivos grficos para cada dispositivo o cada orientacin; solo tu-dominio.com tal
cual en plataformas de escritorio, tablets, Smart Phones, etc.

One design to rule them all


Twitter Bootstrap ofrece un montn de cosas increbles:

Estilos globales para el cuerpo para restablecer tipo y fondo, estilos de enlace,
2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 5

sistema de red y dos diseos simples.

Estilos para elementos HTML comunes como tipografa, cdigo, tablas,


formularios, botones, un conjunto de iconos, etc.

Estilos bsicos para componentes de interfaz comunes como pestaas, alertas,


cabeceras de pgina y ms.

Plugins de JavaScript para cosas como informacin sobre herramientas, modales,


etc.

La ms importante, es que es fcil de aprender y usar, ya que tiene muy buena


documentacin y todos los ejemplos con los que un desarrollador puede soar.

Empezando con Twitter Bootstrap


Al entrar a la pgina oficial 1 descargamos la versin personalizada y luego de extraer el
paquete obtenemos lo siguiente:
milagros@joe:~code/bootstrap$ tree
.
css

bootstrap.css

bootstrap.min.css
js

bootstrap.js

bootstrap.min.js
img

glyphicons-halflings.png

glyphicons-halflings-white.png
prueba.html

Para descargar Twitter Bootstrap, ingresa en http://twitter.github.com/bootstrap/

Por ejemplo, si tenemos un archivo HTML en blanco:


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Proyecto sin bootstrap</title>
</head>
<body>
<p>Nuestra pgina an no es responsive</p>
</body>
</html>

Para tener ya Bootstrap en nuestro archivo debemos hacer la debida referencia al CSS y
1

http://twitter.github.com/bootstrap/

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 6

al JS de Bootstrap:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Proyecto con bootstrap</title>
<link rel="stylesheet" href="css/bootstrap.min.css">
<script src="js/bootstrap.min.js"></script>
</head>
<body>
<p>Nuestra pgina an no es responsive</p>
</body>
</html>

Layouts en Twitter Bootstrap


Diseo Fijo
Debes elegir esta opcin si ests creando un sitio web estndar y probablemente no
necesites el 100% de tu pantalla. Se elige la opcin 940px. Provee un diseo de anchura
fija (y opcionalmente Responsive) solo requiriendo de <div class="container">.
<body>
<div class="container">
...
</div>
</body>

Diseo Fluido
Esta opcin es por si necesitas que tu aplicacin use todo el ancho (el 100%) de tu
pantalla. Crea un diseo fluido: una pgina de dos columnas con <div
class="container-fluid">, ideal para aplicaciones y documentos.
<div class="container-fluid">
<div class="row-fluid">
<div class="span2">
<!--Sidebar content-->
</div>
<div class="span10">
<!--Body content-->
</div>
</div>
</div

Veamos la magia de Bootstrap...


Por ejemplo, vamos a usar un layout fijo:

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 7

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Empezando con Bootstrap en Hackers and Developers Magazine</title>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"">
</head>
<body>
<div class="container">
<div class="hero-unit">
<h1>Ejemplo de diseo responsive para Hackers and Developers
Magazine</h1>
<p>Hola lectores de Hackers and Developers Magazine, gracias por
seguirnos, aqu pueden contactarse con nosotras.</p>
<p><a class="btn btn-primary btn-large">Concenos &raquo;</a></p>
</div>
<div class="row">
<div class="span4">
<h2>Redactores</h2>
<p>Conoce aqu a las personas detrs de este proyecto: Quienes
forman parte del staff, quienes nos brindan su apoyo como
redactores voluntarios y ms. </p>
<p><a class="btn" href="#">Pulsa aqu &raquo;</a></p>
</div>
<div class="span4">
<h2>Artculos</h2>
<p>Aqu encontrars la lista de temas ya tratados en H&D Magazine,
pulsa para verlos y encontrar informacin muy til. </p>
<p><a class="btn" href="#">Pulsa aqu &raquo;</a></p>
</div>
<div class="span4">
<h2>Lineamientos</h2>
<p>Hackers & Developers Magazine, surge como una iniciativa sin
fines de lucro destinada al fomento y difusin de las tecnologas
libres presentes y futuras, bajo una clara ptica docente que
resulte de inters tcnico y/o cientfico. </p>
<p><a class="btn" href="#">Pulsa aqu &raquo;</a></p>
</div>
</div>
</div>
</body>
</html>

Descomponiendo el cdigo veremos:

<div class=container></div> Esto sirve como contenedor para todo el


contenido de tu pgina, en caso de que se quiera usar un layout fluido solo se
aade como clase, container-fluid en vez de container.

<div class=row></div> Esto sirve para crear filas, es un contenedor de


columnas que cuida los mrgenes, relleno, etc. En caso de un layout fluido solo se
reemplaza por row-fluid.

<div class=span4></div> Un layer con la clase span es una columna (el mximo
es 12 columnas); en el ejemplo existen 3 cajas en una fila (span4, porque 12/3 es
2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 8

4. Si se quisieran mostrar 6 columnas, 12 / 6 = span2).

<div class=hero-unit></div> Esto es otro componente de Bootstrap aadido


para hacerlo ms genial.

Pero este ejemplo no debe quedar ah.


Al revisar la documentacin te encontrars con componentes de interfaz de usuario ms
avanzadas. Tambin puedes aadir una serie de plugins de JavaScript estandarizados,
como pestaas o controles deslizantes que van muy bien con el estilo de Bootstrap
predeterminado.

Y nuestro resultado ser:

Y lo genial de todo esto es cuando eligiendo el diseo fluido (container-fluid y row-fluid)


redimensionas tu navegador y te das cuenta de que todo es responsive y as es como
puedes empezar a hacer magia con el elegante, intuitivo y poderoso Twitter Bootstrap.

La simplicidad es la mxima expresin de la sofisticacin

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 9

INTELIGENCIA
ARTIFICIAL

Web Scraping:
excavando en la red

Utilizados en ciencia ficcin por Trish Dunne en su


araa de bsqueda para encontrar el SYMBOLON, la
construccin de web scrapers y spiders se ha
convertido en el nuevo FizzBuzz a la hora de
presentar una prueba tcnica en una entrevista de
trabajo, por lo que no est de ms conocer las
tcnicas bsicas de su funcionamiento.

Escrito por: Elizabeth Ramrez (Ingeniera Electrnica)


Desarrolladora de Software en las Industrias Web, Telecomunicaciones y
Entretenimiento. Especialista en Sistemas de Informacin, con nfasis
en Real-Time Billing. Miembro de IEEE Signal Processing Society, New
York Section. Wantrepreneur.
Webs:
About.Me: http://about.me/elizabethr
Redes sociales:
Twitter: @eramirem

n algunas ocasiones, hemos necesitado procesar informacin de la web de una


manera diferente a la convencional, es decir, usando un navegador. El navegador
slo descarga y renderiza datos de pginas web, pero si tenemos necesidades
especficas de bsqueda de informacin, de ejecucin de acciones y/o toma de
decisiones usando la informacin encontrada, debemos hacerlo de manera manual.
Cuando descargamos el contenido de una pgina web usando un navegador, lo
realizamos de manera manual y, a partir de all debemos decidir qu informacin de la
descargada es relevante para nuestra necesidad, tambin de manera manual. Los web
scrapers y spiders permiten hacer esta bsqueda, descarga y procesamiento de
informacin de manera programtica y automtica.
Los web scrapers ofrecen automatizacin y cierto nivel de inteligencia para la obtencin
y procesamiento de datos de internet. Podra decirse que los web scrapers nos sirven
para descubrir el "internet oculto" en la capa de presentacin de datos. Es bsicamente
adaptar la World Wide Web a necesidades personales y capitalizar informacin que est
"escondida" en la web. Entre los diferentes usos para un web scraper se pueden
encontrar:

Agregacin de noticias que solo muestre historias nuevas relevantes, ignore las
historias redundantes y las que hayan sido ledas previamente.
2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 10

Detectar mercancas/servicios al ms bajo precio, tpico en los sitios que ofrecen


reserva de hoteles y tarifas de avin.

Optimizacin de pginas web, permitiendo analizar la estructura del HTML y el


CSS, optimizndola para mvil.

Cuando un sitio web despliega informacin acerca de un tpico de nuestro


inters, pero no proporciona una API para que nuestros propios programas
realicen consultas de dicha informacin, la solucin es usar screen scraping. Por
ejemplo: informacin de la bolsa de valores, tasas de cambio, eventos.

Sin demasiado optimismo, activ la araa, dando as inicio a


una partida mundial de go fish. A velocidad cegadora, la
araa se puso a comparar las frases con textos de todo el
mundo, en busca de un equivalente exacto. Dan Brown El
Smbolo Perdido.
Normalmente, los conceptos de crawler, scraper y spider, son usados de manera
indistinta. Aunque no existe una definicin precisa para estos trminos, hay algunas
diferencias en su funcionamiento y los casos en que son usados.
Un web crawler recorre enlaces en la web usando un sitio de partida y permite crear
copias del contenido de los sitios visitados, de manera similar a un motor de bsqueda.
El proceso de spidering es el que permite iterar a travs de los enlaces encontrados en el
proceso de crawling hasta el nivel de profundidad indicado. Los enlaces son
identificados mediante las etiquetas <a></a> de cada pgina, por lo que es requerido un
anlisis sintctico (parsing2) del HTML. La combinacin del proceso de crawling +
spidering conforma el conocido web robot. El web robot debe regirse por lo
especificado en el archivo robots.txt 3, evitando visitar los sitios que no estn
autorizados en dicho archivo.
Un web scraper en cambio, realiza la extraccin de informacin de sitios especficos,
buscando expresiones regulares, palabras clave, elementos, atributos, entre otros. Para
llevar a cabo la automatizacin de la bsqueda y procesamiento de informacin en la
web, los tres procesos trabajan en conjunto.

Anatoma
Existen varios esquemas de operacin de un web scraper, entre los ms bsicos se
encuentran los siguientes:

Uno-a-muchos
La estructura de uno a muchos es comn de un scraper que busca por ejemplo,

2
3

Separacin de la informacin que necesitamos, la cual est contenida en otro conjunto de datos
The Robots Exclusion Protocol. Para ms informacin, visitar http://www.robotstxt.org/robotstxt.html

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 11

informacin de precios de boletos de avin a travs de diferentes sitios.

Uno-a-uno
Esta estructura es ms tpica de un screen scraper, en el cual se accede al
contenido de un sitio web especfico. Por ejemplo, buscar el top 5 de historias
con mayor calificacin en un blog.

Cuando se escribe un web scraper, se debe tratar de imitar el comportamiento humano


al usar un navegador, pero de manera programtica. Introducir delays aleatorios -o al
menos variables (no realizar el scraping exactamente cada 30 minutos, por ejemplo)- y
no lanzar las tareas de scraping en horas de bajo trfico, permite respetar a los sitios en
los cuales estamos realizando extraccin de informacin. Esto es especialmente
importante cuando la anatoma del scraper es uno-a-uno.

Web scraping en node.js


Node.js es una eleccin obvia a la hora de implementar un web scraper, pues permite
manipular el DOM en del lado del servidor y es grandioso para el manejo de request y
eventos de I/O asncronos.
Los mdulos de node.js ms tiles para realizar scraping de datos de pginas web y
manipulacin del DOM son los siguientes:

Mdulo url
Mediante el mdulo url se realiza la resolucin y anlisis sintctico de la URL
especfica donde deseamos hacer scraping. Esto nos permite hacer uso de los
2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 12

diferentes segmentos de la URL de manera mas transparente, sin tener que


recurrir a funciones de manipulacin de cadenas de texto. ste, es
particularmente til cuando la URL de un enlace es relativa y debemos resolverla
respecto a la URL base, para poder visitarlos en la siguiente iteracin.
var url = require('url');
link = url.resolve('http://hdmagazine.org', '/conocenos');
console.log(link);

Mdulo http
Este mdulo permite, entre muchas otras funciones, realizar solicitudes a URL
especficas y aadir un listener donde ser entregada la respuesta a la solicitud,
que ejecutar una llamada de retorno cuando se produzca el evento response.
var http = require('http');
var options = { hostname: 'hdmagazine.org' };
var body = '';
http.get(options, function(response) {
response.on('data', function(chunk) {
body += chunk;
});
response.on('end', function(){
console.log(body);
})
});

Mdulo jquery
El mdulo de jquery para node.js requiere instalacin mediante npm (Node
Package Manager), pero permite realizar un anlisis sintctico del DOM de
manera muy fcil. Despus de haber instalado jquery, es posible definir la
variable $, que nos permitir seleccionar elementos del DOM como en jquery.
Complementando el ejemplo anterior:

var $ = require('jquery');
var http = require('http');
var options = { hostname: 'hdmagazine.org' };
var body = '';
http.get(options, function(response) {
response.on('data', function(chunk) {
body += chunk;
}).on('end', function() {
var title = $(body).find('title').text();
console.log(title);
});
});

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 13

Node.io
Entre las numerosas libreras escritas en node.js, que existen para realizar
automatizacin de requerimientos de I/O, est node.io, que permite crear un objeto job
con los siguientes mtodos:

input(): Datos de entrada o semilla a procesar por el job. Por defecto lee el
STDIN interpretando los saltos de lnea con \n o \r. Los datos de entrada tambin
pueden ser: un array, un path_to_file (procesa cada una de las lneas del archivo)
o path_to_dir (procesa cada una de los archivos del directorio), o un stream.

output(): Datos de salida del job. Por defecto se presentan en el STDOUT, pero
tambin puede especificarse la salida a un path_to_file o un stream.

run(): Procesa los datos de entrada y emite el resultado a la salida. En la funcin


de llamada de retorno que se define para este mtodo, es donde encapsulamos
los mtodos de scraping de datos.4

Entre muchos otros mtodos de node.io, se incluyen dos muy importantes para realizar
scraping de datos de pginas web: get() y getHtml(), que permiten hacer extraer los
datos de una URL. Especficamente, la funcin de llamada de retorno de getHtml()
permite tomar el argumento $ (el cual es un objeto similar al $ de jquery) y acceder al
DOM usando selectores para procesar la informacin relevante para nuestro job. Por
ejemplo:
var nodeio = require('node.io');
exports.job = new nodeio.Job({
//Se establece input en false, el job se ejecuta solo 1 vez.
input: false,
run: function () {
this.getHtml('http://hdmagazine.org', function (err, $) {
var links = [];
//Para cada elemento <a> encontrado se obtiene el atributo href
$('a').each(function(data) {
links.push(data.attribs.href);
});
this.emit(links);
});
}
});

A su vez, el mtodo getHtml permite hacer crawling a travs de motores de bsqueda.


Por ejemplo, si deseamos conocer los diferentes subdominios de un sitio web, podemos
utilizar el motor de bsqueda Google en node.io 5:
var nodeio = require('node.io');
//El dominio semilla se ingresa como argumento en CLI
var domain = process.argv[3];
var subs = [''];
//Elementos de la URL de busqueda

4
5

Para conocer el resto de los mtodos, visitar la documentacin de la API https://github.com/chriso/node.io/wiki


Este ejemplo puede ser encontrado en https://github.com/eramirem/node.js/blob/master/domain-crawler.js

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 14

var base_url = 'https://www.google.com';


var base_path = '/m/search?';
var base_query = 'site:' + domain;
//Expresin regular que haga fetch con un dominio/subdominio
var pattern = new RegExp('(\\w+):\\/\\/([\\w-.]+' + domain + ')');
var query = '';
//Mximo nmero de palabras que el motor de bsqueda admite en el query
const max_words = 32;
//Longitud mxima de la URI
const max_uri = 2048;
//Tiempo de espera entre iteraciones de 5 segundos
//Tiempo de espera para la respuesta de 10 segundos
exports.job = new nodeio.Job({ wait: 5, timeout: 10 }, {
//El job se ejecuta indefinidamente hasta que se presente una seal de exit
input: true,
run: function () {
full_query = base_query + query;
//50 resultados por pgina
start_param = '&num=50&start=0';
query_param = 'q=' + full_query;
params = query_param + start_param;
full_url = base_url + base_path + params;
console.log('Query ' + full_url);
if (subs.lenght > max_words) this.exit('Max words limit reached');
if (full_url.length > max_uri) this.exit();
this.getHtml(full_url, function (err, $) {
var new_domain = false;
if($('#resultStats').text == false) this.exit('No results');
//Se obtiene el link del header de cada resultado
$('h3 a').each('href', function(href) {
//Si el link coincide con el patrn de subdominio
if (href.match(pattern))
{
link = href.match(pattern)[2];
//Si el link no se encuentra en el arreglo existente
if(subs.indexOf(link) == -1)
{
new_domain = true;
console.log('New domain found: ' + link);
query += '+-site:' + link;
subs.push(link);
}
}
});
//Si no se encuentran subdominios nuevos en la ltima iteracin
if (new_domain == false) this.exit('No new domains found');
this.emit();
});
}
});

Para ejecutar el script anterior, se utiliza la lnea de comandos, pasando como


argumentos el nombre del script y el dominio a evaluar:
$ node.io domain.js hdmagazine.org

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 15

La salida del script sera la siguiente:


$ node.io test.js hdmagazine.org
Query https://www.google.com/m/search?q=site:hdmagazine.org&num=50&start=0
New domain found: store.hdmagazine.org
New domain found: www.hdmagazine.org
Query https://www.google.com/m/search?q=site:hdmagazine.org+site:store.hdmagazine.org+-site:www.hdmagazine.org&num=50&start=0
ERROR: No results

Bsicamente la utilidad de node.io, radica en la automatizacin de los jobs. Sin embargo,


la lgica del scraping sigue siendo implementada por el usuario.

Conclusin
Los web scrapers son muy tiles para implementar en nuestros scripts mltiples tareas
que realizamos normalmente de manera manual con el navegador, como monitorizacin
de tarifas, tasas de cambio, acciones de bolsa, agregacin de noticias, etc.
Hay que tener las precauciones del caso, como evitar afectar el desempeo del sitio que
se analiza evitando ataques de denegacin de servicio, no deseados. Tambin tener en
cuenta material protegido por copyright. El propsito para el cual la informacin
obtenida mediante un web scraper es usada, debe ser autorizado por el generador de
dicho contenido.

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 16

Cmo empiezo con


JavaScript?

17
JAVASCRIPT

Hackers & Developers Magazine Ao 0, Nmero 3

Te gustara usar JavaScript en el desarrollo de tus


aplicaciones? Conoce cmo puedes empezar con
JavaScript y las ventajas que nos da al momento de
codear.

Escrito por: Milagros Alessandra Infante Montero (Est. Ing. Informtica)


Estudiante de Ingeniera Informtica. Miembro de APESOL
(Asociacin Peruana de Software Libre) y de la comunidad de software
libre Lumenhack. Miembro del equipo de traduccin al espaol de
GNOME. Apasionada por el desarrollo de software, tecnologa y
gadgets. Defensora de tecnologas basadas en software libre y de
cdigo abierto.
Webs:
Blog: www.milale.net
Redes sociales:
Twitter / Identi.ca: @milale

avaScript naci en los aos '90 cuando se empezaba el desarrollo de aplicaciones


web cada vez ms complejas. Para conectarse a Internet, las personas utilizaban
mdems que otorgaban una velocidad de conexin total de 56 Kbps, que no
llegaba a superar los 28.8 Kbps. Por esto, era necesario que existiese un lenguaje que al
rellenar de manera incorrecta un formulario, por ejemplo, no se tuviese que esperar
mucho hasta que el servidor lo procesara y volviera a mostrarlo vaco. De esta forma,
JavaScrip, se ejecutaba -y an se ejecuta- en el navegador del usuario y no en el
servidor, acelerando as todo el proceso.
JavaScript es mejor denominado como ECMAScript (es el lenguaje definido por el
primer estndar ECMA-2626 creado por el comit TC39) ya que es la implementacin de
la empresa Netscape sobre este estndar.

Por qu JavaScript?
JavaScript es muy utilizado en el desarrollo y diseo de sitios web. Los navegadores
directamente interpretan este tipo de cdigo. Muchas veces, se lo confunde con Java
pero son lenguajes diferentes y singulares. JavaScript puede ser aadido en cualquier

http://www.ecma-international.org/publications/standards/Ecma-262.htm

pgina web y ser ejecutado sin la necesidad de otro programa o framework.


Actualmente puede funcionar en correo, chat, buscadores, calculadoras, validadores de
formularios y un extenso etctera. En algn momento perdi popularidad con la
aparicin de Flash pero la recobr cuando naci AJAX. Cuando se firma digitalmente un
script y se solicita al usuario permiso para realizar esas acciones, se superan algunas
limitaciones que el lenguaje presenta, por ejemplo si la ejecucin de un script dura
mucho tiempo quizs por un error, el navegador informa al usuario que demasiados
recursos estn siendo consumidos y da la posibilidad de detener la ejecucin.

Cmo incluyo JavaScript en (X)HTML?


Incluir cdigo JavaScript en (X)HTML es muy flexible. Veremos algunas formas de
hacerlo:
1. JavaScript en el mismo documento XHTML
Colocando las etiquetas <script> y </script> se puede incluir en cualquier parte
del documento.

Se recomienda tener este cdigo en la cabecera del documento dentro de las etiquetas <head> y
</head>

Dentro de esta parte del cdigo se debe aadir el atributo type y segn el
estndar, el valor que debe agregarse es text/javascript. Este mtodo se
emplea en pequeos bloques de cdigo y si se desea cambiar algo, debe hacerse
en todas las partes donde ste se encuentre.
<html>
<head>
<script type="text/javascript">
document.write("Hola lectores de H&D Magazine");
</script>
</head>
<body>
<p>Texto en HTML</p>
</body>
</html>

2. JavaScript en los elementos (X)HTML


Se introducen instrucciones de cdigo dentro de etiquetas (X)HTML,
accionndose los mismos mediante un evento del usuario. Pero no es muy usado
ya que no es una buena prctica de programacin.
<html>
<head>
<meta content="text/html; charset=iso-8859-1" />

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 18

<title>Ejemplo de cdigo JavaScript en el propio documento</title>


</head>
<body>
<p onclick="alert('Probando')">Texto del prrafo.</p>
</body>
</html>

3. JavaScript en un archivo externo


Esta se considerara como la mejor prctica de programacin ya que de esta
manera el cdigo estara limpio, ms manejable al hacer cambios y se reutilizara
al tener un archivo exclusivo para cdigo JavaScript. Se enlazan con la etiqueta
<script> a un documento (X)HTML y no hay lmite de cantidad de archivos
JavaScript a aadir. Se define el atributo src donde se indica la URL del archivo en
JavaScript (archivo con extensin .js) a enlazar.

Se puede enlazar un nico archivo en cada etiqueta <script>, pero en una misma pgina se pueden
incluir tantas etiquetas <script> como se necesiten.

// Archivo ejemplo.js
for (a=1; a<=6; a++){
document.write('<h' + a + '>Cabecera de nivel' + a);
document.write('</h' + a + '>');
}
<!-- documento HTML -->
<html>
<head>
<title>Ejemplo de JavaScript</title>
<script type="text/javascript" src="/js/ejemplo.js"></script>
</head>
<body>
<p>Texto del archivo.</p>
</body>
</html>

Palabras reser vadas para JavaS cript


break, case, catch, continue, default, delete, do, else, finally, for, function,
if, in, instanceof, new, return, switch, this, throw, try, typeof, var, void,
while, with

Ahora veamos, la sintaxis...


Existen muchos aspectos importantes a tomar en cuenta:
2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 19

Distingue entre maysculas y minsculas: si se utilizara indistintamente, el


script no funcionar.

Los espacios en blanco (tabulaciones y nuevas lneas) son ignorados: Para


ordenar el cdigo se puede tabular, crear nuevas lneas para una misma
instruccin, aadir espacios, etc. ya que el intrprete ignorar cualquier espacio
en blanco, esperando el final de la instruccin.

Las instrucciones finalizan en punto y coma: Aunque no sea obligatorio para


todas las sentencias, s lo es para una gran parte de las instrucciones. Utilizar un
punto y coma para finalizar cada instruccin, mantendr el orden y es
considerado una buena prctica de programacin.

No se define tipo de variable: Una variable puede almacenar diferentes tipos al


ejecutar un script ya que es de tipado dinmico.

Uso de comentarios: Se pueden aadir para documentar el cdigo como una


buena prctica ya que al igual que en otros lenguajes, stos no se mostrarn en
pantalla.

//comentarios de una sola lnea


alert("Hola HD Magazine");
/*De esta manera podemos aadir comentarios
de varias lneas cuando se necesite detallar
mucha informacin*/
alert("hola HD Magazine");

Variables
Las variables estn destinadas a almacenar datos. Para declarar una variable, se
antecede a sta, la palabra reservada var. JavaScript tambin permite el uso de
variables sin previa declaracin. Cualquier variable definida en el mbito del
documento, ser interpretada como variable global, pudiendo accederse a ella dentro
de cualquier funcin. Sin embargo, una variable definida dentro de una funcin, no ser
accesible fuera de ella. El smbolo utilizado para la asignacin es =.

Es muy recomendable para evitar futuros errores y como una buena prctica, declarar todas las variables que se
vayan a usar.

El nombre que se le da a la variable es el identificador y se debe tener sumo cuidado en


que el primer carcter no puede ser un nmero y el resto de la palabra puede estar
formado por letras, nmeros y con los smbolos $ y _.

Tipos de datos de las variables


Las variables, en JavaScript pueden ser de diversos tipo:
2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 20

Numricas:
El valor se asigna directamente si es int (entero) o si es float (decimal) donde se coloca
un punto en vez de la coma.
var foo = 90;
var bar = 75.8;

Cadenas de texto:
Se utiliza comillas simples 'texto' o dobles "texto" para delimitar su inicio y fin.
var foo = 'Hola Mundo!';

Booleanas:
Toma valores true o false (verdadero o falso).
var foo = true;

Arrays: Se puede colocar una coleccin de datos que pueden ser o no del mismo tipo:
var meses = ['Enero', 'Marzo', 'Mayo', 'Julio', 'Setiembre', 'Noviembre'];
var datos_persona = ['Juan', 'Prez', 25, 'Per', false];

Para acceder a cada uno de sus elementos, solo se debe indicar la posicin y debemos
recordar que la numeracin empieza en 0 hasta N.
var edad_de_juan = datos_persona[2];
// salida: 25
var casado = datos_persona[4];
// salida: false

Para incrementar una variable se utiliza ++ y para decrementar se utiliza -Si se utiliza como prefijo (delante de la variable) el valor se incrementa antes de la
operacin, pero, si se utiliza como sufijo (despus de la variable) el valor se incrementa
luego de ejecutar la operacin.
var foo = 25;
document.write(foo++);
// salida: 25
document.write(foo);

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 21

// salida: 26
var bar = 25;
document.write(++bar);
// salida: 26

Es importante recordar que mientras aprendes a programar en cualquier lenguaje, un


cheat sheet siempre ser de mucha ayuda al desarrollar 7.

S encillos snippets en JavaS cript, para NO programadores


Cada elemento (etiqueta) de un documento HTML, es tratado como un objeto en
JavaScript. JavaScript puede identificar estos objetos, leer sus propiedades (atributos) y
tambin modificarlos. La forma ms simple de acceder, desde JavaScript a un elemento
del HTML, es a travs de su id. Todo elemento en HTML (tag) puede tener su atributo id.
La id de un elemento debe ser nica y no puede repetirse. Por ejemplo:
<a href="http://www.google.com" id="LinkGoogle">Google</a>
<input type="text" name="nombre_apellido" id="NombreApellido"/>

Desde JavaScript, se acceder a los elementos anteriores, identificndolos como


objetos, mediante su ID:
document.getElementById('idDelElemento');

Por ejemplo:
document.getElementById('LinkGoogle');

Las estructuras de control, se agrupan entre dos llaves y las funciones se definen con la
palabra function. Por ejemplo:
function mi_funcion() {
var a = 10;
var b = 15;
var suma = a + b;
return suma;
}

http://www.addedbytes.com/cheat-sheets/javascript-cheat-sheet/

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 22

Y en JavaScript, las funciones tambin pueden recibir parmetros:


function mi_funcion(a, b) {
var suma = a + b;
return suma;
}

Desde cualquier elemento HTML se puede llamar a una funcin o instruccin JavaScript
(como se coment anteriormente). Para ello, las llamadas se suelen realizar mediante un
evento concreto del usuario. Entre los eventos ms habituales, se pueden encontrar:
onclick
E usuario pulsa el botn izquierdo del ratn sobre el elemento. Es un evento disponible
desde la mayora de los elementos HTML. Por ejemplo:
<p onclick="alert('Esto es un prrafo');">Clic aqu</p>
<!-- en un formulario -->
<input type="radio" name="opcion" value="SI"
onclick="alert('Elegiste la opcin SI');"/>

onkeydown / onkeyup
El usuario pulsa una tecla / el usuario levanta el dedo de una tecla :) Mayormente se
utiliza en campos de formulario. Por ejemplo:
<input type="text" name="edad" onkeyup="alert('escribiste algo');"/>

onchange
En un campo de formulario, por ejemplo un select, se refiere a cuando el usuario,
cambia la opcin seleccionada. Por ejemplo:
<select name="pais" onchange="alert('Cambiaste de opcin');">
<option>Argentina</option>
<option>Espaa</option>
<option>Per</option>
</select>

Un uso frecuente de JavaScript, es por ejemplo, modificar los estilos (CSS) de diversos
elementos, tras un evento determinado. Por ejemplo, la siguiente instruccin, oculta el
elemento cuya id es "parrafo2":
document.getElementById('parrafo2').style.display = 'none';

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 23

Y la siguiente, hace visible el mismo elemento:


document.getElementById('parrafo2').style.display = 'block';

Y esta otra, cambia el color de fuente:


document.getElementById('parrafo2').style.color = '#f60';

Si se coloca esta instruccin en una funcin, luego se la pueda llamar tras cualquier
evento. Por ejemplo:
// archivo .js
function cambiar_color() {
document.getElementById('parrafo2').style.color = '#f60';
}
<!-- documento HTML -->
<p id="p1" onclick="cambiar_color();">Click aqu para cambiar el color del
prrafo 2</p>
<p id="parrafo2">Este prrafo cambiar de color</p>

Podras modificar an ms la funcin anterior y hacer que la ID del elemento se pase por
parmetro. Por ejemplo:
function cambiar_color(id) {
document.getElementById(id).style.color = '#f60';
}

Entonces, usar la misma funcin para cambiar el color de fuente de diversos elementos:
<b id="b1" onclick="cambiar_color('b1');">Pulsar y cambiar mi color</b><br/>
<b id="b2" onclick="cambiar_color('b2');">Pulsar y cambiar mi color</b><br/>
<b id="b3" onclick="cambiar_color('b3');">Pulsar y cambiar mi color</b><br/>

Cuando se desea escribir, con JavaScript, un texto en pantalla, se puede hacer de forma
ms prolija, utilizando las siguientes instrucciones:
function escribir(id) {
var texto = 'Nuevo Texto';
// para la mayora de los navegadores
document.getElementById(id).innerText = texto;

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 24

// para Firefox
document.getElementById(id).contentText = texto;
}

Por ejemplo:
<p id="p1"></p>
<input type="button" value="Escribir" onclick="escribir('p1');"/>

Y si se desea, adems de texto, escribir cdigo HTML, se utiliza innerHTML. Por ejemplo:
// archivo .js
function escribir_html(id) {
var codigo = "<b>Hola Mundo!</b>";
document.getElementById(id).innerHTML = codigo;
}
<!-- documento HTML -->
<div id="layer1"></div>
<input type="button" value="Escribir HTML" onclick="escribir_html('layer1');"/>

En JavaScript se pueden utilizar condicionales if/else. Por ejemplo:


// archivo .js
function mostrar_u_ocultar() {
// si boton1 est checkeado
if(document.getElementById('boton1').checked == true) {
// oculta el campo texto1
document.getElementById('texto1').style.display = 'none';
// muestra el campo texto2
document.getElementById('texto2').style.display = 'block';
// si no est checkeado
} else {
// muestra el campo texto1
document.getElementById('texto1').style.display = 'block';
// oculta el campo texto2
document.getElementById('texto2').style.display = 'none';
}
}
<form>
<input type="radio" name="opcion" id="boton1" value="1"
onclick="mostrar_u_ocultar()"/> 1<br/>
<input type="radio" name="opcion" id="boton2" value="2"
onclick="mostrar_u_ocultar()"/> 2<br/>
Texto 1: <input type="text" name="texto1" id="texto1"/><br/>
Texto 2: <input type="text" name="texto2" id="texto2"/><br/>
</form>

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 25

MANUAL DE DOM

Conociendo a DOM:
Parte I

Para poder desarrollar aplicaciones y sitios web con


HTML5 es importante saber acceder y actualizar el
contenido, la estructura y el estilo de documentos.

Escrito por: Sergio Infante Montero (Ingeniero de Software)


Ingeniero Informtico con estudios de Master de Direccin Estratgica
en TI. Ingeniero de software en Taller Technologies, activista,
contribuidor y consultor de proyectos FLOSS, miembro de APESOL y
escritor de artculos y libros tcnicos de programacin.
Perfiles:
http://about.me/neosergio
Twitter: @neosergio

l Modelo de Objetos del Documento (Document Object Model) o tambin


conocido como DOM (por sus siglas en ingls) es una plataforma mixta y una
interfaz de lenguaje neutral que permite a los scripts y programas acceder al
contenido, estructura y estilo de documentos buscando interactuar con ellos. El
resultado de esta interaccin se incorpora nuevamente en la pgina presentada. En
palabras simples, es una manera de acceder a los objetos en pantalla.

El World Wide Web Consortium (W3C) est a cargo de la especificacin y del esfuerzo de
estandarizacin de DOM8, como es de suponer por obvias razones, el objetivo de W3C
es mantener solo un estndar.
Con el DOM se puede tener control de casi todo elemento de una pgina; crear objetos,
alterar su contenido, cambiar la forma de la pgina y mucho ms. Si se desea tener
mayor referencia tcnica se puede consultar la documentacin del DOM Core9 y del
DOM HTML10.

8
http://www.w3.org/DOM/
9
http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-core.html
10 http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 26

Estructura Jerrquica
La estructura jerrquica del DOM es similar a la de un rbol familiar; entenderla as es
fundamental. De las palabras que forman la sigla, el document, se refiere a la pgina
actual y su contenido. Dentro de la estructura jerrquica, el document representa la
parte superior de la estructura y todo lo dems forma parte de el:

Por ejemplo la etiqueta <html> forma parte del document y la


etiqueta <body> forma parte del <html> -al igual que
<head>-, por lo cual podemos decir que tambin forman
parte del document e imaginarlos como si fuera un rbol
familiar.
Es una jerarqua de objetos que se les conoce como nodos. Hay diversos tipos de nodos
y un nodo puede tener varios de estos:
Tipo de objeto

Interpretacin

parentNode

Nodo tipo padre

childNodes

Lista de nodos hijos

firstChild

Nodo del primer hijo

lastChild

Nodo del ltimo hijo

previousSibling

Nodo hermano anterior al actual

nextSibling

Nodo hermano posterior al actual

Aqu hay un ejemplo que permitir entender mejor:

Para poder usar el grfico anterior como ejemplo vamos a emplear JavaScript y el
mtodo getElementById11.

11 https://developer.mozilla.org/en-US/docs/DOM/document.getElementById

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 27

elemento = document.getElementById(id);

Si an no dominas JavaScript, te recomiendo leer el artculo Cmo comienzo con JavaScript? en la pgina 17
de esta edicin.

Considerar que el id vendra a ser la manera nica de ubicar el elemento dentro del
documento y por esta razn, no deben existir id duplicadas en un mismo documento.

Algunas maneras de acceder a los elementos


Podemos entonces usar esta estructura jerrquica para acceder a los elementos de un
documento.

Usando la imagen anterior podemos tener entonces, algunos ejemplos:


// Para acceder al segundo hijo
segundoHijo = document.getElementById('segundo-hijo');
// Para acceder al padre del segundo hijo
padre = document.getElementById('segundo-hijo').parentNode;
// Para acceder a los hijos del segundo hijo
nietos = document.getElementById('segundo-hijo').childNodes;
// Para acceder al primer hijo a travs del padre
primerHijo = document.getElementById('padre').firstChild;
// Para acceder al tercer hijo (ltimo) a travs del padre
ultimoHijo = document.getElementById('padre').lastChild;
// Para acceder a los hermanos del segundo hijo
hermanoAnterior = document.getElementById('segundo-hijo').previousSibling;
hermanoPosterior = document.getElementById('segundo-hijo').nextSibling;
// Otra manera de acceder a los nietos
primerNieto = document.getElementById('segundo-hijo').childNodes.item(0);

Ahora veamos un ejemplo un poco ms completo y enfocado a HTML. Tenemos la


siguiente estructura HTML:
<!DOCTYPE html>
<html>
<head>
<title>Ejemplo</title>
</head>
<body>

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 28

<nav>
<ul id='lista'>
<li id='elemento1'>
<a id='enlace1'>Primer enlace</a>
</li>
<li id='elemento2'>
<a id='enlace2'>Segundo enlace</a>
</li>
<li id='elemento3'>
<a id='enlace3'>Tercer enlace</a>
</li>
</ul>
</nav>
</body>
</html>

Para acceder a los elementos, ahora vamos a usar un mtodo ms:


getElementsByTagName12 (notar que est en plural, a diferencia del anterior que est en
singular).
// Algunas formas de acceder a la lista
document.getElementById('lista');
document.getElementsByTagName('ul').item(0);
document.getElementsByTagName('li').item(0).parentNode;
document.getElementsByTagName('li').item(1).parentNode;
document.getElementsByTagName('a').item(0).parentNode.parentNode;
// Algunas formas de acceder a la seccin de navegacin
document.getElementById('lista').parentNode;
document.getElementsByTagName('body').item(0).childNodes.item(0);
document.body.childNodes.item(0);

Un mtodo ms que puedes investigar es document.body13

Algunas propiedades, mtodos y atributos de los nodos


Ahora que ya sabemos que podemos acceder a los elementos de varias formas, es
importante aprender que propiedades, mtodos y atributos podemos usar:
nodeName
Nos retorna el nombre de un nodo:
document.getElementById('enlace1').nodeName;

12 https://developer.mozilla.org/en/docs/DOM/document.getElementsByTagName
13 https://developer.mozilla.org/en-US/docs/DOM/document.body

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 29

tagName
Nos retorna el nombre de la etiqueta del elemento:
document.getElementById('enlace1').tagName;

nodeType
Devuelve 1, 2 o 3. Estos nmeros representan los tipos de nodos. Para el nmero 1 es
elemento; 2 es atributo y 3 es texto:
document.getElementById('elemento2').nodeType;

hasChildNodes()
Devuelve verdadero o falso al consultar si el elemento tiene nodos hijos:
document.getElementById('lista').hasChildNodes();

nodeValue
Devuelve el valor del nodo:
document.getElementBy('enlace2').firstChild.nodeValue;

setAttribute(atributo, valor)
Configura un atributo con el valor dado:
document.getElementById('lista').setAttribute('display', 'inline');

getAttribute(atributo)
Recibe el atributo como argumento y devuelve su valor:
document.getElementById('lista').getAttribute('display');

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 30

removeAttribute(atributo)
Remueve el atributo:
document.getElementById('lista').removeAttribute('display');

Es momento de practicar con todos estos elementos y lo visto en este artculo. Un


ejemplo de cdigo para practicar sera el siguiente:
<!DOCTYPE html>
<html>
<head>
<title>Ejemplo</title>
<script type="text/javascript">
function probando(){
variable = document.getElementById('lista').nodeName;
alert(variable);
};
</script>
</head>
<body>
<nav>
<ul id='lista'>
<li id='elemento1'>
<a id='enlace1'>Primer enlace</a>
</li>
<li id='elemento2'>
<a id='enlace2'>Segundo enlace</a>
</li>
<li id='elemento3'>
<a id='enlace3'>Tercer enlace</a>
</li>
</ul>
</nav>
<h1 onClick='probando()'>Clic aqu para probar. S, dale clic aunque
no parezca un enlace</h1>
</body>
</html>

Para probar cdigo se puede usar http://jsfiddle.net, http://jsbin.com o incluso http://dabblet.com/. Puedes
intentar tambin reemplazar alert por console.log y usar la consola de depuracin de javascript, presente en
varios navegadores web.

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 31

32

Manual de MVC: (3)


Los objetos View

MANUAL DE MVC

Hackers & Developers Magazine Ao 0, Nmero 3

En el captulo anterior, vimos como identificar los


diferentes tipos de sustituciones que desde las vistas
de los modelos, en MVC, pueden realizarse. En esta
entrega veremos como crear los objetos View de cada
modelo, los cules implementarn todo lo aprendido
en el captulo anterior.

Escrito por: Eugenia Bahit (Arquitecta GLAMP & Agile Coach)


Eugenia es Arquitecta de Software, docente instructora de tecnologas
GLAMP (GNU/Linux, Apache, MySQL, Python y PHP) y Agile coach (UTN)
especializada en Scrum y eXtreme Programming. Miembro de la Free
Software Foundation e integrante del equipo de Debian Hackers.
Webs:
Cursos de programacin a Distancia: www.cursosdeprogramacionadistancia.com
Web personal: www.eugeniabahit.com
Redes sociales:
Twitter / Identi.ca: @eugeniabahit

n el captulo anterior, estuvimos viendo ejemplos de los diferentes algoritmos que


pueden utilizarse tanto en Python como en PHP, para realizar sustituciones
estticas y dinmicas (render) en los archivos HTML.

Dichos algoritmos, formarn parte de los mtodos de cada una de las vistas, pudiendo
adems, crearse objetos View a nivel del core, para ser reutilizados en las vistas de cada
modelo.

En MVC, cada modelo debe contar con una vista (objeto


ModelView)
En principio, debemos saber que para cada modelo debe haber un objeto vista (objeto
View). Sin embargo, no todos los recursos, debern tener un mtodo en la vista (pero s,
en el controlador del modelo, que veremos ms adelante).
Cuando en MVC se poseen las funcionalidades propias de un ABM, como agregar,
modificar y eliminar un objeto, las vistas, debern tener al menos, dos mtodos: uno
para mostrar el formulario de alta y otro, para mostrar el formulario de edicin. En los

ABM, tambin son frecuentes otros dos mtodos: uno para mostrar el listado de una
coleccin de objetos determinada y otro, para visualizar un objeto puntual. Por
supuesto, la cantidad de mtodos de una vista, depende solo y exclusivamente de los
requerimientos grficos de cada aplicacin. No obstante, el objetivo de esta entrega, es
ver como crear los objetos View. Luego, la cantidad de mtodos a desarrollar,
depender del lector y de los requerimientos de su GUI.
Los mtodos de la vista, sern invocados por el controlador del modelo. ste, ser quien
entregue los datos a la vista, mientras que la ltima, ser la encargada de realizar las
sustituciones pertinentes e imprimir el resultado de las mismas en pantalla.
Bsicamente, la secuencia podra describirse como la siguiente:
1. El usuario solicita un recurso a travs del navegador
2. El FrontController (descrito en la edicin #1), analiza la peticin del usuario e
instancia al controlador correspondiente (veremos controladores ms adelante)
3. El constructor de cada controlador, es quien realiza una llamada de retorno a un
mtodo propio el cual se encargar de:

Instanciar al modelo correspondiente (aunque generalmente, esta


instancia se realiza desde el constructor en la mayora de los casos)

Realizar las modificaciones necesarias sobre el modelo (modificar


propiedades, llamar a los mtodos necesarios, etc.)

Entregar los datos retornados por el modelo a un mtodo de la vista.

4. La vista, traer las plantillas necesarias, para sustituir los datos que le han sido
entregados por el controlador. Finalmente, imprimir en pantalla, el resultado de
dicha sustitucin.

Antes de continuar, si an no lo has hecho, te recomiendo


leer la segunda entrega del manual de MVC14 y practicar
con los ejemplos all descritos, a fin de poder comprender
mejor, todo lo expuesto en este artculo
Cmo bien se coment, debe existir una vista (objeto View) por cada modelo. El nombre
de cada vista, generalmente, ser el nombre del modelo, seguido de la palabra View.
Por ejemplo, dados los modelos: Vidrio, Marco y Ventana, tendremos 3 vistas:
VidrioView, MarcoView y VentanaView:
# en PHP
class VidrioView {
}

14 http://www.hdmagazine.org/?magazine=HackersAndDevelopers&num=2

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 33

# en Python
class VidrioView(object):
pass

Suponiendo que para nuestro modelo Vidrio hayamos definido un recurso agregar (que
deber ser un mtodo del controlador, como veremos ms adelante), en principio,
debemos contar con la GUI para este recurso (aqu no incluiremos an la plantilla
general, sino solo el contenido relativo a este recurso. La plantilla general se incluir al
final de este artculo):
<h3>Agregar un nuevo vidrio</h3>
<form method="POST" action="/mimodulo/vidrio/guardar">
<!-- notar que el nombre de los campos, debe coincidir con el nombre de las
propiedades del objeto, siempre que esto sea posible-->
<label for="grosor">Grosor:</label><br/>
<input type="text" name="grosor" id="grosor" size="3"/> mm<br/><br/>
<label for="sup">Superficie:</label><br/>
<input type="text" name="superficie" id="sup"/><br/><br/>
<label for="color">Color:</label><br/>
<input type="text" name="color" id="color"/><br/><br/>
<input type="submit" value="Guardar"/>
</form>

Como podemos observar, la GUI siempre debe ser el primer paso en el proceso de
desarrollo de las vistas.
En este ejemplo en particular, nos encontramos con que la GUI, no requiere de ninguna
sustitucin (ni esttica ni dinmica). Entonces, lo nico que necesitaremos tener en la
lgica de nuestra vista, es un mtodo que traiga dicha GUI y la muestre en pantalla. Este
mtodo, no necesariamente debe llamarse agregar(). Podra tener un nombre ms
descriptivo como por ejemplo, mostrar_form_alta():
# PHP: Archivo /myapp/modulo/views/vidrio.php
class VidrioView {
function __construct() {
}
function mostrar_form_alta() {
$plantilla = file_get_contents("/ruta/a/agregar_vidrio.html");
print $plantilla;
}
}

# Python: Archivo /myapp/modulo/views/vidrio.py


class VidrioView(object):
def __init__(self):
pass

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 34

def mostrar_form_alta(self):
with open("/ruta/a/agregar_vidrio.html", "r") as archivo:
plantilla = archivo.read()
print plantilla

Cuando el formulario sea enviado, ser solicitado el recurso guardar (ver atributo
action del formulario HTML). Este recurso, ser procesado por el controlador pero
qu haremos finalmente con el usuario? El controlador, podr decidir que sera una
buena idea, mostrarle el objeto creado, al usuario. En ese caso, deber existir un recurso
ver que tambin ser manejado por el controlador (al igual que todos los recursos). El
recurso ver ser un mtodo del controlador. ste, se encargar de recuperar el objeto
Vidrio recin creado y entregrselo a la vista para que haga lo suyo. Entonces qu
debemos tener primero? La GUI, igual que siempre:
<!-- GUI para PHP -->
<h3>Vidrio ID {vidrio_id}</h3>
<b>Grosor:</b> {grosor} mm<br/>
<b>Superficie:</b> {superficie}<br/>
<b>Color:</b> {color}

<!-- GUI para Python -->


<h3>Vidrio ID $vidrio_id</h3>
<b>Grosor:</b> $grosor mm<br/>
<b>Superficie:</b> $superficie<br/>
<b>Color:</b> $color

En este caso, la vista deber contar con un mtodo, que se encargue de realizar una
sustitucin esttica. Para esto, el controlador, le deber pasar un objeto Vidrio como
parmetro. Ampliemos el ejemplo anterior:
# PHP: Archivo /myapp/modulo/views/vidrio.php
class VidrioView {
function __construct() {
}
function mostrar_form_alta() {
$plantilla = file_get_contents("/ruta/a/agregar_vidrio.html");
print $plantilla;
}
function mostrar_objeto($objeto_vidrio) {
# Traigo la plantilla
$plantilla = file_get_contents("/ruta/a/ver_vidrio.html");
# Creo el diccionario
settype($objeto_vidrio, 'array');
foreach($objeto_vidrio as $clave=>$valor) {
$objeto_vidrio["{{$clave}}"] = $valor;

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 35

unset($objeto_vidrio[$clave]);
}
# Realizo la sustitucin
$render = str_replace(array_keys($objeto_vidrio),
array_values($objeto_vidrio), $plantilla);
# Imprimo el resultado en pantalla
print $render;
}
}

# Python: Archivo /myapp/modulo/views/vidrio.py


from string import Template
class VidrioView(object):
def __init__(self):
pass
def mostrar_form_alta(self):
with open("/ruta/a/agregar_vidrio.html", "r") as archivo:
plantilla = archivo.read()
print plantilla
def mostrar_objeto(self, objeto_vidrio):
# Traigo la plantilla
with open("/ruta/a/ver_vidrio.html", "r") as archivo:
plantilla = archivo.read()
# Creo el diccionario
diccionario = vars(objeto_vidrio)
# Realizo la sustitucin
render = Template(plantilla).safe_substitute(diccionario)
# Retorno el resultado
# para que application lo imprima en pantalla
return render

Luego, si el resultado obtenido, se desea imprimir dentro de una plantilla general


(plantilla de base), solo ser cuestin de crear un mtodo show() en una vista a nivel del
core. La plantilla general, deber contar con al menos un parmetro de sustitucin para
el contenido y ser la vista de cada modelo, quien le pase a show() el valor de
sustitucin del mismo para finalmente, imprimir en pantalla el resultado retornado por
show(). Aqu, una vez ms, debemos contar previamente con la GUI:
<!-- PLANTILLA HTML PARA PHP -->
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" type="text/css" href="/static/css/style.css"/>

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 36

<link rel="icon" href="/static/img/favicon.png" type="image/png"/>


<title>{APP_TITLE}</title>
</head>
<body>
<header>
<h1>{APP_TITLE}: {MODULE_TITLE}</h1>
<nav>
<a href="/">{APP_TITLE}</a> &gt;
<a href="/{MODULO}">{MODULE_TITLE}</a> &gt;
<a href="/{MODULO}/{MODELO}">{MODEL_TITLE}</a> &gt;
<b>{RESOURCE_TITLE}</b>
</nav>
</header>
<section>
<!-- aqu ir el contenido sustituido por la vista -->
{CONTENIDO}
</section>
<footer>
&copy; 2013 HDMagazine.org - GPL v3.0
</footer>
</body>
</html>

<!-- PLANTILLA HTML PARA PYTHON -->


<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" type="text/css" href="/static/css/style.css"/>
<link rel="icon" href="/static/img/favicon.png" type="image/png"/>
<title>$APP_TITLE</title>
</head>
<body>
<header>
<h1>$APP_TITLE: $MODULE_TITLE</h1>
<nav>
<a href="/">$APP_TITLE</a> &gt;
<a href="/$MODULO">$MODULE_TITLE</a> &gt;
<a href="/$MODULO/$MODELO">$MODEL_TITLE</a> &gt;
<b>$RESOURCE_TITLE</b>
</nav>
</header>
<section>
<!-- aqu ir el contenido sustituido por la vista -->
$CONTENIDO
</section>
<footer>
&copy; 2013 HDMagazine.org - GPL v3.0
</footer>
</body>
</html>

A nivel del core, se podr tener una vista para la sustitucin de la plantilla general. La
misma, podr realizarse mediante la llamada esttica a un mtodo de clase o a una
funcin (fuera del contexto de una clase). Aqu, lo haremos en el contexto de una clase.
Crear una clase con un mtodo esttico, es una buena alternativa para centralizar
cualquier otro mtodo relacionado con las vistas, directamente disponible desde el
ncleo de la aplicacin.
2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 37

Por favor, notar que en los siguientes ejemplos, la constante


APP_TITLE se supone definida en un archivo settings

# Archivo: /myapp/core/view.php
class CoreView {
public static function show($modulo, $modelo, $recurso, $render) {
$plantilla = file_get_contents("/ruta/a/template.html");
$diccionario = array(
"{APP_TITLE}" => APP_TITLE,
"{MODULE_TITLE}" => ucwords($modulo),
"{MODULO}" => $modulo,
"{MODELO}" => $modelo,
"{MODEL_TITLE}" => ucwords($modelo),
"{RESOURCE_TITLE}" => ucwords("$recurso $modelo"),
"{CONTENIDO}" => $render
);
print str_replace(array_keys($diccionario), array_values($diccionario),
$plantilla);
}
}

# Archivo: /myapp/core/view.py
class CoreView(object):
def __init__(cls):
pass
def show(cls, modulo, modelo, recurso, render) {
with open("/ruta/a/template.html", "r") as archivo:
plantilla = archivo.read()
diccionario = dict(
APP_TITLE=APP_TITLE,
MODULE_TITLE=modulo.title(),
MODULO=modulo,
MODELO=modelo,
MODEL_TITLE=modelo.title(),
RESOURCE_TITLE="%s %s" % (recurso.title(), modelo.title()),
CONTENIDO=render
)
return Template(plantilla).safe_substitute(diccionario)

Luego, solo ser necesario que cada una de las vistas, en vez de imprimir el resultado de
la sustitucin en pantalla, imprima el resultado de la llamada esttica al mtodo show()
de CoreView:
# PHP: Modificacin del archivo /myapp/modulo/views/vidrio.php
function mostrar($objeto_vidrio) {
$plantilla = file_get_contents("/ruta/a/ver_vidrio.html");
settype($objeto_vidrio, 'array');

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 38

foreach($objeto_vidrio as $clave=>$valor) {
$objeto_vidrio["{{$clave}}"] = $valor;
unset($objeto_vidrio[$clave]);
}
$render = str_replace(array_keys($objeto_vidrio),
array_values($objeto_vidrio), $plantilla);
# Se imprime el resultado de la llamada esttica al mtodo show()
print CoreView::show('modulo', 'vidrio', 'ver detalles de', $render);
}

# Python: Modificacin del archivo /myapp/modulo/views/vidrio.py


def mostrar(self, objeto_vidrio):
with open("/ruta/a/ver_vidrio.html", "r") as archivo:
plantilla = archivo.read()
diccionario = vars(objeto_vidrio)
render = Template(plantilla).safe_substitute(diccionario)
# Retorno el resultado de la llamada esttica al mtodo show()
return CoreView().show('modulo', 'vidrio', 'ver detalles de', render)

Siempre digo a mis alumnos, que el arte de las vistas en


MVC, consiste en lograr convertir lo que se tiene, en lo que
se necesita

Generalmente, siempre se tendr un objeto y lo que se necesitar, ser un diccionario formado por pares de
clave-valor, donde los valores, no sean del tipo coleccin (es decir, sean de un tipo de datos simple). Convertir
un objeto en un diccionario, es la base de la lgica de las vistas en MVC .
En la prxima entrega, nos enfocaremos en los controladores de los modelos,
para ir finalizando nuestro Manual de MVC en Python y PHP.

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 39

MANUAL DE NOSQL

Mis primeros pasos


con MongoDB

En la edicin pasada se mencionaron temas


referentes a NoSQL, como fue una breve
introduccin, servicios en la nube, la estructura
interna, entre otros; en este artculo hablar acerca
de MongoDB y como puedes utilizarlo.

Escrito por: Yecely Daz (M.I.A. & Desarrolladora Web)


Yecely es Maestra en Inteligencia Artificial y Desarrolladora Web.
Aficionada de la Tecnologa, Videojuegos y la Web. Ansiosa de aprender,
contribuir y programar todas sus ideas. Ama lo que hace y el cdigo es
su vida.
Webs:
Blog: http://silvercorp.wordpress.com
Redes sociales:
Twitter: @silvercorp

ongoDB es un sistema de base de datos NoSQL orientado a documentos y sin


estructura fija. Esto significa que cada entrada puede tener un esquema de
datos diferente, con atributos que no necesariamente se repiten entre ellos.
Estos datos son guardados en documentos tipo JSON (BSON en MongoDB). Es multiplataforma y adems cuenta con licencia GNU AGPL 3.0, es decir, es Software Libre.
Antes de iniciar la prctica de este artculo es necesario, conozcas las definiciones
siguientes:

Documento. Cada registro o conjunto de datos, es el equivalente a una fila en BD


relacional.

Coleccin. Es donde se agrupan los documentos, lo que conocemos como tablas


en una BD relacional.

Para saber ms sobre la estructura NoSQL y la terminologa empleada, te recomiendo


leer el artculo Estructura interno, cdigo y contexto en la pgina 33, de la edicin
Champagne15 de Hackers & Developers Magazine.

15 http://www.hdmagazine.org/?magazine=HackersAndDevelopers&num=2

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 40

Instalacin de MongoDB en GNU/Linux


En distribuciones basadas en Debian, puede instalarse MongoDB y todas sus
dependencias, mediante apt-get:
apt-get install mongodb

Para iniciar/parar el servicio:


service mongodb start
service mongodb stop

En ArchLinux, se puede instalar mediante pacman:


pacman -S mongodb

Para instalaciones en otras distribuciones como Fedora y/o CentOS, previamente se


deber agregar el repositorio 10gen a YUM, como se indica en el manual oficial:
http://docs.mongodb.org/manual/tutorial/install-mongodb-on-red-hat-centos-orfedora-linux/
Para iniciar/parar el servicio:
service mongod start
service mongod stop

Para ingresar en el Shell interactivo de MongoDB:


mongo

Te desplegar un mensaje similar a:


MongoDB shell version: 2.0.4
connecting to: test
>

Esto nos indicia que ha entrado a la BD denominada test, que MongoDB la tiene por
omisin en su instalacin. Es momento de crear la nuestra, a la cual llamaremos hd.
# Crear o seleccionar la coleccin hd

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 41

> use hd
# Comando para mostrar colecciones
> show collections
# No desplegar nada pues aun no creamos ninguna coleccin

Insertar documentos
Crearemos nuestra primera coleccin que llamaremos editoras y aadiremos
documentos a la misma. Recuerda que la ventaja es que no tienen una estructura fija:
# Insertando documentos
# db.COLECCIN.insert({})
> db.editoras.insert({ nombre:"Yesi", paterno:"Daz", nick:"@silvercorp" })
# Nuevo documento con estructura diferente
> db.editoras.insert({ nombre:"Eugenia", paterno:"Bahit", nick:"@eugeniabahit",
pais:"Argentina" })
# Nuevo documento con estructura diferente
> db.editoras.insert({ nombre:"Celia", nick:"@RTFMCelia", pais:"Argentina" })

Hazlo todo tan simple como sea posible, pero no ms simple


Albert Einstein

Consultas
Tenemos 3 documentos en nuestra coleccin hd. A continuacin te explicar como
realizar consultas:
# Buscar todos los documentos
# db.COLECCIN.find()
> db.editoras.find()

Retornar:
{ "_id" : ObjectId("50fc84bcb6a01eefce9b7925"), "nombre" : "Yesi", "paterno" :
"Daz", "nick" : "@silvercorp" }
{ "_id" : ObjectId("50fc84c6b6a01eefce9b7926"), "nombre" : "Eugenia", "paterno" :
"Bahit", "nick" : "@eugeniabahit", "pais" : "Argentina" }
{ "_id" : ObjectId("50fc84ceb6a01eefce9b7927"), "nombre" : "Celia", "nick" :
"@RTFMCelia", "pais" : "Argentina" }

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 42

Mientras que:
# Mostrar nicamente un documento
# db.COLECCIN.findOne()
> db.editoras.findOne()

Retornar:
{
"_id" : ObjectId("50fc84bcb6a01eefce9b7925"),
"nombre" : "Yesi",
"paterno" : "Daz",
"nick" : "@silvercorp"
}

Bsqueda por campo:


# Desplegar aquellos documentos donde la editora sea de Argentina
# db.COLECCIN.find({campo:Dato})
> db.editoras.find({pais:"Argentina"})
#
#
#
>

Hacer una bsqueda donde las editoras sean de Argentina y nicamente mostrar su
nick
db.COLECCIN.find({campo:Dato}, {campoMostrado:1})
db.editoras.find({pais:"Argentina"}, {nick: 1})

Tambin puedes ordenar tus documentos de acuerdo al campo especificado ya sea


ascendente (1) o descendente (-1):
# Ordenar los resultados de forma ascendente de acuerdo al nombre
# db.COLECCIN.find({campo:Dato}).sort({campoOrdenado: 1})
> db.editoras.find().sort({nombre:1})
# Ordenar los resultados de forma descendente de acuerdo al nombre
# db.COLECCIN.find({campo:Dato}).sort({campoOrdenado: -1})
> db.editoras.find().sort({nombre:-1})

Modificar documentos
Hasta este momento has visto como crear una base de datos en MongoDB, insertar
documentos y hacer bsquedas. Ahora veremos como actualizar campos en tus
documentos:
# Actualizar un documento

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 43

# db.COLECCIN.update({campo:Dato},{$set:{campoModificado:Dato}})
> db.editoras.update({nombre:"Yesi"},{"$set":{pais:"Mexico"}})

Eliminar documentos y colecciones


Por ltimo es necesario conocer como eliminar un documento de nuestra coleccin y
cmo eliminar tambin, la coleccin en s misma:
# Eliminar un documento donde el pas sea Mxico
# db.COLECCIN.remove({campo:Dato})
> db.editoras.remove({pais:"Mexico"})
# Eliminar una coleccin
# db.COLECCIN.drop()
> db.editoras.drop()

Si deseas saber el total de registros de una coleccin usa count() de la siguiente manera
db.COLECCION.count()

Debido a que es un artculo de primeros pasos con MongoDB explicar en otro artculo
ms, operadores para realizar consultas ms complejas y cmo podemos ejecutar scripts
que nos faciliten insertar, modificar, consultar e incluso eliminar datos.

URL PARA REGISTRO: http://bit.ly/payoneer-hd

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 44

Introduccin a Perl
(Parte I)

45
MANUAL DE PERL

Hackers & Developers Magazine Ao 0, Nmero 3

Perl es un gran lenguaje muy utilizado en la


administracin de sistemas. A partir de esta edicin,
damos inicio al Manual de Perl. Cada mes una nueva
entrega, para que puedas inmiscuirte en el mundo de
este maravilloso y legendario lenguaje.

Escrito por: Mara Jos Montes Daz (Archera & Programadora)


Estudiante de Grado Ingeniera en Tecnologa de la informacin. Tcnico
en informtica de gestin. Monitora FPO. Docente de programacin
Python y Scratch para nios de 6-12 aos. Activista del software libre y
cultura libre.
Webs:
Blog: http://archninfa.blogspot.com.es/
Redes sociales:
Twitter: @MMontesDiaz

erl (Practical Extraction and Report Languaje) fue creado por Larry Wall en 1987. Es
un lenguaje de programacin de distribucin gratuita. Su licencia es dual: Artistic
License16 y GPL17 . Toma caractersticas de C, Bourne Shell (sh), AWK, sed y Lisp. Es
multi-paradigma: imperativo, funcional, orientado a objetos y reflexivo y adems, es un
lenguaje interpretado.
Se pens originalmente para la manipulacin de texto. Sin embargo, en la actualidad, se
utiliza en mltiples tareas, sobretodo en administracin de sistemas y hasta hace poco
menos de una dcada (antes de la existencia de PHP), en el Desarrollo de Aplicaciones
Web.
Aunque Perl es un lenguaje interpretado, es muy rpido comparando con otros
lenguajes como Burne Shell. Esto se debe a cmo se ejecuta un programa, que
podramos dividir en:
1. Tiempo de compilacin: Donde se analiza (parsing) el texto del programa en un
rbol sintctico. Este rbol es optimizado simplificando las expresiones
constantes, propagando el contexto y optimizando partes sueltas del cdigo.
2. Tiempo de ejecucin: Se ejecuta el programa siguiendo el rbol generado en la
compilacin.
16 http://www.perlfoundation.org/artistic_license_1_0
17 http://www.gnu.org/licenses/gpl.html

Ejecucin de S cripts en Perl


Disponemos de dos mtodos:
1.- Aadimos al principio del script la lnea:
#!/usr/bin/perl

Con esta sentencia, indicamos al sistema operativo que debe utilizar Perl (el binario
estara en /usr/bin/ ) para ejecutar lo que viene a continuacin. Esta sentencia no es
propia de Perl, si no que es propia de sistemas *nix.

2. Especificando el intrprete desde la lnea de comando:


perl script.pl

El primer parmetro que le pasamos a intrprete es el nombre del script (archivo .pl). Si
le pasamos ms, sern tomados cmo parmetros del script.
El script, para poder ser ejecutado sin necesidad de utilizar el segundo mtodo, debe
tener permisos de ejecucin:
chmod +x script.pl

Algunas opciones del intrprete de Perl:


perl -v

Muestra la versin del intrprete de Perl que estamos utilizando

perl -V

Muestra informacin sobre la configuracin del intrprete de Perl

perl -e expresin

Ejecuta la expresin. Ejemplo:

perl -e "print 'hola mundo\n';"


perl -ne expresin

Ejecuta la expresin a modo de bucle. Por ejemplo: Supongamos que tenemos un


archivo prueba.txt con varios nombres, separados por saltos de lnea. Para extraer
aquellos nombres que empiecen por A, podramos escribir:

perl -ne "print if /A+/;" prueba.txt


perl -pe expresin:

Ejecuta la expresin a modo de bucle, imprimiendo cada lnea.

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 46

Basndonos en el ejemplo anterior, esta sentencia listar el contenido del archivo


prueba.txt, imprimiendo dos veces las lneas que comiencen por A:
perl -pe "print if /A+/;" prueba.txt
perl -d script
Ejecuta el script bajo el depurador.
perl -w script

Da avisos sobre las construcciones con errores.

perl -x script

Empieza a interpretar el archivo que contiene el script cuando encuentra la


referencia al intrprete, por ejemplo: #!/usr/bin/perl.

perl -i archivo

Permite editar archivos. Con la siguiente sentencia, cambiaremos las A por B que
aparezcan en el archivo prueba.txt:

perl -p -i -e "s/A/B/g;" prueba.txt

Nuestro primer programa en Perl.


Los scripts de Perl son una sucesin de instrucciones, delimitadas por punto y coma (;).
Los comentarios se preceden por el smbolo #. A partir de ese smbolo y, hasta el final
de lnea, se ignora el texto.
Para crear nuestro primer hola mundo, creamos un archivo, llamado hola.pl, con el
siguiente contenido:
#!/usr/bin/perl
print "Hola, mundo!";

Le damos permisos de ejecucin:


chmod +x hola.pl

Y ya podemos ejecutarlo:
$./hola.pl

NOTA: En la mayor parte de distribuciones GNU/Linux, la ubicacin del binario de Perl es /usr/bin/. En caso
contrario, se deber especificar la ubicacin correcta.

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 47

Variables
Una caracterstica de Perl, tomada de la programacin Shell, es la marca de las variables
con un sigilo precedente. De esta forma, las variables quedan identificadas
inequvocamente, permitiendo una sintaxis muy rica y adems, permitiendo interpolar
variables dentro de las cadenas de caracteres.

Escalares ($variable)
Las variables escalares son las variables bsicas de Perl. Pueden contener cualquier tipo
de dato: nmeros, letras, cadenas de texto, etc.
La definicin de una variable escalar se hace anteponiendo un $ al nombre:
$variable

El nombre de las variables slo puede contener caracteres alfanumricos. Es sensible a


maysculas y minsculas. Adems, el nombre debe comenzar con letras o _. Despus,
cualquier carcter alfanumrico puede utilizarse.
En la definicin de variables, suele utilizarse la palabra reservada my.

Ejemplos:
my $numero = 223;

O bien, definirla:
my $numero;

Para despus, inicializarla:


$numero = 223;

Otro ejemplo: definimos la variable $cadena1 y $cadena2 con el texto cadena:


my $cadena1 = "texto";
my $cadena2 = $cadena1;

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 48

Arrays (@array)
En Perl, los arrays (matrices) son una lista de datos, que pueden ser nmeros, letras,
cadenas o variables.

Para definirlo, antepondremos al nombre el smbolo @. La lista de valores ir entre


parntesis y, cada valor, separado por comas (,). El ndice de la lista empieza por 0.
my @array;
@array (1,2,3,4,5);

Para acceder a cada elemento, lo haremos utilizando notacin escalar y refirindonos a


cada elemento por su posicin entre []:
my $valor=$array[0];

Podemos obtener, si es necesario, una sublista, con varios elementos:


my @valores=@array[1,3,4];

Dnde, el array @valores ser inicializado con la lista (2,4,5).

Para obtener el ndice del ltimo elemento de la lista, utilizaremos:


1.- Contexto escalar:
$numero = @array;

2.- Sigilo $#
$#array;

Para calcular la cantidad de elementos de una lista, bastar sumar 1 al ndice del ltimo
elemento de la misma:
$numero = @array+1;

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 49

Hashes (%hash)
Este tipo de variable, permite asociar cada elemento de una lista a una llave. Pocos
lenguajes incorporan un tipo similar a ste.
El sigilo utilizado en este caso es el %. Se pueden definir de dos maneras:
my %hash = (u,'uno',d,'dos',t,'tres');

O bien:
my %hash = (
u ==> 'uno',
d ==>'dos',
t ==>'tres',
);

Para llamar al valor de una de nuestras llaves la sintaxis es:


$hash{nombre_llave};

Por ejemplo:
$hash{u};

Igual que hicimos con los arrays, podemos obtener una lista, cambiando el contexto,
mediante sigilos, de la siguiente forma:
@lista=@hash{u,t}

Dnde, @lista, tomar los valores ('uno','tres').

FILEHANDLES
Es un tipo de variables utilizadas para el acceso a archivos.

DIRHANDLES
Igual que el anterior tipo, pero para carpetas.

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 50

51

Introduccin al
desarrollo dirigido por
pruebas

EXTREME PROGRAMMING

Hackers & Developers Magazine Ao 0, Nmero 3

Mucho se ha hablado de una de las doce prcticas


tcnicas ms beneficiosas de la Programacin
eXtrema, pero a excepcin del excelente libro
Diseo gil con TDD18 de Carlos Bl Jurado, muy
poca es la bibliografa que podremos encontrar en
espaol. Y si a esto le sumamos lo complejo que
resulta asimilar el tema, se hace evidente la
necesidad de sumar textos en nuestra lengua, que nos
ayuden a comprender la importancia de esta tcnica y
aprender a implementarla.

Escrito por: Eugenia Bahit (Arquitecta GLAMP & Agile Coach)


Eugenia es Arquitecta de Software, docente instructora de tecnologas
GLAMP (GNU/Linux, Apache, MySQL, Python y PHP) y Agile coach (UTN)
especializada en Scrum y eXtreme Programming. Miembro de la Free
Software Foundation e integrante del equipo de Debian Hackers.
Webs:
Cursos de programacin a Distancia: www.cursosdeprogramacionadistancia.com
Web personal: www.eugeniabahit.com
Redes sociales:
Twitter / Identi.ca: @eugeniabahit

DD (siglas de Test-Driven Development - Desarrollo conducido por pruebas) es una


tcnica de programacin que consiste en guiar el desarrollo de una aplicacin,
por medio de Test Unitarios. Los Test Unitarios (Unit Test, en ingls) no son ms
que algoritmos que emulan lo que la aplicacin se supone debera hacer, convirtindose
as, en un modo simple de probar que lo que piensas programar, realmente funciona.

A la vez, esta tcnica te permitirn saber: qu, cmo, cules y cuntos algoritmos
necesitars desarrollar para que tu aplicacin haga lo que realmente debe hacer y no
falle, ante ciertos casos que no son los que se esperaban.

18 http://www.dirigidoportests.com/el-libro

El objetivo del TDD no es "adivinar", sino probar y actuar,


ya que los Test Unitarios sern una gua para entender como
funciona el cdigo, ayudndote a organizarlo de manera
clara, legible y simple, a la vez de servir como
documentacin

Carlos Bl Jurado en su libro Diseo gil con TDD nos define la tcnica de TDD como:

[...] la respuesta a las grandes preguntas: Cmo lo hago?


Por dnde empiezo? Cmo se qu es lo que hay que
implementar y lo que no? Cmo escribir un cdigo que se
pueda modificar sin romper funcionalidad existente? [...]
Segn Kent Beck -uno de los co-fundadores de la Programacin eXtrema (XP)-,
implementar TDD nos otorga seis grandes ventajas:
1. La calidad del software aumenta disminuyendo prcticamente a cero, la
cantidad de bugs en la aplicacin;
2. Conseguimos cdigo altamente reutilizable puesto que los test nos obligan a
desarrollar algoritmos genricos;
3. El trabajo en equipo se hace ms fcil, une a las personas, ya que al desarrollar
con test, nos aseguramos de no romper funcionalidades existentes de la
aplicacin;
4. Nos permite confiar en nuestros compaeros de equipo aunque tengan menos
experiencia. Esto es, debido a que el hecho de tener que desarrollar test antes de
programar el algoritmo definitivo, nos asegura -independientemente del grado
de conocimiento y experiencia del desarrollador- que el algoritmo, efectivamente
har lo que se supone debe hacer y sin fallos;
5. Escribir el ejemplo (test) antes que el cdigo nos obliga a escribir el mnimo de
funcionalidad necesaria, evitando sobre-disear, puesto que desarrollando lo
mnimamente indispensable, se obtiene un panorama ms certero de lo que la
aplicacin hace y cul y cmo es su comportamiento interno;
6. Los tests son la mejor documentacin tcnica que podemos consultar a la hora
de entender qu misin cumple cada pieza del rompecabezas, ya que cada test,
no es ms que un caso de uso traducido en idioma informtico.

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 52

Caractersticas de los Test Unitarios


Los Test Unitarios (o tcnica de Unit Testing), representan el alma de la programacin
dirigida por pruebas. Son algoritmos independientes que se encargan de verificar -de
manera simple y rpida- el comportamiento de una parte mnima de cdigo, de forma
individual, independiente y sin alterar el funcionamiento de otras partes de la
aplicacin.
Un Test Unitario posee cuatro caractersticas particulares que debe conservar a fin de
considerarse unitario. Estas son:
1. Atmico:
Prueba una parte mnima de cdigo.
Dicho de manera simple, cada test unitario debe probar una -y solo una- accin
realizada por un mtodo.
Por ejemplo, para un mtodo que retorna el neto de un monto bruto ms el IVA
correspondiente, deber haber un test que verifique recibir en forma correcta el
importe bruto, otro que verifique el clculo del IVA sobre un importe bruto y
finalmente, un tercer test unitario que verifique el clculo de un importe bruto
ms su IVA correspondiente.

2. Independiente:
Cada Test Unitario DEBE ser independiente de otro.
Por ejemplo, siguiendo el caso anterior, el test que verifique la suma de un
importe bruto ms su IVA correspondiente, no debe depender del test que
verifica el clculo del IVA.

3. Inocuo:
Podra decirse que cada test unitario debe ser inofensivo para el sistema.
Un test unitario DEBE poder correrse sin alterar ningn elemento del sistema, es
decir, que no debe, por ejemplo, agregar, editar o eliminar registros de una base
de datos.

4. Rpido:
La velocidad de ejecucin de un test unitario cumple un papel fundamental e
ineludible en el desarrollo guiado por pruebas, ya que de la velocidad de
ejecucin de un test, depender de manera proporcional, la velocidad con la que
una funcionalidad se desarrolle.

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 53

Anatoma de un Test
Los Test Unitarios se realizan, en cualquier lenguaje de programacin, mediante
herramientas que proveen un completo entorno de trabajo (Frameworks para Unit
Testing). Estos entornos de trabajo, son desarrollados con un formato determinado,
conocido como xUnit.
De all, que los frameworks para Unit Testing que cumplen con dicho formato, suelen
tener nombres compuestos por una abreviatura del lenguaje de programacin, seguida
del trmino unit. Por ejemplo: PyUnit (Python), PHPUnit (PHP), ShUnit (Shell
Scripting), etc.
Exceptuando el caso de Shell Scripting, los frameworks xUnit de lenguajes que
soportan la orientacin a objetos, utilizan ste paradigma tanto en su anatoma de
desarrollo como para su implementacin (creacin de los test unitarios).
Por lo tanto, los Test Unitarios se agrupan en clases, denominadas Test Case, que
heredan de una clase del framework xUnit, llamada xTestCase:
# Ejemplo con PyUnit
import unittest
class BalanceContableTestCase(unittest.TestCase):
pass
# Ejemplo con PHPUnit
class BalanceContableTest extends PHPUnit_Framework_TestCase {
}

Los mtodos contenidos en una clase Test Case, pueden o no, ser Test Unitarios. Los
Test Unitarios contenidos en una clase Test Case, deben contener el prefijo test_
en el nombre del mtodo a fin de que el framework los identifique como tales:
# Ejemplo con PyUnit
import unittest
class BalanceContableTestCase(unittest.TestCase):
def test_calcular_iva(self):
pass
# Ejemplo con PHPUnit
class BalanceContableTest extends PHPUnit_Framework_TestCase {
public function test_calcular_iva() {
}
}

Otra ventaja que los frameworks xUnit nos proveen, es la facilidad de poder crear dos
mtodos especiales dentro de una clase Test Case -que no son test-, los cuales estn
2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 54

destinados a preparar el escenario necesario para correr los test de esa clase y
eliminar aquello que se desee liberar, una vez que el test finalice. Estos mtodos, son
los denominados setUp() y tearDown() respectivamente:
# Ejemplo con PyUnit
class BalanceContableTestCase(unittest.TestCase):
def setUp(self):
self.importe_bruto = 100
self.alicuota_iva = 21
def tearDown(self):
self.importe_bruto = 0
self.alicuota_iva = 0
def test_calcular_iva():
pass
# Ejemplo con PHPUnit
class BalanceContableTest extends PHPUnit_Framework_TestCase {
public function setUp() {
$this->importe_bruto = 100;
$this->alicuota_iva = 21;
}
public function tearDown() {
$this->importe_bruto = 0;
$this->alicuota_iva = 0;
}
public function test_calcular_iva() {
}
}

Los mtodos setUp() y tearDown() se ejecutan antes y despus de cada test,


respectivamente.
Cada Test estar dividido a la vez, en tres partes identificadas por las siglas AAA las
cules representan a las tres acciones que son necesarias llevar a cabo, para dar forma
a los Tests: Arrange, Act and Assert (preparar, actuar y afirmar).
Preparar consiste en definir y configurar (dentro del test) los recursos necesarios para
poder actuar, es decir, hacer la llamada al cdigo del Sistema cubierto por Test (SUT)
que se desea probar. Esto se conoce como cobertura de cdigo o Code Coverage (o
Coverage a secas).
Finalmente, afirmar el resultado de un test, se refiere a invocar al mtodo assert del
Framework xUnit, que sea necesario para afirmar que el resultado obtenido durante la
actuacin, es el esperado.

Los mtodos assert (mtodos de afirmacin), son mtodos que vienen definidos por
defecto en el framework xUnit, destinados a verificar un resultado. Los nombres de
estos mtodos suelen ser muy similares entre los diversos frameworks, como por
2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 55

ejemplo assertTrue() para verificar que el valor del resultado de la actuacin, devuelto
por el SUT, sea True. Pero los veremos en detalle en la prxima entrega.

Si quieres ir conociendo los mtodos assert, puedes ir visitando las referencias oficiales: PyUnit:
http://docs.python.org/2/library/unittest.html#test-cases y PHPUnit:
http://www.phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.assertions

Por favor, notar que mientras que PyUnit viene incluido como un mdulo estndar de
Python, PHPUnit, requiere de instalacin por separado. En la prxima entrega,
abarcaremos tambin la instalacin de PHPUnit.

Algoritmo para las pruebas unitarias


Existe un algoritmo para escribir Test Unitarios, el cual consiste en:

PRIMER PASO: Escribir el Test y hacer que falle (retornando en el SUT, un valor
contrario al que se espera que devuelva en realidad)

SEGUNDO PASO: Escribir la mnima cantidad de cdigo necesaria (en el SUT)


para que el test pase.

TERCER PASO: Escribir un nuevo test (para el mismo SUT) y esperando que falle
el nuevo test.

CUARTO PASO: Escribir nuevamente, en el SUT, la mnima cantidad de cdigo


necesaria para que ambos test pasen (generalmente, la primera vez, para que el
test pase, se hardcodea -se escribe a mano- el valor de retorno del SUT y, en
esta segunda oportunidad, se escribe el mnimo algoritmo necesario para que el
SUT retorne el mismo valor pero sin estar hardcodeado).
En la siguiente entrega, nos enfocaremos en los Test
Unitarios con PyUnit y PHPUnit.

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 56

IPv6, el presente

57
REDES

Hackers & Developers Magazine Ao 0, Nmero 3

El crecimiento exponencial de Internet, ha hecho que


desde los aos '80, el agotamiento de las direcciones
IPv4 haya sido un tema de preocupacin. El
agotamiento ya ha llegado y nos encontramos en la
era del IPv6.

Escrito por: Laura Mora (Administradora de Redes y Sistemas GNU/Linux)


Laura es administradora de Redes y Sistemas GNU/Linux en Catalua.
Tiene una larga trayectoria en la consultora de soluciones telemticas
opensource para movimientos sociales. La base de sus proyectos es el
empoderamiento tecnolgico de las personas.
Webs:
Blog: http://blackhold.nusepas.com/
Web: http://delanit.net
Redes sociales:
Twitter / Identi.ca: @Blackhold_

l 31 de Enero de 2011, la IANA (Internet Assigned Numbers Authority), entidad


que se encarga de distribuir las IP en Internet, asign los dos ltimos bloques /8
(16 millones de IP) y el 3 de Febrero finalmente se asignaron los ltimos 5 bloques
de direcciones disponibles a los cinco registros de Internet (Regional Internet
Registries o RIR), que tienen delegada la asignacin en las cinco regiones
administrativas en que se divide el mundo segn Internet. Aqu podemos ver19 cuando
los RIR van a agotar definitivamente las Ipv4 disponibles.
En 1999 se prevea que si la red segua creciendo al ritmo que lo haca, el numero de IP
se agotara antes de encontrar una solucin al problema, as que se dise NAT
(Network Address Translation). El concepto de NAT consiste en utilizar una direccin
IP enrutable (o un nmero limitado de direcciones IP) para conectar todas las mquinas
a travs de la traduccin, en la pasarela de Internet, entre la direccin interna (no
enrutable) de la mquina que se desea conectar y la direccin IP de la pasarela.
Adems, el proceso de traduccin de direcciones permite a las compaas asegurar la
red interna siempre y cuando oculte la asignacin de direcciones internas. Para un
observador que se ubica fuera de la red, todos los pedidos parecen provenir de la misma
direccin IP.
NAT ha podido parecer un gran invento, tambin una forma de "tener los ordenadores a
salvo del salvaje Internet". NAT ha sido adoptado como firewall, pero en realidad no lo
es ya que se permite que protocolos como UPNP o conexiones inversas puedan acceder

19 http://www.potaroo.net/tools/ipv4/index.html

a equipos detrs del NAT.


Sin embargo, este sistema no est facilitando la tarea a todas aquellas aplicaciones de
tipo cliente-servidor (que ofrecen servicios dedicados a los usuarios), o permitiendo las
cliente-cliente, tal como podra ser VoIP, Televisin Interactiva, juegos on-line,
programas P2P, etc. Si somos usuarios de estos servicios seguramente alguna vez
habremos tenido que acceder a nuestro router y configurar la redireccin de puertos.
Con IPv6 esta farragosa tarea desaparece! cada ordenador dispone de una IP global y
con esto, es posible rutearlo directamente a Internet, as que desde hace ya unos aos,
los sistemas operativos se toman mucho ms en serio el tema de la seguridad y por un
buen motivo, un sistema o aplicacin que no est preparado para las redes del futuro,
estar condenado a desaparecer!
Adems de esto nos encontramos con la realidad del imparable crecimiento de Internet,
que en los ltimos 10 aos ha experimentado un crecimiento superior al 600%, puesto
que da tras da se unen a esta gran red, nuevos tipos de dispositivos.

IP v6, el protocolo
Este protocolo empez a ser diseado en 1996 por la IETF (Internet Engineering Task
Force)20, organizacin que desarrolla y promueve estndares -sobretodo- acerca de
TCP/IP y protocolos de Internet. Desde entonces IPv6 ha ido evolucionando, pero a
diferencia de otros protocolos se decidi no definir versiones, en motivo del farragoso
proceso de estandarizacin de los RFC que hace que muchos estndares se apliquen en
la red antes de ser estandarizados, como por ejemplo el polmico 802.11n.

Uno de los cambios que saltan mas a la vista es la notacin de las direcciones, que trata
de direcciones de 128bits de longitud escritos en 8 grupos de cuatro dgitos
hexadecimales:
2001:0db8:85a3:08d3:1319:8a2e:0370:7334

Esto es una direccin IPv6 vlida. Usamos el prefijo 2001:0db8: para documentacin.
Si un grupo de cuatro dgitos es nulo (que tiene el valor 0000), puede ser comprimido,
as que estas dos direcciones IPv6 seran en realidad la misma:
2001:0db8:85a3:0000:1319:8a2e:0370:7344
2001:0db8:85a3::1319:8a2e:0370:7344

Siguiendo esta regla, si ms de dos grupos consecutivos son nulos pueden comprimirse
como "::". Si la direccin tiene ms de una serie de grupos nulos consecutivos, la
compresin se puede aplicar en ms de uno, as que:

20 http://www.ietf.org/

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 58

2001:0DB8:0000:0000:0000:0000:1428:57ab
2001:0DB8:0000:0000:0000::1428:57ab
2001:0DB8:0:0:0:0:1428:57ab
2001:0DB8:0::0:1428:57ab
2001:0DB8::1428:57ab

Son todas vlidas y representan lo mismo. Pero:


2001::25de::cade

no es vlida porqu no queda claro cuantos grupos nulos hay en cada lado.

Los ceros iniciales en un grupo pueden ser omitidos. As que:


2001:0DB8:02de::0e13

es lo mismo que:
2001:DB8:2de::e13

Tipos de direcciones IP v6

Multicast (una a muchas): "ff00::/8"

Anycast (una a la ms cercana): para la rplica de DNS (por ejemplo para


hacer peticiones al servidor DNS ms cercano topolgicamente hablando).

Unicast:
Globales : equivaldran a lo que conocemos como IP pblicas en IPv4.
Enlace local (link-local): "fe80::/10". Slo son vlidas a nivel 2. seran como
las 169.254.0.0/16 en IPv4. No son enrutables en la red IPv6. Ms
informacin21.
Locales nicas (ULA): "fc00::/7". Estas tampoco son enrutables en la red
IPv6 y su uso comn es para redes privadas virtuales. Un ejemplo podra
ser el caso de un banco, que tiene sus ordenadores conectados a Internet
con su IP global, pero el programa de gestin del banco slo sera
accesible desde la ULA. Es habitual pues, que un ordenador con IPv6
disponga de varias direcciones IPv6. Ms informacin22.
IPv4 mapeadas: "::ffff:0:0/96" (en desuso)

21 http://es.wikipedia.org/wiki/Direccin_de_Enlace-Local
22 http://en.wikipedia.org/wiki/Unique_local_address

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 59

Compatible IPv4: (desaprobadas)


Local de sitio (site-local): (desaprobadas) "fec0::/10": para definir una red
interna en un edificio o planta.
Loopback: "::1/128" el equivalente a la 127.0.0.1/8

Los rangos de IP
IPv6 est diseado para que cada mquina tenga asignado un rango en lugar de una
nica IP. Solo en casos muy concretos se aconseja que un dispositivo electrnico tenga
una nica IP.
El rango mnimo que se debera asignar a una interfaz de red es un /64 (2^64 IP).
De esta forma puede usarse la MAC address del dispositivo fsico para generar una IP
vlida en esos restantes 64 bits. As, entre otras cosas, se gana privacidad, pues ya no
ser trivial descubrir la IP de una mquina y escanear el rango entero nos podra costar
varios aos.

Los RIR recomiendan a los ISP que entreguen a sus clientes un /48. De esta forma el
cliente puede asignar hasta 2^16 /64 a sus dispositivos domsticos (nevera, telfono,
televisor, enchufe, persiana...)

Asignando un /48 a cada persona del planeta, suponiendo que


estas /48 no se devolviesen, se podra asignar un /48 a cada
persona del planeta durante 480 aos.
Se espera que el protocolo quede obsoleto mucho antes!

Broadcast y ARP
Otro cambio realmente significativo, es que IPv6 no implemente Broadcast y, por lo
tanto, no existe broadcast domain.
En su lugar se ha extendido y mejorado el funcionamiento de Multicast. Para comunicar
los ordenadores directamente conectados (y sin conocer previamente sus IP) se puede
usar la direccin link-local multicast ff02::1.
En IPv6 ARP, ha sido sustituido por un protocolo mucho ms potente: NDP (Neighbor
Discovery Protocol23), que usa ICPMv6 para sus comunicaciones.

23 http://en.wikipedia.org/wiki/Neighbor_Discovery_Protocol

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 60

Una de las consecuencias de estos dos cambios es que, por ejemplo, se pueden
comunicar dos mquinas conectadas sin necesidad de configurar ninguna IP. Las
direcciones link-local (fe80::/10), que se configuran automticamente en nuestro
sistema, nos lo permiten:
ssh usuario@ipv6link-local%eth0

Como se puede apreciar, la interfaz de red debe ser especificada ya que sino, el kernel
no tiene forma de saber hacia donde enviar los paquetes. El ordenador destino ver que
la direccin de destino es su propia IP link-local y aceptar el paquete.

UL A
Tambin funcionara por las ULA, pero no tiene sentido, ya que aunque no sean
enrutables por Internet, s pueden serlo dentro de la red local y en este caso, el gateway
ya nos enrutara a la ubicacin correcta.
Para aadir una ULA:
ip -6 addr add ULA/64 dev INTERFACE

El enrutamiento esttico
El comportamiento de la red en esta versin cambia de forma significativa con la versin
anterior. Por ejemplo, no es usual encontrar configuraciones como la siguiente:
eth0: 192.168.1.1/24
eth1: 192.168.1.10/16

En IPv6, lo habitual es que un mismo rango est incluido en dos dispositivos de red (uno
incluye el otro), el ms pequeo es siempre el que manda. Esta caracterstica fue
exportada a IPv4.
2001:0DB8:1006::/64

es mas pequeo que:

2001:0DB8:1006:1100::/56

SL ACC (Stateless Address Autoconfiguration)


En IPv6 son los mismos hosts quienes se configuran automticamente usando el
protocolo Neighbor Discovery Protocol24 (NDP) mediante mensajes ICMPv625.

24 http://en.wikipedia.org/wiki/Neighbor_Discovery_Protocol
25 http://en.wikipedia.org/wiki/Internet_Control_Message_Protocol_version_6

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 61

En el momento que stos se conectan a la red, envan al router una solicitud de linklocal mediante una peticin multicast (router solicitation) pidiendo los parmetros de
configuracin. Entonces, los routers respondern con un paquete "router advertisment"
que contiene los parmetros de configuracin de la red.

La cabecera de IP v6
IPv6 incrementa la longitud de la cabecera IP de 20 a 40 bytes. La cabecera IPv6
contiene dos direcciones de 16 bytes (fuente y destino) precedidas de 8 bytes de
control. La reduccin de la informacin de control y la eliminacin de opciones de la
cabecera tienen como fin optimizar el procesamiento del paquete. Los campos de uso
poco frecuente se han eliminado de la cabecera y se han pasado a extensiones de
cabecera opcionales.

El campo "cabecera siguiente" o "next header", permite aadir nuevos campos en la


cabecera sin tener que actualizar el software o el hardware de todos los dispositivos de
la red. Y es que IPv6 se ha diseado para poder implementar nuevos cambios de forma
progresiva sin tener que apagar toda la red para aplicarlos. Ms informacin26.

La asignacin de IP
En IPv6 exististe DHCPv6, pero no es la opcin recomendada. Para ello tenemos el
nuevo protocolo SLAAC.
En el router cabecera activamos el RA y, los equipos de la red al conectarse a ella, ven el
anuncio del router y son ellos mismos quienes se aplican la direccin IP a partir de, por
ejemplo, su direccin MAC. En sistemas basados en GNU/Linux siempre se asigna dicha
IP a partir de la MAC, pero en otros sistemas existen las llamadas direcciones de

26 http://en.wikipedia.org/wiki/IPv6_Packet

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 62

privacidad27, donde se genera la IP de forma aleatoria.


Para activar IPv6 privacy en GNU/Linux deberemos activar las "IPv6 Privacy Extensions".
Como root editamos el archivo /etc/sysctl.conf y aadimos estas lneas:
net.ipv6.conf.all.use_tempaddr = 2
net.ipv6.conf.default.use_tempaddr = 2

Reiniciamos la red (o la maquina si se resiste al cambio) y entonces, si disponemos de un


RA en nuestra red, veremos que nos asigna 2 direcciones IPv6: una basada en nuestra
MAC y otra aleatoria. Un ejemplo:
wlan0

Link encap:Ethernet HWaddr 00:21:6a:a5:18:79


inet addr:192.168.1.6 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: 2001:db8:1006:0:221:6aff:fea5:1879/64 Scope:Global
inet6 addr: fe80::221:6aff:fea5:1879/64 Scope:Link
inet6 addr: 2001:db8:1006:0:2c04:41de:e3bc:ffe/64 Scope:Global

De esta forma, las peticiones en una pgina web aparecen como si se hicieran desde la
IP privacy:
Nombre del Ordenador:

2001:db8:1006:0:2c04:41de:e3bc:ffe

Una direccin IP, en el caso que tengamos una ip /64, vendr formada de la siguiente
manera:
los 64 primeros bits vendrn dados por nuestro proveedor
los ltimos 64, se generarn aleatoriamente.

Al igual que en IPv4, podremos usar igualmente DHCP (aunque no sera recomendable)
o bien definir una IPv6 de forma manual.
La recomendacin con IPv6 (y esto es realmente muy importante), seria olvidarse de
recordar un montn de direcciones IP y empezar a usar los DNS (Domain Name
System), que para esto fueron creados! :)
En los DNS, para asignar una direccin IPv4 usamos el Address Record28 A, en IPv6
usaremos AAAA, as que al ejecutar una peticin de resolucin sobre un dominio nos va
a devolver las direcciones IPv4 y IPv6 relacionadas. Si nuestra red tiene salida IPv6, la
direccin IPv6 ser la prioritaria:

27 http://www.ietf.org/rfc/rfc3041.txt
28 http://en.wikipedia.org/wiki/List_of_DNS_record_types

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 63

$ host guifi.net
guifi.net has address 109.69.8.5
guifi.net has IPv6 address 2a00:1508::5

El protocolo de movilidad
En IPv6 se ha desarrollado un conjunto de protocolos y herramientas de movilidad29,
que permiten "saltar" de red a red sin perder en ningn momento la conectividad. Por
ejemplo, gracias a SLAAC, los ltimos 64 bits de nuestra IP son fijos (basados en la MAC).
As que si sabemos el prefijo (los primeros 64 bits) de la nueva red donde nos vamos a
mover, podemos hacerlo sin perder nunca la conexin.
Por ejemplo, estamos en nuestra casa haciendo una llamada telefnica con nuestro
mvil conectado a nuestra wi-fi y de repente salimos a la calle, fuera del alcance de
nuestra wi-fi y pasamos a la red mvil de nuestro operador telefnico. Gracias a este
protocolo podremos realizar dicha llamada telefnica sin ningn corte!

Extensin IPS ec
IPv4 se dise para ser funcional, no seguro. Pero con IPv6 se ha dado un paso adelante
en este aspecto. Es la razn por la que se ha implementado IPSec en este protocolo. El
uso de IPSec no es obligatorio en IPv6, lo que s es realmente obligatorio es que todos
los dispositivos que soporten IPv6 (y esto sera extensivo para las conexiones
end2end30), tambin soporten IPSec, dejando a nuestro libre albedro la decisin de
proteger o no nuestras comunicaciones. Ms informacin31

Trabajando con IP v6
La primera impresin que tenemos con IPv6 es pensar... qu jaleo! se han vuelto locos!
esto es el fin! Pero en realidad migrar una red de IPv4 a IPv6 no es una cosa tan crtica,
adems de que ambos protocolos pueden convivir perfectamente sin ningn tipo de
conflicto! Y es que TCP/IP aunque sea el protocolo ms extendido no es el nico.
Posiblemente si analizamos nuestra red y se ha conectado nuestro vecino con su
icacharro, podremos ver peticiones del protocolo manzanatalk. Vale que
manzanatalk cada vez est ms en desuso, pero es el primer protocolo distinto a
tcp/ip que nos viene a la cabeza. Existen otros como netbios, ipx, etc.

Posiblemente nuestro operador de telecomunicaciones no est haciendo su trabajo y en


tu casa an no dispones de IPv6, pero no desesperes! hay opcin!
Existen los llamados tunnel brokers32, que te permiten realizar tneles 6to4 (sit). Todos
los que he probado requeran IPv4 esttica, pero parece que existe ya, alguno que
29
30
31
32

http://long.ccaba.upc.es/long/050Dissemination_Activities/tomas_demiguel.pdf
http://en.wikipedia.org/wiki/End-to-end_principle
http://www.ipv6.com/articles/security/IPsec.htm
http://en.wikipedia.org/wiki/List_of_IPv6_tunnel_brokers

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 64

tambin permiten IPv4 dinmica.


As que vayamos a ver uno de los mas conocidos: el de hurricane electric, que adems te
ofrece los comandos para hacer un copy-paste en tu consola y disponer al acto de IPv6 :)

Hurricane Electric ( tunnelbroker.net )


Esta pgina requiere registro y tambin IPv4 esttica, pero una vez pasamos estos
trmites podemos crear un tnel 6to4 realmente estable.
Una vez logueados vamos a "Create Regular Tunnel", especificamos nuestra direccin IP
(si no la ha localizado), escogemos uno de los servidores y le damos a "Create Tunnel".
A continuacin, nos aparece una pgina con nuestra configuracin IPv6 y en la pestaa
example configurations escogemos nuestro sistema operativo (el caso ms comn
Linux-net-tools):
ifconfig
ifconfig
ifconfig
ifconfig
route -A

sit0 up
sit0 inet6 tunnel ::216.66.84.46
sit1 up
sit1 inet6 add 2001:470:1f14:18b::2/64
inet6 add ::/0 dev sit1

A partir de aqu ya dispondremos de un tnel IPv6 en nuestra mquina y uno de los


siguientes pasos es probar si estamos ya preparados para el mundo IPv6: http://testipv6.com/

Una vez tengamos IPv6, podemos realizar algunas pruebas. Dichas pruebas estn hechas
desde un servidor de giss.tv (giss.delanit.net), as que a partir de aqu las direcciones
2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 65

IPv6 son reales:


$ host giss.delanit.net
giss.delanit.net is an alias for v-giss.delanit.net.
v-giss.delanit.net has address 109.69.9.56
v-giss.delanit.net has IPv6 address 2a00:1508:1000::6d45:938

Configuracin IP
Este servidor tiene en eth0 la IPv4 (pblica) 108.69.9.56 y la IPv6 (global)
2a00:1508:1000::6d45:938. En eth1 la IPv4 interna de guifi.net. En la interfaz lo nos
fijamos que est la ::1 que equivale a la 127.0.0.1.
# ifconfig
eth0
Link encap:Ethernet HWaddr 00:18:51:e6:d6:47
inet addr:109.69.9.56 Bcast:109.69.9.63 Mask:255.255.255.240
inet6 addr: 2a00:1508:1000::6d45:938/64 Scope:Global
inet6 addr: fe80::218:51ff:fee6:d647/64 Scope:Link
eth1

Link encap:Ethernet HWaddr 00:18:51:16:16:17


inet addr:10.138.15.131 Bcast:10.138.15.159 Mask:255.255.255.224
inet6 addr: fe80::218:51ff:fe16:1617/64 Scope:Link

lo

Link encap:Local Loopback


inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host

# route -6 -n
Kernel IPv6 routing table
Destination
Next Hop
2a00:1508:1000::/64
::
fe80::/64
::
fe80::/64
::
::/0
2a00:1508:1000::6d45:901
::/0
::
::1/128
::
2a00:1508:1000::6d45:938/128
::
fe80::218:51ff:fe16:1617/128
::
fe80::218:51ff:fee6:d647/128
::
ff00::/8
::
ff00::/8
::
::/0
::

Flag
U
U
U
UG
!n
Un
Un
Un
Un
256 0
U
!n

Met Ref Use If


256 0
1 eth0
256 0
0 eth0
256 0
0 eth1
1024 1
312 eth0
-1 1
830 lo
0
1 31179 lo
0
1 21440 lo
0
1
0 lo
0
1
74 lo
0 eth0
256 0
0 eth1
-1 1
830 lo

Al ser un servidor, le hemos definido al igual que la IPv4, una IPv6 esttica:
[/etc/network/interfaces]
auto lo eth0
iface lo inet loopback
iface eth0 inet static
address 109.69.9.56
netmask 255.255.255.240
gateway 109.69.9.49
iface eth0 inet6 static
address 2a00:1508:1000::6d45:938
netmask 64

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 66

up ip r add default via 2a00:1508:1000::6d45:901 dev eth0

Ping
$ ping6 guifi.net
PING guifi.net(2a00-1508--5.ip6.guifi.net) 56 data bytes
64 bytes from v6.guifi.net: icmp_seq=1 ttl=62 time=2.47 ms
64 bytes from 2a00-1508--5.ip6.guifi.net: icmp_seq=2 ttl=62 time=1.96 ms
64 bytes from v6.guifi.net: icmp_seq=3 ttl=62 time=2.08 ms

Traceroute
$ traceroute -6 guifi.net
traceroute to guifi.net (2a00:1508::5), 30 hops max, 80 byte packets
1
2
3

2a00:1508:1000::6d45:901 (2a00:1508:1000::6d45:901) 0.183 ms 0.166 ms 0.280 ms


2a00:1508:ffff:fffb::21 (2a00:1508:ffff:fffb::21) 2.032 ms 2.034 ms 2.029 ms
v6.guifi.net (2a00:1508::5) 2.438 ms 2.430 ms 2.423 ms

Si nos fijamos, estamos usando las tpicas herramientas de red, pero le estamos
aadiendo la opcin -6.

De momento, como no todo el mundo dispone de IPv6 en sus servidores, dependemos


de IPv4 hasta que poco a poco toda la red vaya migrando a IPv6 (algunos proveedores
estiman que el proceso no se completar hasta 2030). Muchos, antes de empezar a
mirar Ipv6, nos imaginamos que este cambio puede ser una cosa tan crtica como el ms
que conocido efecto 200033, en la que nos pensbamos que todo dejara de funcionar.
Pero como todo, es bueno estar preparados antes de que nos pille el tren y lo ms
importante, es informarse de lo que realmente implica este cambio. En mi humilde
opinin a mejor! :)

Presentes y futuros usos de un Internet basado en IP v6


Al igual que cuando se dise IPv4, nadie imaginaba que terminaramos todos con
pequeos dispositivos en nuestros bolsillos con una capacidad computacional de varios
cientos de veces de la de aquellos antiguos ordenadores de los aos '80.
Pero es que en la actualidad somos incapaces de imaginarnos cmo accederemos a
Internet en el futuro inmediato, con qu dispositivos, cuales sern sus usos... etc. Y es
que esta realidad la podemos ver sin tener que ir muchos aos atrs. Quin hubiese
imaginado hace tan slo 5 aos que lo comn sera estar con nuestro telfono mvil
sacando fotos de una cosa que nos gusta en la calle y compartindola en tiempo real
con cientos de amigos/contactos en la red? Las protestas organizadas simultneamente

33 http://es.wikipedia.org/wiki/Problema_del_ao_2000

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 67

a varios puntos del planeta han sido posibles gracias a la evolucin de la tecnologa.
Cuando tenemos a nuestro alcance la posibilidad de asignar una direccin IP a cualquier
dispositivo, nos pueden venir a la cabeza algunos de sus usos en modo de ciencia ficcin.
Algunos de los usos ms novedosos que se le est dando a IPv6 en la actualidad es en el
mbito de la domtica: casas inteligentes en las cuales podemos controlar con
nuestro dispositivo mvil hasta la mas insignificante bombilla. La imaginacin se
desborda cuando tratamos temas como la seguridad o la reduccin de costes
energticos a favor de nuestro bolsillo y del medio ambiente.
Otro de los posibles usos que podra tener es, por ejemplo, para gestionar mucho mejor
nuestra agenda. Cada componente electrnico de nuestro coche podra tener su nica
direccin IP, estar conectado con la base de datos del fabricante y en el momento de
que este fallase, el propio coche contactara con nuestro taller mecnico, pedira la
pieza y el coche se coordinara con nuestra agenda para que, por ejemplo, cuando
tengamos que ir a hacer una visita a un cliente, en lugar de aparcar el coche en el
parqumetro dejarlo en el taller mecnico ms cercano, dnde nos estara esperando el
nuevo recambio.
No tenemos que olvidarnos tampoco de las ventajas que puede aportar IPv6 en el
campo de la medicina, para el seguimiento en tiempo real de enfermos los cuales es
preciso tener un control exhaustivo de su tratamiento, as como monitorizacin remota
de dispositivos de electro-medicina, como los marcapasos, control de la diabetes, etc.
Coches, elementos electrnicos, dispositivos mviles, etc. permanentemente
conectados a Internet gracias a las nuevas tecnologas mviles como LTE y el diseo de
IPv6 de estar permanentemente conectados a cualquier tipo de red sin ningn tipo de
corte... Y es que el futuro ya est aqu; es el presente.
Lecturas recomendadas
http://www.ipv6.es/es-ES/recursos/Paginas/Libros.aspx
http://www.worldipv6launch.org/
http://es.wikipedia.org/wiki/IPv6
http://www.ipv6.com/
Muchas gracias p4u (p4u@dabax.net) por la revisin del
artculo y a xsf (www.xsf-coop.net) por la revisin idiomtica ;)

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 68

Psate a GNU/Linux
con Arch: Gestores de
ventanas y escritorios

69
MANUAL DE ARCH LINUX

Hackers & Developers Magazine Ao 0, Nmero 3

Los usuarios que se inician en GNU/Linux deben tener


claro los conceptos del entorno grfico, para disponer
de las herramientas suficientes a la hora de decidir
qu utilizar.

Escrito por: Mara Jos Montes Daz (Archera & Programadora)


Estudiante de Grado Ingeniera en Tecnologa de la informacin. Tcnico
en informtica de gestin. Monitora FPO. Docente de programacin
Python y Scratch para nios de 6-12 aos. Activista del software libre y
cultura libre.
Webs:
Blog: http://archninfa.blogspot.com.es/
Redes sociales:
Twitter: @MMontesDiaz

na de las caractersticas de los sistemas GNU/Linux, es la posibilidad que nos


brindan para adaptar nuestro sistema a nuestras necesidades y gustos. Para
poder hacer esto, es conveniente aclarar determinados conceptos que, a veces,
por su similitud, pueden hacer que un usuario recin iniciado confunda.
Una vez presentados estos conceptos, veremos dos escritorios desarrollados con la
intencin de aprovechar al mximo los recursos del equipo, sin necesidad de grandes
requerimientos. Con ellos podremos aprovechar equipos antiguos, sin tener que recurrir
a tecnologas obsoletas.

Gestor de ventanas o Window Manager


Es un conjunto de programas, ventanas y funcionalidades que hacen posible que el
usuario pueda interactuar con el sistema de forma grfica y no en modo texto. Antes de
instalar un gestor de ventanas, es necesaria la instalacin previa de un servidor X.
Debemos tener claro que el gestor de ventanas y el servidor X son independientes.
El servidor X nos proporciona la base para poder disponer de interfaz grfica. Acta con
arquitectura cliente-servidor. Es decir, es el servidor grfico, sobre el que vamos a
poder dibujar, mover ventanas, interactuar con el ratn y el teclado.

No es necesario en GNU/LINUX utilizar un servidor X y gestor de ventanas para usar el


sistema. Estamos hablando de temas distintos e independientes entre si. Hay muchos
usuarios que trabajan en modo texto, sin usar ninguna interfaz grfica.
Existen muchos gestores de ventanas, el usuario es el que decide cual quiere utilizar,
pudiendo tener ms de uno instalado.
Podramos distinguir tres tipos:
Stacking: Tambin conocidos cmo flotantes, son los utilizados, por ejemplo, en
sistemas operativos comerciales y los ms extendidos a nivel general. Se basan en
entender la estacin de trabajo cmo un escritorio tradicional, donde las
aplicaciones seran los papeles que hay encima de l y podemos moverlos y
colocarlos a nuestro antojo sobre el escritorio.
Tiling: En este caso, la intencin es la de no superponer las ventanas. Tienden a
utilizar atajos de teclado y evitar, en mayor o menor medida, el uso del ratn. La
gestin de ventanas se realiza en forma de mosaico y se puede configurar
manualmente o utilizar los diseos predefinidos que nos suelen ofrecer.
Dynamic: Permiten alternar de forma dinmica entre los dos diseos: mosaico y
flotante.

Dentro del primer grupo, disponemos, entre otros, de:

WindowMaker: se dise originalmente para el entorno de escritorio GNUstep.


Es muy sencillo y potente, emula el entorno NeXT. Todava sigue siendo utilizado
por usuarios que les gusta su capacidad de personalizacin.

BlackBox: Es un gestor de ventanas construido en C++ y con cdigo


completamente original, aunque la aplicacin de grficos se parece a la de
WindowMaker. Su principal objetivo es aprovechar los recursos del sistema al
mximo.

Fluxbox. Basado en el cdigo de BlackBox 0.61.1, es muy ligero y fcil de


manejar. Dispone de una gran cantidad de opciones de personalizacin, lo que lo
hace muy interesante.

OpenBox: Es un gestor con un extenso soporte de estndares, altamente


configurable. Su apariencia es minimalista. En sus inicios, se bas en BlackBox,
pero fue reescrito completamente. Varios entornos de escritorio lo utilizan cmo
gestor de ventanas, por ejemplo, LXDE o RAZOR-QT.

Compiz: Es un gestor de composicin de ventanas. El hecho de ser de


composicin hace referencia a que permite utilizar 2D y 3D a la hora de dibujar
los elementos grficos, proporcionando una gran cantidad de efectos visuales.
Necesita, adems, de un decorador de ventanas, como, por ejemplo, Emerald. No
puede utilizarse junto a otros gestores, como Openbox, FluxBox o aquellos que
incorporen composicin.

Metacity: Fue el gestor de ventanas utilizado por el proyecto Gnome. Presentaba


una interfaz sencilla y amigable. Actualmente, ha sido sustituido por Mutter,
aunque an est disponible para los equipos que no poseen la potencia suficiente
2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 70

para trabajar con Mutter.

Mutter: Es un gestor de composicin y ventanas para GNOME. Se basa en Clutter


y utiliza OpenGL. Sobre este gestor, se pueden construir diferentes Shell, para
la gestin de las ventanas y el escritorio. El proyecto Gnome desarrolla GnomeShell, que es la interfaz sobre la que interacta el usuario, programada en C y
javascript, altamente configurable, con la posibilidad de utilizacin y creacin de
extensiones, que modifican y adaptan nuestro escritorio a nuestras necesidades.

Xfwm: Es el gestor de ventanas del escritorio XFCE. Tiene su propio gestor de


composicin para ofrecer efectos visuales.

Kwin: El gestor de ventanas estndar del escritorio KDE. Tambin es un gestor de


composicin, similar a Compiz. Ofrece una gran cantidad de aspectos visuales
configurables.

Del segundo grupo, cabe destacar:

Ion3: Ion es un TWM diseado pensando en el teclado de los usuarios. Fue el


primero de este tipo de escritorios. La configuracin de todo el gestor se realiza
mediante el lenguaje de programacin Lua.

Ratpoison: Es simple, no contiene excesos y no posee grandes elementos


grficos. Se configura mediante un archivo de texto. En este gestor, el ratn
carece de sentido.

Stumpwm: El sucesor de Ratpoison. Est escrito en Common Lisp. No hay


decoracin de ventanas, ni botones, ni iconos. Tampoco dispone de bandeja de
sistema.

En el tercer grupo, disponemos, entre otros, de:

Awesome: Es un gestor altamente configurable, mediante Lua. Muy rpido y


extensible. Dispone de bandeja de sistema y barra de informacin. Est
desarrollado en C y Lua. Permite manejar las ventanas sin la necesidad del uso del
ratn.

DWM: Gestor de ventanas dinmico, con diseos aplicables de forma dinmica,


que permiten la optimizacin del entorno. No dispone de archivos para
configuracin. sta se hace modificando el cdigo fuente en C, por lo que es
necesario recompilar cada vez que deseemos modificar algo.

WMII: Este gestor, del mismo autor que DWM, es muy pequeo, rpido y con un
consumo mnimo de recursos. Su interfaz utiliza el sistema de archivos 9P. El
objetivo de este gestor es mantener un cdigo base pequeo y limpio. Su
configuracin, por defecto, es en Bash, aunque tambin puede realizarse en
Ruby.

Xmonad: Este gestor est escrito y se configura con Haskell. Cualquier cambio
que se quiera realizar en la configuracin, debe volver a compilarse.

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 71

Por supuesto, existen muchos ms gestores de ventanas en cada uno de los grupos,
pero la intencin no es mostrar todos los existentes, sino mostrar el amplio abanico de
posibilidades que nos ofrece el hecho de utilizar un sistema GNU/Linux.

Entornos de Escritorio
Nos proporcionan los elementos para una interfaz grfica de usuario, incorporando,
entre otras cosas, iconos, ventanas, barras de herramientas, fondos de pantalla, adems
de aplicaciones y utilidades integradas, cmo gestores de archivos, navegadores web,
etc.
En general, dentro de un escritorio, podramos utilizar aplicaciones o utilidades
pertenecientes a otro escritorio, brindndonos la posibilidad de adaptarlo a nuestros
gustos y necesidades.
En el artculo anterior, tras instalar el sistema base, propuse la instalacin de los dos
grandes escritorios que hay en GNU/Linux: GNOME y KDE. Estos escritorios incluyen una
gran cantidad de herramientas y, adems, visualmente son muy atractivos. Sin embargo,
requieren equipos con una potencia relativamente grande, aunque pueda optimizarse
su consumo mediante la eliminacin de efectos grficos, o la utilizacin de aplicaciones
ms ligeras que las proporcionadas de manera estndar por ellos.

Ahora voy a centrarme en otros escritorios, disponibles en nuestra distribucin, que


estn diseados para ofrecer funcionalidades similares, pero con un costo muy inferior
en recursos.
XFCE.- Este entorno de escritorio se escribi utilizando las herramientas GTK2. Dispone
de aplicaciones cmo administrador de archivos (Thunar), administrador de ventanas
(Xfwm) y paneles, entre otras.
Es ms ligero que Gnome y KDE y su mtodo de configuracin es mediante GUI.
Adems, posee un compositor para permitir transparencias y aceleracin. Trabaja bien
con mltiples monitores.
El objetivo de este escritorio es ser rpido y con un consumo mnimo de recursos, sin
dejar de lado el atractivo visual y la facilidad de uso.

Para instalarlo, disponemos de dos grupos de paquetes:

xfce4: Incluye el escritorio, panel, sesin, herramientas de configuracin,


terminal, gestor de archivos y gestor de ventanas, entre otras cosas.

xfce4-goodies: Aqu estarn los plugins para el panel, notificaciones y otras


herramientas de sistema.

La instalacin la realizaremos de la siguiente manera:


2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 72

sudo pacman -Sy xfce4 xfce4-goodies gamin gvfs gvfs-afc udisks polkit-gnome

La configuracin de Xfce puede realizarse de dos maneras:

1.- Mediante las opciones del Men, de forma grfica.


2.- Mediante una interfaz en lnea de comandos, xfconf-query. Con esta herramienta,
tenemos acceso a toda la configuracin y permite realizar cambios en tiempo real.
Veamos el uso de esta herramienta:
Cada elemento se le llama canal. Dentro de cada canal, disponemos de diferentes
propiedades.

xfconf-query [opciones...]

Las opciones disponibles:


-h (help)

.- Mostrar opciones de ayuda.

-V (version)

.- Muestra la versin.

-c (channel)

.- El canal a consultar o modificar.

-p (property)

.- La propiedad a consultar o modificar.

-s (set)

.- Establece un nuevo valor a la propiedad.

-l (list)

.- Listar las propiedades (o canales, si -c no se


especifica).

-v (verbose)

.- Salida detallada.

-n (create)

.- Crear una nueva propiedad, si sta no existe.

-t (type)

.- Especificar el tipo de

-r (reset)

.- Restablecer propiedad .

-R (recursive)

.- Recursivo (usar con -r)

valor de la propiedad.

-a (force-array).- Forzar como vector incluso si slo hay un elemento.


-T (toggle)

.- Invertir una propiedad booleana existente

-m (monitor)

.- Monitorizar un canal.

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 73

Algunos ejemplos:
Para listar todos los canales disponibles:
xfconf-query -l

Para listar las propiedades del canal xfce4-panel:


xfconf-query -c xfce4 -l

Para listar las propiedades del canal xfce4-panel y sus sus valores:
xfconf-query -c xfce4-panel -l -v

Para activar la composicin:


xfconf-query -c xfwm4 -p /general/use_compositing -s true

O para invertir el valor:


xfconf-query -c xfwm4 -p /general/use_compositing -T

En principio, los requisitos mnimos para este escritorio son:

Procesador: 300Mhz.

Memoria: 128 MB.

Disco Duro: 90 MB.

LXDE.- Es el acrnimo en ingls de "Lightweight X11 Desktop Environment" (entorno


de escritorio ligero para X11) y, adems, LX puede referirse a LinuX.
Los componentes de este escritorio tienen escasas dependencias entre ellos, por lo que
pueden utilizarse individualmente. Son independientes.
El proyecto LXDE intenta ofrecer un nuevo entorno de escritorio que sea
suficientemente til, manteniendo a la vez un uso reducido de recursos. La usabilidad, la
rapidez y la utilizacin de memoria son las prioridades de los desarrolladores.

Esta compuesto por:

PCManFM: Gestor de ficheros, proporciona adems los iconos del escritorio


2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 74

LXPanel: Panel de escritorio.

LXSession: Gestor de sesiones ajustado a los estndares con funciones de


apagado, reiniciado y suspensin.

LXAppearance: LXAppearance es un seleccionador de temas GTK+ muy


completo, capaz de cambiar temas GTK+, temas de iconos e incluso las fuentes
tipogrficas usadas por las aplicaciones

Lxappearance-obconf: Es un plugin para Lxappereance que permite configurar


OpenBox.

Gestor de ventanas: Openbox, icewm, fluxbox, metacity, etc. Por defecto, LXDE
utiliza Openbox.

GPicView: Un visualizador de imgenes sencillo, rpido y ligero que arranca al


instante.

Leafpad: Editor de texto ligero y sencillo: No forma parte del proyecto LXDE,
pero se recomienda su uso.

XArchiver: Programa archivador ligero, rpido, basado en gtk+ e independiente


del escritorio. Igual que ocurre con Leafpad, no forma parte del proyecto, pero es
el editor que se recomienda.

LXNM : Gestor de red ligero para LXDE con capacidad de conexin sin hilos (slo
para Linux). Su desarrollo est parado, por lo que es aconsejable utilizar otro
gestor de red.

Lxtask: Un gestor de tareas ligero.

Menu-cache: Un demonio (daemon) encargado de generar el men de


aplicaciones.

La instalacin la realizaremos de la siguiente manera:


# pacman -Sy lxde leafpad obconf epdfview polkit-gnome gvfs gvfs-afc upower

Para tener acceso a la papelera en el administrador de archivos:


mkdir -p ~/.config/autostart
cp /etc/xdg/autostart/polkit-gnome-authentication-agent-1.desktop
~/.config/autostart

Ahora, editamos el archivo


~/.config/autostart/polkit-gnome-authentication-agent-1.desktop
y aadimos LXDE a la siguiente lnea:
2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 75

OnlyShowIn=GNOME;XFCE;LXDE;

Para reemplazar el gestor de ventanas openbox por otro, por ejemplo, compiz,
editamos el archivo /etc/xdg/lxsession/LXDE/destktop.conf y modificamos la opcin
window_manager:
[Session]
window_manager=compiz ccp --indirect-rendering

Los requisitos mnimos para LXDE son:

Procesador: Pentium II 266 Mhz

Memoria: Aunque, una vez arrancado LXDE, el uso total de memoria es de 45 MB,
es aconsejable disponer de, al menos, 128 MB

Disco: 60 MB

Iniciando sesin
Para iniciar sesin, por defecto Arch arranca en modo multiusuario, que es en modo
texto. Podemos utilizar gestores de login grfico para el inicio de sesin. Primero
debemos activar el arranque en modo grfico. Lo haremos as:
sudo rm /etc/systemd/system/default.target
sudo systemctl enable graphical.target

Desde el modo multiusuario tambin es posible, por supuesto, lanzar nuestro escritorio
preferido.

Disponemos de varios gestores de login grficos. Veamos los ms usuales:


GDM.- Es un gestor de login perteneciente al proyecto Gnome. Para instalarlo:
sudo pacman -S gdm

KDM.- Es el gestor de login del proyecto KDE. Lo instalaremos as:


sudo pacman -S

kdebase-workspace

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 76

SLiM.- Acrnimo de Simple Login Manager. Es un gestor de login muy liviano. Su


configuracin para la eleccin de sesin se realiza mediante la edicin del archivo
~/.xinitrc.
sudo pacman -S slim

Si optamos por KDM y pretendemos lanzar LXDE, deberemos crear una entrada para
que KDM lo reconozca y nos permita seleccionarlo:
sudo cp /usr/share/xsessions/LXDE.desktop /usr/share/apps/kdm/sessions/

Tanto para la utilizacin de SLiM, cmo para iniciar sesin en un escritorio desde
consola, debemos crear el archivo de configuracin ~/.xinitrc:
cp /etc/skel/.xinitrc ~
chmod +x ~/.xinitrc

Ahora, al final del archivo, aadimos, segn sea el escritorio que decidamos instalar, uno
de los siguientes comandos:
exec
exec
exec
exec

gnome-session
startkde
startlxde
startxfce4

Adems, si pretendemos lanzar con SLiM el escritorio Gnome o vamos a utilizar


herramientas de este escritorio, habr que editar el archivo /etc/pam.d/slim y aadir:
auth
session

optional
optional

pam_gnome_keyring.so
pam_gnome_keyring.so

auto_start

En el archivo /etc/pam.d/passwd tambin debemos aadir:


password
auth

optional
optional

pam_gnome_keyring.so
pam_gnome_keyring.so

Ahora, ya tenemos nuestro gestor de login instalado. Adems, tenemos habilitado el


arranque en modo grfico. Slo falta habilitar el gestor correspondiente. Debemos
tener en cuenta que slo podemos iniciar un gestor a la vez.
Habilitar en el inicio un gestor:
2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 77

sudo systemctl enable gdm|kdm|slim

Para deshabilitarlo:
sudo systemctl disable gdm|kdm|slim

En el caso de no querer utilizar login grfico, desde la terminal, slo debemos ejecutar
startx y se lanzar el escritorio que hayamos especificado en el ~/.xinitrc.

No slo es posible iniciar sesin grfica con un escritorio completo. Tambin sera
posible hacerlo con, nicamente, un gestor de ventanas, por ejemplo. Adems, podemos
tener los gestores y escritorios que deseemos instalados a la vez, e ir utilizando el que
nos convenga en cada momento.

Enlaces de inters:
http://lxde.org/
http://www.xfce.org/
http://slim.berlios.de/
https://wiki.archlinux.org/index.php/Window_manager
https://wiki.archlinux.org/index.php/Desktop_Environment

MARA JOS MONTES DAZ TE INVITA A PARTICIPAR DEL PROYECTO E-CIDADANIA. Pulsa sobre la imagen para informarte o visita
los enlaces que figuran a continuacin.

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 78

Invitacin al proyecto
GcalcTool: GNOME
Calculator

79
HERRAMIENTAS LIBRES

Hackers & Developers Magazine Ao 0, Nmero 3

GNOME no solo brinda un entorno de escritorio


genial: tambin cuenta con muchas aplicaciones muy
tiles para usuarios y programadores, las cuales
muchas personas ni imaginan las funcionalidades con
las que cuentan. Por ejemplo Calculator, una simple
pero poderosa herramienta.

Escrito por: Milagros Alessandra Infante Montero (Est. Ing. Informtica)


Estudiante de Ingeniera Informtica. Miembro de APESOL (Asociacin
Peruana de Software Libre) y de la comunidad de software libre
Lumenhack. Miembro del equipo de traduccin al espaol de GNOME.
Apasionada por el desarrollo de software, tecnologa y gadgets.
Defensora de tecnologas basadas en software libre y de cdigo abierto.
Webs:
Blog: www.milale.net
Redes sociales:
Twitter / Identi.ca: @milale

alculator34 es una aplicacin de GNOME que provee clculos matemticos de nivel


simple y medio, con eficiencia y es conveniente como una aplicacin
predeterminada en un entorno de escritorio.

La calculadora ya viene de manera predeterminada con el entorno de escritorio de


GNOME pero tambin puede ser usada en otras distribuciones, ya que la herramienta
provee ms funcionalidades que las que parece ofrecer por defecto.
Para la instalacin en cualquier distribucin que soporte apt-get, solo se hace uso del
siguiente comando:
sudo apt-get install gcalctool

34 https://live.gnome.org/Calculator

Caractersticas

Es una herramienta para clculos de ecuaciones matemticas.

Usa notacin matemtica estndar donde sea posible (los usuarios no tienen que
aprender la aplicacin al ya saber matemtica).

Es lo suficientemente simple para matemtica bsica (sumar, restar, dividir,


multiplicar).

Es lo suficientemente poderosa para matemtica de nivel medio.

Fcil de cargar y de responder a las entradas.

Tiene el tamao apropiado para encajar en resoluciones de pantalla estndares


(por ejemplo, Netbooks).

Totalmente accesible.

Bien documentado.

Pero tambin es importante saber las caractersticas con las que no cuenta:

No emula ninguna interfaz de calculadora existente, ni hardware, ni software.

No es una herramienta poderosa para matemticos profesionales (los


profesionales deben usar una aplicacin especial).

No es un lenguaje de programacin.

Interfaz de la calculadora de GNOME GcalcTool


La interfaz simple con la que cuenta a primera vista, se cambia de acuerdo al modo en el
que lo ests usando.

Barra de mens:
Est ubicada en la parte superior. Aqu se encuentran todas las acciones y
opciones disponibles para el GcalcTool.

Barra de visualizacin:
Los resultados calculados se muestran en esta barra y los nmeros tambin se
muestran al escribir o pulsarlos.

rea de modo:
Es donde todos los botones estn mostrados, los botones disponibles cambiarn
de acuerdo al modo elegido.

Barra de estado:
Se mostrar el estado de sus clculos.
2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 80

Ecuaciones de la calculadora de GNOME GcalcTool


GcalcTool es capaz de trabajar con muchos tipos de ecuaciones, las ms comunes son:.

Aritmtica bsica

Trigonometra

Potencia

Raz cuadrada

La matemtica parece dotar a uno, de un nuevo sentido.


Charles Darwin
Tamao de la palabra
Un detalle importante a tomar en cuenta est dentro de las Preferencias de Calculator.
Nosotros podemos elegir el tamao de la palabra (la cadena finita de bits) ya que al
momento de disear una arquitectura de computadores, este dato es fundamental.
Calculator soporta palabras de 8 a 64 bits.

Modos de la calculadora de GNOME GcalcTool


Los modos ofrecidos por esta herramienta se dan si se necesita de funcionalidades
extras.

Modo bsico:
Este es el modo predeterminado que provee las funcionalidades simples y
clculos bsicos.

Modo avanzado:
Revela naturalmente todas las funcionalidades avanzadas.

Modo financiero:
Este modo lo ayudar con sus clculos financieros. Ideal para testear clculos
financieros y asegurarse de ser los correctos, antes de codearlos.

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 81

Modo cientfico:
Los usuarios pueden probar este modo para clculos trigonomtricos.

Modo programador:
Este modo provee funcionalidades adicionales que los programadores pueden
encontrar tiles y es en este modo, en el cul nos enfocaremos.

Modo programador de GcalcTool


Como se menciona en la seccin de arriba sobre los modos de Calculator, existe un
modo programador poco conocido pero el cual proporciona ecuaciones tiles como
funciones bit a bit y un editor de los mismos.

Veamos algunos ejemplos:

Algebra Booleana:
Calculator soporta las funciones AND, OR, XOR, NOT.
110010 XOR 100011 nos dar como resultado 10001

La funcin NOT invierte los bits en un nmero. Con NOT 110100 obtendremos
001011

Cdigos de caracteres:
El botn convierte caracteres en cdigos de caracteres. Por ejemplo el smbolo
~ en hexadecimal equivale a 7E
2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 82

Como colaborar con Calculator?


Los errores y requerimientos de caractersticas deben ser presentadas en el Sistema de
Seguimiento de Errores de GNOME35, rellenando la informacin del error que hallaste 36.
Y si quieres ser parte del proyecto e involucrarte en l para su mejora, puedes inscribirte
en la lista de correo37. Al leer un poco en la Ayuda de GcalcTool podremos verificar
algunas funcionalidades con las que an no cuenta, como el soporte a nmeros
complejos o el soporte a funciones definidas por el usuario. No dudes en participar de
la lista de correos y quizs llegar a involucrarte en darle un improve a Calculator.

35 https://bugzilla.gnome.org/
36 https://bugzilla.gnome.org/enter_bug.cgi?product=gcalctool
37 https://mail.gnome.org/mailman/listinfo/gcalctool-list

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 83

Ubuntu Rookie: Toma 3

USABILIDAD

Por Eliana Caraballo (@elianaca)


Ingeniera de desarrollo senior y miembro activo de AVANET. Apasionada por todo lo
relacionado con la ingeniera de software y los procesos de calidad para desarrollo.
Siempre abierta a aprender y a compartir lo que los aos de desarrollo me han enseado.
http://co.linkedin.com/in/elianacaraballoa

a historia comenz con un: No eres


t Ubuntu, soy yo quien de verdad no
te entiende y tres intentos despus,
por fin pude adaptarme a este sistema
operativo. Esta es mi historia...
Estaba en los ltimos semestres de la
universidad cuando escuch sobre un sistema
operativo que poda correr desde un CD y no
haba necesidad de instalarlo. Por esos das
necesitaba recuperar cierta informacin de mi
equipo que ya estaba listo para ser formateado
porque el SO que tena no quera arrancar -ni
siquiera en modo a prueba de fallos- as que
decid probar cmo funcionaba mientras
realizaba el backup de mi informacin. Pero
cuando lleg el momento de configurar la red
wi-fi me di cuenta que no era tan sencillo como
estaba acostumbrada, as que prefer aplazar la
prueba para despus.

Mi segundo intento con Ubuntu vino unos 3


aos despus, cuando escuch a un amigo
hablar acerca de compiz y que haban mejorado
su interfaz grfica. As que de nuevo lo
descargu y descubr con real agrado que la
configuracin de la red inalmbrica era
muchsimo ms sencilla y que visualmente era
todo ms atractivo. En esa oportunidad, el
intento fall porque estaba realizando algunos
trabajos por mi cuenta y el software que usaba
no era compatible con el sistema operativo, ni
siquiera usando Wine y el manejo de la
mquina virtual se me hizo complicado para los
propsitos que tena en ese momento.

Comentando mi problema con algunos colegas,


se generaron discusiones sobre las diferencias
y ventajas entre X e Y sistemas operativos.
LLegamos a la conclusin de que Ubuntu era
tan tcnico, que se haca demasiado
complicado para un usuario no tcnico o con
pocos conocimientos al respecto. Por lo menos
a mis ojos se hizo patente la necesidad de
generar programas amigables porque al final,
no
vamos
a
ser
nosotros
quienes
interactuaremos con el software que
realizamos en nuestro da a da, sino que
siempre hay que pensar en el usuario final que
tendr que lidiar con nuestro sistema.

Si no nos esforzamos para que su


configuracin y manejo sean amigables, muy
probablemente nuestro cliente se sentir
frustrado y preferir buscar otra alternativa
donde se sienta ms cmodo.

He descubierto que la mayora de los


programadores, hacemos todo tan obvio a
nuestros ojos de ingenieros de sistemas que
nos olvidamos del perfil de las personas que
realmente van a usar el software y podemos
complicar su usabilidad.

La amigabilidad comenz como un hito en 1998


al comenzar a aproximar al usuario con el
software a travs de tareas sencillas como la
configuracin,
restauracin
y
dems
necesidades que tuviera frente a su
informacin. Se tena una interfaz grfica que
interactuaba con el usuario con la intencin de
facilitar la satisfaccin de sus necesidades y una

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 84

serie de procesos independientes automticos,


encargados de las tareas que no necesitaban
ser monitorizadas.

A partir de ese momento, casi todo el software


que se produce usa este mismo modelo donde
el usuario simplemente interacta con
pantallas que le permiten alimentar un sistema
que tiene la capacidad de realizar las tareas que
necesita.

La amigabilidad de un sistema permite que


se vuelva intuitivo para el usuario final y que
su facilidad de uso aumente la satisfaccin
de nuestro cliente, quien es al final para el
que estamos trabajando.

Poco o nada importa en qu lenguaje haya sido


escrito; lo que importa es que para ellos, no se
vuelva una tortura de parches, comandos y
truquios para que funcione como se supone
debera funcionar. La parte pesada debe
estar siempre en la complejidad de las reglas
de negocio y nuestra interfaz, lo ms intuitiva,
sencilla y amigable posible.

Tal parece que Ubuntu se dio cuenta y tom


nota de estas cosas, porque la versin que
actualmente tengo instalada ha sido
bastante interesante: Hay una tienda donde el
software se descarga solo y facilita el trabajo y
a su vez sirve de manejador, si hay que
descargarlo desde la web; la suite de
LibreOffice con la que viene instalada es
fabulosa y tiene bastantes utilidades; la
configuracin del sistema es sencilla e intuitiva.

Podrs pensar que soy toda una Rookie


emocionada con mis nuevos descubrimientos,
pero para ser el tercer intento con el sistema
operativo instalado en mi PC, debo reconocer
que ha mejorado muchsimo, pues se hizo
mucho ms sencillo manejarlo y es mucho ms
amigable con usuarios que no son tcnicos en
computacin. Todava hay cosas por mejorar en
cuanto
a compatibilidad
con
algunos
programas, pero en conjunto, ha sido una
experiencia muchsimo ms agradable y varios
meses despus, todava no he sentido las ganas
de volver a mi antiguo sistema operativo.

En mi opinin, fue esa falta de amigabilidad en


Ubuntu en los dos primeros intentos, lo que
hizo que no me enamorara del todo del sistema
operativo, porque al pensar en todos los que en
ese momento usbamos el PC en la casa,
comprend que no iba a ser fcil que se
adaptaran al cambio.

Recuerda: no eres torpe, no importa


lo que digan esos libros. Los torpes de
verdad son gente que, creyndose
expertos tcnicos, no podran disear
hardware y software manejable por
usuarios normales, aunque la vida les
fuera en ello. Walter Mossberg
Columnista de The Wall Street Journal

2013 HDMagazine.org Creative Commons Atribucin NoComercial CompartirIgual 3.0 Unported

Pg. 85

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#######@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###@#########@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####@##++###@######@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#########++'++############@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##++''#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###################+;++##############@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+;;,,:;+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@##@##+##++++++;+#++++'+++################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#:,,,,,,'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+'###'++'';;;;;;:+#+++++++###################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@;,,,,,,,'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+,:++;'++;+:;;;'''+#+''+++########################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#:..,,,,;+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+.:;'::''':;':;+++++++++############################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+,,,,,::;+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@+,;,:::'+'';';+#+++++++###############################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@;.,,,,,:;+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###;;'::''+++'++;###++++#+#################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#:,,,,:::'+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@##':''';+++#++++'###'+'+#######################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@',,,:::;:'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####+'',:;;''+++##+#++##'''+#########################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@;,,::::;:'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##@#+#;;:.:''++++##++#+##+++'############################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#:,,::;;;;'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###'+#:;;:;''++++##+#+##'#+++#############################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#,,::;;;;;+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'++#:#+:;;';'+++##++##+##'++++###############################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+::::::;;;+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#'+#+:'',;;+'+++####+##'+#++++#################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'::::::;''+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##'#++:';,:;++++#######+++++++###################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#;,:::;;;;'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##+++++';':;+++++#######+++##+#####################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#:,::;;;;''@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@#+'+++':''++#+++######+####+########################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+,,::;;;;'+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###@+''+;:;'+++##++#####+#++############################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+,,::;;';;'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###+#+::;'+++#############################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#',,::;;;;;'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+####';:;'++##############################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#;,,::::;;;'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#'###'''''++#################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#;,::::::;;'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+#+#::;'++#''+###############################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#:.,,:::::;'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+:::'+++##'+################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+:,::::::;;'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+;,;;++####+##################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+,::::::::;'##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@@:::;'+###############+#########################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#':::::::,:;'##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##':,:'+################'##########################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#':::;;::::;;##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##+:,,'######++##########+###########################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#;:::;;::::;;+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@++'..:++####+++#######################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#,,::,:::::;'+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#'',,:'+########++++####################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#,,:,::::::;'+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@++,,:'+####+#####'+#######################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#,,:,:::::::;+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#:,,;''#########+'+#######################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#,,,,:,::,,:'+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#;,,:''+####++++'+++#+######################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#,,::,,,::,:;+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+.,,;++######'+''++###########################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#,,,:,,,,,:;'+##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#:,::'++######'++++#++#########################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#,,:,,,,,,:;''''+##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#:,:'++####+#+'++###############################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#:::,,,,,::::::::;+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@+,:;+++###+'+';+#################################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#:,,::::::,,,,,,,,:;##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###:,,'++#####+#++###################################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#:,::,,:,,,,,,,,,,,,;#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##+;:,;'++##+++########################################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@:,::::,,,,,,,,,,.,,:+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####':,;;'+###''#+########################################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#;:::::,,,,,,,,,,.,,:'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##+';,:''++###++##########################################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#;,:,:,,.,......,,,::;+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###++;,,,'''+#'+#############################################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#',;:,,.,,......,,,,:;'######@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+'++::,;''++#;'##############################################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#;,:,,...,.......,,:;;;+#''''+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#''+',::''''++''+##############################################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#,,...,,.......,,,:;;'''++;;::+##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@+;+#;:;;'+'++#+'+##############################################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#..............,,::;';::;'';:,:'+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@';'+:::''''++++;'###############################################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+...........,,,,:;;;,,,,,,;;;::::+##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###;;;;,,,'+''++#','###############################################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@;...........,,,::;:,......,:;;:,,,+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##;;'':,:;''''#+#';+################################################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#,``.........,,:;:,.........,;;:,`.,;#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###+++',:;';:'++'#++##################################################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@@@@@@@@@@@@@@@@@@@@@@@@@@#.......,,..,,:;:,..`...``..,:';,..,:+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###+++;,;'''.'+++#+####################################################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@######@@@@@@@@@@@@@@@@@@@@@@@'....,,,.,.,,:;:,............:;':,,:,;#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####+++;:;'';:+++++++###################################################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#';:;'+##@@@@@@@@@@@@@@@@@@@@@;.,,,,,,,,,,:::,..``...`....,:;;',,:::'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##+++::;;;''++#+########################################################################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@:,,,,,:'+##@@@@@@@@@@@@@@@@@@#:.,:::::,,:::,,:,..``....,.,::;'':,:::'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###+++;;;';''+####+##########################################+++++########################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#:....,,:;+#@@@@@@@@@@@@@@@@@@+,,,:::::::::,,,,,,.......,,,:;;'+'''';'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#####++::;:;'++#############################################+##+++++++#####################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#;..,,,,,:;++@@@@@@@@@@@@@@@@@'.,::::::::,,,,,,,.,,.,,,,::::;'+''+++';+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##++++'::;;'+++++#+########################################+#+++'';';++####################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@',,..,,,:::'#@@@@@@@@@@@@@@@#;,::;:;:::,,,..,,.,.,.,::::;'';''''+##++'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##+##+'::'''++++++#######################################+++++++++'';'+#####################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#:...,,,,:,:'#@@@@@@@@@@@@@@+:,::;;;::,,,.,,,.,,,:::::;''''''++#######@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####+'';;'++++++'########################################+++++'++''''''++###################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@',,,,,,,,,,:+@@@@@@@@@@@@@#':,,:;;;:,,...,.,,,,:;;;;''++++'++++######@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##+#''''''''+++++########################################+++++'+;;''''''+###################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+:,,,,,,,,:::#@@@@@@@@@@@@#;.,,,;;;:,,....,,,,:;;''++++++''++++######@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##+';'''''++#+++#########################################++++++';''''';'+###################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#;::::,,,,:::;#@@@@@@@@@@@#:,,,::;:,.,..,.,,::;;'''++++++'++'++#+####@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##''''''''++++#+++##########################################+++++;;:'';;''+#################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+;;;:::::::::+@@@@@@@@@@@#:,,::::,......,,:;';+''+++++'''''''''''+##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+'+''''''++++++++#########################################+++++++;::;;;'++#################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#'';::;::::::'##@@@@@@@@@#:::::,,....,,,,:;';'''''''+'';;;;;;;:::;+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@++''+''''+++++++#########################################++++''++++';;;'++##################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+'';;;;:::::;+#@@@@@@@@@#;,:,,.....,,::::';'''+';';;;::::,:::::::;+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##+'''''''++++++##########################################+++'';;;''';;;''++#################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#'';;;;:::;;;'##@@@@@@@@+:,,........,::;'''+'';::,,,,,,,,,:,,:::::;#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+''''''''++;'++########################################++++';;:::;;:;;''''++###############################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+'';;;;::;;;;+@@@@@@@@#;..........,,:;'''';;:,,.,...,.,,,,,::::::;+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##+''''''''':'+##########################################+++';::::::::::::;++################################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+'';;;;;;;;::'#@#@@@@@+:.........,,::''''';:,....,,,,..,::::::;::;+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##+';;''';'''++##########################################+++'';::::::,:::::;+++##############################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#''';';;;;;::;+####@##',...,,,,,,,:;'''+++;,,,.......,,,::;:;;:;;;+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+':''';;''''+############################################+++++';;;::::::::::'+++############################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#'''+';';';::;'#@#####:..,:;::,,:::;''++++';,,,,,,,,,:::::;;;;;;''+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@++++++;::;:;'+##################+#########################+++++++';;::::::::::;+++############################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@++''''+'::::;;+#####',.,,;;;;;;;;;''+++##+';;;;:::::::;;;;'''''''+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#++'++':::;;''##################+###+#######+###############+++#+';;;::::::::::'+++###########################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#''++++;:::::;'+##+':,.,;;;;'';'''+++++###+'''';;;;;;;'''''''''++##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##++++';:;:''''##################+####++######++################++++'';:::::::::;'+++##########################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+++#+'';::::::;'';:,,,:;;'''''++++++++#####++++'''++++++++++++++##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#####+::''''++#++######################++######+#+###########+++++++'';:::::;:;::;''+++########################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#''+++';';;;:;,:,:,,,,;;'''++++++++++#########+++'''+++++++++++###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+;''''+++++###############+++#####++#######+#+########++++'';;;;:::,:::::::;:;''+++#######################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+'++++';';';,:::,,,,:'''''+++++++++############++++++++++++++++##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##'';''+++++##############+##+#####+++#####+++++########++;;:::,,,,,,,,::::::;:;'''+++#####################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#'+'++++'''::,,,,,,:;'''''+++++++###############+++++##+++++++++#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'''+++++++##############++#+++###++#+####++#+##+#####++';:,,,,,,,,,,,,,::::;;:;;;'+++####################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+'+''+''';;;,,,,,:;''''+'++++++#############+###+++######+++++++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@''##+##+#+################+++++++#++++###++++++++++###++';;:,:,,,,,,,,,,,::;::;:;;''++#####################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+;:''+';':'::,,,,:'''''+'++++++############+++##+++########+++++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#'+#####++##################+++#++++#++#+++++''''''''''''';;:;:,,,,,,,,,,,,:::::;:;;''++####################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#;;;;;;;;;;:,,,,,:'''''''+++++#############+++++++++######+++'''#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'###++++#####################+#+++++++++++++++''';;;;:;;::::,,,,,,,,,,,,::,:::;::::;''+++##################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@';:;;;:::::,,,,,;'''''''''+++#############++'++##+++####++''''+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+###+##++##################++#+++++++++++'+'''';:;:::::::::::,,,,::,,::::::::::::::;;:'+++##################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+::;;:::;:,,,,,,;'''''+'''+++############++++++++++++#++++''''++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#######++#####@@@@@####+++++++++++++++''+''''';;;;::::::::::;;::;;;;;;;';::::::::::;::;'+++#################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#:;;:::::,,,,,,,:'''''''''+++###########+++++++++++++++++''''''+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##@@@@@#@@@@@@@@@@@@##+++++++++++++++''++''';;;;:::::::::;;''''''+'++''';;;;:::::,,,:::;'+++################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#;::::::::,::,,,:''''''''''+++#######++++++++++++++++++''''''''+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#++'''''++++++''++++'';;;;:;:::::;;'''+++++++++++'';';;:::,,,,,,::;;+++#################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@':::::;::,:::,,,;';;''''''++++#####+++';'++++'''+++++'''''''''+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#++'';;'++++++''''''';;;;;;:::::;;'++++++++++++''';';';::,,,,,,,,::;;++#################################################@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+;::::::,:::,,,,,;''''+++''+++++###+'+';;'++;;;'++++;:;;;;''''+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#++';;:;'+++++'''''';;;;;;;;;;;;+++++#+#+++++'''''';::;:,,,,,,,:,::::;++###############################';;;;;+#++###++##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#';::;;;:,,:,..,,,:;;'''''''++++++++';;;;;+';;:''+';:::::;;;;'+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+'';::;'++++++'''';;;;;;;;;;'++########+++'';;;;'';:;:,,,,,,,,,,::::;'++############################+:,,,,,:'++'###;;###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#;;:;;::,,:,..,,,::;''''''''++++++;:;:;;;';;:;''';:::,:;:;;;''#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#';;;;;;;''''''';;;;;;;;''''+#########+++''';;;;;';;::,,,,...,,,,,::;:;'+###########################+:,,,.,'#+++;:;+;;###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+;;;;::,,:,,:,,,::'''''';'''+'''':::;;''';:::'';;::::::::;;;'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@':;;;;''';';;'';;;;''''+'++#########+++''';;;;;';;:,,,,,.,.,,,,,,::;:;'++########################+#:.,..,++####;,,'::+###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#;;;::,::,,,,:::;;''';;'''+'''';:::;''';:;::';:::::::,:::;;'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#',:;'''';;;'';;;;;''''+++###########+++';'';;'';:,,,,,,.,.,,,,,,::::;;;++######################+#++,....+#+#+++':,;:,;###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+;;:::,:::::,:;''''''''''''';::::;'''';:::;;;::::::::;;:;;'+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#',:;;''''''''''''''''++####+++######++''+'''''';,,,,,,,,,.,.,,,,:::::;;++#####################+##;';```,#+'++''+;:::,,+##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+;::;:::::::;;'''''''''''';::::;'+++';::::::::;::::::::;;'+#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#',,:;''';''''''+''''+++####++#######+++'''++++;::,:,,,,,,,..,,.,,::,:;;'++####################+#+:;'..`;+;'###++':,,,,'##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+;;;;;;::::;'''''''''''''::::;'++++';:::::::::::,:::::;;;'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#'.,:;'''''''''+'''+++++##+++######@##+++++++++';::,,,,,,,...,,,,,::,::;'+++#################++++::'+.``';;+####+:',,.,;###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+;';';;;:;''''''''''''';:::;''++++';::::,,,:::::::::::;;:;#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+,.:'''''''+'''+'+++++++++++####@##@##+######'';;:,,,,,,,.,,,,,,,::::::''+###############+++:#':::+',`.+,:@####+,+;.,,,+##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+;';'';;;'''''''''''';::::''+++++';:;:,,,,:::::,;:;::;;,,;#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+,,;++++++++++++'''''++++++++#######@#######+++;:,,,,,,,..,,,,,,::::::;'++###############+++.++:;:'.,.,+;'@###'',+;..,,;##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+';'';'''''''''''''';:::''++++++';::,,,,,::::::;:::;;;,..'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+:,'+#######+++++';;;'''+'+++######@@#######++';:,,,,,.,,,,,,,,:::::::;+++##############+'++.;+'+';;'`,+''+;::.',+'...,,+##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+';+'''+++''+''''';:::;'+++#+++';:::,,::::::::::;;;;;:.`,+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+;+##########+#++';;;;';;;;'+++++#########+#';:,,,,..,..,,,,,,:::::::;'++##############+''',,+;'+;;'.;,#:.;.:,:,:'.....;##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+''''+++++++++++;:::;''++++++';:;:::::,::::;::;:;;;;',`.:#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#++###+##########';;:;:::::::;:;;'++#####++';:,,,,,.,.,,,,,,,,::::::::'++#############+;;;',,+:;++;;.''+:,;.::'.:;,.....##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+'''+++++++++';;:;:''+++++++';:::,::::::::::::;;;;;':.`.'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####++++########+;:::,,..,,..,,,,:;'+++++'';:::,,,,,,,,,,,:,:::::::::''+#############;:::';,+::'+';`';':.:;:+':'::....,;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+'''+++++++++;;;:;''++++++';::,:::::::::::::;:;;;'':...,#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###++++#########;:,,,,..,,.,,,,,,,:';;';;;::::,,,,,,,,,,,,,,,,,:::::'++#############;:::;'.+,:''+'.+:;,.;;,++;';;.....:#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+''++++++++'';;;;'++++++'':::,,::::::::::::;;;;;'':....'#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@####++########:,....,.,..,..`...,:;::::::::::,,,,,,,,,,,,,,,,,::::'++############+::,,:'.+,,+:.:.+:::.;.`;+'+;;......#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#+'''++++++''';;;'++++++';:,,,::::::::::::;;;;;;'+:,...,@@@@@@@

Elvis
Hackers & Deve opers Magaz ne

ASCII Art

U! Tu zona exclusiva
Para publicar tu mensaje en la Zona U!, envanos un e-mail contacto@hdmagazine.org,
indicando ZonaU! en el asunto del mensaje.

HDMagazine Responde:
Matas Caricato (Argentina):
(...) Primero que nada, quiero felicitar a todos los que participan
en la creacin de esta excelente revista que llena nuestros
espacios de ocio aportando temas de lectura muy interesantes y
de primera calidad. Mi sugerencia es la siguiente: agregar a la
web un mdulo de subscripcin que notifique por email cuando
hay una nueva edicin de la revista disponible (...)
Aura Mara Acosta (Colombia):
(...) Quiero saber como hago para suscribirme a esta revista, no
perderme un solo numero ya que mi campo de accin son los
sistemas; reparo computadores y dicto clases.
Respuesta a Aura y Matas: Hola Aura y Matas!
Muchas gracias por escribirnos. Para poder ofreceros
un sistema de suscripcin por e-mail, necesitaramos
contar con un servidor de correo y personal que se
encargue de mantenerlo. Confiamos en que los aportes
voluntarios que puedan hacer nuestros lectores, en un
futuro, nos podrn ayudar a solventar los costes que
este servicio implicara.
Richard Diaz Rodriguez (Cuba):
Me gustara que hicieran alusin a la seguridad de las
comunicaciones GSM y sobre si es cierto determinar o triangular
la posicin de un comunicacin mvil o va GPS. Saludos a
todos(as) creo que estn haciendo un trabajo magnifico y por
ac por cuba se les sigue de muy cerca y se cree y quiere mucho
su trabajo. Feliz 2013.
Respuesta: Hola Richard! Muchas gracias por tu
mensaje! Seguro que HackLadino cumplir tu deseo!
Lailah (Uruguay):
Hola a todos! Le la ltima edicin con la entrevista a Richard
Stallman. Podran en algn momento incluir una entrevista a
Linus Torvalds? Creo que sera muy interesante.

HD

Fabian Arellano (Chile):


hola quiero agradecerles por la revista es muy instructiva e
informativa y si en el otro numero de su revista puedan incluir
un apartado de inteligencia artificial aplicado a Juegos Saludos
y feliz ao mi nombre es Fabin y soy de Chile
Respuesta: Hola Fabian! Muchas gracias por tu
mensaje! Por el momento, no contamos con
columnistas especializados en el desarrollo de
videojuegos, pero s, con una experta en IA (Yecely).
Veremos que puede hacer nuestra experta al respecto.
Stefan (Espaa):
Me encanta vuestro trabajooo!! grande... muy grande!! Un
saludo desde Espaa!!
Respuesta: Hola Stefan! Muchsimas gracias por tu
mensaje! Un placer leerte :)

Anuncios:
FIREFOX OS APP DAYS
El pasado sbado 26 de enero de 2013, se lanzaron los Firefox OS
App Days en diferentes ciudades de todo el mundo. Fuimos
invitadas/os a cubrir el evento y nuestra columnista Laura
Mora estuvo en el Firefox OS App Day Barcelona. En
la prxima edicin, tendremos los detalles en exclusiva. Ms
informacin sobre Firefox OS: www.mozilla.org/es-ES/firefoxos/
L ANZAMIENTO DE OPENWEBINARS
La Fundacin Guadalux los invita a participar de los nuevos
seminarios Web gratuitos sobre aplicaciones, herramientas y
tecnologas para el desarrollo de proyectos OpenSource, que
pueden aplicarse al entorno empresarial. Ms informacin:
www.guadalux.org/openwebinars

Respuesta: Hola Lailah! Promesa que intentaremos


hacer todo lo posible por cumplir tu deseo en 2013 =)

GRACIAS A TOD@S POR LEERNOS!

PRODUCIDO EN L A REPBLIC A ARGENTINA , POR HACKERS DE TODO EL MUNDO, PARA PROFESIONALES DE TODO EL PLANETA.

También podría gustarte