Month: July 2020

Oferta de trabalho (em Lisboa)

+infos(oficial): https://www.zpx.pt/

Tags :

Memoire’44, as expansões

” all these Memoir ’44 expansions should be back on stores before the end of the year!

– Pacific Theater
– Mediterranean Theater
– Winter Wars
– Eastern Front
– Terrain Pack
– Operation Overlord
– Winter/Desert Map.”

+infos(rede social): LINK

Tags : , , ,

Oferta de trabalho (em Lisboa)

A Marmalade Game Studio PT está neste momento à procura de um/a Concept Artist.

+infos(oficial): LINK

Tags :

Oferta de trabalho (em Lisboa)

A Marmalade Game Studio PT está neste momento à procura de um/a Graphic Designer para integrar a equipa de Marketing.

+infos(oficial): LINK

Tags :

Humble Game Creator bundle (uma campanha)

Um conjunto de assets para o desenvolvimentos dos jogos, e da lista consta:

Music:
Locked contentTales Of The Far East
Inspirational Music Pack Vol 1
Retro Music Pack
16-Bit Fantasy Action Music Pack
Grand Adventure Music Mega Pack
Madness Music Pack
Inspirational Music Pack Vol 2
Inspirational Music Pack Vol 3
Inspirational Music Pack Vol 4
Dragon’s Den Resource Pack
Survival Horror Music Mega-Pack Vol.2
Nightmares Music Pack
Classical Adventure
Medieval Music Pack
Creature Feature SFX

Graphics:
Sci-Fi Backgrounds
Backgrounds
2.5D Character Pieces Vol. 2
PVGames Sci-Fi Game Assets
Japanese School Interior Game Assets
Forest Graveyard Game Assets
2.5D Character Pieces Vol. 3
Batting Center Game Assets
2.5D Character Pieces Vol. 1
Pixel Animations And Effects
Train Station Game Assets
2.5D Medieval Buildings Vol. 2
2.5D Medieval Buildings Vol. 1
Kanagawa Game Assets
Omega Modern Graphics Pack
Japanese Arcade Game Assets + Music
Mythos: Reawakening
2.5D Monsters: Daemonum Infernum
2.5D Nature Pack Vol. 1

Sprites:
Horror City Sprite Pack 1
Horror City Sprite Pack 2

Tileset:
CyberPop Interior Tiles
Horror City Sewer & Factory Tiles
Japanese Urban Accessories Pack
Horror City Tile Pack

Battlers:
Seraph Circle Monster Pack II
RPG Battlers 3rd 50 Monsters
RPG Battlers 5th 50 Monsters Shades of Battle
Seraph Circle Monster Pack I
RPG Battlers 2nd 50 Monsters
RPG Battlers 1st 50 Monsters
RPG Battlers 4th 50 Monsters
RPG Battlers 6th 50 Monsters Evolution
Badass Bosses Monster Pack
Sci-Fi Foes Monster Pack
Fantasy Beasts Monster Pack
PV Games Humble Bundle Exclusive Pack
Seraph Circle Monster Pack III

Software:
001 Game Creator
Pixelmash

+infos(campanha): LINK

Tags : , , , , , ,

Estatísticas…

A malta do superdataresearch.com lançou mais uma estatística relativa ao mês de Maio :)

A free giveaway of Grand Theft Auto V on the Epic Games Store caused PC player numbers to jump 245% from April to May. Launched seven years ago, the title continues to be a major draw, and the traffic from the promotion crashed the Epic Games Store. PC player numbers were only a quarter lower than the console version and PC revenue more than doubled as players purchased in-game content. Despite the surge in revenue, however, the console version continues to outearn its PC counterpart 4-to-1.

Sid Meier’s Civilization VI, another Take-Two Interactive title, was also given away for free on the Epic Games Store and PC player numbers surged 477%. PC revenue grew by 52% thanks to the promotion and the release of new in-game content, including a season pass.

May’s biggest new release, Minecraft Dungeons, attracted 1.8M players — but elements of its business model limited its revenue potential. The Microsoft title, an action role-playing game (RPG) spinoff, did not earn enough to make it to the top 10 PC games of the month and was only number nine on console. The title had a low upfront price ($19.99), and players on Xbox One and PC did not have to purchase the game directly, since it was available to Xbox Game Pass subscribers.

Peacekeeper Elite from Tencent hit an all-time revenue high and was the highest-earning game overall. The game is a China-localized version of PlayerUnknown’s Battlegrounds Mobile, which also hit a revenue high during May and is especially popular in markets like India and Southeast Asia. The success of the titles shows there is strong demand for fast-paced multiplayer titles on smartphones. Gamers in North America and Europe may prefer to play these types of games on PC or console, but mobile is the platform of choice for hardcore gamers throughout much of the world.

Pokemon GO spending rose 60% month-over-month to thanks to a combination of warm weather and even more options for playing at home. Earnings for the game typically rise during the summer months, and May 2020 was no exception. Earnings reached their highest point since September 2019 and were up 45% year-over-year. Due to COVID-19, developer Niantic began selling remote raid passes at the end of April, which allowed players to join in-game battles without the need to travel to certain physical locations.

Counter-Strike: Global Offensive earnings and player numbers fell from an April all-time-high as competing title Valorant prepared to launch. After months of upward momentum, CS:GO revenue shrank by 9% and user numbers fell 6%. During this time, Valorant, the rival tactical shooter from League of Legends maker Riot Games, was in beta and potentially siphoned away CS:GO players.”

+infos(oficial): LINK

Tags : , ,

Java, exercício de análise

assunto: excepções
pergunta: qual o output do seguinte:

package recursopa2;

class MyException extends Exception {
}

class main {
    static void f(int n) throws MyException {
        try {
            if (n > 0) {
                throw new MyException();
            }
            System.out.print("fl ");
        } catch (MyException e) {
            System.out.print("f2 ");
            //saida: f2
        } finally {
            System.out.print("f3 ");
            //saida: f3
        }
        System.out.print("f4 ");
        //saida: f4
    }

    public static void main(String[] args) {
        try {
            f(2);
            System.out.print("ml ");
            //saida: m1
        } catch (MyException e) {
            System.out.print("m2 ");
        }
        System.out.print("m3 ");
        //saida: m3
    }
}

assunto: classes concreta (não abstracta)
pergunta: qual o output do seguinte:

interface IMove {
    void move();
}

interface IJump extends IMove {
    default void jump() {
        System.out.println(" jump ");
    }
    int getHeight();
}

class Kanguru implements IJump {
//para se tornar numa classe concreta, tem que ter todos os métodos anteriores
    public void jump() {
    }
    public void move() {
    }
    public int getHeight() {
        return 1;
    }
}

assunto: equals, arrays, hashCode, hashSet
pergunta: qual o output do seguinte:

package recursopa2;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

class Product {

    private String id;
    private int stockQt;

    public Product(String id, int q) {
        this.id = id;
        this.stockQt = q;
    }

    public boolean sell(int n) {
        if (stockQt >= n) {
            stockQt -= n;
            return true;
        }
        return false;
    }

    @Override
    public boolean equals(Object ob) {
        if (ob == null || getClass() != ob.getClass()) {
            return false;
        }
        return id.equals(((Product) ob).id);
    }

    @Override
    public int hashCode() {
        return this.stockQt;
    }
}

public class main {

    public static void main(String[] args) {
        Product a = new Product("idA", 10);
        Set<Product> set = new HashSet<>();
        set.add(a);
        a.sell(4);
        System.out.print(" Contains? " + set.contains(a));
        //supostamente estas a comparar com o equals endereços de memória
        //saida: falso
        
        Product b = new Product("id8", 10);
        List<Product> list = new ArrayList<>();
        list.add(b);
        b.sell(4);
        System.out.print(" Contains? " + list.contains(b));
        //sendo um array..
        //saida: true
    }
}

assunto: classes derivadas, super
pergunta: qual o output do seguinte:

package recursopa2;

class Bird {

    private String name;

    public Bird(String s) {
        name = s;
    }

    @Override
    public String toString() {
        return name;
    }
}

class Swallow extends Bird {

    public Swallow(String s) {
        //line A
        super(s);
    }

    public String toString() {
        // line B
        return super.toString() + "Swallow";
    }
}

public class main {

    public static void main(String[] args) {
        Swallow objl = new Swallow(" from Africa ");
        Swallow obj2 = new Swallow(" from the islands ");
        System.out.println(objl + " " + obj2);
        //saida: from Africa Swallow from the islands Swallow
    }
}

assunto: classes derivadas
pergunta: qual o output do seguinte:

package recursopa2;

interface IMove {
    void move(); //mover 
}

interface IFly extends IMove {

    void fly(); //voar
}

class Gaivota implements IFly {

    public void move() {
        System.out.println("move");
    }

    public void fly() {
        System.out.println("fly");
    }
}

class main {

    public static void main(String[] args) {
        IMove a = new IMove();  //linha 1
        //erro: IMove, é uma interface, é abstracta 
        
        IMove[] b = new IFly[4];  //linha 2
        IFly c = new Gaivota();  //linha 3
        IMove d = new Gaivota(); //linha 4
        c.move(); //linha 5
        c.fly(); //linha 6
        d.fly(); //linha 7
        //erro: o método fly nao faz parte de IMove
        
        d.move(); //linha 8
        c = d; //linha 9
        //erro: não da para coverter tipos diferentes
        
        d = c; //linha 10
    }
}

assunto: máquina de estados, state machine
pergunta: pretende desenvolver uma nova versão da classe MTThread sob a forma de uma máquina de estados orientada a objectos. Recorra, para o efeito, ao padrão estudado nas aulas laboratoriais e aplicado ao trabalho prático de modo a que uma thread passe a ser uma instância de uma classe que, entre outros atributos, inclua o seu estado actual e tire partido do polimorfismo ao nível dos estados.

package recursopa2;

class MTThread {

    public static enum Const {
        WAII_START, WAII_TO_BE_SCHEDULED, TERMINATED,
        YELD_INVOKED, RUNNING, SCHEDULE_COMPLETED, UNBLOCKED,
        SLEEP_COMPLETED, BLOCKED, SLEEPING, SLEEP_INVOKED
    };
    private Const situation;
    private Data data;

    // Some hidden stuff you don't have to worry about
    //(constructors, getters, ...J
    /* ... */
    public Const getSituation() {
        return situation;
    }

    public void start() {
        if (situation == Const.WAII_START) {
            situation = Const.WAII_TO_BE_SCHEDULED;
        }
    }

    public void schedule() {
        if (situation == Const.WAII_TO_BE_SCHEDULED) {
            situation = Const.RUNNING;
        }
    }

    public void doSomething() {
        if (situation == Const.RUNNING) {
            Const result = data.doSomething();
            switch (result) {
                case YELD_INVOKED:
                    situation = Const.WAII_TO_BE_SCHEDULED;
                    break;
                case BLOCKED:
                    situation = Const.BLOCKED;
                    break;
                case SLEEP_INVOKED:
                    situation = Const.SLEEPING;
                    break;
                case TERMINATED:
                    situation = Const.TERMINATED;
                    break;
                default:
                    break;
            }
        }
    }

    public void scheduleCompleted() {
        if (situation == Const.WAII_TO_BE_SCHEDULED) {
            situation = Const.RUNNING;
        }
    }

    public void unblocked() {
        if (situation == Const.BLOCKED) {
            situation = Const.WAII_TO_BE_SCHEDULED;
        }
    }

    public void sleepCompleted() {
        if (situation == Const.SLEEPING) {
            situation = Const.WAII_TO_BE_SCHEDULED;
        }
    }
}

resposta:

interface IStates {
    Const getSituation();
    IStates start();
    IStates schedule();
    IStates doSomething();
    IStates scheduleCompleted();
    IStates unblocked();
    IStates sleepCompleted();
}

assunto: máquina de estados, state machine
pergunta: implemente uma classe StateAdapter que implemente a interface IStates e a partir da qual derivam todos os estados da nova versão da máquina de estados MTThread

public class StateAdapter implements IStates {
    @Override
    public Const getSituation() {
        return this;
    }

    @Override
    IStates start() {
        return this;
    }

    @Override
    IStates schedule() {
        return this;
    }

    @Override
    IStates doSomething() {
        return this;
    }

