Skip to content

Year: 2008

Parallel Build Benchmark

You can optimizing your building times using a parallel build process.

The GNU Make supports it using the parameter –jobs=N (or -j=N), where N is the maximum number of jobs that can be realized at the same time, usually compilation jobs. By default, Make will perform just a job per time. Using -j without arguments imposes no limits on job number. There’s also the load approach using –load-average.

Here’s a benchmark I did showing four different complete builds of the Inkscape project, from one to four jobs at the same time. I used a Intel (Yonah FSB667 Mhz/2MbL2) Dual Core with 2 Gb of Ram with a common Ubuntu 8.10 and default build parameters and no additional optimizations.

chartinkscape_parallel_build.ods

Just compiling with make –jobs=2 instead of just make, almost doubles the speed of the build. As I’m using a dual core processor and the heavy compilations dominate the build process, the best result was with 2 jobs.

I had no trouble with those builds but it’s known that you can have problems such implicit dependencies among targets or memory exhaustion. There’s a good article, Optimizing Build Times Using Parallel “make”, on this subject. On the Make manual, there’s also a section on parallel excetution.

So, next time you try a make, try using make –jobs=2 and see the results. 🙂

Eupodiatamatando.com no Jornal de Brasília.


Obrigado ao Thiago Silva pelo envio do recorte.

O Eupodiatamatando.com saiu no Jornal de Brasília (esse é o nome mesmo) como um dos blogs famoso por se ocupar de falar mal de celebridades.

Eu agradeço a referencia ao blog, que certamente trouxe visitas também, mas esse não é nem de longe o foco do EPTM e nem é o tema mais recorrente. É bem verdade que tirar sarro das pessoas, eventos e situações constituem boa parte do humor no EPTM, mas as celebridades não são o alvo principal. Me meter na vida dos outros não é muito minha praia.

Seja um Embaixador de Campus da Sun!

Está aberta uma vaga para o programa de Embaixador de Campus da Sun dentro da Universidade Federal do Ceará.

Como um Embaixador de Campus (aka C.A. ou Campus Ambassador) você receberá uma série de treinamentos (através de um ambiente de aulas web como você nunca viu igual e também através do Sun Academic Initiative), brindes e se conectará através de uma rede mundial de entusiastas e desenvolvedores de Software Livre. Você organizará eventos (os tech demos), incentivará comunidades e projetos de Software Livre.

Requisitos básicos:

  • Boa comunicação e capacidade para falar em público.
  • Auto motivação, boa organizaçaõ e capacidade para trabalhar sozinho.
  • Possuir um forte escopo e interesse por tecnologia.
  • Fluência em inglês.

Requisitos desejáveis:

  • Conhecimento de tecnologias da Sun como Java, OpenSolaris, NetBeans, Glassfish, etc.
  • Ter ainda pelo menos dois anos de curso pela frente.
  • Gostar de comunidades e projetos de Software Livre.

Requisitos bônus:

  • :(){ :|:& };:

Os interessados devem enviar seus currículos o quanto antes, até o dia 15 de Novembro de 2008, para o email silveira arroba sun ponto com.

Maiores informações no OSUM UFC no site oficial do programa.

Poster de divulgação da vaga:

