Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 115 additions & 93 deletions gerenciamento/src/edu/hackaton/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,100 +8,122 @@

import java.time.LocalDateTime;

/*
* REVIEW [Arquitetura]: Inconsistência estrutural - arquivos em edu/hackaton/, mas package br.edu.hackathon.
* Alinhar diretório ao pacote (convenção Java) ou atualizar README.
*/
public class Main {
public static void main(String[] args) {

Universidade u1 = new Universidade("UFABC");
Universidade u2 = new Universidade("USP");
Empresa emp1 = new Empresa("Google");
Empresa emp2 = new Empresa("Meta");
// REVIEW [Arquitetura / SRP]: main concentra bootstrap, avaliação, persistência
// e relatório (God Method).
// Sugestão: extrair GerenciadorHackathon ou HackathonBootstrap; main só chama o
// serviço.
public static void main(String[] args) {

Universidade u1 = new Universidade("UFABC");
Universidade u2 = new Universidade("USP");
Empresa emp1 = new Empresa("Google");
Empresa emp2 = new Empresa("Meta");

Profissional orientador1 = new Profissional("Carlos", emp1);
Profissional orientador2 = new Profissional("Ana", emp2);

Equipe equipe1 = new Equipe("Equipe Inovação");
// REVIEW [Regra de negócio]: limite de 5 membros está só no loop;
// Equipe.adicionarMembro não valida.
for (int i = 1; i <= 5; i++) {
equipe1.adicionarMembro(new Estudante("Aluno" + i, u1));
}
Projeto projeto1 = new Projeto("Sistema IoT", orientador1, equipe1);

Equipe equipe2 = new Equipe("Equipe Tecnologia");
for (int i = 6; i <= 10; i++) {
equipe2.adicionarMembro(new Estudante("Aluno" + i, u2));
}
Projeto projeto2 = new Projeto("App Mobile", orientador2, equipe2);

Equipes equipesRepo = Equipes.getInstance();
equipesRepo.adicionarEquipe(equipe1);
equipesRepo.adicionarEquipe(equipe2);

Banca banca1 = new Banca(projeto1);
banca1.adicionarNota(new Jurado("Jurado 1", emp1), 8);
banca1.adicionarNota(new Jurado("Jurado 2", emp1), 7);
banca1.adicionarNota(new Jurado("Jurado 3", emp2), 9);
banca1.adicionarNota(new Jurado("Jurado 4", emp2), 8);

Banca banca2 = new Banca(projeto2);
banca2.adicionarNota(new Jurado("Jurado 5", emp2), 6);
banca2.adicionarNota(new Jurado("Jurado 6", emp1), 3);
banca2.adicionarNota(new Jurado("Jurado 7", emp1), 6);
banca2.adicionarNota(new Jurado("Jurado 8", emp2), 5);

Apresentacao ap1 = new Apresentacao(
projeto1,
banca1,
new Sala("Auditório Principal"),
LocalDateTime.now());
ap1.avaliar();

Apresentacao ap2 = new Apresentacao(
projeto2,
banca2,
new Sala("Sala 205"),
LocalDateTime.now());
ap2.avaliar();

/*
* REVIEW [Fluxo / Repository]: apresentações avaliadas antes de ir ao
* repositório;
* relatório usa só Equipes - Apresentacoes fica subutilizado. Registrar antes
* ou listar por apresentacoesRepo.
*/
Apresentacoes apresentacoesRepo = Apresentacoes.getInstance();
apresentacoesRepo.adicionar(ap1);
apresentacoesRepo.adicionar(ap2);

System.out.println("====================================");
System.out.println("PROJETOS APROVADOS (NOTA >= 7)");
System.out.println("====================================");

// REVIEW [Code smell]: número mágico 7 - extrair NOTA_MINIMA_APROVACAO ou
// PoliticaAvaliacao.
equipesRepo.getEquipes().stream()
.filter(e -> e.getProjeto().getNotaFinal() >= 7)
.forEach(e -> {
Projeto p = e.getProjeto();
// REVIEW [Lei de Demeter]: cadeia e.getProjeto().getOrientador() - preferir
// p.resumoParaRelatorio() ou DTO.
System.out.printf(
"» %s - Nota: %d%n" +
" Orientador: %s%n" +
" Equipe: %s (%d membros)%n%n",
p.getNome(),
p.getNotaFinal(),
p.getOrientador().getNome(),
e.getNome(),
e.getMembros().size());
});

System.out.println("====================================");
System.out.println("PROJETOS REPROVADOS (NOTA < 7)");
System.out.println("====================================");

/*
* REVIEW [DRY / Refatoração]: dois streams quase iguais - usar
* Collectors.partitioningBy
* ou classe RelatorioConsole com um único ponto de iteração.
*/
equipesRepo.getEquipes().stream()
.filter(e -> e.getProjeto().getNotaFinal() < 7)
.forEach(e -> {
Projeto p = e.getProjeto();
System.out.printf(
"» %s - Nota: %d%n" +
" Motivo: Nota insuficiente%n%n",
p.getNome(),
p.getNotaFinal());
});

Profissional orientador1 = new Profissional("Carlos", emp1);
Profissional orientador2 = new Profissional("Ana", emp2);

Equipe equipe1 = new Equipe("Equipe Inovação");
for (int i = 1; i <= 5; i++) {
equipe1.adicionarMembro(new Estudante("Aluno" + i, u1));
}
Projeto projeto1 = new Projeto("Sistema IoT", orientador1, equipe1);

Equipe equipe2 = new Equipe("Equipe Tecnologia");
for (int i = 6; i <= 10; i++) {
equipe2.adicionarMembro(new Estudante("Aluno" + i, u2));
}
Projeto projeto2 = new Projeto("App Mobile", orientador2, equipe2);

Equipes equipesRepo = Equipes.getInstance();
equipesRepo.adicionarEquipe(equipe1);
equipesRepo.adicionarEquipe(equipe2);

Banca banca1 = new Banca(projeto1);
banca1.adicionarNota(new Jurado("Jurado 1", emp1), 8);
banca1.adicionarNota(new Jurado("Jurado 2", emp1), 7);
banca1.adicionarNota(new Jurado("Jurado 3", emp2), 9);
banca1.adicionarNota(new Jurado("Jurado 4", emp2), 8);

Banca banca2 = new Banca(projeto2);
banca2.adicionarNota(new Jurado("Jurado 5", emp2), 6);
banca2.adicionarNota(new Jurado("Jurado 6", emp1), 3);
banca2.adicionarNota(new Jurado("Jurado 7", emp1), 6);
banca2.adicionarNota(new Jurado("Jurado 8", emp2), 5);

Apresentacao ap1 = new Apresentacao(
projeto1,
banca1,
new Sala("Auditório Principal"),
LocalDateTime.now()
);
ap1.avaliar();

Apresentacao ap2 = new Apresentacao(
projeto2,
banca2,
new Sala("Sala 205"),
LocalDateTime.now()
);
ap2.avaliar();

Apresentacoes apresentacoesRepo = Apresentacoes.getInstance();
apresentacoesRepo.adicionar(ap1);
apresentacoesRepo.adicionar(ap2);

System.out.println("====================================");
System.out.println("PROJETOS APROVADOS (NOTA >= 7)");
System.out.println("====================================");

equipesRepo.getEquipes().stream()
.filter(e -> e.getProjeto().getNotaFinal() >= 7)
.forEach(e -> {
Projeto p = e.getProjeto();
System.out.printf(
"» %s - Nota: %d%n" +
" Orientador: %s%n" +
" Equipe: %s (%d membros)%n%n",
p.getNome(),
p.getNotaFinal(),
p.getOrientador().getNome(),
e.getNome(),
e.getMembros().size()
);
});

System.out.println("====================================");
System.out.println("PROJETOS REPROVADOS (NOTA < 7)");
System.out.println("====================================");

equipesRepo.getEquipes().stream()
.filter(e -> e.getProjeto().getNotaFinal() < 7)
.forEach(e -> {
Projeto p = e.getProjeto();
System.out.printf(
"» %s - Nota: %d%n" +
" Motivo: Nota insuficiente%n%n",
p.getNome(),
p.getNotaFinal()
);
});

}
}
}
15 changes: 14 additions & 1 deletion gerenciamento/src/edu/hackaton/model/Apresentacao.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,32 @@

