Hola
Para hacer correr NoMachine NX 3.5 entre dos máquinas ubuntu 14.04 LTS con el escritorio XFCE tenemos que:
1) Instalar en ambas máquinas NX
nxclient_3.5.0-7_amd64.deb
nxnode_3.5.0-9_amd64.deb
nxserver_3.5.0-11_amd64.deb
2) Instalar en ambas máquinas xfce4
sudo apt-get install xfce4
3) Configurar en el cliente la conexión:
Login: id-usuario
Password: contraseña
En el área de configuración rellenaremos :
Server: IP de nuestro server
Port: 22
Desktop: Unix/Custom
En el botón settings ajustamos:
Run the following command: /usr/sbin/lightdm-session "startxfce4"
Options: New virtual desktop
4) Dado que conectamos por el puerto 22, deberemos verificar que tenemos instalado ssh en ambas máquinas:
Server: sudo apt-get install openssh-server
Client: sudo apt-get install openssh-client
Nota. XFCE es un escritorio muy ligero y rápido usado en muchas distribuciones y especialmente aconsejable para ahorrar memoria y recursos en el ordenador.
Un saludo
Páginas
viernes, 3 de octubre de 2014
Ubuntu 14.04 + NoMachine NX 3.5 + XFCE
martes, 23 de septiembre de 2014
Acceder a https://notificaciones.060.es desde Linux
Hola
En la página de https://notificaciones.060.es se carga un applet para firmar diversas acciones: aceptar una notificación, cambiar datos personales, etc. La cuestión es que dicho applet no accede al almacen de certificados del navegador, sino al almacen de certificados de la máquina virtual de Java.
En las versiones más antiguas de Java, podíamos añadir certificados desde la consola 'javaws -viewer' pero en las últimas versiones ésta opción ha desaparecido, no obstante el almacen de certificados sigue existiendo.
Dicho almacen lo encontramos en:
/home/usuarioxxx/.java/deployment/security/trusted.clientcerts
Para meter tu certificado personal en dicho almacen deberás ejecutar el siguiente comando adecuadamente ajustado:
keytool -importkeystore -srckeystore /xxxx/xxxx/xxxx/certificado.p12 -srcstoretype pkcs12 -destkeystore /home/usuarioxxx/.java/deployment/security/trusted.clientcerts
certificado.p12 es el almacen de certificados con tu clave pública y tu clave privada que habríamos exportado previamente desde nuestro navegador.
Nota. La password del almacen destino trusted.clientcerts es normalmente changeit
Un saludo
En la página de https://notificaciones.060.es se carga un applet para firmar diversas acciones: aceptar una notificación, cambiar datos personales, etc. La cuestión es que dicho applet no accede al almacen de certificados del navegador, sino al almacen de certificados de la máquina virtual de Java.
En las versiones más antiguas de Java, podíamos añadir certificados desde la consola 'javaws -viewer' pero en las últimas versiones ésta opción ha desaparecido, no obstante el almacen de certificados sigue existiendo.
Dicho almacen lo encontramos en:
/home/usuarioxxx/.java/deployment/security/trusted.clientcerts
Para meter tu certificado personal en dicho almacen deberás ejecutar el siguiente comando adecuadamente ajustado:
keytool -importkeystore -srckeystore /xxxx/xxxx/xxxx/certificado.p12 -srcstoretype pkcs12 -destkeystore /home/usuarioxxx/.java/deployment/security/trusted.clientcerts
certificado.p12 es el almacen de certificados con tu clave pública y tu clave privada que habríamos exportado previamente desde nuestro navegador.
Nota. La password del almacen destino trusted.clientcerts es normalmente changeit
Un saludo
martes, 1 de julio de 2014
Instalación y prueba de SonarQube con PostgreSQL 9.1
Hola
Hemos probado SonarQube 4.3.2 sobre PostgreSQL 9.1, como herramienta de análisis de calidad del código.
Ésta entrada recoge los pasos a dar para instalar el portal sonar, el analizador sonar-runner y realizar el análisis sobre un proyecto maven multimodular con Spring, Hibernate, JSF y Facelets.
1) Instalamos el servidor PostgreSQL 9.1 con el comando:
sudo apt-get install postgresql
2) Instalamos la consola de administración del servidor con el comando:
sudo apt-get install pgadmin3
3) Creamos una base de datos llamada sonar.
4) Creamos un usuario sonar con password sonar y con permisos de superusuario sobre la base de datos anterior.
5) Descargamos sonar de la página http://www.sonarqube.org/downloads/ en éste ejemplo hemos bajado la versión 4.3.2.
6) Descomprimimos el zip por ejemplo en nuestro $HOME.
7) Seguimos los pasos del tutorial de instalación de la página http://docs.codehaus.org/display/SONAR/Installing
- Editamos el fichero $HOME/sonarqube-4.3.2/conf/sonar.properties
- Comentamos la cadena de conexión definida para la BBDD H2, que viene activada por defecto
#sonar.jdbc.url=jdbc:h2:tcp://localhost:9092/sonar
- Descomentamos y ajustamos la cadena de conexión correspondiente a la BBDD PostgreSQL
sonar.jdbc.username=sonar
sonar.jdbc.password=sonar
sonar.jdbc.url=jdbc:postgresql://localhost:5432/sonar
- Ajustamos los parámetros de configuración del servidor web
sonar.web.host=localhost
sonar.web.context=/sonar
sonar.web.port=9000
- Ajustamos los parámetros de conexión a internet para el update-center, que permitirá que sonar se baje los plugins necesarios para analizar proyectos en varios lenguajes.
sonar.updatecenter.activate=true
http.proxyHost=xxx.xxx.xxx.xxx
http.proxyPort=zzz
http.proxyUser=usuario
http.proxyPassword=password
- Levantamos sonar mediante el comando $HOME/sonarqube-4.3.2/bin/linux-x86-64/sonar.sh start
- Vigilamos el contenido del fichero $HOME/sonarqube-4.3.2/logs/sonar.log por si hubiese errores. Si todo va bien deberíamos ver que se han generado 51 tablas en nuestro esquema de BBDD.
8) Accedemos a la URL del servidor Sonar en nuestro navegador:
http://127.0.0.1:9000/sonar/
9) Ahora queremos analizar un proyecto java, para ello nos autenticamos en el portal con admin/admin
10) Entramos en Settings/Update Center para verificar si tenemos o no instalado el plugin para el lenguaje de programación que vamos a analizar. En nuestro caso proyectos Java (1.6/1.7) con Maven 2.2.1. En la pestaña 'Installed Plugins' veremos que ya tenemos Java. En la pestaña 'Available Plugins' podremos elegir muchos más, concretamente para nuestros proyectos no interesan:
- Artifact Size
- Checkstyle
- PDF Report
- CSS
- JavaScript
- Web
- XML
Tras instalar todos éstos plugins deberemos reiniciar Sonar con los comandos:
$HOME/sonarqube-4.3.2/bin/linux-x86-64/sonar.sh stop
$HOME/sonarqube-4.3.2/bin/linux-x86-64/sonar.sh start
Nota. Hay montones de plugins adicionales que permiten conectar Sonar con LDAP para autenticar a los usuarios del portal, con JIRA para gestión de errores en las aplicaciones analizadas, con JMeter para publicar los resultados de pruebas de rendimiento en Sonar, etc.
11) Instalamos el analizador de código 'SonarQube Runner', para ello:
- Lo descargamos de: http://repo1.maven.org/maven2/org/codehaus/sonar/runner/sonar-runner-dist/2.4/sonar-runner-dist-2.4.zip
- Lo descomprimimos en $HOME/sonar-runner-2.4
- Ajustamos el fichero de configuración: $HOME/sonar-runner-2.4/conf/sonar-runner.properties
sonar.host.url=http://localhost:9000/sonar
sonar.jdbc.url=jdbc:postgresql://localhost:5432/sonar
sonar.jdbc.username=sonar
sonar.jdbc.password=sonar
- Definimos la variable de entorno SONAR_RUNNER_HOME en nuestro fichero .profile y ajustamos la variable PATH del entorno:
SONAR_RUNNER_HOME=/home/egdepedro/sonar-runner-2.4
export SONAR_RUNNER_HOME
PATH="$SONAR_RUNNER_HOME/bin:$PATH"
- Reiniciamos la sesión para activar las variables de entorno.
- Probamos que todo haya quedado bien instalado con el comando:
egdepedro@oberon:~$ sonar-runner -h
INFO:
INFO: usage: sonar-runner [options]
INFO:
12) Ahora vamos a analizar uno de nuestros proyectos, para ello:
- Añadimos en la raíz del mismo, al mismo nivel que el fichero pom.xml, el fichero 'sonar-project.properties' con el siguiente contenido:
# Required metadata
sonar.projectKey=prueba
sonar.projectName=prueba
sonar.projectVersion=1.0
# Some properties that will be inherited by the modules
sonar.sources=src
# List of the module identifiers
sonar.modules=prueba-web,prueba-batch,prueba-ws,prueba-comun
- Levantamos el servidor sonar con el comando
$HOME/sonarqube-4.3.2/bin/linux-x86-64/sonar.sh start
- Nos movemos al directorio raíz del proyecto, donde hemos colocado el fichero 'sonar-project.properties' y lanzamos el comando:
sonar-runner
- Con ésto veremos que se va ejecutando en análisis sobre cada uno de los módulos de nuestro proyecto
13) Ahora volvemos a conectar al servidor sonar: http://127.0.0.1:9000/sonar/ y en el menú Projects podremos ver un nuevo proyecto 'prueba' con el resultado del análisis.
Referencias
http://docs.codehaus.org/display/SONAR/Installing
http://docs.codehaus.org/display/SONAR/Provisioning+Projects
http://docs.codehaus.org/display/SONAR/Analyzing+Source+Code
http://docs.codehaus.org/display/SONAR/Installing+and+Configuring+SonarQube+Runner
http://docs.codehaus.org/display/SONAR/Analyzing+with+SonarQube+Runner
Hemos probado SonarQube 4.3.2 sobre PostgreSQL 9.1, como herramienta de análisis de calidad del código.
Ésta entrada recoge los pasos a dar para instalar el portal sonar, el analizador sonar-runner y realizar el análisis sobre un proyecto maven multimodular con Spring, Hibernate, JSF y Facelets.
1) Instalamos el servidor PostgreSQL 9.1 con el comando:
sudo apt-get install postgresql
2) Instalamos la consola de administración del servidor con el comando:
sudo apt-get install pgadmin3
3) Creamos una base de datos llamada sonar.
4) Creamos un usuario sonar con password sonar y con permisos de superusuario sobre la base de datos anterior.
5) Descargamos sonar de la página http://www.sonarqube.org/downloads/ en éste ejemplo hemos bajado la versión 4.3.2.
6) Descomprimimos el zip por ejemplo en nuestro $HOME.
7) Seguimos los pasos del tutorial de instalación de la página http://docs.codehaus.org/display/SONAR/Installing
- Editamos el fichero $HOME/sonarqube-4.3.2/conf/sonar.properties
- Comentamos la cadena de conexión definida para la BBDD H2, que viene activada por defecto
#sonar.jdbc.url=jdbc:h2:tcp://localhost:9092/sonar
- Descomentamos y ajustamos la cadena de conexión correspondiente a la BBDD PostgreSQL
sonar.jdbc.username=sonar
sonar.jdbc.password=sonar
sonar.jdbc.url=jdbc:postgresql://localhost:5432/sonar
- Ajustamos los parámetros de configuración del servidor web
sonar.web.host=localhost
sonar.web.context=/sonar
sonar.web.port=9000
- Ajustamos los parámetros de conexión a internet para el update-center, que permitirá que sonar se baje los plugins necesarios para analizar proyectos en varios lenguajes.
sonar.updatecenter.activate=true
http.proxyHost=xxx.xxx.xxx.xxx
http.proxyPort=zzz
http.proxyUser=usuario
http.proxyPassword=password
- Levantamos sonar mediante el comando $HOME/sonarqube-4.3.2/bin/linux-x86-64/sonar.sh start
- Vigilamos el contenido del fichero $HOME/sonarqube-4.3.2/logs/sonar.log por si hubiese errores. Si todo va bien deberíamos ver que se han generado 51 tablas en nuestro esquema de BBDD.
8) Accedemos a la URL del servidor Sonar en nuestro navegador:
http://127.0.0.1:9000/sonar/
9) Ahora queremos analizar un proyecto java, para ello nos autenticamos en el portal con admin/admin
10) Entramos en Settings/Update Center para verificar si tenemos o no instalado el plugin para el lenguaje de programación que vamos a analizar. En nuestro caso proyectos Java (1.6/1.7) con Maven 2.2.1. En la pestaña 'Installed Plugins' veremos que ya tenemos Java. En la pestaña 'Available Plugins' podremos elegir muchos más, concretamente para nuestros proyectos no interesan:
- Artifact Size
- Checkstyle
- PDF Report
- CSS
- JavaScript
- Web
- XML
Tras instalar todos éstos plugins deberemos reiniciar Sonar con los comandos:
$HOME/sonarqube-4.3.2/bin/linux-x86-64/sonar.sh stop
$HOME/sonarqube-4.3.2/bin/linux-x86-64/sonar.sh start
Nota. Hay montones de plugins adicionales que permiten conectar Sonar con LDAP para autenticar a los usuarios del portal, con JIRA para gestión de errores en las aplicaciones analizadas, con JMeter para publicar los resultados de pruebas de rendimiento en Sonar, etc.
11) Instalamos el analizador de código 'SonarQube Runner', para ello:
- Lo descargamos de: http://repo1.maven.org/maven2/org/codehaus/sonar/runner/sonar-runner-dist/2.4/sonar-runner-dist-2.4.zip
- Lo descomprimimos en $HOME/sonar-runner-2.4
- Ajustamos el fichero de configuración: $HOME/sonar-runner-2.4/conf/sonar-runner.properties
sonar.host.url=http://localhost:9000/sonar
sonar.jdbc.url=jdbc:postgresql://localhost:5432/sonar
sonar.jdbc.username=sonar
sonar.jdbc.password=sonar
- Definimos la variable de entorno SONAR_RUNNER_HOME en nuestro fichero .profile y ajustamos la variable PATH del entorno:
SONAR_RUNNER_HOME=/home/egdepedro/sonar-runner-2.4
export SONAR_RUNNER_HOME
PATH="$SONAR_RUNNER_HOME/bin:$PATH"
- Reiniciamos la sesión para activar las variables de entorno.
- Probamos que todo haya quedado bien instalado con el comando:
egdepedro@oberon:~$ sonar-runner -h
INFO:
INFO: usage: sonar-runner [options]
INFO:
12) Ahora vamos a analizar uno de nuestros proyectos, para ello:
- Añadimos en la raíz del mismo, al mismo nivel que el fichero pom.xml, el fichero 'sonar-project.properties' con el siguiente contenido:
# Required metadata
sonar.projectKey=prueba
sonar.projectName=prueba
sonar.projectVersion=1.0
# Some properties that will be inherited by the modules
sonar.sources=src
# List of the module identifiers
sonar.modules=prueba-web,prueba-batch,prueba-ws,prueba-comun
- Levantamos el servidor sonar con el comando
$HOME/sonarqube-4.3.2/bin/linux-x86-64/sonar.sh start
- Nos movemos al directorio raíz del proyecto, donde hemos colocado el fichero 'sonar-project.properties' y lanzamos el comando:
sonar-runner
- Con ésto veremos que se va ejecutando en análisis sobre cada uno de los módulos de nuestro proyecto
13) Ahora volvemos a conectar al servidor sonar: http://127.0.0.1:9000/sonar/ y en el menú Projects podremos ver un nuevo proyecto 'prueba' con el resultado del análisis.
Referencias
http://docs.codehaus.org/display/SONAR/Installing
http://docs.codehaus.org/display/SONAR/Provisioning+Projects
http://docs.codehaus.org/display/SONAR/Analyzing+Source+Code
http://docs.codehaus.org/display/SONAR/Installing+and+Configuring+SonarQube+Runner
http://docs.codehaus.org/display/SONAR/Analyzing+with+SonarQube+Runner
Eliminar todos los directorios .svn de un proyecto
Hola
Para eliminar de un cierto proyecto java todas las carpetas .svn de cada una de las subcarpetas que componen el proyecto lo más útil es lanzar un comando unix:
1) Nos movemos a la raíz del proyecto
2) Lanzamos el comando:
find -type d -name '.svn' -exec rm -rfv {} \;
Para eliminar del mismo proyecto los ficheros de cierto tipo. por ejemplo .project el comando es:
find . -type f -name "*.project" -delete
Para eliminar de un cierto proyecto java todas las carpetas .svn de cada una de las subcarpetas que componen el proyecto lo más útil es lanzar un comando unix:
1) Nos movemos a la raíz del proyecto
2) Lanzamos el comando:
find -type d -name '.svn' -exec rm -rfv {} \;
Para eliminar del mismo proyecto los ficheros de cierto tipo. por ejemplo .project el comando es:
find . -type f -name "*.project" -delete
Ejecutar aplicaciones X de otra máquina en local
Hola
Cuando queremos ejecutar algún aplicativo que precise de un sistema de ventanas en un servidor donde no esté instalado/levantado el servidor x-windows por ejemplo para ahorrar recursos, podemos utilizar el servidor x-windows de nuestra máquina Ubuntu para hacerlo.
Supondremos que la IP de nuestra máquina es XXX.XXX.XXX.XXX y que la IP de la máquina remota es ZZZ.ZZZ.ZZZ.ZZZ
A partir de aquí los pasos son sencillos:
1) Permitimos que la máquina remota acceda a nuestro servidor X lanzando en nuestra máquina el comando:
xhost ZZZ.ZZZ.ZZZ.ZZZ
2) Verificamos el valor de la variable DISPLAY de nuestra máquina con el comando:
echo $DISPLAY --> 0.0
3) Nos conectamos a la máquina remota con el comando:
ssh usuario@ZZZ.ZZZ.ZZZ.ZZZ
4) Redirigimos la salida gráfica de la máquina remota a nuestro servidor x-windows ejecutando en la máquina remota el comando:
export DISPLAY=XXX.XXX.XXX.XXX:0.0
5) Levantamos en la máquina remota el aplicativo gráfico que queremos visualizar en local, por ejemplo xclock, con lo que veremos que en nuestro equipo aparece el reloj.
Nota. Para eliminar el permiso de uso de nuestro servidor x-windows otorgado a la máquina ZZZ.ZZZ.ZZZ.ZZZ deberíamos ejecutar:
xhost -ZZZ.ZZZ.ZZZ.ZZZ
Un saludo
Cuando queremos ejecutar algún aplicativo que precise de un sistema de ventanas en un servidor donde no esté instalado/levantado el servidor x-windows por ejemplo para ahorrar recursos, podemos utilizar el servidor x-windows de nuestra máquina Ubuntu para hacerlo.
Supondremos que la IP de nuestra máquina es XXX.XXX.XXX.XXX y que la IP de la máquina remota es ZZZ.ZZZ.ZZZ.ZZZ
A partir de aquí los pasos son sencillos:
1) Permitimos que la máquina remota acceda a nuestro servidor X lanzando en nuestra máquina el comando:
xhost ZZZ.ZZZ.ZZZ.ZZZ
2) Verificamos el valor de la variable DISPLAY de nuestra máquina con el comando:
echo $DISPLAY --> 0.0
3) Nos conectamos a la máquina remota con el comando:
ssh usuario@ZZZ.ZZZ.ZZZ.ZZZ
4) Redirigimos la salida gráfica de la máquina remota a nuestro servidor x-windows ejecutando en la máquina remota el comando:
export DISPLAY=XXX.XXX.XXX.XXX:0.0
5) Levantamos en la máquina remota el aplicativo gráfico que queremos visualizar en local, por ejemplo xclock, con lo que veremos que en nuestro equipo aparece el reloj.
Nota. Para eliminar el permiso de uso de nuestro servidor x-windows otorgado a la máquina ZZZ.ZZZ.ZZZ.ZZZ deberíamos ejecutar:
xhost -ZZZ.ZZZ.ZZZ.ZZZ
Un saludo
domingo, 29 de junio de 2014
Utilizar galternatives en Ubuntu 14.04 LTS
Hola
En Ubuntu 14.04 LTS ha dejado de guncionar galternatives, herramienta muy versatil a la hora de ajustar, por ejemplo, qué entorno java queremos utilizar en nuestro equipo.
Por lo que parece el problema radica en que el código de galternatives apunta a fuego al path siguiente: /usr/sbin/update-alternatives, pero en la versión 14.04 de Ubuntu update-alternatives ha sido reubicado a /usr/bin/ update- alternatives
La forma más rápida de solventarlo es:
1) Nos movemos a la carpeta /usr/sbin
2) Creamos un enlace a /usr/bin/ update- alternatives
sudo ln -s /usr/bin/update-alternatives update-alternatives
Con éste miniajuste, ya podemos ejecutar con normalidad:
sudo galternatives
Y configurar nuestras alternativas con comodidad
Referencias
https://bugs.launchpad.net/ubuntu/+source/galternatives/+bug/1309709
En Ubuntu 14.04 LTS ha dejado de guncionar galternatives, herramienta muy versatil a la hora de ajustar, por ejemplo, qué entorno java queremos utilizar en nuestro equipo.
Por lo que parece el problema radica en que el código de galternatives apunta a fuego al path siguiente: /usr/sbin/update-alternatives, pero en la versión 14.04 de Ubuntu update-alternatives ha sido reubicado a /usr/bin/
La forma más rápida de solventarlo es:
1) Nos movemos a la carpeta /usr/sbin
2) Creamos un enlace a /usr/bin/
sudo ln -s /usr/bin/update-alternatives update-alternatives
Con éste miniajuste, ya podemos ejecutar con normalidad:
sudo galternatives
Y configurar nuestras alternativas con comodidad
Referencias
https://bugs.launchpad.net/ubuntu/+source/galternatives/+bug/1309709
miércoles, 18 de junio de 2014
HUAWEI E3331 en Ubuntu 14.04
Hola
Instalar HUAWEI E3331 en Ubuntu 14.04 en Ubuntu 12.04 nos ha resultado por el momento imposible, así que hemos decidido probar la instalación en Ubuntu 14.04 y parece que funciona, pero de una forma muy poco convencional. El resumen de pasos es:
1) Conectamos el pincho a un puerto USB
2) Abrimos el navegador e intentamos acceder a cualquier página/enlace, por ejemplo: http://www.google.com si no intentamos una conexión nada.
3) Se nos cargará automáticamente la URL: http://192.168.1.1/html/pincoderequired.html?index donde:
- Insertamos el PIN
- Pulsamos Conectar
4) Tras unos instantes se cargará la página: http://192.168.1.1/html/home.html donde:
- Tenemos la opción desconectar
- Vemos los datos de velocidad de subida/bajada
- Vemos los datos de consumo de la sesión y totales (pueden resetearse)
- Podemos deshabilitar/habilitar la solicitud del PIN en sesiones posteriores
- Podemos cambiar el PIN
- etc
5) Para finalizar la sesión accedemos a la página http://192.168.1.1/html/home.html, pulsamos desconectar y quitamos el stick del puerto USB
Conclusiones
Mientras permanecemos conectados vía 3G parece que no están disponibles las restantes conexiones de red, juas juas juas. De hecho el pincho nunca aparece en el gestor de conexiones a red de Ubuntu, parece que sí o sí se gestiona desde la URL.
Referencias:
http://vxlabs.com/2014/06/15/huawei-e3331-3g-usb-dongle-works-on-ubuntu-14-04-linux/
domingo, 25 de mayo de 2014
Aprobar exámenes PMP 5
Presentarse al examen de certificación PMP
Para poder presentarse al examen hay que cumplir los siguientes requisitos:
Renovar la certificación PMP
La certificación PMP caduca a los tres años, por lo que si se quiere renovar hay que justificar ciertas actividades:
Libros en Español
Consejos
Hay multitud de simuladores online del examen PMP, tras unos días probando unos cuantos, los que a mi entender destacan por la calidad de las traducciones, por la cantidad de preguntas, por precio y por la agilidad de funcionamiento son:
http://es.wikipedia.org/wiki/Project_Management_Professional
https://www.youtube.com/user/portalucam/
Para poder presentarse al examen hay que cumplir los siguientes requisitos:
- Haber realizado un curso de al menos 35 horas de gestión de proyectos.
- Si se posee un título universitario superior, hay que acreditar 7.500 horas (60 meses) de experiencia en gestión de proyectos. Si se posee un título universitario medio, hay que acreditar 4.500 horas (36 meses) de experiencia en gestión de proyectos. En ambos casos, las horas deberán corresponder a proyectos no solapados realizados en los 8 años previos a la solicitud de examen.
- Prometer el código de conducta ética y profesional del PMI.
- Inicio. 13%
- Planificación. 24%
- Ejecución. 30%
- Seguimiento y control. 25%
- Cierre 8%
Renovar la certificación PMP
La certificación PMP caduca a los tres años, por lo que si se quiere renovar hay que justificar ciertas actividades:
- Haber obtenido 60 PDU en los últimos 3 años, bien en cursos o bien mediante la acreditación de otras actividades sobre la dirección de proyectos como haber escrito blogs, haber dado conferencias, etc. Todo ésto se acredita en las páginas de PMI. Nota. Un PDU equivale a 1 hora de curso.
- Introducción.
- Procesos de inicio.
- Procesos de planificación.
- Procesos de ejecución.
- Procesos de seguimiento y control.
- Procesos de cierre.
- Etica PMP.
Libros en Español
Consejos
- Al exámen hay que acudir con una tasa de acierto superior al 70%.
- A la hora de realizar el exámen no debemos entretenernos con preguntas difíciles, es mejor marcar una respuesta y marcarlas para un repaso final.
- Hay que fijarse un ritmo de respuestas, por ejemplo responder 20 preguntas cada 20 minutos nos dejaría 40 minutos al final para repasar.
- Las preguntas falladas no puntúan negativo, por lo que hay que responder todas.
Hay multitud de simuladores online del examen PMP, tras unos días probando unos cuantos, los que a mi entender destacan por la calidad de las traducciones, por la cantidad de preguntas, por precio y por la agilidad de funcionamiento son:
- http://pablolledo.net/moodle/login/index.php
- http://www.danielecheverria.com
http://es.wikipedia.org/wiki/Project_Management_Professional
https://www.youtube.com/user/portalucam/
jueves, 1 de mayo de 2014
Generar un arquetipo maven a partir del proyecto actual
Hola
Hoy vamos a comentar cómo generar un arquetipo maven de forma rápida a partir de un proyecto existente. Los pasos a dar son los siguientes:
1) Nos colocamos en el directorio del pom.xml del proyecto
2) Lanzamos el comando:
mvn archetype:create-from-project
3) El arquetipo queda en la ubicación:
target\generated-sources\archetype
4) Nos movemos a la ubicación del arquetipo y vemos que la estructura del arquetipo es:
6) En la carpeta src/main/resources tenemos dos archivos importantes:
<requiredProperties>
<requiredProperty key="groupId">
<defaultValue>org.dune.casa</defaultValue>
</requiredProperty>
<requiredProperty key="artifactId">
<defaultValue>test</defaultValue>
</requiredProperty>
<requiredProperty key="version">
<defaultValue>1.0-SNAPSHOT</defaultValue>
</requiredProperty>
<requiredProperty key="package">
<defaultValue>org.dune.casa</defaultValue>
</requiredProperty>
</requiredProperties>
8) Ajustaremos el contenido de 'archetype-resources', donde veremos un pom.xml y los diferentes módulos del proyecto (__rootArtifactId__-core, __rootArtifactId__-web, __rootArtifactId__-batch, __rootArtifactId__-ws, etc). hay dos clases de ajustes:
mvn clean install
Si ahora queremos generar un nuevo proyecto basado el en arquetipo debemos seguir estos pasos:
1) Nos vamos a una nueva carpeta como por ejemplo:
cd $HOME/wks-juno/wksTestArquetipo
2) Lanzamos el comando
mvn archetype:generate -DarchetypeGroupId=org.dune.casa -DarchetypeArtifactId=nombre-archetype -DarchetypeVersion=1.0 -DgroupId=org.dune.casa -DartifactId=nombre-proyecto
Eso es todo
Hoy vamos a comentar cómo generar un arquetipo maven de forma rápida a partir de un proyecto existente. Los pasos a dar son los siguientes:
1) Nos colocamos en el directorio del pom.xml del proyecto
2) Lanzamos el comando:
mvn archetype:create-from-project
3) El arquetipo queda en la ubicación:
target\generated-sources\archetype
4) Nos movemos a la ubicación del arquetipo y vemos que la estructura del arquetipo es:
- pom.xml
- src/
- target/
6) En la carpeta src/main/resources tenemos dos archivos importantes:
- archetype-resources. Es la plantilla del proyecto que se generará cuando se ejecute el arquetipo
- META-INF/maven. Contiene el fichero archetype-metadata.xml donde podremos definir las propiedades que se solicitarán para los proyectos generados con el arquetipo.
<requiredProperties>
<requiredProperty key="groupId">
<defaultValue>org.dune.casa</defaultValue>
</requiredProperty>
<requiredProperty key="artifactId">
<defaultValue>test</defaultValue>
</requiredProperty>
<requiredProperty key="version">
<defaultValue>1.0-SNAPSHOT</defaultValue>
</requiredProperty>
<requiredProperty key="package">
<defaultValue>org.dune.casa</defaultValue>
</requiredProperty>
</requiredProperties>
8) Ajustaremos el contenido de 'archetype-resources', donde veremos un pom.xml y los diferentes módulos del proyecto (__rootArtifactId__-core, __rootArtifactId__-web, __rootArtifactId__-batch, __rootArtifactId__-ws, etc). hay dos clases de ajustes:
- Meter comodines del tipo '__rootArtifactId__' como nombre o parte del nombre de las carpetas que se deseen personalizar.
- Meter comodines del tipo ${package}, ${parentArtifactId}, etc, en clases y ficheros de configuración.
mvn clean install
Si ahora queremos generar un nuevo proyecto basado el en arquetipo debemos seguir estos pasos:
1) Nos vamos a una nueva carpeta como por ejemplo:
cd $HOME/wks-juno/wksTestArquetipo
2) Lanzamos el comando
mvn archetype:generate -DarchetypeGroupId=org.dune.casa -DarchetypeArtifactId=nombre-archetype -DarchetypeVersion=1.0 -DgroupId=org.dune.casa -DartifactId=nombre-proyecto
Eso es todo
sábado, 26 de abril de 2014
Tres en raya (minimax)
Hola
Hace unos días asistí en el colegio de mi hija a una charla donde debía explicar a qué me dedicaba a los chavales de su clase. Como no sabía por donde meterle mano pensé en explicarles las bases de un algoritmo típico en juegos de mesa contra un openente, el minimax. El algoritmo está suficientemente explicado en muchas páginas como: http://es.wikipedia.org/wiki/Minimax
Por ello, recordando viejos tiempos de facultad me puse a programar el minimax para el juego de las tres en raya. Dejo aquí las distintas clases generadas.
Cada clase y método están suficientemente comentados como para no necesitar añadir nada mas.
1.- Lanzador del aplicativo
package org.dune.juegos;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.UIManager;
import java.awt.SystemColor;
public class TresR {
private JFrame frame;
/**
* Lanzador de la aplicación tres en raya
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
final TresR tr = new TresR();
tr.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Constructor
*/
public TresR() {
//Inicializamos entorno grafico
inicializaPantalla();
}
private void inicializaPantalla() {
//Definimos la pantalla del juego
frame = new JFrame();
frame.setBackground(SystemColor.control);
frame.getContentPane().setBackground(SystemColor.control);
frame.setBounds(100, 100, 800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
//Definimos el contenedor del tablero
final JPanel cajaTablero = new JPanel();
cajaTablero.setBounds(12, 71, 756, 471);
cajaTablero.setBackground(SystemColor.control);
frame.getContentPane().add(cajaTablero);
cajaTablero.setLayout(new BorderLayout(0, 0));
//Definimos la barra de menú
final JMenuBar menuBar = new JMenuBar();
menuBar.setBackground(SystemColor.control);
menuBar.setBounds(0, 0, 780, 21);
frame.getContentPane().add(menuBar);
//Definimos el menú Juego
final JMenu mJuego = new JMenu("Juego");
final JMenuItem smEmpezar = new JMenuItem("Empezar");
final JMenuItem smSalir = new JMenuItem("Salir");
mJuego.add(smEmpezar);
mJuego.add(smSalir);
menuBar.add(mJuego);
//Definimos el menú ayuda
final JMenu mAyuda = new JMenu("Ayuda");
final JMenuItem smInfo = new JMenuItem("Info");
mAyuda.add(smInfo);
menuBar.add(mAyuda);
//Definimos la acción de la opción de menú Empezar
smEmpezar.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
//Pintamos el tablero
final Tablero pTablero = new Tablero();
cajaTablero.removeAll();
cajaTablero.add(pTablero);
frame.setVisible(true);
}
});
//Definimos la acción de la opción de menú Salir
smSalir.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
//Salimos del juego
System.exit(0);
}
});
//Definimos la acción de la opción de menú info
smInfo.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
//Pintamos la pantalla de ayuda
final Info pInfo = new Info();
cajaTablero.removeAll();
cajaTablero.add(pInfo);
frame.setVisible(true);
}
});
}
}
2.- Tablero
package org.dune.juegos;
import java.awt.Button;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
public class Tablero extends JPanel implements ActionListener {
private static final long serialVersionUID = -6025639950351265124L;
//Botonera que representa el tablero
final Button botonesCasillas[][] = new Button[3][3];
//Estructura de memoria con las casillas del juego
int matrizTablero[][] = new int[3][3];
//Implementación del algoritmo minimax
final MiniMax minimax;
//Indicador de turno de jugador
boolean turnoHumano;
/**
* Constructor del panel
*/
public Tablero() {
//Define el contenido del panel
setBackground(UIManager.getColor("info"));
setLayout(new GridLayout(3, 3, 0, 0));
for (int i=0; i<3; i++) {
for (int j=0; j <3; j++) {
botonesCasillas[i][j] = new Button();
botonesCasillas[i][j].setBackground(SystemColor.control);
botonesCasillas[i][j].setFont(new Font("Arial",Font.BOLD,60));
botonesCasillas[i][j].addActionListener(this);
this.add(botonesCasillas[i][j]);
}
}
//Inicializamos variables de la partida
turnoHumano = true;
//Limpia los botones del tablero
limpiaBotones();
//Iniciamos el minimax
minimax = new MiniMax(3,3);
}
/**
* Interprete de las acciones del usuario.
*/
public void actionPerformed(ActionEvent e){
//Movimiento decidido por el ordenador
Movimiento mov;
//Si el turno era del humano
if(turnoHumano==true){
//Quitamos el turno al humano
turnoHumano = false;
//Revisa qué casilla ha pulsado
for (int i=0;i<3;i++) {
for (int j=0;j<3;j++) {
//Mira si la casilla pulsada por el humaon estaba libre
if ((e.getSource()==botonesCasillas[i][j]) && (botonesCasillas[i][j].getLabel().equals(""))){
//Pone en la casilla una P
botonesCasillas[i][j].setLabel("P");
matrizTablero[i][j] = MiniMax.CASILLA_PERSONA;
//Lanza el algoritmo minimax y recoge el movimiento elegido
mov = minimax.minimax(matrizTablero);
if (mov.getPosX()!=-1 && mov.getPosY()!=-1) {
//Introducimos un retardo
retarda(500);
//Dibujamos el movimiento del ordenador
botonesCasillas[mov.getPosX()][mov.getPosY()].setLabel("O");
matrizTablero[mov.getPosX()][mov.getPosY()]=MiniMax.CASILLA_ORDENADOR;
//Si hay ganador quito el turno al humano para que no pueda mover mas
if(minimax.haGanadoJugador(MiniMax.CASILLA_PERSONA)) {
turnoHumano=false;
JOptionPane.showMessageDialog(null, "ME HAS GANADO");
} else if (minimax.haGanadoJugador(MiniMax.CASILLA_ORDENADOR)) {
turnoHumano = false;
JOptionPane.showMessageDialog(null, "JE JE JE, SIEMPRE GANO YO...");
} else {
turnoHumano = true;
}
} else {
turnoHumano = false;
JOptionPane.showMessageDialog(null, "HEMOS VUELTO A EMPATAR");
}
}
}
}
}
}
private void retarda(int milis){
try {
Thread.sleep(milis);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
/**
* Limpia los botones del tablero
*/
private void limpiaBotones(){
for (int i=0; i<3; i++) {
for (int j=0; j <3; j++) {
botonesCasillas[i][j].setLabel("");
}
}
}
}
3.- Implementación del minimax
package org.dune.juegos;
public class MiniMax {
public static final int CASILLA_VACIA = 0;
public static final int CASILLA_PERSONA = 1;
public static final int CASILLA_ORDENADOR = 2;
private int tableroActual[][];
private int numCols;
private int numFils;
/**
* Recibe los datos del tablero de juego.
*
* @param anchura Dimensión horizontal del tablero.
* @param altura Dimensión vertical del tablero.
*/
public MiniMax(int anchura, int altura) {
super();
this.numCols = anchura;
this.numFils = altura;
this.tableroActual = new int[numCols][numFils];
}
/**
* Es el turno del ordenador y en base al tablero actual decidimos el movimiento a realizar.
*/
public Movimiento minimax(int[][] tableroParam){
this.tableroActual = tableroParam;
int posX=-1;
int posY=-1;
int aux=-9999;
int mejor=-9999;
for (int x=0;x<this.numCols;x++){
for (int y=0;y<this.numFils;y++){
if (isCasillaVacia(x,y)){
marcarCasilla(x,y,CASILLA_ORDENADOR);
aux = min();
if (aux>mejor) {
mejor=aux;
posX=x;
posY=y;
}
marcarCasilla(x,y,CASILLA_VACIA);
}
}
}
return new Movimiento(posX,posY);
}
/**
* El último jugador que marcó alguna casilla fue el ordenador, por lo que analizamos los posibles
* movimientos de la persona.
*
* Si estamos en un nodo hoja devolvemos la valoración del tablero, puede que haya ganado el ordenador
* o puede que sigamos empatados, así que hay dos posibles valores: 1 (gana el ordenador)
* y 0 (seguimos empatados).
*
* Si no es nodo hoja recorremos las casillas vacías simulando ser el jugador humano, y llamando
* a continuación al método MAX. Llamamos a MAX porque en el siguiente turno le tocará jugar a la CPU
* y nos interesa maximizar su resultado.
*/
private int min(){
if (haGanadoJugador(CASILLA_ORDENADOR)){
//Si ha ganado el ordenador devolvemos el valor del tablero
return 1;
} else if (isTableroLleno()){
//Si el tablero está lleno y no ha ganado el ordenador hemos empatado
return 0;
} else {
//Si el tablero no está lleno y no ha ganado el ordenador, recorremos todos
//los posibles movimientos restantes y los valoramos llamando a max()
int aux=9999;
int mejor=9999;
for (int x=0;x<this.numCols;x++){
for (int y=0;y<this.numFils;y++){
if (isCasillaVacia(x,y)){
marcarCasilla(x,y,CASILLA_PERSONA);
aux = max();
if (aux<mejor) {
mejor=aux;
}
marcarCasilla(x,y,CASILLA_VACIA);
}
}
}
return mejor;
}
}
/**
* El último jugador que marcó alguna casilla fue la persona, por lo que analizamos los posibles
* movimientos del ordenador.
*
* Si estamos en un nodo hoja devolvemos la valoración del tablero, puede que haya ganado la persona
* o puede que sigamos empatados, así que hay dos posibles valores: -1 (gana la persona)
* y 0 (seguimos empatados).
*
* Si no es nodo hoja recorremos las casillas vacías simulando ser el ordenador, y llamando
* a continuación al método MIN. Llamamos a MIN porque en el siguiente turno le tocará jugar al humano
* y nos interesa minimizar su resultado.
*/
private int max(){
if (haGanadoJugador(CASILLA_PERSONA)){
//Si ha ganado la persona devolvemos el valor del tablero
return -1;
} else if (isTableroLleno()){
//Si el tablero está lleno y no ha ganado la persona hemos empatado
return 0;
} else {
///Si el tablero no está lleno y no ha ganado la persona, recorremos todos
//los posibles movimientos restantes y los valoramos llamando a min()
int aux=-9999;
int mejor=-9999;
for (int x=0;x<this.numCols;x++){
for (int y=0;y<this.numFils;y++){
if (isCasillaVacia(x,y)){
marcarCasilla(x,y,CASILLA_ORDENADOR);
aux = min();
if (aux>mejor) {
mejor=aux;
}
marcarCasilla(x,y,CASILLA_VACIA);
}
}
}
return mejor;
}
}
/**
* Determina si una determinada posición del tablero está
* o no vacía.
*
* @param x. Fila de la casilla a analizar.
* @param y. Columna de la casilla a analizar.
*
* @return True cuando la casilla está vacía
*/
private boolean isCasillaVacia(int x, int y){
return tableroActual[x][y]==CASILLA_VACIA;
}
/**
* Ocupa la casilla indicada con la ficha recibida.
*
* @param x. Fila de la casilla a marcar.
* @param y. Columna de la casilla a marcar.
* @param ficha. Ficha a colocar.
*/
private void marcarCasilla(int x, int y, int ficha){
tableroActual[x][y]=ficha;
}
/**
* Determina si el tablero tiene casillas libres.
*
* @return True si hay casillas no ocupadas.
*/
private boolean isTableroLleno(){
for (int x=0;x<3;x++){
for (int y=0;y<3;y++){
if (isCasillaVacia(x,y)){
return false;
}
}
}
return true;
}
/**
* Determina si el jugador que maneja la ficha recibida
* por parámetro ha ganado la partida.
*
* @param ficha Ficha que podría haber ganado
*
* @return True cuando el jugador con la ficha recibida ha ganado.
*/
public boolean haGanadoJugador(int ficha){
//Verifica si el jugador ha ganado en las diagonales
if((tableroActual[0][0]==ficha && tableroActual[1][1]==ficha && tableroActual[2][2]==ficha)||
(tableroActual[0][2]==ficha && tableroActual[1][1]==ficha && tableroActual[2][0]==ficha)) {
return true;
} else {
//Verifica si el jugador ha ganado en una fila
for(int i=0;i<3;i++) {
if(tableroActual[i][0]==ficha && tableroActual[i][1]==ficha && tableroActual[i][2]==ficha) {
return true;
}
}
//Verifica si el jugador ha ganado en una columna
for(int i=0;i<3;i++) {
if(tableroActual[0][i]==ficha && tableroActual[1][i]==ficha && tableroActual[2][i]==ficha) {
return true;
}
}
}
return false;
}
}
4.- Clase auxiliar para manejar los movimientos
package org.dune.juegos;
public class Movimiento {
private int posX;
private int posY;
public Movimiento(int posX, int posY) {
super();
this.posX = posX;
this.posY = posY;
}
public int getPosX() {
return posX;
}
public void setPosX(int posX) {
this.posX = posX;
}
public int getPosY() {
return posY;
}
public void setPosY(int posY) {
this.posY = posY;
}
}
Hace unos días asistí en el colegio de mi hija a una charla donde debía explicar a qué me dedicaba a los chavales de su clase. Como no sabía por donde meterle mano pensé en explicarles las bases de un algoritmo típico en juegos de mesa contra un openente, el minimax. El algoritmo está suficientemente explicado en muchas páginas como: http://es.wikipedia.org/wiki/Minimax
Por ello, recordando viejos tiempos de facultad me puse a programar el minimax para el juego de las tres en raya. Dejo aquí las distintas clases generadas.
Cada clase y método están suficientemente comentados como para no necesitar añadir nada mas.
1.- Lanzador del aplicativo
package org.dune.juegos;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.UIManager;
import java.awt.SystemColor;
public class TresR {
private JFrame frame;
/**
* Lanzador de la aplicación tres en raya
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
final TresR tr = new TresR();
tr.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Constructor
*/
public TresR() {
//Inicializamos entorno grafico
inicializaPantalla();
}
private void inicializaPantalla() {
//Definimos la pantalla del juego
frame = new JFrame();
frame.setBackground(SystemColor.control);
frame.getContentPane().setBackground(SystemColor.control);
frame.setBounds(100, 100, 800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
//Definimos el contenedor del tablero
final JPanel cajaTablero = new JPanel();
cajaTablero.setBounds(12, 71, 756, 471);
cajaTablero.setBackground(SystemColor.control);
frame.getContentPane().add(cajaTablero);
cajaTablero.setLayout(new BorderLayout(0, 0));
//Definimos la barra de menú
final JMenuBar menuBar = new JMenuBar();
menuBar.setBackground(SystemColor.control);
menuBar.setBounds(0, 0, 780, 21);
frame.getContentPane().add(menuBar);
//Definimos el menú Juego
final JMenu mJuego = new JMenu("Juego");
final JMenuItem smEmpezar = new JMenuItem("Empezar");
final JMenuItem smSalir = new JMenuItem("Salir");
mJuego.add(smEmpezar);
mJuego.add(smSalir);
menuBar.add(mJuego);
//Definimos el menú ayuda
final JMenu mAyuda = new JMenu("Ayuda");
final JMenuItem smInfo = new JMenuItem("Info");
mAyuda.add(smInfo);
menuBar.add(mAyuda);
//Definimos la acción de la opción de menú Empezar
smEmpezar.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
//Pintamos el tablero
final Tablero pTablero = new Tablero();
cajaTablero.removeAll();
cajaTablero.add(pTablero);
frame.setVisible(true);
}
});
//Definimos la acción de la opción de menú Salir
smSalir.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
//Salimos del juego
System.exit(0);
}
});
//Definimos la acción de la opción de menú info
smInfo.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
//Pintamos la pantalla de ayuda
final Info pInfo = new Info();
cajaTablero.removeAll();
cajaTablero.add(pInfo);
frame.setVisible(true);
}
});
}
}
2.- Tablero
package org.dune.juegos;
import java.awt.Button;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
public class Tablero extends JPanel implements ActionListener {
private static final long serialVersionUID = -6025639950351265124L;
//Botonera que representa el tablero
final Button botonesCasillas[][] = new Button[3][3];
//Estructura de memoria con las casillas del juego
int matrizTablero[][] = new int[3][3];
//Implementación del algoritmo minimax
final MiniMax minimax;
//Indicador de turno de jugador
boolean turnoHumano;
/**
* Constructor del panel
*/
public Tablero() {
//Define el contenido del panel
setBackground(UIManager.getColor("info"));
setLayout(new GridLayout(3, 3, 0, 0));
for (int i=0; i<3; i++) {
for (int j=0; j <3; j++) {
botonesCasillas[i][j] = new Button();
botonesCasillas[i][j].setBackground(SystemColor.control);
botonesCasillas[i][j].setFont(new Font("Arial",Font.BOLD,60));
botonesCasillas[i][j].addActionListener(this);
this.add(botonesCasillas[i][j]);
}
}
//Inicializamos variables de la partida
turnoHumano = true;
//Limpia los botones del tablero
limpiaBotones();
//Iniciamos el minimax
minimax = new MiniMax(3,3);
}
/**
* Interprete de las acciones del usuario.
*/
public void actionPerformed(ActionEvent e){
//Movimiento decidido por el ordenador
Movimiento mov;
//Si el turno era del humano
if(turnoHumano==true){
//Quitamos el turno al humano
turnoHumano = false;
//Revisa qué casilla ha pulsado
for (int i=0;i<3;i++) {
for (int j=0;j<3;j++) {
//Mira si la casilla pulsada por el humaon estaba libre
if ((e.getSource()==botonesCasillas[i][j]) && (botonesCasillas[i][j].getLabel().equals(""))){
//Pone en la casilla una P
botonesCasillas[i][j].setLabel("P");
matrizTablero[i][j] = MiniMax.CASILLA_PERSONA;
//Lanza el algoritmo minimax y recoge el movimiento elegido
mov = minimax.minimax(matrizTablero);
if (mov.getPosX()!=-1 && mov.getPosY()!=-1) {
//Introducimos un retardo
retarda(500);
//Dibujamos el movimiento del ordenador
botonesCasillas[mov.getPosX()][mov.getPosY()].setLabel("O");
matrizTablero[mov.getPosX()][mov.getPosY()]=MiniMax.CASILLA_ORDENADOR;
//Si hay ganador quito el turno al humano para que no pueda mover mas
if(minimax.haGanadoJugador(MiniMax.CASILLA_PERSONA)) {
turnoHumano=false;
JOptionPane.showMessageDialog(null, "ME HAS GANADO");
} else if (minimax.haGanadoJugador(MiniMax.CASILLA_ORDENADOR)) {
turnoHumano = false;
JOptionPane.showMessageDialog(null, "JE JE JE, SIEMPRE GANO YO...");
} else {
turnoHumano = true;
}
} else {
turnoHumano = false;
JOptionPane.showMessageDialog(null, "HEMOS VUELTO A EMPATAR");
}
}
}
}
}
}
private void retarda(int milis){
try {
Thread.sleep(milis);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
/**
* Limpia los botones del tablero
*/
private void limpiaBotones(){
for (int i=0; i<3; i++) {
for (int j=0; j <3; j++) {
botonesCasillas[i][j].setLabel("");
}
}
}
}
3.- Implementación del minimax
package org.dune.juegos;
public class MiniMax {
public static final int CASILLA_VACIA = 0;
public static final int CASILLA_PERSONA = 1;
public static final int CASILLA_ORDENADOR = 2;
private int tableroActual[][];
private int numCols;
private int numFils;
/**
* Recibe los datos del tablero de juego.
*
* @param anchura Dimensión horizontal del tablero.
* @param altura Dimensión vertical del tablero.
*/
public MiniMax(int anchura, int altura) {
super();
this.numCols = anchura;
this.numFils = altura;
this.tableroActual = new int[numCols][numFils];
}
/**
* Es el turno del ordenador y en base al tablero actual decidimos el movimiento a realizar.
*/
public Movimiento minimax(int[][] tableroParam){
this.tableroActual = tableroParam;
int posX=-1;
int posY=-1;
int aux=-9999;
int mejor=-9999;
for (int x=0;x<this.numCols;x++){
for (int y=0;y<this.numFils;y++){
if (isCasillaVacia(x,y)){
marcarCasilla(x,y,CASILLA_ORDENADOR);
aux = min();
if (aux>mejor) {
mejor=aux;
posX=x;
posY=y;
}
marcarCasilla(x,y,CASILLA_VACIA);
}
}
}
return new Movimiento(posX,posY);
}
/**
* El último jugador que marcó alguna casilla fue el ordenador, por lo que analizamos los posibles
* movimientos de la persona.
*
* Si estamos en un nodo hoja devolvemos la valoración del tablero, puede que haya ganado el ordenador
* o puede que sigamos empatados, así que hay dos posibles valores: 1 (gana el ordenador)
* y 0 (seguimos empatados).
*
* Si no es nodo hoja recorremos las casillas vacías simulando ser el jugador humano, y llamando
* a continuación al método MAX. Llamamos a MAX porque en el siguiente turno le tocará jugar a la CPU
* y nos interesa maximizar su resultado.
*/
private int min(){
if (haGanadoJugador(CASILLA_ORDENADOR)){
//Si ha ganado el ordenador devolvemos el valor del tablero
return 1;
} else if (isTableroLleno()){
//Si el tablero está lleno y no ha ganado el ordenador hemos empatado
return 0;
} else {
//Si el tablero no está lleno y no ha ganado el ordenador, recorremos todos
//los posibles movimientos restantes y los valoramos llamando a max()
int aux=9999;
int mejor=9999;
for (int x=0;x<this.numCols;x++){
for (int y=0;y<this.numFils;y++){
if (isCasillaVacia(x,y)){
marcarCasilla(x,y,CASILLA_PERSONA);
aux = max();
if (aux<mejor) {
mejor=aux;
}
marcarCasilla(x,y,CASILLA_VACIA);
}
}
}
return mejor;
}
}
/**
* El último jugador que marcó alguna casilla fue la persona, por lo que analizamos los posibles
* movimientos del ordenador.
*
* Si estamos en un nodo hoja devolvemos la valoración del tablero, puede que haya ganado la persona
* o puede que sigamos empatados, así que hay dos posibles valores: -1 (gana la persona)
* y 0 (seguimos empatados).
*
* Si no es nodo hoja recorremos las casillas vacías simulando ser el ordenador, y llamando
* a continuación al método MIN. Llamamos a MIN porque en el siguiente turno le tocará jugar al humano
* y nos interesa minimizar su resultado.
*/
private int max(){
if (haGanadoJugador(CASILLA_PERSONA)){
//Si ha ganado la persona devolvemos el valor del tablero
return -1;
} else if (isTableroLleno()){
//Si el tablero está lleno y no ha ganado la persona hemos empatado
return 0;
} else {
///Si el tablero no está lleno y no ha ganado la persona, recorremos todos
//los posibles movimientos restantes y los valoramos llamando a min()
int aux=-9999;
int mejor=-9999;
for (int x=0;x<this.numCols;x++){
for (int y=0;y<this.numFils;y++){
if (isCasillaVacia(x,y)){
marcarCasilla(x,y,CASILLA_ORDENADOR);
aux = min();
if (aux>mejor) {
mejor=aux;
}
marcarCasilla(x,y,CASILLA_VACIA);
}
}
}
return mejor;
}
}
/**
* Determina si una determinada posición del tablero está
* o no vacía.
*
* @param x. Fila de la casilla a analizar.
* @param y. Columna de la casilla a analizar.
*
* @return True cuando la casilla está vacía
*/
private boolean isCasillaVacia(int x, int y){
return tableroActual[x][y]==CASILLA_VACIA;
}
/**
* Ocupa la casilla indicada con la ficha recibida.
*
* @param x. Fila de la casilla a marcar.
* @param y. Columna de la casilla a marcar.
* @param ficha. Ficha a colocar.
*/
private void marcarCasilla(int x, int y, int ficha){
tableroActual[x][y]=ficha;
}
/**
* Determina si el tablero tiene casillas libres.
*
* @return True si hay casillas no ocupadas.
*/
private boolean isTableroLleno(){
for (int x=0;x<3;x++){
for (int y=0;y<3;y++){
if (isCasillaVacia(x,y)){
return false;
}
}
}
return true;
}
/**
* Determina si el jugador que maneja la ficha recibida
* por parámetro ha ganado la partida.
*
* @param ficha Ficha que podría haber ganado
*
* @return True cuando el jugador con la ficha recibida ha ganado.
*/
public boolean haGanadoJugador(int ficha){
//Verifica si el jugador ha ganado en las diagonales
if((tableroActual[0][0]==ficha && tableroActual[1][1]==ficha && tableroActual[2][2]==ficha)||
(tableroActual[0][2]==ficha && tableroActual[1][1]==ficha && tableroActual[2][0]==ficha)) {
return true;
} else {
//Verifica si el jugador ha ganado en una fila
for(int i=0;i<3;i++) {
if(tableroActual[i][0]==ficha && tableroActual[i][1]==ficha && tableroActual[i][2]==ficha) {
return true;
}
}
//Verifica si el jugador ha ganado en una columna
for(int i=0;i<3;i++) {
if(tableroActual[0][i]==ficha && tableroActual[1][i]==ficha && tableroActual[2][i]==ficha) {
return true;
}
}
}
return false;
}
}
4.- Clase auxiliar para manejar los movimientos
package org.dune.juegos;
public class Movimiento {
private int posX;
private int posY;
public Movimiento(int posX, int posY) {
super();
this.posX = posX;
this.posY = posY;
}
public int getPosX() {
return posX;
}
public void setPosX(int posX) {
this.posX = posX;
}
public int getPosY() {
return posY;
}
public void setPosY(int posY) {
this.posY = posY;
}
}
jueves, 24 de abril de 2014
Gnome 3 (gnome-shell) gestión varios monitores
Hola
Si tenemos nuestro PC conectado a varios monitores y queremos configurar tanto el monitor principal (donde se ubica el lanzador) como la posición del monitor secundario con respecto al primario podemos seguir los siguientes pasos:
1) Lanzar el comando
$ xrandr
2) Ésto generará una salida similar a la siguiente:
Screen 0: minimum 320 x 200, current 3286 x 1080, maximum 32767 x 32767
LVDS1 connected 1366x768+1920+0 (normal left inverted right x axis y axis) 344mm x 193mm
1366x768 60.0*+ 40.0
1360x768 59.8 60.0
1024x768 60.0
800x600 60.3 56.2
640x480 59.9
VGA1 disconnected (normal left inverted right x axis y axis)
HDMI1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 480mm x 270mm
1920x1080 60.0*+ 60.0 50.0 59.9
1680x1050 59.9
1600x900 60.0
1280x1024 60.0
1440x900 59.9
1280x720 60.0 50.0 59.9
1024x768 60.0
800x600 60.3
720x576 50.0
720x480 60.0 59.9
640x480 60.0 59.9
720x400 70.1
DP1 disconnected (normal left inverted right x axis y axis)
VIRTUAL1 disconnected (normal left inverted right x axis y axis)
VGA-1-1 disconnected
3) Nos fijamos en que tenemos varios monitores activos, en el ejemplo anterior tenemos dos: LVDS1 y HDMI1
4) Para hacer que el monitor principal sea HDMI1, que el monitor secundario sea LVDS1 y que el monitor secundario esté a la derecha del primario podemos lanzar el siguiente comando:
$ xrandr --output HDMI1 --primary --mode 1920x1080 --output LVDS1 --mode 1366x768 --right-of HDMI1
5) Ésto efectuará el cambio inmediatamente, con lo que podemos seguir jugando indefinidamente con las opciones de xrandr hasta dar con la configuración deseada. Hay muchas páginas documentando éstos parámetros, como por ejemplo: http://pkg-xorg.alioth.debian.org/howto/use-xrandr.html
6) Una vez definido el ajuste ideal, tenemos que almacenarlo en alguna parte, dado que en el siguiente inicio de sesión se habrá perdido. Seguro que hay una forma mejor de hacerlo, pero mientras investivamos podemos añadir el comando anterior al final del fichero .profile de nuestro $HOME.
P.D. En mi caso todo ésto tiene una pega y es que cuando use el portatil sin el monitor secundario la pantalla del portatil no mostrará el lanzador, en esas ocasiones deberé comentar ésta línea del .profile, seguiremos curioseando para solucionar éste tema.
Un saludo
Si tenemos nuestro PC conectado a varios monitores y queremos configurar tanto el monitor principal (donde se ubica el lanzador) como la posición del monitor secundario con respecto al primario podemos seguir los siguientes pasos:
1) Lanzar el comando
$ xrandr
2) Ésto generará una salida similar a la siguiente:
Screen 0: minimum 320 x 200, current 3286 x 1080, maximum 32767 x 32767
LVDS1 connected 1366x768+1920+0 (normal left inverted right x axis y axis) 344mm x 193mm
1366x768 60.0*+ 40.0
1360x768 59.8 60.0
1024x768 60.0
800x600 60.3 56.2
640x480 59.9
VGA1 disconnected (normal left inverted right x axis y axis)
HDMI1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 480mm x 270mm
1920x1080 60.0*+ 60.0 50.0 59.9
1680x1050 59.9
1600x900 60.0
1280x1024 60.0
1440x900 59.9
1280x720 60.0 50.0 59.9
1024x768 60.0
800x600 60.3
720x576 50.0
720x480 60.0 59.9
640x480 60.0 59.9
720x400 70.1
DP1 disconnected (normal left inverted right x axis y axis)
VIRTUAL1 disconnected (normal left inverted right x axis y axis)
VGA-1-1 disconnected
3) Nos fijamos en que tenemos varios monitores activos, en el ejemplo anterior tenemos dos: LVDS1 y HDMI1
4) Para hacer que el monitor principal sea HDMI1, que el monitor secundario sea LVDS1 y que el monitor secundario esté a la derecha del primario podemos lanzar el siguiente comando:
$ xrandr --output HDMI1 --primary --mode 1920x1080 --output LVDS1 --mode 1366x768 --right-of HDMI1
5) Ésto efectuará el cambio inmediatamente, con lo que podemos seguir jugando indefinidamente con las opciones de xrandr hasta dar con la configuración deseada. Hay muchas páginas documentando éstos parámetros, como por ejemplo: http://pkg-xorg.alioth.debian.org/howto/use-xrandr.html
6) Una vez definido el ajuste ideal, tenemos que almacenarlo en alguna parte, dado que en el siguiente inicio de sesión se habrá perdido. Seguro que hay una forma mejor de hacerlo, pero mientras investivamos podemos añadir el comando anterior al final del fichero .profile de nuestro $HOME.
P.D. En mi caso todo ésto tiene una pega y es que cuando use el portatil sin el monitor secundario la pantalla del portatil no mostrará el lanzador, en esas ocasiones deberé comentar ésta línea del .profile, seguiremos curioseando para solucionar éste tema.
Un saludo
domingo, 26 de enero de 2014
Aprobar exámenes ITIL V3
Hola
Con los siguientes resúmenes de ITIL y los exámanes referenciados, todos los miembros del equipo hemos obtenido la certificación con más de un 80% de acierto.
Resúmenes
1. Estrategia para los Servicios TI.odt
2. Diseño de los Servicios TI.odt
3. Transición de los Servicios TI.odt
4. Operación de los Servicios TI.odt
5. Proceso de Mejora Continua de los Servicios TI.odt
Exámenes
http://www.proprofs.com/quiz-school/story.php?title=itil-foundation-v3-examen-2
http://www.proprofs.com/quiz-school/story.php?title=itil-foundation-v3-examen-3
http://www.proprofs.com/quiz-school/story.php?title=test-itil-foundation-v3
Referencias
http://itilv3.osiatis.es/
Con los siguientes resúmenes de ITIL y los exámanes referenciados, todos los miembros del equipo hemos obtenido la certificación con más de un 80% de acierto.
Resúmenes
1. Estrategia para los Servicios TI.odt
2. Diseño de los Servicios TI.odt
3. Transición de los Servicios TI.odt
4. Operación de los Servicios TI.odt
5. Proceso de Mejora Continua de los Servicios TI.odt
Exámenes
http://www.proprofs.com/quiz-school/story.php?title=itil-foundation-v3-examen-2
http://www.proprofs.com/quiz-school/story.php?title=itil-foundation-v3-examen-3
http://www.proprofs.com/quiz-school/story.php?title=test-itil-foundation-v3
Referencias
http://itilv3.osiatis.es/
jueves, 16 de enero de 2014
Montar una petición PKCS#10 RSA de 2048 bits
PKCS#10 es un estándar para solicitar certificados (definido en la RFC 2986) que define el formato del mensaje a enviar a una CA (por ejemplo la FNMT).
Para generar una de éstas solicitudes podemos usar la herramienta java keytool (estoy usando JDK 1.7.0_51).
Los pasos serían los siguientes:
1) Nos creamos nuestro certificado.
keytool -genkey -alias firma.dune.org -keyalg RSA –keysize 2048 -keystore /home/usuario/dune-keystore.jks
2) Creamos el CSR (Certificate Signing Request) y que en el ejemplo he llamado cert-req.txt
keytool -certreq -keyalg RSA -alias firma.dune.org -file cert-req.txt -keystore /home/usuario/dune-keystore.jks
3) Enviamos a la CA el fichero cert-req.txt
Un saludo
Para generar una de éstas solicitudes podemos usar la herramienta java keytool (estoy usando JDK 1.7.0_51).
Los pasos serían los siguientes:
1) Nos creamos nuestro certificado.
keytool -genkey -alias firma.dune.org -keyalg RSA –keysize 2048 -keystore /home/usuario/dune-keystore.jks
2) Creamos el CSR (Certificate Signing Request) y que en el ejemplo he llamado cert-req.txt
keytool -certreq -keyalg RSA -alias firma.dune.org -file cert-req.txt -keystore /home/usuario/dune-keystore.jks
3) Enviamos a la CA el fichero cert-req.txt
Un saludo
miércoles, 15 de enero de 2014
Alfresco ContentStore sobre NFS
Vamos a montar el contentstore de nuestro server Alfresco en otra máquina accesible mediante NFS.
Para ello necesitaremos montar el servidor NFS en nuestra máquina Ubuntu servidora de disco y el cliente NFS en nuestra la Ubuntu donde corre el Alfresco.
Montar server NFS y dar permisos
1) Descargamos server NFS con el comando:
sudo apt-get install nfs-kernel-server
2) Decidimos qué carpeta vamos a compartir, por ejemplo /home/compartido
3) Editamos el fichero /etc/exports con el comando:
sudo gedit /etc/exports
4) Añadimos la siguiente línea:
/home/compartido ccc.ccc.ccc.ccc(rw,async,no_subtree_check,insecure,all_squash,anonuid=65534,anongid=65534)
Nota 1. Todos los parámetros aparecen perfectamente descritos en la ayuda: man exports
Nota 2. Para sacar los ID de usuario/grupo de la cuenta anónima nobody/nogroup hemos lanzado:
sudo id nobody
5) Publicamos los cambios en la configuración de carpetas compartidas ejecutando el comando:
sudo /usr/sbin/exportfs
6) Levantamos el servidor con el comando:
sudo /etc/init.d/nfs-kernel-server start
Montar el cliente NFS
1) Descargamos el cliente NFS con el comando:
sudo apt-get isntall nfs-common
2) Decidimos en qué carpeta vamos a montar la unidad de red compartida, por ejemplo /home/red/compartido1
3) Montamos la unidad de red compartida vía NFS con el comando:
sudo mount -t nfs sss.sss.sss.sss:/home/compartido /home/red/compartido1
Referencias
- Algunas páginas interesantes son:
http://ubuntuforums.org/showthread.php?t=1356807
https://www.digitalocean.com/community/articles/how-to-set-up-an-nfs-mount-on-ubuntu-12-04
http://www.idevelopment.info/data/Unix/Linux/LINUX_ExportingaFileSystemforNFS.shtml
https://help.ubuntu.com/12.04/serverguide/network-file-system.html
Para ello necesitaremos montar el servidor NFS en nuestra máquina Ubuntu servidora de disco y el cliente NFS en nuestra la Ubuntu donde corre el Alfresco.
Montar server NFS y dar permisos
1) Descargamos server NFS con el comando:
sudo apt-get install nfs-kernel-server
2) Decidimos qué carpeta vamos a compartir, por ejemplo /home/compartido
3) Editamos el fichero /etc/exports con el comando:
sudo gedit /etc/exports
4) Añadimos la siguiente línea:
/home/compartido ccc.ccc.ccc.ccc(rw,async,no_subtree_check,insecure,all_squash,anonuid=65534,anongid=65534)
Nota 1. Todos los parámetros aparecen perfectamente descritos en la ayuda: man exports
Nota 2. Para sacar los ID de usuario/grupo de la cuenta anónima nobody/nogroup hemos lanzado:
sudo id nobody
5) Publicamos los cambios en la configuración de carpetas compartidas ejecutando el comando:
sudo /usr/sbin/exportfs
6) Levantamos el servidor con el comando:
sudo /etc/init.d/nfs-kernel-server start
Montar el cliente NFS
1) Descargamos el cliente NFS con el comando:
sudo apt-get isntall nfs-common
2) Decidimos en qué carpeta vamos a montar la unidad de red compartida, por ejemplo /home/red/compartido1
3) Montamos la unidad de red compartida vía NFS con el comando:
sudo mount -t nfs sss.sss.sss.sss:/home/compartido /home/red/compartido1
Referencias
- Algunas páginas interesantes son:
http://ubuntuforums.org/showthread.php?t=1356807
https://www.digitalocean.com/community/articles/how-to-set-up-an-nfs-mount-on-ubuntu-12-04
http://www.idevelopment.info/data/Unix/Linux/LINUX_ExportingaFileSystemforNFS.shtml
https://help.ubuntu.com/12.04/serverguide/network-file-system.html
Suscribirse a:
Entradas (Atom)