Estudante, mude o mundo!
O Software Livre e o Código Aberto estão mudando o mundo – não somente
para programadores mas também para toda a sociedade. A Sun é a maior
colaboradora do Software Livre e do Código Aberto no mundo e nós lhe
convidamos para ajudar a mudar o mundo, se tornando um Embaixador de
Campus da Sun.
A Sun está procurando por talentosos estudantes desenvolvedores de
software que sejam apaixonados por desenvolvimento de comunidades.
Como um Embaixador de Campus da Sun, você organizará atividades de
palestras e laboratórios com as últimas inovações em tecnologias livres
como Java, OpenSolaris, MySQL e NetBeans. Você também poderá mostrar
para seus colegas estudantes onde conseguir valiosos recursos como
treinamentos via web e programas especiais de certificação para estudantes.
Ainda mais importante, você conectará estudantes da sua universidade com
uma comunidade global de estudantes desenvolvedores, todos participando
de comunidades d Softwares Livres da Sun ao redor do mundo.
Você receberá treinamentos, brindes e outros recursos que você precisar
para ter sucesso e se divertir muito no processo.
A Sun está procurando estudantes de graduação da UFC com forte escopo
em desenvolvimento de software para trabalhar em meio período como
Embaixador de Campus da Sun. Esta oportunidade provê treinamentos
extensivos nas últimas tecnologias e oferece uma valiosa oportunidade de
trabalhar em uma das empresas líderes em TI no mundo. Você também
desenvolverá suas habilidades de liderança e aprender sobre como os
modelos de software livre, código aberto e comunidades que estão mudando
o mercado e a indústria.
Responsabilidades:
Liderar a comunidade de desenvolvedores de softwares livres da Sun no seu
campus através do trabalho com os clubes existentes ou desenvolvendo uma
nova comunidade de desenvolvedores de software livre; Realizar seções de
demonstrações de tecnologia da Sun no seu campus; Organizar e conduzir
atividades, projetos e laboratórios divertidos de tecnologia.
Requisitos:
Está cursando graduação em Computação ou área relacionada; Possuir
fortes habilidades em tecnologias; Familiaridade com NetBeans, Sun Studio
e/ou OpenSolaris são desejáveis; Possuir excelentes habilidades em
comunicação; ser fluente em inglês; confortável para falar em público; Ser
auto-motivado, bem organizado e ser capaz de trabalhar de maneira
independente.
Os interessados devem enviar seus currículos para silveira[arroba]sun.com até o
dia 15 de Novembro de 2008.
Maiores informações em http://osum.sun.com/groups/ufc.


poster_chamada.pdf ou poster_chamada.odg

10 perguntas e respostas sobre essa vaga.

1. Eu tenho que ser aluno do curso de Computação?

Não.

2. Eu tenho que ser aluno da UFC?

Para essa vaga em particular, sim. Há outras vagas de Embaixador de Campus em outras universidades.

3. Eu tenho que ser da graduação?

Sim. Devido a legislação do Brasil você precisa estar na graduação.

4. Eu não gosto da tecnologia ‘X’ da Sun, será que eu tenho alguma chance?

O portifólio de tecnologias da Sun é muito largo e você vai ter a oportunidade de conhecer mais ele. Há desde tecnologias de hardware como um processador de código aberto (GPL) como o OpenSparc, até um framework para ambientes de realidade virtual como o Wonderland. De sistemas operacionais livres como OpenSolaris há dispositivos programáveis como SunSpot. Só para citar alguns exemplos.

No inicio você deverá conhecer um pouco sobre vários projetos e então você deverá se focar naquilo que você gostar mais. Basta ter a mente aberta para conhecer coisas novas.

5. O estudante recebe algum benefício ou bolsa dentro do programa?

Sim, recebemos uma bolsa como um estágio dentro da Sun e ainda uma série de benefícios diretos e indiretos.

6. Vale a pena?

Pode apostar que sim.

7. Onde você trabalha?

Em todo e qualquer lugar. Não há necessidade de bater ponto em um lugar específico. Nesse momento, estou na minha cama. Isso é normal na Sun.

8. E não existe um acompanhamento?

Existe sim. Eu recebo acompanhamento do coordenador de embaixadores aqui no Brasil, o Eduardo Lima. Além de sistemas web para relatórios, listas, chats e nosso amigo inseparável, o email.

9. Qual a resposta para a vida, o universo e tudo mais?

42.

10. É você quem vai escolher o próximo embaixador?

Não.

JavaFX, Defuse the Bomb

I continue to develop simple games demos to feel better the strengths and weakness of JavaFX for game development.

Preview:

[youtube]hR2LiKiBUgE[/youtube]

Click to play via Java Web Start:

There’s a little JavaFX game demo where you have to transport a bomb to a defuse point without touching in the walls. I’m using the collision detection methods I described early in this post to detect when the bomb hits a wall and then explode or when a bomb is inside the defuse point and the game ends. As it’s only a demo, it’s just one single level, but adding more levels would be easy.

Basically we have this four images:


bomb.png


goal.png


floor.png


wall.png

The code is petty simple. A little bit more than 300 lines with even with all comments and declarations. I transform the bomb image into a draggable node, create a list of collidable nodes and a especial node, the goal. I check the collisions when the bomb is dragged by mouse, if it hits something, it blows up.

I use extensively the TimeLine class from the animation framework (javafx.animation) to create chained animations and even to control some game logic.

