Archive for the ‘Pràctiques’ Category

Projecte de final de carrera: presentacions col·laboratives amb l’eyeOS

dimarts, octubre 11th, 2011

El 16 de setembre de 2011 vaig presentar el meu projecte de final de carrera «Presentacions col·laboratives amb l’eyeOS».

Ha estat desenvolupat entre el 9 de març i el 16 de setembre a les oficines d’eyeOS i ha obtingut una qualificació de 10.0/10 matrícula d’honor.

En qualsevol cas ja sóc feliçment enginyer tècnic en informàtica per la UPC.

La memòria del projecte està disponible per a tothom a UPC Commons en PDF:

Presentacions col·laboratives amb l’eyeOS.

Com no podia ser d’altra manera, vaig fer algunes piulades al Twitter (o algú les va fer de part meva) 1 2 3 4 5 6 7 8

http://eduard-gamonal.net/wp-content/plugins/downloads-manager/img/icons/pdf.gif download: Projecte de final de carrera - diapositives de la presentació (2.47MB)
added: 11/10/2011
clicks: 299
description: Diapositives de la presentació del projecte de final de carrera «Presentacions col·laboratives amb l\'eyeOS», UPC - FIB

http://eduard-gamonal.net/wp-content/plugins/downloads-manager/img/icons/pdf.gif download: Projecte de final de carrera - diapositives de la demo en la presentació (298.40KB)
added: 11/10/2011
clicks: 263
description: Diapositives de la demo en directe en la presentació del projecte de final de carrera «Presentacions col·laboratives amb l\'eyeOS», UPC - FIB

Fixing a WindowsError in Qooxdoo’s generate.py

divendres, juny 24th, 2011

eyeOS 2.5 uses Qooxdoo  1.3. For my project I needed to include the SVG contrib by Marc Puts, so I checked if there was an easy way to do this in eyeOS.

A step in this process is calling generate.py, which is quite simple but wouldn’t finish on my laptop. Well, it happened to be a bug with a very quick patch. I sent a bug report and it has been fixed for trunk and branch 1.4.x.

Under certain circumstances generate.py can't finish its job.

I tried to build an app with
generate.py build
where build is a job defined in our (eyeOS) custom config.json

It failed with the message "global name 'WindowsError' is not defined".
The program was attempting to copy some files and the destination folder's
owner was somebody with higher privileges.

The affected file is qooxdoo-sdk/tool/pylib/misc/copytool.py
line 82:
   except WindowsError:
     try:
       os.chmod(targetPath, stat.S_IWUSR)

WindowsError is a subclass of OSError, as stated in
http://docs.python.org/library/exceptions.html#exceptions.WindowsError
"it's raised when a Windows-specific error occurs or when the error number does
not correspond to an errno value"

I suggest changing WindowsError for OSError.

I'm running Fedora 14 (2.6.35.13-92.fc14.i686)
Python 2.7 (r27:82500, Sep 16 2010, 18:03:06) 

Steps to reproduce
1. get a working qooxdoo app
2. set its owner to somebody but yourself (e.g. chown apache:apache -R myApp/ )
3. run generate.py

Introduction to software engineering

dimecres, maig 5th, 2010

Tomorrow morning I’ll be giving a  lightning talk about Software Engineering, as part of the course Oral English for the Technical Professions.

Find the slides below :)

http://eduard-gamonal.net/wp-content/plugins/downloads-manager/img/icons/pdf.gif download: Software Engineering (879.58KB)
added: 04/05/2010
clicks: 583
description: Lightning talk about Software Engineering, as part of the subject Oral English for the Technical Professions. Universitat Politècnica de Catalunya

Com fer servir Java, JDBC i GNU/Linux

dissabte, abril 25th, 2009

A la facultat ens han donat instruccions per a treballar amb Java i JDBC des de Windows. Com que alguns no fem servir aquest sistema inoperatiu per motius tant tècnics com ètics, m’hi he barallat una estoneta i he trobat com fer-ho amb GNU/Linux. No és complicat :)

