Lab2 Yves Conselvan

aluno: Yves Conselvan
ano/sem: 2008/2o.
data do laboratório (num. da semana) : 20/08/2008 (4)

Introdução

Neste laboratório continuamos o desenvolvimento do sistema de simulação iniciado no primeiro laboratório.

Primeiramente implementamos a classe Simulador para manipular objetos das classes anteriormente criadas. Para a execução dessa tarefa achei necessário efetuar primeiro a trasformação da lista de relatórios para tipos genéricos, ficando mais fácil manipular uma lista de alunos. Para facilitar o acesso à lista de alunos implementei a interface Iterator na classe Queue, deixando apenas o método remove em branco, pois exigiria complexidade adicional (e não se mostrou necessário até a atual implementação).

Após a implementação inicial da classe Simulador seguiu-se a modificação na estrutura da classe Aluno eliminando a herança e inserido a classe Comportamento pra representar características específicas de cada diferente aluno. Para a definição dos comportamentos adicionais fiz algumas alterações na classe Comportamento de forma que fosse possível definir no construtor se a propriedade era pseudo-aleatória, e nesse caso um valor máximo, ou não pseudo-aleatória, e nesse caso o valor da propriedade. Dessa forma foi possível não ficar repetindo métodos muito parecidos para sobreescrever as funções de acesso das propriedades para colocar o código que gerava o valor pseudo-aleatório.

O próximo passo foi a definição de diferentes tipos de instituição para os alunos, criando sub-classes de Aluno para cada uma das instituições, e consequentemente a alteração da classe Simulador para suportar as novas funcionalidades.

Desenvolvimento

O passo inicial do desenvolvimento foi a criação da classe Simulador para fazer a interface entre os objetos e o usuário. Optei por uma solução baseada em menus. A idéia era que na tela inicial fosse possível inserir alunos, mandar que os alunos façam e entreguem os relatórios, ou mandar que o professor efetue a correção dos relatórios. Para atingir este objetivo foi necessária a utilização de uma lista de alunos, de forma que os alunos são inseridos na lista e quando for selecionada a opção para fazer e entregar os relatórios itera-se pela lista de alunos chamado-se o método fazEEntregaRelatorio() em cada um deles. Sendo assim achei importante realizar primeiramente o item 5 do laboratório, de forma que a classe Simulador utilizasse a Queue genérica tanto para manter a lista dos relatórios quanto dos alunos. A antiga classe RelaQueueItem passou a se chamar QueueItem, e a classe Queue absorveu o código que estava na RelaQueue. RelaQueue apenas é sub-classe de Queue com o tipo definido.

Apresento o código das classes QueueItem, Queue e Simulador.

Classe QueueItem

//classe agora declarada com o tipo generico T
public class QueueItem<T>
{
    //o item aponta para o tipo genérico T
    private T item;
    private QueueItem next;
 
    //construtor da classe
    //recebe a referencia de um item T
    public QueueItem(T item)
    {
        this.item = item;
        this.next = null;
    }
 
    //retorna o proximo item da fila
    public QueueItem getNext()
    {
        return this.next;
    }
 
    //seta o proximo item da fila
    public void setNext(QueueItem p)
    {
        this.next = p;
    }
 
    //retorna o item T referenciado por este item da lista
    public T getItem()
    {
        return this.item;
    }
}

Classe Queue

import java.util.Iterator;
 
public class Queue<T> implements Iterator
{
    private QueueItem<T> inicio, fim, iterador;   
 
    //construtor da classe
    //cria um nó cabeça
    public Queue()
    {
        inicio = new QueueItem<T>(null);
        fim = inicio;
        iterador = inicio;
    }
 
    //coloca um item na fila    
    public void queue(T rela) 
    {
        fim.setNext(new QueueItem(rela));
        fim = fim.getNext();
    }
 
    //retira um item da fila    
    public T dequeue() 
    {
        T ret = null;
        if (inicio.getNext() != null)
        {            
            //este casting gerou um warning de operação insegura ou não checada
            //sem ele dá erro
            ret = (T)inicio.getNext().getItem();
            if (inicio.getNext() == fim) {
                fim = inicio;
            }
            inicio.setNext(inicio.getNext().getNext());            
        }
        return ret;
    }       
 
    //retorna se o iterator tem um proximo item
    public boolean hasNext()
    {
        boolean ret = true;
        if (iterador.getNext() == null)
        {
            ret = false;
            iterador = inicio;
        }
        return ret;
    }
 