    @Override
    IStates scheduleCompleted() {
        return this;
    }

    @Override
    IStates unblocked() {
        return this;
    }

    @Override
    IStates sleepCompleted() {
        return this;
    }
}

assunto: máquina de estados, state machine, IStates
pergunta: implemente uma classe que representa o estado em que a thread se encontra bloqueada na nova versão da máquina de estados MTThread

class Blocked extends StateAdapter{
    @Override
    IStates unblocked(){
        return new WaitToBeScheduled();
    }
}

assunto: máquina de estados, state machine
pergunta: As classes Defender e Forward representam jogadores de futebol, sendo ambas derivadas da classe Player. A classe Club contém uma coleção de jogadores que podem ser do tipo Defender ou Forward. A classe Club permite acrescentar jogadores e saber o número de jogadores que contém. Escreva o código necessário para que a criação de objetos do tipo Player seja feita utilizando o padrão Fábrica de Objetos e complete a função addPlayer() da classe Club, utilizando este padrão.

package recursopa2;

import java.util.ArrayList;
import java.util.List;

enum PlayerTypes {
    DEFENDER, FORWARD
}

abstract class Player {
    private String name;

    public Player(String name) {
        this.name = name;
    }
    //...
}

class Defender extends Player {
    public Defender(String name) {
        //...
    }
    //...
}

class Forward extends Player {
    public Forward(String name) {
        //...
    }
    //...
}

class Club {
    private List<Player> players = new ArrayList<>();
    //...

    public void addPlayer(PlayerTypes type, String name) {
        // Fazer : usar a fabrica de objetos do tipo Player
    }

    public int getNumPlayers() {
        return players.size();
    }
}

resposta:

 public void addPlayer(PlayerTypes type, String name) {
  switch (type) {
            case DEFENDER:
                players.add(new Defender(name));
                break;
            case FORWARD:
                players.add(new Forward(name));
                break;
        }
}

assunto: PropertyChangeListener, propertyChange
pergunta: A classe ClubPanel faz parte do interface de utilizador gráfico para objetos de Club, tendo o objetivo de mostrar o número de jogadores do clube, sempre atualizado. Acrescente o necessário à classe ClubPanel de modo a cumprir este objetivo

package recursopa2;

import java.beans.PropertyChangeEvent;

class ClubPanel extends VBox {

    private ObservableClub modelObs;// ligacao ao modelObs
    private Label nPlayers;

    public ClubPanel(ObservableClub model) {
        this.modelObs = model;
        nPlayers = new Label("N. players " + modelObs.getNumPlayers());
        getChildren().addAll(nPlayers);
        setSpacing(5);
        setPadding(new Insets(10, 10, 10, 10));
        setAlignment(Pos.CENTER);
        modelObs.addPropertyChangeListener(this);
    }

    //resposta:
    private void updateNumberOfPlayers(){
        nPlayers.setText("N. players" + modelObs.getNumPlayers());
    }
    @Override
    public void propertyChange(PropertyChangeEvent ev){
        updateNumberOfPlayers();
    }
}

assunto: máquina de estados, state machine
pergunta: Idealize um diagrama que represente a máquina de estados MTThread de forma adequada, com atribuição de nomes aos estados e às transições/métodos coincidentes com os da listagem. Deve representar todas as transições que podem ocorrer entre os estados. Descreva este diagrama de forma textual seguindo o formato usado no seguinte exemplo (estado [condição] => próximo estado):

e

package recursopa2;

class MTThread {

    public static enum Const {
        WAII_START, WAII_TO_BE_SCHEDULED, TERMINATED,
        YELD_INVOKED, RUNNING, SCHEDULE_COMPLETED, UNBLOCKED,
        SLEEP_COMPLETED, BLOCKED, SLEEPING, SLEEP_INVOKED
    };
    private Const situation;
    private Data data;

    // Some hidden stuff you don't have to worry about
    //(constructors, getters, ...J
    /* ... */
    public Const getSituation() {
        return situation;
    }

    public void start() {
        if (situation == Const.WAII_START) {
            situation = Const.WAII_TO_BE_SCHEDULED;
        }
    }

    public void schedule() {
        if (situation == Const.WAII_TO_BE_SCHEDULED) {
            situation = Const.RUNNING;
        }
    }

    public void doSomething() {
        if (situation == Const.RUNNING) {
            Const result = data.doSomething();
            switch (result) {
                case YELD_INVOKED:
                    situation = Const.WAII_TO_BE_SCHEDULED;
                    break;
                case BLOCKED:
                    situation = Const.BLOCKED;
                    break;
                case SLEEP_INVOKED:
                    situation = Const.SLEEPING;
                    break;
                case TERMINATED:
                    situation = Const.TERMINATED;
                    break;
                default:
                    break;
            }
        }
    }

    public void scheduleCompleted() {
        if (situation == Const.WAII_TO_BE_SCHEDULED) {
            situation = Const.RUNNING;
        }
    }

    public void unblocked() {
        if (situation == Const.BLOCKED) {
            situation = Const.WAII_TO_BE_SCHEDULED;
        }
    }

    public void sleepCompleted() {
        if (situation == Const.SLEEPING) {
            situation = Const.WAII_TO_BE_SCHEDULED;
        }
    }
}

resposta:

States:
WAIT_START, WAIT_TO_BE_SCHEDULED, 
TERMINATED, RUNNING, BLOCKED, SLEEPING

Transitions:
WAIT_START
start()=>WAIT_TO_BE_SCHEDULED
WAIT_TO_BE_SCHEDULED
schedule()=>RUNNING
TERMINATED
RUNNING
doSomething()[result = YELD_INVOKED] => WAII_TO_BE_SCHEDULED
doSomething()[result = BLOCKED] => BLOCKED
doSomething()[result = SLEEP_INVOKED] => SLEEPING
doSomething()[result = TERMINATED] => TERMINATED
scheduleCompleted() => WAII_TO_BE_SCHEDULED
BLOCKED
unblocked() =>WAII_TO_BE_SCHEDULED
SLEEPING
sleepCompleted() =>WAII_TO_BE_SCHEDULED

Tags : ,

Java, exercício de análise

assunto: equals, hashcode e colecções
pergunta: qual o output do seguinte:

package recursopa2;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

class Aluno{
    private String nome;
    private int codigo;

    public Aluno(String nome, int codigo){
        this.nome = nome;
        this.codigo = codigo;
    }

    public boolean equals(Object ob){
        if(!(ob instanceof Aluno)) return false;
        //o equals só exige que tenham o mesmo nome
        return nome.equals(((Aluno)ob).nome);// (Aluno) é um cast importante, por ser Object
    }
    
    public int hashCode(){
        //vai retornar o código do aluno
        return this.codigo;
    }   
}
//o equals e o hashCode estão mal feitos/compativeis (não está bem planeado)
//eles deviam ser compativeis, pois cada um pergunta por uma coisa diferente
//o hashCode devia retornar  os mesmo ou um sub conjunto dos membros do equals

class main{
     public static void main(String[] args) {

        Set<Aluno> conjunto = new HashSet<>(); 
        //HashSet (se são iguais) se:
        //para ver se está contido, uso o equals e o hashCode
        //se o hashCode for diferente acabou
        //se o hashCode for igual vai ver se o equals diz que sim ou que não
        //HashSet, não deixa acrescentar elementos que ele ache que já tem
        //não permite/recusa assim repetições
        
        Map<Aluno,Integer> mapa = new HashMap<>();
        //HashMap
        //não deixa que existam chaves iguais 
        //(compara a chave do map, primeiro testa o hashcode depois o equals)
        //vai verificar se existe alguma chave igual, se o hashCode é o mesmo
        //se for só deixa entrar alterando o valor da chave que está a ser usada
        
        List<Aluno> lista = new ArrayList<>();
        //ArrayList
        //acrescenta tudo o que lhe dado, e considera que contém
        //e só usa o equals para verificar, mas deixa sempre acrescentar
        
        conjunto.add(new Aluno("aaa", 2)); //fica, é o primeiro
        conjunto.add(new Aluno("aaa", 2)); //não fica, tem o mesmo nome, usado o equals
        conjunto.add(new Aluno("aaa", 4)); //fica, não existe nenhum com o mesmo  hashCode
        conjunto.add(new Aluno("bbb", 2)); //hashCode igual, vamos ver o equals se dá igual, fica

        mapa.put(new Aluno("aaa", 2),1); //fica é o primeiro, mas depois saiu
        mapa.put(new Aluno("aaa", 2),1); //fica, é igual, mas sai o primeiro
        mapa.put(new Aluno("aaa", 4),1); //fica, a chave/hashCode é diferente: "aaa", 4, nem sequer usa o equals
        mapa.put(new Aluno("bbb", 2),1); //o hashCode é igual, mas usa o equals que é diferente, fica

        lista.add(new Aluno("aaa", 2)); //fica é i primeiro
        lista.add(new Aluno("aaa", 2)); //fica, mesmo que sejam iguais, aceita sempre 
        lista.add(new Aluno("aaa", 4)); //fica 
        lista.add(new Aluno("bbb", 2)); //fica
        
        System.out.print(conjunto.size() + " "); // 3
        System.out.print(mapa.size() + " "); // 3
        System.out.println(lista.size()); //4

        Aluno a = new Aluno("bbb", 3); 
        System.out.print(conjunto.contains(a) + " "); 
        //perguntar se o conjunto tem o "bbb", 3
        //o conjunto tem o "bbb" mas não tem o código 3
        //assim o cojunto vai ver primeiro o hashCode, é diferente
        //logo não contem, logo a resposta dá false
        
        System.out.print((mapa.get(a) != null) + " "); 
        //o mapa.get(a), tem lá um "bbb" com código 2
        //mas o a tem código 3
        //não existe nenhum hashcode 3, , resposta dá false
        
        System.out.println(lista.contains(a));   
        //a lista só vai ver o equals
        //o equals neste caso só compara o nome
        //, e a resposta dá true
     }
} 
Tags : ,

Java, exercício de análise

assunto: arraylist, equals
pergunta: qual o output do seguinte:

package recursopa2;

import java.util.ArrayList;
import java.util.List;

class Inteiro {
    private int i;

    public Inteiro(int i) {
        this.i = i;
    }

    public void setVal(int i) {
        this.i = i;
    }

    public int getVal() {
        return i;
    }

    public String toString() {
        return "" + i;
    }
}

class main {

    public static void main(String[] args) {
        List<Inteiro> listaInteiros = new ArrayList<>();
        //criado um arraylist de listaInteiros
        
        Inteiro i = new Inteiro(10);
        Inteiro j = new Inteiro(10);

        System.out.println(i == j);
        //saida: falso
        //porque estão em referências diferentes
        
        System.out.println(i.equals(j));
        //saida: falso
        //o equals faz a comparação que nos programamos lá dentro
        //por exemplo comparar conteudos
        //mas o equals não foi definido, e não dá erro porque
        //está a usar a do object, class Inteiro extends object
        //e a equals no object considera dois objetos iguais
        //se tiverem o mesmo endereço

        listaInteiros.add(i);
        listaInteiros.add(j);

        j = i;
        //j refere o i
        
        j.setVal(2);
        //o primeiro elemento do array list fica 2
        
        System.out.println(i);
        //saida: 2
        
        System.out.println(j);
        //saida: 2
        
        System.out.println(listaInteiros.get(0));
        //saida: 2
        
        System.out.println(listaInteiros.get(1));
        //saida: 10
    }
}
Tags : ,

Java, exercício de análise

Desenvolva a classe Artista tendo em consideração os seguintes requisitos:

Assuma que a classe Artista herda as características encapsuladas pela classe Pessoa (atenção, não a desenvolva… assuma apenas que já existe);
resposta: Artista extends Pessoa

Assuma que Pessoa possui o atributo privado nomeCivil e que não existe qualquer getter correspondente;
resposta:

Assuma que Pessoa apenas pode ser instanciada fornecendo o nome civil da pessoa encapsulada;
resposta:

Assuma que Pessoa possui os métodos int hashCode(), boolean equals(Object o) e String toString() adequadamente redefinidos, sabendo que duas instâncias de Pessoa são iguais quando possuem os mesmos nomes civis (a utilização de maiúsculas e minúsculas é irrelevante).
resposta:

