martes, 22 de marzo de 2011

F1: 20 pasos para configurar un coche de carreras

Bueno, antes que nada aclarar que estas imágenes no son mías. Las hizo un amigo, Yago, pero me pidió que las subiera al blog para que las pudiera ver más gente.

Se trata de dos hojas con una lista de parámetros de configuración de un coche de carreras. Él las usa como referencia en simuladores de Fórmula 1.

Para ver (e imprimir) las fichas a tamaño completo, pulsa sobre las imágenes.

20 pasos para configurar un coche de carreras - Hoja 1 -

20 pasos para configurar un coche de carreras - Hoja 2 -

viernes, 11 de febrero de 2011

C#: Acceso directo a ficheros de Word 2010

- Introducción.

A veces es útil acceder directamente a un fichero de Word en formato .docx desde un programa en C#. Por ejemplo, yo lo uso para generar documentos personalizados más allá de lo que permite la opción "combinar correspondencia", insertar imágenes, etc.

Antes, los ficheros de word eran binarios y esas tareas había que hacerlas a través de la aplicación Word con  objetos COM. Desde la introducción del formato open XML (.docx), el mundo es un lugar mejor para los programadores.

- El meollo de la cuestión.

Un fichero .docx no es más que un fichero comprimido .zip , que contiene todos los ficheros e imágenes del documento de Word en formato XML.

Si quieres hacer la prueba, crea un fichero prueba.docx, escribe algo de texto, inserta una imagen, guárdalo, sal de Word, renómbralo como prueba.xml, y ábrelo. Verás un fichero XML, y varias carpetas. Entra en la carpeta "word", y abre el fichero "document.xml" Ahí está tu texto. Si abres la carpeta "media", verás tus imágenes.

Finalmente, cierra los ficheros, y renombra la carpeta prueba.zip por prueba.docx Podrás abrirlo sin problema con word.

En los siguientes apartados veremos cómo modificar el fichero a través de C# Voy a usar las siguientes variables:

string directorio_trabajo = Path.GetTempPath();
string fichero_entrada ="prueba";
string fichero_salida = "prueba2.docx";

... donde, evidentemente, directorio_trabajo es un directorio temporal donde comprimir/descomprimir los ficheros, fichero_entrada es el fichero "plantilla" que nos va a servir de base para generar la documentación, y fichero_salida va a contener el resultado.

En los ejemplos de código siguientes, vamos a suponer que fichero_entrada se encuentra dentro del directorio_trabajo.

- Descomprimiendo el fichero.

Hace años, cuando investigué la forma de acceder a ficheros OpenXML, C# no tenía forma de acceder a una carpeta ZIP. La solución que encontré (no muy elegante), es usar un programa externo para comprimir y descomprimir los ficheros. Busca (en Google) una versión libre de zip.exe y unzip.exe como esta....

http://stahlworks.com/dev/index.php?tool=zipunzip

Una vez tengas esos ejecutables, añádelos a tu proyecto, y usa este código para llamarlo:

string orden = "\"" + Application.StartupPath + "\\unzip.exe\"";
string parametros = "\"" + Application.StartupPath + "\\prueba.docx\"";


System.Diagnostics.Process p = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo(orden);
info.UseShellExecute = true;
info.Arguments = parametros;
info.WorkingDirectory = dir_trabajo;
info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;


p.StartInfo = info;
while (!p.Start()) ;
while (!p.HasExited) ;


Dependiendo de dónde esté tu fichero docx, tendrás que ajustar un poco las rutas de los ficheros en tu código.

- Cambiando el texto del fichero.

Dentro del árbol de ficheros que aparece tras descomprimir el .docx, debes abrir el fichero \word\document.xml.

La forma elegante de hacer los cambios es cargar el fichero XML con la clase XmlDocument , buscar los nodos que contienen el texto que quieres sustituir y volver a crear el fichero. Desgraciadamente, me pagan por programar rápido y no por programar elegantemente :)