    //retorna o proximo item do iterador
    public T next()
    {
        T ret = null;
        //verifica se tem um proximo
        if (this.hasNext()){
            //este casting gerou um warning de operação insegura ou não checada
            //sem ele dá erro
            ret = (T)iterador.getNext().getItem();
            iterador = iterador.getNext();
        }
        else {
            iterador = inicio;
        }
        return ret;
    }
 
    //remove o item apontado pelo iterador
    //não implementado
    public void remove()
    {        
    }
}

Classe Simulador

import java.io.InputStreamReader;
import java.io.Console;
 
public class Simulador
{
    //lista de alunos
    private static Queue<Aluno> alunos = new Queue<Aluno>();
    //lista de realtorios, matem o tipo RelaQueue
    private static RelaQueue relas = new RelaQueue();    
    //InputStreamReader para 
    private static InputStreamReader cin = new InputStreamReader(System.in);    
    private static Professor professor;
 
    public static void main(String args[])
    {
        professor = new Professor(relas);
        menu();
    }
 
    //laço do menu principal
    private static void menu() 
    {
        int opcao;
        boolean fim = false;
 
        do {
            System.out.println("\n1 - Inserir alunos\n2 - Entrega de relatorios\n3 - Correcao de relatorios\n4 - Sair");
            try {
                //laço para pegar uma opção válida
                do {
                    opcao = cin.read();        
                } while (opcao < 49 || opcao > 52);
                switch (opcao) 
                {
                    case 49:
                        insereAluno();
                        break;
                    case 50:
                        entregaRelatorios();
                        break;
                    case 51:
                        corrigeRelatorios();                
                        break;
                    case 52:
                        fim = true;
                        break;
                }
            }
            catch(Exception e)
            {
                System.out.println("Erro ao ler opcao");
                System.out.println(e.toString());
            }
        } while (!fim);        
    }  
 
    //insere um aluno na lista
    private static void insereAluno()
    {        
        int opcao;
        Aluno novo_aluno;
        String nome;        
 
        System.out.println("\nInserir aluno");        
 
        //tenta ler o nome do aluno
        //deu problema ao tentar rodar dentro do BlueJ
        //parece que a tela de saída do BlueJ não funciona bem como um console
        try {         
            Console c = System.console();
            nome = c.readLine("\nNome: ");            
        }
        catch (Exception e)
        {
            System.out.println("Nao foi possivel abrir o console");
            System.out.println("Nao sera possivel inserir um aluno");
            System.out.println("Tente utilizar o programa a partir de um console do sistema");
            return;
        }
 
        //passa o nome lido para a função que seleciona o tipo do aluno
        novo_aluno = selecionaTipo(nome);
        if (novo_aluno == null) {
            //nao criou o aluno
            return;
        }
        //insere o novo aluno na lista
        alunos.queue(novo_aluno);        
 
    }   
 
    //seleciona o tipo do aluno e retorna um objeto do tipo selecionado
    private static Aluno selecionaTipo(String nome)
    {
        Aluno aluno = null;
        int opcao;
        System.out.println("Selecione o tipo:\n1 - Esforcado\n2 - SafoPreguicoso");        
        try {
            //laço para pegar uma opção válida
            do {
                opcao = cin.read();        
            } while (opcao < 49 || opcao > 50);
            switch (opcao) 
            {
                case 49:
                    aluno = new AlunoEsforcado(nome, relas);
                    break;
                case 50:
                    aluno = new AlunoSafoPreguicoso(nome, relas);
                    break;
            }        
        }
        catch(Exception e)
        {
            System.out.println("Erro ao ler opcao");
        }      
        return aluno;
    }
 
    //itera pelos alunos da lista e manda fazer e entregar o relatório
    private static void entregaRelatorios()
    {
        Aluno aluno;
        System.out.println("\nEntrega de relatorios\nAlunos na lista de alunos:");
        while (alunos.hasNext())
        {
            aluno = alunos.next();
            System.out.println(aluno.getNome());
            aluno.fazEEntregaRelatorio();
        }
    }
 
    //manda o professor corrigir os relatórios
    private static void corrigeRelatorios()
    {
        System.out.println("\nCorrecao de relatorios");
        professor.corrigirRelatorios();
    }
}

Nas modificações da classe Aluno surgiu a nova classe Comportamento. Para tentar generalizar mais os comportamentos criei um construtor que permite selecionar se alguma das propriedades é aleatória e neste caso um valor máximo para a propriedade. Se a propriedade não é aleatória então o valor passado será tratado como o valor da propriedade.