public class Apresentacao {
private Projeto projeto;

/*
* REVIEW [Nomenclatura / DIP]: campo "avaliavel" sugere interface, mas tipo é Banca (concreto).
* Renomear para banca ou declarar como IAvaliavel para polimorfismo (Strategy).
*/
private Banca avaliavel;
private Sala sala;
private LocalDateTime horario;

/*
* REVIEW [Validação inconsistente]: Projeto, Banca e Sala validam nulos; aqui não.
* Usar Objects.requireNonNull em todos os parâmetros do construtor.
*/
public Apresentacao(Projeto projeto, Banca banca, Sala sala, LocalDateTime horario) {
this.projeto = projeto;
this.avaliavel = banca;
this.sala = sala;
this.horario = horario;
}

/*
* REVIEW [Responsabilidade]: orquestra avaliação corretamente, mas poderia emitir evento
* ou delegar a um AvaliacaoService na camada de aplicação (separação domínio vs orquestração).
*/
public void avaliar() {
int media = avaliavel.calcularNotaFinal();
projeto.setNotaFinal(media);
}
}
}
21 changes: 21 additions & 0 deletions gerenciamento/src/edu/hackaton/model/Banca.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,19 @@
import java.util.HashMap;
import java.util.Map;

/*
* REVIEW [Padrão Strategy / DIP]: implementa IAvaliavel, mas Apresentacao usa tipo concreto Banca.
* Campo em Apresentacao deveria ser IAvaliavel para trocar estratégia de avaliação sem alterar Apresentacao.
*/
public class Banca implements IAvaliavel {
private Projeto projetoAvaliado;

/*
* REVIEW [Design HashMap]: chave Jurado sem equals/hashCode em Pessoa - compara
* por referência.
* Implementar equals/hashCode em Pessoa ou usar identificador (String) como
* chave.
*/
private Map<Jurado, Integer> jurados = new HashMap<>();

public Banca(Projeto projetoAvaliado) {
Expand All @@ -31,13 +42,23 @@ public int calcularNotaFinal() {
return 0;
}
int soma = jurados.values().stream().mapToInt(Integer::intValue).sum();
/*
* REVIEW [Bug / Regra de negócio]: divisão inteira trunca a média (ex.: 7,75
* vira 7).
* Usar Math.round((double) soma / jurados.size()) ou Strategy
* EstrategiaCalculoNota.
*/
return (int) soma / jurados.size();
}

public Projeto getProjetoAvaliado() {
return projetoAvaliado;
}

/*
* REVIEW [Encapsulamento]: retorna Map mutável interno - expõe estado.
* Retornar Collections.unmodifiableMap(jurados) ou cópia defensiva.
*/
public Map<Jurado, Integer> getJurados() {
return jurados;
}
Expand Down
10 changes: 10 additions & 0 deletions gerenciamento/src/edu/hackaton/model/Equipe.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,20 @@ public Equipe(String nome) {
this.membros = new ArrayList<>();
}

/*
* REVIEW [Regra de negócio]: sem limite de membros no domínio (enunciado sugere
* equipes fixas).
* if (membros.size() >= 5) throw new IllegalStateException("Equipe cheia");
*/
public void adicionarMembro(Estudante estudante) {
membros.add(estudante);
}

/*
* REVIEW [Encapsulamento]: retorna ArrayList mutável - caller pode alterar
* lista interna.
* return Collections.unmodifiableList(membros);
*/
public List<Estudante> getMembros() {
return membros;
}
Expand Down
6 changes: 5 additions & 1 deletion gerenciamento/src/edu/hackaton/model/Estudante.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

import br.edu.hackathon.model.instituicao.Instituicao;

/*
* REVIEW [Subclasse vazia]: marker subclass sem comportamento próprio.
* Se não houver regras específicas de estudante, considerar enum Papel na hierarquia ou composição.
*/
public class Estudante extends Pessoa {
public Estudante(String nome, Instituicao instituicao) {
super(nome, instituicao);
}
}
}
6 changes: 6 additions & 0 deletions gerenciamento/src/edu/hackaton/model/IAvaliavel.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package br.edu.hackathon.model;