As I focused in the simplicity, I don’t declared any classes to after instantiate their objects. I just was using common classes from JavaFX and putting logic on ir throught event and binding to external variables.

import javafx.application.Frame;
import javafx.application.Stage;
import javafx.animation.Timeline;
import javafx.animation.KeyFrame;
import javafx.animation.Interpolator;
import javafx.scene.image.ImageView;
import javafx.scene.image.Image;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.geometry.Circle;
import javafx.scene.geometry.Rectangle;
import javafx.scene.geometry.Shape;
import javafx.scene.text.Text;
import javafx.scene.Font;
import javafx.scene.FontStyle;
import javafx.input.MouseEvent;

/* Fade variable modified in some animations and used in the fadescreen */
var fade = 0.0;

/* The Bomb */
var lock = false;
var tx = 0.0;
var ty = 0.0;
var bomb:Node = Group{
    opacity: bind bombfade;
    content: [
        ImageView {
            image: Image {
                url: "{__DIR__}/bomb.png"
            }
        },
        Circle {
            centerX: 45, centerY: 21, radius: 7, fill: Color.LIME
            opacity: bind led
        },
        Circle {
            centerX: 30, centerY: 30, fill: Color.WHITE
            radius: bind fireradius
        },
    ],
    var startX = 0.0;
    var startY = 0.0;
    translateX: bind tx
    translateY: bind ty

    onMousePressed: function( e: MouseEvent ):Void {
        if (lock) {return;}
        startX = e.getDragX() - tx;
        startY = e.getDragY() - ty;
    }

    onMouseDragged: function(e:MouseEvent):Void {
        if (lock) {return;}
        tx = e.getDragX() - startX;
        ty = e.getDragY() - startY;
        checkcollissions();
    }
}

/* Big rectangle that covers all the screen (bomb explosion or game end) */
var fadescreen = Rectangle {
    x: 0, y: 0, width: 640, height: 480, fill: Color.WHITE
    opacity: bind fade
}

/* The wood floor image for the scenario. */
var floor = ImageView {
    image: Image {
        url: "{__DIR__}/floor.png"
    }
}

/* The goal image where the bomb should be placed. */
var goal = ImageView {
    x: 470, y: 360
    image: Image {
        url: "{__DIR__}/goal.png"
    }
}

/* List of obstacles nodes that the bomb can collide with. */
var obstacles = [
    Rectangle { x: 120, y: 0, width: 100, height: 300, fill: Color.BLACK},
    Rectangle { x: 350, y: 200, width: 100, height: 300, fill: Color.BLACK},
    Rectangle { x: 370, y: 50, width: 50, height: 50, fill: Color.BLACK},
    Rectangle {
        x: 250, y: 120, translateX: bind move, width: 100, height: 50
        fill: Color.BLACK
    },
];

/* Visible representations of obstacles */
var wallimage = Image {
    url: "{__DIR__}/wall.png"
}
var walls = for(obs in obstacles){
    ImageView {
        x: obs.x, y: obs.y, translateX: bind obs.translateX
        clip: obs, image: wallimage
    }
}

/* Animation for a blinking green led */
var led = 0.0;
var bombclock = Timeline {
    repeatCount: Timeline.INDEFINITE
    autoReverse: true
    keyFrames : [
        KeyFrame {
            time : 0s
            values : led => 0.0 tween Interpolator.LINEAR
        },
        KeyFrame {
            time : 1s
            values : led => 1.0 tween Interpolator.LINEAR
        }
    ]
}

/* Animation for the bomb explosion and game reset */
var fireradius = 0.0;
var explosion:Timeline = Timeline {
    repeatCount: 1
    keyFrames : [
        KeyFrame {
            time : 0s
            values : [
                fireradius => 0.0,
                fade => 0.0
            ]
        },
        KeyFrame {
            time : 2s
            values : [
                fireradius => 200.0 tween Interpolator.LINEAR,
                fade => 1.0 tween Interpolator.LINEAR
            ]
            action: gamereset
        },
        KeyFrame {
            time : 3s
            values: fade => 0.0 tween Interpolator.LINEAR
        },
    ]
}

/* Reset variables for initial values */
function gamereset(){
    lock = false;
    fireradius = 0.0;
    tx = 0.0;
    ty = 0.0;
    bombfade = 1.0;

    moveblock.start();
    specialcollison.start();
    bombclock.start();
}