Entorn

Java

Primer de tot ens cal l’entorn per desenvolupar aplicacions en Java

apt-get install sun-java6-jdk

Amb això no n’hi ha prou per fer un Hello World. GNU/Linux permet tenir diverses màquines virtuals instal·lades, i per defecte en ve una de lliure (cosa que ja em sembla bé). Volem desenvolupar en un entorn tan semblat a la facultat com sigui possible, així que ens toca canviar la màquina virtual i posar la privativa:

artoo:/home/edu# update-alternatives --config java

Hi ha 3 alternatives que proveeixin «java».

Selecció     Alternativa
-----------------------------------------------
1    /usr/bin/gij-4.3
+        2    /usr/lib/jvm/java-gcj/jre/bin/java
*         3    /usr/lib/jvm/java-6-sun/jre/bin/java

Premeu retorn per a mantenir l'opció per defecte[*], o introduïu un número de selecció:

Volem la 3.

Per treballar amb JDBC i PostgreSQL ens fa falta el driver adequat. A dia d’avui n’hi ha dos de disponibles, el 3 i el 4. Jo he necessitat el 4 perquè tinc màquina virtual versió >= 1.6
edu@artoo:~/facultat/bd/java$ java -version
java version "1.6.0_12"
Java(TM) SE Runtime Environment (build 1.6.0_12-b04)
Java HotSpot(TM) Client VM (build 11.2-b01, mixed mode, sharing)
edu@artoo:~/facultat/bd/java$

Ens baixarem un fitxer .jar, que ve a ser un tar.gz. El podem posar on vulguem, perquè després li direm al sistema on és. Jo he optat per fer-me un directori de treball per fer les pràctiques en /home/edu/facultat/bd/java :
edu@artoo:~/facultat/bd/java$ ls
classp             gestioSocis.java     HelloWorldApp.java
gestioSocis.class  HelloWorldApp.class
edu@artoo:~/facultat/bd/java$ ls classp/
postgresql.jar

Ara ja tenim els ingredients, i falta connectar-los. Caldrà exportar la variable d’entorn CLASSPATH. Pels veterans de C++, això ve a ser com quan compilem amb g++

g++ -c programa.cpp -I/includesdiversos

Cal dir-li on cercar fitxers que inclourem i que no venen de sèrie. Com si fos una variable d’entorn normal, fem:

export CLASSPATH=.:classp/postgresql.jar

i així li diem que busqui classes en el directori actual i en classp/postgresql.jar. Ara, per fi, ja podem fer les primeres proves amb JDBC.

Servidor i PostgreSQL

Necessitem un servidor Apache i PostgreSQL. L’opció més fàcil és fer servir LAMPP :

Instal·leu lampp en /opt/lampp Instruccions i paquet

Instal·leu el plugin per a PosgreSQL Instruccions i paquet

Els passos indicats a la web del plugin són:

  1. “tar xfz postgresql.tar.gz -C /tmp” Canvieu el nom de fitxer pel que hagueu baixat, és clar.
  2. “cd /tmp/postgresql-addon”
  3. “./INSTALL”

Per a iniciar el servidor POSGRESQL: /opt/lampp/lampp startpostgresql

Stop: /opt/lampp/lampp stoppostgresql

combinació usuari i contrasenya per defecte: User: root Password: lampp

És recomanable iniciar primer el servidor apache: /opt/lampp/lampp start i després el posgresql: /opt/lampp/lampp startpostgresql

Podeu veure una interfície web per a Posgres des del Firefox, tot anant a l’adreça: /localhost/phppgadmin

Com compilar amb Java

Farem un HelloWorld en un segon:

class HelloWorldApp {
public static void main(String[] args) {
System.out.println("Hello World!"); // Display the string.
}
}

Aquest és el codi. Cal desar-lo en HelloWorldApp.java. És important respectar el nom de fitxer, que ha de ser igual al de la classe principal.

Doncs apa:

edu@artoo:~/facultat/bd/java$ javac HelloWorldApp.java
edu@artoo:~/facultat/bd/java$ java HelloWorldApp
Hello World!
edu@artoo:~/facultat/bd/java$

Proves amb JDBC

Per l’assignatura de Bases de Dades de la FIB, quadrimestre 08-09Primavera, fem servir el següent escenari (font)

CREATE TABLE socis
(dni char(9),
nom char(30) NOT NULL,
telefon char(9),
numVISA char(12),
ciutatResidencia char(20) DEFAULT 'Barcelona',
PRIMARY KEY (dni));
 
CREATE TABLE tipus
(tipus char(15),
numMaxInscripcions integer NOT NULL,
PRIMARY KEY (tipus));
 
CREATE TABLE activitats
(tipusActivitat char(15),
dataInici integer,
descripcio char(50) UNIQUE,
dni char(9),
preu integer CHECK (preu > 10),
lloc char(20),
ciutat char(20),
PRIMARY KEY (tipusActivitat, dataInici),
FOREIGN KEY (tipusActivitat) REFERENCES tipus (tipus),
FOREIGN KEY (dni) REFERENCES socis);
 
CREATE TABLE inscripcions
(tipusActivitat char(15),
dataInici integer,
dni char(9),
formaPagament char(20),
dataPagament integer,
CHECK (dataInici < dataPagament),
PRIMARY KEY (tipusActivitat, dataInici, dni),
FOREIGN KEY (tipusActivitat, dataInici) REFERENCES activitats,
FOREIGN KEY (dni) REFERENCES socis);

Amb les dades a continuació (font):

INSERT INTO socis VALUES (10, 'Carme', 101,NULL, 'Hospitalet');
INSERT INTO socis VALUES (11, 'Nuria', 111, 111111, 'Hospitalet');
INSERT INTO socis VALUES (12, 'Josep', 121, 121121, 'Hospitalet');
INSERT INTO socis VALUES (13, 'Jordi', 131, 131131, 'Barcelona');
INSERT INTO socis VALUES (14, 'Imma', 141, 141141, 'Barcelona');
INSERT INTO socis VALUES (15, 'Roger', 151, 151151, 'Barcelona');
INSERT INTO socis VALUES (16, 'Oriol', 161, 161161, 'Barcelona');
INSERT INTO socis VALUES ('17', 'Mireia', 101,101101, 'Palleja');
INSERT INTO socis (dni, nom, telefon, numVISA) VALUES (19, 'Joan', 333, 333333);
INSERT INTO socis (dni, nom, telefon, ciutatResidencia) VALUES (20, 'Joan', 333, 'Sant Just');
 
INSERT INTO tipus VALUES ('capDAny', 200);
INSERT INTO tipus VALUES ('cine', 10);
INSERT INTO tipus VALUES ('teatre', 6);
INSERT INTO tipus VALUES ('discoteca', 30);
INSERT INTO tipus VALUES ('excursio', 30); 
INSERT INTO tipus VALUES ('sopar', 2);
INSERT INTO tipus VALUES ('opera', 6);
INSERT INTO tipus VALUES ('concert', 6);
 
INSERT INTO activitats VALUES ('cine', 124, 'One Milion Baby', 10, 17, 'Cinesa Diagonal', 'Barcelona');
INSERT INTO activitats VALUES ('cine', 224, 'Magnolias de Acero', 11, 16, 'La Farga', 'Hospitalet');
INSERT INTO activitats VALUES ('capDAny', 1224, 'Festa Roc Blanc', 12, 100, 'Plaça Major', 'Vic');
INSERT INTO activitats VALUES ('sopar', 425, 'Aniversari Josep', 12, 80, 'Can Jubany', 'Calldetenes'); 
INSERT INTO activitats VALUES ('teatre', 424, 'El Ratoli Viatger', 10, 15, 'Teatre Atlantida', 'Ripoll');
INSERT INTO activitats VALUES ('opera', 2345, 'La Flauta Magica', NULL, NULL, 'Liceu', 'Barcelona');
INSERT INTO activitats VALUES ('concert', 3234, 'La Casa de Vent i de Fusta', 10, NULL, NULL, 'Barcelona');
 
INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('cine', 124, 10, 'amex');
INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('sopar', 425, 10, 'sdfjñs');
INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('capDAny', 1224, 10, 'amex');
INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('cine', 124, 11, 'visa');
INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('sopar', 425, 11, 'visa');
INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('capDAny', 1224, 11, 'visa');
INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('sopar', 425, 12, 'sdfjñs');
INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('cine', 224, 13, 'sdfjñs');
INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('cine', 224, 14, 'sdfjñs');
INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('cine', 224, 15, 'sdfjñs');
INSERT INTO inscripcions (tipusActivitat, dataInici, dni, formaPagament) VALUES ('cine', 224, 16, 'sdfjñs');
INSERT INTO inscripcions VALUES ('teatre', 424, 10, 'VISA', 435);
INSERT INTO inscripcions VALUES ('teatre', 424, 11, 'VISA', 435);
INSERT INTO inscripcions VALUES ('teatre', 424, 12, 'VISA', 435);
INSERT INTO inscripcions VALUES ('teatre', 424, 13, 'VISA', 435);
INSERT INTO inscripcions VALUES ('teatre', 424, 14, 'VISA', 435);
INSERT INTO inscripcions VALUES ('teatre', 424, 15, 'VISA', 435);
INSERT INTO inscripcions VALUES ('teatre', 424, 16, 'VISA', 435);
INSERT INTO inscripcions (tipusActivitat, dataInici, dni) VALUES ('opera', 2345, 10);
INSERT INTO inscripcions (tipusActivitat, dataInici, dni) VALUES ('opera', 2345, 11);
INSERT INTO inscripcions (tipusActivitat, dataInici, dni) VALUES ('opera', 2345, 12);
INSERT INTO inscripcions (tipusActivitat, dataInici, dni) VALUES ('opera', 2345, 13);
INSERT INTO inscripcions (tipusActivitat, dataInici, dni) VALUES ('opera', 2345, 14);
INSERT INTO inscripcions (tipusActivitat, dataInici, dni) VALUES ('opera', 2345, 15);

La facultat ens facilita també un codi plantilla amb les línies indispensables per establir una connexió:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import java.sql.*;
import java.util.Properties;
 