A classe Artista possui, além do atributo herdado de Pessoa, o atributo nomeArtistico;
resposta: No artista, o construtor tem que receber o nome, e tem que se fazer super do nomecivil

O método boolean equals(Object o) da classe Artista deve garantir que uma instância desta classe é considerada igual a outro objecto quando este último é do tipo Artista e possui o mesmo nome civil e o mesmo nome artístico (a utilização de maiúsculas e minúsculas é irrelevante);
resposta: a classe artista que deriva, sabemos que o equals da pessoa exisge um nome civil, não temos acesso ao nomecivil, não existe getter, assim tem que se construir o equals da classe derivada, return super.equals e a exisgência da igualdade do nome artistica. não esquecer do instanceof artista

A classe Artista deve possuir um método int hashCode() adequado;
resposta: super hashCode

O método String toString() da classe Artista deve retornar uma string em que o nome civil aparece entre parêntesis depois do nome artístico;
resposta: super.toString() + nomeDoArtista

As linhas de código “oo.writeObject(artista);” e “(Artista)oin.readObject();”, sabendo que oo é do tipo ObjectOuputStream, oin do tipo ObjectInputStream e artista do tipo Artista, não devem gerar qualquer tipo de exceção relacionada com a natureza de artista.
resposta: para as classes implementarem serializer, para a escrita de ficheiros não terem problemas

Tags : ,

Java, exercício de análise

assunto: hierarquia, classes, interface, derivadas
pergunta: qual o output do seguinte:

package recursopa2;

interface IPodeDeslocar {

    void vira(double angulo);

    void defineVelocidade(double v);
}

interface IPodeCaminhar extends IPodeDeslocar {

    void caminha();
}

interface IPodeCorrer extends IPodeCaminhar {

    void corre();
}

interface IPodeVoar extends IPodeDeslocar {

    void voa(double altitude);
}

class Felino implements IPodeCorrer {

    public void corre() {
    }
    //está mal falta mas outras três 
    //para ser concreta e não precisar do abstract
    //precisa: caminha, defineVelocidade, vira
}

abstract class AveRapina implements IPodeVoar {

    public void voa(double a) {
    }
    //para ser concreta precisa do vira, defineVelocidade
    //mas é abstract e não precisa
}

class Tigre extends Felino {
    //se corrigir acrescentado em  Felino
    //caminha, defineVelocidade, vira
    //assim em Tigre devemos implemntar todas
    //corre, caminha, defineVelocidade, vira
    //e sem restringir a visibilidade, isto é
    //mantendo public void corre() ...
}

class Avestruz implements IPodeCorrer {

    public void vira(double angulo) {
    }

    public void defineVelocidade(double v) {
    }

    public void caminha() {
    }

    public void corre() {
    }
    //está correcta este concretização
}

class Aguia extends AveRapina implements IPodeCaminhar {

    public void vira(double angulo) {
    }

    public void defineVelocidade(double v) {
    }

    public void caminha() {
    }
    //aguia deriva de AveRapina
    //tem por via do implements: 
    //caminha, vira, defineVelocidade
    //tem pelo extends da sua derivada abstract 
    //deveria ter voa, mas a AveRapina é asbtract
    //logo esta classe implementa tudo
}

class Main {

    public static void main(String args[]) {
        IPodeDeslocar d1[] = new IPodeDeslocar[10];
        //não tem erro
        //podemos criar arrays dinâmicos para interfaces

        d1[0] = new AveRapina();
        //erro: não se pode criar um objecto de uma classe abstracta
        //podem existir referências, objetos não

        d1[0].voa(10.5);
        //erro, d1 é uma referencia para IPodeDeslocar
        //mas o IPodeDeslocar não tem o método voa

        d1[1] = new Avestruz();

        Avestruz av = d1[1];
        //erro, uma referências para  derivada não pode receber
        //uma referencia para o topo da hierarquia

        IPodeDeslocar t1 = new Tigre();

        IPodeCorrer t2 = t1;
        //t2=t1, siginifca o mais abaixo receber o mais acima
        //IPodeDeslocar é o topo, IPodeCorrer está abaixo
        //não funciona. 

        t1 = t2;
        //o de cima pode receber o debaixo
        //IPodeDeslocar é o topo, IPodeCorrer está abaixo

        Tigre t2 = new Felino();
        //erro, porque Tigre deriva de Felino
        //uma referência para a derivada não pode receber a da base
        //só a referência para base é que podia receber a derivada

        Aguia ag = new Aguia();
        AveRapina ar = ag;
        //aguia deriva de aveRapina
        //aveRapina está mais acima pode então receber
        //o que está mais abaixo

        ar.caminha();
        //não faz parte das funções que desaguam..

        IPodeCaminhar aguia = new Aguia();
        //sim porque Ague implementa IPodeCaminhar

        IPodeCorrer tigre = new Tigre();
        //sim IPodeCorrer está na linha acima da hierarquia

        tigre = aguia;
        //erro, porque tigre está mais abaixo na hierarquia
        //IPodeCaminhar está acima não pode ser dado ao mais abaixo

        aguia = tigre;
        //IPodeCorrer está acima e pode ser dado ao mais abaixo
        //ao contrário já dá
                
        IPodeCaminhar ag2 = (AveRapina) aguia;
        //não está na mesma linha 
        
        IPodeCorrer t3 = (Felino) tigre;
    }
}
Tags : ,

Java, exercício de análise

assunto: interfaces, classes, heranças, métodos, classes concretas, classes abstractas


pergunta: qual o output do seguinte:

package recursopa2;

interface IA {
    String getA();
}

interface IB extends IA {
    //extends, deriva de IA
    int getB();
}

interface IC {
    int getC();
}

class D implements IB, IC {
    //implements. tem que ter todos os métodos
    //mas sendo abstract não precisa
    private String a;
    private int b, c;

    public D(String a, int b, int c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    public String getA() {
        return a;
    }

    public int getB() {
        return b;
    }

    public int getC() {
        return c;
    }

    public void setA(String a) {
        this.a = a;
    }

    public void setB(int b) {
        this.b = b;
    }

    public void setC(int c) {
        this.c = c;
    }

    public boolean equals(Object o) {
        if (o == null || !(o instanceof D)) {
            //se a referência for nula ou se não for instanceof
            return false;
        }
        //return a.equalsIgnoreCase(o.getA());
        //o o não sabe da referencia do getA()
        //resolução do erro:
        //return a.equalsIgnoreCase(((D)o).getA());
        //resolução:
        return a.equalsIgnoreCase(((D) o).getA());
    }
}

class E extends D {
    //extends, deriva de D

    public E(String a, int b, int c) {
        //1º vai ser chamado o construtor da base
        //mas o construtor da base não tem valores por omissão

        //setA(a);
        //setB(b);
        //setC(c);
        //resolução:
        super(a, b, c);
    }
}

class F extends E {
    //extends, deriva de E
    private double d;

    public F(String a, int b, int c, double d) {
        //setA(a);
        //setB(b);
        //setC(c);
        //resolução:
        super(a, b, c);
        this.d = d;
    }

    public double getD() {
        return d;
    }

    public boolean equals(Object o) {
        if (o == null || !(o instanceof F)) {
            return false;
        }
        //return a.equalsIgnoreCase(o.getA()) && b == o.getB() && c == o.getC();
        //porque o é object, não conhece o getA, getB, getC, e o a é privado da base
        //e não temos qualquer acesso
        //resolução:
        return getA().equalsIgnoreCase(((F)o).getA()) 
                && getB() == ((F)o).getB() 
                && getC() == ((F)o).getC();
    }
} 

class main {

    public static void main(String args[]) {
        IB a = new E("abc", 1, 1);
        //classe E dreviva de D
        //D implementa IB e IC
        //assim a classe E está na linha de herança de IB
        //classe E está na descendencia de IB
        //uma referencia para o IB pode referir um objecto E
        
        D b = new F("abc", 1, 1, 2.2);
        //classe F deriva de E
        //e E deriva de B
        //F está na linha de descendencia de D
        //pode então referir um objecto de F
        
        
        IA c = new E("abc", 3, 3);
        //classe E deriva de D
        //D implementa IB, 
        //IB que deriva de IA
        //logo E está na descendencia de IA
        
        //IB d = new IB();
        //dá erro
        //criar um objeto de uma interface
        //com funções abstractas 
        //não é possivel
        
        IC e = new F("ddd", 4, 4, 4.4);
        //F deriva de E
        //E deriva de D
        //D implementa IC
        //F está na descendencia de IC
        //F é uma classe concreta

        IA r1[] = new D[5];
        //criar um array de referências new D[5];
        //D é uma classe abstracta  
        //não se pode criar objetos da classe D
        //mas podemos criar arrays de referências para D
        //mas que depois se refere a objectos de classes
        //derivadas de D mas que são concretas
        //assim, podemos criar arrays de referências para
        //classes abstractas
        //e IA está na herança da linha para cima 
        
        IA r2[] = new IB[5];
        //tambem se pode criar arrays para referências
        //de interfaces, porque se trata de arrays 
        //de referências, e essas referências 
        //vão ser objectos de classes concretas
        //e que implementam directa ou indirectamente
        //este interface 
        //e IA está na linha de herança de IB
        
        
        //IB r3[] = new IA[5];
        //dá erro
        //porque estamos a observar a herança ao contrário
        //o IA é que é a base de IB
        //a derivada a receber a base não
        
        IC r4[] = new IC[5];
        //um array para referêncas para interfaces new IC[5]
        //e é uma classe concreta

        System.out.println(a);
        System.out.println(b);
        
        System.out.println(a.equals(b));
        //a é um objecto da classe E
        //o a chama o equals, 
        //o a é da classe E
        //a classe E não tem o equals
        //mas a classe E deriva de D que tem
        //vai ter a versão herdada
        //e também
        //b é um objecto da classe F
        //f é instanciaof de D (é derivada da derivada de D)
        //e na comparação interessa o getA que é a string "abc"
        //resultado: true
        
        System.out.println(b.equals(a));
        //b é uma objecto   da classe F
        //vai ser chamado o equals da classe F
        //membroA e membroB e membroC sejam iguais
        //o a é um objecto de E
        //E é instanceof D
        //e por esse motivo não faz mais nada
        //resultado: false
        
        //o (o instanceof F)
        //não garante uma simetria de igualdade
          
        System.out.println(c.equals(b));
        //c é uma objecto da classe E
        //E, em um equals que exige  
        //que o argumento seja (o instanceof D)
        //e D tem que getA, string, seja igual
        //resultado: true
        
        System.out.println(c.getA());
        //resultado: abc
        
        //System.out.println(e.getA());
        //tem erro 
        //o e é uma referencia para IC
        //o IC só tem o método getC
        //quem tem o getA é o interface IA
    }
}
Tags : ,

Java, exercício de análise

assunto: interfaces, funções abstracta, derivadas
e funções default: não sou obrigado a redefinir, não é abstracta, tem uma implementação por omissão
e funções static

pergunta: qual o output do seguinte:

package recursopa2;

interface Pagamento {
    void receber();
    void darTroco();
}

abstract class Parquimetro implements Pagamento {
    private String cidade;

    Parquimetro(String s) {
        cidade = s;
    }

    abstract void calcula();

    void calcula2() {
    }
}

interface RegistaVisita {
    void registaVisita();
}

//ser derivada de Parquimetro e "do tipo" RegistaVisita 
// "do tipo" -> impementa a interface RegistaVisita
// "ser concreta", todos os métodos têm que ser concretizados 
//e o membro cidade ser inicializada com "Coimbra"
//assim,
//se forem default ou static não é preciso/não é obrigatório redefinir 
//se a base, for do extendes, e estiver concretizada, não preciso de a redefinir  void calcula2()
//os métodos das outras classes de que esta deriva ou que desagua 
class ParquimetroCoimbra extends Parquimetro implements RegistaVisita {
    public ParquimetroCoimbra() {
        super("Coimbra");
    }
    void calcula() {
    }
    public void registaVisita() {
    }

    public void receber() {
    }

