[DÚVIDA] Enquete com MVC

Olá Galera!

Estou com uma dúvida, se alguém puder me ajudar…Nossa! Ficarei muito grato! kkk

O sistema está todo pronto! Tudo funcionando!

Porém para um sistema de votação completo, devemos ter algumas “limitações”…

Abaixo os códigos, quem quiser usar…É livre!

[EDIT]


Os códigos não são de autoria minha…
Rodrigo Rebouças de Almeida é o autor do código…
Colaborou, postando e ensinando, por partes, cada parte da enquete e o porque de cada coisa…
Todo crédito a ele e o muito obrigado!


[EDIT]

Quando tiver resolvido, faço um anexo com os arquivos aqui para quem precisar…Conhecimento é livre!

Vamos parar de enrolação, vamos para o que interessa…

Amo MVC…Então vamos lá…

- Controller: enquete.controller.TelaVotacaoCtrl

package controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import model.EnqueteSimples;

public class TelaVotacaoCtrl implements ActionListener{

    private EnqueteSimples enquete;

    public TelaVotacaoCtrl(EnqueteSimples enquete){
        this.enquete = enquete;
    }

    /**
     * Evento lançado pelo clique nos botoes da TelaVotacao
     * @see java.awt.event.ActionListener#actionPerformed(ActionEvent)
     */
    public void actionPerformed(ActionEvent event) {
        enquete.votar(event.getActionCommand());
    }
}

- Model: enquete.model.EnqueteEvent

package model;

import java.util.EventObject;

public class EnqueteEvent extends EventObject {
    
    private String opcao = null;
    private int votos = 0;

    public EnqueteEvent(EnqueteSimples source){
        super(source);
    }

    public EnqueteEvent(EnqueteSimples source,String opcao){
        this(source);
        this.opcao = opcao;
    }

    /**
     * Retorna a opção associada ao evento gerado.
     * A opção pode ser uma nova opção adicionada à EnqueteSimples
     * ou a opção escolhida para adicionar um novo voto.
     * @return String opção
     */
    public String getOpcao() {
        return opcao;
    }

    /**
     * Retorna o numero de votos da opcao
     * @return int votos
     */
    public int getVotos() {
        return ((EnqueteSimples)this.source).getVotos(opcao);
    }

    /**
     * Retorna o total de votos da enquete
     * @return int
     */
    public int getTotalVotos() {
        return ((EnqueteSimples)this.source).getTotalVotos();
    }
    
}

- Model: enquete.model.EnqueteListener

package model;


import java.util.EventListener;

// Interface comum a todos os interessados em saber sobre os Eventos (EnqueteEvent)
// relacionados ao Source (EnqueteSimple)
public interface EnqueteListener extends EventListener {

    /**
     * Invocado quando um novo voto é contabilizado na Enquete.
     * @param event Evento gerado pela Enquete.
     */
    public void novoVoto(EnqueteEvent event);

    /**
     * Invocado quando uma nova opção é adicionada à Enquete.
     * @param event Evento gerado pela Enquete.
     */
    public void novaOpcao(EnqueteEvent event);
}

- Model: enquete.model.EnqueteSimples

package model;

import java.util.List;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;


public class EnqueteSimples {
    
    
    
private Map <String,Integer>opcoes;

    // Conjunto de interesados (Listeners) em saber sobre mudanças no Source (EnqueteSimples)
    private List <EnqueteListener>enqueteListeners = new LinkedList();

    public EnqueteSimples(){
        opcoes = new HashMap<String, Integer>();
    }

    /**
     * Adiciona uma opção para ser votada na enquete
     * @param opcao nome da opção
     */
    public void addOpcao(String opcao){
        opcoes.put(opcao,new Integer(0));
        this.disparaNovaOpcao(opcao);
    }

    /**
     * Retorna um iterador de opções disponíveis na enquete
     * @return Iterator opções disponiveis na enquete
     */
    public Set <String> getOpcoes(){
        return opcoes.keySet();
    }

    /**
     * Incrementa um voto para opção
     * @param opcao opção que receberá voto
     */
    public void votar(String opcao){
        int votoAtual = (opcoes.get(opcao)).intValue();
        opcoes.put(opcao,new Integer(++votoAtual));
        this.disparaNovoVoto(opcao);
    }

    /**
     * Retorna a soma dos votos de todas as opções da enquete
     * @return int soma dos votos de todas as opções da enquete
     */
    public int getTotalVotos(){

        int total = 0;
        for(Integer votos : opcoes.values()){
            total+= votos.intValue();
        }
        return total;
    }