Apresento abaixo o código da classe comportamento e de suas sub-classes.

Classe Comportamento

import java.util.Random;
 
public abstract class Comportamento
{    
    private float inteligencia;
    private float dedicacao;
    private boolean inteligencia_aleatoria = false;
    private boolean dedicacao_aleatoria = false;
    private Aluno aluno;
 
    //construtor para inteligencia e dedicacao determinadas
    public Comportamento(Aluno aluno, float inteligencia, float dedicacao) 
    {
        this.aluno = aluno;
        this.inteligencia = inteligencia;
        this.dedicacao = dedicacao;        
    }
 
    //construtor com possibilidade de selecionar uma propriedade como aleatoria
    public Comportamento(Aluno aluno, boolean inteligencia_aleatoria, float inteligencia, boolean dedicacao_aleatoria, float dedicacao) 
    {
        this.aluno = aluno;
        this.inteligencia = inteligencia;
        this.dedicacao = dedicacao;
        this.inteligencia_aleatoria = inteligencia_aleatoria;
        this.dedicacao_aleatoria = dedicacao_aleatoria;        
    }
 
    //retorna a inteligencia
    public float getInteligencia()
    {
        if (inteligencia_aleatoria) {
            return valorAleatorio(this.inteligencia);
        }
        else {
            return this.inteligencia;
        }
    }
 
    //retorna a dedicação
    public float getDedicacao()
    {
        if (dedicacao_aleatoria) {
            return valorAleatorio(this.dedicacao);
        }
        else {
            return this.dedicacao;
        }
    }
 
    //gera um valor aleatorio com um maximo
    private float valorAleatorio(float maximo)
    {
        Random generator = new Random();
        float r = generator.nextFloat();
        return r * maximo;        
    }
}

Classe Imprevisivel

public class Imprevisivel extends Comportamento
{
    public Imprevisivel(Aluno aluno)
    {        
        super(aluno, true, 1, true, 1);
    }
}

Classe Pemba

public class Pemba extends Comportamento
{
    public Pemba(Aluno aluno)
    {        
        super(aluno, true, 0.5f, true, 0.5f);
    }
}

Classe Esforcado

public class Esforcado extends Comportamento
{
    public Esforcado(Aluno aluno)
    {
        super(aluno, 0.5f, 1);
    }
}

Classe SafoPreguicoso

public class SafoPreguicoso extends Comportamento
{
    public SafoPreguicoso(Aluno aluno)
    {
        super(aluno, false, 1, true, 0.5f);
    }
 
}

Classe Burro

public class Burro extends Comportamento
{
    public Burro(Aluno aluno)
    {        
        super(aluno, 0, 0);
    }
}

Classe Summa

public class Summa extends Comportamento
{
    public Summa(Aluno aluno)
    {        
        super(aluno, 1, 1);
    }
}

Após a implementação destas novas classes a classe Aluno deixou de ser abstrata e deixaram de existir as sub-classes AlunoSafoPreguicoso e AlunoEsforçado.

Apresento abaixo as principais alterações na classe Aluno

//classe agora não é mais abstrata
public class Aluno
{
...
    //referencia a um comportamento
    private Comportamento comportamento;
...
    public Aluno(String nome, RelaQueue queue)
    {
    ...
        //seta como padrão o comportamento esforçado
        this.comportamento = new Esforcado(this);
    }   
 
    //retorna a inteligencia a partir do comportamento
    public float getInteligencia()
    {
        return comportamento.getInteligencia();
    }
 
    //retorna a dedicação a partir do comportamento
    public float getDedicacao()
    {
        return comportamento.getDedicacao();        
    }
...
    //novo método para setar o comportamento
    public void setComportamento(Comportamento comportamento) throws Exception
    {
        this.comportamento = comportamento;   
    }
}

Após esta alteração foi simples fazer uma implementação para várias instituições utilizando herança a partir da classe Aluno.

Apresento abaixo o código da três subclasse criadas AlunoITA, AlunoUSP e AlunoUnicamp

Classe AlunoITA

public class AlunoITA extends Aluno
{
    public AlunoITA(String nome, RelaQueue queue)
    {
        super(nome, queue);
    }
 
    public void setComportamento(Comportamento comportamento) throws Exception 
    {
        if(comportamento instanceof Burro)
        {
            throw new Exception(); 
        }
        super.setComportamento(comportamento);
    }
}

Classe AlunoUSP