    public void darTroco() {
    }
}

//public class main
class main {
    public static void main(String[] args) {

    }
}

assunto: equals, arrays
pergunta: qual o output do seguinte:

package recursopa2;

import java.util.ArrayList;
import java.util.List;

class A {
    int n;
    A(int nn) {
        n = nn;
    }
    //não tem uma redefinição do equals
    //tem apenas a do object
}

class B extends A {
    B(int nn) {
        super(nn);
    }
    public boolean equals(B obj) {
        return true;
    }
    //"trocar", e podem coexistir
//    public boolean equals(Object obj) {
//        return true;
//    }
}

class main {

    static public void main(String[] args) {
        A r1 = new A(10);
        A r2 = new A(10);
        A r3 = new B(10);
        A r4 = new B(10);

        System.out.println("r1.equals(r2) " + r1.equals(r2));
        //a classA não tem o seu equals, herda do object
        //assim os objectos estão em diferentes endereços
        //saida: false

        System.out.println("r3.equals(r4) " + r3.equals(r4));
        //a classeB tem um equals
        //r3 equals r4, r3 chama a equals através de uma referência de r3 para A
        //vai chamar a equals que A conhece, e A que a conhece é da object
        //e em A não existe uma redefinição da equals
        //saida: false

        //mas para ser true era "trocar"
        //r3 invoca a função equals que conhece
        //que é o equals da object
        //mas o polimorfismo como aponta para o objecto do tipo B
        //e assim sendo vai buscar a versão da b "trocar"
        
        List<B> list = new ArrayList<B>();
        B b1 = new B(4);
        B b2 = new B(4);
        list.add(b1);
        list.add(b2);
        System.out.println("list contem new B(4)? " + list.contains(new B(4)));
        //o contains no array, vai pegar no objecto e vai fazer o equals 
        //com os que já lá estão, e o array lista usa apenas a equals do object
        //que compara referências, e por esse motivo diz que não está lá
        //saida: false
    }
}

assunto: excepções

pergunta: qual o output do seguinte:

package recursopa2;

class EstaExcepcao extends Exception {
}

class main {
    static void f() throws EstaExcepcao {
        try {
            System.out.println("Ponto 1");
            throw new EstaExcepcao();
            //saida: ponto 1
            
            //System.out.println("AAAAA"); //se existir dá erro
            //depois do lançamento da excepção dá sempre erro 
        } catch (EstaExcepcao e) {
            System.out.println("Ponto 2");
            //saida: ponto 2
            
            throw e;
            //vai ser relançada
        } finally {
            System.out.println("Ponto 3");
            //saida: ponto 3
        }
         //System.out.println("BBBB"); //se existice
         //como houve erro nunca iria ser executada, por exemplo
         //não havendo o throw
    }

    public static void main(String[] args) {
        try {
            f(); 
            // f() sai em erro, vai fazer o catch
            System.out.println("Ponto 4");
        } catch (EstaExcepcao e) {
            System.out.println("Ponto 5");
            //saida: ponto 5
        } catch (Exception e) {
            System.out.println("Ponto 6");
        }
        System.out.println("Ponto 7");
        //saida: ponto 5
    }
}
Tags : ,

Java, exercício de análise

assunto: excepções
pergunta: qual o output do seguinte:

package recursopa2;

class InteiroSomaRaizesQ {

    static private double somaRaizesQuadradas = 0;
    private double n;

    public InteiroSomaRaizesQ(String n) throws Exception {
        try {
            try {
                this.n = Double.parseDouble(n);
                //Double.parseDouble, se for bem formado do tipo 4.0
            } catch (NumberFormatException e) {
                //NumberFormatException, como é o caso de A.0
                return;
            }
            if (this.n < 0) {
                throw new Exception();
            }
            somaRaizesQuadradas += Math.sqrt(this.n);
        } finally {
            System.out.print("f1 ");
            //acontece sempre quer o if corra bem quer corra mal
        }
    }

    public static void main2(String[] args) {
        System.out.print("m1 ");
        //saida: m1
        
        try {
            new InteiroSomaRaizesQ("4.0");
            //somaRaizesQuadradas = 2
            //saida: f1, correu bem passa ao seguinte
            
            new InteiroSomaRaizesQ("A.0");
            //saida: f1, termina em paz
            
            new InteiroSomaRaizesQ("9.0");
            //somaRaizesQuadradas = 2+3
            //saida: f1, correu bem passa ao seguinte
            
            new InteiroSomaRaizesQ("-4.0");
            //acontece throw new Exception();
            //saida: f1, mas correu mal, 
            //não faço mais nada no try
            
            new InteiroSomaRaizesQ("9");
        } catch (Exception e) {
            System.out.print("e1 ");
            //saida: e1
            
            return;
        } finally {
            System.out.print("f2: " + somaRaizesQuadradas);
            //saida: f2
            //saida: 5
        }
    }
}
//para testar
public class main {
    public static void main(String[] args) {
        InteiroSomaRaizesQ.main2(args);
    }
}
Tags : ,

Java, exercício de análise

assunto: máquina de estados, padrão comando

ou

pergunta: qual o output do seguinte:

package recursopa2;

class Semaforo {

    static final int TEMPO_VERDE = 4, TEMPO_VERMELHO = 4, TEMPO_AMARELO = 1;
    private int tempo;
    private String estado;
    private String estadoAoLigar;

    public Semaforo() {
        tempo = 0;
        estado = "desligado";
        estadoAoLigar = "vermelho";
    }

    public void passaTempo() {
        if (estado.equalsIgnoreCase("desligado")) {
            return;
            //se for igual a desligado, não faz nada
        }
        tempo--;
        //se for diferente a desligado
        if (tempo > 0) {
            return;
            //se fo tempo for positivo, não faz mais nada
        }
        //se for == 0, então..
        if (estado.equalsIgnoreCase("vermelho")) {
            estado = "verde";
            tempo = TEMPO_VERDE;
        } else if (estado.equalsIgnoreCase("verde")) {
            estado = "amarelo";
            tempo = TEMPO_AMARELO;
        } else if (estado.equalsIgnoreCase("amarelo")) {
            estado = "vermelho";
            tempo = TEMPO_VERMELHO;
        }
    }

    public void desliga(String ligarEm) {
        if (estado.equalsIgnoreCase("desligado")) {
            return;
        }
        //se estiver ligado, então..
        estadoAoLigar = ligarEm;
        estado = "desligado";
        tempo = 0;
    }

    public void liga() {
        if (!estado.equalsIgnoreCase("desligado")) {
            return;
        }
        //se estiver desligado, então..
        estado = estadoAoLigar;
        if (estado.equalsIgnoreCase("vermelho")) {
            tempo = TEMPO_VERMELHO;
        } else if (estado.equalsIgnoreCase("verde")) {
            tempo = TEMPO_VERDE;
        } else if (estado.equalsIgnoreCase("amarelo")) {
            tempo = TEMPO_AMARELO;
        }
    }

    public String toString() {
        return estado + "   " + tempo;
    }
}

//para testar
public class main {

    public static void main(String[] args) {
        Semaforo s = new Semaforo();
        s.desliga("ligado");
        s.liga();
        s.passaTempo();
        System.out.println(s.toString());
    }
}

perguntas, parte I:
____ É suficiente definir três classes concretas e tipo(s) base destas classes (classe e/ou interface)
resposta: não, temos quatro estados

____ É suficiente definir quatro classes concretas sem qualquer característica em comum
resposta: não, são derivadas na mesma base

____ Conceitos como “Vermelho” ou “Verde” representam métodos
resposta: não, são classes

____ Conceitos como “PassaTempo”, “Liga” ou “Desliga” representam métodos
resposta: sim

____ Todas as classes que representam os estados dispõem de implementações (vazias ou não) de todos os métodos que representam as acções a que o semáforo tem que responder
resposta: ou seja em todos os estados temos implementações vazias ou não, de liga ou desliga, sim verdadese não temos o que interessa, temos estão o return this (o vazio)

____ Três é o número mais adequado de métodos declarados na classe abstracta de base ou na interface comum
resposta: verdade, são três

____ As implementações dos métodos definidos na classe abstracta de base ou na interface comum podem modificar os dados e/ou devolver uma referência para o objecto que representa o estado actual
resposta: é verdade. “podem modificar os dados, e não retornam o estado em que ficamos”

____ Apenas um dos métodos (representando uma transição na máquina de estados) declarados na classe abstracta de base ou na interface comum necessita de receber um argumento
resposta: é verdade, que é o String ligarEm

perguntas, parte II:
Conceitos como “PassaTempo”, “Liga” ou “Desliga” representam ____________________ (métodos/classes)
resposta: na máquina de estados eram métodos, no padrão comando são classes
arranjam-se objectos que embrulham estas acções (classes que representam comandos simples, para haver uma evolução), logo elas vão ser classes

As classes que representam os comandos concretos implementam um interface ou derivam de uma mesma classe abstracta. Indique os métodos desse tipo base abstracto ____________________________________
resposta: os métodos são o execute (executar) e o undo (refazer)

O membro “estadoAoLigar” da classe Semaforo da listagem anterior deveria ser membro de que classe da hierarquia de comandos.
resposta: no comando correspondente ao desligar

O argumento “ligaEm” da classe Semaforo da listagem E deveria ser membro da classe ____________ da hierarquia de comandos.
resposta: “ligaEm” vai ser gravado na classe desliga
quando queremos por em padrão comando um método que leva argumentos, esses argumentos também são passados ao construtor do comando e são membros do objeto comando, e ficam lá gravados dentro
“os argumentos com que as funções são chamadas, quando embrulhamos a função com um comando, esses argumentos ficam gravados na classe que representa aquela acção, que representa aquele comando”

perguntas, parte III:
a classe semáforo deve implementar a interface PropertyChangeListener
resposta: não, pois a classe semáforo é a nossa lógica/dados. Os observadores (objectos da vista) que estão do lado da vista é que implementam o PropertyChangeListener

a classe semáforo deve ser derivada de PropertyChangeSupport ou referida por uma classe derivada de PropertyChangeSupport
resposta: verdade, a classe semáforo vai ser derivada de PropertyChangeSupport

o objecto painel desenho pode ser uma instância de uma classe derivada de PropertyChangeSupport
resposta: não, o painel de desenho não tem nenhum membro de PropertyChangeSupport, ele regista-se como observador, ele tem um observador lá dentro

o objecto painelDesenho pode ser instância de uma classe que não implementa a interface PropertyChangeListener, desde que tenha definida o método propertyChange
resposta: se ele tem um método propertyChange e não tem registo como observador, então não recebe ordens de actualização

o local mais apropriado para colocar código que trata da representação gráfica do semáforo é um método designado propertyChange
resposta: sim, os objetos gráficos são actualizados no propertyChange

o objecto painelDesenho, se tiver uma referência para a classe que deriva de PropertyChangeSupport (modelo), já não precisa de se registar como listener modelo.addProppertyChangeListener(this))
resposta: falso, pode ter uma referência, mas se não tiver um registo como listener/observador, não sabe se existem actualizações, quando os dados se alterarem

a classe que deriva PropertyChangeSupport (a classe observável) deve ter métodos, como passaTempo e desliga, que permitem alterar a informação encapsulada pelo modelo. Nestes métodos, é necessário chamar o método firePropertyChange antes de fazer as alterações ao semáforo
resposta: falso, o firePropertyChange é chamado depois. primeiro mudamos os dados, depois o firePropertyChange vai mandar os observadores fazer a actualização da vista

Tags : ,

Java, várias coisas

ArrayList
Um objecto do tipo ArrayList representa uma sequência ordenada de objectos do tipo T. Implementa o interface List.
A seguinte instrução cria um ArrayList vazio de elementos do tipo Produto:
List produtos= new ArrayList();

Alguns métodos:
public boolean add(E e) acrescenta o elemento e ao fim da lista.
public E remove(int index) remove o elemento da posição index, ajustando os índices seguintes; retorna o elemento removido.
public boolean remove(Object o) remove a primeira ocorrência de o, se existir, ou seja remove o elemento com menor índice tal que (o==null ? get(i)==null : o.equals(get(i))) (se esse elemento existir); retorna true se o elemento foi encontrado e eliminado.
public void clear() remove todos os elementos da lista.
public int size() retorna o numero de elementos da lista.
public int indexOf(Object o) retorna o índica da primeira ocorrência de o na lista, ou -1 se não existir.he element, ou seja, retorna o elemento com menor índice tal que (o==null ? get(i)==null : o.equals(get(i))) ou -1 se este índice não existir.
public E get(int index) retorna o elemento da lista na posição índex.

