Usuario:ManuelRomero/estados

De WikiEducator
Saltar a: navegación, buscar



EstadoCalculadora

Es la clase que implementa la máquina de estados
Lleva un atributo que representa el estado acutal de la calculadora
Su método principal es el cambiaEstado con el que se comunica con la clase VentanaCalculadora

Código fuente

package calculadora;
 
 
 
public class EstadoCalculadora {
	//Definir una constante para cada estado
	final int INICIAL =11;
	final int OP1 = 12;
	final int ESPERANDO_OP2=2;
	final int ESPERANDO_DEN_OP1 =7;
	final int DEN_OP1=9;
	final int DEN_OP2=10;
	final int ESPERANDO_DEN_OP2=8;
	final int OP1_DECIMAL=3;
	final int OP2_DECIMAL = 4;
	final int OP2 =5;
	final int RESULTADO =6;
 
	//Definimos las entradas con constantes
	final int NUMERO =100;
	final int OPERADOR_RACIONAL =101;
	final int OPERADOR_REAL =102;
	final int SEPARADOR_PUNTO =103;
	final int SEPARADOR_RACIONAL =104;
	final int IGUAL =105;
	final int MAS_MENOS =106;
	final int RETROCESO =107;
	final int CLEAR =108;
 
	//ConstanttipoCalculadoraes para evaluar modo de calculadora
	final int REAL = 0;
	final int RACIONAL = 1;
 
 
 
 
 
	//atributo estrelpr	
	private int estado;
	private int tipo; //Para saber como interpretar las entradas
 
 
 
 
 
	//constructor
	EstadoCalculadora(){
		estado=INICIAL;
	}
 