    /**
     * Retorna a quantidade de votos de uma opção individual
     * @param opcao opção que se quer o voto
     * @return int quantidade de votos da opção
     */
    public int getVotos(String opcao){
        return (opcoes.get(opcao)).intValue();
    }

    /**
     * Adiciona um EnqueteListener, um objeto interessado em
     * receber eventos lançados pela Enquete
     * @see EnqueteListener
     * @param listener objeto interessado em receber eventos
     */
    public synchronized void addEnqueteListener(EnqueteListener listener){

        // Adiciona ao conjunto de Listeners novo interessado em saber sobre as mudanças
        // que ocorrem no Source (EnqueteSimples)

        if(enqueteListeners.contains(listener)){ return; }
        this.enqueteListeners.add(listener);
    }

    /**
     * Informa aos objetos interessados nos eventos lançados
     * pela Enquete que um novo voto foi contabilizado.
     */
    private synchronized void disparaNovoVoto(String opcao){

        // Dispara o evento (EnqueteEvent) a todos os Listeners interssados nas mudanças
        // do Source (EnqueteSimples)

        for(EnqueteListener listeners : this.enqueteListeners){
            listeners.novoVoto(new EnqueteEvent(this,opcao));
        }
    }

    /**
     * Informa aos objetos interessados nos enventos lançados
     * pela Enquete que uma nova opção foi adicionada.
     */
    private synchronized void disparaNovaOpcao(String opcao){

        // Dispara o evento (EnqueteEvent) a todos os Listeners interssados nas mudanças
        // do Source (EnqueteSimples)

        for(EnqueteListener listeners : this.enqueteListeners){
            listeners.novaOpcao(new EnqueteEvent(this,opcao));
        }
    }
}

- View: enquete.view.TelaResultado

package view;

import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Window;
import java.util.HashMap;
import java.util.Map;

import java.awt.Frame;
import model.EnqueteEvent;
import model.EnqueteListener;

// TelaResultado é um interessado em saber sobre o Source (EnqueteSimples)
// por isto implementa a interface EnqueteListener
// Logo, TelaResultado é um Listener

public class TelaResultado extends Window implements EnqueteListener{

    private Map <String, Label>labels = new HashMap();

    public TelaResultado(Frame parent){
        super(parent);
        this.setSize(110,120);
        this.setLayout(new GridLayout(0,2)); // Grid com qualquer numero
                                              // de linhas e uma coluna
        this.add(new Label("Votos"));
        this.add(new Label());

    }

    /**
     * @see enquete.model.EnqueteListener#novaOpcao(EnqueteEvent)
     */

    // Recebe o evento e atualiza os dados de forma simples
    public void novaOpcao(EnqueteEvent event) {
        String opcao = event.getOpcao();

        Label label;
        Label votos;
        if(!labels.containsKey(opcao)){
            label = new Label(opcao+" - ");
            votos = new Label(""+event.getVotos());
            labels.put(opcao,votos);
            this.add(label);
            this.add(votos);
        }
    }

    /**
     * @see enquete.model.EnqueteListener#novoVoto(EnqueteEvent)
     */
    // Recebe o evento e atualiza os dados de forma simples
    public void novoVoto(EnqueteEvent event) {
        String opcao = event.getOpcao();

        Label votos;
        votos = labels.get(opcao);
        votos.setText(""+event.getVotos());
    }

}

- View: enquete.view.TelaResultadoPercentual

package view;

import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Window;
import java.util.HashMap;
import java.util.Map;

import java.awt.Frame;
import model.EnqueteEvent;
import model.EnqueteListener;

// Outro interessado nas mudanças do Sorce (EnqueteSimples)
// Outro Listener
public class TelaResultadoPercentual extends Window implements EnqueteListener{

    private Map <String,Label>labels = new HashMap();

    public TelaResultadoPercentual(Frame parent){
        super(parent);
        this.setSize(180,120);
        this.setLayout(new GridLayout(0,2)); // Grid com qualquer numero
                                              // de linhas e uma coluna
        this.add(new Label("Percentual"));
        this.add(new Label());
    }