Percorrer um ArrayList:

for( int i = 0 ; i < produtos.size(); i++){
// …  produtos.get(i)
}

for(Produto produto: produtos){
// …  produto;
} 

Interface Iterator
Um iterator é um objecto que lhe permite percorrer uma colecção. As colecções têm um método:
Iterator iterator();

Que retorna um iterator para a colecção que o invoca.

public interface Iterator<E> {
boolean hasNext();  
// retorna true se existem mais elementos 
E next();          
// retorna o próximo elemento da colecção 
void remove();
}

Interface Set
Um set é uma colecção que não pode ter elementos repetidos. Uma das implementações do interface Set é HashSet.
A seguinte instrução cria um HashSet vazio de elementos do tipo Entidade:
Set< Entidade > c = new HashSet< Entidade >();

Percorrer uma colecção com iterator: Iterator it = v.iterator();

while (it.hasNext()){
// … it.next();
}
}

Para verificar se um determinado objecto pertence a um HashSet, é calculado o hashCode do objecto. O objecto é comparado com equals() só com os elementos do HashSet que têm o mesmo hashCode do objecto que está a ser pesquisado.
O objecto é considerado como pertencente ao HashSet se tiver o mesmo hashCode de um elemento e se também em relação a esse elemento a comparação com equals() der verdadeira.
Os objectos que se colocam num HashSet devem dispor de funções equals() e hashCode() devidamente definidas (se x.equals(y) for true, então x.hashCode() == y.hashCode()).

Ao adicionar um elemento a um HashSet, esta operação só tem sucesso (retornando true e adicionando de facto) se o novo elemento não pertencer ainda ao HashSet.

Interface Map
Um objecto do tipo Map representa uma correspondência chave-valor. Não pode haver chaves repetidas.

public interface Map<K,V> {
V put(K key, V value);    
// insere a correspondência de  (key, value) 
V get(Object key);        
// retorna o valor associado a  key
V remove(Object key);     
// remove a associação cuja chave é  key
boolean containsKey(Object key); 
// contém uma associação com chave  key 
boolean containsValue(Object value); 
// contém uma associação com valor  value int size();
boolean isEmpty();        
// estar vazio
void clear();             
// remove todas as associações
public Set<K> keySet();   
// conjunto das chaves
public Collection<V> values(); 
// colecção dos valores
}

Uma das implementações do interface Map é HashMap.
A seguinte instrução cria um HashMap vazio de elementos do tipo Entidade:

Map map = new HashMap();

Percorrer um map:

Set<String> chaves = map.keySet(); 
Iterator<String> iter = chaves.iterator(); 
while (iter.hasNext()) {
String key = iter.next();
str += " \n" + map.get(key);
}

Interfaces Comparable e Comparator
Implementando o interface Comparable a classe define uma ordem natural entre os seus elementos.

public abstract class Cartao implements Comparable<Cartao>{

protected List<Chamada> chamadas = new ArrayList<Chamada>();
private int numero;
private double saldo;
// …
public int compareTo(Cartao o) {
return numero - o.getNumero();
}
// …
}

public class Telefonica {
private String nome;
private Map<Integer, Cartao> cartoes = new HashMap<Integer, Cartao>();
// …
public String toStringPorNumero(){
List<Cartao> listaOrdenada =
new ArrayList<Cartao>(cartoes.values()); //Faz a cópia
Collections.sort(listaOrdenada);
return "Operadora de telemoveis ***" + nome + "***\n"
+ "Lista ordenada por numero:\n" + listaOrdenada;
}
// …
} 

O interface Comparator permite ordenar a mesma colecção segundo diversos critérios.
É preciso definir um objecto do tipo Comparator, neste caso, um objecto da classe OrdenaPorSaldo que vai ser o segundo argumento da função: Collections.sort(listaOrdenada, new OrdenaPorSaldo());

public class Telefonica {
private String nome;
private Map<Integer, Cartao> cartoes = new HashMap<Integer, Cartao>();
// …
class OrdenaPorSaldo implements Comparator<Cartao> {
public int compare(Cartao o1, Cartao o2) {
if (o1.getSaldo() < o2.getSaldo())
return -1;
else if (o1.getSaldo() > o2.getSaldo())
return 1;
else return 0;
}
}
public String toStringPorSaldo(){ List<Cartao> listaOrdenada =
new ArrayList<Cartao>(cartoes.values()); //Faz a cópia
Collections.sort(listaOrdenada, new OrdenaPorSaldo());
return "Operadora de telemoveis ***" + nome + "***\n"
+ "Lista ordenada por saldo:\n" + listaOrdenada;
}
// …
}
Tags : ,

JavaFX, exercício 3.1

package recursopa;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import recursopa.iu.gui.PaneOrganizer;

public class RecursoPA extends Application {
    public static void main(String[] args) {
        //passamos os argumentos para o subsistema gráfico os parametros
        launch(args); 
    }
 
    @Override
    //quando começa a aplicação
    public void start(Stage stage) throws Exception{
        PaneOrganizer po = new PaneOrganizer();
        Scene scene = new Scene(po,600,400);
        stage.setScene(scene); //aplica a cena no stage
        stage.setTitle("Exercicio de programação avançada");
        stage.setMinHeight(300.0);
        stage.setMinWidth(300.0);
        stage.show();
    }
}   
package recursopa.iu.gui;

import javafx.event.EventHandler;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import recursopa.logica.Desenho;
import recursopa.logica.Figura;

public class AreaDesenho extends Canvas {

    Desenho desenho;

    public AreaDesenho(Desenho desenho) {
        super(100.0, 100.0);
        this.desenho = desenho;
    }

    public void registaListeners() {
        //detectar as ações do rato
        this.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent t) {
                desenho.iniciaFigura((int) t.getX(),
                        (int) t.getY(),
                        (int) (Math.random() * 256),
                        (int) (Math.random() * 256),
                        (int) (Math.random() * 256)
                );
                atualiza();
            }
        });

        //usando lambda functions
        this.setOnMouseReleased((t) -> {
            desenho.atualizaFigura((int) t.getX(), (int) t.getY());
            atualiza();
        });
        this.setOnMouseDragged((t) -> {
            desenho.finalizaFigura((int) t.getX(), (int) t.getY());
            atualiza();
        });

    }

    void apagarCanvas(GraphicsContext gc) {
        gc.setFill(Color.rgb(233, 233, 0));
        gc.fillRect(0, 0, getWidth(), getHeight());
    }

    //para desenhar as figuras
    void atualiza() {
        //obter as ferramentas de desenho
        GraphicsContext gc = getGraphicsContext2D();
        apagarCanvas(gc);

        //rir buscar todas as figuras
        for (Figura fig : desenho.getListaFiguras()) {
            //fazer as operações sobre o GraphicsContext
            Color cor = Color.rgb(fig.getR(), fig.getG(), fig.getB());
            gc.setFill(cor);
            gc.fillOval(fig.getXi(), fig.getYi(), fig.getLargura(), fig.getAltura());
        }

        //desenhar a figura actual
        Figura figura = desenho.getActual();
        if (figura != null){
            Color cor = Color.rgb(figura.getR(), figura.getG(), figura.getB());
            gc.setFill(cor);
            gc.fillOval(figura.getXi(), figura.getYi(), figura.getLargura(), figura.getAltura());
        }

    }

    public void setDim(int w, int h) {
        setWidth(w);
        setHeight(h);
        atualiza();
    }

}

package recursopa.iu.gui;

import javafx.scene.layout.Pane;
import recursopa.logica.Desenho;

public class PaneOrganizer extends Pane {
    //vai extender sempre um dos containers possiveis,  extends Pane
    Desenho desenho;
    //Canvas canvas; //é uma zona de desenho
    AreaDesenho areaDesenho;

    public PaneOrganizer() {
        desenho = new Desenho();

        criaLayout(); //para criar os componentes que vão surgir no ecrã
        registaListeners(); // registar os comportamentos dos objectos

    }

    
    void criaLayout() {
        //adicionar o elemento ao Pane
        areaDesenho = new AreaDesenho(desenho);
        this.getChildren().add(areaDesenho);
    }

    private void registaListeners() {
        areaDesenho.registaListeners();
        
        this.widthProperty().addListener((e) -> {
            areaDesenho.setDim((int)PaneOrganizer.this.getWidth(), (int)PaneOrganizer.this.getHeight());
        });
        this.heightProperty().addListener((e) -> {
            areaDesenho.setDim((int)PaneOrganizer.this.getWidth(), (int)PaneOrganizer.this.getHeight());
        });
    }
}

package recursopa.logica;

import java.util.ArrayList;
import java.util.List;

public class Desenho {

    //para um conjunto de figuras, que ser´auma lista de figuras
    List<Figura> listaDeFiguras;
    Figura figuraAtual;

    public Desenho() {
        listaDeFiguras = new ArrayList<>();
    }

    public void iniciaFigura(int x, int y, int r, int g, int b) {
        figuraAtual = new Figura();
        figuraAtual.setRGB(r, g, b);
        figuraAtual.setPrimeiroPonto(x, y);
        figuraAtual.setSegundoPonto(x, y);
    }

    public void atualizaFigura(int x, int y) {
        if (figuraAtual != null) {
            figuraAtual.setSegundoPonto(x, y); //atualizar o segundo ponto
        }
    }

    public void finalizaFigura(int x, int y) {
        //para terminar a figura
        if(figuraAtual != null && listaDeFiguras !=null){
            listaDeFiguras.add(figuraAtual);
            figuraAtual = null;
        }
    }
    public Figura getActual(){
        return figuraAtual;
    }
    
    public List<Figura> getListaFiguras(){
        return listaDeFiguras;
    }
}

package recursopa.logica;

public class Figura {
//métodos necessários para gerir a figura

    int xi, yi, xf, yf; //posicao e tamanho
    int r, g, b; //para a cor

    public Figura() {

    }

    public int getXi() {
        return xi < xf ? xi : xf;
    }

    public int getYi() {
        return yi < yf ? yi : yf;
    }

    public int getXf() {
        return xf < xi ? xf : xi;
    }

    public int getYf() {
        return yf < yi ? yf : yi;
    }

    public int getR() {
        return r;
    }

    public int getG() {
        return g;
    }

    public int getB() {
        return b;
    }

    public void setRGB(int r, int g, int b) {
        this.r = r;
        this.g = g;
        this.b = b;
    }

    public void setPrimeiroPonto(int x, int y) {
        this.xi = x;
        this.yi = y;
    }

    public void setSegundoPonto(int x, int y) {
        this.xf = x;
        this.yf = y;
    }

    public int getLargura() {
        return Math.abs(xf - xi); //não interessa a ordem dos valores
    }

    public int getAltura() {
        return Math.abs(yf - yi); //não interessa a ordem dos valores
    }
}

Tags : ,

Java, exercício de análise

assunto: arraylist, equals
pergunta: qual o output do seguinte:

package recursopa2;

import java.util.ArrayList;
import java.util.List;

class Inteiro {

    private int i;

    public Inteiro(int i) {
        this.i = i;
    }

    public void setVal(int i) {
        this.i = i;
    }

    public int getVal() {
        return i;
    }

    public String toString() {
        return "" + i;
    }

    //extra
    public boolean equals(Object ob) {
        if (ob == null) {
            return false;
        }
        if (getClass() != ob.getClass()) {
            return false;
        }
        //se chego aqui já posso comparar o i

        //return (i==ob.i); 
        //dá erro, porque ob não conhece i, então
        
        Inteiro a = (Inteiro) ob;
        //fazemos um cast
        return (i == a.i);
    }
    //e desta forma o System.out.println(i.equals(j));
    //dá true
}

class main {

    public static void main(String[] args) {
        List<Inteiro> listaInteiros = new ArrayList<>();
        //criado um arraylist de listaInteiros

        Inteiro i = new Inteiro(10);
        Inteiro j = new Inteiro(10);

        System.out.println(i == j);
        //saida: falso
        //porque estão em referências diferentes

        System.out.println(i.equals(j));
        //saida: falso
        //o equals faz a comparação que nos programamos lá dentro
        //por exemplo comparar conteudos
        //mas o equals não foi definido, e não dá erro porque
        //está a usar a do object, class Inteiro extends object
        //e a equals no object considera dois objetos iguais
        //se tiverem o mesmo endereço

        listaInteiros.add(i);
        listaInteiros.add(j);

        j = i;
        //j refere o i

        j.setVal(2);
        //o primeiro elemento do array list fica 2

        System.out.println(i);
        //saida: 2

        System.out.println(j);
        //saida: 2

        System.out.println(listaInteiros.get(0));
        //saida: 2

        System.out.println(listaInteiros.get(1));
        //saida: 10
    }
}