La forma más rápida de hacer cambios es cargar el fichero XML en una cadena de texto:

// Leemos toda la cadena en un fichero.
string documento = File.ReadAllText(fichero + "\\word\\document.xml");


// Pon aquí los cambios que necesites. En el ejemplo, sustituyo la cadena "{nombre}" en 
// la plantilla por un nombre cualquiera.
documento = documento.Replace("{nombre}", "Armando Bronca Segura");


// Volvemos a grabar el fichero.
File.WriteAllText(fichero + "\\word\\document.xml", documento);

- Cambiando imágenes.

La forma más sencilla de cambiar imágenes en un documento es insertar una imagen desde Word en la plantilla, y luego sustituirla por otra en tu programa.

Las imágenes están en la carpeta \word\media\image1.gif , \word\media\image2.gif ... Antes de de escribir el programa, debes ver qué nombre le ha dado Word a tu imagen, para poder sustituirla por otra.

Si tienes un fichero con la nueva imagen, solo tienes que copiarlo usando la librería IO:

File.Copy ("mi_imagen.gif", @" \word\media\image2.gif");

Si quieres copiar el contenido del portapapeles como una imagen, usa este código:

if (Clipboard.GetDataObject() != null)
{
         IDataObject data = Clipboard.GetDataObject();


         if (data.GetDataPresent(DataFormats.Bitmap))
         {
                  Image image = (Image)data.GetData(DataFormats.Bitmap, true);
                  image.Save(Directory.GetCurrentDirectory() + "\\" + fichero + "\\word\\media\\image1.gif", System.Drawing.Imaging.ImageFormat.Gif);
         }
}


- Comprimiendo el fichero.

Una vez hechos todos los cambios, hay que volver a crear el documento .docx

string orden = "\"" + Application.StartupPath + "\\zip.exe\"";
string parametros = " -r -9 \"" + dir_salida + @"\prueba2.docx\" *";

System.Diagnostics.Process p = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo(orden);
info.UseShellExecute = true;
info.Arguments = parametros;
info.WorkingDirectory = dir_trabajo;
info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;

p.StartInfo = info;
while (!p.Start()) ;
while (!p.HasExited) ;

- Abriendo el fichero.


Probablemente querrás abrir el fichero con Word  desde tu aplicación para que el usuario no tenga que buscarlo y abrirlo él.

System.Diagnostics.Process p = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo(plantilla);
info.UseShellExecute = true;
p.StartInfo = info;
while(!p.Start());

Saludos :)

miércoles, 9 de febrero de 2011

C#: Tareas multihilo en dos patás.

- Introducción.

Como probablemente ya sabes, hoy en día es importante construir tus aplicaciones de forma que aprovechen los múltiples "cores" de los procesadores y que sean capaces de seguir respondiendo al usuario aunque "por detrás" estén ejecutando procesos pesados.

En los viejos tiempos (más o menos, a principios del año pasado) , los programadores de C# usábamos el objeto BackgroundWorker para construir aplicaciones multihilo. Con la llegada de .NET 4, tenemos una nueva herramienta: los objetos Task.

A continuación encontrarás algunos fragmentos de código útiles para crear tareas y organizar su ejecución. Dejo de lado el tratamiento de excepciones y el paso de parámetros para otro artículo.

- Para crear una tarea.

Imagínate que tienes un formulario, y que quieres ejecutar una tarea cuando se carga (por ejemplo, leer unos datos de la base de datos).

using System.Threading.Tasks;
....
private void Callejero_Load(object sender, EventArgs e)


{
     Task t1 = new Task(
     () =>
           {
                  // Cargamos la lista de provincias en el control.
           });


      t1.Start();
}

Este  método, define una tarea, solicita que se empiece a ejecutar, y sale sin esperar a que termine. El formulario seguirá respondiendo al usuario mientras ejecuta otras tareas en segundo plano.