    /**
     * @see enquete.model.EnqueteListener#novaOpcao(EnqueteEvent)
     */
    // Manipula as informações adquiridas através do Evento utilizando perentual
    public void novaOpcao(EnqueteEvent event) {
        String opcao = event.getOpcao();

        Label label;
        Label votos;
        if(!labels.containsKey(opcao)){
            label = new Label(opcao+" - ");
            votos = new Label(""+event.getVotos()+" %");
            labels.put(opcao,votos);
            this.add(label);
            this.add(votos);
        }
    }

    /**
     * @see enquete.model.EnqueteListener#novoVoto(EnqueteEvent)
     */
    // Manipula as informações adquiridas através do Evento utilizando perentual
    public void novoVoto(EnqueteEvent event) {
        String opcao = event.getOpcao();

        Label votos;
        votos = labels.get(opcao);
        votos.setText(""+(event.getVotos()*100/event.getTotalVotos())+" %");
    }

}

- View: enquete.view.TelaVotacao

package view;

import java.awt.Button;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Collection;

import java.awt.Frame;
import model.EnqueteEvent;
import model.EnqueteListener;

// Outro interessado nas mudanças do Sorce (EnqueteSimples)
// Outro Listener
public class TelaVotacao extends Frame implements EnqueteListener{

    private Collection <String>botoes = new ArrayList();

    private ActionListener controller;

    public TelaVotacao(ActionListener controller){
        super("Tela de Votação - Enquete");
        this.setSize(100,120);
        this.setLayout(new GridLayout(0,1)); // Grid com qualquer numero
                                              // de linhas e uma coluna
        this.controller = controller;
        this.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                e.getWindow().hide();
                System.exit(0);
            }
        });
    }

    /**
     * @see enquete.model.EnqueteListener#novaOpcao(EnqueteEvent)
     */
    // Manipula as informações adquiridas através do Evento criando novos botões
    public void novaOpcao(EnqueteEvent event) {
        String opcao = event.getOpcao();
        Button botao;

        if(!botoes.contains(opcao)){
            botoes.add(opcao);
            botao = new Button(opcao);
            botao.setActionCommand(opcao);
            botao.addActionListener(controller);
            this.add(botao);
        }
    }

    /**
     * @see enquete.model.EnqueteListener#novoVoto(EnqueteEvent)
     */
    public void novoVoto(EnqueteEvent event) {
        // Nothing to do
    }

}

- Classe para teste se o mesmo funciona:

import controller.TelaVotacaoCtrl;
import model.EnqueteSimples;
import view.TelaResultado;
import view.TelaResultadoPercentual;
import view.TelaVotacao;

public class Enquete{

    public static void main(String[] args) {

        // Modelo
        EnqueteSimples enquete= new EnqueteSimples();

        // Controlador da Interface "TelaVotacao"
        TelaVotacaoCtrl ctrl = new TelaVotacaoCtrl(enquete);

        // Interface que altera o estado do modelo
        TelaVotacao votacao = new TelaVotacao(ctrl);
        votacao.setLocation(5,5);

        // Interface que exibe o resultado absoluto da votacao
        TelaResultado resultado = new TelaResultado(votacao);
        resultado.setLocation(120,5);

        // Interface que exibe o resultado percentual da votacao
        TelaResultadoPercentual resultadoPerc = 
                                new TelaResultadoPercentual(votacao);
        resultadoPerc.setLocation(250,5);

        // Adicionando as interfaces interessadas na mudança do
        // estado do modelo
        enquete.addEnqueteListener(votacao);
        enquete.addEnqueteListener(resultado);
        enquete.addEnqueteListener(resultadoPerc);

        // Povoando o modelo
        enquete.addOpcao("Opção 1");
        enquete.addOpcao("Opção 2");
        enquete.addOpcao("Opção 3");
        enquete.addOpcao("Opção 4");

        // Exibindo as interfaces
        votacao.show();
        resultado.show();
        resultadoPerc.show();
    }

}

A questão é, pensei em algo como “limitar” a 1 voto por usuário (Isso mesmo, logado no site) e alguma forma do usuário do site, poder votar em até 2 ou 3 de uma só vez…
Queria mesmo só uma ideia de como fazer isso…

A princípio a votação está sendo por meio de “Swing”… Estou implementando uma “Área Administrativa”, onde o administrador escolhe as opções e quantas opções a “enquete” irá ter…
Estou ainda com dúvidas, mas estou pesquisando e estou progredindo…Sobre como mostrar as estatísticas por meio de gráfico…

Não sou profissional em Java, ainda…Mas estou me esforçando para me tornar…

Qualquer sugestão, ou crítica (construtiva) será muito bem vinda…

Obrigado!