package projetofinal;


public aspect ColetorEstatisticasAspect {
	
		private double[] tempoOcupado = new double[2];
		private int[] contaAtendida = new int[2];
		private double[][] tempoServidor = new double[2][3];
		private double[] tempoFalhado = new double[2];
		private int[] contaFalha = new int[2];
		private double[][] tempoFalhaServidor = new double[2][3];
		private double[] tempoEntreFalha = new double[2];
		private double[] tempoEntreFalhaAcumulado = new double[2];
		private int[] contaEntreFalha = new int[2];
		private double[][] tempoEntreFalhaServidor = new double[2][3];
		
		private HTMLw Simulator.outHTML = null;
		
		public void Simulator.setOutHTML(HTMLw obj){
			this.outHTML = obj;
		}
		
		public HTMLw Simulator.getOutHTML(){
			return(this.outHTML);
		}
		
		private void iniciaVariaveis(){
			tempoOcupado = new double[2];
			contaAtendida = new int[2];
			tempoServidor = new double[2][3];
			tempoFalhado = new double[2];
			contaFalha = new int[2];
			tempoFalhaServidor = new double[2][3];
			tempoEntreFalha = new double[2];
			tempoEntreFalhaAcumulado = new double[2];
			contaEntreFalha = new int[2];
			tempoEntreFalhaServidor = new double[2][3];
			tempoOcupado[0]=0.0;
			tempoOcupado[1]=0.0;
			contaAtendida[0]=0;
			contaAtendida[1]=0;
			tempoServidor[0][0]=Double.MAX_VALUE;//minimo
			tempoServidor[0][1]=0.0;//medio
			tempoServidor[0][2]=Double.MIN_VALUE;//maximo
			tempoServidor[1][0]=Double.MAX_VALUE;//minimo
			tempoServidor[1][1]=0.0;//medio
			tempoServidor[1][2]=Double.MIN_VALUE;//maximo
			tempoFalhado[0]=0.0;
			tempoFalhado[1]=0.0;
			contaFalha[0]=0;
			contaFalha[1]=0;
			tempoFalhaServidor[0][0]=Double.MAX_VALUE;//minimo
			tempoFalhaServidor[0][1]=0.0;//medio
			tempoFalhaServidor[0][2]=Double.MIN_VALUE;//maximo
			tempoFalhaServidor[1][0]=Double.MAX_VALUE;//minimo
			tempoFalhaServidor[1][1]=0.0;//medio
			tempoFalhaServidor[1][2]=Double.MIN_VALUE;//maximo
			tempoEntreFalha[0]=0.0;
			tempoEntreFalha[1]=0.0;
			tempoEntreFalhaAcumulado[0]=0.0;
			tempoEntreFalhaAcumulado[1]=0.0;
			contaEntreFalha[0]=0;
			contaEntreFalha[1]=0;
			tempoEntreFalhaServidor[0][0]=Double.MAX_VALUE;//minimo
			tempoEntreFalhaServidor[0][1]=0.0;//medio
			tempoEntreFalhaServidor[0][2]=Double.MIN_VALUE;//maximo
			tempoEntreFalhaServidor[1][0]=Double.MAX_VALUE;//minimo
			tempoEntreFalhaServidor[1][1]=0.0;//medio
			tempoEntreFalhaServidor[1][2]=Double.MIN_VALUE;//maximo
			//edc
			conta1 = 0;
			conta2 = 0;
			acumula1 = new double[1];
			acumula2 = new double[1];
			tMax1 = 0;
			tMax2 = 0;
			tMin1 = 0;
			tMin2 = 0;
			primeiravez1 = true;
			primeiravez2 = true;		

		}
		
		
        pointcut execucao() : execution(public void projetofinal.Simulator.run(..));
        
	    pointcut saida(Item evento) : execution( void projetofinal.Simulator.saida(Item)) && args(evento);

		pointcut termino() : execution( void projetofinal.Simulator.imprimirEstatisticas());

	    pointcut falha(Item evento) : execution( void projetofinal.Simulator.falha(Item)) && args(evento);

	    pointcut retornofalha(Item evento) : execution( void projetofinal.Simulator.retornoFalha(Item)) && args(evento);
	    
        before() : execucao() {
			((Simulator)thisJoinPoint.getThis()).setOutHTML(new HTMLw("saida.html"));
			((Simulator)thisJoinPoint.getThis()).getOutHTML().escreve(cabecalho());
			iniciaVariaveis();
        }
        
		after() : execucao() {
			HTMLw htmlo = ((Simulator)thisJoinPoint.getThis()).getOutHTML();
			htmlo.escreve(montaLinha("Tempo do Servidor 1 ocupado :",Double.toString(Funcoes.round(tempoOcupado[0]))));
			htmlo.escreve(montaLinha("Tempo do Servidor 2 ocupado :",Double.toString(Funcoes.round(tempoOcupado[1]))));
			htmlo.escreve(montaLinha("Tempo de Serviço do Servidor 1:","Min: "+Double.toString(Funcoes.round(tempoServidor[0][0]))+" Méd: "+Double.toString(Funcoes.round(tempoServidor[0][1]))+" Max: "+Double.toString(Funcoes.round(tempoServidor[0][2]))));
			htmlo.escreve(montaLinha("Tempo de Serviço do Servidor 2:","Min: "+Double.toString(Funcoes.round(tempoServidor[1][0]))+" Méd: "+Double.toString(Funcoes.round(tempoServidor[1][1]))+" Max: "+Double.toString(Funcoes.round(tempoServidor[1][2]))));
			htmlo.escreve(montaLinha("Tempo do Servidor 1 falhado :",Double.toString(Funcoes.round(tempoFalhado[0]))));
			htmlo.escreve(montaLinha("Tempo do Servidor 2 falhado :",Double.toString(Funcoes.round(tempoFalhado[1]))));
			htmlo.escreve(montaLinha("Tempo em falha do Servidor 1:","Min: "+Double.toString(Funcoes.round(tempoFalhaServidor[0][0]))+" Méd: "+Double.toString(Funcoes.round(tempoFalhaServidor[0][1]))+" Max: "+Double.toString(Funcoes.round(tempoFalhaServidor[0][2]))));
			htmlo.escreve(montaLinha("Tempo em falha do Servidor 2:","Min: "+Double.toString(Funcoes.round(tempoFalhaServidor[1][0]))+" Méd: "+Double.toString(Funcoes.round(tempoFalhaServidor[1][1]))+" Max: "+Double.toString(Funcoes.round(tempoFalhaServidor[1][2]))));
			htmlo.escreve(montaLinha("Tempo entre falha do Servidor 1:","Min: "+Double.toString(Funcoes.round(tempoEntreFalhaServidor[0][0]))+" Méd: "+Double.toString(Funcoes.round(tempoEntreFalhaServidor[0][1]))+" Max: "+Double.toString(Funcoes.round(tempoEntreFalhaServidor[0][2]))));
			htmlo.escreve(montaLinha("Tempo entre falha do Servidor 2:","Min: "+Double.toString(Funcoes.round(tempoEntreFalhaServidor[1][0]))+" Méd: "+Double.toString(Funcoes.round(tempoEntreFalhaServidor[1][1]))+" Max: "+Double.toString(Funcoes.round(tempoEntreFalhaServidor[1][2]))));
			//EDC
			htmlo.escreve(montaLinha("No. de entidades do tipo 1 no sistema :" , Integer.toString(conta1)));
			htmlo.escreve(montaLinha("Tempo Total de entidades do tipo 1 no sistema :", Double.toString(Funcoes.round(acumula1[0]))));
			htmlo.escreve(montaLinha("Tempo Mínimo de uma entidade do tipo 1 no sistema :" , Double.toString(Funcoes.round(tMin1)))); 
			htmlo.escreve(montaLinha("Tempo Máximo de uma entidade do tipo 1 no sistema :" , Double.toString(Funcoes.round(tMax1))));
			htmlo.escreve(montaLinha("Tempo Médio das entidades do tipo 1 no sistema :" , Double.toString(Funcoes.round((acumula1[0]/conta1)))));
			htmlo.escreve(montaLinha("No. de entidades do tipo 2 no sistema :" , Integer.toString(conta2)));
			htmlo.escreve(montaLinha("Tempo Total do tipo 2 no sistema :" , Double.toString(Funcoes.round(acumula2[0]))));
			htmlo.escreve(montaLinha("Tempo Mínimo de uma entidade do tipo 2 no sistema :" , Double.toString(Funcoes.round(tMin2))));
			htmlo.escreve(montaLinha("Tempo Máximo do uma entidade do tipo 2 no sistema :" , Double.toString(Funcoes.round(tMax2))));
			htmlo.escreve(montaLinha("Tempo Médio das entidades do tipo 2 no sistema :" , Double.toString(Funcoes.round((acumula2[0]/conta2)))));
			htmlo.escreve("</table></body></html>");
			htmlo.fecha();
		}

		after(Item evento) : falha(evento){
			int servidorIndice = evento.getServidor().getTipo()-1;
			tempoEntreFalha[servidorIndice]=evento.getRelogio()-tempoEntreFalha[servidorIndice];
			tempoEntreFalhaAcumulado[servidorIndice]+=tempoEntreFalha[servidorIndice];
			contaEntreFalha[servidorIndice]++;
			tempoEntreFalhaServidor[servidorIndice][0]=Math.min(tempoEntreFalhaServidor[servidorIndice][0], tempoEntreFalha[servidorIndice]);//minimo
			tempoEntreFalhaServidor[servidorIndice][1]=tempoEntreFalhaAcumulado[servidorIndice]/contaEntreFalha[servidorIndice];//medio
			tempoEntreFalhaServidor[servidorIndice][2]=Math.max(tempoEntreFalhaServidor[servidorIndice][2], tempoEntreFalha[servidorIndice]);//maximo
		}

		after(Item evento) : saida(evento) {
			int servidorIndice = evento.getServidor().getTipo()-1;

			tempoOcupado[servidorIndice]+=evento.getEntidade().getTempoEmServico();
			contaAtendida[servidorIndice]++;
			tempoServidor[servidorIndice][0]=Math.min(tempoServidor[servidorIndice][0], evento.getEntidade().getTempoEmServico());//minimo
			tempoServidor[servidorIndice][1]=tempoOcupado[servidorIndice]/contaAtendida[servidorIndice];//medio
			tempoServidor[servidorIndice][2]=Math.max(tempoServidor[servidorIndice][2], evento.getEntidade().getTempoEmServico());//maximo
			//EDC
			Entidade ent_atual;
					
			ent_atual = evento.getEntidade();
			if (ent_atual.getTipo() == Entidade.TIPO1) {
				if (primeiravez1) {
				  primeiravez1 = false;
				  tMin1 = ent_atual.getTempoTotalNoSistema();
				  tMax1 = ent_atual.getTempoTotalNoSistema();
				}				
				conta1 = conta1 + 1;
				acumula1[0] = acumula1[0] + (ent_atual.getTempoTotalNoSistema());
				if (tMin1 > (ent_atual.getTempoTotalNoSistema())){
					tMin1 = ent_atual.getTempoTotalNoSistema();
				}
				if (tMax1 < (ent_atual.getTempoTotalNoSistema())){
					tMax1 = ent_atual.getTempoTotalNoSistema();
				}				
			}
			else{
				if (primeiravez2) {
				  primeiravez2 = false;
				  tMin2 = ent_atual.getTempoTotalNoSistema();
				  tMax2 = ent_atual.getTempoTotalNoSistema();
				}				
				conta2 = conta2 + 1;
				acumula2[0] = acumula2[0] + (ent_atual.getTempoTotalNoSistema());				
				if (tMin2 > (ent_atual.getTempoTotalNoSistema())){
					tMin2 = ent_atual.getTempoTotalNoSistema();
				}
				if (tMax2 < (ent_atual.getTempoTotalNoSistema())){
					tMax2 = ent_atual.getTempoTotalNoSistema();
				}	
			}

		}
		
		after(Item evento) : retornofalha(evento) {
			int servidorIndice = evento.getServidor().getTipo()-1;
			tempoFalhado[servidorIndice]+=evento.getServidor().getTempoEmFalha();
			contaFalha[servidorIndice]++;
			tempoFalhaServidor[servidorIndice][0]=Math.min(tempoFalhaServidor[servidorIndice][0], evento.getServidor().getTempoEmFalha());//minimo
			tempoFalhaServidor[servidorIndice][1]=tempoFalhado[servidorIndice]/contaFalha[servidorIndice];//medio
			tempoFalhaServidor[servidorIndice][2]=Math.max(tempoFalhaServidor[servidorIndice][2], evento.getServidor().getTempoEmFalha());//maximo
			tempoEntreFalha[servidorIndice]=evento.getRelogio();
		}

        
        private String cabecalho(){
        	StringBuffer stbf = new StringBuffer();
        	stbf.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">").append("\n");
			stbf.append("<html><head>").append("\n");
			stbf.append("<title>Resultados</title>").append("\n");
			stbf.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">").append("\n");
			stbf.append("</head>").append("\n");
			stbf.append("<body>").append("\n");
			stbf.append("<table border=\"1\" align=\"center\">").append("\n");
			stbf.append("  <tr bordercolor=\"#666666\" bgcolor=\"#0066FF\"> ").append("\n");
			stbf.append("    <th colspan=\"2\"> <div align=\"center\">Resultados da simula&ccedil;&atilde;o</div></th>").append("\n");
			stbf.append("  </tr>").append("\n");
			stbf.append("  <tr bordercolor=\"#666666\" bgcolor=\"#0099FF\"> ").append("\n");
			stbf.append("    <th>Descri&ccedil;&atilde;o</th>").append("\n");
			stbf.append("    <th>Valor</th>").append("\n");
			stbf.append("  </tr>").append("\n");
			return(stbf.toString());
        }
        
        private String montaLinha (String desc, String val){
			StringBuffer stbf = new StringBuffer();
			stbf.append("<tr bordercolor=\"#00FFFF\" bgcolor=\"#00FF66\">");
			stbf.append("<td>").append(desc).append("</td>");
			stbf.append("<td>").append(val).append("</td>");
			stbf.append("</tr>").append("\n");
			return(stbf.toString());
        }
        
        //EDC
        
		private int conta1 = 0;
		private int conta2 = 0;
		private double[] acumula1 = new double[1];
		private double[] acumula2 = new double[1];
		private double tMax1 = 0;
		private double tMax2 = 0;
		private double tMin1 = 0;
		private double tMin2 = 0;
		private boolean primeiravez1 = true;
		private boolean primeiravez2 = true;		
        
}