Tags : ,

Java, exercício análise

assunto: excepções
pergunta: qual o output do seguinte:

package recursopa2;

class UmaExcepcao extends Exception {
    //foi definida uma excepção
}

class Conta {
    int c = 4;

    void f(int i) throws UmaExcepcao {
        if (i < c) {
            System.out.print(" f1");
            f(++i);
            return;
        } else try {
            System.out.print(" f2");
            if (i == c) {
                throw new UmaExcepcao();
            }
        } finally {
            System.out.print(" f3");
        }
        System.out.print(" f4");
    }

    public static void main2(String[] args) {
        Conta c1 = new Conta();
        Conta c2 = new Conta();
        //não existe nenhum construtor

        try {
            c1.f(3);
            // saida: System.out.print(" f1");
            // saida: System.out.print(" f2");
            // i == c, true
            // lança uma excepção, throw new UmaExcepcao(); 
            // saida: faz sempre o finally, System.out.print(" f3");
            // e terminou em estado de excepção e não faz o f4, 
           
            System.out.print(" m1");
            c2.f(4);
            System.out.print(" m2");
            
        } catch (UmaExcepcao ex1) {
            System.out.print(" m3");
            // saida: System.out.print(" m3");
            // porque apanhou uma excepção
            
            try {
                c1.f(5);
                // saida: System.out.print(" f2");
                // i == c, falso
                // saida: System.out.print(" f3");
                // saida: System.out.print(" f4");
                // porque não tinha excepção
                
            } catch (UmaExcepcao ex2) {
                System.out.print(" m4");
            }
        }
        System.out.print(" m5");
        // saida: System.out.print(" m5");
        // porque não tinha excepção
    }
}

//para testar
public class main {
    public static void main(String[] args) {
        Conta.main2(args);
    }
}

assunto: excepções
pergunta: qual o output do seguinte:

package recursopa2;

class EstaExcepcao extends Exception {
}

class main {
    static void f() throws EstaExcepcao {
        try {
            System.out.println("Ponto 1");
            throw new EstaExcepcao();
            //saida: ponto 1
            
            //System.out.println("AAAAA"); //se existir dá erro
            //depois do lançamento da excepção dá sempre erro 
        } catch (EstaExcepcao e) {
            System.out.println("Ponto 2");
            //saida: ponto 2
            
            throw e;
            //vai ser relançada
        } finally {
            System.out.println("Ponto 3");
            //saida: ponto 3
        }
         //System.out.println("BBBB"); //se existice
         //como houve erro nunca iria ser executada, por exemplo
         //não havendo o throw
    }

    public static void main(String[] args) {
        try {
            f(); 
            // f() sai em erro, vai fazer o catch
            System.out.println("Ponto 4");
        } catch (EstaExcepcao e) {
            System.out.println("Ponto 5");
            //saida: ponto 5
        } catch (Exception e) {
            System.out.println("Ponto 6");
        }
        System.out.println("Ponto 7");
        //saida: ponto 5
    }
}
Tags : ,

Java, exercício de análise

assunto: map, hashmap
Pergunta:
Pretende-se um programa destinado a modelizar um conjunto de pássaros, especificamente canários e periquitos. Em termos de funcionalidades requeridas, apenas se pretende inserir novas instâncias de pássaros e manter um mapeamento entre os tipos e as respectivas quantidades. Sendo assim, complete o código da Listagem C de modo a que o resultado da sua execução seja: {Piriquito=10, Canario=10}. A classe Passaro encontra-se declarada como abstracta de modo a não poder ser instanciada, não sendo necessário alterá-la. As classes Periquito e Canario requerem a redefinição dos seguintes métodos: String toString(), boolean equals(Object o) e int hashCode().
A interface Map, sendo K o tipo da chave e V o tipo do valor associado, inclui, entre outros, os métodos V put(K k, V v) e V get(Object k). Ambos devolvem o valor associado à chave k fornecida, antes de substituir o valor já existente pelo novo valor v fornecido no caso do put, ou null caso esta não seja encontrada.

package recursopa2;

import java.util.HashMap;
import java.util.Map;

abstract class Passaro {

    public static String PASSARO = "Passaro";
    public static String PERIQUITO = "Periquito";
    public static String CANARIO = "Canario";

    //fabrica de objectos
    public static Passaro criaPassaro(String tipoPassaro) {
        if (tipoPassaro.equalsIgnoreCase(PERIQUITO)) {
            return new Periquito();
        } else if (tipoPassaro.equalsIgnoreCase(CANARIO)) {
            return new Canario();
        } else {
            return null;
        }
    }
}

class Periquito extends Passaro {

    public String toString() {
        return "Periquito";
    }

    public boolean equals(Object ob) {
        //return ob instanceof Periquito;
        //ou em alternativa
        return getClass() == ob.getClass();
    }

    public int hashCode() {
        return PERIQUITO.hashCode();
    }
}

class Canario extends Passaro {

    public String toString() {
        return "Canario";
    }

    public boolean equals(Object ob) {
        return ob instanceof Canario;
    }

    public int hashCode() {
        return CANARIO.hashCode();
    }
}

class MainPassaro {

    public static void adicionaPassaro(Passaro p, Map<Passaro, Integer> gaiola) {
        if (gaiola == null || p == null) {
            return;
        }

        Integer quantidade = gaiola.get(p);
        //se não tive cananrio, a quantidade vem null
        //se já tiver algum, a quantidade vair ser >0

        if (quantidade == null) {
            gaiola.put(p, 1);
            //acrescentamos um elemento novo
        } else {
            gaiola.put(p, quantidade + 1);
            //adiciono um novo, com um update quantidade
        }
    }

    public static void main2(String args[]) {
        //Map</*..f..*/> gaiola = new HashMap<>();
        //resolução:
        Map<Passaro, Integer> gaiola = new HashMap<>();

        Passaro p;

        for (int i = 0; i < 10; i++) {
            adicionaPassaro(Passaro.criaPassaro(Passaro.PERIQUITO), gaiola);
            adicionaPassaro(Passaro.criaPassaro(Passaro.CANARIO), gaiola);
        }
        System.out.println(gaiola);
    }
}

////para testar
public class main {
    public static void main(String[] args) {
        MainPassaro.main2(args);
    }
}
Tags : ,

Java, exercício de análise

assunto: array
pergunta: qual o output do seguinte:

package recursopa2;

class Conta {
    public static int sn = 0;
    public Conta() {
        ++sn;
    }
}

public class main {
    public static void main(String[] args) {
        System.out.print(Conta.sn + " ");
        //saida: 0

        Conta[] a = new Conta[4];
        //com o new Conta[4] é um array de 4 referências nulas para Conta
        //não existe ainda nenhum objecto, não existe nenhum construtor
        
        System.out.print(Conta.sn + " ");
        //saida: 0
        
        for (int i = 0; i < a.length; i++) {
            a[i] = new Conta();
           //aqui já estamos a criar  
        }
        System.out.println(Conta.sn);
        //saida: 4
    }
}
Tags : ,

exercício javaFx

Tópicos: máquina de estados, interface gráfica, threads,

o diagrama da máquina de estados:

o projeto:

o código:

package jfxsomajogo;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import jfxsomajogo.modelo.SomaJogoObs;
import jfxsomajogo.ui.SomaUI;

public class JFXSomaJogo extends Application {

    public static void main(String[] args) {
        launch(args);;
    }
    
    @Override
    public void start(Stage primaryStage){
        primaryStage.setTitle("Acereta nos números");
        SomaJogoObs a = new SomaJogoObs();
        SomaUI ui = new SomaUI(a);
        Scene scene = new Scene(ui, 300,250);
        primaryStage.setScene(scene);
        primaryStage.show();
     
        //que serve para fechar a janela
        primaryStage.setOnHidden((WindowEvent event) -> {
            a.paraRelogio();
        });
    }
    
}
package jfxsomajogo.fsm;

import jfxsomajogo.integracao.EstadoID;
import jfxsomajogo.modelo.SomaDados;

public class AguardaNomeJogador extends SomaFSMAdapter {

    public AguardaNomeJogador(SomaDados dados) {
        super(dados);
    }

    //transição
    @Override
    public ISomaFSM defineJogador(String nome) {
        dados.defineNomeJogador(nome);
        if (dados.jogadorValido()) {
            dados.reset(); //iniciação do jogo
            return new AguardaResposta(dados); //novo estado
        }else{
            return this;
        }
    }

    //cada um retorna o seu próprio identicador
    //para evitar o uso do instanceof e o get class
    @Override
    public EstadoID obtemEstadoID() {
        return EstadoID.AGUARDA_NOME;
    }

}

package jfxsomajogo.fsm;

import jfxsomajogo.integracao.EstadoID;
import jfxsomajogo.modelo.SomaDados;

public class AguardaReinicio extends SomaFSMAdapter {

    public AguardaReinicio(SomaDados dados) {
        super(dados);
    }

    //este estado é basicamente, um "press any key to conitnue"
    @Override
    public ISomaFSM recomeca() {
        return new AguardaNomeJogador(dados);
    }

    @Override
    public EstadoID obtemEstadoID() {
        return EstadoID.AGUARDA_REINICIO;
    }
}

package jfxsomajogo.fsm;

import jfxsomajogo.integracao.EstadoID;
import jfxsomajogo.modelo.SomaDados;

public class AguardaResposta extends SomaFSMAdapter{

    AguardaResposta(SomaDados dados) {
        super(dados);
    }

    @Override
    public ISomaFSM tentaResposta(int n) {
        dados.tentaResposta(n);
        if(dados.excedeuErros()){
            return new AguardaReinicio(dados); //muda de estado
        }else{
            return this; //fica no mesmo estado
            //return new AguardaResposta(dados); //alternativa, mostramos evolução do estado
        }
    }
    
    @Override
    public ISomaFSM relogioAvanca() {
        dados.diminuiCountDown();
        if(dados.excedeuErros()){
            return new AguardaReinicio(dados);
        }else{
            return this;
        }
    }

    @Override
    public EstadoID obtemEstadoID(){
        return EstadoID.AGUARDA_RESPOSTA; //para evitar o instance of
    }
}

package jfxsomajogo.fsm;

import java.io.Serializable;
import jfxsomajogo.integracao.EstadoID;

public interface ISomaFSM extends Serializable{
    //vai servir para definir um estado, transições:
    default ISomaFSM defineJogador(String nome){return this;} 
    //implementação default, pode ser no Adpater
    default ISomaFSM tentaResposta(int n){return this;}
    default ISomaFSM recomeca(){return this;}
    default ISomaFSM relogioAvanca(){return this;}
    EstadoID obtemEstadoID(); //retorna um ID
    
    //default, permite a implementação default mas devia ser no adaptar e não aqui.
    //mudar no final para ver como fica
}

package jfxsomajogo.fsm;

import jfxsomajogo.modelo.SomaDados;

public abstract class SomaFSMAdapter implements ISomaFSM{
    //guarda a referencia para o modelo de dados
    protected final SomaDados dados;
    //protected para os outros estados poderem aceder à informação
    
    protected SomaFSMAdapter(SomaDados dados){
        this.dados = dados;
    }
    
    //public AdividnhaDados obtemDados(){return dados;}
    //usa-se protected para isto
    
    //implementações de default de cada um dos métodos de 
    
}


package jfxsomajogo.integracao;
//isto é um package que vai ser usado pelo modelo de dados e pela interface


import jfxsomajogo.fsm.AguardaReinicio;

public enum EstadoID {
    //os ID dos estados
    AGUARDA_NOME, AGUARDA_RESPOSTA, AGUARDA_REINICIO
}

//este package agrupa as enumerações e constantes relacioandos com
//integração entre vários módulos da aplicação
//assim, a UD nao tem que improtar coisas dos packages de dados ou FSM
package jfxsomajogo.integracao;
//isto é um package que vai ser usado pelo modelo de dados e pela interface