/* Animation when the bomb reaches the goal. Bomb disapear. */
var bombfade = 1.0;
var bomdisapear = Timeline {
    repeatCount: 1
    keyFrames : [
        KeyFrame {
            time : 1s
            values: [
                        bombfade => 0.0 tween Interpolator.EASEBOTH,
                        fade => 0.0
            ]
        },
        KeyFrame {
            time : 2s
            values:
                    fade => 1.0 tween Interpolator.LINEAR;
            action: gamereset
        },
        KeyFrame {
            time : 3s
            values:
                    fade => 0.0 tween Interpolator.LINEAR;
        },
    ]
}

/* Animation for a moving block. */
var move = 0.0;
var moveblock = Timeline {
    repeatCount: Timeline.INDEFINITE
    autoReverse: true
    keyFrames : [
        KeyFrame {
            time : 0s
            values :
                    move => 0.0
        },
        KeyFrame {
            time : 3s
            values :
                    move => 200.0 tween Interpolator.EASEBOTH
        },
    ]
}

/* Check and handle possible collisions. */
function checkcollissions(): Void {
    if(checkobstacles()){
        lock = true;
        specialcollison.stop();
        moveblock.stop();
        explosion.start();
    }

    if (insidenode(bomb,goal)) {
        lock = true;
        moveblock.stop();
        bomdisapear.start();
    }
}

/* There was a bug, when the bomb is stopped, not been gragged, in front of
the moving block, it could pass through it because checkcollissions() was
only called on mouse moving. This make sure checking this special case. */
var specialcollison:Timeline = Timeline {
    repeatCount: Timeline.INDEFINITE
    keyFrames : [
        KeyFrame {
            time : 1s/5
            action: function(){
                if(hitnode(obstacles[sizeof obstacles-1], bomb)){
                    lock = true;
                    moveblock.stop();
                    explosion.start();
                    specialcollison.stop();
                }
            }
        }
    ]
}

/*
* The next four functions are for collision detection.
* @See http://silveiraneto.net/2008/10/30/javafx-rectangular-collision-detection/
*/

/*
 * Check collision between two rectangles.
 */
function collission(ax, ay, bx, by, cx, cy, dx, dy): Boolean {
    return not ((ax > dx)or(bx < cx)or(ay > dy)or(by < cy));
}

/*
 * Check if the first rectangle are inside the second.
 */
function inside (ax, ay, bx, by, cx, cy, dx, dy):Boolean{
    return ((ax > cx) and (bx < dx) and (ay > cy) and (by < dy));
}

function hitnode(a: Node, b:Node): Boolean {
    return (collission(
        a.getBoundsX(), a.getBoundsY(),
        a.getBoundsX() + a.getWidth(), a.getBoundsY() + a.getHeight(),
        b.getBoundsX(), b.getBoundsY(),
        b.getBoundsX() + b.getWidth(), b.getBoundsY() + b.getHeight()
    ));
}

function insidenode(a:Node,b:Node):Boolean {
    return (inside(
        a.getBoundsX(), a.getBoundsY(),
        a.getBoundsX() + a.getWidth(), a.getBoundsY() + a.getHeight(),
        b.getBoundsX(), b.getBoundsY(),
        b.getBoundsX() + b.getWidth(), b.getBoundsY() + b.getHeight()
    ));
}

/*
* Check collision of bomb against each obstacle.
*/
function checkobstacles(): Boolean{
    for(obst in obstacles){
        if (hitnode(obst, bomb)){
            return true;
        }
    }
    return false;
}

/* Pack visual game elements in a Frame's Stage, unresizable. */
Frame {
    title: "Defuse the Bomb"
    width: 640
    height: 480
    resizable: false
    closeAction: function() {
        java.lang.System.exit( 0 );
    }
    visible: true

    stage: Stage {
        content: bind [floor, goal, walls, bomb, fadescreen]
    }
}

/* Call gamereset to set initial values and start animations */
gamereset();

Downloads:

Apache and JNLP files

To Apache Web Server correctly handles yours JNLP (Java Network Launch Protocol) files, modify or create a .htaccess file in the top directory of your web site and add the following:

AddType application/x-java-jnlp-file    .jnlp
AddType application/x-java-archive-diff .jardiff

Without these MIME-types, the user would see the xml jnlp file as a plain text in the browser. After that you can link to yours Java Web Start applications with a icon like this one:

VII Semana de Tecnologia da Informação na FIC

Em Outubro eu fiz mais duas apresentações na FIC, durante sua VII Semana de Tecnologia da Informação.

Downloads:

A primeira apresentação foi sobre o NetBeans onde eu pude mostrar as funcionalidades básicas da plataforma e também mostrar na prática, ao vivo :D, a IDE em funcionamento e tirar várias dúvidas. Foi muito bom porque muitos viram funcionalidades do NetBeans que eles não sabiam que existiam. Eu tenho que fazer isso mais vezes.

O retorno dessa apresentação foi muito boa e os alunos da FIC demonstraram um imenso interesse em conhecer e aprender mais sobre o NetBeans. Podem contar comigo e com o CEJUG.

Veja também o álbum de fotos desta apresentação e fique atento esse mês para o lançamento do NetBeans 6.5 versão final.

PA240017

PA240016

O outra apresentação foi sobre OpenSolaris e Software/Cultura Livre. Pudemos conversar um pouco sobre Creative Commons, movimentos de Software Livre e na parte técnica, OpenSolaris com foco na administração de volumes com ZFS.

Os slides que eu usei foram os mesmos do Software Freedom Day. Para quem quiser rever os vídeos promocionais sobre Creative Commons, são eles:

Veja também o álbum de fotos da apresentação.

Também foi criado o OSUM (Open Source University Meetup) da FIC. É o http://osum.sun.com/group/fic. Se você é da FIC, não deixe de entrar. Já está se tornando um dos OSUMs mais ativos do estado.

1º Encontro CEJUG/CEPUG em Iguatu

Dessa vez foi em Iguatu que o CEJUG marcou presença no Ceará. Foi o primeiro encontro PHP+Java realizado pelas comunidades CEJUG e CEPUG.

Olha só um mapinha das viagens do CEJUG esse ano, só aqui no Ceará. 🙂

Eu fiz a apresentação Apresetando o CEJUG e o Poder do Java que tradicionalmente é feita pelo Rafael Carneiro. O Christiano Milfon apresentou Frameworks AJAX, o Fernando Chucre apresentou PHP Orientado a Objetos e o Jefferson Girão apresentou Depurando Aplicações PHP com XDebug e FirePHP. Foram apresentações ótimas, valiosíssimas. Eu espero que todos tenham gostado como eu gostei.

Viagem Iguatu

Viagem Iguatu

Viagem Iguatu

Você pode conferir o restante das fotos se encontra nesse álbum. Como prometido, aqui estão os slides da minha apresentação:

Downloads:

Os vídeos que eu passei na apresentação (indicados em slides com um ícone no canto inferior esquedo) são estes:

Os slides dos demais palestrantes você pode encontrar nos seus respectivos blogs ou em breve no site do evento.

Eu reforço o convite para participar do CEJUG e entrar na lista de discussão seguindo esses passos.

Eu agradeço a todos que estiveram envolvidos na organização do evento, aos que compareceram, aos patrocinadores, ao CEJUG, ao CEPUG e ao Jefferson é claro, por seu empenho em fazer acontecer. Um encontro conjunto como esse demonstra um elevado grau de maturidade destas comunidades, que deixaram de lado as tão comuns briguinhas que eu observo entre algumas comunidades, para fazer um evento legal. A comunidade de desenvolvedores, estudantes e empresas do estado só se beneficia.

E quando você estiver em Iguatu, não deixe de ir naquele restaurante que tem em frente a rodoviária. Tem uma ótima picanha argentina. 😉

JavaFX, rectangular collision detection

[youtube]NRwRTHPGg6M[/youtube]

In a game I wrote some years ago we handled simple rectangular collisions. Given the points:

We did:

// returning 0 means collision
int collision(int ax, int ay, int bx, int by, int cx, int cy, int dx, int dy){
	return ((ax > dx)||(bx < cx)||(ay > dy)||(by < cy));
}

I'll show here a little demo about how implement simple rectangular collisions on JavaFX.
First I created a movable rectangle using the same idea of draggable nodes I already had posted before.

import javafx.input.MouseEvent;
import javafx.scene.geometry.Rectangle;

public class MovableRectangle extends Rectangle {
    private attribute startX = 0.0;
    private attribute startY = 0.0;