public class gestioSocis
   {
   public static void main (String args[])
     {
	try
	   {
	   // carregar el driver al controlador
	   Class.forName ("org.postgresql.Driver");
	   System.out.println ("Driver de PostgreSQL carregat correctament.");
 
 
	   // connectar a la base de dades
	   // cal modificar el username, password i el nom de la base de dades
	   // en el servidor postgresfib, SEMPRE el SSL ha de ser true
	   Properties props = new Properties();
	   props.setProperty("user","elMeuNomUsuari");
	   props.setProperty("password","elMeuPassword");
	   props.setProperty("ssl","true");
	   props.setProperty("sslfactory", "org.postgresql.ssl.NonValidatingFactory"); 
	   Connection c = DriverManager.getConnection("jdbc:postgresql://postgresfib.fib.upc.es:5432/laMevaBaseDeDades", props);
	   c.setAutoCommit(false);
	   System.out.println ("Connexio realitzada correctament.");
 
 
	   // canvi de l'esquema per defecte a un altre esquema
		 Statement s = c.createStatement();
		 s.executeUpdate("set search_path to elMeuEsquema;");
		 s.close();					
	   System.out.println ("Canvi d'esquema realitzat correctament.");
 
 
	   // consultar tots les socis que viuen a Hospitalet
	   // Dir quantes inscripcions té cada un 
	   String cR = "Hospitalet";
	   String consSocis="select dni,nom from socis "+
                         "where ciutatResidencia = '"+cR+"';";
	   System.out.println (consSocis);
	   s = c.createStatement();
	   ResultSet r = s.executeQuery (consSocis);
 
           String consInscr="select count(*) as numInscr "+
                      "from inscripcions i where i.dni = ? ;";
	   System.out.println (consInscr);
 	   PreparedStatement ps = c.prepareStatement(consInscr); 
 	   ResultSet rs = null;
	   int quantsSocis = 0;
	   String dni=" ";
	   String nom=" ";
	   while (r.next())
	   	   {
	   	   quantsSocis = quantsSocis + 1;
	   	   dni = r.getString("dni");
	   	   nom = r.getString("nom");
	   	   System.out.print ("El soci amb dni "+dni+" i nom ");
	   	   if (nom==null) { System.out.print ("null"); }
                     else { System.out.print (nom); }
		     ps.setString(1,dni);
		     rs = ps.executeQuery();
		     rs.next();
		     System.out.print("te ");
		     System.out.print (rs.getInt("numInscr"));
		     System.out.println(" inscripcions");
		     rs.close();
	   	   }
           r.close();
           System.out.println ("Nombre de socis consultats "+quantsSocis);
	   s.close();
 
	   // Inserir una activitat 
 
	   s = c.createStatement();
	   String inserirAct="insert into activitats "+
                      "values ('concert', 3250, 'El fantasma del museu', 10, 120, 'Romea', 'Barcelona')";
	   s.executeUpdate(inserirAct);
	   System.out.println ("Una activitat inserida");
           s.close();
 
	   // Rollback i desconnexió de la base de dades
	   c.rollback();
	   c.close();
	   System.out.println ("Rollback i desconnexio realitzats correctament.");
	   }
 
	catch (ClassNotFoundException ce)
	   {
	   System.out.println ("Error al carregar el driver");
	   }	
	catch (SQLException se)
	   {
	   System.out.println (se.getSQLState());
	   System.out.println (se.getMessage());	   
	   }
  }
}

El que passa és que està preparat per connectar-se des dels laboratoris de la uni, i a casa vull treballar en local. M’ho modifico:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import java.sql.*;
import java.util.Properties;
 
public class gestioSocis
   {
   public static void main (String args[])
     {
	try
	   {
	   // carregar el driver al controlador
	   Class.forName ("org.postgresql.Driver");
	   System.out.println ("Driver de PostgreSQL carregat correctament.");
 
 
	   // connectar a la base de dades
	   // cal modificar el username, password i el nom de la base de dades
	   // en el servidor postgresfib, SEMPRE el SSL ha de ser true
	   Properties props = new Properties();
	   props.setProperty("user","root");
	   props.setProperty("password","lampp");
	   //props.setProperty("ssl","true");
	   //props.setProperty("sslfactory", "org.postgresql.ssl.NonValidatingFactory"); 
	   Connection c = DriverManager.getConnection("jdbc:postgresql://localhost/javafib", props);
	   c.setAutoCommit(false);
	   System.out.println ("Connexio realitzada correctament.");
 
 
	   // canvi de l'esquema per defecte a un altre esquema
		 Statement s = c.createStatement();
		 s.executeUpdate("set search_path to public;");
		 s.close();					
	   System.out.println ("Canvi d'esquema realitzat correctament.");
 
 
	   // consultar tots les socis que viuen a Hospitalet
	   // Dir quantes inscripcions té cada un 
	   String cR = "Hospitalet";
	   String consSocis="select dni,nom from socis "+
                         "where ciutatResidencia = '"+cR+"';";
	   System.out.println (consSocis);
	   s = c.createStatement();
	   ResultSet r = s.executeQuery (consSocis);
 
           String consInscr="select count(*) as numInscr "+
                      "from inscripcions i where i.dni = ? ;";
	   System.out.println (consInscr);
 	   PreparedStatement ps = c.prepareStatement(consInscr); 
 	   ResultSet rs = null;
	   int quantsSocis = 0;
	   String dni=" ";
	   String nom=" ";
	   while (r.next())
	   	   {
	   	   quantsSocis = quantsSocis + 1;
	   	   dni = r.getString("dni");
	   	   nom = r.getString("nom");
	   	   System.out.print ("El soci amb dni "+dni+" i nom ");
	   	   if (nom==null) { System.out.print ("null"); }
                     else { System.out.print (nom); }
		     ps.setString(1,dni);
		     rs = ps.executeQuery();
		     rs.next();
		     System.out.print("te ");
		     System.out.print (rs.getInt("numInscr"));
		     System.out.println(" inscripcions");
		     rs.close();
	   	   }
           r.close();
           System.out.println ("Nombre de socis consultats "+quantsSocis);
	   s.close();
 
	   // Inserir una activitat 
 
	   s = c.createStatement();
	   String inserirAct="insert into activitats "+
                      "values ('concert', 3250, 'El fantasma del museu', 10, 120, 'Romea', 'Barcelona')";
	   s.executeUpdate(inserirAct);
	   System.out.println ("Una activitat inserida");
           s.close();
 
	   // Rollback i desconnexió de la base de dades
	   c.rollback();
	   c.close();
	   System.out.println ("Rollback i desconnexio realitzats correctament.");
	   }
 
	catch (ClassNotFoundException ce)
	   {
	   System.out.println ("Error al carregar el driver");
	   }	
	catch (SQLException se)
	   {
	   System.out.println (se.getSQLState());
	   System.out.println (se.getMessage());	   
	   }
  }
}