public enum MsgCode {
    START, RIGHT, WRONG, TIMEOUT
}

package jfxsomajogo.integracao;
//isto é um package que vai ser usado pelo modelo de dados e pela interface

public enum PropsID {
    
    //podiam ser usadas constantes
    //"" -> alteração gráfica
    PROP_ESTADO("prop_estado"),
    PROP_DESAFIO("prop_desafio"),
    PROP_RELOGIO("prop_relogio");
    
    String valor;

    private PropsID(String v) {
        this.valor = v;
    }

    @Override
    public String toString() {
        return valor;
    }
}

package jfxsomajogo.modelo;

import java.io.Serializable;
import java.util.Random;
import jfxsomajogo.integracao.MsgCode;

public class SomaDados implements Serializable {

    private static final int COUNTDOWN_TIMEOUT = 10;
    private static final int MAX_ERROS = 3;
    private static final int MIN_VALOR = 1;
    private static final int MAX_VALOR = 100;

    private String jogador = "X";
    private MsgCode msg; //ver o estado actual
    private int pontuacao, erros;
    private int numA, numB;
    private int countdown;
    Random rand;

    SomaDados() {
        rand = new Random();
        jogador = "X";
        msg = MsgCode.START;
        pontuacao = erros = numA = numB = -1;
        countdown = -1;

    }

    public final void reset() {
        pontuacao = 0;
        erros = 0;
        novoDesafio();
        msg = MsgCode.START;
    }

    public void defineNomeJogador(String nome) {
        jogador = nome;
    }

    public void novoDesafio() {
        numA = rand.nextInt(MAX_VALOR - MIN_VALOR + 1) + MIN_VALOR;
        numB = rand.nextInt(MAX_VALOR - MIN_VALOR + 1) + MIN_VALOR;
        resetCountDown();
    }

    public void diminuiCountDown() {
        --countdown;
        if (countdown <= 0) {
            msg = MsgCode.TIMEOUT;
            erros++;
            novoDesafio();
        }
    }

    public void tentaResposta(int resp) {
        if (resp == (numA + numB)) {
            pontuacao++;
            msg = MsgCode.RIGHT;
            novoDesafio();
        } else {
            erros++;
            msg = MsgCode.WRONG;
        }
    }

    //para ver a evolução dos estados
    public boolean jogadorValido() {
        //se indicar o nome, pode ir para jogar
        return jogador != null && jogador.length() > 0;
    }

    public boolean excedeuErros() {
        return erros >= MAX_ERROS;
    }

    //obtem info para o ecrã
    public String obtemNomeJogador() {
        return jogador;
    }

    public int obtemNumA() {
        return numA;
    }

    public int obtemNumB() {
        return numB;
    }

    public int obtemPontuacao() {
        return pontuacao;
    }

    public int obtemErros() {
        return erros;
    }

    public int obtemCountDown() {
        return countdown;
    }

    public MsgCode obtemMsg() {
        return msg;
    }

    private void resetCountDown() {
        countdown = COUNTDOWN_TIMEOUT;
    }
}

package jfxsomajogo.modelo;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import jfxsomajogo.fsm.AguardaNomeJogador;
import jfxsomajogo.fsm.ISomaFSM;
import jfxsomajogo.integracao.EstadoID;
import jfxsomajogo.integracao.MsgCode;
import jfxsomajogo.integracao.PropsID;

//esta é a classe "contexto" da máquina de estados
//tem a máquina de estados + dados
//máquina de estados
public class SomaJogo implements Serializable {

    private final SomaDados dados = new SomaDados(); //criar o modelo de dados
    private ISomaFSM estado = null;  //define o estado incial

    public SomaJogo() {
        estado = new AguardaNomeJogador(dados);
    }

    //defineEstado recebe o próximoe stado
    private Set<PropsID> defineEstado(ISomaFSM prox, PropsID... eventosBase) {
        //isto vai ajudar no observable, vai avisar a vista
        Set<PropsID> eventos = new HashSet<>(Set.of(eventosBase));
        ISomaFSM anterior = estado;
        estado = prox;
        if (anterior != prox) {
            eventos.add(PropsID.PROP_ESTADO);
        }
        return eventos;
    }

    //operação do sistema ("dispositivo") contexto da FSM
    //-> reencaminha para FSM
    //os métodos que permitem a transição de estados
    //ponte entre o estado, o modelo de estados e a vista
    public Set<PropsID> defineJogador(String nome) {
        //ao inves de retornar o estado pode ser um return de boolean
        //retornar Set<PropsID>, um conjunto de situações de jogo que ajuda na vista do jogo
        //para a parte gráfica
        return defineEstado(estado.defineJogador(nome));
    }

    public Set<PropsID> tentaResposta(int n) {
        return defineEstado(estado.tentaResposta(n), PropsID.PROP_DESAFIO);
        //estas duas significa que podem acontecer dois eventos, e disparar o fire de uma das duas
    }

    public Set<PropsID> recomeca() {
        return defineEstado(estado.recomeca());
    }

    public Set<PropsID> relogioAvanca() {
        return defineEstado(estado.relogioAvanca(), PropsID.PROP_RELOGIO, PropsID.PROP_DESAFIO);
    }

       
    public EstadoID obtemEstadoID() {
        return estado.obtemEstadoID();
    }

    //obtenção de dados para uso nas UI
    //informação relevanta para mostrar ao utilizador
    //-> reencaminha para dados
    
    //isto é o mesmo que os gets apenas traudizdo para obtem
    //para serem mostrados no UI do utilziador
    
    public String obtemNomeJogador() {
        return dados.obtemNomeJogador();
    }

    public int obtemNumA() {
        return dados.obtemNumA();
    }

    public int obtemNumB() {
        return dados.obtemNumB();
    }

    public int obtemPontuacao() {
        return dados.obtemPontuacao();
    }

    public int obtemErros() {
        return dados.obtemErros();
    }

    public MsgCode obtemMsg() {
        return dados.obtemMsg();
    }

    public int obtemCountDown() {
        return dados.obtemCountDown();
    }
    
    //não devemos retornar o modelo SomaDados todo
    //porque se o fizermos vamos dar hipotese a quem faz
    //a vista de alterar os dados

}

package jfxsomajogo.modelo;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import jfxsomajogo.integracao.EstadoID;
import jfxsomajogo.integracao.MsgCode;
import jfxsomajogo.integracao.PropsID;

//missao principal - adicionar o suporte para ligacao a vistas
// = property change support
//mantem a ligacao separada do contexto da FGSM e dados
//permite save/load a FSM+dados sem dependencia (referencia) a vistas
//adiciona save/load neste nivel e age sobre o modelo (contexto da FSM)
public class SomaJogoObs {

    //os propertir change support
    SomaJogo jogo = null; //a referencia para o jogo, maquina de estados
    private PropertyChangeSupport props = null;

    private final Timer relogio;
    private final Temporizador segundos;

    public SomaJogoObs() {
        jogo = new SomaJogo();
        props = new PropertyChangeSupport(jogo);

        relogio = new Timer();
        segundos = new Temporizador();
        relogio.schedule(segundos, 0, 1000);
    }

    //registar o interesse das vistas, quando uma determinada propriedade for alterada
    //
    public void registaPropertyChangeListener(PropsID prop, PropertyChangeListener listener) {
        props.addPropertyChangeListener(prop.toString(), listener);
    }

    private void disparaEventos(Set<PropsID> eventos) {
        for (var e : eventos) {
            props.firePropertyChange(e.toString(), null, null);
        }

        //alternaiva ao for
        //eventos.forEach((e) -> {
        //props.firePropertyChange(e.toString(), null, null);
        //});
    }

    public void paraRelogio() {
        segundos.cancel();
        relogio.purge(); //eliminar todas as as timer text 
        relogio.cancel();
    }

    // inicio: métodos que fazem a ponte entre as vistas e a maquina de estados
    public void relogioAvanca() {
        disparaEventos(jogo.relogioAvanca());
    }

    // operação do sistema ("dispotivo") - reencaminha para jogo depois p/ FSM
    public void defineJogador(String nome) {
        disparaEventos(jogo.defineJogador(nome));
    }

    public void tentaResposta(int n) {
        disparaEventos(jogo.tentaResposta(n));

        //alternaiva ao udo do disparaEventos
        //jogo.tentaResposta(n);
        //props.firePropertyChange(PropsID.PROP_DESAFIO, null. null);
        //props.firePropertyChange(PropsID.PROP_ESTADO, null. null);
    }

    public void recomeca() {
        disparaEventos(jogo.recomeca());
    }

    public EstadoID obtemEstadoID() {
        return jogo.obtemEstadoID();
    }
    //fim: métodos que fazem a ponte entre as vistas e a maquina de estados

    //obenção de dados para uso das UI - reencaminha p/jogo (depois para dados)
    public String obtemNomeJogador() {
        return jogo.obtemNomeJogador();
    }

    public int obtemNumA() {
        return jogo.obtemNumA();
    }

    public int obtemNumB() {
        return jogo.obtemNumB();
    }

    public int obtemPontuacao() {
        return jogo.obtemPontuacao();
    }

    public int obtemErros() {
        return jogo.obtemErros();
    }

    public MsgCode obtemMSG() {
        return jogo.obtemMsg();
    }

    public int obtemCountDown() {
        return jogo.obtemCountDown();
    }

    //load/save
    public void saveGame(String filename) {
        ObjectOutputStream out;
        try {
            out = new ObjectOutputStream(new FileOutputStream(filename));
            out.writeObject(jogo);
            out.close();
        } catch (IOException e) {
            Logger.getLogger(SomaJogoObs.class.getName()).log(Level.SEVERE, null, e);
        }
    }

    public void loadGame(String filename) {
        ObjectInputStream in;
        try {
            in = new ObjectInputStream(new FileInputStream(filename));
            jogo = (SomaJogo) in.readObject();
            in.close();
            props.firePropertyChange(PropsID.PROP_ESTADO.toString(), null, null);
        } catch (IOException | ClassNotFoundException e) {
            Logger.getLogger(SomaJogoObs.class.getName()).log(Level.SEVERE, null, e);
        }
    }

    //time taks
    class Temporizador extends TimerTask {
        @Override
        public void run() {
            relogioAvanca();
        }
    }
}

package jfxsomajogo.ui;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import jfxsomajogo.integracao.EstadoID;
import jfxsomajogo.integracao.MsgCode;
import jfxsomajogo.integracao.PropsID;
import jfxsomajogo.modelo.SomaJogoObs;


//esta é uma classe genérica, que é um adpater para PropertyChangeListener
//PropertyChangeListenerJFXAdapter faz com que seja implementado o PropertyChangeListener
//vai implementar o propertyChange, que é o método obrigatório pelo inteface método PropertyChangeListener
//e sempre que ele for chamado, e antes de correr o código pretendido ele faz um  
// Platform.runLater(() do método onChange(evt);
// e quanto ele for corrido ele já foi corrido no contexto do .runLater(()
//com o objecto qd é criado é abstracto 
//por exemplo propsID.PROP_ESTADO, new PropertyChangeListenerJFXAdapter() 
//sou obrigado a implementar o onChange(), com todo o código necessário
//para as alterações que eu necessito 
//e assim o onChange() já foi executado na thread do javaFX
//evito assim que estoire, e que acontece quanto tentamos executar código a partir de uma thread
//difernte da que está responsavel por fazer a gestão dos componentes gráficos
//isto por causa da utilização do timer, porque o timer está numa thread à parte


abstract class PropertyChangeListenerJFXAdapter implements PropertyChangeListener{
    @Override
    public final void propertyChange(PropertyChangeEvent evt){
        Platform.runLater(()->{
            onChange(evt);
        });
    }
abstract public void onChange(PropertyChangeEvent evt);
}


public class SomaUI extends BorderPane {

    SomaJogoObs adivObs;

