Agrupar por data

2 respostas
bglbruno

Olá pessoal, bom dia !
Estou com um problema de lógica.

É o seguinte, tenho uma lista de ControleCombustivel

public class ControleCombustivel {
	private long idControle;
	private Equipamento placa;
	private LocalDateTime data;
	private double litros;
	private double quilometragem;
	private BigDecimal valorUnitario;

	/*... Getters e Setters ...*/
}

Dado uma lista de ControleCombustivel, tenho que montar um gráfico que mostra a média de consumo por registro, por dia, por mês e etc.
Por registro eu consegui implementar

public class MediaPorRegistro implements IndicadorMediaCombustivel{
	
	public List<Media> calcula(List<ControleCombustivel> lista) {
		
		List<Media> media = new ArrayList<Media>();
		
		for (int i = 0; i < lista.size(); i++) {
			
			double kmAnterior = i == 0 ? 0 : lista.get(i-1).getQuilometragem();
			
			double km = lista.get(i).getQuilometragem() - kmAnterior;
			double m = km / lista.get(i).getLitros();
			
			media.add(new Media(lista.get(i).getData(), m));
		}
		
		return media;
	}
	
}

Já a média por dia, eu não consegui. E é justamente nela que estou com problemas.
Comecei implementando da seguinte maneira

public class MediaPorDia implements IndicadorMediaCombustivel {

	public List<Media> calcula(List<ControleCombustivel> lista) {
		List<Media> media = new ArrayList<Media>();
		
		LocalDateTime dataInicial = lista.get(0).getData();
		
		double somaKM = 0;
		double somaLITRO = 0;
		
		for (int i = 0; i < lista.size(); i++) {
			ControleCombustivel cc = lista.get(i);
			
			if(dataInicial.getDayOfYear() == cc.getData().getDayOfYear()){
				somaKM += cc.getQuilometragem();
				if(i > 1){
					somaLITRO += cc.getLitros();					
				}
				
				if(i == 0 && cc.getData().getDayOfYear() != lista.get(i+1).getData().getDayOfYear()){
					double m = somaKM / somaLITRO;
					media.add(new Media(cc.getData(), m));	
					dataInicial = cc.getData();
				}
			}else{	
				double m = somaKM / somaLITRO;
				media.add(new Media(cc.getData(), m));
				
				dataInicial = cc.getData();
			}
		}
		return media;
	}
}

Escrevi 3 testes, e 2 deles não passaram.
Se eu passo uma lista com 3 objetos, ele retorna 3 objetos na lista.
Mas, se eu passo 1 objeto o JUnit aponta java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
E, se eu passo 2 objetos, ele me retorna 10 :shock:

public class MediaPorDiaTest {

	/* Não passa, retorna IndexOutOfBoundsException */
	@Test
	public void testaMediaComUmItem(){
		List<ControleCombustivel> lista = new ArrayList<ControleCombustivel>();
		LocalDateTime d = new LocalDateTime();
		
		ControleCombustivel cc = new ControleCombustivel();
		
		cc.setData(d);
		cc.setLitros(10);
		cc.setQuilometragem(1);
		lista.add(cc);
		
		
		List<Media> media = new MediaPorDia().calcula(lista);
		
		assertEquals(1, media.size());
		
	}

	/* Não passa, retorna 10, ao invés de 2 */	
	@Test
	public void testaMediaComDoisItens(){
		List<ControleCombustivel> lista = new ArrayList<ControleCombustivel>();
		LocalDateTime d = new LocalDateTime();
		
		for (int i = 1; i <= 10; i++) {
			
			ControleCombustivel cc = new ControleCombustivel();
			
			cc.setData(d.plusDays(i));
			cc.setLitros(10);
			cc.setQuilometragem(i+1);
			lista.add(cc);
		}
		
		List<Media> media = new MediaPorDia().calcula(lista);
		
		assertEquals(2, media.size());
		
	}
	
	/* Passa */
	@Test
	public void testaMediaComTresItens(){
		List<ControleCombustivel> lista = new ArrayList<ControleCombustivel>();
		LocalDateTime d = new LocalDateTime();
		
		for (int i = 1; i <= 3; i++) {
			
			ControleCombustivel cc = new ControleCombustivel();
			
			cc.setData(d.plusDays(i));
			cc.setLitros(10);
			cc.setQuilometragem(i+1);
			lista.add(cc);
		}
		
		List<Media> media = new MediaPorDia().calcula(lista);
		
		assertEquals(3, media.size());
		
	}
}

Com o JodaTime tem alguma maneira mais simples de implementar isso ?
Ou então, alguém pode me ajudar com esse algoritmo ?

Desde já agradeço!

2 Respostas

mauricioadl

cara confesso que nem li todo seu codigo, mas acho q o erro acontece porque o seu for comeca sempre do 1 e as listas comecam sempre do 0.

Nao poderia ser esse o erro?

bglbruno

mauricioadl:
cara confesso que nem li todo seu codigo, mas acho q o erro acontece porque o seu for comeca sempre do 1 e as listas comecam sempre do 0.

Nao poderia ser esse o erro?

Não não cara, porque os loops que começam com 1 são para teste, e não estão ligados as posições da lista que eu passo pra classe.
O contador do loop, no teste, só serve para popular os objetos.

Se tivesse lido, teria visto isso. rs

Valeu !

Criado 25 de agosto de 2011
Ultima resposta 25 de ago. de 2011
Respostas 2
Participantes 2