Fiz a implementação usando TDD, mas vendo a resposta vi que nem todos os itens da lista foram verificados, apenas o último. Em listas grandes essa é uma boa prática ou devemos ver todos os itens.
Segue o código realizado.
package br.com.caelum.leilao.dominio;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import com.google.common.collect.Lists;
public class Leilao {
private String descricao;
private List<Lance> lances;
public Leilao(String descricao) {
this.descricao = descricao;
this.lances = Lists.newArrayList();
}
public void propoe(Lance lance) {
if(isRegrasValidasDo(lance)){
lances.add(lance);
Collections.sort(lances);
}
}
private boolean isRegrasValidasDo(Lance lance) {
return lances.isEmpty() || isUsuarioUltimoLanceDiferenteDoAtual(lance) && isUsuarioLanceAtualJaDeuMenos5LancesComputados(lance);
}
private boolean isUsuarioLanceAtualJaDeuMenos5LancesComputados(Lance lance) {
return lances.stream().filter(l-> l.getUsuario().equals(lance.getUsuario())).count() < 5;
}
private boolean isUsuarioUltimoLanceDiferenteDoAtual(Lance lance) {
return getUltimoUsuario()
.filter(ultimoUsuario-> !ultimoUsuario.equals(lance.getUsuario()))
.isPresent();
}
private Optional<Usuario> getUltimoUsuario() {
if(lances.isEmpty()){
return Optional.empty();
}
return Optional.of(lances.get(lances.size()-1).getUsuario());
}
public String getDescricao() {
return descricao;
}
public EstatisticasDoLeilao getEstatiscasDoLeilao() {
return new EstatisticasDoLeilao(this);
}
public List<Lance> getLances() {
return Collections.unmodifiableList(lances);
}
@Override
public String toString() {
return String.format("Leilao [descricao=%s, lances=%s]", descricao, lances);
}
}
package br.com.caelum.leilao.dominio;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import org.junit.Test;
@SuppressWarnings("unchecked")
public class LeilaoTest {
@Test
public void naoDeveAceitarDoisLancesSeguidosDoMesmoUsuario(){
Usuario paulo = new Usuario("Paulo");
Leilao leilao = LeilaoDataBuilder.builder()
.com("Macbook Air Pro 15")
.comLanceDe(1_000, paulo)
.comLanceDe(2_000, new Usuario("Joana"))
.comLanceDe(3_000, paulo)
.comLanceDe(4_000, paulo)
.build();
assertThat(leilao.getLances(), hasSize(3));
assertThat(leilao.getLances(), contains(hasProperty("valor", is(1000.0)), hasProperty("valor", is(2000.0)), hasProperty("valor", is(3000.0))));
}
@Test
public void naoDeveAceitarMaisDoQue5LancesDeUmMesmoUsuario(){
Usuario paulo = new Usuario("Paulo");
Usuario joana = new Usuario("Joana");
Leilao leilao = LeilaoDataBuilder.builder()
.com("Macbook Air Pro 15")
.comLanceDe(1_000, paulo)
.comLanceDe(2_000, joana)
.comLanceDe(3_000, paulo)
.comLanceDe(4_000, joana)
.comLanceDe(5_000, paulo)
.comLanceDe(6_000, joana)
.comLanceDe(7_000, paulo)
.comLanceDe(8_000, joana)
.comLanceDe(9_000, paulo)
.comLanceDe(10_000, joana)
.comLanceDe(11_000, paulo)
.build();
assertThat(leilao.getLances(), hasSize(10));
assertThat(leilao.getLances(), contains(hasProperty("valor", is(1_000.0)), hasProperty("valor", is(2_000.0)), hasProperty("valor", is(3_000.0)), hasProperty("valor", is(4_000.0)), hasProperty("valor", is(5_000.0)),
hasProperty("valor", is(6_000.0)), hasProperty("valor", is(7_000.0)), hasProperty("valor", is(8_000.0)), hasProperty("valor", is(9_000.0)), hasProperty("valor", is(10_000.0))));
}
}
package br.com.caelum.leilao.dominio;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
public class LeilaoDataBuilder {
private String nomeLeilao = "Playstation 4";
private Ordem ordem;
private int numeroLances;
private List<Lance> lances = new ArrayList<>();
public LeilaoDataBuilder com(String nome){
this.nomeLeilao = nome;
return this;
}
public LeilaoDataBuilder comLancesAutomaticosNaOrdem(int numeroLances, Ordem ordem){
this.numeroLances = numeroLances;
this.ordem = ordem;
return this;
}
public LeilaoDataBuilder comLanceDe(double valorLance, Usuario usuario){
this.lances.add(new Lance(usuario, valorLance));
return this;
}
public static LeilaoDataBuilder builder(){
return new LeilaoDataBuilder();
}
public Leilao build() {
Leilao leilao = new Leilao(nomeLeilao);
if(!lances.isEmpty()){
lances.forEach(leilao::propoe);
}else{
IntStream.range(0, numeroLances)
.mapToObj(i -> new Lance(new Usuario("Fulano " + i), ordem.proximoNumero(i)))
.forEach(l -> leilao.propoe(l));
}
return leilao;
}
public enum Ordem{
CRESCENTE(1,1), DECRESCENTE(999_999, -1);
private int numeroBase;
private int numeroSinal;
private Ordem(int numeroBase, int numeroSinal) {
this.numeroBase = numeroBase;
this.numeroSinal = numeroSinal;
}
public int proximoNumero(int numeroIteracao) {
return numeroBase + (numeroIteracao * numeroSinal);
}
}
}