    public SomaUI(SomaJogoObs a) {
        adivObs = a;
        FileChooser fileChooser = new FileChooser();

        //esta funcao esta extensa. passar código para funcções auxiliares
        //implica passar as refs locais dos componentes para a classe
        //cria componentes
        //menu
        MenuBar menuBar = new MenuBar();

        Menu fileMenu = new Menu("file");
        MenuItem fileNew = new MenuItem("new");
        MenuItem fileSave = new MenuItem("save");
        MenuItem fileLoad = new MenuItem("load");
        MenuItem fileExit = new MenuItem("exit");
        fileMenu.getItems().addAll(fileNew, fileSave, fileLoad, fileExit);

        Menu aboutMenu = new Menu("about");
        MenuItem aboutInfo = new MenuItem("info");
        aboutMenu.getItems().addAll(aboutInfo);

        menuBar.getMenus().addAll(fileMenu, aboutMenu);
        setTop(menuBar);

        //eventos para os menus
        //file->new
        fileNew.setOnAction((ActionEvent e) -> {
            adivObs.recomeca();
        });
        //file-> save
        fileSave.setOnAction((ActionEvent e) -> {
            File f = fileChooser.showSaveDialog(getScene().getWindow());
            if (f != null) {
                adivObs.saveGame(f.getAbsolutePath());
            }

        });

        //file -> load
        fileLoad.setOnAction((ActionEvent e) -> {
            File f = fileChooser.showSaveDialog(getScene().getWindow());
            if (f != null) {
                adivObs.loadGame(f.getAbsolutePath());
            }

        });

        //file -> exit
        fileExit.setOnAction((ActionEvent e) -> {
            encerra();
            ((Stage) getScene().getWindow()).close();

            //Platform.exit(); //funciona apenas em windows
        });
        //about
        aboutInfo.setOnAction((ActionEvent e) -> {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setHeaderText("acerca disto");
            alert.getDialogPane().setContentText("programa de javafx");

            alert.showAndWait();
        });

        StackPane areaUtil = new StackPane();
        areaUtil.setPadding(new Insets(10));

        UINome uinome = new UINome(); //é um pane
        UIJoga uijoga = new UIJoga(); //é um pane
        UIFim uifim = new UIFim();

        uijoga.setVisible(false);
        uifim.setVisible(false);

        areaUtil.getChildren().addAll(uinome, uijoga, uifim);

        setCenter(areaUtil);
    }

    public void encerra() {
        adivObs.paraRelogio();
    }

    class UINome extends VBox {

        private final Label lNome = new Label("escreve nome");
        private final TextField tfNome = new TextField();
        private final Button btnDefineNome = new Button("ok");

        public UINome() {
            super(10); //espaçamento entre items
            adivObs.registaPropertyChangeListener(PropsID.PROP_ESTADO, new PropertyChangeListenerJFXAdapter() {
                //registaPropertyChangeListener para sermos avisados de evolução de estados
                @Override
                public void onChange(PropertyChangeEvent evt) {
                    setVisible(adivObs.obtemEstadoID() == EstadoID.AGUARDA_NOME);
                }
            });
            btnDefineNome.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent t) {
                    adivObs.defineJogador(tfNome.getText());
                }
            });
            tfNome.setOnKeyPressed(e -> {
                if (e.getCode() == KeyCode.ENTER) {
                    adivObs.defineJogador(tfNome.getText());
                }
            });
            getChildren().addAll(lNome, tfNome, btnDefineNome);

        }

    }

    class UIJoga extends VBox {

        private final Label lMsg = new Label();
        private final Label lDesafio = new Label();
        private final TextField tfResposta = new TextField();
        private final Button btnEnviaResposta = new Button("ok");
        private final Label lRelogio = new Label();
        Map<MsgCode, String> mensagens = new HashMap<>();

        public UIJoga() { //1,39
            super(10); //espaçamento entre items
            mensagens.put(MsgCode.START, "vamos começar");
            mensagens.put(MsgCode.RIGHT, "certo. outro desafio");
            mensagens.put(MsgCode.WRONG, "errado. tenta outra vez");
            mensagens.put(MsgCode.TIMEOUT, "tempo excedido. outro desafio");

            btnEnviaResposta.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent t) {
                    tentaResposta();
                }
            });
            tfResposta.setOnKeyPressed(e -> {
                if (e.getCode() == KeyCode.ENTER) {
                    tentaResposta();
                }
            });

            adivObs.registaPropertyChangeListener(PropsID.PROP_ESTADO, new PropertyChangeListenerJFXAdapter() {
                //registaPropertyChangeListener para sermos avisados de evolução de estados
                @Override
                public void onChange(PropertyChangeEvent evt) {
                    if (adivObs.obtemEstadoID() == EstadoID.AGUARDA_RESPOSTA) {
                        setVisible(true);
                        defineMensagens(); //atualziar todas as labels com o texto em causa
                        intiTfResposta(); //por o texto a vazio (escrita do texto), quando existe mudança de estado
                    } else {
                        setVisible(false);
                    }
                }
            });

            adivObs.registaPropertyChangeListener(PropsID.PROP_DESAFIO, new PropertyChangeListenerJFXAdapter() {
                //registaPropertyChangeListener para sermos avisados de evolução de estados
                @Override
                public void onChange(PropertyChangeEvent evt) {
                    defineMensagens();
                }
            });

            adivObs.registaPropertyChangeListener(PropsID.PROP_RELOGIO, new PropertyChangeListenerJFXAdapter() {
                //registaPropertyChangeListener para sermos avisados de evolução de estados
                @Override
                public void onChange(PropertyChangeEvent evt) {
                    //para processamento futuro caso necessário
                }
            });

            getChildren().addAll(lMsg, lDesafio, tfResposta, btnEnviaResposta, lRelogio);
            defineMensagens();
        }

        private void defineMensagens() {
            lMsg.setText(mensagens.getOrDefault(adivObs.obtemMSG(), "nao compreendo.."));
            //adivObs.obtemMSG() com ajuda de um switch case para obter as mensagens (string) acerca do estado
            //em que se encontra
            //a alternativa foi a opção de se usar um Map<MsgCode, String> mensagens

            lDesafio.setText(adivObs.obtemNomeJogador()
                    + " ,quando é "
                    + adivObs.obtemNumA()
                    + " + "
                    + adivObs.obtemNumB() + "?"
            );
            lRelogio.setText("tempo restante: " + adivObs.obtemCountDown());
        }

        private void intiTfResposta() {
            //serve para apagar a resposta que é escrita
            //e só acontece quando existe mudança de estado
            tfResposta.setText("");
            tfResposta.requestFocus();

        }

        private void tentaResposta() {
            try {
                int val = Integer.parseInt(tfResposta.getText());
                adivObs.tentaResposta(val);
                intiTfResposta();

            } catch (NumberFormatException e) {

            }
        }
    }

    class UIFim extends VBox {

        private final Label lResultado = new Label();
        private final Button btnRecomecar = new Button("Novo jogo");

        public UIFim() {
            super(5);
            adivObs.registaPropertyChangeListener(PropsID.PROP_ESTADO, new PropertyChangeListenerJFXAdapter() {
                @Override
                public void onChange(PropertyChangeEvent evt) {
                    if (adivObs.obtemEstadoID() == EstadoID.AGUARDA_REINICIO) {
                        setVisible(true);
                        lResultado.setText(adivObs.obtemNomeJogador()
                                + ", o teu resultado:\n"
                                + "pontuação: "
                                + adivObs.obtemPontuacao()
                                + "\n"
                                + "Erros:" + +adivObs.obtemErros()
                                + "(obviamente)\n\n"
                                + "ok para jogar outra vez\n\n"
                        );
                        //formatação com \n em ambiente grafico - tem tudo a ver
                    } else {
                        setVisible(false);
                    }
                }
            });
            btnRecomecar.setOnAction((ActionEvent e) -> {
                adivObs.recomeca();
            }
            );
            getChildren().addAll(lResultado, btnRecomecar);
        }

    }

}

Tags : ,

JavaFX, exercício 3

package recursopa;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import recursopa.iu.gui.PaneOrganizer;

public class RecursoPA extends Application {
    public static void main(String[] args) {
        //passamos os argumentos para o subsistema gráfico os parametros
        launch(args); 
    }
 
    @Override
    //quando começa a aplicação
    public void start(Stage stage) throws Exception{
        PaneOrganizer po = new PaneOrganizer();
        Scene scene = new Scene(po,600,400);
        stage.setScene(scene); //aplica a cena no stage
        stage.setTitle("Exercicio de programação avançada");
        stage.setMinHeight(300.0);
        stage.setMinWidth(300.0);
        stage.show();
    }
}   
package recursopa.iu.gui;
import javafx.event.EventHandler;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
import recursopa.logica.Figura;

public class PaneOrganizer extends Pane {
    //vai extender sempre um dos containers possiveis,  extends Pane

    Figura fig;
    Ellipse elipse;

    public PaneOrganizer() {
        fig = new Figura();
        fig.setPrimeiroPonto(0, 0);
        fig.setSegundoPonto(100, 50);
        fig.setRGB(0, 50, 0);

        criaLayout(); //para criar os componentes que vão surgir no ecrã
        registaListeners(); // registar os comportamentos dos objectos
        atualizaElipse();

    }

    void criaLayout() {
        //adicionar o elemento ao Pane
        elipse = new Ellipse();
        this.getChildren().add(elipse);
    }

    public void registaListeners() {
        //detectar as ações do rato
        this.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent t) {
                fig.setPrimeiroPonto((int) t.getX(), (int) t.getY());
                fig.setSegundoPonto((int) t.getX(), (int) t.getY());
                fig.setRGB((int) (Math.random() * 256), (int) (Math.random() * 256), (int) (Math.random() * 256));
                atualizaElipse();
            }
        });

        //usando lambda functions
        this.setOnMouseReleased((t) -> {
            fig.setSegundoPonto((int) t.getX(), (int) t.getY());
            atualizaElipse();
        });
        this.setOnMouseDragged((t) -> {
            fig.setSegundoPonto((int) t.getX(), (int) t.getY());
            atualizaElipse();
        });

    }

    //para desenhar a elipse
    void atualizaElipse() {
        //elipse.setFill(Color.GREEN);
        elipse.setFill(Color.rgb(fig.getR(), fig.getG(), fig.getB())); //para ir buscar as informações à fig
        //elipse.setCenterX(200.0);
        elipse.setCenterX((fig.getXi() + fig.getXf()) / 2);
        //elipse.setCenterY(200.0);
        elipse.setCenterY((fig.getYi() + fig.getYf()) / 2);
        //elipse.setRadiusX(150.0);
        elipse.setRadiusX(fig.getLargura() / 2);
        //elipse.setRadiusY(100.0);
        elipse.setRadiusY(fig.getAltura() / 2);
    }

}

package recursopa.logica;
public class Figura {
//métodos necessários para gerir a figura

    int xi, yi, xf, yf; //posicao e tamanho
    int r, g, b; //para a cor

    public Figura() {

    }

    public int getXi() {
        return xi;
    }

    public int getYi() {
        return yi;
    }

    public int getXf() {
        return xf;
    }

    public int getYf() {
        return yf;
    }

    public int getR() {
        return r;
    }

    public int getG() {
        return g;
    }

    public int getB() {
        return b;
    }

    public void setRGB(int r, int g, int b) {
        this.r = r;
        this.g = g;
        this.b = b;
    }

    public void setPrimeiroPonto(int x, int y) {
        this.xi = x;
        this.yi = y;
    }

    public void setSegundoPonto(int x, int y) {
        this.xf = x;
        this.yf = y;
    }

    public int getLargura() {
        return Math.abs(xf - xi); //não interessa a ordem dos valores
    }

    public int getAltura() {
        return Math.abs(yf - yi); //não interessa a ordem dos valores
    }
}

Tags : ,

JavaFX, exercícios

Relembrar para o netBeans correr um projeto com JavaFX e nas propriedades de um projeto:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class RecursoPA extends Application {
    public static void main(String[] args) {
        //passamos os argumentos para o subsistema gráfico os parametros
        launch(args); 
    }
 
    @Override
    //quando começa a aplicação
    public void start(Stage stage) throws Exception{
        BorderPane bp = new BorderPane();
        Label label1 = new Label("programação avançada");
        Label label2 = new Label("outra label");
        bp.setBottom(label1);
        bp.setTop(label2);
        //criar a cena
        Scene scene = new Scene(bp,400,400); //raiz da cena, e dimensões
        //adicionar a cena ao palco
        stage.setScene(scene);
        stage.show();
    }
}   
Tags : ,