Programació II
Pràctica 2

Pau Santesmasses
Octubre 2005
GMMD | UOC

Codi


/*PER VEURE EL MONITOR D'ACIVITAT CAL BORRAR EL SELECTOR #DEBUG DEL FULL D'ESTIL*/


//inicialitzem les variables


a = ""               //el primer nombre de la operacio
operador=""          //l'operador
b = ""               //el nombre de la dreta de l'operador
reserva=""           //aqui hi guardarem les sumes i restes mentre 
                     //fem els productes i divisions
resultat=""          //el resultat

operacioFinalitzada=false  //aquesta booleana ens permet determinar si
                           //cal reiniciar l'entrada de l'usuari o 
                           //concatenar-la amb l'existent
aEsDecimal=false           //booleanes que indiquen si l'entrada es decimal
bEsDecimal=false
rad=false                  //booleanes que indiquen si el resultat de les
deg=true                   //operacions trigonomètriques es en graus o radians

E=0                        //per si de cas...



//actualitza la pantalla
function actualitzaPantalla(valor){
   document.getElementById("pantalla").value = valor;
}

//actualitza la pantalla del mode trigonometric
function actualitzaMode(valor){
   document.getElementById("mode").value = valor;
   document.getElementById("deg").className=""
   document.getElementById("rad").className=""
   document.getElementById(valor).className="actiu"

}

//reinicia algunes variables, es fa servir 
//quan la operacio finalitza
function reinicia(){
   a=""
   reserva=""
   operador=""
   b=""
   resultat=""
   operacioFinalitzada=false
   aEsDecimal=false
   bEsDecimal=false
   actualitzaPantalla(0)
}

//monitor d'activitat
function debug(){
   document.forms[0].a.value=a
   document.forms[0].reserva.value=reserva
   document.forms[0].operador.value=operador
   document.forms[0].b.value=b
   document.forms[0].resultat.value=resultat
}