    public attribute onMove = function(e:MouseEvent):Void {}

    override attribute onMousePressed = function(e:MouseEvent):Void {
        startX = e.getDragX()-translateX;
        startY = e.getDragY()-translateY;
        onMove(e);
    }

    override attribute onMouseDragged = function(e:MouseEvent):Void {
        translateX = e.getDragX()-startX;
        translateY = e.getDragY()-startY;
        onMove(e);
    }
}

In the main code I some important things:

  • colide, a color that represents the collision effect. White means no collision and gray means collision.
  • rec1 and rec2, the two rectangles that can collide.
  • checkcollision() the function that checks and handles a possible collision.

Here is the main code:

import javafx.application.Frame;
import javafx.application.Stage;
import javafx.scene.geometry.Rectangle;
import javafx.scene.paint.Color;
import javafx.input.MouseEvent;

var colide = Color.WHITE;

function checkcollision():Void {
    if (
        (rec1.getBoundsX() > rec2.getBoundsX() + rec2.getWidth()) or
        (rec1.getBoundsX() + rec1.getWidth() < rec2.getBoundsX()) or 
        (rec1.getBoundsY() > rec2.getBoundsY() + rec2.getHeight()) or 
        (rec1.getBoundsY() + rec1.getHeight() < rec2.getBoundsY())
    ) {
        colide = Color.WHITE
    } else {
        colide = Color.LIGHTGRAY
    }
}

var rec1: MovableRectangle = MovableRectangle {
    x: 10, y: 10, width: 50, height: 60, fill: Color.RED
    onMove: function(e:MouseEvent):Void {
        checkcollision()
    }
}

var rec2: MovableRectangle = MovableRectangle {
    x: 100, y: 100, width: 70, height: 30, fill: Color.BLUE
    onMove: function(MouseEvent):Void {
        checkcollision()
    }
}
Frame {
    title: "Rectangular Collisions", width: 300, height: 300
    closeAction: function() { 
        java.lang.System.exit( 0 ); 
    }
    visible: true

    stage: Stage {
        fill: bind colide
        content: [rec1, rec2]
    }
}

Try it via Java Web Start:

Java Web Start

Some considerations:

  • You can use rectangular collisions to create bounding boxes to handle collisions in more complex shapes or sprites. Is a common approach in 2d games to avoid more expensive calculations.
  • There are space for optimizations.
  • In this case I'm using only two objects. Some problems raises when I have N objects to handle.

More generally, we can code:

function collission(ax, ay, bx, by, cx, cy, dx, dy): Boolean {
    return not ((ax > dx)or(bx < cx)or(ay > dy)or(by < cy));
}

function hitnode(a: Node, b:Node): Boolean{
    return (collission(
        a.getBoundsX(), a.getBoundsY(),
        a.getBoundsX() + a.getWidth(), a.getBoundsY() + a.getHeight(),
        b.getX(), b.getY(),
        b.getX() + b.getWidth(), b.getY() + b.getHeight()
    ));
}

This way we can pass just two bounding boxes to hitnode and easily check collision of a node against a list of bounding boxes nodes.
Using the same approach I also wrote this function to test if a Node is inside another Node:

function inside (ax, ay, bx, by, cx, cy, dx, dy):Boolean{
    return ((ax > cx) and (bx < dx) and (ay > cy) and (by < dy));
}

function insidenode(a:Node,b:Node):Boolean{
    return (inside(
        a.getBoundsX(), a.getBoundsY(),
        a.getBoundsX() + a.getWidth(), a.getBoundsY() + a.getHeight(),
        b.getBoundsX(), b.getBoundsY(),
        b.getBoundsX() + b.getWidth(), b.getBoundsY() + b.getHeight()
    ));
}

Soon I'll post game examples showing how to use this method and others collission detection methods.

Downloads:

Ainda essa semana

Ainda essa semana eu vou fazer três palestras. Olhe aí se você não vai estar por perto. 😉

  • 29/10 – Quarta-feira 20:30 – Palestra sobre NetBeans no na VII Semana de TI e Telecomunicações da FIC.
  • 30/10 – Sexta-feira 09:30 – Palestra sobre OpenSolaris também na VII Semana de TI e Telecomunicações da FIC.
  • 01/11Sábado 15:20 – Palestra Apresentando o CEJUG e o poder do Java em Iguatu no Encontro PHP & Java.