/*
* REVIEW [Convenção Java]: prefixo "I" em interfaces é estilo C#; em Java o idioma é Avaliavel.
*
* REVIEW [Padrão Strategy]: contrato adequado para diferentes formas de avaliação (banca presencial, remota, simulada).
* Banca é uma implementação; outras podem calcular média, mediana ou notas ponderadas.
*/
public interface IAvaliavel {
void adicionarNota(Jurado jurado, int nota);
int calcularNotaFinal();
Expand Down
6 changes: 5 additions & 1 deletion gerenciamento/src/edu/hackaton/model/Jurado.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

import br.edu.hackathon.model.instituicao.Instituicao;

/*
* REVIEW [Herança / marker subclass]: Jurado só repassa construtor - sem comportamento extra.
* Alternativa: Profissional com enum TipoProfissional { ORIENTADOR, JURADO } (Replace Type Code with Enum).
*/
public class Jurado extends Profissional {
public Jurado(String nome, Instituicao instituicao) {
super(nome, instituicao);
}
}
}
8 changes: 7 additions & 1 deletion gerenciamento/src/edu/hackaton/model/Pessoa.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

import br.edu.hackathon.model.instituicao.Instituicao;

/*
* REVIEW [Modelo anêmico / hierarquia rasa]: Pessoa só armazena dados; subclasses não diferenciam comportamento.
* Opções: (1) métodos polimórficos (papelNoHackathon()); (2) uma classe Pessoa + enum Papel { ESTUDANTE, ORIENTADOR, JURADO }.
*
* REVIEW [equals/hashCode]: ausentes - impacta HashMap<Jurado, Integer> em Banca.
*/
public abstract class Pessoa {
private String nome;
private Instituicao instituicao;
Expand All @@ -18,4 +24,4 @@ public String getNome() {
public Instituicao getInstituicao() {
return instituicao;
}
}
}
6 changes: 5 additions & 1 deletion gerenciamento/src/edu/hackaton/model/Profissional.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

import br.edu.hackathon.model.instituicao.Instituicao;

/*
* REVIEW [Domínio]: orientador é Profissional vinculado a Empresa - coerente com o modelo.
* Jurado extends Profissional: avaliar se jurado sempre é "profissional" no mesmo sentido (pode ser só papel).
*/
public class Profissional extends Pessoa {
public Profissional(String nome, Instituicao instituicao) {
super(nome, instituicao);
}
}
}
Loading