//registra l'entrada de l'usuari
function apreta(entrada){

   switch (entrada){
      //la coma (al menys aquí, a washington)
      case ".":                              
         //si no hi ha operador previ i la operacio
         //esta finalitzada, la coma indica 0.
         //actualitzem la pantalla
         //activem la booleana que indica que a es decimal
         //a partir d'ara la tecla coma ja no te efecte.
         if(!operador && operacioFinalitzada){
               a = "0."
               actualitzaPantalla(a)
               aEsDecimal=true
               operacioFinalitzada=false
         //si no tenim operador i la operacio no esta finalitzada,
         //vol dir que l'usuari esta entrant el primer nombre.
         //Amb l'operador ternari '?'
         //si 'a' encara no te valor: 0.
         //si a te valor: a.
         }else if(!operador && !operacioFinalitzada){
            if (!aEsDecimal){
               a=(a=="")? "0." : a + "."
               actualitzaPantalla(a)
               aEsDecimal=true
               }
         //si l'operador existeix, hem de modificar el segon nombre.
         //Amb l'operador ternari '?'
         //si 'b' no existeix: b es 0.
         //en cas de que b ja existeixi: b es b.
         }else if(operador){
            if (!bEsDecimal){
               b=(b=="")? "0." : b + "."
               actualitzaPantalla(b)
               bEsDecimal=true
            }
         }
         break;
         '
      //El 'clear'   
      case "C":                     //reinicia la calculadora
         reinicia();
         break;
         
      //Els nombres  
      case "0":                     //introduim els nombres.
      case "1":                     //Si no detectem un operador:
      case "2":                     //sila operacio previa ha acabat 
      case "3":                     //assignem el nombre a 'a';
      case "4":                     //si pel contrari la operacio previa 
      case "5":                     //ja ha acabat, afegim l'entrada a 
      case "6":                     //el valor existent de 'a'
      case "7":                     //Si detectem un operador:
      case "8":                     //assignem el valor a b.
      case "9":
         if(!operador && operacioFinalitzada){
            aEsDecimal=false
            a=entrada   
            actualitzaPantalla(a)
            operacioFinalitzada=false
         }else if (!operador && !operacioFinalitzada){
            a += entrada
            actualitzaPantalla(a)
         }else if(operador){
            b += entrada
            actualitzaPantalla(b)
         }
         break;
         
      //El canvi de signe  
      case "+-":        //Canvi de signe a o b segons hi hagi operador o no
         if(!operador){
               a = -a
               actualitzaPantalla(a)         
         }else if(operador){
               b = -b
               actualitzaPantalla(b)
         }
         break;
         
      //Suma i resta
      
      case "+":
      case "-":
         //si trobem una suma o resta en curs, la resolem,
         //assignem el resultat a 'a' i assignem el nou operador
         if (a && operador==("+"||"-") && b){
            resultat = eval(a + operador + b)
            actualitzaPantalla(resultat)
            a=resultat
            b=""
            bEsDecimal=false
            operador = entrada
            
         //si trobem una operacio guardadea en un reserva i l'operador
         //es el producte o la divisió, actualitzem la reserva amb el nou        
         //operador i reiniciem 'b' (aixo ens grantira la 
         //correcta precedencia d'operadors)
         //assignem el nou operador
         } else if (reserva && operador==("*"||"http://cv.uoc.edu/~psantesmasses/")){
            reserva=reserva + operador + b 
            b=""
            bEsDecimal=false
            operador = entrada
            
         //si no hi ha reserva pero l'operador anterior era un producte o 
         //divisio, guardem la operacio anterior a la reserva i reiniciem 'b'
         //assignem el nou operador
         } else if (operador==("*"||"http://cv.uoc.edu/~psantesmasses/")){
            reserva=a + operador + b 
            b=""
            bEsDecimal=false
            operador = entrada
            
         //Si no hi cap operacio en curs, nomes cal que  
         //assignem el nou operador
         } else 
         operador = entrada
         break;
         
         //producte i divisio
      case "*":
      case "http://cv.uoc.edu/~psantesmasses/":
         
         //si trobem un reserva, l'actualitzem
         //assignem el nou operador
         if(reserva && operador && b){
            reserva=reserva + operador + b 
            b=""
            bEsDecimal=false
            operador=entrada
         }
         //si trobem una multiplicació o divisió en curs,
         //la resolem, passem el resulta a 'a'
         //assignem el nou operador
         
         //si en canvi trobem una suma o resta, l'hem de gurdar a la reserva
         //per poderla efectuar posteriorment
         
         //assignem el nou operador i reiniciem el valor de 'b'
         if (a && operador && b){
            if (operador=="*" || operador=="http://cv.uoc.edu/~psantesmasses/"){
               resultat = eval(a + operador + b)
               actualitzaPantalla(resultat)
               a=resultat
               b=""
               bEsDecimal=false
               operador = entrada
            }else if (operador=="+" || operador=="-"){
               reserva=a + operador + b 
               b=""
               bEsDecimal=false
               operador = entrada
            }
         //si no hi ha operacio, assignem al nou operador
         } else{
            operador = entrada
         }
         break;
         
      //Potencia

      case "^":
               
         //si detectem una operacio en curs, passem el valor de 'b' a 'a'
         //per volem que 'b' sigui la base de la potencia i hem de guardar
         //'a' i l'operador en unes variables de reserva. L'exponent el 
         //recollirem a la propera entrada.
         
         
         /*13/11/05 He trobat bugs a les cadenes de operacions que inclouen      
         una potencia. Just abans de l'entrega... */
         if (a && operador && b){
         
               reserva=a
               preoperador=operador
               a=b
               b=""
               bEsDecimal=false
               operador = entrada
         //i si no nomes cal que... assignem el nou operador
         } else {
            operador=entrada
         }
         break;
         
      // l'igual
      case "=":
         //si l'operador es la potencia:
         if (operador=='^'){        
            
            //si tenim reserva
            //resolem la potencia i hi afegim la reserva
            //actualitzem la pantalla i assignem el resultat a 'a'
            
            if (reserva){
               potencia=Math.pow(a,b)  
               resultat =eval(reserva + potencia)
               actualitzaPantalla(resultat)
               a=resultat
               reserva=""
               operador=""
               b=""
               bEsDecimal=false
               operacioFinalitzada=true
            
            //si no hi reserva, resolem la potencia,
            //actualitzem la pantalla i assignem el resultat a 'a'
            }else{
               resultat = Math.pow(a, b);
               actualitzaPantalla(resultat)
               a=resultat
               operador=""
               operacioFinalitzada=true
               b=""
               bEsDecimal=false
            }
         }
         //sitenim una cadena d'operacions guardada en reserva
         //la resolem junt amb la ultima operació
         //actualitzem la pantalla i assignem el resultat a 'a'
         if(reserva && b){
            resultat=eval(reserva + operador + b)
            actualitzaPantalla(resultat)
            a=resultat
            operador=""
            operacioFinalitzada=true
            reserva=""
            b=""
            bEsDecimal=false
         //si tenim reserva pero no tenim 'b'
         //ignorem l'operador i resolem la reserva
         }else if(reserva){
            resultat=eval(reserva)
            actualitzaPantalla(resultat)
            a=resultat
            operador=""
            operacioFinalitzada=true
            reserva=""
            b=""
            bEsDecimal=false  
         //si en comptes de reserva tenim a,operador i b
         //resolem la operacio
         }else if (a && operador && b){
            resultat = eval(a + operador + b)
            actualitzaPantalla(resultat)
            a=resultat
            operador=""
            operacioFinalitzada=true
            b=""
            bEsDecimal=false
         }
         break;
      
      //el percentatge
      case "%":
         //necessitem una operació previa...
         if (a && operador && b){
            //si l'operacio es una suma o una resta calcularem
            //calculareem el percentatge i els umarem o restarem 
            //al nombre inicial
            if (operador=="+" || operador=="-") resultat = eval(a + operador +(a*b/100))
            //fent servir l'operador ternari com a condicional,
            //si l'operacio es un producte, dividim percent el resultat 
            //d'aquest, obtenint el 'b' per cent de 'a'
            //si fos una divisio, multipliquem el resulta per 100,
            //lo qual ens dona la fraccio a/b en forma de tant per cent
            else resultat=(operador=="*")? eval(a + operador + b)/100 : eval(a + operador + b)*100
            actualitzaPantalla(resultat)
            a=resultat
            operador=""
            operacioFinalitzada=true
            b=""
            bEsDecimal=false
         }
         break;   
      
      //les funcions trigonomètriques son predefinides.
      //Els resultat son en radians per defecte amb la qual cosa 
      //si els volem en graus els haurem de convertir multiplicant per PI i   
      //dividint per 180 o a l'inrev´s
      //En cas de error, per exemple l'arcsinus de un n > 1, mostrarem la 
      //classica E
      case "sin":
      case "cos":
      case "tan":
         metode = eval("Math."+entrada)
         if (rad){
            resultat = metode(a)
            resultat=(isNaN(resultat))? "E" : resultat
            actualitzaPantalla(resultat)
          }else if (deg){
            a = a * Math.PI / 180
            resultat = metode(a) 
            resultat=(isNaN(resultat))? "E" : resultat
            actualitzaPantalla(resultat)
          }  
         a=(resultat=="E")? "" : resultat
         operacioFinalitzada=true
         break;
      
      case "asin":
      case "acos":
      case "atan":
         metode = eval("Math."+entrada)
         if (rad){
            resultat = metode(a)
            resultat=(isNaN(resultat))? "E" : resultat
            actualitzaPantalla(resultat)
          }else if (deg){
            
            resultat = metode(a) *  180 / Math.PI
            resultat=(isNaN(resultat))? "E" : resultat
            actualitzaPantalla(resultat)
          }  
         a=(resultat=="E")? "" : resultat
         operacioFinalitzada=true
         break;
      //altres metodes de l'objecte math:
      //simplement apliquem el metode al valor de 'a'
      case "abs": 
      case "sqrt":
      case "log":
      case "round":  
      case "floor":
      case "ceil":
         metode = eval("Math."+entrada)
         resultat = metode(a)
         resultat=(isNaN(resultat))? "E" : resultat
         a=resultat
          actualitzaPantalla(resultat)
            operacioFinalitzada=true
            break;
      //botons deg i rad:
      //activem les booleanas tal i com convingui
      // i acutlitzem la pantalla del mode
      case "deg":
         deg=true
         rad=false
         actualitzaMode(entrada)
         break;
      case "rad":
         deg=false
         rad=true
         actualitzaMode(entrada)
         break;
      
   }
   
   debug() //enviar dades al monitor d'activitat
}