i es fa la màgia

edu@artoo:~/facultat/bd/java$ java gestioSocis
Driver de PostgreSQL carregat correctament.
Connexio realitzada correctament.
Canvi d'esquema realitzat correctament.
select dni,nom from socis where ciutatResidencia = 'Hospitalet';
select count(*) as numInscr from inscripcions i where i.dni = ? ;
El soci amb dni 10 i nom Carme te 5 inscripcions
El soci amb dni 11 i nom Nuria te 5 inscripcions
El soci amb dni 12 i nom Josep te 3 inscripcions
Nombre de socis consultats 3
Una activitat inserida
Rollback i desconnexio realitzats correctament.
edu@artoo:~/facultat/bd/java$

PROLOG: introducció a la programació lògica – 2

dilluns, abril 13th, 2009

Avís: article orientat a estudiants d’Enginyeries en Informàtica de la FIBUPC. Basat en les explicacions a classe del professor Enric Rodríguez.

La programació lògica es cursa en les assignatures d’«introducció a la lògica» i a «lògica per a la informàtica». La utilitat directa per un fíber és: calcular respostes pel concurs «Cifras y letras» o trobar una manera de resoldre el problema de missioners i caníbals. També es fa servir per calcular horaris de l’ACB o els mateixos de la FIB.

Problema de concatenació

Inducció per concatenació:

concat([], L, L).
concat([X|Y1], Y2, [X|Y3]) :- concat(Y1, Y2, Y3).

Vegem que si L1, L2 són llistes i L3 és una variable, aleshores la consulta

edu@debian:~$ prolog
GNU Prolog 1.3.0
By Daniel Diaz
Copyright (C) 1999-2007 Daniel Diaz
| ?- concat(L1, L2, L3)

instancia (unifica) L3 amb la concatenació de L1 i L2.

Cas base

L1 és la llista buida []. Per la primera clàusula, tenim que L3 queda instanciada a L2, de manera que L3 s’instancia correctament.

Cas inductiu

Suposem que la llista L1 té almenys un element, és a dir, és de la forma [X | Y1]. Y1 amb longitud n+1. Aleshores, per hipòtesi d’inducció, la consulta

| ?- concat(Y1, L2, L3)

on Y3 és una variable, instancia Y3 a la concatenació de Y1 i Y2. Y1 té longitud n.
Per la segona clàusula, la consulta

| ?- concat([X|Y1], L2, L3).

instancia L3 a [X|Y3], que és la concatenació de X, Y1, Y2. Per tant, L3 queda instanciada correctament.


Entra