Hace una semana arrancábamos comentando de qué iba a tratar el proyecto pytweetclin, pero dábamos poca información: cliente de Twitter, multiplataforma, desarrollado en Python+PyQT y poco más. Durante esta semana han sido varias las personas que se han interesado y nos han comentado lo arriesgado de la propuesta por la existencia de multitud de clientes de Twitter, y nos sugerían algún modo de diferenciación con el resto.
Que existen multitud de clientes de Twitter es obvio, pero a nuestro gusto la gran mayoría de ellos adolecen de numerosos problemas de usabilidad. Además, existen algunos clientes que están bien en unos aspectos pero bastante mal en otros. Tal y como le comentábamos a David en los comentarios de nuestra primera entrada, en principio pretendemos desarrollar una funcionalidad básica de Twitter que incluya lo que a día de hoy ya incluyen la mayoría de los clientes de Twitter, pero centrándonos sobre todo en la usabilidad y la experiencia del usuario. Es por este motivo por lo que desde hace algún tiempo veníamos teniendo idea de intentar desarrollar un cliente que sea sencillo y visual, pero sobre todo usable.
También uno de nuestros objetivos desde el principio es que nuestro trabajo pudiera ser aprovechable en numerosas plataformas, de ahí la decisión de optar por Python+PyQT, una solución que en un principio es tan válida para Windows como para Linux y Mac. Podíamos haber optado por una solución web pero particularmente creemos que para este uso es más cómoda una aplicación de escritorio.
Tenemos algunas otras ideas de funcionalidades añadidas que creemos pueden ser interesantes. Sin embargo, primero vamos a centrarnos en lo básico y el tiempo dirá, pues ya se sabe: quién mucho abarca proco aprieta :-)
Para terminar por hoy, tan solo aclarar que no somos expertos en usabilidad, tan solo aprendices, y es la primera vez que nos involucramos en un proyecto de software. Como estudiantes de Informática que somos ambos, hemos hecho algún que otro desarrollo de software pero hasta la fecha nada de considerable envergadura. Para no alargar más una idea que teníamos en mente decidimos inscribirnos en el Concurso Universitario de Software Libre. Esperamos que nuestro esfuerzo y nuestro trabajo se convierta en algo útil para la comunidad pero sobre todo esperamos poder aprender a desarrollar y mantener por nuestra cuenta un proyecto de software.
En breve publicaremos otro artículo, así que permaneced atentos. Vamos a necesitar de vuestra colaboración :-)
Filed under: Noticias
Gracias a que he dado de alta el proyecto Camimic en la forja de Redirirs, tenemos una serie de herramientas muy útiles, entre otras, un dominio y alojamiento de páginas web en el que crearé una página estática a modo de presentación del proyecto. De momento he hecho algo muy simple, espero tener tiempo para [...]
Después de mucho esfuerzo para conseguir el resultado que queríamos para esta primera versión, hoy podemos decir que ya la tenemos terminada, a partir de ahora el trabajo se centra básicamente en la implementación de nuevas funciones, aumentando la complejidad de las mismas ya que la idea inicial del proyecto es proporcionar códigos de funciones complejas para que cualquier programador que este iniciándose pueda crear sus programas “sin dificultad”.
A parte del desarrollo de nuevas funciones, mejoraremos el aspecto gráfico de la aplicación poco a poco.
Publicada esta primera versión, no publicaremos la segunda hasta que no este terminada. Ya fijaremos los objetivos para esa segunda versión, ya que todavía no están muy claros.
Esperamos poder dedicarle el tiempo suficiente al desarrollo y no dejar el proyecto parado, lo importante era llegar hasta aquí, a partir de ahora no deberíamos tener muchos problemas.
Llevo unos días un poco liado con prácticas de la universidad, y no he podido mantener demasiado el blog (he preferido aprovechar el poco tiempo libre que tengo para dar un poco más de forma a YUD).
La revisión 6, que ya está subida en el repositorio del proyecto, modifica de forma automática el Live CD pasándole una serie de parámetros por la línea de comandos. Para ello, he utilizado el módulo “argparse” de Python, incluido desde la versión 2.7. El uso del programa es:
sudo python yud.py -i IMAGE.ISO -o DESTINE -c CUSTOM_FILES_DIR
Para saber más acerca de otros parámetros que admite el programa, se puede ejecutar el programa con el parámetro “-h”:
python yud.py -h
Por otro lado, la interfaz gráfica básica está casi terminada, así que espero en unos días poder subirla al repositorio. No he puesto demasiada atención en la gestión de errores (comprobar si la imagen pasada es correcta, permisos de superusuario, …), porque he preferido tener cuanto antes una versión simple pero completamente funcional, para poder distribuirla e intentar conseguir algun colaborador (la verdad es que es mucho el trabajo que hay que realizar).
Así que el objetivo de los próximos días es terminar la interfaz gráfica, para continuar añadiendo módulos para modificar el Live CD (aspecto, configuración, etc).
Cuando hace unos días escribía un artículo presentando a la Asociación de Desarrollo de Videojuegos de la Universidad de Cádiz (ADVUCA) comentaba que estábamos preparando nuestra primera actividad. El taller: “Introducción al desarrollo de videojuegos con un Pong” va viento en popa y se celebrará los días 22 y 25 de noviembre de 17:00 a
En la entrada anterior hablamos de las bases de datos objeto-relacional Neodatis, de sus pros y de sus contras. En esta entrada explicaremos como las características de Neodatis han influido en la organización, planificación y desarrollo del paquete data.kanji
.
Antes de nada, pondré de nuevo el diagrama para que podáis ir consultándolo:
Paquete data.kanji
Las clases principales que motivan el desarrollo del resto de clases son la clases KanjiTag
y Kanji
. Como puede verse en el diagrama, son fundamentalmente la misma clase, con la diferencia de que Kanji
incorpora métodos de establecimiento. La motivación de esto es diferenciar claramente entre la construcción de la base de datos y la consulta, de forma que, usando generalización de tipos heredados, KanjiTag
será el tipo de objetos que devolverá la base de datos y Kanji
los que realmente estarán almacenados y que se usarán para construirla. La rigidez en este sentido llega hasta tal extremo que, a diferencia de la clase Kanji
, los métodos que devuelven listas o sets (como por ejemplo getMeanings()
) devuelven listas no modificables.
El problema
Los atributos de la clase KanjiTag
definen los atributos que puede tener un kanji. Ya dijimos que los atributos podían ser de cuatro tipos: entero, clases específicas, pareja de cadenas, y lista de cadenas asociada a una clave. Sobre las dos últimas ya hablamos el otro día, dijimos que las clases que representan a estos atributos heredaban de KanjiStringPair
y KanjiStringListEntry
respectivamente. Sabiendo esto, a un programador experto podrían surgirle las siguientes preguntas:
KanjiStringPair
o un KanjiStringListEntry
dentro de la clase Kanji
para representar los distintos atributos?Pair
y de ListEntry
del paquete data.auxi
en KanjiStringPair
y en KanjiStringListEntry
si hacen fundamentalmente lo mismo?KanjiReference
?Segunda pregunta puede responderse rápido. Recordemos la frase de la entrada anterior sobre Neodatis:
En Neodatis, la mezcla de herencia y tipos genéricos en una misma clase genera problemas a la hora de recuperar objetos de dicha clase.
En principio Pair
y de ListEntry
fueron desarrollados con el objetivo de que KanjiStringPair
y KanjiStringListEntry
heredasen de ellos, pero cuando elaboré las pruebas de funcionamiento simplemente la cosa no andaba, así que corté por lo sano y eliminé los tipos genéricos, haciendo que todos los atributos heredasen de KanjiStringPair
y KanjiStringListEntry
, lo cual solucionó el problema.
Responder a las otras dos nos costará un poco más. Recordemos lo siguiente sobre las bases de datos Objeto-Relacional:
equals
de cada clase.KanjiStringPair
Estas afirmaciones generan problemas al buscar objetos usando como criterio una propiedad de éste referida a un contenedor. Pondremos un ejemplo para ilustrar el caso, imaginemos las siguientes clases:
Y la siguiente instancia de ClaseA
:
Si almacenamos el objeto anterior en la base de datos de Neodatis, lo haría de la siguiente manera:
Como vemos por (1), Neodatis ha extraido las clases no básicas contenidas en ClaseA
, es decir, ha extraído todas las instancias de ClaseB
contenidas en ClaseA
obviando los tipos básicos y contenedores que son List
e Integer
, los cuales son solo accesibles desde la clase que los contiene. Todos están ahora en el mismo saco, visibles al mismo nivel.
Ahora imaginemos que queremos ejecutar la siguiente query escrita en lenguaje natural sobre la base de datos anterior:
Busca todas las instancias de ClaseA
tal que su atributo contenedor listaClaseB_2
contenga una instancia de ClaseB
tal que su propiedad “entero1
” sea menor que “2″ y su propiedad “entero2
” tenga un valor cualquiera.
Por (2), solo podríamos hacer consultas que nos devolviesen objetos de ClaseA
o de ClaseB
. Si hacemos una consulta sobre ClaseA
, debido a (4) la única manera que se nos ocurre de obtener las instancias deseadas es usar un contains
sobre el atributo listaClaseB_2
de ClaseA
. Las queries de este tipo se se escribirían:
Busca todas las instancias de la clase tal que su atributo contenedor
; contenga una instancia de
que sea igual a esta instancia de
que te doy.
Y aquí tenemos el primer problema. En la parte en negrita de la query, se especifica que para usar contains
necesitamos especificar un objeto de ejemplo, de forma que la base de datos pueda comparar todas las instancias de contenidas en
con el objeto que le otorgamos. Esto significa, primero, que debido a (4) solo podremos hacer consultas sobre la igualdad (y no, por ejemplo, sobre desigualdades como “mayor que” o “menor que”); y segundo, que debido a que necesitamos un objeto de ejemplo en el cual todas sus variables estén definidas y a que por (3) el criterio de igualdad usado será la igualdad de todas sus propiedades, no podremos seleccionar un objeto contenido en una lista por solo una de sus propiedades, sino que deberemos definir el valor que tendrá cada una de ellas. Por lo tanto será absolutamente imposible ejecutar la query deseada, a lo sumo podríamos hacer algo parecido a esto:
Busca todas las instancias de la clase ClaseA
tal que su atributo contenedor listaClaseB_2
contenga una instancia de ClaseB
que sea igual a esta instancia de ClaseB
que te doy, que tiene como atributos “entero1
” igual a “2″ y “entero2
” igual a “7″.
La solución
Vamos a modificar las clases ClaseA
y ClaseB
, haciéndolas heredar de una clase ReferenciaA
que les obliga a tener un atributo de tipo entero llamado “referencia
” que inicializaremos al mismo valor(por ejemplo, 100) tanto en ClaseA
como en todas las subclases contenidas en ClaseA
. La base de datos quedaría ahora:
Ahora podemos resolver la query dividiéndola en dos, primera una sobre los objetos de ClaseB
y luego otra sobre los de ClaseA
en función de los resultados de la primera. Dado que Neodatis si permite búsquedas en igualdades y desigualdades sobre atributos que no son listas (como Integer
), ahora podremos hacer:
Busca todas las instancias de la clase ClaseB
tal que su atributo “entero2
” sea menor que “2″.
Obtenemos un conjunto de objetos ClaseB. A continuación, obtenemos una lista de enteros, llamada por ejemplo listaReferencias que contenga la intersección de todos los valores del atributo “referencia”, quedado de la forma listaReferencias =[ref1, ref2, ref3,...]. Ahora podemos hacer la siguiente query:
Busca todas las instancias de la clase ClaseA
tal que su atributo “referencia
” sea igual que ref1 o su atributo “referencia
” sea igual que ref2 o su atributo “referencia
” sea igual que ref3 o …
Obteniendo así las instancias de ClaseA
según los criterios deseados.
Esto es casi lo mismo que hacemos en JavaDiKt. Creamos una interfaz KanjiReference
la cual es implementada por todas las clases que están contenidas en una instancia de Kanji
, lo que significa que estas clases adquieren el compromiso de tener un valor entero que será accesible mediante getUnicodeRef()
que representará una referencia dicho objeto Kanji
. Esa referencia la consideramos, además como la clave primaria del tipo Kanji
, que representa al código unicode de cada kanji. Respondida la tercera pregunta, solo nos queda una.
Los más avispados se habrán dado cuenta que esta solución puede no funcionar del todo bien en ciertos casos. Volviendo al ejemplo, imaginemos un objeto del tipo ClaseB
cuyo atributo “entero1
” es igual a “1″ y su atributo “referencia
” es igual a “100″, y otro objeto del tipo ClaseB
cuyo atributo “entero1
” es igual a “0″ y su atributo “referencia
” es igual a “155″. El primer objeto está contenido en el contendor listaClaseB_1
de un objeto ClaseA
cuya referencia es “100″ y el segundo en el contenedor “listaClaseB_2
” de un objeto ClaseA
cuya referencia es “150″. ¡La query propuesta anteriormente devolvería ambas clases cuando solo debería devolver la primera! Esto es debido a que los objetos de ambas listas son del mismo tipo, y hacemos la búsqueda sobre todos ellos. Además, hablando ya en cuestiones de eficiencia, de esta manera estaríamos realizando la búsqueda sobre un grupo grande de objetos cuando en realidad solo queremos hacerlo sobre un grupo reducido de ellos.
¿La solución? Clases distintas para objetos contenidos en listas distintas. Veamos como quedaría el ejemplo tras todas las modificaciones:
Y la base de datos:
Y ahora la query propuesta si que devuelve los resultados buscados gracias a (2). De la misma manera, en el paquete data.kanji
hay ciertas clases que se diferencian de otras solo por el nombre para evitar confusiones entre las búsquedas y para aumentar el rendimiento de la base de datos. Respondemos así a la última pregunta, la primera.
Consideraciones adicionales
Todo lo que hemos hecho anteriormente respecto a la asignación de una variable para contener referencias viene implementado por defecto en Neodatis mediante el OID, o en inglés Object Identifier(supongo), que es un número entero que identifica unívocamente a cada objeto, sea de la clase que sea, dentro de la base de datos. Sin embargo, decidí usar mi propio sistema de referencias mediante el código unicode porque pensé que era más lógico que los kanjis estuviesen organizados por una clave primaria característica.
Finalmente, echemos un vistazo a la lista de enteros contenida en ClaseA
. Anteriormente, utilizando la clase ClaseB
, dimos un un rodeo para conseguir busquedas mediante desigualdades para propiedades contenidas en listas dentro de ClaseA
. Pero, ¿Qué ocurre si queremos buscar mediante desigualdades en listas de tipos básicos, como puede ser la lista de enteros contenida en listaEntero? Pues simple y llanamente, no se puede hacer de ninguna manera eficiente. Ésta es una limitación importante y creo que subsanable que lastra a Neodatis y que por suerte no supone problemas importantes para JavaDiKt.
Con esto terminamos la entrada de hoy, en la próxima entrada empezaremos a hablar sobre el paquete data.dict
y la interfaz de construcción de queries en lenguaje natural.
Buenas a todos,
Despues de estar algo más de una semana buscando materiales para poder hacer una pata y empezar a programar código, he descubierto que los perfiles de aluminio que se venden, o son muy caros, y te lo venden al por mayor. Y ninguno de los dos me valen.
La solución que he encontrado para esto, es utilizar la carcasa de un sobremesa viejo e inservible, cortando y moldeando una a una cada pieza. Es algo rudimentario y farragoso, pero es la solución más viable si quiero piezas resistentes y algo flexibles de metal a un precio más que módico.
El problema es que el tiempo de construcción por cada pieza se puede echar entre 30 y 50 minutos. Y cada pata tiene del orden de 4 – 6 piezas (según el tipo de anclaje al soporte), y el HXBot tiene seis patas. No hace falta multiplicar para ver que son muchas horas de trabajo. De momento sólo tengo 3 piezas de una pata.
En el momento en que tenga una pata construida, subo fotos y primeros códigos.
Un saludo!
La verdad es que el proyecto Robocomp es bastante activo y en la lista de correo se suelen ver varios commits al día, esta actividad supone algunos problemas, sobre todo respecto al tema de direcctorios que en algunas ocasiones los componentes usan rutas del directorio personal del administrador de dicho componente. Otro de los problemas [...]
Empezamos a entrar en materia, hoy voy a detallar el entorno de programación que estoy utilizando para desarrollar Wii Pang, y los pasos necesarios para instalarlo y poder compilar y ejecutar el código que se encuentra en la Forja.
Como sistema operativo se puede emplear tanto Windows como Linux; yo utilizo una distribución Ubuntu 9.10, y voy a redactar este artículo basándome en ella, pero es aplicable a cualquier otra distribución.
No es necesario que tengamos instalado ningún compilador de C++, ya que en DevKitPro vienen incluidas todas las herramientas necesarias para poder trabajar en código Wii.
En primer lugar, procedemos a preparar la base de la compilación de este lenguaje para Nintendo Wii. Esta base consiste en el conjunto de herramientas DevKitPro (click en el nombre para acceder a SourceForge). Necesitamos los siguientes paquetes:
devkitPPC / previous / devkitPPC release 21 / devkitPPC_r21-i686-linux.tar.bz2
libogc / previous / libogc-1.8.4.tar.bz2
libfat / libfat-ogc-1.0.7.tar.bz2
Detalle a comentar es que no utilizo las últimas releases de DevKitPPC ni de libogc, debido a que me he familiarizado con las versiones que sugiero (además de que proporcionan la potencia suficiente, y de sobra, para el desarrollo que pretendo), y, por eso, Wii Pang se va a basar en ellas.
Por otro lado, necesitamos la biblioteca gráfica screenlib, creada por Hermes (entuwii.net y elotrolado.net), pero que no es necesario descargar, ya que la he incluido como biblioteca local.
Una vez descargados todos los paquetes, creamos (con la orden sudo) la siguiente estructura de directorios:
/opt/devkitpro
/opt/devkitpro/devkitPPC
/opt/devkitpro/libogc
Siguiente paso, asignar permisos suficientes para que cualquier usuario del sistema pueda utilizar dichos directorios:
sudo chmod 777 /opt/devkitpro
Ahora, nos vamos al directorio /opt/devkitpro, y desempaquetamos el DevKitPpc con la siguiente orden:
tar -xvjf /ruta/al/archivo/devkitPPC_r21-i686-linux.tar.bz2
Ya queda menos… Vamos a instalar ahora la libogc y la libfat, para lo cual, nos vamos al directorio /opt/devkitpro/libogc, y desempaquetamos la biblioteca con las ordenes:
tar -xvjf /ruta/al/archivo/libogc-1.8.4.tar.bz2
tar -xvjf /ruta/al/archivo/libfat-ogc-1.0.7.tar.bz2
El último paso para poder compilar el proyecto es establecer variables de entorno en las que el sistema sepa dónde encontrar devkitppc y devkitpro. Para ello, basta con añadir a nuestro archivo ~/.bashrc las siguientes líneas al final:
export DEVKITPRO=/opt/devkitpro
export DEVKITPPC=$DEVKITPRO/devkitPPC
Y con esto y un bizcocho, tenemos las herramientas necesarias para compilar la versión de los repositorios de Wii Pang.
Pero eso no es todo, amigos. Con lo explicado hasta aquí, podemos generar un archivo ejecutable con extensión dol, que debemos colocar en la tarjeta SD, y ejecutarlo en la Wii por el método preferido por cada uno (yo recomiendo HomeBrew Channel).
Ciertamente, es una tarea tediosa (cuanto menos) el pasar el .dol a la SD, insertar la SD en la consola, ejecutar, etc. para probar cada compilación. Podemos librarnos de este contratiempo si tenemos la Wii conectada a la misma LAN en la que esté nuestro puesto de desarrollo. Basta con hacer uso de la herramienta Wiiload, para cargar directamente el boot.dol generado en el HomeBrew Channel. (Más información sobre esta maravillosa herramienta haciendo click en el nombre)
Y ahora sí, doy por concluida la entrada, espero que esté más o menos claro cómo preparar un entorno de desarrollo para Nintendo Wii. Puede que en el futuro cree un script para dejarlo todo listo sin comerse tanto la cabeza, pero de momento, hay que hacerlo de modo manual.
En la siguiente entrada, hablaré de la estructura de directorios de un proyecto C++ para Nintendo Wii, y del Makefile necesario para compilarlo.
¡Hasta la próxima!
En un primer momento he instalado Mantis Bug Tracker ya que sólo necesita PHP y MySQL para funcionar.
Más tarde me he dado cuenta de que http://forja.rediris.es tiene un sistema de Registros y Tareas que pueden servirme : p
He creado un registro llamado Bugs y una tarea llamada Desarrollo. En ámbas iré creando entradas asociadas a la versión en la que esté trabajando, y a la hora de hacer commits en lugar de utilizar una descripción escribiré:
-bugxxx
-desxxx
Siendo xxx el número identificativo del bug o la tarea creada : )