Una cosa importante es que no puedes acceder a los controles del formulario desde un hilo distinto al que lo ha creado. Por ejemplo, la tarea no podrá cambiar el valor de una caja de texto del formulario directamente. Más adelante veremos un ejemplo de cómo hacerlo.


- Definir una tarea que se ejecute cuando otra termine.

Si tenemos una tarea T1 (como la anterior), y queremos definir una tarea T2 que se ejecute a continuación...


Task t2 = t1.ContinueWith(
ant =>
{
           // Hacer más cosas
});


No es necesario llamar a Start() en una tarea de continuación (de hecho da un error). La tarea se arrancará automáticamente cuando T1 termine.

- Definir una tarea que se ejecute cuando varias tareas terminen.

Si tenemos dos tareas T1 y T2 que se van a ejecutar en paralelo, y queremos definir una tarea T3 que arranque cuando las otras dos terminen ...


Task t3 = Task.Factory.ContinueWhenAll(
       new[] { t1, t2 },
        tasks =>
              {
                   // Hacemos más cosas
              }
 );

- Definir una tarea que se ejecute cuando otra termina, y actualice controles de nuestro formulario WPF.

Este es un caso muy típico. Imagínate que tienes un formulario que, cuando pulsas un botón, arranca una tarea T1. Cuando la tarea empieza, apagas un botón para que el usuario no le vuelva a dar. Cuando la tarea termina, quieres volver a habilitarlo. Nada más fácil.


Task t_final = t_1.ContinueWith(
        ant =>
       {
              btn_procesar.IsEnabled = true;
       }, TaskScheduler.FromCurrentSynchronizationContext());




- Definir una tarea que se ejecute cuando terminan otras, y actualice controles de nuestro formulario.



Task tarea_final = Task.Factory.ContinueWhenAll(
                        new[] { task_eventos, task_estados, task_info, task_parametros, task_control, task_canont },
                        tasks =>
                        {
                            // Accedemos a controles de nuestro formulario.
                        }, 
                        CancellationToken.None, 
                        TaskContinuationOptions.None,
                        TaskScheduler.FromCurrentSynchronizationContext()
                    );

viernes, 21 de enero de 2011

Debian Squeeze: habilitar sesiones X remotas.

Por motivos de seguridad, por defecto en las distribuciones de Debian el servidor de X Windows no escucha en ningún puerto de red.

En versiones anteriores, lo único que había que hacer era irse al fichero /etc/X11/xinit/xserverrc y cambiar la línea:
 exec /usr/bin/X -nolisten tcp "$@"
por
exec /usr/bin/X "$@"
Desgraciadamente, si usas GNOME ahora eso no funciona. El problema está en que el programa GDM3 siempre añade la opción "nolisten" a menos que se configure específicamente para que no lo haga. Hay que ir al fichero  /etc/gdm3/daemon.conf , y done pone ...
[security]

... añadir ...
[security]
DisallowTCP=false
Reinicia las X (o el equipo), y deberías ver al servidor escuchando en el puerto 6000:
~$ nmap -sT 192.168.0.20