public class AlunoUSP extends Aluno
{
    public AlunoUSP(String nome, RelaQueue queue)
    {
        super(nome, queue);
    }
 
    public void setComportamento(Comportamento comportamento) throws Exception 
    {
        if(comportamento instanceof Summa || comportamento instanceof SafoPreguicoso) {
            throw new Exception();
        }
        super.setComportamento(comportamento);
    }
}

Classe AlunoUnicamp

public class AlunoUnicamp extends Aluno
{
    public AlunoUnicamp(String nome, RelaQueue queue)
    {
        super(nome, queue);
    }
 
    public void setComportamento(Comportamento comportamento) throws Exception 
    {
        if(comportamento instanceof Summa || comportamento instanceof SafoPreguicoso) {
            throw new Exception();
        }
        super.setComportamento(comportamento);
    }
}

Após estas novas implementações foi necessário fazer modificações na classe Simulador de forma que o usuário pudesse fazer a seleção de instituição e comportamento. O método insereAluno fo modificado, o método selecionaTipo saiu e surgiram os novos métodos selecionaInstituicao e selecionaComportamento. Apresento abaixo fragmentos da classe simulador com as alterações.

public class Simulador
{
...
 
    private static void insereAluno()
    {        
        int opcao;
        Aluno novo_aluno;
        Comportamento comportamento;
 
        Console c = System.console();
 
        System.out.println("\nInserir aluno");
        String nome = c.readLine("\nNome: ");
 
        novo_aluno = selecionaInstituicao(nome);
        if (novo_aluno == null) {
            return;
        }
        alunos.queue(novo_aluno);        
 
        comportamento = selecionaComportamento(novo_aluno);               
 
        if (comportamento != null) {
            try {
                novo_aluno.setComportamento(comportamento);
            }
            catch(Exception e) 
            {
                System.out.println("Operacao nao permitida");
            }
        }
    }
 
    private static Aluno selecionaInstituicao(String nome)
    {
        Aluno aluno = null;
        int opcao;
        System.out.println("Selecione uma instituicao: \n1 - ITA\n2 - USP\n3 - Unicamp");
        try {
            do {
                opcao = cin.read();        
            } while (opcao < 49 || opcao > 51);
            switch (opcao) 
            {
                case 49:
                    aluno = new AlunoITA(nome, relas);
                    break;
                case 50:
                    aluno = new AlunoUSP(nome, relas);
                    break;
                case 51:
                    aluno = new AlunoUnicamp(nome, relas);
                    break;
            }        
        }
        catch(Exception e)
        {
            System.out.println("Erro ao ler opcao");
        }            
        return aluno;
    }
 
    private static Comportamento selecionaComportamento(Aluno aluno)
    {
        Comportamento comportamento = null;
        int opcao;
        System.out.println("Selecione o comportamento:");
        System.out.println("1 - Burro\n2 - Esforcado");
        System.out.println("3 - Imprevisivel\n4 - Pemba");
        System.out.println("5 - SafoPreguicoso\n6 - Summa");    
        try {
            do {
                opcao = cin.read();        
            } while (opcao < 49 || opcao > 54);
            switch (opcao) 
            {
                case 49:
                    comportamento = new Burro(aluno);
                    break;
                case 51:
                    comportamento = new Imprevisivel(aluno);
                    break;
                case 52:
                    comportamento = new Pemba(aluno);
                    break;
                case 53:
                    comportamento = new SafoPreguicoso(aluno);
                    break;
                case 54:
                    comportamento = new Summa(aluno);
                    break;                
            }        
        }
        catch(Exception e)
        {
            System.out.println("Erro ao ler opcao");
        }      
        return comportamento;
    }
 
...
}

Apresento abaixo as telas com o diagrama de classes do BlueJ, tela de teste e saída dos testes.

Diagrama de classes

diagrama.jpg

Tela de testes

testes.jpg

Saída dos testes

saida.jpg

Abaixo apresento a execução a partir de um console do método main da classe Simulador

execucao.jpg

Conclusão

Este laboratório foi uma continuação do primeiro laboratório e apresentou um nível de complexidade um pouco maior. O código da lista genérica ficou por nossa conta, acho que isso estimula o desenvolvimento de código.
Não consegui rodar o método main da classe Simulador a partir do BlueJ, pois não era possível pegar o console, foi necessário rodar a partir da linha de comando.
Uma questão que ainda apresenta dificuldades de escalabilidade é a necessidade de se utilizar switch's para instanciar cada um dos diferentes tipos de classe.

Add a New Comment
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License