	public void setTipo(int tipo){
		if (tipo == 0)
			this.tipo=REAL;
		else
			this.tipo = RACIONAL;
	}
 
 
	/**
	 * doy un tipo de entrada (ver constantes predefinidas)
	 * en función de caracter que representa el botón que el usuario a presionadp
	 * @param c es el caracter que el usuario ha presionado de la calculadora
	 * @return un entero en forma que constante que representa la entrada
	 */
    private int tipoEntrada(char c){
    	//Por defecto el valor de retorno doy clear por su hay una invocación errónea a la función 
    	//que sea clear lo que se devuelva
    	int valor=CLEAR;
    	if ((c >='0')&& (c<='9'))
    		valor= NUMERO;
 
		if ((c=='/')&&(tipo==RACIONAL))
			valor =  SEPARADOR_RACIONAL;
		if (c=='.')
			valor =  SEPARADOR_PUNTO;
		if (tipo==REAL){
			switch (c){
				case '+':
				case '-':
				case '*':
				case '/':
				case '%':
					valor =  OPERADOR_REAL;
			}
		}
		if (tipo==RACIONAL){
			switch (c){
				case '+':
				case '-':
				case '*':
				case ':':
				valor =  OPERADOR_RACIONAL;
			}
		}
		if (c=='=')
			valor =  IGUAL;
		if (c=='C')
			valor =  CLEAR;
		if (c==(char)8592)
			valor =  RETROCESO;
		if (c==(char)177)
			valor =  MAS_MENOS;
		return valor;
    }
			/*
	 * La e es la entrada de la calculadora
	 * el método cambia de estado
	 */
 
private void inicializarEstado(AccionCalculadora accion){
    	estado=INICIAL;
    	//accion.actualiza("0");
    }
 
public void actualizaEstado(Character entrada,
		                    String valorActual,
		                    AccionCalculadora accion,
		                    int tipo){
	setTipo(tipo);
		System.out.println("accion estado actual: "+getEstado(estado) + " entrada "+entrada);
		if (tipoEntrada(entrada)==CLEAR){
			estado=INICIAL;
			accion.limpiaPantalla();//inicializarEstado(accion);
		}
		else
		switch  (estado){
			case INICIAL:
				estado=inicial(entrada,valorActual,accion);
				break;
			case OP1 :
				estado = op1(entrada,valorActual,accion);
				break;
			case OP1_DECIMAL:
				estado =op1Decimal(entrada, valorActual,accion);
				break;
			case ESPERANDO_OP2:
				estado = esperandoOp2(entrada,valorActual,accion);
				break;
			case OP2:
				estado = op2(entrada,valorActual,accion);
				break;
			case OP2_DECIMAL:
				estado = op2Decimal(entrada,valorActual,accion);
				break;
			case RESULTADO:
				estado = resultado(entrada,valorActual,accion);
			break;
			case ESPERANDO_DEN_OP2:
				estado = esperandoDenOp2(entrada,valorActual,accion);
				break;
			case ESPERANDO_DEN_OP1:
				estado = esperandoDenOp1(entrada,valorActual,accion);
				break;
			case DEN_OP1:
				estado = denOp1(entrada,valorActual,accion);
				break;
			case DEN_OP2:
				estado = denOp2(entrada,valorActual,accion);
			break;
 
		}//End switch
		System.out.println("Estado siguiente "+ getEstado(estado));
		System.out.println("===================================");
 
}
private int inicial(Character entrada,String valorActual,AccionCalculadora accion){
	int estado=this.estado;
 
	switch (tipoEntrada(entrada)){
        case NUMERO :
        	estado=OP1;
        	accion.actualiza(valorActual+entrada);
        	break;
        case SEPARADOR_PUNTO :
        	estado=OP1_DECIMAL;
        	accion.actualiza(valorActual+"0"+entrada);
        	break;
        case SEPARADOR_RACIONAL :
        	estado=ESPERANDO_DEN_OP1;
        	accion.actualiza(valorActual+"0"+entrada);
        	break;
 
        case MAS_MENOS :
        	if (valorActual.indexOf('-')==-1)
        		accion.actualiza("-");
        	else
        		accion.limpiaPantalla();
        	break;
        case RETROCESO:
        	accion.actualiza("");
	}
	return estado;
}
private int op1(Character entrada ,String valorActual,AccionCalculadora accion){
	int estado=this.estado;
	switch (tipoEntrada(entrada)){
 
        case NUMERO :
        	int num = Integer.parseInt(valorActual+entrada);//Para quitar posibles ceros a la izquierda
        	accion.actualiza(""+num);
        	break;
        case MAS_MENOS :
        	accion.cambioSignoOp1(valorActual);
        	break;
        case OPERADOR_RACIONAL :
        	if (tipo==RACIONAL){
        	    System.out.println("---");
        		estado=ESPERANDO_OP2;
        		accion.actualiza(valorActual+"/1"+entrada);
        	}
        	break;
        case OPERADOR_REAL :
        	if (tipo==REAL){
        	    estado=ESPERANDO_OP2;
        	    accion.actualiza(valorActual+entrada);
        	}
        	break;
        case SEPARADOR_PUNTO :
        	estado = OP1_DECIMAL;
        	accion.actualiza(valorActual+entrada);
        	break;
        case SEPARADOR_RACIONAL :
        	estado = ESPERANDO_DEN_OP1;
        	accion.actualiza(valorActual+entrada);
        	break;
 
        case RETROCESO :
        	int n= Integer.parseInt(valorActual);
        	if ((n<-9) ||(n>9))
        		estado=OP1;
        	else
        		estado =INICIAL;
        	accion.quitarCaracterOp1(valorActual);
        	break;
        }
		return estado;
	}
private int esperandoDenOp1(Character entrada, String valorActual, AccionCalculadora accion){
 
	   int estado = this.estado;	
		switch (tipoEntrada(entrada)){
	    	case NUMERO :
	    		accion.actualiza(valorActual+entrada);
	    		estado=DEN_OP1;
	    		break;
	    	case MAS_MENOS :
	    		accion.cambioSignoOp1(valorActual);
	    		break;
         	case RETROCESO ://PLEASE SIMPLIFICA ESTO MRM
         		int pos = valorActual.length();
         		if (valorActual.charAt(0)=='-'){
         			if (valorActual.charAt(pos-2)=='0'&pos==3){ //caso "-0/" ==> "-"
         			   estado = INICIAL;
         		       accion.actualiza("-");
         			}
         			else{
         				estado = OP1;
         				accion.quitarCaracterOp1(valorActual);
         			}
         		}
         		else{
         			if (valorActual.charAt(pos-2)=='0'&pos==2){ //caso "0/" ==> ""
          			   estado = INICIAL;
          		       accion.actualiza("");
          			}
          			else{
          				estado = OP1;
          				accion.quitarCaracterOp1(valorActual);
          			}
         		}
		}	
   	return estado;
}
private int op1Decimal (Character entrada, String valorActual,AccionCalculadora accion){
 
	int estado=this.estado;
	switch (tipoEntrada(entrada)){
 
        case NUMERO :
        	accion.actualiza(valorActual+entrada);
        	break;
        case OPERADOR_REAL :
        	estado = ESPERANDO_OP2;
        	if (valorActual.charAt(valorActual.length()-1)=='.')
        		accion.actualiza(valorActual+"0"+entrada);
        	else{
        		float num = Float.parseFloat(valorActual);//Para evitar el caso 9.000000000000000+...
        		accion.actualiza(""+num+entrada);
        	}
        	break;
        case MAS_MENOS :
        	double n= Double.parseDouble(valorActual);
        	accion.actualiza(Double.toString(-n));
        	break;
        case RETROCESO :
        	int pos = valorActual.length();
        	if (valorActual.charAt(pos-1)=='.'){
        		if( Integer.parseInt(valorActual.substring(0,pos-1))==0)
        			estado = INICIAL;
        		else
        			estado = OP1;
        	}
        	else
        		estado = OP1_DECIMAL;
        	accion.quitarCaracterOp1(valorActual);
        	break;
		}
		return estado;
}
private int denOp1(Character entrada, String valorActual, AccionCalculadora accion){
	   int estado = this.estado;	
   	   switch (tipoEntrada(entrada)){
 
	    	case NUMERO :
	    		accion.actualiza(valorActual+entrada);
	    		break;
	    	case OPERADOR_RACIONAL :
	    		estado = ESPERANDO_OP2;
	    		accion.actualiza(valorActual+entrada);
	    		break;
 
	    	case MAS_MENOS :
	    		accion.cambioSignoOp1(valorActual);
	    		break;
 
	    	case RETROCESO :
	    		int pos = valorActual.length();
	    		if (valorActual.charAt(pos-2)=='/')
	    				estado = ESPERANDO_DEN_OP1;
	    		accion.actualiza(valorActual.substring(0,pos-1));
	    		break;
	   }
	return estado;
}
private int esperandoOp2(Character entrada, String valorActual,AccionCalculadora accion){
	int estado=this.estado;
	switch (tipoEntrada(entrada)){
 
        case NUMERO :
        	estado = OP2;
        	accion.actualizarConPosibleParentesis(valorActual,Character.toString(entrada));
        	break;
         //Ante la entrada punto o / no he de ver si estoy en tipo REAL o RACIONAL ya que sólo existe
        	//la entrada punto en tipo REAL :)
        case SEPARADOR_PUNTO :
        	estado=OP2_DECIMAL;
        	accion.actualizarConPosibleParentesis(valorActual,"0"+entrada);
            break;
         case SEPARADOR_RACIONAL :
        	estado=ESPERANDO_DEN_OP2;
        	accion.actualizarConPosibleParentesis(valorActual,"0"+entrada);
            break;
 
        case MAS_MENOS :
        	if (valorActual.contains("("))
        		accion.actualiza(valorActual.substring(0,valorActual.indexOf('(')));
        	else
        		accion.actualiza(valorActual+"(-)");
        	break;
 
        case RETROCESO :
        	int pos = valorActual.length();
        	String op1;
        	if (valorActual.charAt(pos-1)==')'){
        		accion.quitarSignoOp2(valorActual);
        		System.out.println("Esperando Op2 retroceso  "+valorActual);
        	}
           	else{
           		op1=valorActual.substring(0,pos-1);
           		accion.quitarCaracterOp1(valorActual);
        	    if (op1.indexOf('.')!=-1)
    			    estado = OP1_DECIMAL;
        	    else
        	    	if (op1.indexOf('/')!=-1)
        	    		estado = DEN_OP1;
    		        else
    				    estado =OP1;
           	}
        	break;
    	}
	return estado;
}
private int op2(Character entrada, String valorActual,AccionCalculadora accion){
	int estado=this.estado;
	switch (tipoEntrada(entrada)){
        case NUMERO :
        	accion.actualizarConPosibleParentesis(valorActual,""+entrada);
        	break;
        case OPERADOR_RACIONAL :
       		accion.calcula(valorActual,tipo);
       		accion.addResultado(entrada);
       		estado=ESPERANDO_OP2;
        	break;
        case OPERADOR_REAL :
        	accion.calcula(valorActual,tipo);
        	accion.addResultado(entrada);
        	estado=ESPERANDO_OP2;
        	break;
        case SEPARADOR_PUNTO :
        	accion.actualizarConPosibleParentesis(valorActual,""+entrada);
        	estado=OP2_DECIMAL;
        	break;
        case SEPARADOR_RACIONAL :
       	    accion.actualizarConPosibleParentesis(valorActual,""+entrada);
       	    estado=ESPERANDO_DEN_OP2;
        	break;
        case IGUAL :
        	estado= RESULTADO;
        	accion.calcula(valorActual,tipo);
        	break;
        case MAS_MENOS :
        	accion.cambiarSignoOp2(valorActual,tipo);
        	break;
        case RETROCESO :                                     // 1  x/y op z     ==>   x/y op         ESPERANDO_OP2
       //        											    2  x/y op zv    ==>   x/y op z      OP2
       // 	                                                    3  x/y op -(z)  ==>   x/y op -()     ESPERANDO_OP2
       // 	                                                    4  x/y op -(zv) ==>   x/y op -(z)    OP2       	
       // 	                                                    5  x op y       ==>     x op         ESPERANDO_OP2
       // 	                                                    6  x op yz      ==>     x op y       OP2        	
       // 	                                                    7  x op -(y)    ==>     x op -()     ESPERANDO_OP2
       // 	                                                    8  x op -(yz)   ==>     x op -(y)    OP2
        	int c = accion.caracteresOp2(valorActual,tipo);
        	if (c==0)
        	   estado = ESPERANDO_OP2;
         	else 
         		estado = OP2;
        	accion.quitarCaracterOp2(valorActual);
	}
	return estado;
}
private int op2Decimal(Character entrada, String valorActual,AccionCalculadora accion){
	   int estado = this.estado;	
 
		switch (tipoEntrada(entrada)){
 
	    case NUMERO :
	    	accion.actualizaNumOp2Decimal(valorActual,entrada);
	    	break;
	    case OPERADOR_REAL :
	    	estado=ESPERANDO_OP2;
	    	accion.calcula(valorActual,tipo);
	    	accion.actualiza(""+entrada);
	    	break;
	    case IGUAL:
	    	estado = RESULTADO;
	    	accion.calcula(valorActual,tipo);
	    	accion.actualiza(""+entrada);
	    case MAS_MENOS :
	    	accion.actualizaCambioSigno(valorActual);
	    	break;
	    case RETROCESO :
	    	int pos = valorActual.length();
	    	accion.actualiza(valorActual.substring(0,pos-1));
	    	if (valorActual.charAt(pos-1)=='.')
	    		if (valorActual.charAt(pos-2)=='0'){
	    			estado=ESPERANDO_OP2;
	    			accion.actualiza(valorActual.substring(0,pos-2));
	    		}
	    		else
	    			estado = OP2;
	    	break;
	}
	return estado;
}
private int esperandoDenOp2(Character entrada, String valorActual, AccionCalculadora accion){
	   int estado = this.estado;	
		switch (tipoEntrada(entrada)){
 
	    	case NUMERO :
	    		estado = DEN_OP2;
	    		accion.actualiza(valorActual+entrada);
	    		break;
	    	case MAS_MENOS :
	    		accion.cambiarSignoOp2(valorActual,tipo);
	        	break;
	    	case IGUAL:
	    		if (valorActual.contains("("))
	    			valorActual=valorActual.substring(0,valorActual.length()-2)+"1)";
	    		else
	    			valorActual=valorActual+"1";
	    		accion.calcula(valorActual, tipo);
	    		estado = RESULTADO;
	    		break;
	    	case OPERADOR_RACIONAL:
	    		if (valorActual.contains("("))
	    			valorActual=valorActual.substring(0,valorActual.length()-2)+"1)";
	    		else
	    			valorActual=valorActual+"1";
	    		accion.calcula(valorActual, tipo);
	    		accion.addResultado(entrada);
	    		estado=ESPERANDO_OP2;
	    		break;
	    	case RETROCESO ://MRM Me quede aquí
	    		//  1 a/b op c/   ==> a/b op c    OP2
	    		//  2 a/b op 0/   ==> a/b op       ESPERANDO_OP2
	    		//  3 a/b op (-c/)   ==> a/b op (-c)    OP2
	    		//  4 a/b op (-0/)   ==> a/b op       ESPERANDO_OP2
 
	 	    		int c = accion.caracteresOp2(valorActual,tipo);
	        	if (c==1)
	        	   estado = ESPERANDO_OP2;
	         	else 
	         		estado = OP2;
	        	accion.quitarCaracterOp2(valorActual);
	       		break;
		}//End case
	return estado;
}
private int denOp2(Character entrada, String valorActual, AccionCalculadora accion){
	   int estado = this.estado;	
 
		switch (tipoEntrada(entrada)){
 
	    	case NUMERO :	    	
	    		accion.actualizarConPosibleParentesis(valorActual,""+entrada);
	    		break;
	    	case OPERADOR_RACIONAL :
	    		estado=ESPERANDO_OP2;
		    	accion.calcula(valorActual,tipo);
		    	accion.actualiza(""+entrada);
		    	break;
	    	case IGUAL:
	    		estado=RESULTADO;
		    	accion.calcula(valorActual,tipo);
		    	break;
	    	case MAS_MENOS :
	    		accion.actualizaCambioSigno(valorActual);
	        	break;
	    	case RETROCESO :    // 1 a/b op c/d ==> a/b op c/  ESPERANDO_DEN_OP2
	    				  	    // 2 a/b op c/de ==> a/b op c/d DEN OP2
	    						// 3 a/b op -(c/d) ==> a/b op -(c/)  ESPERANDO_DEN_OP2
				  				// 4 a/b op -(c/de) ==> a/b op -(c/d) DEN_OP2
	    	 	int c = accion.caracteresOp2(valorActual,tipo);
	        	if (c==0)
	        	   estado = ESPERANDO_OP2;
	         	else 
	         		estado = OP2;
	        	accion.actulizaRetrocesoConPosibleParentesis(valorActual);
		}
	return estado;
}
private int resultado(Character entrada, String valorActual, AccionCalculadora accion){
	   int estado = this.estado;	
			switch (tipoEntrada(entrada)){
 
		    	case NUMERO :
		    		estado=OP1;
		    		accion.actualiza(""+entrada);
		    		break;
		    	case OPERADOR_RACIONAL :
		    	case OPERADOR_REAL :
		    		estado=ESPERANDO_OP2;
		    		accion.addResultado(entrada);
		    		break;
		    	case MAS_MENOS :
		    		estado = OP1;
		    		accion.cambiaSignoResultado();
		    		break;
 
		    	case CLEAR :
			}
	   	return estado;
}
public void inicializa(AccionCalculadora accion){
	estado=INICIAL;
	accion.actualiza("");
}
 public int getEstado(){
	  return estado;
}
 
private String getEstado(int estado){
 
	switch (estado){
	case INICIAL:
	      return "INICIAL";
	case  OP1 :
		return "OPERANDO 1";
	case  OP1_DECIMAL:
		return "OP1_DECIMAL";
    case ESPERANDO_OP2 :
    	return "ESPERANDO_OP2";
	case  OP2 :
		return "OP2";
	case  OP2_DECIMAL :
		return "OP2_DECIMAL";
	case  RESULTADO :
		return "RSULTADO";
	case ESPERANDO_DEN_OP1:
		return "ESPERANDO_DEN_OP1";
	case ESPERANDO_DEN_OP2:
		return "ESPERANDO_DEN_OP2";
	case DEN_OP1:
		return "DEN_OP1";
	case DEN_OP2:
		return "DEN_OP2";
 
 
	default:
		return("SIN ESTADO!!!!");
	}
}
/**
 * Me verifica si un número es negativo
 * Paso solamente el número a verificar como un string
 * @return true si el número es negativo falso en otro caso
 */
 
}//eND CLASE