Starting Nmap 5.00 ( http://nmap.org ) at 2011-01-21 10:09 CET
Interesting ports on 192.168.0.20:
Not shown: 989 closed ports
PORT     STATE SERVICE
...
6000/tcp open  X11
6001/tcp open  X11:1
...
Nmap done: 1 IP address (1 host up) scanned in 0.05 seconds
Saludos.

martes, 16 de noviembre de 2010

World of Warcraft: Addons para principiantes.

Esta es una pequeña guía que escribí para lo foros de World of Warcraft. Contiene una descripción rápida de lo que son los addons, como se usan, algunas dudas típicas, etc. Está un poco obsoleto, pero puede resultar útil a los principiantes.

1-¿Qué son los addons, y para qué sirven? 

Los addons son programas que se integran con World of Warcraft y que lo mejoran de alguna forma.

Pueden hacer muchas cosas, desde presentar información útil en combate, cambiar el modo en el que se visualizan las barras de vida y maná, organizar los iconos de forma distinta, ayudarte a comerciar... Hay un addon para casi cualquier cosa que se te ocurra.

2- ¿Son ilegales?

Respuesta corta: normalmente, no.

Respuesta larga: Sólo es ilegal usar programas que te den una ventaja evidente sobre el resto de jugadores. Por ejemplo, es ilegal usar un programa que te permita correr más deprisa, o que haga que tu personaje pueda combatir solo.

La regla de oro es que, si el addon va instalado en el directorio Interface/Addons, es legal al 99,9%. Si es un programa ejecutable externo al juego, es ilegal al 99,9%


3- ¿Dónde se consiguen? 

Hay muchas páginas desde donde se pueden descargar addons. Ten cuidado, porque a veces vienen con bicho (troyanos para robarte tu cuenta de WoW). Aquí tienes un par de páginas importantes, y seguras:

http://wow.curse.com
http://www.wowinterface.com/addons.php

Antes de descargar un addon, debes comprobar dos cosas:

a- Que es compatible con tu versión del juego. Por ejemplo, los addons para la versión 3.x no funcionarán en la 4.x. Ten en cuenta que no hay addons para PC y Mac, son independientes del sistema operativo.

b- Que es compatible con el idioma en el que juegas. Lógicamente, hay muchos más addons que funcionan en inglés que en castellano.

Esa información suele estar disponible en el sitio de descarga.

4- ¿Cómo se instalan? 

La mayoría de addons vienen en un fichero .zip que debe descomprimirse en la carpeta interface\addons. Cada add-on debe instalarse en un directorio separado.

Es muy importante cerrar el juego antes de trastear con la instalación de addons.

Por poner un ejemplo, vamos a instalar el addon Questhelper. Lo primero es bajarse el addon de la página de curse:

http://wow.curse.com/downloads/wow-addons/details/quest-helper.aspx

Abre el fichero ZIP. Dentro verás una carpeta Questhelper.

Ahora vete al directorio del juego (MI PC -> Archivos de programa -> World of Warcraft) , entra en la carpeta Interface, y luego en Addons. Verás algunas carpetas con addons de Blizzard (Blizzard_AchievementUI, Blizzard_ArenaUI, etc) Si no ves esas carpetas, estás en un sitio incorrecto.

Para instalar el addon, sencillamente arrastra la carpeta Questhelper para que se descomprima dentro de la carpeta addons y le haga compañía a las carpetas de Blizzard.

Bien, entra en el juego. En la pantalla de selección de personaje (recuerda, ANTES de entrar en Azeroth) aparecerá un botón "Accesorios" ("addons") abajo a la izquierda.

Desde ahí puedes seleccionar qué addons quieres cargar. Asegúrate que "Questhelper" está seleccionado. Entra en el mundo, y verás que aparecen nuevas ventanas con información de las quests que tienen activas.

5- No veo el botón de Accesorios, o mi addon no aparece en la lista 

El botón de accesorios sólo aparece cuando tienes instalado correctamente al menos un addon. Si no lo ves, o si tu addon no aparece en la lista de los complementos, es que no está bien instalado.

Comprueba que la carpeta está donde tiene que estar.

Comprueba que NO lo has metido en una subcarpeta. En nuestro ejemplo anterior, World of Warcraft\Interface\addons\Questhelper\Questhelper estaría mal

Comprueba que los ficheros del addon están en la carpeta con su nombre. En nuestro ejemplo anterior, tiene que haber un fichero World of Warcraft\Interface\addons\Questhelper\QuestHelper.toc

6- ¿Cómo se usan? 

Eso ya depende de cada addon. Normalmente, deberás revisar la documentación para ver cómo se usa.

En algunos casos no tienes que hacer nada, y verás los cambios directamente en el propio interfaz del juego.

En algunos casos, aparecerá un botón nuevo al lado del minimapa. Pulsa sobre él para activar/configurar el addon.

Casi siempre podrás acceder a la configuración de tus addons a través de la configuración del juego. Entra en el menú principal (ESC) , configuración del interfaz. Arriba verás dos solapas, una para las opciones de Blizzard, y otra para las opciones de los addons.

Finalmente, a veces tendrás que introducir una orden en el chat para activarlo. Por ejemplo, escribe /mi2 para activar el addon "mobinfo"

7- Mis mods han dejado de funcionar después de un parche. 

Todos los mods están asociados a una versión de WoW. Cuando la versión de WoW cambia, los mods que no han sido actualizados dejan de funcionar "por prudencia".

Hay dos formas de solucionar esto. La mejor es bajarte una versión actualizada de tu mod.

Si esto no es posible por la razón que sea, puedes irte al botón de addons y hacer clic sobre la casilla "Cargar addons no actualizados". Lo normal es que siga funcionando (aunque siempre es mejor actualizarse a la última versión del addon)

8- Arggggggg, en la web hay unos 100 millones de addons, ¿cual instalo? 

Eso depende de cada jugador, incluso de cada personaje de cada jugador. También hay que tener en cuenta si juegas en español o no.

Creo que lo mejor que puedes hacer es irte a curse.com (o a cualquier otra web) y ordenar las listas por número de descargas. Así verás qué addons son los más populares (y, normalmente, más útiles).

A continuación tienes algunas sugerencias que a mi me han resultado útiles...

.OmniCC - En el interfaz por defecto de Blizzard, cuando usas una habilidad el botón queda sombreado. Con este pequeño addon podrás ver una cuenta atrás sobre el botón que te indica cuándo podrás usar la habilidad de nuevo.

. Recount - Este addon recopila información del combate (quien hace daño, con que habilidades...) y te muestra estadísticas y gráficos. Es muy útil para analizar tu personaje y tu forma de combatir.

. Auctioneer. Este addon es muy útil para comprar y vender en la casa de subastas. Crea una base de datos de precios de subasta, de forma que sabes cuánto se ha estado pagando por un objeto. Si encuentras que Auctioneer es muy complicado, prueba AuctionLite o Auctionator.

. X-Perl: Un lavado de cara completo para el interfaz. Retratos en 3D, barras de vida más grandes, indicadores de agro... Uno de los mejores addons que se han hecho para el juego.

.Grid : Un addon muy utilizado por sanadores. Visualiza toda la información que necesitas de tu grupo o banda (vida, buffs, debuffs) de forma completamente configurable.

.Clique : Este addon te permite asociar hechizos a los botones del ratón, y lanzarlos pulsando sobre el retrato de un jugador o monstruo. Es el complemento perfecto de Grid, y muy útil para curar.

. Atlas: un addon que contiene mapas detallados de todas las mazmorras del juego, junto con la posición de los jefes.

. Deadly Boss Mods : Imprescindible para visitar mazmorras. Este addon contiene avisos y temporizadores específicos de cada jefe, para avisarte de cuándo va a usar una habilidad o cuanto queda para que cambie de fase.

. BossInfo: un pequeño addon con información táctica de los jefes de mazmorra.

9- ¿Puedo hacer mis propios addons?

¡Por supuesto! Y si además las compartes con el resto de usuarios, mejor que mejor :)

Puedes usar algún addon como Discord, que permiten re-configurar completamente la interfaz, y luego publicar tus modificaciones.

Puedes crear un paquete de addons y distribuirlo. Tienes las instrucciones en este otro hilo, creado por Atha:

http://forums.wow-europe.com/thread.html?topicId=122552664&pageNo=1

O puedes escribir un addon desde cero. Necesitarás algunos conocimientos de XML y LUA. Pásate por aquí...

http://www.blizzard.com/support/wow/?id=aww01671p