/***********************************************************************************\
*
*    Mòdul Generador Bewoom del projecte Col·lectiva 2.0
* 
*    Copyright (C) Gerard Romo Garrido (www.toomates.net)
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
************************************************************************************/

DiccionariBewoom_Cat=[
"",
"Nombres",
"Tipus de nombre",
"Enter",
"Fracci&oacute;",
"Decimal",
"Valors negatius",
"Evitar els zeros",
"Valor m&agrave;xim",
"Valor m&agrave;xim dels numeradors",
"Valor m&agrave;xim dels denominadors",
"Limitar la factoritzaci&oacute; dels denominadors",
"Nombre primer m&agrave;xim",
"Si",
"No",
"Nombre de xifres decimals",
"Resultats parcials",
"Resultat final",
"Igual que els nombres",
"Igual que els resultats parcials",
"Espec&iacute;fiques",
"Evitar...",
"Sumes o restes de fraccions amb el mateix denominador",
"Sumes o restes de fraccions sense mcm",
"Divisions entre s&iacute; mateix A/A",
"Operacions cancel·ladores",
"Escriptura de les f&oacute;rmules matem&agrave;tiques",
"Divisi&oacute; de fraccions en horitzontal",
"S&iacute;mbol de la divisi&oacute; en horitzontal",
"Barra (/)",
"Barra i dos punts (&divide;)",
"S&iacute;mbol de la multiplicaci&oacute;",
"Aspes (&times;)",
"Punt (·)",
"Asterisc (*)",
"Nombre de xifres decimals a visualitzar",
"Pauta fixa o aleat&ograve;ria?",
"Pauta fixa",
"Pauta aleat&ograve;ria",
"Exemple",
"Nombre d&#39;operacions",
"sumes",
"restes",
"multiplicacions",
"divisions",
"pot&egrave;ncies",
"arrels",
"E.D.O.",
"Obligatori",
"Mode",
"Pauta",
"Realitza les seg&uuml;ents operacions",
"Operacions"
];

DiccionariBewoom_Cas=[
"",
"N&uacute;meros",
"Tipo de n&uacute;mero",
"Entero",
"Fracci&oacute;n",
"Decimal",
"Valores negativos",
"Evitar los ceros",
"Valor m&aacute;ximo",
"Valor m&aacute;ximo de los numeradores",
"Valor m&aacute;ximo de los denominadores",
"Limitar la factorizaci&oacute;n de los denominadores",
"N&uacute;mero primo m&agrave;ximo",
"Si",
"No",
"N&uacute;mero de cifras decimales",
"Resultados parciales",
"Resultado final",
"Igual que los n&uacute;meros",
"Igual que los resultados parciales",
"Espec&iacute;ficas",
"Evitar...",
"Sumas o restas de fracciones con el mismo denominador",
"Sumas o restas de fracciones sin mcm",
"Divisiones entre s&iacute; mismo A/A",
"Operaciones canceladoras",
"Escritura de las f&oacute;rmulas matem&aacute;ticas",
"Divisi&oacute;n de fracciones en horizontal",
"S&iacute;mbolo de la divisi&oacute;n en horizontal",
"Barra (/)",
"Barra y dos puntos (&divide;)",
"S&iacute;mbolo de la multiplicaci&oacute;n",
"Aspas (&times;)",
"Punto (·)",
"Asterisco (*)",
"N&uacute;mero de cifras decimales a visualizar",
"¿Pauta fija o aleatoria?",
"Pauta fija",
"Pauta aleatoria",
"Ejemplo",
"N&uacute;mero de operaciones",
"sumas",
"restas",
"multiplicaciones",
"divisiones",
"potencias",
"ra&iacute;ces",
"E.D.O.",
"Obligatorio",
"Modo",
"Pauta",
"Realiza las siguientes operaciones",
"Operaciones"
];

DiccionariBewoom_Ita=[
"",
"Numeri",
"Tipo di numero",
"Intero",
"Frazzione",
"Decimale",
"Valori Negativi",
"Evitare gli zeri",
"Valore massimo",
"Valore massimo dei numeratori",
"Valore massimo dei denominatori",
"Limitare la fattorizzazione dei denominatori",
"Numero primo massimo",
"Si",
"No",
"Numero di cifre decimale",
"Risultati parziali",
"Risultato finale",
"Uguale ai numeri",
"Uguale ai risultati parziali",
"Specifiche",
"Evitare...",
"Somme o sottrazioni di frazioni con lo stesso denominatore",
"Somme o sottrazioni di frazioni senza mcm",
"Divisioni di un numero per s&egrave; stesso A/A",
"Semplificazioni",
"Scrittura delle formule matematique",
"Divisione di frazioni in orizzontale",
"Simbolo della divisione in orizzontale",
"Barra (/)",
"Barra e due punti (&divide;)",
"Simbolo della moltiplicazione",
"Croce (&times;)",
"Punto (·)",
"Asterisco (*)",
"Numero di cifre decimali a visualizare",
"Schema fisso o aleatorio?",
"Schema fisso",
"Schema aleatorio",
"Esempio",
"Numero di operazioni",
"somme",
"sottrazioni",
"moltiplicazioni",
"divisioni",
"potenze",
"radici",
"E.D.O.",
"Obligatorio",
"Mode",
"Schema",
"Effettuare le seguenti operazioni aritmetique",
"Operazione"
];


/***********************************************************************************

Interface del generador:

	- Constructor(CodiGenerador)

		El CodiGenerador és un string que conté tota la informació que defineix el
		tipus d'exercici que es vol crear.

	- IniciGenesis()  

		S'executa una única vegada al principi per a posar el generador preparat
		per a treballar.

		Crida a Inici() per a qualsevol hereu de Bewoom
	
		Retorna Status
	
	- ResetGenesis() 

		S'executa cada vegada que cal tornar a començar la generació d'un exercici
		de nou.

		Crida a Reset() per a qualsevol hereu de Bewoom

		Retorna Status

	- Generar(TipusLlenguatge) 

		És la funció principal. Intenta generar un exercici. 

		Retorna Status

		Si ho aconsegueix retorna 1 i les variables següents:

			Enunciat (String) 

				Cadena HTML amb l'enunciat de l'exercici, amb la codificació
				TipusLlenguatge

			SolucioHTML (String)

				Cadena HTML amb la solució que ha d'aparèixer un cop s'ha corregit

			Pauta (string)
			
				La pauta associada a aquest exercici

			Solucio (String)

				La solució codificada en ASCII per a que pugui ser interpretada per
				Kiwis. (Separada per comes si és múltiple)

			InfoExtra (String)

				Informació extra per a l'exercici.
				

- Configuració general del generador:
	
	TipusResposta (String)
		Alguns generador d'exercicis poden obligar a fer servir un tipus determinat
		de resposta. Si no és "" indica el tipus de resposta que cal fer servir.

	LlenguatgeSortida (Enter)
		Tipus de codificació per a les expressions
			LLENGUATGE_MATEMATIC_ASCII = 0
			LLENGUATGE_MATEMATIC_OPEN_OFFICE = 1
			LLENGUATGE_MATEMATIC_MSWORD = 2
			LLENGUATGE_MATEMATIC_TEX_MOODLE = 3
			LLENGUATGE_MATEMATIC_MATHML = 4


- Funcions Complementàries

	- NombreOperacions() 
		Retorna el nombre d'operacions de l'exercici.
		Serveix per a mesurar la seva dificultat.


************************************************************************************/



// Status

// 	< 0 --> 	Error greu
// 	= 0 --> 	STATUS_NO_FET Valor inicial 
// 	= 1 --> 	STATUS_FET_OK Resultat fet i acceptable
// 	> 1 --> 	Resultat no fet o no acceptable però es pot mirar d'arreglar-lo
// 			o continuar insistint.


// 	Llista d'errors greus:

// 		Llista --> Carregar Llista
// 		-1 --> Error carregant la llista 
	
//		INPUT
//		-5  --> Valor numèric no acceptable
// 		-7  --> Expressió literal no acceptable
//		-11 --> Entrada buida
//		-9  --> Més d'un "=" al text d'entrada
//		-8  --> S'esperava un operand
// 		-4  --> S'esperava una operació binària
// 		-6  --> Error en el recompte de parèntesis
//		-2  --> Més d'una coma decimal al mateix nombre

	var STATUS_NO_FET = 0;	// Status inicial

	var STATUS_FET_OK = 1;	// Resultat fet i acceptable

	var STATUS_FET_NO_OK = 3; // S'ha realitzat la construcció però no és acceptable

	// Nombre aleatori:

	var STATUS_ALEATORI_NO_VALID_GENERAL = 19;
		// S'ha generat el nombre aleatori general però no passa el test
		// de nombre vàlid
	var STATUS_ALEATORI_NO_VALID_ESPECIAL= 20;
		// S'ha generat el nombre aleatori especial però no passa el test
		// de nombre vàlid
	var STATUS_ALEATORI_IMPOSSIBLE=21;
		// Es demana generar un nombre aleatori impossible, per exemple
		// un divisor d'un nombre primer

	// Complement (rutina Completar() )
	// Totes les de Nombre aleatori més:

	var STATUS_INCOMP_D = 8;
	var STATUS_INCOMP_E = 9;
	var STATUS_INCOMP_R = 10;
	var STATUS_INCOMP_DE = 11;
	var STATUS_INCOMP_DR = 12;
	var STATUS_INCOMP_ER = 13;
	var STATUS_INCOMP_DER = 14;
	var STATUS_NO_VALID_D = 15;
	var STATUS_NO_VALID_E = 16;
	var STATUS_NO_VALID_R = 17;
	var STATUS_NO_VALID_NODE = 18;

	// GestionarNode()	
	// Totes les de Complement més:

	var STATUS_INCOMP_VALOR_FIX_PREVI = 5; 
	var STATUS_INCOMP_VALOR_FIX_INICIAL = 7;
		// Alguns valors INCOMP_X poden passar a aquests

	// CompletarStep()

	// Retorna STATUS_INCOMP_VALOR_FIX_PREVI,STATUS_INCOMP_VALOR_FIX_INICIAL i també

	var STATUS_TIME_OUT_STEP = 4;


	// GenesisStep() 

	// Retorna les de CompletarStep(), però si la pauta és aleatòria els status
	// STATUS_INCOMP_VALOR_FIX_PREVI,STATUS_INCOMP_VALOR_FIX_INICIAL es gestionen 
	// internament.

	// Bewoom  ( GenerarStep() )
	// Retorna STATUS_FET_OK, STATUS_TIME_OUT_STEP, o també

	var STATUS_CONDICIONS_INCOMPATIBLES = 2;

	// Llista
	// Retorna les de Bewoom més 

	var STATUS_BREAK = 22;

	// Activitat
	// Les mateixes que Llista

	// Principal
	// Qualsevol cosa que no sigui STATUS_FET_OK (=1) es considera error.


/***********************************************************************************\
*
* GENERADORBEWOOM --> CONSTRUCTOR I VARIABLES
*
************************************************************************************/

function Bewoom() {
	this.CodiBewoomInicial="A686868GKCGG2686868GKCGG2686868GKCGG0A0C6868S53066R0M8CGP1I00001";
	this.CodiBewoomActual="";
	AutoomatesGen.call(this);
	//
	// Configuració
	//
	//
	// 1 --> Nombres
	//
	this.Items[1]=new CondicionsNumeriques("MyGenerador.Items[1].","BEWOOM1");
	//
	// 2 --> Resultats parcials
	//	
	this.Items[2]=new Formulari("MyGenerador.Items[2].","BEWOOM16");
	this.Items[2].Items[1]=new EntradaSelector("MyGenerador.Items[2].Items[1].","BEWOOM16");
	this.Items[2].Items[1].AfegirNomOpcio("BEWOOM18");							// 0 --> Igual que nombres
	this.Items[2].Items[1].AfegirNomOpcio("BEWOOM20");							// 1 --> Condicions específiques
	this.Items[2].Items[1].Items[1]=new CondicionsNumeriques("MyGenerador.Items[2].Items[1].Items[1].",0);
	//
	// 3 --> Resultat final
	//	
	this.Items[3]=new Formulari("MyGenerador.Items[2].","BEWOOM17");
	this.Items[3].Items[1]=new EntradaSelector("MyGenerador.Items[3].Items[1].","BEWOOM16");
	this.Items[3].Items[1].AfegirNomOpcio("BEWOOM19");							// 0 --> Igual que nombres
	this.Items[3].Items[1].AfegirNomOpcio("BEWOOM20");							// 1 --> Condicions específiques
	this.Items[3].Items[1].Items[1]=new CondicionsNumeriques("MyGenerador.Items[3].Items[1].Items[1].",0);
	//
	// 4 --> Exponents
	//	
	this.Items[4]=new CondicionsNumeriques("MyGenerador.Items[4].",0);
	this.Items[4].Invisible=true;
	//
	// 5 --> Evitar
	//	
	this.Items[5]=new Formulari("MyGenerador.Items[5].","BEWOOM21");				// Evitar...
	this.Items[5].Items[1]=new EntradaTrueFalse("MyGenerador.Items[5].Items[1].","BEWOOM22");	// ...sumes/restes amb el mateix denominador
	this.Items[5].Items[1].Valor=1;
	this.Items[5].Items[2]=new EntradaTrueFalse("MyGenerador.Items[5].Items[2].","BEWOOM23"); 	// ...sumes/restes fraccions sense mcm
	this.Items[5].Items[2].Valor=1;
	this.Items[5].Items[3]=new EntradaTrueFalse("MyGenerador.Items[5].Items[3].","BEWOOM24"); 	// ...Divisions entre sí mateix
	this.Items[5].Items[3].Valor=1;	
	this.Items[5].Items[4]=new EntradaTrueFalse("MyGenerador.Items[5].Items[4].","BEWOOM25"); 	// ...Operacions cancel·ladores
	this.Items[5].Items[4].Valor=1;	
	//
	// 6 --> Output
	//
	this.Items[6]=new Formulari("MyGenerador.Items[6].","BEWOOM26");				// "Escriptura de les fórmules matemàtiques"
	this.Items[6].Items[1]=new EntradaTrueFalse("MyGenerador.Items[6].Items[1].","BEWOOM27");	// "Divisió de fraccions en horitzontal"
	this.Items[6].Items[1].Valor=0;	// Per defecte és en vertical
	this.Items[6].Items[2]=new EntradaSelector("MyGenerador.Items[6].Items[2].","BEWOOM28");	// Text divisions en horitzontal
	this.Items[6].Items[2].Valor=1;
	this.Items[6].Items[2].AfegirNomOpcio(0);							// (buit, comença en 1)
	this.Items[6].Items[2].AfegirNomOpcio("BEWOOM29");						// barra
	this.Items[6].Items[2].AfegirNomOpcio("BEWOOM30");						// barra i dos puntets
	this.Items[6].Items[3]=new EntradaSelector("MyGenerador.Items[6].Items[3].","BEWOOM31");	// Text multiplicació
	this.Items[6].Items[3].Valor=1; // Per defecte és un punt
	this.Items[6].Items[3].AfegirNomOpcio(0);							// (buit, comença en 1)
	this.Items[6].Items[3].AfegirNomOpcio("BEWOOM33");						// punt (cdot)
	this.Items[6].Items[3].AfegirNomOpcio("BEWOOM32");						// Creu (ctimes)
	this.Items[6].Items[3].AfegirNomOpcio("BEWOOM34");						// Asterisc
	this.Items[6].Items[4]=new EntradaEnter("MyGenerador.Items[6].Items[4].","BEWOOM35");		// "Nombre decimals a visualitzar"
	this.Items[6].Items[4].Valor=2;
	//
	// 7 --> Construcció
	//
	this.Items[7]=new Formulari("MyGenerador.Items[7].","BEWOOM50");					// Pauta
	this.Items[7].Items[1]=new EntradaSelector("MyGenerador.Items[7].Items[1].","BEWOOM36");		// Pauta fixa o aleatòria?
	this.Items[7].Items[1].Valor=1;
	this.Items[7].Items[1].AfegirNomOpcio("BEWOOM37");							// 7.0 Fixa
	this.Items[7].Items[1].Items[0]=new EntradaText("MyGenerador.Items[7].Items[1].Items[0].","BEWOOM39");	// Exemple
	this.Items[7].Items[1].Items[0].Valor="";
	this.Items[7].Items[1].AfegirNomOpcio("BEWOOM38");							// 7.1 Aleatòria
	this.Items[7].Items[1].Items[1]=new Formulari("MyGenerador.Items[7].Items[1].Items[1].",0);	
	this.Items[7].Items[1].Items[1].Items[0]=new EntradaEnter("MyGenerador.Items[7].Items[1].Items[1].Items[0].","BEWOOM40");	// 7.1.0 Nombre d'operacions
	this.Items[7].Items[1].Items[1].Items[0].ValorMinim=1;
	this.Items[7].Items[1].Items[1].Items[0].Valor=1;
	//
	// 7 --> Construcció --> Sumes
	//
	this.Items[7].Items[1].Items[1].Items[1]=new EntradaEnter("MyGenerador.Items[7].Items[1].Items[1].Items[1].","BEWOOM41");	// 7.1.1 Percentatge de sumes
	this.Items[7].Items[1].Items[1].Items[1].ValorMinim=0;
	this.Items[7].Items[1].Items[1].Items[1].ValorMaxim=100;
	this.Items[7].Items[1].Items[1].Items[1].Valor=25;
	this.Items[7].Items[1].Items[1].Items[1].AfegirSaltLinia=false;
	this.Items[7].Items[1].Items[1].Items[2]=new EntradaTrueFalse("MyGenerador.Items[7].Items[1].Items[1].Items[2].","BEWOOM48");	// 7.1.2 Obligatori
	this.Items[7].Items[1].Items[1].Items[2].Valor=0;
	this.Items[7].Items[1].Items[1].Items[2].AfegirSaltLinia=false;
	this.Items[7].Items[1].Items[1].Items[3]=new EntradaTrueFalse("MyGenerador.Items[7].Items[1].Items[1].Items[3].","BEWOOM47");	// 7.1.3 Evitar dobles operacions
	this.Items[7].Items[1].Items[1].Items[3].Valor=0;
	//
	// 7 --> Construcció --> Restes
	//
	this.Items[7].Items[1].Items[1].Items[4]=new EntradaEnter("MyGenerador.Items[7].Items[1].Items[1].Items[4].","BEWOOM42");	// 7.1.4 Percentatge de restes
	this.Items[7].Items[1].Items[1].Items[4].ValorMinim=0;
	this.Items[7].Items[1].Items[1].Items[4].ValorMaxim=100;
	this.Items[7].Items[1].Items[1].Items[4].Valor=25;
	this.Items[7].Items[1].Items[1].Items[4].AfegirSaltLinia=false;
	this.Items[7].Items[1].Items[1].Items[5]=new EntradaTrueFalse("MyGenerador.Items[7].Items[1].Items[1].Items[5].","BEWOOM48");	// 7.1.5 Obligatori
	this.Items[7].Items[1].Items[1].Items[5].Valor=0;
	this.Items[7].Items[1].Items[1].Items[5].AfegirSaltLinia=false;
	this.Items[7].Items[1].Items[1].Items[6]=new EntradaTrueFalse("MyGenerador.Items[7].Items[1].Items[1].Items[6].","BEWOOM47");	// 7.1.6 Evitar dobles operacions
	this.Items[7].Items[1].Items[1].Items[6].Valor=0;
	//
	// 7 --> Construcció --> Multiplicacions
	//
	this.Items[7].Items[1].Items[1].Items[7]=new EntradaEnter("MyGenerador.Items[7].Items[1].Items[1].Items[7].","BEWOOM43");	// 7.1.7 Percentatge de multiplicacions
	this.Items[7].Items[1].Items[1].Items[7].ValorMinim=0;
	this.Items[7].Items[1].Items[1].Items[7].ValorMaxim=100;
	this.Items[7].Items[1].Items[1].Items[7].Valor=25;
	this.Items[7].Items[1].Items[1].Items[7].AfegirSaltLinia=false;
	this.Items[7].Items[1].Items[1].Items[8]=new EntradaTrueFalse("MyGenerador.Items[7].Items[1].Items[1].Items[8].","BEWOOM48");	// 7.1.8 Obligatori
	this.Items[7].Items[1].Items[1].Items[8].Valor=0;
	this.Items[7].Items[1].Items[1].Items[8].AfegirSaltLinia=false;
	this.Items[7].Items[1].Items[1].Items[9]=new EntradaTrueFalse("MyGenerador.Items[7].Items[1].Item[1].Items[9].","BEWOOM47");	// 7.1.9 Evitar dobles operacions
	this.Items[7].Items[1].Items[1].Items[9].Valor=0;
	//
	// 7 --> Construcció --> Divisions
	//
	this.Items[7].Items[1].Items[1].Items[10]=new EntradaEnter("MyGenerador.Items[7].Items[1].Items[1].Items[10].","BEWOOM44");	// 7.1.10 Percentatge de divisions
	this.Items[7].Items[1].Items[1].Items[10].ValorMinim=0;
	this.Items[7].Items[1].Items[1].Items[10].ValorMaxim=100;
	this.Items[7].Items[1].Items[1].Items[10].Valor=25;
	this.Items[7].Items[1].Items[1].Items[10].AfegirSaltLinia=false;
	this.Items[7].Items[1].Items[1].Items[11]=new EntradaTrueFalse("MyGenerador.Items[7].Items[1].Items[1].Items[11].","BEWOOM48");	// 7.1.11 Obligatori
	this.Items[7].Items[1].Items[1].Items[11].Valor=0;
	this.Items[7].Items[1].Items[1].Items[11].AfegirSaltLinia=false;
	this.Items[7].Items[1].Items[1].Items[12]=new EntradaTrueFalse("MyGenerador.Items[7].Items[1].Item[1].Items[12].","BEWOOM47");	// 7.1.12 Evitar dobles operacions
	this.Items[7].Items[1].Items[1].Items[12].Valor=0;
	//
	// 7 --> Construcció --> Potències
	//
	this.Items[7].Items[1].Items[1].Items[13]=new EntradaEnter("MyGenerador.Items[7].Items[1].Items[1].Items[13].","BEWOOM45");	// 7.1.13 Percentatge de potències
	this.Items[7].Items[1].Items[1].Items[13].ValorMinim=0;
	this.Items[7].Items[1].Items[1].Items[13].ValorMaxim=100;
	this.Items[7].Items[1].Items[1].Items[13].AfegirSaltLinia=false;
	this.Items[7].Items[1].Items[1].Items[14]=new EntradaTrueFalse("MyGenerador.Items[7].Items[1].Items[1].Items[14].","BEWOOM48");	// 7.1.14 Obligatori
	this.Items[7].Items[1].Items[1].Items[14].Valor=0;
	this.Items[7].Items[1].Items[1].Items[14].AfegirSaltLinia=false;
	this.Items[7].Items[1].Items[1].Items[15]=new EntradaTrueFalse("MyGenerador.Items[7].Items[1].Item[1].Items[15].","BEWOOM47");	// 7.1.15 Evitar dobles operacions
	this.Items[7].Items[1].Items[1].Items[15].Valor=0;
	//
	// 7 --> Construcció --> Arrels
	//
	this.Items[7].Items[1].Items[1].Items[16]=new EntradaEnter("MyGenerador.Items[7].Items[1].Items[1].Items[16].","BEWOOM46");	// 7.1.16 Percentatge de arrels
	this.Items[7].Items[1].Items[1].Items[16].ValorMinim=0;
	this.Items[7].Items[1].Items[1].Items[16].ValorMaxim=100;
	this.Items[7].Items[1].Items[1].Items[16].AfegirSaltLinia=false;
	this.Items[7].Items[1].Items[1].Items[17]=new EntradaTrueFalse("MyGenerador.Items[7].Items[1].Items[1].Items[17].","BEWOOM48");	// 7.1.17 Obligatori
	this.Items[7].Items[1].Items[1].Items[17].Valor=0;
	this.Items[7].Items[1].Items[1].Items[17].AfegirSaltLinia=false;
	this.Items[7].Items[1].Items[1].Items[18]=new EntradaTrueFalse("MyGenerador.Items[7].Items[1].Item[1].Items[18].","BEWOOM47");	// 7.1.18 Evitar dobles operacions
	this.Items[7].Items[1].Items[1].Items[18].Valor=0;

	this.NomDivModal="FORMULARIGEN";

	/////////////////////////////////////////////////////////////////////////////
	//
	// Configuració del generador
	//
	/////////////////////////////////////////////////////////////////////////////
	
	this.TipusResposta="";

	this.LlenguatgeSortida=4;	// MathML

	/////////////////////////////////////////////////////////////////////////////
	//
	// Variables de sortida si s'ha pogut realitzar un exercici vàlid
	//
	/////////////////////////////////////////////////////////////////////////////

	this.Enunciat=""; // Cadena HTML amb l'enunciat de l'exercici, amb la codificació TipusLlenguatge
	this.SolucioHTML=""; // Cadena HTML amb la solució que ha d'aparèixer un cop s'ha corregit
	this.Pauta=""; 	// La pauta associada a aquest exercici
	this.Solucio=""; // La solució codificada en ASCII per a que pugui ser interpretada per Kiwis.
	this.InfoExtra=""; // Alguna informació extra per a l'exercici.

	/////////////////////////////////////////////////////////////////////////////
	//
	// Variables internes.
	//
	/////////////////////////////////////////////////////////////////////////////
	
	this.Arbre = new Arbre(1);

	this.Arbre.Titol="Operacions combinades";	// variable
	this.PautaResposta="___x___";			// fix
	this.FormatResposta="F";			// variable

	this.Arbre.CodiConfBin="";		// Codi binari de la configuració per Codi
						// és l'output de la rutina PassarCodiHexABinari

	this.Arbre.TitolExercicis="";		// Nom dels exercicis que es generaran 

	this.Arbre.NSteps=0;			// comptador de passos de la generació de la llista
	this.Arbre.MaxNSteps=5;			// Nombre de steps abans d'abandonar la generació i 
						// començar una nova construcció
	this.Arbre.ArbreConstruit=false;	// Indica si l'arbre ja té estructura o no.
	this.Arbre.CodiError=0;
	this.Arbre.MaxNCiclesBranca=10;	
	this.Arbre.MaxNCiclesStep=1000;
	this.Arbre.NCiclesStep=0;		// Comptador de cicles de Completar--> Step

	/////////////////////////////////////////////////////////////////////////////
	//
	// RESULTAT FINAL FIX
	//
	/////////////////////////////////////////////////////////////////////////////

	this.Arbre.ResultatFinal=new Nombre();	// Valor final fix si Contingut=true

	this.Arbre.MyComplement=new Complement();

	// Pauta aleatòria	

	this.Arbre.PercentatgeSumarActual=0;
	this.Arbre.PercentatgeRestarActual=0;
	this.Arbre.PercentatgeMultiplicarActual=0;
	this.Arbre.PercentatgeDividirActual=0;
	this.Arbre.PercentatgeElevarActual=0;
	this.Arbre.PercentatgeRadicarActual=0;

	this.Arbre.OperacionsEncadenades=new EntradaTrueFalse("MyGenerador.OperacionsEncadenades.",0);
	this.Arbre.OperacionsEncadenades.Invisible=true;
	this.Arbre.MaxNCiclesBrancaPautaAleatoria=100;

	this.Arbre.NSumesArbre=0;	// Variables de sortida de recompte d'operacions
	this.Arbre.NRestesArbre=0;
	this.Arbre.NMultiplicacionsArbre=0;
	this.Arbre.NDivisionsArbre=0;
	this.Arbre.NPotenciesArbre=0;
	this.Arbre.NArrelsArbre=0;
	this.Arbre.NNombresArbre=0;
}
Bewoom.prototype = new AutoomatesGen();

Bewoom.prototype.InputObjecteJSON= function(ObjecteJSON) {
	if (ObjecteJSON) {
		if(ObjecteJSON.P) this.Items[7].Items[1].Items[0].Input(ObjecteJSON.P);	
		if(ObjecteJSON.C) this.CodiBewoomActual=ObjecteJSON.C;
	}
}	

Bewoom.prototype.OutputJSON= function() {
	var Text="C:{";
	var NouCodiBewoom=this.GenerarCodiBewoom();
	if (NouCodiBewoom!=this.CodiBewoomInicial) {
		Text+='C:"'+NouCodiBewoom+'"';
	}
	var Pauta=this.Items[7].Items[1].Items[0].Valor;
	if (Pauta!="") {
		if (Text!="") Text+=",";
		Text+='P:"'+Pauta+'"';
	}
	Text+="}"
	return(Text);
}	

/************************************************************************************
*
* Bewoom --> Entrada de CodiBewoom
*
************************************************************************************/

Bewoom.prototype.IniciarPerCodiBewoom = function (CadenaCodi) {
	this.IniciarPerCodiNombres(CadenaCodi.substr(0,12));
	this.IniciarPerCodiResultatsParcials(CadenaCodi.substr(12,12));
	this.IniciarPerCodiResultatFinal(CadenaCodi.substr(24,12));
	this.IniciarPerCodiExponents(CadenaCodi.substr(36,12));
	this.IniciarPerCodiEvitar(CadenaCodi.substr(48,1));
	this.IniciarPerCodiOutput(CadenaCodi.substr(49,2));
	this.IniciarPerCodiGeneral(CadenaCodi.substr(51,1));
	this.IniciarPerCodiConstruccio(CadenaCodi.substr(52,12));
}

Bewoom.prototype.IniciarPerCodiNombres = function (CadenaCodi) {
	this.Items[1].IniciarPerCodi(CadenaCodi);	
}

Bewoom.prototype.IniciarPerCodiResultatsParcials = function (CadenaCodi) {
	this.Items[2].Items[1].Items[1].IniciarPerCodi(CadenaCodi);	
}

Bewoom.prototype.IniciarPerCodiResultatFinal = function (CadenaCodi) {
	this.Items[3].Items[1].Items[1].IniciarPerCodi(CadenaCodi);	
}

Bewoom.prototype.IniciarPerCodiExponents = function (CadenaCodi) {
	this.Items[4].IniciarPerCodi(CadenaCodi);	
}

Bewoom.prototype.IniciarPerCodiEvitar = function (CadenaCodi) {
	var CodiBinari=ConvertirBase32ABinari(CadenaCodi);
	this.Items[5].Items[1].CarregarValorDeCadenaBinari(CodiBinari,0);
	this.Items[5].Items[2].CarregarValorDeCadenaBinari(CodiBinari,1);
	this.Items[5].Items[3].CarregarValorDeCadenaBinari(CodiBinari,2);
	this.Items[5].Items[4].CarregarValorDeCadenaBinari(CodiBinari,3);
}

Bewoom.prototype.IniciarPerCodiOutput = function (CadenaCodi) {
	var CodiBinari=ConvertirBase32ABinari(CadenaCodi);
	this.Items[6].Items[3].CarregarValorDeCadenaBinari(CodiBinari,0,3);
	this.Items[6].Items[1].CarregarValorDeCadenaBinari(CodiBinari,3);
	this.Items[6].Items[2].CarregarValorDeCadenaBinari(CodiBinari,4,2);
	this.Items[6].Items[4].CarregarValorDeCadenaBinari(CodiBinari,6,4);
}

Bewoom.prototype.IniciarPerCodiGeneral = function (CadenaCodi) {
	var CodiBinari=ConvertirBase32ABinari(CadenaCodi);
	this.Items[2].Items[1].CarregarValorDeCadenaBinari(CodiBinari,0,1);
	this.Items[3].Items[1].CarregarValorDeCadenaBinari(CodiBinari,1,1);
}

Bewoom.prototype.IniciarPerCodiConstruccio = function (CadenaCodi) {
	var CodiBinari=ConvertirBase32ABinari(CadenaCodi);
	this.Items[7].Items[1].CarregarValorDeCadenaBinari(CodiBinari,0,1);
	this.Items[7].Items[1].Items[1].Items[1].CarregarValorDeCadenaBinari(CodiBinari,1,7);	// Sumar
	this.Items[7].Items[1].Items[1].Items[2].CarregarValorDeCadenaBinari(CodiBinari,8);
	this.Items[7].Items[1].Items[1].Items[3].CarregarValorDeCadenaBinari(CodiBinari,9);
	this.Items[7].Items[1].Items[1].Items[4].CarregarValorDeCadenaBinari(CodiBinari,10,7);	// Restar
	this.Items[7].Items[1].Items[1].Items[5].CarregarValorDeCadenaBinari(CodiBinari,17);
	this.Items[7].Items[1].Items[1].Items[6].CarregarValorDeCadenaBinari(CodiBinari,18);
	this.Items[7].Items[1].Items[1].Items[7].CarregarValorDeCadenaBinari(CodiBinari,19,7);	// Multiplicar
	this.Items[7].Items[1].Items[1].Items[8].CarregarValorDeCadenaBinari(CodiBinari,26);
	this.Items[7].Items[1].Items[1].Items[9].CarregarValorDeCadenaBinari(CodiBinari,27);
	this.Items[7].Items[1].Items[1].Items[10].CarregarValorDeCadenaBinari(CodiBinari,28,7);	// Dividir
	this.Items[7].Items[1].Items[1].Items[11].CarregarValorDeCadenaBinari(CodiBinari,35);
	this.Items[7].Items[1].Items[1].Items[12].CarregarValorDeCadenaBinari(CodiBinari,36);
	this.Items[7].Items[1].Items[1].Items[13].CarregarValorDeCadenaBinari(CodiBinari,37,7);	// Elevar
	this.Items[7].Items[1].Items[1].Items[14].CarregarValorDeCadenaBinari(CodiBinari,44);
	this.Items[7].Items[1].Items[1].Items[15].CarregarValorDeCadenaBinari(CodiBinari,45);
	this.Items[7].Items[1].Items[1].Items[16].CarregarValorDeCadenaBinari(CodiBinari,46,7);	// Radicar
	this.Items[7].Items[1].Items[1].Items[17].CarregarValorDeCadenaBinari(CodiBinari,53);
	this.Items[7].Items[1].Items[1].Items[18].CarregarValorDeCadenaBinari(CodiBinari,54);
	this.Items[7].Items[1].Items[1].Items[0].CarregarValorDeCadenaBinari(CodiBinari,55,5);
}

/************************************************************************************
*
* Bewoom --> Sortida de Codi Bewoom
*
************************************************************************************/

Bewoom.prototype.GenerarCodiBewoom = function () {
	var Text="";
	Text+=this.GenerarCodiNombres();
	Text+=this.GenerarCodiResultatsParcials();
	Text+=this.GenerarCodiResultatFinal();
	Text+=this.GenerarCodiExponents();
	Text+=this.GenerarCodiEvitar();
	Text+=this.GenerarCodiOutput();
	Text+=this.GenerarCodiGeneral();
	Text+=this.GenerarCodiConstruccio();
 	return (Text);
}

Bewoom.prototype.GenerarCodiNombres = function () {
	var Text=this.Items[1].GenerarCodi();
	return (Text);
}

Bewoom.prototype.GenerarCodiResultatsParcials = function () {
	var Text=this.Items[2].Items[1].Items[1].GenerarCodi();
	return (Text);
}

Bewoom.prototype.GenerarCodiResultatFinal = function () {
	var Text=this.Items[3].Items[1].Items[1].GenerarCodi();
	return (Text);
}

Bewoom.prototype.GenerarCodiExponents = function () {
	var Text=this.Items[4].GenerarCodi();
	return (Text);
}

Bewoom.prototype.GenerarCodiEvitar = function () {
	var Text="";
	Text+=this.Items[5].Items[1].OutputBinari();
	Text+=this.Items[5].Items[2].OutputBinari();
	Text+=this.Items[5].Items[3].OutputBinari();
	Text+=this.Items[5].Items[4].OutputBinari();
	var Codi32=ConvertirBinariABase32(Text);
	return(Codi32);
}

Bewoom.prototype.GenerarCodiOutput = function () {
	var Text="";
	Text+=this.Items[6].Items[3].OutputBinari(3);
	Text+=this.Items[6].Items[1].OutputBinari();
	Text+=this.Items[6].Items[2].OutputBinari(2);
	Text+=this.Items[6].Items[4].OutputBinari(4);
	var Codi32=ConvertirBinariABase32(Text);
	return(Codi32);
}

Bewoom.prototype.GenerarCodiGeneral = function () {
	var Text="";
	Text+=this.Items[2].Items[1].OutputBinari(1);
	Text+=this.Items[3].Items[1].OutputBinari(1);
	var Codi32=ConvertirBinariABase32(Text);
	return(Codi32);
}

Bewoom.prototype.GenerarCodiConstruccio = function () {
	var Text="";
	Text+=this.Items[7].Items[1].OutputBinari(1);
	Text+=this.Items[7].Items[1].Items[1].Items[1].OutputBinari(7);
	Text+=this.Items[7].Items[1].Items[1].Items[2].OutputBinari();
	Text+=this.Items[7].Items[1].Items[1].Items[3].OutputBinari();
	Text+=this.Items[7].Items[1].Items[1].Items[4].OutputBinari(7);
	Text+=this.Items[7].Items[1].Items[1].Items[5].OutputBinari();
	Text+=this.Items[7].Items[1].Items[1].Items[6].OutputBinari();
	Text+=this.Items[7].Items[1].Items[1].Items[7].OutputBinari(7);
	Text+=this.Items[7].Items[1].Items[1].Items[8].OutputBinari();
	Text+=this.Items[7].Items[1].Items[1].Items[9].OutputBinari();
	Text+=this.Items[7].Items[1].Items[1].Items[10].OutputBinari(7);
	Text+=this.Items[7].Items[1].Items[1].Items[11].OutputBinari();
	Text+=this.Items[7].Items[1].Items[1].Items[12].OutputBinari();
	Text+=this.Items[7].Items[1].Items[1].Items[13].OutputBinari(7);
	Text+=this.Items[7].Items[1].Items[1].Items[14].OutputBinari();
	Text+=this.Items[7].Items[1].Items[1].Items[15].OutputBinari();
	Text+=this.Items[7].Items[1].Items[1].Items[16].OutputBinari(7);
	Text+=this.Items[7].Items[1].Items[1].Items[17].OutputBinari();
	Text+=this.Items[7].Items[1].Items[1].Items[18].OutputBinari();
	Text+=this.Items[7].Items[1].Items[1].Items[0].OutputBinari(5);
	var Codi32=ConvertirBinariABase32(Text);
	return(Codi32);
}

/***********************************************************************************\
*
* GENERADORBEWOOM --> Interface
*
************************************************************************************/

Bewoom.prototype.IniciGenesis= function() {
	// Rutina reescrivible per a qualsevol generador hereu d'aquest
	return(this.IniciBewoom());
}

Bewoom.prototype.GenerarTitol = function() {
	return(Traduir("BEWOOM52"));	// "Operacions"
}

Bewoom.prototype.GenerarEnunciatGeneral = function() {
	return(Traduir("BEWOOM51"));	// "Realitza les següents operacions"
}

Bewoom.prototype.GenerarPautaGeneral = function() {
	return("");
	//return(this.PautaGeneral);
}

Bewoom.prototype.IniciBewoom= function() {
	var Text=this.CodiBewoomActual;
	if (Text=="" || Text==undefined) Text=this.CodiBewoomInicial;
	this.IniciarPerCodiBewoom(Text);
	// Crida a un Inici per als hereus d'aquest objecte.
	return(1);
}

Bewoom.prototype.ResetGenesis= function() {
	// Retorna Status
	this.Enunciat="";
	this.SolucioHTML="";
	this.Pauta="";
	this.Solucio="";
	this.InfoExtra="";		
	// Crida a un Reset per als hereus d'aquest objecte.
	var StatusResetLocal=this.Reset();
	if (StatusResetLocal<0) return (StatusResetLocal);
	var StatusReset=this.Arbre.ResetGenesis();
	return (StatusReset);
}

Bewoom.prototype.Reset= function() {
	// Rutina reescrivible per a qualsevol generador hereu d'aquest
	return(1);
}

Bewoom.prototype.Generar= function () {
	var Status=this.Arbre.GenesisStep();
	if (Status==1) {
		// Si l'exercici s'ha pogut construir cal omplir les variables de sortida
		// GenerarEnunciat ha de ser la primera perquè també pot realitzar accions
		// complementàries de la generació de l'exercici
		this.Enunciat=this.GenerarEnunciat();
		this.SolucioHTML=this.GenerarSolucioHTML();
		this.Pauta=this.GenerarPauta();
		this.Solucio=this.GenerarSolucio();
		this.InfoExtra=this.GenerarInfoExtra();		
	}
	return(Status);
}

Bewoom.prototype.GenerarEnunciat = function() {
	// Visualitza l'operació combinada
	return (this.Arbre.EscriureArbre(this.LlenguatgeSortida));	
}

Bewoom.prototype.GenerarSolucio = function() {
	// Com a resposta és el valor de l'arbre d'operacions en format ASCII (0)
	return (this.Arbre.EscriureValorFinalArbre(0));
}

Bewoom.prototype.GenerarSolucioHTML = function() {
	return("");
}

Bewoom.prototype.GenerarPauta = function() {
	var Text="___"+this.GenerarFormatResposta()+"___";
	return (Text);
}

Bewoom.prototype.GenerarFormatResposta = function() {
	var TipusNombre=this.Arbre.MyComplement.CondicionsNumeriquesNombresAleatoris.Items[3].Valor;
	var TextFormat="";
	if (TipusNombre==1) TextFormat="N";
	if (TipusNombre==2) TextFormat="N";
	if (TipusNombre==3) {
		TextFormat="D";
		// Augmento en un el nombre de decimals.
		var NDecimals=parseFloat(this.Arbre.MyComplement.CondicionsNumeriquesNombresAleatoris.Items[3].Items[3].Items[1].Valor)+1
		TextFormat=TextFormat +""+NDecimals ;
	}
	return (TextFormat);
}

Bewoom.prototype.GenerarInfoExtra = function() {
	return ("");
}

/***********************************************************************************\
*
* GENERADORBEWOOM --> CICLE GENERADOR
*
************************************************************************************/

/************************************************************************************
*
* GENERADORBEWOOM --> CICLE GENERADOR --> CICLE PRINCIPAL
*
************************************************************************************/

Arbre.prototype.ResetGenesis = function() {
	// Inicialitza la generació d'expressions aleatòries.
	// Retorna Status.
	this.NSteps=0;
	this.ArbreConstruit=false;
	this.Reset();
	var Status=this.ResetConstruir();
	return (Status);
}

Bewoom.prototype.NombreOperacions= function() {
	return (MyGenerador.Items[7].Items[1].Items[1].Items[0].Valor);	// Nombre d'operacions
}

Arbre.prototype.GenesisStep = function () {
	// va fent "steps" de construcció de l'expressió i després de la seva 
	// completació fins que la completa.
	// Retorna Status.
	var Status=0;
	this.NSteps=this.NSteps+1;	
	if (this.NSteps>this.MaxNSteps+1) {
		Status=this.ResetGenesis();
		if (Status<0) return (Status);
		return (STATUS_TIME_OUT_STEP); 
	} 
	if (!this.ArbreConstruit){
		// Si l'arbre no està encara construït, cal construir-lo
		Status=this.ConstruirStep();
		if (Status<0) return (Status);
		if (Status==STATUS_FET_OK) {
			// Si s'ha construit l'arbre, iniciem la seva completació
			this.ArbreConstruit=true;
			Status=this.ResetCompletar();
			if (Status<0) return (Status);
		}
		if (Status==STATUS_FET_NO_OK) {
			// S'ha construït l'arbre però no és acceptable
			Status=this.ResetConstruir();
			if (Status<0) return (Status);
		}
		return (STATUS_TIME_OUT_STEP); 	// L'expressió està construïda però 
						// no està feta encara
	}
	
	// Si l'arbre està construït, va fent "steps" de completació
	Status=this.CompletarStep();
	
	// Si hi ha error d'incompatibilitat entre els valors fixos i la pauta
	// i la pauta es pot canviar, la canviem fent un Reset general
	if (Status==STATUS_INCOMP_VALOR_FIX_PREVI || Status==STATUS_INCOMP_VALOR_FIX_INICIAL) {
		if (MyGenerador.Items[7].Items[1].Valor==1) {
			Status=this.ResetGenesis();
			if (Status<0) return (Status);
			return (STATUS_TIME_OUT_STEP); 	
		}
	}
	return (Status);
}

/***********************************************************************************\
*
* GENERADORBEWOOM --> CICLE GENERADOR --> CONSTRUCCIÓ
*
************************************************************************************/

/************************************************************************************
*
* GENERADORBEWOOM --> CICLE GENERADOR --> CONSTRUCCIÓ --> CICLE CONSTRUCCIÓ
*
************************************************************************************/

Arbre.prototype.ResetConstruir = function() {
	// Retorna Status
	if (MyGenerador.Items[7].Items[1].Valor==0) {		// Pauta Fixa
		// Si la pauta és fixa, no cal fer res.
		return (STATUS_FET_OK);
	}
	// Si cal construir amb pauta aleatòria, iniciem la "construcció Step"
	return (this.ResetConstruirPautaAleatoria());
}

Arbre.prototype.ConstruirStep = function() {
	// Retorna Status
	if (MyGenerador.Items[7].Items[1].Valor==0) {
		// Si la pauta és fixa, la construeix ( i inicia completació )
		var Status=this.ConstruirExpressioPerExemple();
		if (Status<0) return (Status);
		this.ArbreConstruit=true;
		return (STATUS_FET_OK);
	}
	// Si cal construir amb pauta aleatòria, iniciem la "construcció Step"
	var Status=this.ConstruirPautaAleatoriaStep();
	return (Status);
}

/************************************************************************************
*
* GENERADORBEWOOM --> CICLE GENERADOR --> CONSTRUCCIÓ --> CICLE CONSTRUCCIÓ --> CONSTRUCCIÓ PER EXEMPLE
*
************************************************************************************/

Arbre.prototype.ConstruirExpressioPerExemple = function () {
	// Construeix una operació combinada amb la mateixa extructura que la que hi ha
	// al text this.Pauta
	// retorna Status

	// Genera l'expressió
	var Status=this.InputArbre(MyGenerador.Items[7].Items[1].Items[0].Valor);	// Pauta
	if (Status!=STATUS_FET_OK) return (Status);

	// Compta les operacions i esborra el seu contingut numèric.
	this.ComptarOperacionsArbre();
	return (STATUS_FET_OK);
}

/************************************************************************************
*
* GENERADORBEWOOM --> CICLE GENERADOR --> CONSTRUCCIÓ --> CICLE CONSTRUCCIÓ 
* --> CONSTRUCCIÓ PER PAUTA ALEATÒRIA
*
************************************************************************************/

Arbre.prototype.ResetConstruirPautaAleatoria = function () {
	return (STATUS_FET_OK);
}

Arbre.prototype.ConstruirPautaAleatoriaStep = function() {
	// Retorna Status.
	this.Reset();
	var PosicioArbre=0;
	this.Nodes[PosicioArbre].NOperacionsBranca=MyGenerador.Items[7].Items[1].Items[1].Items[0].Valor;
	this.Nodes[PosicioArbre].NCiclesBranca=	this.MaxNCiclesBrancaPautaAleatoria;
	Status=this.ConstruirBrancaPautaAleatoriaRecursivament(PosicioArbre);
	if (Status<0) return (Status);
	if (Status==STATUS_FET_OK) {	
		if (this.TestPautaAleatoriaAcceptable()) return (STATUS_FET_OK);
		else return (STATUS_FET_NO_OK);
	}
	return (Status);
}

Arbre.prototype.ConstruirBrancaPautaAleatoriaRecursivament = function (PosicioBranca) {
	// Construeix una branca nova des de la posicio PosicioBranca (on hi ha un node final)
	// Amb NOperacionsBranca. 
	// Retorna Status
	var SortirDeBucle=false;
	var OperacioPare=0;
	this.Posicio=PosicioBranca;	
	var NOperacionsBranca=this.Nodes[this.Posicio].NOperacionsBranca;
	while (!SortirDeBucle) {
		// Si és un node final, posem un nombre	

		if (this.Nodes[this.Posicio].NOperacionsBranca==0) {
			this.Nodes[this.Posicio].Operacio=0;	// NOMBRE
			return (STATUS_FET_OK); 
		}	

		// És un node operació. Cal fer descendència.

		this.GenerarDescendencia();

		this.Nodes[this.PosicioD()].NCiclesBranca=this.MaxNCiclesBrancaPautaAleatoria;
		this.Nodes[this.PosicioE()].NCiclesBranca=this.MaxNCiclesBrancaPautaAleatoria;

		// Posem una operació aleatòria.

		if (this.PosicioInicial()) OperacioPare=0;
			else OperacioPare=this.Nodes[this.PosicioPare()].Nombre.Operacio;
		
		this.Nodes[this.Posicio].Nombre.Operacio=this.OperacioAleatoria(OperacioPare);
	
		// Posem un nombre d'operacions aleatori.
		var OperacionsEsquerra=this.CalcularOperacionsEsquerra(NOperacionsBranca,this.Operacio());
		this.Nodes[this.PosicioE()].NOperacionsBranca=OperacionsEsquerra;
		this.Nodes[this.PosicioD()].NOperacionsBranca=NOperacionsBranca-OperacionsEsquerra-1;
		
		// Construïm les subbranques per recursivitat.

		var Status=this.ConstruirBrancaPautaAleatoriaRecursivament(this.PosicioE());
		if (Status>0) {
			this.Posicio=PosicioBranca;
			var Status=this.ConstruirBrancaPautaAleatoriaRecursivament(this.PosicioD());
			if (Status>0) {
				// Si s'han pogut construir les dues subbranques, mirem si la branca
				// és acceptable
				this.Posicio=PosicioBranca;
				if (this.TestBrancaPautaAleatoriaAcceptable()) {
					return (STATUS_FET_OK); 
				}
			}
		}
	
		// No hem pogut fer la descendència, cal tornar a provar.

		this.EliminarDescendencia();

		this.Nodes[this.Posicio].NCiclesBranca=this.Nodes[this.Posicio].NCiclesBranca-1;
		if (this.Nodes[this.Posicio].NCiclesBranca<=0) SortirDeBucle=true; // TIME OUT BRANCA
	}
	return (STATUS_TIME_OUT_STEP);
}		

/************************************************************************************
*
* GENERADORBEWOOM --> CICLE GENERADOR --> CONSTRUCCIÓ --> CICLE CONSTRUCCIÓ 
* --> CONSTRUCCIÓ PER PAUTA ALEATÒRIA --> TEST PAUTA ALEATORIA ACCEPTABLE
*
************************************************************************************/

Arbre.prototype.TestPautaAleatoriaAcceptable =function() {
	// Comprova si la pauta aleatòria és acceptable.
	// Retorna false si no ho és.
	this.ComptarOperacionsArbre(); // Sempre comptem les operacions (per a estadístiques)
	if (this.HiHaOperacionsObligatories()) {
		if (MyGenerador.Items[7].Items[1].Items[1].Items[2].Valor==1) {
			if (this.NSumesArbre<1) return (false);
		}
		if (MyGenerador.Items[7].Items[1].Items[1].Items[5].Valor==1) {
			if (this.NRestesArbre<1) return (false);
		}
		if (MyGenerador.Items[7].Items[1].Items[1].Items[8].Valor==1) {
			if (this.NMultiplicacionsArbre<1) return (false);
		}
		if (MyGenerador.Items[7].Items[1].Items[1].Items[11].Valor==1) {
			if (this.NDivisionsArbre<1) return (false);
		}
		if (MyGenerador.Items[7].Items[1].Items[1].Items[14].Valor==1) {
			if (this.NPotenciesArbre<1) return (false);
		}
		if (MyGenerador.Items[7].Items[1].Items[1].Items[17].Valor==1) {
			if (this.NArrelsArbre<1) return (false);
		}
	}
	var Operacions=this.NSumesArbre+this.NRestesArbre+this.NMultiplicacionsArbre;
	Operacions+=this.NDivisionsArbre+this.NPotenciesArbre+this.NArrelsArbre
	var OperandsPossibles=0;
	if (MyGenerador.Items[7].Items[1].Items[1].Items[1].Valor>0) OperandsPossibles+=1;
	if (MyGenerador.Items[7].Items[1].Items[1].Items[4].Valor>0) OperandsPossibles+=1;
	if (MyGenerador.Items[7].Items[1].Items[1].Items[7].Valor>0) OperandsPossibles+=1;
	if (MyGenerador.Items[7].Items[1].Items[1].Items[10].Valor>0) OperandsPossibles+=1;
	if (MyGenerador.Items[7].Items[1].Items[1].Items[13].Valor>0) OperandsPossibles+=1;
	if (MyGenerador.Items[7].Items[1].Items[1].Items[16].Valor>0) OperandsPossibles+=1;
	//
	// Condició adicional #1: Si hi ha menys operacions que operands almenys no repetir
	// 
	if (Operacions<=OperandsPossibles) {
		if (this.NSumesArbre>1) return (false);
		if (this.NRestesArbre>1) return (false);
		if (this.NMultiplicacionsArbre>1) return (false);
		if (this.NDivisionsArbre>1) return (false);
		if (this.NPotenciesArbre>1) return (false);
		if (this.NArrelsArbre>1) return (false);
	}
	//
	// Condició adicional #2: Si hi ha més operacions que operands almenys una de cada
	// 
	if (Operacions>=OperandsPossibles) {
		if (this.NSumesArbre<1 && MyGenerador.Items[7].Items[1].Items[1].Items[1].Valor>0) return (false);
		if (this.NRestesArbre<1 && MyGenerador.Items[7].Items[1].Items[1].Items[4].Valor>0) return (false);
		if (this.NMultiplicacionsArbre<1 && MyGenerador.Items[7].Items[1].Items[1].Items[7].Valor>0) return (false);
		if (this.NDivisionsArbre<1 && MyGenerador.Items[7].Items[1].Items[1].Items[10].Valor>0) return (false);
		if (this.NPotenciesArbre<1 && MyGenerador.Items[7].Items[1].Items[1].Items[13].Valor>0) return (false);
		if (this.NArrelsArbre<1 && MyGenerador.Items[7].Items[1].Items[1].Items[16].Valor>0) return (false);
	}
	return (true);
}

Arbre.prototype.HiHaOperacionsObligatories = function() {
	if (MyGenerador.Items[7].Items[1].Items[1].Items[2].Valor==1) return (true);
	if (MyGenerador.Items[7].Items[1].Items[1].Items[5].Valor==1) return (true);
	if (MyGenerador.Items[7].Items[1].Items[1].Items[5].Valor==1) return (true);
	if (MyGenerador.Items[7].Items[1].Items[1].Items[11].Valor==1) return (true);
	if (MyGenerador.Items[7].Items[1].Items[1].Items[14].Valor==1) return (true);
	if (MyGenerador.Items[7].Items[1].Items[1].Items[17].Valor==1) return (true);
	return (false);
}

Arbre.prototype.ComptarOperacionsArbre = function (){
	// Recompta les operacions que hi ha a l'arbre.
	this.NSumesArbre=0;
	this.NRestesArbre=0;
	this.NMultiplicacionsArbre=0;
	this.NDivisionsArbre=0;
	this.NPotenciesArbre=0;
	this.NArrelsArbre=0;
	this.NNombresArbre=0;
	this.ComptarOperacionsBrancaRecursivament(0);
}
Arbre.prototype.ComptarOperacionsBrancaRecursivament = function(PosicioBranca){
	this.Posicio=PosicioBranca;
	if (this.PosicioFinal()) return;
	this.AfegirOperacio(this.Nodes[this.Posicio].Nombre.Operacio);
	this.ComptarOperacionsBrancaRecursivament(this.PosicioD());
	this.Posicio=PosicioBranca;
	this.ComptarOperacionsBrancaRecursivament(this.PosicioE());
}	
Arbre.prototype.AfegirOperacio = function (Operacio){
	switch (Operacio) {
		case SUMAR : this.NSumesArbre=this.NSumesArbre+1;break;
		case RESTAR : this.NRestesArbre=this.NRestesArbre+1;break;
		case MULTIPLICAR : this.NMultiplicacionsArbre=this.NMultiplicacionsArbre+1;break;
		case DIVIDIR : this.NDivisionsArbre=this.NDivisionsArbre+1;break;
		case ELEVAR : this.NPotenciesArbre=this.NPotenciesArbre+1;break;
		case RADICAR : this.NArrelsArbre=this.NArrelsArbre+1;break;
		default: this.NNombresArbre=this.NNombresArbre+1;
	}
}

Arbre.prototype.CalcularOperacionsEsquerra = function (NOperacionsBranca,OperacioPare) {
	var MaxOperacions=NOperacionsBranca-1;
	// Cal Repartir MaxOperacions entre les dues branques.
	if (this.OperacionsEncadenades.Valor==1) {
		// Si són operacions encadenades va tot a l'esquerra
		return (MaxOperacions);
	}
	if (OperacioPare==ELEVAR || OperacioPare==RADICAR) {
		// Un exponent d'una potència o arrel només pot ser numèrica
		return (MaxOperacions);
	}
	return (GenerarEnterAleatoriAcotat(0,MaxOperacions));
}

Arbre.prototype.OperacioAleatoria = function (OperacioPare) {
	this.NormalitzarOperacionsAleatories(OperacioPare);
	var Nombre=GenerarEnterAleatoriAcotat(0,100);
	var Index=this.PercentatgeSumarActual;
	if (Nombre<Index) return (SUMAR);
	Index=Index+this.PercentatgeRestarActual;
	if (Nombre<Index) return (RESTAR);
	Index=Index+this.PercentatgeMultiplicarActual;
	if (Nombre<Index) return (MULTIPLICAR);
	Index=Index+this.PercentatgeDividirActual;
	if (Nombre<Index) return (DIVIDIR);
	Index=Index+this.PercentatgeElevarActual;
	if (Nombre<Index) return (ELEVAR);
	Index=Index+this.PercentatgeRadicarActual;
	if (Nombre<Index) return (RADICAR);
	return (SUMAR);//no hauria d'arribar aquí mai.
}

Arbre.prototype.NormalitzarOperacionsAleatories = function (OperacioPare) {
	// Per a escollir l'operació aleatòria es fa una distribució de 
	// Percentatge entre totes les operacions, i com que tenim informació 
	// de l'operació del pare, anulem aquelles combinacions prohibides,
	// i evitem també fer dobles potències (Elevar-Radicar)
	var Cent=MyGenerador.Items[7].Items[1].Items[1].Items[1].Valor+MyGenerador.Items[7].Items[1].Items[1].Items[4].Valor+
		MyGenerador.Items[7].Items[1].Items[1].Items[7].Valor+MyGenerador.Items[7].Items[1].Items[1].Items[10].Valor+
		MyGenerador.Items[7].Items[1].Items[1].Items[13].Valor+MyGenerador.Items[7].Items[1].Items[1].Items[16].Valor;
	MyGenerador.Items[7].Items[1].Items[1].Items[1].Valor=MyGenerador.Items[7].Items[1].Items[1].Items[1].Valor/Cent*100;
	MyGenerador.Items[7].Items[1].Items[1].Items[4].Valor=MyGenerador.Items[7].Items[1].Items[1].Items[4].Valor/Cent*100;
	MyGenerador.Items[7].Items[1].Items[1].Items[7].Valor=MyGenerador.Items[7].Items[1].Items[1].Items[7].Valor/Cent*100;
	MyGenerador.Items[7].Items[1].Items[1].Items[10].Valor=MyGenerador.Items[7].Items[1].Items[1].Items[10].Valor/Cent*100;
	MyGenerador.Items[7].Items[1].Items[1].Items[13].Valor=MyGenerador.Items[7].Items[1].Items[1].Items[13].Valor/Cent*100;
	MyGenerador.Items[7].Items[1].Items[1].Items[16].Valor=MyGenerador.Items[7].Items[1].Items[1].Items[16].Valor/Cent*100;

	this.PercentatgeSumarActual=MyGenerador.Items[7].Items[1].Items[1].Items[1].Valor;
	this.PercentatgeRestarActual=MyGenerador.Items[7].Items[1].Items[1].Items[4].Valor;
	this.PercentatgeMultiplicarActual=MyGenerador.Items[7].Items[1].Items[1].Items[7].Valor;
	this.PercentatgeDividirActual=MyGenerador.Items[7].Items[1].Items[1].Items[10].Valor;
	this.PercentatgeElevarActual=MyGenerador.Items[7].Items[1].Items[1].Items[13].Valor;
	this.PercentatgeRadicarActual=MyGenerador.Items[7].Items[1].Items[1].Items[16].Valor;
	
	if (OperacioPare==SUMAR) {
		if (MyGenerador.Items[7].Items[1].Items[1].Items[3].Valor==1) this.PercentatgeSumarActual=0;
	}
	if (OperacioPare==RESTAR) {
		if (MyGenerador.Items[7].Items[1].Items[1].Items[6].Valor==1) this.PercentatgeRestarActual=0;
	}
	if (OperacioPare==MULTIPLICAR) {
		if (MyGenerador.Items[7].Items[1].Items[1].Items[9].Valor==1) this.PercentatgeMultiplicarActual=0;
	}
	if (OperacioPare==DIVIDIR) {
		if (MyGenerador.Items[7].Items[1].Items[1].Items[12].Valor==1) this.PercentatgeDividirActual=0;
	}
	if (OperacioPare==ELEVAR) {
		if (MyGenerador.Items[7].Items[1].Items[1].Items[15].Valor==1) this.PercentatgeElevarActual=0;
		// En principi no es poden fer dobles potències...
		this.PercentatgeElevarActual=0;
		this.PercentatgeRadicarActual=0;
	}
	if (OperacioPare==RADICAR) {
		if (MyGenerador.Items[7].Items[1].Items[1].Items[18].Valor==1) this.PercentatgeRadicarActual=0;
		// En principi no es poden fer dobles potències...
		this.PercentatgeElevarActual=0;
		this.PercentatgeRadicarActual=0;
	}
	Cent=this.PercentatgeSumarActual+this.PercentatgeRestarActual+
		this.PercentatgeMultiplicarActual+this.PercentatgeDividirActual+
		this.PercentatgeElevarActual+this.PercentatgeRadicarActual;
	this.PercentatgeSumarActual=this.PercentatgeSumarActual/Cent*100;
	this.PercentatgeRestarActual=this.PercentatgeRestarActual/Cent*100;
	this.PercentatgeMultiplicarActual=this.PercentatgeMultiplicarActual/Cent*100;
	this.PercentatgeDividirActual=this.PercentatgeDividirActual/Cent*100;
	this.PercentatgeElevarActual=this.PercentatgeElevarActual/Cent*100;
	this.PercentatgeRadicarActual=this.PercentatgeRadicarActual/Cent*100;
}

Arbre.prototype.ComptarNombreOperacionsPautaAleatoria = function() {
	// Compta el nombre d'operacions amb percentatge >0 de la pauta aleatoria
	// S'utilitza en la rutina GenerarTitolOperacions()
	var NOperacionsPautaAleatoria=0;
	if (MyGenerador.Items[7].Items[1].Items[1].Items[1].Valor>0) NOperacionsPautaAleatoria=NOperacionsPautaAleatoria+1;
	if (MyGenerador.Items[7].Items[1].Items[1].Items[4].Valor>0) NOperacionsPautaAleatoria=NOperacionsPautaAleatoria+1;
	if (MyGenerador.Items[7].Items[1].Items[1].Items[7].Valor>0) NOperacionsPautaAleatoria=NOperacionsPautaAleatoria+1;
	if (MyGenerador.Items[7].Items[1].Items[1].Items[10].Valor>0) NOperacionsPautaAleatoria=NOperacionsPautaAleatoria+1;
	if (MyGenerador.Items[7].Items[1].Items[1].Items[13].Valor>0) NOperacionsPautaAleatoria=NOperacionsPautaAleatoria+1;
	if (MyGenerador.Items[7].Items[1].Items[1].Items[16].Valor>0) NOperacionsPautaAleatoria=NOperacionsPautaAleatoria+1;
	return (NOperacionsPautaAleatoria);
}

/************************************************************************************
*
* GENERADORBEWOOM --> CICLE GENERADOR --> CONSTRUCCIÓ --> CICLE CONSTRUCCIÓ 
* --> CONSTRUCCIÓ PER PAUTA ALEATÒRIA --> TEST BRANCA ACCEPTABLE
*
************************************************************************************/

Arbre.prototype.TestBrancaPautaAleatoriaAcceptable = function() {

	// Comprovem les dobles operacions
	if (MyGenerador.Items[7].Items[1].Items[1].Items[3].Valor==1) {
		if (this.TestDobleOperacio(SUMAR)) return (false);
	}
	if (MyGenerador.Items[7].Items[1].Items[1].Items[6].Valor==1) {
		if (this.TestDobleOperacio(RESTAR)) return (false);
	}
	if (MyGenerador.Items[7].Items[1].Items[1].Items[9].Valor==1) {
		if (this.TestDobleOperacio(MULTIPLICAR)) return (false);
	}
	if (MyGenerador.Items[7].Items[1].Items[1].Items[12].Valor==1) {
		if (this.TestDobleOperacio(DIVIDIR)) return (false);
	}
	if (MyGenerador.Items[7].Items[1].Items[1].Items[15].Valor==1) {
		if (this.TestDobleOperacio(ELEVAR)) return (false);
	}
	if (MyGenerador.Items[7].Items[1].Items[1].Items[17].Valor==1) {
		if (this.TestDobleOperacio(RADICAR)) return (false);
	}

	return (true);
}

Arbre.prototype.TestDobleOperacio = function(Operacio) {
	if (this.PosicioFinal()) return (false);
	if (this.Nodes[this.Posicio].Nombre.Operacio!=Operacio) return (false);
	if (this.Nodes[this.PosicioE()].Nombre.Operacio==Operacio) return (true);
	if (this.Nodes[this.PosicioD()].Nombre.Operacio==Operacio) return (true);
	return (false);
}

/***********************************************************************************\
*
* GENERADORBEWOOM --> CICLE GENERADOR --> COMPLETACIÓ
*
************************************************************************************/

/************************************************************************************
*
* GENERADORBEWOOM --> CICLE GENERADOR --> COMPLETACIÓ --> CICLE COMPLETACIÓ
*
************************************************************************************/

Arbre.prototype.ResetCompletar = function(){
	// Retorna Status
	this.InicialitzarArbre(); // Buida l'arbre de contingut numèric 
	this.GestionarResultatFinalFix();
	this.Posicio=0;
	return (STATUS_FET_OK); //
}

Arbre.prototype.GestionarResultatFinalFix= function () {
	if (this.ResultatFinal.Contingut==false) return;
	this.Nodes[0].Nombre.ValorFix=true;
	this.Nodes[0].Nombre.Contingut=true;
	this.Nodes[0].Nombre.Num=this.ResultatFinal.Num;
	this.Nodes[0].Nombre.Den=this.ResultatFinal.Den;
	this.Nodes[0].Nombre.Dec=this.ResultatFinal.Dec;
	this.Nodes[0].Nombre.Tipus=this.ResultatFinal.Tipus;
	this.Nodes[0].Nombre.NDecimalsPrecisio=this.ResultatFinal.NDecimalsPrecisio;
}

Arbre.prototype.CompletarStep= function(){
	// Retorna Status;
	this.NCiclesStep=0;
	while (this.NCiclesStep<this.MaxNCiclesStep) {	
		this.NCiclesStep=this.NCiclesStep+1;

		// Mirem si hem esgotat el temps de càlcul per branca
		this.Nodes[this.Posicio].NCiclesBranca=this.Nodes[this.Posicio].NCiclesBranca-1;
		if (this.Nodes[this.Posicio].NCiclesBranca<=0) {
			this.Nodes[this.Posicio].NCiclesBranca=this.MaxNCiclesBranca;
			if (!this.PosicioInicial()) {
				this.PassarABrancaPare(false);
				continue;
			} 
			else {
				return (STATUS_TIME_OUT_STEP);
			}
		}
		
		// Gestionem si val la pena fer alguna branca abans del node.		
		var Prioritat=this.Test_Prioritat_Branca();
		if (Prioritat==1) {this.PassarABrancaD(false);continue;}
		if (Prioritat==2) {this.PassarABrancaE(false);continue;}
		
		// Completem el node si no s'ha fet encara.
		if (!this.Nodes[this.Posicio].NodeFet) {
			var Resultat=this.GestionarNode();
			if (Resultat!=STATUS_FET_OK) {
				if (Resultat<0 
					|| Resultat==STATUS_INCOMP_VALOR_FIX_PREVI 
					|| Resultat==STATUS_INCOMP_VALOR_FIX_INICIAL) 
					return (Resultat);
				if (Resultat==STATUS_INCOMP_D) this.ResetBrancaD();
				if (Resultat==STATUS_INCOMP_E) this.ResetBrancaE();
				if (Resultat==STATUS_INCOMP_R) this.PassarABrancaPare(false);
				continue;
			} 
			else this.Nodes[this.Posicio].NodeFet=true; 
		}	

		// Si cal fer alguna subbranca, es fa.
		if (!this.PosicioFinal()) {
			if (!this.Nodes[this.PosicioE()].BrancaCompleta) 
				{this.PassarABrancaE(true);continue;}
			if (!this.Nodes[this.PosicioD()].BrancaCompleta) 
				{this.PassarABrancaD(true);continue;}
		}

		// S'ha fet el node i s'han fet les dues subbranques. Només cal 
		// comprovar que la branca és acceptable.		
		if (this.TestBrancaAcceptable()) {
			if (this.PosicioInicial()) { 
				return (STATUS_FET_OK);
			}
			else {
				this.PassarABrancaPare(true);
				continue;
			}
		}
		
		// Si la branca no és acceptable, tornem a començar.		
		this.ResetBranca();
	}
	//Si s'ha acabat el temps del step, tornem.
	return (STATUS_TIME_OUT_STEP);
}

/************************************************************************************
*
* GENERADORBEWOOM --> CICLE GENERADOR --> COMPLETACIÓ --> CICLE COMPLETACIÓ
* --> PASSAR A BRANCA
*
************************************************************************************/

Arbre.prototype.PassarABrancaD = function(ResultatProposat) {
	this.Posicio=this.PosicioD();
	this.Nodes[this.Posicio].NodeFet=false;
	this.Nodes[this.Posicio].BrancaCompleta=false;
	this.Nodes[this.Posicio].ResultatProposatPare=ResultatProposat;
	this.Nodes[this.Posicio].NCiclesBranca=this.MaxNCiclesBranca;
	if (!ResultatProposat) {
		this.Nodes[this.Posicio].ResetNombre();
	}
	if (!this.PosicioFinal()){
		this.ResetBrancaD();
		this.ResetBrancaE();			
	}
}

Arbre.prototype.PassarABrancaE = function(ResultatProposat) {
	this.Posicio=this.PosicioE();
	this.Nodes[this.Posicio].NodeFet=false;
	this.Nodes[this.Posicio].BrancaCompleta=false;
	this.Nodes[this.Posicio].ResultatProposatPare=ResultatProposat;
	this.Nodes[this.Posicio].NCiclesBranca=this.MaxNCiclesBranca;
	if (!ResultatProposat) {
		this.Nodes[this.Posicio].ResetNombre();
	}
	if (!this.PosicioFinal()){
		this.ResetBrancaD();
		this.ResetBrancaE();			
	}
}

Arbre.prototype.PassarABrancaPare = function(TheBrancaCompleta) {
	//Se suposa que s'ha comprovat que no és la posició inicial.
	this.Nodes[this.Posicio].BrancaCompleta=TheBrancaCompleta;
	this.Posicio=this.PosicioPare();
	if (!TheBrancaCompleta) {
		this.ResetBranca();
	}
}

Arbre.prototype.ResetBrancaD = function() {
	this.Nodes[this.PosicioD()].BrancaCompleta=false;	
	this.Nodes[this.PosicioD()].ResetNombre();
}

Arbre.prototype.ResetBrancaE = function() {
	this.Nodes[this.PosicioE()].BrancaCompleta=false;	
	this.Nodes[this.PosicioE()].ResetNombre();
}

Arbre.prototype.ResetBranca = function() {
	this.ResetBrancaD();
	this.ResetBrancaE();
	this.Nodes[this.Posicio].NodeFet=false;
	if (!this.Nodes[this.Posicio].ResultatProposatPare) {
		this.Nodes[this.Posicio].ResetNombre();
	}

}

/************************************************************************************
*
* GENERADORBEWOOM --> CICLE GENERADOR --> COMPLETACIÓ --> CICLE COMPLETACIÓ
* --> TEST PRIORITAT BRANCA
*
************************************************************************************/

Arbre.prototype.Test_Prioritat_Branca= function(){
	// Comprova si cal fer una subbranca abans del node.
	// Retorna 1 --> Branca Dreta, 2--> Branca Esquerra, 0 --> No prioritat
	
	// Si és operació final no prioritza.
	if (this.PosicioFinal()) return (0);
	
	// Si hi ha dos nombres ja fets no prioritza.
	if (this.TestDosDeTresNombres()) return (0);

	// Si el node ja està fet, no prioritza
	if (this.Nodes[this.Posicio].NodeFet) return (0);

	// Si s'està treballant amb nombres decimals cal prioritzar sempre per a evitar
	// els errors d'arrodoniment.

	if (MyGenerador.Items[1].Items[3].Valor==3) {
		if (this.Nodes[this.PosicioE()].Nombre.Contingut&&!this.Nodes[this.PosicioD()].Nombre.Contingut) return (1);
		if (this.Nodes[this.PosicioD()].Nombre.Contingut&&!this.Nodes[this.PosicioE()].Nombre.Contingut) return (2);
		// Si totes dues estan sense fer, se selecciona una aleatòriament.		
		if (Math.random()>0.5) return (1);
		return (2);
	}

	if (MyGenerador.Items[3].Items[1].Items[1].Items[3].Valor==3) {	
		// Almenys una de les dues branques està sense fer, sinó hagués saltat el 
		// filtre TestDosDeTresNombres()
		if (this.Nodes[this.PosicioE()].Nombre.Contingut&&!this.Nodes[this.PosicioD()].Nombre.Contingut) return (1);
		if (this.Nodes[this.PosicioD()].Nombre.Contingut&&!this.Nodes[this.PosicioE()].Nombre.Contingut) return (2);
		// Si totes dues estan sense fer, se selecciona una aleatòriament.		
		if (Math.random()>0.5) return (1);
		return (2);
	}

	// Si hi ha una arrel, té priorita
	
	if (this.Operacio()==RADICAR) return (0);
	if (this.OperacioD()==RADICAR &&!this.Nodes[this.PosicioD()].Nombre.Contingut) return (1);
	if (this.OperacioE()==RADICAR &&!this.Nodes[this.PosicioE()].Nombre.Contingut) return (2);

	// Si hi ha una potència, té priorita
	
	if (this.Operacio()==ELEVAR) return (0);
	if (this.OperacioD()==ELEVAR &&!this.Nodes[this.PosicioD()].Nombre.Contingut) return (1);
	if (this.OperacioE()==ELEVAR &&!this.Nodes[this.PosicioE()].Nombre.Contingut) return (2);


	// Si hi ha una divisió, té priorita
	
	if (this.Operacio()==DIVIDIR) return (0);
	if (this.OperacioD()==DIVIDIR &&!this.Nodes[this.PosicioD()].Nombre.Contingut) return (1);
	if (this.OperacioE()==DIVIDIR &&!this.Nodes[this.PosicioE()].Nombre.Contingut) return (2);

	// Si hi ha una multiplicació, té priorita
	
	if (this.Operacio()==MULTIPLICAR) return (0);
	if (this.OperacioD()==MULTIPLICAR &&!this.Nodes[this.PosicioD()].Nombre.Contingut) return (1);
	if (this.OperacioE()==MULTIPLICAR &&!this.Nodes[this.PosicioE()].Nombre.Contingut) return (2);

	// Si només queden sumes o restes, prioritza

	if ((this.OperacioD()==RESTAR || this.OperacioD()==SUMAR) &&!this.Nodes[this.PosicioD()].Nombre.Contingut) return (1);
	if ((this.OperacioE()==RESTAR || this.OperacioE()==SUMAR) &&!this.Nodes[this.PosicioE()].Nombre.Contingut) return (2);

	return (0); 
}

Arbre.prototype.TestDosDeTresNombres = function() {
	var NNombresFets=0;
	if (this.Nodes[this.Posicio].Nombre.Contingut) NNombresFets=1;
	if (this.Nodes[this.PosicioD()].Nombre.Contingut) NNombresFets=NNombresFets+1;
	if (this.Nodes[this.PosicioE()].Nombre.Contingut) NNombresFets=NNombresFets+1;
	if (NNombresFets>=2) return (true);
	else return (false);
}

/************************************************************************************
*
* GENERADORBEWOOM --> CICLE GENERADOR --> COMPLETACIÓ --> CICLE COMPLETACIÓ
* --> GESTIONAR NODE
*
************************************************************************************/

Arbre.prototype.GestionarNode = function() {
	var Status=STATUS_NO_FET;
	this.CarregarNode();
	Status=this.MyComplement.Completar();	
	if (Status==STATUS_FET_OK) {
		this.DescarregarNode();
		return (Status);
	}
	// Si ha sortit alguna incompatibilitat mirem si són valors fixos, perquè
	// llavors no hi ha res a fer.
	if (Status==STATUS_INCOMP_D) {
		if (this.Nodes[this.PosicioD()].Nombre.Contingut) {
			if (this.Nodes[this.PosicioD()].Nombre.ValorFix==true) {
				return (STATUS_INCOMP_VALOR_FIX_PREVI);
			}
		} else Status=STATUS_NO_VALID_NODE;
	}
	if (Status==STATUS_INCOMP_E) {
		if (this.Nodes[this.PosicioE()].Nombre.Contingut) {
			if (this.Nodes[this.PosicioE()].Nombre.ValorFix==true) {
				return (STATUS_INCOMP_VALOR_FIX_PREVI);
			}
		} else Status=STATUS_NO_VALID_NODE;

	}
	if (Status==STATUS_INCOMP_R) {
		if (this.Nodes[this.Posicio].Nombre.Contingut) {
			if (this.Posicio==0) {
				return (STATUS_INCOMP_VALOR_FIX_INICIAL);
			}
			if (this.Nodes[this.Posicio].Nombre.ValorFix==true) {
				return (STATUS_INCOMP_VALOR_FIX_PREVI);
			}
		} else Status=STATUS_NO_VALID_NODE;
	}
	return (Status);
}
Arbre.prototype.CarregarNode= function(){
	this.MyComplement.NombreD.MyNombre.Contingut=false;
	this.MyComplement.NombreE.MyNombre.Contingut=false;
	this.MyComplement.NombreR.MyNombre.Contingut=false;

	// Carreguem els continguts dels nombres.
	this.MyComplement.NombreR.MyNombre.Tipus=this.Nodes[this.Posicio].Nombre.Tipus;
	this.MyComplement.NombreR.MyNombre.Operacio=this.Nodes[this.Posicio].Nombre.Operacio;
	this.MyComplement.NombreR.MyNombre.ValorFix=this.Nodes[this.Posicio].Nombre.ValorFix;	
	if (this.Nodes[this.Posicio].Nombre.Contingut) {		
		this.MyComplement.NombreR.MyNombre.Num=this.Nodes[this.Posicio].Nombre.Num;
		this.MyComplement.NombreR.MyNombre.Den=this.Nodes[this.Posicio].Nombre.Den;
		this.MyComplement.NombreR.MyNombre.Dec=this.Nodes[this.Posicio].Nombre.Dec;
		this.MyComplement.NombreR.MyNombre.Contingut=true;
		this.MyComplement.NombreR.MyNombre.NDecimalsPrecisio=this.Nodes[this.Posicio].Nombre.NDecimalsPrecisio;	
	}
 	if (!this.PosicioFinal()) {
		this.MyComplement.NombreD.MyNombre.Operacio=this.Nodes[this.PosicioD()].Nombre.Operacio;
		this.MyComplement.NombreE.MyNombre.Operacio=this.Nodes[this.PosicioE()].Nombre.Operacio;
		this.MyComplement.NombreD.MyNombre.Tipus=this.Nodes[this.PosicioD()].Nombre.Tipus;
		this.MyComplement.NombreE.MyNombre.Tipus=this.Nodes[this.PosicioE()].Nombre.Tipus;
		this.MyComplement.NombreD.MyNombre.ValorFix=this.Nodes[this.PosicioD()].Nombre.ValorFix;
		this.MyComplement.NombreE.MyNombre.ValorFix=this.Nodes[this.PosicioE()].Nombre.ValorFix;
		if(this.Nodes[this.PosicioD()].Nombre.Contingut) {		
			this.MyComplement.NombreD.MyNombre.Num=this.Nodes[this.PosicioD()].Nombre.Num;
			this.MyComplement.NombreD.MyNombre.Den=this.Nodes[this.PosicioD()].Nombre.Den;
			this.MyComplement.NombreD.MyNombre.Dec=this.Nodes[this.PosicioD()].Nombre.Dec;
			this.MyComplement.NombreD.MyNombre.NDecimalsPrecisio=this.Nodes[this.PosicioD()].Nombre.NDecimalsPrecisio;
			this.MyComplement.NombreD.MyNombre.Contingut=true;
		}
		if(this.Nodes[this.PosicioE()].Nombre.Contingut) {
			this.MyComplement.NombreE.MyNombre.Num=this.Nodes[this.PosicioE()].Nombre.Num;
			this.MyComplement.NombreE.MyNombre.Den=this.Nodes[this.PosicioE()].Nombre.Den;
			this.MyComplement.NombreE.MyNombre.Dec=this.Nodes[this.PosicioE()].Nombre.Dec;
			this.MyComplement.NombreE.MyNombre.NDecimalsPrecisio=this.Nodes[this.PosicioE()].Nombre.NDecimalsPrecisio;
			this.MyComplement.NombreE.MyNombre.Contingut=true;
		}
	}
	
	// Carreguem les condicions numèriques.

	var OldPos=this.Posicio;
	this.MyComplement.NombreR.Condicions=this.DeterminarCondicionsNumeriques();	
	this.Posicio=OldPos;
	if (!this.PosicioFinal()) {
		this.Posicio=this.PosicioE();
		this.MyComplement.NombreE.Condicions=this.DeterminarCondicionsNumeriques();	
		this.Posicio=OldPos;
		this.Posicio=this.PosicioD();
		if (this.MyComplement.NombreR.MyNombre.Operacio==ELEVAR ||
			this.MyComplement.NombreR.MyNombre.Operacio==RADICAR ) {
			this.MyComplement.NombreD.Condicions=this.MyComplement.CondicionsNumeriquesExponents;
		} 
		else {	
			this.MyComplement.NombreD.Condicions=this.DeterminarCondicionsNumeriques();	
		}
		this.Posicio=OldPos;
	}
}

/************************************************************************************
*
* GENERADORBEWOOM --> CICLE GENERADOR --> COMPLETACIÓ --> CICLE COMPLETACIÓ
* --> GESTIONAR NODE --> Determinar Condicions Numèriques
*
************************************************************************************/

Arbre.prototype.DeterminarCondicionsNumeriques = function() {
	// Determina les condicions que poden tenir els valors numèrics d'aquesta posició.
	if (this.Nodes[this.Posicio].Nombre.EsOperacio()) {
		if (this.PosicioInicial()) return (this.DeterminarCondicionsNumeriquesResultatFinal());
		else return (this.DeterminarCondicionsNumeriquesResultatParcial());
	}
	else return (this.DeterminarCondicionsNumeriquesNombresAleatoris());
}

Arbre.prototype.DeterminarCondicionsNumeriquesResultatFinal = function() {	
	if (MyGenerador.Items[3].Items[1].Valor==0) 
		return (this.DeterminarCondicionsNumeriquesResultatParcial());
	if (MyGenerador.Items[3].Items[1].Valor==1) 
		return (MyGenerador.Items[3].Items[1].Items[1]);	// Resultat final
	BUGEnDeterminarCondicionsNumeriquesResultatFinal();
}

Arbre.prototype.DeterminarCondicionsNumeriquesResultatParcial = function() {
	if (MyGenerador.Items[2].Items[1].Valor==0) return (MyGenerador.Items[1]);	// Nombres aleatoris
	if (MyGenerador.Items[2].Items[1].Valor==1) return (MyGenerador.Items[2].Items[1].Items[1]);// Resultats parcials
	BUGEnDeterminarCondicionsNumeriquesResultatParcial();
}

Arbre.prototype.DeterminarCondicionsNumeriquesNombresAleatoris = function() {
	return(MyGenerador.Items[1]);
}

/************************************************************************************
*
* GENERADORBEWOOM --> CICLE GENERADOR --> COMPLETACIÓ --> CICLE COMPLETACIÓ
* --> GESTIONAR NODE --> DESCARREGAR NODE
*
************************************************************************************/

Arbre.prototype.DescarregarNode= function() {
	this.Nodes[this.Posicio].Nombre.Tipus=this.MyComplement.NombreR.MyNombre.Tipus;
	this.Nodes[this.Posicio].Nombre.Num=this.MyComplement.NombreR.MyNombre.Num;
	this.Nodes[this.Posicio].Nombre.Den=this.MyComplement.NombreR.MyNombre.Den;
	this.Nodes[this.Posicio].Nombre.Dec=this.MyComplement.NombreR.MyNombre.Dec;
	this.Nodes[this.Posicio].Nombre.NDecimalsPrecisio=this.MyComplement.NombreR.MyNombre.NDecimalsPrecisio;
	this.Nodes[this.Posicio].Nombre.Contingut=this.MyComplement.NombreR.MyNombre.Contingut;
	
	if (!this.PosicioFinal()) {
		this.Nodes[this.PosicioD()].Nombre.Tipus=this.MyComplement.NombreD.MyNombre.Tipus;
		this.Nodes[this.PosicioD()].Nombre.Num=this.MyComplement.NombreD.MyNombre.Num;
		this.Nodes[this.PosicioD()].Nombre.Den=this.MyComplement.NombreD.MyNombre.Den;
		this.Nodes[this.PosicioD()].Nombre.Dec=this.MyComplement.NombreD.MyNombre.Dec;
		this.Nodes[this.PosicioD()].Nombre.NDecimalsPrecisio=this.MyComplement.NombreD.MyNombre.NDecimalsPrecisio;
		this.Nodes[this.PosicioD()].Nombre.Contingut=this.MyComplement.NombreD.MyNombre.Contingut;
	
		this.Nodes[this.PosicioE()].Nombre.Tipus=this.MyComplement.NombreE.MyNombre.Tipus;
		this.Nodes[this.PosicioE()].Nombre.Num=this.MyComplement.NombreE.MyNombre.Num;
		this.Nodes[this.PosicioE()].Nombre.Den=this.MyComplement.NombreE.MyNombre.Den;
		this.Nodes[this.PosicioE()].Nombre.Dec=this.MyComplement.NombreE.MyNombre.Dec;
		this.Nodes[this.PosicioE()].Nombre.NDecimalsPrecisio=this.MyComplement.NombreE.MyNombre.NDecimalsPrecisio;
		this.Nodes[this.PosicioE()].Nombre.Contingut=this.MyComplement.NombreE.MyNombre.Contingut;
	}
}

/************************************************************************************
*
* GENERADORBEWOOM --> CICLE GENERADOR --> COMPLETACIÓ --> CICLE COMPLETACIÓ
* --> TEST BRANCA ACCEPTABLE
*
************************************************************************************/

Arbre.prototype.TestBrancaAcceptable= function(){
	if (MyGenerador.Items[5].Items[4].Valor==1) {				// Evitar Operacions cancel.ladores
		if (this.TestOperacionsCancelladores()) return (false);
	}
	return (true);
}

Arbre.prototype.TestOperacionsCancelladores = function () {
	// Retorna true si la branca actual es pot escriure com algo+3-3 o algo*3/3...
	// retorna false si no s'han trobat.
	if (this.PosicioFinal()) return (false);
	if (this.TestOperacionsCancelladoresDreta()) return (true);
	if (this.TestOperacionsCancelladoresEsquerra()) return (true);	
	return (false);
}
Arbre.prototype.TestOperacionsCancelladoresDreta = function () {
	// Retorna true si la branca actual es pot escriure com algo + 3 - 3
	if (!this.PosicioFinalPos(this.PosicioD())) return (false);
	var Op=this.Operacio();
	if (Op==ELEVAR || Op==RADICAR) return (false);
	var OpInversa=this.DeterminarOperacioInversa(Op);
	var PosicioActual=this.Posicio;
	var PosicioNombre=this.PosicioD();
	this.Posicio=this.PosicioE();
	var Resultat=this.DetectarOperacioEnBranca(OpInversa,PosicioNombre);
	this.Posicio=PosicioActual;
	return (Resultat);
}
Arbre.prototype.TestOperacionsCancelladoresEsquerra = function () {
	// Retorna true si la branca actual es pot escriure com 3 - (algo+3)
	if (!this.PosicioFinalPos(this.PosicioE())) return (false);
	var Op=this.Operacio();
	if (Op==ELEVAR || Op==RADICAR) return (false);
	var OpInversa=this.DeterminarOperacioInversa(Op);
	var PosicioActual=this.Posicio;
	var PosicioNombre=this.PosicioE();
	this.Posicio=this.PosicioD();
	var Resultat=this.DetectarOperacioEnBranca(OpInversa,PosicioNombre);
	this.Posicio=PosicioActual;
	return (Resultat);
}
Arbre.prototype.DeterminarOperacioInversa = function (Operacio) {
	// Determina la operacio inversa, Operacio * Operacio Inversa = 1
	if (Operacio==SUMAR) return (RESTAR);
	if (Operacio==RESTAR) return (SUMAR);
	if (Operacio==MULTIPLICAR) return (DIVIDIR);
	if (Operacio==DIVIDIR) return (MULTIPLICAR);
	if (Operacio==ELEVAR) return (RADICAR);
	if (Operacio==RADICAR) return (ELEVAR);
	BugArbrePrototypeDeterminarOperacioInversa();
}

/************************************************************************************
*
* GENERADORBEWOOM --> CICLE GENERADOR --> COMPLETACIÓ --> CICLE COMPLETACIÓ
* --> TEST BRANCA ACCEPTABLE --> Detectar Operació en Branca
*
************************************************************************************/

Arbre.prototype.DetectarOperacioEnBranca = function(Operacio,PosicioNombre) {
	// Detecta si la branca actual es pot escriure com "Algo * Operacio * Nombre"
	if (Operacio==SUMAR) return (this.DetectarOperacioEnBrancaSumar(PosicioNombre));
	if (Operacio==RESTAR) return (this.DetectarOperacioEnBrancaRestar(PosicioNombre));
	if (Operacio==MULTIPLICAR) return (this.DetectarOperacioEnBrancaMultiplicar(PosicioNombre));
	if (Operacio==DIVIDIR) return (this.DetectarOperacioEnBrancaDividir(PosicioNombre));
	Alert ("Bug en Arbre.prototype.DetectarOperacioEnBranca");
	ja();
}	

Arbre.prototype.DetectarOperacioEnBrancaSumar = function(PosicioNombre) {
	// Determina recursivament si la branca actual es pot escriure com Algo + Nombre
	if (this.Operacio()==SUMAR) {
		if (this.PosicioFinalPos(this.PosicioD())) {
			if (this.ValorsIgualsAbsoluts(this.PosicioD(),PosicioNombre)) {
				return (true);
			}
		}
		if (this.PosicioFinalPos(this.PosicioE())) {
			if (this.ValorsIgualsAbsoluts(this.PosicioE(),PosicioNombre)) {
				return (true);
			}
		}
		
		// Mirem recursivament dintre de la branca.
		var PosicioActual=this.Posicio;
		this.Posicio=this.PosicioD();
		if (this.DetectarOperacioEnBrancaSumar(PosicioNombre)) return (true);
		this.Posicio=PosicioActual;
		this.Posicio=this.PosicioE();
		if (this.DetectarOperacioEnBrancaSumar(PosicioNombre)) return (true);
		return (false);
	}
	if (this.Operacio()==RESTAR) {
		// Mirem només en la part esquerra. 
		// Es podria mirar també en la dreta per a detectar expressions com 
		//   4 -( 5 -3) +3  , on es repeteix el "+3", però no és aquest
		// l'objectiu d'aquest filtre
		var PosicioActual=this.Posicio;	
		this.Posicio=this.PosicioE();
		return (this.DetectarOperacioEnBrancaSumar(PosicioNombre));
	}
	return (false);
}

Arbre.prototype.DetectarOperacioEnBrancaRestar = function(PosicioNombre) {
	// Determina recursivament si la branca actual es pot escriure com Algo + Nombre
	if (this.Operacio()==RESTAR) {
		if (this.PosicioFinalPos(this.PosicioD())) {
			if (this.ValorsIgualsAbsoluts(this.PosicioD(),PosicioNombre)) {
				return (true);
			}
		}
		// Mirem només en la part esquerra. 
		var PosicioActual=this.Posicio;	
		this.Posicio=this.PosicioE();
		return (this.DetectarOperacioEnBrancaRestar(PosicioNombre));
	}
	if (this.Operacio()==SUMAR) {
		// Mirem recursivament dintre de la branca.
		var PosicioActual=this.Posicio;
		this.Posicio=this.PosicioD();
		if (this.DetectarOperacioEnBrancaRestar(PosicioNombre)) return (true);
		this.Posicio=PosicioActual;
		this.Posicio=this.PosicioE();
		if (this.DetectarOperacioEnBrancaRestar(PosicioNombre)) return (true);
		return (false);
	}
	return (false);
}

Arbre.prototype.DetectarOperacioEnBrancaMultiplicar = function(PosicioNombre) {
	// Determina recursivament si la branca actual es pot escriure com Algo * Nombre
	if (this.Operacio()==MULTIPLICAR) {
		if (this.PosicioFinalPos(this.PosicioD())) {
			if (this.ValorsIgualsAbsoluts(this.PosicioD(),PosicioNombre)) {
				return (true);
			}
		}
		if (this.PosicioFinalPos(this.PosicioE())) {
			if (this.ValorsIgualsAbsoluts(this.PosicioE(),PosicioNombre)) {
				return (true);
			}
		}
		
		// Mirem recursivament dintre de la branca.
		var PosicioActual=this.Posicio;
		this.Posicio=this.PosicioD();
		if (this.DetectarOperacioEnBrancaMultiplicar(PosicioNombre)) return (true);
		this.Posicio=PosicioActual;
		this.Posicio=this.PosicioE();
		if (this.DetectarOperacioEnBrancaMultiplicar(PosicioNombre)) return (true);
		return (false);
	}
	if (this.Operacio()==DIVIDIR) {
		// Mirem només en la part esquerra. 
		// Es podria mirar també en la dreta per a detectar expressions com 
		//   4 -( 5 -3) +3  , on es repeteix el "+3", però no és aquest
		// l'objectiu d'aquest filtre
		var PosicioActual=this.Posicio;	
		this.Posicio=this.PosicioE();
		return (this.DetectarOperacioEnBrancaMultiplicar(PosicioNombre));
	}
	return (false);
}

Arbre.prototype.DetectarOperacioEnBrancaDividir = function(PosicioNombre) {
	// Determina recursivament si la branca actual es pot escriure com Algo / Nombre
	if (this.Operacio()==DIVIDIR) {
		if (this.PosicioFinalPos(this.PosicioD())) {
			if (this.ValorsIgualsAbsoluts(this.PosicioD(),PosicioNombre)) {
				return (true);
			}
		}
		// Mirem només en la part esquerra. 
		var PosicioActual=this.Posicio;	
		this.Posicio=this.PosicioE();
		return (this.DetectarOperacioEnBrancaDividir(PosicioNombre));
	}
	if (this.Operacio()==MULTIPLICAR) {
		// Mirem recursivament dintre de la branca.
		var PosicioActual=this.Posicio;
		this.Posicio=this.PosicioD();
		if (this.DetectarOperacioEnBrancaMultiplicar(PosicioNombre)) return (true);
		this.Posicio=PosicioActual;
		this.Posicio=this.PosicioE();
		if (this.DetectarOperacioEnBrancaMultiplicar(PosicioNombre)) return (true);
		return (false);
	}
	return (false);
}

/************************************************************************************
*
* GENERADORBEWOOM --> CICLE GENERADOR --> COMPLETACIÓ --> CONFIGURADOR
*
************************************************************************************/

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT
*
************************************************************************************/

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> CONDICIONS NUMÈRIQUES
*
************************************************************************************/

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> CONDICIONS NUMÈRIQUES --> CONSTRUCTOR
*
************************************************************************************/

function CondicionsNumeriques(Aqui,TheCodiNom) {
	Formulari.call(this,Aqui,TheCodiNom);
	this.Items[1]=new EntradaTrueFalse(Aqui+"Items[1].","BEWOOM6");		// 1 Negatius acceptats
	this.Items[2]=new EntradaTrueFalse(Aqui+"Items[2].","BEWOOM7");		// 2 Evitar el valor zero
	this.Items[2].Valor=1;
	this.Items[3]=new EntradaSelector(Aqui+"Items[3].","BEWOOM2");		// 3 Tipus de nombre	
	this.Items[3].Valor=1;
	this.Items[3].AfegirNomOpcio(0);					// (buit, comença en 1)
	//
	// Condicions per als nombres enters
	//
	this.Items[3].AfegirNomOpcio("BEWOOM3");								// 3.1 Enter
	this.Items[3].Items[1]=new EntradaEnter(Aqui+"Items[3].Items[1].","BEWOOM8");				// 3.1 Valor màxim
	this.Items[3].Items[1].ValorMinim=5;
	this.Items[3].Items[1].Valor=100;
	//
	// Condicions per a les fraccions.
	//
	this.Items[3].AfegirNomOpcio("BEWOOM4");								// 3.2 Fracció
	this.Items[3].Items[2]=new Formulari(Aqui+"Items[3].Items[2].",0)
	this.Items[3].Items[2].Items[1]=new EntradaEnter(Aqui+"Items[3].Items[2].Items[1].","BEWOOM9");		// 3.2 Valor màxim numeradors
	this.Items[3].Items[2].Items[1].ValorMinim=5;
	this.Items[3].Items[2].Items[1].Valor=100;
	this.Items[3].Items[2].Items[2]=new EntradaEnter(Aqui+"Items[3].Items[2].Items[2].","BEWOOM10");	// 3.2 Valor màxim denominadors
	this.Items[3].Items[2].Items[2].ValorMinim=5;
	this.Items[3].Items[2].Items[2].Valor=100;
	this.Items[3].Items[2].Items[3]=new EntradaSelector(Aqui+"Items[3].Items[2].Items[3].","BEWOOM11");	// Limitació factorizació denominadors
	this.Items[3].Items[2].Items[3].AfegirNomOpcio(0);	// (opció 0 buida)
	this.Items[3].Items[2].Items[3].AfegirNomOpcio("BEWOOM13");	// Si (per defecte)
	this.Items[3].Items[2].Items[3].AfegirNomOpcio("BEWOOM14");	// No
	this.Items[3].Items[2].Items[3].Items[2]=new EntradaEnter(Aqui+"Items[3].Items[2].Items[3].Items[2].","BEWOOM12");// Màxim factor primer
	this.Items[3].Items[2].Items[3].Items[2].ValorMinim=1;
	this.Items[3].Items[2].Items[3].Items[2].Valor=5;
	//
	// Condicions per als nombres decimals.
	//
	this.Items[3].AfegirNomOpcio("BEWOOM5");							// 3.3 Decimal
	this.Items[3].Items[3]=new Formulari(Aqui+"Items[3].Items[3].",0)
	this.Items[3].Items[3].Items[1]=new EntradaEnter(Aqui+"Items[3].Items[3].Items[1].","BEWOOM15");// Nombre de xifres decimals
	this.Items[3].Items[3].Items[1].Valor=2;
	this.Items[3].Items[3].Items[2]=new EntradaEnter(Aqui+"Items[3].Items[3].Items[2].","BEWOOM8"); // Valor màxim (del nombre decimal)
	this.Items[3].Items[3].Items[2].ValorMinim=5;
	this.Items[3].Items[3].Items[2].Valor=100;
	//
	// Altres
	//
	this.NoTestValorAcceptable=false;
	this.EvitarDenominadorUnitat=true;
}
CondicionsNumeriques.prototype = new Formulari();

CondicionsNumeriques.prototype.NomesNaturals= function() {
	// Retorna True si només nombres enters no negatius
	if (this.Items[3].Valor==1 && this.Items[1].Valor==0) return (true);
	else return (false);
}

CondicionsNumeriques.prototype.IniciarPerCodi = function (CadenaCodi) {
	var CodiBinari=ConvertirBase32ABinari(CadenaCodi);
	this.Items[1].CarregarValorDeCadenaBinari(CodiBinari,0);
	this.Items[2].CarregarValorDeCadenaBinari(CodiBinari,1);
	this.Items[3].CarregarValorDeCadenaBinari(CodiBinari,2,2);
	this.Items[3].Items[1].CarregarValorDeCadenaBinari(CodiBinari,4,10);
	this.Items[3].Items[2].Items[1].CarregarValorDeCadenaBinari(CodiBinari,14,10);
	this.Items[3].Items[2].Items[2].CarregarValorDeCadenaBinari(CodiBinari,24,10);
	this.Items[3].Items[2].Items[3].CarregarValorDeCadenaBinari(CodiBinari,34,2);
	this.Items[3].Items[2].Items[3].Items[2].CarregarValorDeCadenaBinari(CodiBinari,36,7);
	this.Items[3].Items[3].Items[2].CarregarValorDeCadenaBinari(CodiBinari,43,10);
	this.Items[3].Items[3].Items[1].CarregarValorDeCadenaBinari(CodiBinari,53,4);
}

CondicionsNumeriques.prototype.GenerarCodi = function () {
	var Text="";
	Text+=this.Items[1].OutputBinari();
	Text+=this.Items[2].OutputBinari();
	Text+=this.Items[3].OutputBinari(2);
	Text+=this.Items[3].Items[1].OutputBinari(10);
	Text+=this.Items[3].Items[2].Items[1].OutputBinari(10);
	Text+=this.Items[3].Items[2].Items[2].OutputBinari(10);
	Text+=this.Items[3].Items[2].Items[3].OutputBinari(2);
	Text+=this.Items[3].Items[2].Items[3].Items[2].OutputBinari(7);
	Text+=this.Items[3].Items[3].Items[2].OutputBinari(10);
	Text+=this.Items[3].Items[3].Items[1].OutputBinari(4);
	var Codi32=ConvertirBinariABase32(Text);
	return(Codi32);
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> NOMBRE ALEATORI
*
************************************************************************************/

function NombreAleatori() {
	this.MyNombre=new Nombre();
	this.Condicions= new CondicionsNumeriques(0,"No definit");
	this.NombresPrimers=[1,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,
			71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151];
}

NombreAleatori.prototype.Negativitzar = function () {
	// Si la funció permet negatius, canvia a l'atzar el valor a negatiu.
	if (this.Condicions.Items[1].Valor==0) return;
	if (Math.random()<0.5) return;
	if (this.MyNombre.Tipus==1 || this.MyNombre.Tipus==2) {
		this.MyNombre.Num=-this.MyNombre.Num;
		return;
	}
	if (this.MyNombre.Tipus==3) {
		this.MyNombre.Dec=-this.MyNombre.Dec;
		return;
	}
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> NOMBRE ALEATORI --> GENERACIÓ
*
************************************************************************************/

NombreAleatori.prototype.GenerarNombreAleatoriGeneral = function() {
	if (this.Condicions.Items[3].Valor==NOMBRE_ENTER)  
		return (this.GenerarNombreAleatoriEnter());
	if (this.Condicions.Items[3].Valor==NOMBRE_FRACCIO) 
		return(this.GenerarNombreAleatoriFraccio());
	if (this.Condicions.Items[3].Valor==NOMBRE_DECIMAL) 
		return(this.GenerarNombreAleatoriDecimal());
	LogError("NombreAleatori.prototype.GenerarNombreAleatoriGeneral");
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> NOMBRE ALEATORI --> GENERACIÓ --> ENTERS
*
************************************************************************************/

NombreAleatori.prototype.GenerarNombreAleatoriEnter = function() {
	//Genera un nombre aleatori enter. Retorna Status
	var Minim=0;
	if (this.Condicions.Items[2].Valor==1) Minim=1; 
	var Maxim=this.Condicions.Items[3].Items[1].Valor;
	var Valor=GenerarEnterAleatoriAcotat(Minim,Maxim);
	this.MyNombre.InEnter(Valor);
	this.Negativitzar();
	if (this.TestValorAcceptable()==true) return (STATUS_FET_OK);
	return (STATUS_ALEATORI_NO_VALID_GENERAL);
}

NombreAleatori.prototype.GenerarNombreAleatoriEnterInterval= function(Inici,Final) {
	// Genera un nombre enter aleatori [inici,final]
	// Accepta nombres negatius. Retorna Status
	var Rang=0;
	var Valor;
	if (Final<Inici) {
		Rang=Final;
		Final=Inici;
		Inici=Rang;
	}
	Rang=Final-Inici;
	Valor=Inici+GenerarEnterAleatoriAcotat(0,Rang);
	this.MyNombre.InEnter(Valor);
	if (this.TestValorAcceptable()==true) return (STATUS_FET_OK);
	return (STATUS_ALEATORI_NO_VALID_ESPECIAL);
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> NOMBRE ALEATORI --> GENERACIÓ --> ENTERS --> DIVISORS
*
************************************************************************************/

NombreAleatori.prototype.GenerarEnterAleatoriDivisorDe = function (n) {
	// Intenta generar un nombre aleatori que sigui divisor de n.
	// Retorna STATUS_ALEATORI_IMPOSSIBLE si no ha pogut (n=0, n=1 o n=primer)
	// Retorna STATUS_FET_OK si ha pogut.
	var Divisor=this.DivisorAleatori(n);
	if (Divisor==1) return (STATUS_ALEATORI_IMPOSSIBLE);
	if (this.Condicions.Items[1].Valor==1) {
		if (Math.random()>0.5) Divisor=-Divisor;
	}	
	this.MyNombre.InEnter(Divisor);
	if (this.TestValorAcceptable()) return (STATUS_FET_OK);
	else return (STATUS_ALEATORI_NO_VALID_ESPECIAL);	
}

NombreAleatori.prototype.DivisorAleatori = function(n) {
	//Genera un divisor aleatori de n
	//Retorna 1 si no ha pogut.
	if (n>=0) var Valor=n;
	else var Valor=-n;
	if (Valor==1 || Valor==2 || Valor==3) return (1);
	//En primer lloc comptem tots els divisors no trivials
	NombreDivisors=this.ComptarDivisors(Valor);
	//Si el nombre és primer tornem
	if (NombreDivisors==0) return (1);

	//Escollim un a l'atzar.
	var DivisorEscollit=GenerarEnterAleatoriAcotat(1,NombreDivisors);

	//El localitzem
	DivisorsComptats=0;
	for (var i=2;i<=Valor/2;i++) {
		if (Valor % i == 0) {
			DivisorsComptats=DivisorsComptats+1;
			if (DivisorsComptats==DivisorEscollit) return (i);
		}
	}
	return (1); //Mai hauria d'arribar aqui...
}

NombreAleatori.prototype.ComptarDivisors = function (m) {
	//Retorna el nombre de divisors no trivials de m
	if (m<0) m=-m;
	if (m==0 || m==1 || m==2 || m==3) return (0);
	var DivisorsComptats=0;
	for (var i=2;i<=m/2;i++) if (m % i == 0) DivisorsComptats=DivisorsComptats+1;
	return (DivisorsComptats);
}		

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> NOMBRE ALEATORI --> GENERACIÓ --> ENTERS --> MÚLTIPLES
*
************************************************************************************/

NombreAleatori.prototype.GenerarEnterAleatoriMultipleDe =function (n) {
	// Genera nombre aleatori x tal que x*n < valor màxim
	// Retorna STATUS_ALEATORI_IMPOSSIBLE si no ha pogut (n=0)
	// Retorna STATUS_FET_OK si ha pogut.
	if (n==0) return (STATUS_ALEATORI_IMPOSSIBLE);
	var Valor=n;
	if (n<0) Valor=-n; 
	var MaximMultiple=Math.floor(this.Condicions.Items[3].Items[1].Valor/Valor);	
	if (MaximMultiple<2) return (STATUS_ALEATORI_IMPOSSIBLE);
	var MultipleEscollit=GenerarEnterAleatoriAcotat(2,MaximMultiple);
	if (this.Condicions.Items[1].Valor==1) {
		if (Math.random()>0.5) MultipleEscollit=-MultipleEscollit;
	}	
	this.MyNombre.InEnter(MultipleEscollit);	
	if (this.TestValorAcceptable()) return (STATUS_FET_OK);
	else return (STATUS_ALEATORI_NO_VALID_ESPECIAL);
}
	
/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> NOMBRE ALEATORI --> GENERACIÓ --> FRACCIONS
*
************************************************************************************/

NombreAleatori.prototype.GenerarNombreAleatoriFraccio = function() {
	//Genera un nombre aleatori fracció
	var ValorMinim=0;
	if (this.Condicions.Items[2].Valor==1) ValorMinim=1;
	var DenominadorMinim=1;
	if (this.Condicions.EvitarDenominadorUnitat) DenominadorMinim=2;
	
	var NombreAleatoriNumerador=GenerarEnterAleatoriAcotat(ValorMinim,this.Condicions.Items[3].Items[2].Items[1].Valor);
	
	if (this.Condicions.Items[3].Items[2].Items[3].Valor==2)   
		var NombreAleatoriDenominador=GenerarEnterAleatoriAcotat(DenominadorMinim,this.Condicions.Items[3].Items[2].Items[2].Valor);
	else var NombreAleatoriDenominador=this.GenerarEnterAleatoriMaximFactorPrimer(this.Condicions.Items[3].Items[2].Items[3].Items[2].Valor,this.Condicions.Items[3].Items[2].Items[2].Valor);
	
	if (this.Condicions.Items[1].Valor==1) {
		if (Math.random()>0.5) NombreAleatoriNumerador=-NombreAleatoriNumerador;
	}
	this.MyNombre.InFraccio(NombreAleatoriNumerador,NombreAleatoriDenominador,true);

	if (this.TestValorAcceptable()) return (STATUS_FET_OK);
	else return (STATUS_ALEATORI_NO_VALID_GENERAL);
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> NOMBRE ALEATORI --> GENERACIÓ --> FRACCIONS --> FACTORS PRIMERS
*
************************************************************************************/

NombreAleatori.prototype.GenerarEnterAleatoriMaximFactorPrimer = function (PrimerMaxim,ValorMaxim) {
	// Genera un nombre enter amb una descomposició en factors sense cap 
	// factor superior al primer número MaximPrimer
	// i amb valor <= ValorMaxim
	var Factor;
	if (ValorMaxim<0) ValorMaxim=-ValorMaxim;
	if (ValorMaxim<=1) return (1);
	var Valor=1;
	while (Valor<ValorMaxim) {
		Factor=this.NombrePrimerAleatori(3);
		Valor=Valor*Factor;
	}
	if (Valor>ValorMaxim) Valor=Valor/Factor;
	return (Valor);
}

NombreAleatori.prototype.NombrePrimerAleatori = function (PrimerMaxim) {
	// Genera un nombre primer aleatori <= al primer # PrimerMaxim
	// PrimerMaxim 1 --> 2 PrimerMaxim 2 --> 3 ...
	if (PrimerMaxim>this.NombresPrimers.length) PrimerMaxim=this.NombresPrimers.length;
	var n=GenerarEnterAleatoriAcotat(1,PrimerMaxim);
	return (this.NombresPrimers[n]);
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> NOMBRE ALEATORI --> GENERACIÓ --> POTÈNCIES
*
************************************************************************************/

NombreAleatori.prototype.GenerarExponentEnterAleatori = function(){
	// Genera un valor enter com a exponent d'una potència.
	// Retorna false si no s'ha pogut.	
	var Exponent=GenerarEnterAleatoriAcotat(2, this.Condicions.Items[3].Items[1].Valor);
	this.MyNombre.InEnter(Exponent);
	if (this.TestValorAcceptable()) return (STATUS_FET_OK);
	else return (STATUS_ALEATORI_NO_VALID_ESPECIAL);}

NombreAleatori.prototype.GenerarBaseEnteraAleatoria = function (ValorMaximResultat,Exponent) {
	// Genera una base aleatòria de forma que n^Exponent < ValorMaximResultat
	// Exponent un nombre enter positiu.
	var Base=this.GenerarBaseEnteraPositivaAleatoria(ValorMaximResultat,Exponent); 
	if (Base==0) return (false);
	this.MyNombre.InEnter(Base);
	this.Negativitzar();
	if (this.TestValorAcceptable()) return (STATUS_FET_OK);
	else return (STATUS_ALEATORI_NO_VALID_ESPECIAL);}

NombreAleatori.prototype.GenerarBaseFraccioAleatoria = function (ValorMaximNumerador,ValorMaximDenominador,Exponent) {
	// Genera una base aleatòria de forma que a^Exponent < ValorMaximNumerador,
	// b^Exponent < ValorMaximDenominador 
	// Exponent un nombre enter positiu.
	var BaseNum=this.GenerarBaseEnteraPositivaAleatoria(ValorMaximNumerador,Exponent); 
	if (BaseNum==0) return (false);
	var BaseDen=this.GenerarBaseEnteraPositivaAleatoria(ValorMaximDenominador,Exponent); 
	if (BaseDen==0) return (false);
	this.MyNombre.InFraccio(BaseNum,BaseDen,true);
	this.Negativitzar();
	if (this.TestValorAcceptable()) return (STATUS_FET_OK);
	else return (STATUS_ALEATORI_NO_VALID_ESPECIAL);}

NombreAleatori.prototype.GenerarBaseEnteraPositivaAleatoria = function (ValorMaximResultat,Exponent) {
	// Genera una base positiva entera aleatòria n,
	// de forma que n^Exponent < ValorMaximResultat
	// i n >= 2.
	// Exponent un nombre enter positiu.
	// Retorna 0 si no ha pogut.
	var ValorMaximBase=Math.pow(ValorMaximResultat,1/Exponent);
	if (ValorMaximBase==NaN) return (0);
	if (ValorMaximBase<2) return (0);
	var Base=GenerarEnterAleatoriAcotat(2,Math.floor(ValorMaximBase));	
	return (Base);
}
NombreAleatori.prototype.GenerarBaseDecimalAleatoria = function (ValorMaximResultat,Exponent) {
	// Genera una base aleatòria decimal de forma que n^Exponent < ValorMaxim
	// Exponent un nombre enter positiu.
	// Amb aquesta rutina ens arrisquem a que la part decimal que afegim pugui fer passar 
	// el valor màxim...
	var Base=this.GenerarBaseEnteraPositivaAleatoria(ValorMaximResultat,Exponent); 
	if (Base==0) return (false);
	this.MyNombre.InDecimal(Base+this.GenerarPartDecimal(this.Condicions.Items[3].Items[3].Items[1].Valor));
	this.Negativitzar();
	if (this.TestValorAcceptable()) return (STATUS_FET_OK);
	else return (STATUS_ALEATORI_NO_VALID_ESPECIAL);
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> NOMBRE ALEATORI --> GENERACIÓ --> DECIMALS
*
************************************************************************************/

NombreAleatori.prototype.GenerarNombreAleatoriDecimal = function() {
	// Intenta genera un nombre aleatori decimal, i testea si és vàlid.
	var Valor=this.GenerarNombreAleatoriDecimalAcotat(this.Condicions.Items[3].Items[3].Items[2].Valor,this.Condicions.Items[3].Items[3].Items[1].Valor);
  	this.MyNombre.InDecimal(Valor,this.Condicions.Items[3].Items[3].Items[1].Valor);
	this.Negativitzar();
	if (this.TestValorAcceptable()) return (STATUS_FET_OK);
	else return (STATUS_ALEATORI_NO_VALID_GENERAL);
}

NombreAleatori.prototype.GenerarNombreAleatoriDecimalAcotat = function(ValorMaxim,NDecimals) {
	// Intenta genera un nombre aleatori decimal acotat
    	var PartEntera = GenerarEnterAleatoriAcotat(0,ValorMaxim-1);
	var PartDecimal=this.GenerarPartDecimal(NDecimals);
	return (PartEntera + PartDecimal);	
}

NombreAleatori.prototype.GenerarPartDecimal = function(NDecimals) {
	// Genera un nombre aleatori < 1 amb NDecimals xifres decimals
	var PartDecimal = Math.round(Math.random() * Math.pow(10 ,NDecimals));
    	PartDecimal = PartDecimal / Math.pow(10 ,NDecimals);
	return (PartDecimal);	
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> NOMBRE ALEATORI --> GENERACIÓ --> TEST VALOR ACCEPTABLE
*
************************************************************************************/

NombreAleatori.prototype.TestValorAcceptable = function(){
	// Retorna false si el nombre aleatori actual no compleix les condicions.
	if (this.Condicions.NoTestValorAcceptable) return (true);
	if (this.Condicions.Items[1].Valor==0) {
		if (this.MyNombre.ValorNumeric()<0) return (false);
	}	
	if (this.Condicions.Items[2].Valor==1) {
		if (this.MyNombre.EsZero()) return (false);
	}	
	if (this.Condicions.Items[3].Valor==NOMBRE_ENTER)   return (this.TestValorAcceptableEnter());
	if (this.Condicions.Items[3].Valor==NOMBRE_FRACCIO) return (this.TestValorAcceptableFraccio());
	if (this.Condicions.Items[3].Valor==NOMBRE_DECIMAL) return (this.TestValorAcceptableDecimal());
	return (false);
}

NombreAleatori.prototype.TestValorAcceptableEnter = function(){
	if (this.MyNombre.Tipus!=1) return (false);
	if (Math.abs(this.MyNombre.ValorNumeric())>this.Condicions.Items[3].Items[1].Valor) return (false);
	return (true);
}

NombreAleatori.prototype.TestValorAcceptableFraccio = function(){
	if (this.MyNombre.Tipus!=1 && this.MyNombre.Tipus!=2) return (false);
	if (this.MyNombre.Den==0) return (false);
	if (this.Condicions.EvitarDenominadorUnitat) {
		if (Math.abs(this.MyNombre.Den)==1) return (false);	
	}
	if (Math.abs(this.MyNombre.Num)>this.Condicions.Items[3].Items[2].Items[1].Valor) return (false);	
	if (Math.abs(this.MyNombre.Den)>this.Condicions.Items[3].Items[2].Items[2].Valor) return (false);	

	if (this.Condicions.Items[3].Items[2].Items[3].Valor==1) { 
		if (!this.TestLimitacioFactorPrimerFraccio()) return (false);
	}
	return (true);
}

NombreAleatori.prototype.TestValorAcceptableDecimal = function () {
	if (Math.abs(this.MyNombre.ValorNumeric())>this.Condicions.Items[3].Items[3].Items[2].Valor) return (false);
	return (true);
	
}

NombreAleatori.prototype.TestLimitacioFactorPrimerFraccio = function() {
	// Comprova si la factorització del denominador de la fracció no tingui cap factor
	// > this.Condicions.PrimerMaxim
	var NombreDeFactors=1;
	var PrimerMesGran=0;
	var n=this.MyNombre.Den;
	if (n<0) n=-n;
	if (n==0) return (false); // No pot ser...
	while (n!=1) {
		PrimerMesGran=PrimerMesGran+1;
		if (PrimerMesGran>this.Condicions.Items[3].Items[2].Items[3].Items[2].Valor) return (false);
		while (n % this.NombresPrimers[PrimerMesGran]==0) {
			n= n / this.NombresPrimers[PrimerMesGran];
			NombreDeFactors=NombreDeFactors+1;
		}
	}
	return (true);
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> CONSTRUCTOR I VARIABLES
*
************************************************************************************/

function Complement() {
	this.NombreD=new NombreAleatori();
	this.NombreE=new NombreAleatori();
	this.NombreR=new NombreAleatori();
	this.MyCalculadora=new Calculadora();
	this.Status=STATUS_NO_FET; //Resultat de la complementació

	/////////////////////////////////////////////////////////////////////////////
	//
	// CONDICIONS NODE
	//
	/////////////////////////////////////////////////////////////////////////////

	this.EvitarMultiplicarPer1=true;// Evita multiplicacions pel nombre 1 <-- No opcional
	this.EvitarDividirEntre1=true; 	// Evita divisions a/1 (amb nombre 1) <-- No opcional
	this.EvitarMultiplicarPer0=true;// Evita multiplicacions pel nombre 0 <-- No opcional

	/////////////////////////////////////////////////////////////////////////////
	//
	// CONDICIONS NOMBRES
	//
	/////////////////////////////////////////////////////////////////////////////

	this.CondicionsNumeriquesNombresAleatoris= new CondicionsNumeriques(1);

	this.CondicionsNumeriquesResultatsParcials= new CondicionsNumeriques(2);
	this.CondicionsNumeriquesResultatsParcials.Items[3].Items[3].Items[1].Invisible=true;

	this.CondicionsNumeriquesResultatFinal= new CondicionsNumeriques(3);
	this.CondicionsNumeriquesResultatFinal.Items[3].Items[3].Items[1].Invisible=true;

	this.CondicionsNumeriquesExponents= new CondicionsNumeriques(4);
	this.CondicionsNumeriquesExponents.Items[3].Valor=NOMBRE_ENTER;
	this.CondicionsNumeriquesExponents.Items[1].Valor=0;
	this.CondicionsNumeriquesExponents.Items[2].Valor=1;
	this.CondicionsNumeriquesExponents.NoTestValorAcceptable=true;
	this.CondicionsNumeriquesExponents.Items[3].Items[1].Valor=6;
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR
*
************************************************************************************/

Complement.prototype.Completar = function () {
	//Intenta completar l'operació NombreR = (NombreE)*(OperacioR)*(NombreD)	
	//I retorna Status
	this.Status=STATUS_NO_FET;
	if (this.NombreR.MyNombre.EsOperacio())	this.CompletarOperacio();
	else this.CompletarPosicioFinal();
	if (this.Status<0) return (this.Status);
	if (this.Status==STATUS_FET_OK) {
		if (!this.NombreR.MyNombre.EsOperacio()) return (STATUS_FET_OK);
		if (this.TestNodeAcceptable()) return (STATUS_FET_OK);
		return (STATUS_NO_VALID_NODE);
	}
	return (this.Status);
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Agafar resultats de la calculadora
*
************************************************************************************/

Complement.prototype.PassarResultatCalculadoraANombreE = function() {
	this.NombreE.MyNombre.Tipus=this.MyCalculadora.NombreR.Tipus;
	this.NombreE.MyNombre.Num=this.MyCalculadora.NombreR.Num;
	this.NombreE.MyNombre.Den=this.MyCalculadora.NombreR.Den;
	this.NombreE.MyNombre.Dec=this.MyCalculadora.NombreR.Dec;
	this.NombreE.MyNombre.NDecimalsPrecisio=this.MyCalculadora.NombreR.NDecimalsPrecisio;	
	this.NombreE.MyNombre.Contingut=this.MyCalculadora.NombreR.Contingut;
}
Complement.prototype.PassarResultatCalculadoraANombreD = function() {
	this.NombreD.MyNombre.Tipus=this.MyCalculadora.NombreR.Tipus;
	this.NombreD.MyNombre.Num=this.MyCalculadora.NombreR.Num;
	this.NombreD.MyNombre.Den=this.MyCalculadora.NombreR.Den;
	this.NombreD.MyNombre.Dec=this.MyCalculadora.NombreR.Dec;
	this.NombreD.MyNombre.NDecimalsPrecisio=this.MyCalculadora.NombreR.NDecimalsPrecisio;	
	this.NombreD.MyNombre.Contingut=this.MyCalculadora.NombreR.Contingut;
}
Complement.prototype.PassarResultatCalculadoraANombreR = function() {
	this.NombreR.MyNombre.Tipus=this.MyCalculadora.NombreR.Tipus;
	this.NombreR.MyNombre.Num=this.MyCalculadora.NombreR.Num;
	this.NombreR.MyNombre.Den=this.MyCalculadora.NombreR.Den;
	this.NombreR.MyNombre.Dec=this.MyCalculadora.NombreR.Dec;
	this.NombreR.MyNombre.NDecimalsPrecisio=this.MyCalculadora.NombreR.NDecimalsPrecisio;	
	this.NombreR.MyNombre.Contingut=this.MyCalculadora.NombreR.Contingut;
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Test de node acceptable
*
************************************************************************************/

Complement.prototype.TestNodeAcceptable = function() {
	// Comprova si el node fet per Completar és acceptable o no.
	// Retorna true/false
	if (this.EvitarMultiplicarPer1) {
		if (!this.TestEvitarMultiplicarPerNombre1()) return (false);
	}
	if (this.EvitarMultiplicarPer0) {
		if (!this.TestEvitarMultiplicarPerNombre0()) return (false);
	}
	if (MyGenerador.Items[5].Items[1].Valor==1) {
		if (this.SumesRestesFraccionsAmbMateixDenominador()) return (false);
	}
	if (MyGenerador.Items[5].Items[2].Valor==1) {
		if (this.SumesRestesFraccionsSensemcm()) return (false);
	}
	if (MyGenerador.Items[5].Items[3].Valor==1) {
		if (this.TestDivisionsEntreSiMateix()) return (false);
	}
	if (this.EvitarDividirEntre1) {
		if (this.TestDivisionsEntre1()) return (false);
	}
	return (true);
}

Complement.prototype.TestEvitarMultiplicarPerNombre1 = function() {
	if (this.NombreR.MyNombre.Operacio!=MULTIPLICAR) return (true);
	// Mira per l'esquerra...
	if (!this.NombreE.MyNombre.EsOperacio()) {
		if (Math.abs(this.NombreE.MyNombre.ValorNumeric())==1) return (false);
	}
	if (!this.NombreD.MyNombre.EsOperacio()) {
		if (Math.abs(this.NombreD.MyNombre.ValorNumeric())==1) return (false);
	}
	return (true);
}

Complement.prototype.TestEvitarMultiplicarPerNombre0 = function() {
	if (this.NombreR.Operacio!=MULTIPLICAR) return (true);
	// Mira per l'esquerra...
	if (!this.NombreE.MyNombre.EsOperacio()) {
		if (this.NombreE.MyNombre.ValorNumeric()==0) return (false);
	}
	if (!this.NombreD.MyNombre.EsOperacio()) {
		if (this.NombreD.MyNombre.ValorNumeric()==0) return (false);
	}
	return (true);
}

Complement.prototype.SumesRestesFraccionsAmbMateixDenominador = function() {
	// Torna True si està sumant o restant dues fraccions amb el mateix denominador.
	if (!this.NombreR.MyNombre.EsOperacio()) return (false);	
	if (this.NombreR.MyNombre.Operacio!=SUMAR && this.NombreR.MyNombre.Operacio!=RESTAR) 
		return (false);
	if (this.NombreE.MyNombre.EsOperacio()) return (false);
	if (this.NombreD.MyNombre.EsOperacio()) return (false);
	if (this.NombreE.MyNombre.Tipus!=2) return (false);
	if (this.NombreD.MyNombre.Tipus!=2) return (false);
	if (Math.abs(this.NombreE.MyNombre.Den)!=Math.abs(this.NombreD.MyNombre.Den)) return (false); 
	return (true);	
}

Complement.prototype.SumesRestesFraccionsSensemcm = function () {
	if (!this.NombreR.MyNombre.EsOperacio()) return (false);	
	if (this.NombreR.MyNombre.Operacio!=SUMAR && this.NombreR.MyNombre.Operacio!=RESTAR) 
		return (false);	
	if (this.NombreE.MyNombre.EsOperacio()) return (false);
	if (this.NombreD.MyNombre.EsOperacio()) return (false);
	if (this.NombreE.MyNombre.Tipus==1 && this.NombreD.MyNombre.Tipus==1) return (false);
	if (this.NombreE.MyNombre.Tipus!=2) return (false);
	if (this.NombreD.MyNombre.Tipus!=2) return (false);

	var denA=this.NombreE.MyNombre.Den;
	var denB=this.NombreD.MyNombre.Den;
	var mcm=this.NombreD.MyNombre.MaximComuDivisor(denA,denB);
	if (mcm==denA || mcm==denB) return (true);
	return (false);
}
Complement.prototype.TestDivisionsEntreSiMateix = function() {
	if (!this.NombreR.MyNombre.EsOperacio()) return (false);	
	if (this.NombreR.MyNombre.Operacio!=DIVIDIR) return (false);	
	if (Math.abs(this.NombreE.MyNombre.ValorNumeric())==Math.abs(this.NombreD.MyNombre.ValorNumeric())) return (true);
	return (false);
	
}
Complement.prototype.TestDivisionsEntre1 = function() {
	if (!this.NombreR.MyNombre.EsOperacio()) return (false);	
	if (this.NombreR.MyNombre.Operacio!=DIVIDIR) return (false);	
	if (this.NombreD.MyNombre.EsOperacio()) return (false);
	if (Math.abs(this.NombreD.MyNombre.ValorNumeric())==1) return (true);
	return (false);
	
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> POSICIÓ FINAL
*
************************************************************************************/

Complement.prototype.CompletarPosicioFinal = function() {
	//Només posem un valor en una posició final si està buida.
	if (this.NombreR.MyNombre.Contingut) {
		this.Status=STATUS_FET_OK;
		return;
	}
	this.Status=this.NombreR.GenerarNombreAleatoriGeneral();
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> OPERACIÓ
*
************************************************************************************/

Complement.prototype.CompletarOperacio = function () {
	//Generem dinàmicament el nom de la rutina a executar per a estalviar-nos una
	//pila de codi aburrit.	
	var NomFuncio="";
	var Aux;
	var AvisIntercanviDivisio=false;
	switch (this.NombreR.MyNombre.Operacio) {
		case SUMAR : NomFuncio="CompletarOperacioSumar";break;
		case RESTAR : NomFuncio="CompletarOperacioRestar";break;
		case MULTIPLICAR : NomFuncio="CompletarOperacioMultiplicar";break;
		case DIVIDIR : NomFuncio="CompletarOperacioMultiplicar";break;
		case ELEVAR : NomFuncio="CompletarOperacioElevar";break;
		case RADICAR : NomFuncio="CompletarOperacioElevar";break;
		default: return -4;		
	}
	if ((this.NombreR.MyNombre.Operacio!=DIVIDIR)&&(this.NombreR.MyNombre.Operacio!=RADICAR)) {
		if (this.NombreE.MyNombre.Contingut) NomFuncio=NomFuncio+"AmbE";
		else NomFuncio=NomFuncio+"SenseE"
		if (this.NombreD.MyNombre.Contingut) NomFuncio=NomFuncio+"AmbD";
		else NomFuncio=NomFuncio+"SenseD"
		if (this.NombreR.MyNombre.Contingut) NomFuncio=NomFuncio+"AmbR";
		else NomFuncio=NomFuncio+"SenseR"
	} 
	else {
		AvisIntercanviDivisio=true;
		//Les divisions es resolen com a multiplicacions intercanviant
		// R i E  R=E/D <--> E=R*D
		if (this.NombreR.MyNombre.Contingut) NomFuncio=NomFuncio+"AmbE";
		else NomFuncio=NomFuncio+"SenseE"
		if (this.NombreD.MyNombre.Contingut) NomFuncio=NomFuncio+"AmbD";
		else NomFuncio=NomFuncio+"SenseD"
		if (this.NombreE.MyNombre.Contingut) NomFuncio=NomFuncio+"AmbR";
		else NomFuncio=NomFuncio+"SenseR";
		Aux=this.NombreR.MyNombre.Num;
		this.NombreR.MyNombre.Num=this.NombreE.MyNombre.Num;
		this.NombreE.MyNombre.Num=Aux;
		Aux=this.NombreR.MyNombre.Den;
		this.NombreR.MyNombre.Den=this.NombreE.MyNombre.Den;
		this.NombreE.MyNombre.Den=Aux;
		Aux=this.NombreR.MyNombre.Dec;
		this.NombreR.MyNombre.Dec=this.NombreE.MyNombre.Dec;
		this.NombreE.MyNombre.Dec=Aux;
		Aux=this.NombreR.MyNombre.Tipus;
		this.NombreR.MyNombre.Tipus=this.NombreE.MyNombre.Tipus;
		this.NombreE.MyNombre.Tipus=Aux;
		Aux=this.NombreR.MyNombre.Contingut;
		this.NombreR.MyNombre.Contingut=this.NombreE.MyNombre.Contingut;
		this.NombreE.MyNombre.Contingut=Aux;

	}

	eval("this."+NomFuncio+"()");

	// Si era una divisió desfem l'intercanvi de R i E i potser en Status

	if (AvisIntercanviDivisio==true) {
		Aux=this.NombreR.MyNombre.Num;
		this.NombreR.MyNombre.Num=this.NombreE.MyNombre.Num;
		this.NombreE.MyNombre.Num=Aux;
		Aux=this.NombreR.MyNombre.Den;
		this.NombreR.MyNombre.Den=this.NombreE.MyNombre.Den;
		this.NombreE.MyNombre.Den=Aux;
		Aux=this.NombreR.MyNombre.Dec;
		this.NombreR.MyNombre.Dec=this.NombreE.MyNombre.Dec;
		this.NombreE.MyNombre.Dec=Aux;
		Aux=this.NombreR.MyNombre.Tipus;
		this.NombreR.MyNombre.Tipus=this.NombreE.MyNombre.Tipus;
		this.NombreE.MyNombre.Tipus=Aux;
		Aux=this.NombreR.MyNombre.Contingut;
		this.NombreR.MyNombre.Contingut=this.NombreE.MyNombre.Contingut;
		this.NombreE.MyNombre.Contingut=Aux;

		switch (this.Status) {
			case STATUS_INCOMP_E: this.Status=STATUS_INCOMP_R; break;
			case STATUS_INCOMP_R: this.Status=STATUS_INCOMP_E; break;
			case STATUS_INCOMP_DE: this.Status=STATUS_INCOMP_DR; break;
			case STATUS_INCOMP_DR: this.Status=STATUS_INCOMP_DE; break;
			case STATUS_NO_VALID_E: this.Status=STATUS_NO_VALID_R; break;
			case STATUS_NO_VALID_R: this.Status=STATUS_NO_VALID_E; break;
		}		
		if (this.NombreR.MyNombre.Operacio==RADICAR) {
			// Si la operació era ELEVAR el resultat ha de ser positiu
		}
	}

}	

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Operacio --> Sumar
*
************************************************************************************/

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Operacio --> Sumar --> 3 Op.
*
************************************************************************************/

Complement.prototype.CompletarOperacioSumarSenseESenseDSenseR= function() {	
	this.Status=this.NombreD.GenerarNombreAleatoriGeneral();
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioSumarSenseEAmbDSenseR();
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Operacio --> Sumar --> 2 Op.
*
************************************************************************************/

Complement.prototype.CompletarOperacioSumarSenseESenseDAmbR= function () {
	if (this.NombreE.Condicions.NomesNaturals()) {
		this.CompletarOperacioSumarSenseESenseDAmbRNaturals();
		return;
	}
	this.Status=this.NombreE.GenerarNombreAleatoriGeneral();
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioSumarAmbESenseDAmbR();	
}

Complement.prototype.CompletarOperacioSumarSenseESenseDAmbRNaturals= function () {
	if (this.NombreR.MyNombre.Num<=1) {
		this.Status=STATUS_INCOMP_R;
		return;
	}
	this.Status=this.NombreE.GenerarNombreAleatoriEnterInterval(1,this.NombreR.MyNombre.Num-1);
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioSumarAmbESenseDAmbR();	
}

Complement.prototype.CompletarOperacioSumarSenseEAmbDSenseR= function () {
	if (this.NombreE.Condicions.NomesNaturals()) {
		this.CompletarOperacioSumarSenseEAmbDSenseRNaturals();
		return;
	}
	this.Status=this.NombreR.GenerarNombreAleatoriGeneral();
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioSumarSenseEAmbDAmbR();	
}

Complement.prototype.CompletarOperacioSumarSenseEAmbDSenseRNaturals= function () {
	if (this.NombreD.MyNombre.Num>=this.NombreR.Condicions.Items[3].Items[1].Valor) {
		this.Status=STATUS_INCOMP_D;
		return;
	}		
	this.Status=this.NombreE.GenerarNombreAleatoriEnterInterval(1,this.NombreR.Condicions.Items[3].Items[1].Valor-this.NombreD.MyNombre.Num);
	if (this.Status!=STATUS_FET_OK) {
		this.Status=STATUS_ALEATORI_NO_VALID_ESPECIAL;
		return;
	}
	this.CompletarOperacioSumarAmbEAmbDSenseR();	
}

Complement.prototype.CompletarOperacioSumarAmbESenseDSenseR= function () {
	if (this.NombreD.Condicions.NomesNaturals()) {
		this.CompletarOperacioSumarAmbESenseDSenseRNaturals();
		return;
	}
	this.Status=this.NombreD.GenerarNombreAleatoriGeneral();
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioSumarAmbEAmbDSenseR();	
}

Complement.prototype.CompletarOperacioSumarAmbESenseDSenseRNaturals= function () {
	if (this.NombreE.MyNombre.Num>=this.NombreR.Condicions.Items[3].Items[1].Valor) {
		this.Status=STATUS_INCOMP_E;
		return;
	}		
	this.Status=this.NombreD.GenerarNombreAleatoriEnterInterval(1,this.NombreR.Condicions.Items[3].Items[1].Valor-this.NombreE.MyNombre.Num);
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioSumarAmbEAmbDSenseR();	
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Operacio --> Sumar --> 1 Op.
*
************************************************************************************/

Complement.prototype.CompletarOperacioSumarAmbESenseDAmbR= function () {
	// Cal Resoldre R= E + x --> x= R - E
	if (this.NombreD.Condicions.Items[1].Valor==0) {
		if (this.NombreR.MyNombre.ValorNumeric()<=this.NombreE.MyNombre.ValorNumeric()) {
			this.Status=STATUS_INCOMP_ER;
			return;
		}
	}		
	this.MyCalculadora.NombreA=this.NombreR.MyNombre;
	this.MyCalculadora.NombreB=this.NombreE.MyNombre;
	this.MyCalculadora.Restar();
	this.PassarResultatCalculadoraANombreD();
	if (this.NombreD.TestValorAcceptable()) this.Status=STATUS_FET_OK;
	else this.Status=STATUS_NO_VALID_D;
}

Complement.prototype.CompletarOperacioSumarAmbEAmbDSenseR= function () {
	// Cal Resoldre x= E + D 
	this.MyCalculadora.NombreA=this.NombreE.MyNombre;
	this.MyCalculadora.NombreB=this.NombreD.MyNombre;
	this.MyCalculadora.Sumar();
	this.PassarResultatCalculadoraANombreR();
	if (this.NombreR.TestValorAcceptable()) this.Status=STATUS_FET_OK;
	else this.Status=STATUS_NO_VALID_R;
}

Complement.prototype.CompletarOperacioSumarSenseEAmbDAmbR= function () {
	// Cal Resoldre R = x + D --> x = R - D 
	this.MyCalculadora.NombreA=this.NombreR.MyNombre;
	this.MyCalculadora.NombreB=this.NombreD.MyNombre;
	this.MyCalculadora.Restar();
	this.PassarResultatCalculadoraANombreE();
	if (this.NombreE.TestValorAcceptable()) {
		this.Status=STATUS_FET_OK;
	}
	else this.Status=STATUS_NO_VALID_E;
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Operacio --> Restar
*
************************************************************************************/

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Operacio --> Restar --> 3 Op.
*
************************************************************************************/

Complement.prototype.CompletarOperacioRestarSenseESenseDSenseR= function() {	
	this.Status=this.NombreE.GenerarNombreAleatoriGeneral();
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioRestarAmbESenseDSenseR();
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Operacio --> Restar --> 2 Op.
*
************************************************************************************/

Complement.prototype.CompletarOperacioRestarSenseESenseDAmbR= function () {
	if (this.NombreE.Condicions.NomesNaturals()) {
		this.CompletarOperacioRestarSenseESenseDAmbRNaturals();
		return;
	}
	this.Status=this.NombreE.GenerarNombreAleatoriGeneral();
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioRestarAmbESenseDAmbR();	
}

Complement.prototype.CompletarOperacioRestarSenseESenseDAmbRNaturals= function () {
	if (this.NombreR.MyNombre.Num>=this.NombreR.Condicions.Items[3].Items[1].Valor) {
		this.Status=STATUS_INCOMP_R;
		return;
	}		
	this.Status=this.NombreE.GenerarNombreAleatoriEnterInterval(this.NombreR.MyNombre.Num+1,this.NombreR.Condicions.Items[3].Items[1].Valor);
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioRestarAmbESenseDAmbR();	
}

Complement.prototype.CompletarOperacioRestarSenseEAmbDSenseR= function () {
	if (this.NombreD.Condicions.NomesNaturals()) {
		this.CompletarOperacioRestarSenseEAmbDSenseRNaturals();
		return;
	}
	this.Status=this.NombreR.GenerarNombreAleatoriGeneral();
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioRestarSenseEAmbDAmbR();	
}

Complement.prototype.CompletarOperacioRestarSenseEAmbDSenseRNaturals= function () {
	if (this.NombreD.MyNombre.Num>=this.NombreR.Condicions.Items[3].Items[1].Valor) {
		this.Status=STATUS_INCOMP_D;
		return;
	}		
	this.Status=this.NombreE.GenerarNombreAleatoriEnterInterval(this.NombreD.MyNombre.Num+1,this.NombreR.Condicions.Items[3].Items[1].Valor);
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioRestarAmbEAmbDSenseR();	
}

Complement.prototype.CompletarOperacioRestarAmbESenseDSenseR= function () {
	if (this.NombreD.Condicions.NomesNaturals()) {
		this.CompletarOperacioRestarAmbESenseDSenseRNaturals();
		return;
	}
	this.Status=this.NombreD.GenerarNombreAleatoriGeneral();
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioRestarAmbEAmbDSenseR();	
}

Complement.prototype.CompletarOperacioRestarAmbESenseDSenseRNaturals= function () {
	if (this.NombreE.MyNombre.Num<=1) {
		this.Status=STATUS_INCOMP_E;
		return;
	}		
	this.Status=this.NombreD.GenerarNombreAleatoriEnterInterval(1,this.NombreE.MyNombre.Num-1);
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioRestarAmbEAmbDSenseR();	
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Operacio --> Restar --> 1 Op.
*
************************************************************************************/

Complement.prototype.CompletarOperacioRestarAmbESenseDAmbR= function () {
	// Cal Resoldre R= E - x --> x= E - R
	this.MyCalculadora.NombreA=this.NombreE.MyNombre;
	this.MyCalculadora.NombreB=this.NombreR.MyNombre;
	this.MyCalculadora.Restar();
	this.PassarResultatCalculadoraANombreD();
	if (this.NombreD.TestValorAcceptable()) this.Status=STATUS_FET_OK;
	else this.Status=STATUS_NO_VALID_D;
}

Complement.prototype.CompletarOperacioRestarAmbEAmbDSenseR= function () {
	// Cal Resoldre x = E - D
	this.MyCalculadora.NombreA=this.NombreE.MyNombre;
	this.MyCalculadora.NombreB=this.NombreD.MyNombre;
	this.MyCalculadora.Restar();
	this.PassarResultatCalculadoraANombreR();
	if (this.NombreR.TestValorAcceptable()) this.Status=STATUS_FET_OK;
	else this.Status=STATUS_NO_VALID_R;
}

Complement.prototype.CompletarOperacioRestarSenseEAmbDAmbR= function () {
	// Cal Resoldre R = x - D --> x = R + D 
	this.MyCalculadora.NombreA=this.NombreR.MyNombre;
	this.MyCalculadora.NombreB=this.NombreD.MyNombre;
	this.MyCalculadora.Sumar();
	this.PassarResultatCalculadoraANombreE();
	if (this.NombreE.TestValorAcceptable()) this.Status=STATUS_FET_OK;
	else this.Status=STATUS_NO_VALID_E;
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Operacio --> Multiplicar
*
************************************************************************************/

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Operacio --> Multiplicar --> 3 Op.
*
************************************************************************************/

Complement.prototype.CompletarOperacioMultiplicarSenseESenseDSenseR= function() {	
	this.Status=this.NombreR.GenerarNombreAleatoriGeneral();
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioMultiplicarSenseESenseDAmbR();
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Operacio --> Multiplicar --> 2 Op.
*
************************************************************************************/

Complement.prototype.CompletarOperacioMultiplicarSenseESenseDAmbR = function() {
	if (this.NombreE.Condicions.Items[3].Valor==NOMBRE_ENTER) {
		this.CompletarOperacioMultiplicarSenseESenseDAmbREnters();
		return;
	}
	this.Status=this.NombreE.GenerarNombreAleatoriGeneral();
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioMultiplicarAmbESenseDAmbR();	
}

Complement.prototype.CompletarOperacioMultiplicarSenseESenseDAmbREnters= function () {
	// Cal trobar un divisor de R per a posar-lo en E.
	// Si no hi ha, no es pot continuar.
	this.Status=this.NombreE.GenerarEnterAleatoriDivisorDe(this.NombreR.MyNombre.Num);
	if (this.Status==STATUS_ALEATORI_IMPOSSIBLE) {
		//Si no té divisors, retorna "incompatibilitat R"
		this.Status=STATUS_INCOMP_R;
		return;
	} 
	if (this.Status!=STATUS_FET_OK) return;
	//Si s'ha pogut continuem completant el Node
	this.CompletarOperacioMultiplicarAmbESenseDAmbR();	
}

Complement.prototype.CompletarOperacioMultiplicarSenseEAmbDSenseR = function() {
	if (this.NombreE.Condicions.Items[3].Valor==NOMBRE_ENTER) {
		this.CompletarOperacioMultiplicarSenseEAmbDSenseREnters();
		return;
	}
	this.Status=this.NombreR.GenerarNombreAleatoriGeneral();
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioMultiplicarSenseEAmbDAmbR();	
}

Complement.prototype.CompletarOperacioMultiplicarSenseEAmbDSenseREnters= function () {
	// Cal trobar un múltiple de D per a posar-lo en E.
	// Si no hi ha, no es pot continuar.
	this.Status=this.NombreE.GenerarEnterAleatoriMultipleDe(this.NombreD.MyNombre.Num);
	if (this.Status==STATUS_ALEATORI_IMPOSSIBLE) {
		//Si no té múltiples acceptables, retorna "incompatibilitat D"
		this.Status=STATUS_INCOMP_D;
		return;
	} 
	if (this.Status!=STATUS_FET_OK) return;
	//Si s'ha pogut continuem completant el Node
	this.CompletarOperacioMultiplicarAmbEAmbDSenseR();	
}

Complement.prototype.CompletarOperacioMultiplicarAmbESenseDSenseR = function() {
	if (this.NombreD.Condicions.Items[3].Valor==NOMBRE_ENTER) {
		this.CompletarOperacioMultiplicarAmbESenseDSenseREnters();
		return;
	}
	this.Status=this.NombreR.GenerarNombreAleatoriGeneral();
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioMultiplicarAmbESenseDAmbR();	
}

Complement.prototype.CompletarOperacioMultiplicarAmbESenseDSenseREnters= function () {
	// Cal trobar un múltiple de E per a posar-lo en D.
	// Si no hi ha, no es pot continuar.
	this.Status=this.NombreD.GenerarEnterAleatoriMultipleDe(this.NombreE.MyNombre.Num);
	if (this.Status==STATUS_ALEATORI_IMPOSSIBLE) {
		//Si no té múltiples acceptables, retorna "incompatibilitat E"
		this.Status=STATUS_INCOMP_E;
		return;
	} 
	if (this.Status!=STATUS_FET_OK) return;
	//Si s'ha pogut continuem completant el Node
	this.CompletarOperacioMultiplicarAmbEAmbDSenseR();	
}


/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Operacio --> Multiplicar --> 1 Op.
*
************************************************************************************/

Complement.prototype.CompletarOperacioMultiplicarAmbESenseDAmbR = function() {
	//Cal resoldre R = E * x --> x = R / E
	this.MyCalculadora.NombreA=this.NombreR.MyNombre;
	this.MyCalculadora.NombreB=this.NombreE.MyNombre;
	this.MyCalculadora.Dividir();
	if (this.MyCalculadora.CodiError<0) {
		//E és zero.
		this.Status=STATUS_INCOMP_E;
		return;
	}
	this.PassarResultatCalculadoraANombreD();
	if (this.NombreD.TestValorAcceptable()) this.Status=STATUS_FET_OK;
	else this.Status=STATUS_NO_VALID_D;
}

Complement.prototype.CompletarOperacioMultiplicarSenseEAmbDAmbR = function() {
	// Cal resoldre R = x * D --> x = R / D
	this.MyCalculadora.NombreA=this.NombreR.MyNombre;
	this.MyCalculadora.NombreB=this.NombreD.MyNombre;
	this.MyCalculadora.Dividir();
	if (this.MyCalculadora.CodiError<0) {
		//D és zero.
		this.Status=STATUS_INCOMP_D;
		return;
	}
	this.PassarResultatCalculadoraANombreE();
	if (this.NombreE.TestValorAcceptable()) this.Status=STATUS_FET_OK;
	else this.Status=STATUS_NO_VALID_E;
}

Complement.prototype.CompletarOperacioMultiplicarAmbEAmbDSenseR = function() {
	// Cal resoldre x = E * D 
	this.MyCalculadora.NombreA=this.NombreE.MyNombre;
	this.MyCalculadora.NombreB=this.NombreD.MyNombre;
	this.MyCalculadora.Multiplicar();
	this.PassarResultatCalculadoraANombreR();
	if (this.NombreR.TestValorAcceptable()) this.Status=STATUS_FET_OK;
	else this.Status=STATUS_NO_VALID_R;
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Operacio --> Elevar
*
************************************************************************************/

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Operacio --> Elevar --> 3 Op.
*
************************************************************************************/

Complement.prototype.CompletarOperacioElevarSenseESenseDSenseR= function() {	
	this.Status=this.NombreD.GenerarExponentEnterAleatori();
	if (this.Status!=STATUS_FET_OK) return;
	this.CompletarOperacioElevarSenseEAmbDSenseR();
}

/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Operacio --> Elevar--> 2 Op.
*
************************************************************************************/

Complement.prototype.CompletarOperacioElevarSenseEAmbDSenseR = function(){
	if (this.NombreR.Condicions.Items[3].Valor==1) {
		this.CompletarOperacioElevarSenseEAmbDSenseRResultatEnter();
		return;
	}
	if (this.NombreR.Condicions.Items[3].Valor==2) {
		this.CompletarOperacioElevarSenseEAmbDSenseRResultatFraccio();
		return;
	}
	if (this.NombreR.Condicions.Items[3].Valor==3) {
		this.CompletarOperacioElevarSenseEAmbDSenseRResultatDecimal();
		return;
	}
	BUGEnCompletarOperacioElevarSenseEAmbDSenseR();
}

Complement.prototype.CompletarOperacioElevarSenseEAmbDSenseRResultatEnter = function() {
	var ValorMaxim=this.NombreR.Condicions.Items[3].Items[1].Valor;
	var Exp=this.NombreD.MyNombre.Num;
	this.Status=this.NombreE.GenerarBaseEnteraAleatoria(ValorMaxim,Exp);
	if (this.Status!=STATUS_FET_OK) {
		this.Status=STATUS_INCOMP_D;
		return;
	}
	this.CompletarOperacioElevarAmbEAmbDSenseR(); 
}

Complement.prototype.CompletarOperacioElevarSenseEAmbDSenseRResultatFraccio = function() {
	var ValorMaximNum=this.NombreR.Condicions.Items[3].Items[2].Items[1].Valor;
	var ValorMaximDen=this.NombreR.Condicions.Items[3].Items[2].Items[2].Valor;
	var Exp=this.NombreD.MyNombre.Num;
	this.Status=this.NombreE.GenerarBaseFraccioAleatoria (ValorMaximNum,ValorMaximDen,Exp);
	if (this.Status!=STATUS_FET_OK) {
		this.Status=STATUS_INCOMP_D;
		return;
	}
	this.CompletarOperacioElevarAmbEAmbDSenseR(); 
}

Complement.prototype.CompletarOperacioElevarSenseEAmbDSenseRResultatDecimal = function() {
	var ValorMaxim=this.NombreR.Condicions.Items[3].Items[3].Items[2].Valor;
	var Exp=this.NombreD.MyNombre.Num;
	this.Status=this.NombreE.GenerarBaseDecimalAleatoria (ValorMaxim,Exp);
	if (this.Status!=STATUS_FET_OK) {
		this.Status=STATUS_INCOMP_D;
		return;
	}
	this.CompletarOperacioElevarAmbEAmbDSenseR(); 
}


/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> COMPLETAR --> Operacio --> Elevar --> 1 Op.
*
************************************************************************************/

Complement.prototype.CompletarOperacioElevarAmbEAmbDSenseR = function(){
	this.MyCalculadora.NombreA=this.NombreE.MyNombre;
	this.MyCalculadora.NombreB=this.NombreD.MyNombre;
	this.MyCalculadora.Elevar();
	this.PassarResultatCalculadoraANombreR();
	if (this.NombreR.TestValorAcceptable()) this.Status=STATUS_FET_OK;
	else this.Status=STATUS_NO_VALID_R;
}
/************************************************************************************
*
* GENERADORBEWOOM --> COMPLEMENT --> CONDICIONS NUMÈRIQUES --> CONFIGURADOR --> NOMBRES PRIMERS
*
************************************************************************************/

function TaulaNombresPrimers(TheIndex) {
	// Variables relacionades amb la factorització.
	this.NombresPrimers=[1,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,
			71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151];
	this.IndexActual=TheIndex;
}	
TaulaNombresPrimers.prototype.NPrimer = function (IndexPrimer) {
	return (this.NombresPrimers[IndexPrimer]);
}

TaulaNombresPrimers.prototype.RectificarValorNoAcceptable = function (IndexPrimer) {
	if (IndexPrimer>this.NombresPrimers.length-1) return(this.NombresPrimers.length-1);
	return(IndexPrimer)
}

TaulaNombresPrimers.prototype.NombrePrimerAnterior = function() {
	if (this.IndexActual<2) return;
	this.IndexActual=this.IndexActual-1;
	this.ActualitzarFinestra();
}
TaulaNombresPrimers.prototype.NombrePrimerPosterior = function() {
	if (this.IndexActual>=this.NombresPrimers.length-1) return;
	this.IndexActual=this.IndexActual+1;
	this.ActualitzarFinestra();
}
TaulaNombresPrimers.prototype.ActualitzarFinestra = function() {
	var MaximPrimer=this.NombresPrimers[this.IndexActual];
	document.getElementById("PrimerMax").value=MaximPrimer;
}
TaulaNombresPrimers.prototype.MaxPrimer = function () {
	return (this.NombresPrimers.length);
}

/***********************************************************************************\
*
*    Mòdul Kernel-Bewoom del projecte Col·lectiva versió 2.0
*
************************************************************************************/	

	var NOMBRE_NO_DEFINIT = 0;
	var NOMBRE_ENTER = 1;
	var NOMBRE_FRACCIO = 2;
	var NOMBRE_DECIMAL = 3;
	var VALOR_LOGIC = 4;		// Num = 1 --> true, Num = 0 --> False

	var NOMBRE = 0;
	var SUMAR = 1;
	var RESTAR = 2;
	var MULTIPLICAR = 3;
	var DIVIDIR = 4;
	var ELEVAR = 5;
	var RADICAR = 6;
	var IGUALTAT= 9;

	var LLENGUATGE_MATEMATIC_ASCII = 0;
	var LLENGUATGE_MATEMATIC_OPEN_OFFICE = 1;
	var LLENGUATGE_MATEMATIC_MSWORD = 2;
	var LLENGUATGE_MATEMATIC_TEX_MOODLE = 3;
	var LLENGUATGE_MATEMATIC_MATHML = 4;



/***********************************************************************************\
*
* Nombre 
*
************************************************************************************/
/*
* Aquest mòdul defineix l'objecte fonamental de tot el programa: un nombre, sigui
* enter, fracció o decimal, i les rutines associades a la seva manipulació numèrica
* i la seva escriptura.
*/

/************************************************************************************
*
* Nombre --> Constructor
*
************************************************************************************/

function Nombre() {

	// Contingut numèric:
	this.Tipus=0;			// Per defecte és un tipus NO DEFINIT		
					// Tipus:
					//	NO DEFINIT = 0
					//	ENTER = 1
					//	FRACCIO = 2
					//	DECIMAL = 3
					//	VALOR LOGIC = 4;
					// 	Num = 1 --> true, Num = 0 --> False


	this.Contingut=false;		// Indica si té contingut numèric o no	
	this.ValorFix=false;		// Valor Fix. Indica que aquest valor 
					// no es pot canviar per les rutines de
					// GÈNESIS

	this.Num=0;			// El numerador o el valor si és un ENTER
	this.Den=1;			// El denominador o 1 si és un ENTER, d'aquesta
					// forma els ENTERS també són FRACCIONS.
	this.Dec=0;			// El contingut si és un DECIMAL

	this.NDecimalsPrecisio=-1;
					// Si el contingut és un decimal, indica 
					// el nombre de xifres decimals que té.
					// Si per exemple = 3, 0.0001 és zero
					// Si és -1 significa infinits
	
	// Variables per a l'escriptura del nombre
	
	this.TextFix=false;		// si true el TextNombre ja ve fixat i no es toca
					// vol dir que és un paràmetre. 
	this.TextNombre="";		// Escriptura del nombre
	this.TextIniciaAmbMenys=false;	// Informa que el nombre comença amb "-"
	this.CodisEspecials=false;	// Indica si s'han fet servir 
					// codis especials en l'escriptura.

	// Operació:

	this.Operacio=0;
					// NOMBRE = 0 (és posició final, no és resultat)
					// SUMAR = 1
					// RESTAR = 2
					// MULTIPLICAR = 3
					// DIVIDIR = 4
					// ELEVAR = 5
					// RADICAR = 6
					// IGUALTAT = 9	(operació lògica) 	
}

/************************************************************************************
*
* Nombre --> INPUT
*
************************************************************************************/

Nombre.prototype.InputPosicioFinalNombre = function (TextNombre,TheNDecimalsPrecisio) {
	// Genera en la posició actual un nombre que ve donat per TextNombre
	// Retorna <0 Error de sintaxis, 1 = OK
	this.Operacio=0;
	var ValorNumeric=parseFloat(TextNombre);
	if (ValorNumeric==NaN) return(-5);	// Error Nombre no acceptable.
	if (ValorNumeric==Math.round(ValorNumeric)) this.InEnter(ValorNumeric);
	else this.InDecimal(ValorNumeric,TheNDecimalsPrecisio);
	return (1);
}

Nombre.prototype.InEnter = function (ValorEnter) {
	// Introdueix un valor enter en el nombre.
	this.Num=ValorEnter;
	this.Den=1;
	this.Tipus=1;	// Enter	
	this.Contingut=true;
}	

Nombre.prototype.InZero = function () {
	// Introdueix un nombre zero.
	// Aquesta rutina s'utilitza per a treballar amb expressions -A --> 0-A
	this.InEnter(0);
	this.ValorFix=true;	
}	
	
Nombre.prototype.InFraccio = function (ValorNum, ValorDen,Simplificacio) {
	// Introdueix una fracció i la simplifica si Simplificacio=true
	this.Num=ValorNum;
	this.Den=ValorDen;
	this.Tipus=2;	// Fracció
	this.Contingut=true;
	if (Simplificacio) this.SimplificarFraccio(false);
}

Nombre.prototype.InDecimal = function (ValorDecimal,TheNDecimalsPrecisio) {
	// Introdueix un valor decimal en una posició
	// I el nombre de xifres decimals (si no està, infinites)
	if (!TheNDecimalsPrecisio) this.NDecimalsPrecisio=-1
	else this.NDecimalsPrecisio=TheNDecimalsPrecisio;
	this.Dec=ValorDecimal;
	this.Tipus=3;	// Decimal
	this.Contingut=true;
}

Nombre.prototype.InputPosicioFinalLiteral = function (TextLiteral) {
	// En principi un literal, per exemple "x" és un nombre (no definit)
	// amb una visualització obligatoria com "x"
	// Retorna <0 Error de sintaxis, 1 = OK
	this.Contingut=false;
	this.TextFix=true;
	this.TextNombre=TextLiteral;	
	this.TextIniciaAmbMenys=false;
	this.CodisEspecials=false;	
	return (1); // OK
}

/************************************************************************************
*
* Nombre --> Rutines matemàtiques
*
************************************************************************************/

Nombre.prototype.ValorNumeric= function() {
	// Retorna el valor numèric del nombre, independentment del seu tipus.
	// Retorna POSITIVE_INFINITY si és una fracció i el denominador és 0
	if (this.Tipus==NOMBRE_ENTER) {
		return this.Num;
	}
	if (this.Tipus==NOMBRE_FRACCIO) {
		if (this.Den==0) {
			return POSITIVE_INFINITY;
		} else {
			return this.Num/this.Den;
		}
	}
	return this.Dec; // Per exclusió ha de ser un nombre decimal.
}

Nombre.prototype.Decimalitzar = function () {
	// Sense tocar el tipus de nombre, deixa en this.Dec el seu valor 
	// decimal, de forma que pugui ser utilitzat en les rutines de cálcul 
	// de nombres decimals.
	if (this.Tipus==3) return; // Si el nombre ja és decimal no fa res.
	this.Dec=this.ValorNumeric();
}

Nombre.prototype.EsZero = function(){
	//Indica si el nombre és zero o no
	if (!this.Contingut) return (false);
	if (this.Tipus==NOMBRE_ENTER || this.Tipus==NOMBRE_FRACCIO) {
		if (this.Num==0) return (true); 
		return (false);
	}
	// Si és un valor decimal, mirem si és un valor més petit que 
	// el nombre de decimals estipulat.
	// Si el nombre de decimals és -1 implica infinits i ha de ser
	// zero total
	if (this.NDecimalsPrecisio==-1) {
		if (this.Dec==0) return (true);
		return (false);
	}
	if (Math.abs(this.Dec)<Math.pow(10,-this.NDecimalsPrecisio)) return (true);
	return (false);
}

Nombre.prototype.Reset= function() {
	if (this.ValorFix==false) this.Contingut=false;
}

Nombre.prototype.EsOperacio = function () {
	if (this.Operacio==0) return (false);
	else return (true);
}

Nombre.prototype.SimplificarFraccio= function(NoSimplificarFraccions) {
	// Normalitza, simplifica (opcionalment) i Retipifica una fracció.
	var mcd;
	this.NormalitzarFraccio();
	if (NoSimplificarFraccions!=false) {
		NoSimplificarFraccions=NoSimplificarFraccions;
	}
	if (this.Den!=1 && this.Den!=0 && this.Num!=0 && NoSimplificarFraccions==false) {
		mcd=this.MaximComuDivisor(this.Num,this.Den);
		if (mcd!=0) {
			this.Num=this.Num/mcd;
			this.Den=this.Den/mcd;
		}
	}
	this.Retipificar();
}

Nombre.prototype.NormalitzarFraccio= function() {
	// fem que una fracció sempre tingui el denominador positiu.
	if (this.Den<0) {
		this.Den=-this.Den;
		this.Num=-this.Num;
	}
}	

Nombre.prototype.Retipificar = function(){
	// Si una fracció (suposem ja simplificada i normalitzada!!)
	// té denominador = 1, és en realitat un enter.
	if (this.Tipus==NOMBRE_FRACCIO) {
		if (this.Den==1) {
			this.Tipus=NOMBRE_ENTER;
			return;
		}
		if (this.Num==0) {
			this.Den=1;
			this.Tipus=NOMBRE_ENTER;
			return;
		}
	}
}

Nombre.prototype.MaximComuDivisor = function(x,y){
	// Calcula el màxim comú divisor de dos nombres.
	// Retorna 0 si no es pot.
	var pgcd=0;
	var aux=0;
	x=Math.abs(x);
	y=Math.abs(y);
	if (x<y) {
		aux=x;
		x=y;
		y=aux;
	}
	if (y==0) return (0);
	pgcd=y;
	aux=x % y;
	while (aux>0) {
		pgcd=aux;
		x=y;
		y=pgcd;
		aux= x % y;
	} 
	return (pgcd);
}

Nombre.prototype.TestLimitaciofactorPrimerFraccio = function (){
	// Determina si la fracció té com a factors primers nombres massa alts.
}

Nombre.prototype.Arrodonir = function() {
	// Normalitza un nombre decimal al nombre de decimals que té.
	var NDecimals=this.NDecimalsPrecisio;
	var Valor=this.Dec;
	var Valor2=this.ArrodonirANDecimals(Valor,NDecimals);
	this.Dec=Valor2;
}
Nombre.prototype.ArrodonirANDecimals = function(Valor,NDecimals) {
	var Factor= Math.pow(10,NDecimals);
	var v=Math.round(Valor*Factor);
	var v2=v/Factor;
	return (v2);
}


/************************************************************************************
*
* Nombre --> OUTPUT
*
************************************************************************************/

Nombre.prototype.EscriureNombre = function(LlenguatgeMatematic,NDecimals){
	// Genera l'escriptura del nombre.	
	// Si ve fixat previament, no fa res.
	// El LlenguatgeMatematic pot ser:
	//	LLENGUATGE_MATEMATIC_ASCII
	//	LLENGUATGE_MATEMATIC_OPEN_OFFICE
	// 	LLENGUATGE_MATEMATIC_MSWORD
	//	LLENGUATGE_MATEMATIC_TEX_MOODLE
	//	LLENGUATGE_MATEMATIC_MATHML

	if (this.TextFix) return;
	if (this.Tipus==NOMBRE_ENTER) {
		this.EscriureNombreEnter(LlenguatgeMatematic);
		return;
	}
	if (this.Tipus==NOMBRE_FRACCIO) {
		this.EscriureNombreFraccio(LlenguatgeMatematic);
		return;
	}
	if (this.Tipus==NOMBRE_DECIMAL) {
		this.EscriureNombreDecimal(LlenguatgeMatematic,NDecimals);
		return;
	}
	if (this.Tipus==VALOR_LOGIC) {
		this.EscriureValorLogic(LlenguatgeMatematic);
		return;
	}
	BUGerrorEscriureNombre();
}

Nombre.prototype.EscriureNombreEnter = function (LlenguatgeMatematic) {
	//Genera les variables TextNombre i TextIniciaAmbMenys	
	this.CodisEspecials=false;
	this.IniciAmbMenys=false;
	NombreLletres=this.Num;
	if (LlenguatgeMatematic==LLENGUATGE_MATEMATIC_MATHML) {
		this.TextNombre="<mn>"+NombreLletres+"</mn>";
		this.CodisEspecials=true;
	}
	else this.TextNombre=NombreLletres;
	if (this.Num<0) this.TextIniciaAmbMenys=true;
}

Nombre.prototype.EscriureNombreFraccio = function (LlenguatgeMatematic) {
	// Genera les variables TextNombre i TextIniciaAmbMenys	
	// Per a una fracció
	if (LlenguatgeMatematic==LLENGUATGE_MATEMATIC_ASCII) {
		this.TextNombre=this.Num+"/"+this.Den;
		if (this.Num<0) this.TextIniciaAmbMenys=true;
		else this.TextIniciaAmbMenys=false;
		return;
	}
	if (LlenguatgeMatematic==LLENGUATGE_MATEMATIC_MATHML) {
		this.TextNombre="<mfrac><mn>"+this.Num+"</mn><mn>"+this.Den+"</mn></mfrac>";
		this.TextIniciaAmbMenys=false;
		this.CodisEspecials=true;
	} 	
	if (LlenguatgeMatematic==LLENGUATGE_MATEMATIC_TEX_MOODLE) {
		this.TextNombre="\\frac\\{" +this.Num + "\\} \\{" + this.Den + "\\}";
		this.TextIniciaAmbMenys=false;
		this.CodisEspecials=true;
	} 	

}

Nombre.prototype.EscriureNombreDecimal = function (LlenguatgeMatematic,NDecimals) {
	// Escriu un valor decimal.
	var Valor=this.ArrodonirANDecimals(this.Dec,NDecimals);
   	if (LlenguatgeMatematic!=LLENGUATGE_MATEMATIC_MATHML) {
	    	//this.TextNombre =ToString(Valor);
        	this.TextNombre =Valor;    
		this.CodisEspecials = false;
        }
        if (LlenguatgeMatematic==LLENGUATGE_MATEMATIC_MATHML) {
            	this.TextNombre = "<mn>" + Valor + "</mn>";
            	this.CodisEspecials = true;
        }
	if (Valor<0) this.TextIniciaAmbMenys=true;      
	else this.TextIniciaAmbMenys=false;
}

Nombre.prototype.EscriureValorLogic = function () {
	// Escriu true (Num=1) o false (Num<>1)
	if (this.Num==1) this.TextNombre="true";
	else this.TextNombre="false";
	this.CodisEspecials=false;
}

/***********************************************************************************\
*
* Calculadora
* 
************************************************************************************/

function Calculadora() {
	this.NombreA=new Nombre();
	this.NombreB=new Nombre();
	this.NombreR=new Nombre();

	// NombreA i NombreB poden arribar per referència, per tant no es poden modificar

	this.CodiError=0; 	// Si es produeix algun error, queda registrat (<0).
				// -1 --> Valors d'entrada no numèrics
				// -2 --> Divisió entre zero.	
				// -3 --> Resultat no numèric en Elevar

	this.NoSimplificarFraccions=false;	// Si es true no simplifica les fraccions
						// es necessita per a corregir exercicis
						// on es demana que l'alumne simplifiqui ell.
	this.ExigirTipusIguals=false; 		// Si true decimal no és fracció
}

/************************************************************************************
*
* Calculadora --> Rutines Generals.
*
************************************************************************************/

Calculadora.prototype.DeterminarTipusResultat = function() {
	if (this.NombreA.Tipus==NOMBRE_NO_DEFINIT || this.NombreB.Tipus==NOMBRE_NO_DEFINIT) {
		this.CodiError=-1;
		return;
	}
	// Si un dels dos és decimal, treballa amb rutines de decimals
	
	if (this.NombreA.Tipus==NOMBRE_DECIMAL || this.NombreB.Tipus==NOMBRE_DECIMAL) {
		this.NombreR.Tipus=NOMBRE_DECIMAL;
		this.DeterminarNDecimalsPrecisioResultat();
		if (this.NombreB.Tipus!=NOMBRE_DECIMAL) this.NombreB.Decimalitzar();
		if (this.NombreA.Tipus!=NOMBRE_DECIMAL) this.NombreA.Decimalitzar();
		return;
	}

	// Si un dels dos és fracció, treballa amb rutines de fraccions

	if (this.NombreA.Tipus==NOMBRE_FRACCIO || this.NombreB.Tipus==NOMBRE_FRACCIO) {
		this.NombreR.Tipus=NOMBRE_FRACCIO;
		return;
	}

	// Si tots dos són enters, treballa amb rutines de enters.
	
	this.NombreR.Tipus=NOMBRE_ENTER;
}
Calculadora.prototype.DeterminarNDecimalsPrecisioResultat = function() {
	// Determina el nombre de decimals del resultat en funció del nombre de decimals
	// de cada operador.
	// És el mínim de tots dos, tenint en compte que pot ser infinit (=-1)
	var NDecimalsA=this.NombreA.NDecimalsPrecisio;
	var NDecimalsB=this.NombreB.NDecimalsPrecisio;
	if (NDecimalsA==-1) {
		this.NombreR.NDecimalsPrecisio=NDecimalsB;
		return;
	}
	if (NDecimalsB==-1) {
		this.NombreR.NDecimalsPrecisio=NDecimalsA;
		return;
	}
	if (NDecimalsA>NDecimalsB) {
		this.NombreR.NDecimalsPrecisio=NDecimalsB;
		return;
	}
	this.NombreR.NDecimalsPrecisio=NDecimalsA;
}		


/************************************************************************************
*
* Calculadora --> Operacions
*
************************************************************************************/

/************************************************************************************
*
* Calculadora --> Operacions --> Sumar
*
************************************************************************************/

Calculadora.prototype.Sumar = function() {
	this.CodiError=0;
	this.DeterminarTipusResultat();
	if (this.CodiError<0) return;
	if (this.NombreR.Tipus==NOMBRE_ENTER) {
		this.NombreR.Num=this.NombreA.Num+this.NombreB.Num;
		this.NombreR.Den=1;
		this.NombreR.Contingut=true;
		return;
	}
	if (this.NombreR.Tipus==NOMBRE_FRACCIO) {
		this.NombreR.Num=this.NombreA.Num*this.NombreB.Den+this.NombreA.Den*this.NombreB.Num;
		this.NombreR.Den=this.NombreA.Den*this.NombreB.Den;
		this.NombreR.Contingut=true;
		this.NombreR.SimplificarFraccio(this.NoSimplificarFraccions);
		return;
	}
	if (this.NombreR.Tipus==NOMBRE_DECIMAL) {
		this.NombreR.Dec=this.NombreA.Dec+this.NombreB.Dec;
		this.NombreR.Contingut=true;
		return;
	}
}

/************************************************************************************
*
* Calculadora --> Operacions --> Restar
*
************************************************************************************/

Calculadora.prototype.Restar = function() {
	this.CodiError=0;
	this.DeterminarTipusResultat();
	if (this.CodiError<0) return;
	if (this.NombreR.Tipus==NOMBRE_ENTER) {
		this.NombreR.Num=this.NombreA.Num-this.NombreB.Num;
		this.NombreR.Den=1;
		this.NombreR.Contingut=true;
		return;
	}
	if (this.NombreR.Tipus==NOMBRE_FRACCIO) {
		this.NombreR.Num=this.NombreA.Num*this.NombreB.Den-this.NombreA.Den*this.NombreB.Num;
		this.NombreR.Den=this.NombreA.Den*this.NombreB.Den;
		this.NombreR.Contingut=true;
		this.NombreR.SimplificarFraccio(this.NoSimplificarFraccions);
		return;
	}
	if (this.NombreR.Tipus==NOMBRE_DECIMAL) {
		this.NombreR.Dec=this.NombreA.Dec-this.NombreB.Dec;
		this.NombreR.Contingut=true;
		return;
	}
}

/************************************************************************************
*
* Calculadora --> Operacions --> Multiplicar
*
************************************************************************************/

Calculadora.prototype.Multiplicar = function() {
	this.CodiError=0;
	this.DeterminarTipusResultat();
	if (this.CodiError<0) return;
	if (this.NombreR.Tipus==NOMBRE_ENTER) {
		this.NombreR.Num=this.NombreA.Num*this.NombreB.Num;
		this.NombreR.Den=1;
		this.NombreR.Contingut=true;
		return;
	}
	if (this.NombreR.Tipus==NOMBRE_FRACCIO) {
		this.NombreR.Num=this.NombreA.Num*this.NombreB.Num;
		this.NombreR.Den=this.NombreA.Den*this.NombreB.Den;
		this.NombreR.Contingut=true;
		this.NombreR.SimplificarFraccio(this.NoSimplificarFraccions);
		return;
	}		
	if (this.NombreR.Tipus==NOMBRE_DECIMAL) {
		this.NombreR.Dec=this.NombreA.Dec*this.NombreB.Dec;
		this.NombreR.Contingut=true;
		return;
	}
}

/************************************************************************************
*
* Calculadora --> Operacions --> Dividir
*
************************************************************************************/

Calculadora.prototype.Dividir = function () {
	this.CodiError=0;
	// Intenta fer la divisió NombreA/NombreB i deixar el resultat en NombreR
	// els enters els treballa com a fraccions i després mira si el resultat
	// és enter o no.
	// Si s'intenta dividir entre zero produeix un error de codi -2
	this.DeterminarTipusResultat();
	if (this.CodiError<0) return;
	if (this.NombreR.Tipus==NOMBRE_ENTER ||this.NombreR.Tipus==NOMBRE_FRACCIO) {
 		this.NombreR.Tipus=NOMBRE_FRACCIO; 	// Per defecte el resultat serà 
							// una fracció	
		this.DividirFraccions();
		return;
	}
	this.DividirDecimals();
}

Calculadora.prototype.DividirFraccions = function () {
	var Denominador=this.NombreA.Den*this.NombreB.Num;
	if (Denominador==0) {
		this.CodiError=-2;
		return ;
	}
	this.NombreR.Den=Denominador;
	this.NombreR.Num=this.NombreA.Num*this.NombreB.Den;
	this.NombreR.Contingut=true;
	this.NombreR.SimplificarFraccio(this.NoSimplificarFraccions);
	return;
}

Calculadora.prototype.DividirDecimals = function () {
	if (this.NombreB.EsZero()) {
		this.CodiError=-2;
		return ;
	}
	this.NombreR.Dec=this.NombreA.Dec/this.NombreB.Dec;
	this.NombreR.Contingut=true;
	return ;	
}


/************************************************************************************
*
* Calculadora --> Operacions --> Elevar
*
************************************************************************************/

Calculadora.prototype.Elevar = function () {
	// Intenta generar NombreR=NombreA^NombreB
	// Retorna el errors 
	//	-3 --> Resultat no numèric
	this.CodiError=0;
	this.DeterminarTipusResultat();
	if (this.CodiError<0) return;
	if (this.NombreR.Tipus==NOMBRE_ENTER) {
		this.ElevarEnters();
		return;
	}
	if (this.NombreR.Tipus==NOMBRE_FRACCIO) {
		this.ElevarFraccions();
		return;
	}	
	this.ElevarDecimals();
}		

Calculadora.prototype.ElevarEnters = function() {
	if (this.NombreB.Num<0) {
		// L'exponent és negatiu: a^(-n) = 1/(a^n)
		this.NombreR.Num=1;
		this.NombreR.Den=Math.pow(this.NombreA.Num,-this.NombreB.Num);
		this.NombreR.Tipus=2;
		this.NombreR.Contingut=true;
		if (!this.TestValorNumeric(this.NombreR.Den)) {
			this.NombreR.Contingut=false;
			return;
		}
		this.NombreR.SimplificarFraccio(this.NoSimplificarFraccions);
		return;
	}
	// L'exponent és positiu.
	this.NombreR.Den=1;
	this.NombreR.Num=Math.pow(this.NombreA.Num,this.NombreB.Num);
	this.NombreR.Contingut=false;
	if (this.TestValorNumeric(this.NombreR.Num)) {
		this.NombreR.Contingut=true;
		return;
	}
	this.NombreR.Contingut=false;
}
Calculadora.prototype.TestValorNumeric = function (Valor) {
	// Determina si un nombre és un valor numèric o no
	// i deixa resultat en CodiError
	if (this.NombreR.Num==NaN) {
		this.CodiError=-3;
		return (false);
	}
	if (this.NombreR.Num==Number.POSITIVE_INFINITY) {
		this.CodiError=-3;
		return (false);
	}
	if (this.NombreR.Num==Number.NEGATIVE_INFINITY) {
		this.CodiError=-3;
		return (false);
	}
	return (true);
}

Calculadora.prototype.ElevarFraccions = function() {
	if (this.NombreB.Tipus==1) {
		this.ElevarFraccionsExponentEnter();
		return;
	}
	BUGenElevarFraccions();
}
Calculadora.prototype.ElevarFraccionsExponentEnter = function() {
	//
	//           /   (a^n)/(b^n) si n>0
	//           |
	// (a/b)^n = |   1 si n=0 ( i Error si a/b = 0 )
	//           |
	//           \  (b^-n)/(a^-n) si n<0 ( i Error si a/b=0 )
	//

	this.NombreR.Contingut=false;

	if (this.NombreB.Num==0) {

		if (this.NombreA.Num==0) {
			this.CodiError=-3;
			return;
		}
		this.NombreR.Den=1;
		this.NombreR.Num=1;
		this.NombreR.Tipus=1;
		this.NombreR.Contingut=true;
		return;
	}
	if (this.NombreB.Num>0) {
		this.NombreR.Num=Math.pow(this.NombreA.Num,this.NombreB.Num);
		this.NombreR.Den=Math.pow(this.NombreA.Den,this.NombreB.Num);
		if (!this.TestValorNumeric(this.NombreR.Num)) return;
		if (!this.TestValorNumeric(this.NombreR.Den)) return;
		this.NombreR.Contingut=true;
		this.NombreR.SimplificarFraccio(this.NoSimplificarFraccions);
		return;
	} 	
	// this.NombreB.Num<0

	if (this.NombreA.Num==0) {
		this.CodiError=-3;
		return;
	}

	this.NombreR.Num=Math.pow(this.NombreA.Den,-this.NombreB.Num);
	this.NombreR.Den=Math.pow(this.NombreA.Num,-this.NombreB.Num);
	if (!this.TestValorNumeric(this.NombreR.Num)) return;
	if (!this.TestValorNumeric(this.NombreR.Den)) return;
	this.NombreR.Contingut=true;
	this.NombreR.SimplificarFraccio(this.NoSimplificarFraccions);
}

Calculadora.prototype.ElevarDecimals = function() {
	this.NombreR.Dec=Math.pow(this.NombreA.Dec,this.NombreB.Dec);
	this.NombreR.Contingut=true;
}

/************************************************************************************
*
* Calculadora --> Operacions --> Radicar
*
************************************************************************************/

Calculadora.prototype.Radicar = function () {
	// Intenta generar NombreR=NombreA^(1/NombreB)
	// Retorna el errors 
	//	-3 --> Resultat no numèric
	this.CodiError=0;
	this.DeterminarTipusResultat();
	if (this.CodiError<0) return;
	this.NombreA.Decimalitzar();
	this.RadicarDecimals();
}		

Calculadora.prototype.RadicarDecimals = function () {
	// Intenta generar NombreR=NombreA^(1/NombreB)
	// on la base és un decimal i NombreB és un enter positiu.
	var AvisBaseNegativa=false;
	var Base=this.NombreA.Dec;
	var Index=this.NombreB.Num;
	if (Base<0) {
		if (Index%2==0) {	// Si és parell
			this.CodiError=-3;
			return;
		}
		AvisBaseNegativa=true;
		Base=-Base;
	}
	var Resultat=Math.pow(Base,1/Index);
	if (AvisBaseNegativa) {
		Resultat=-Resultat;
	}
	this.NombreR.Dec=Resultat;
	this.NombreR.Tipus=3;
	this.NombreR.Contingut=true;	
}

/************************************************************************************
*
* Calculadora --> Operacions --> Igualar (Operació lògica)
*
************************************************************************************/

Calculadora.prototype.Igualar= function() {
	// fa l'operació lògica NombreA=NombreB
	// La comparació és purament numèrica sense importar el format dels respectius
	// nombres.
	// El Resultat queda en NombreR que tindrà un tipus VALOR_LOGIC

	var Resultat=this.Igualtat();
	if (Resultat) this.NombreR.Num=1;
	else this.NombreR.Num=0;
	this.NombreR.Tipus=4;	
}

Calculadora.prototype.Igualtat = function () {
	// Determina si NombreA==NombreB (true) o no (false)
	this.CodiError=0;
	if (this.ExigirTipusIguals==true) {
		if(this.NombreA.Tipus==NOMBRE_DECIMAL && this.NombreB.Tipus!=NOMBRE_DECIMAL) return(false);
		if(this.NombreB.Tipus==NOMBRE_DECIMAL && this.NombreA.Tipus!=NOMBRE_DECIMAL) return(false);
	}
	this.DeterminarTipusResultat();
	if (this.CodiError<0) return;	
	if (this.NombreR.Tipus==NOMBRE_ENTER || this.NombreR.Tipus==NOMBRE_FRACCIO) {
		return (this.IgualtatFraccions());
	}
	return (this.IgualtatDecimals());
}
Calculadora.prototype.IgualtatFraccions = function () {
	// Normalitzem les dues fraccions. D'aquesta manera són iguals si i només si
	// coincideixen numerador i denominador.
	// No les simplifiquem, ja que se suposa que serveix per a detectar si la 
	// resposta de l'exercici és correcta, i és l'usuari qui ha de simplificar...
	this.NombreA.NormalitzarFraccio();
	this.NombreB.NormalitzarFraccio();
	if (this.NombreA.Num!=this.NombreB.Num) return (false);
	if (this.NombreA.Den!=this.NombreB.Den) return (false);
	return (true);
}
Calculadora.prototype.IgualtatDecimals = function () {
	// Determina si dos nombres decimals són "iguals", tenint en compte el grau
	// de precisio.
	this.Restar();
	return (this.NombreR.EsZero());
}

/***********************************************************************************\
*
* Node
*
************************************************************************************/

function Node(PosicioDelPare) {

	// Contingut numèric del node.
	this.Nombre=new Nombre();

	// Variables per al manteniment de l'arbre.
	this.PosicioD=0;			// = Posicio si és un node final
	this.PosicioE=0;			// = Posicio si és un node final
	this.PosicioPare=PosicioDelPare;	// = Posicio (=0) si és un node inicial

	// GENESIS
	this.ResultatProposatPare=false;
	this.BrancaCompleta=false;
	this.NodeFet=false;
	this.NCiclesBranca=0;
	this.NOperacionsBranca=0; 		// S'utilitza en la construcció d'un arbre
						// per pauta aleatòria.

	// INPUT-OUTPUT
	this.TextBranca="";
	this.TextBrancaProtegit=""; 		// és el text que pot anar després d'una resta.
	this.TextIniciaAmbMenys=false;
}

Node.prototype.ResetNombre = function () {
	// Per a les rutines de GENESIS, esborra el contingut de la posició si 
	// és una posició que no té un valor fix
	if (!this.Nombre.ValorFix) this.Nombre.Contingut=false;
}

/***********************************************************************************\
*
* Arbre
*
************************************************************************************/

function Arbre(Index) {
	
	// Índex de l'arbre (únic per a cada arbre)
	// Serveix per a generar identificadors HTML únics
	if (!Index) Index=1;
	var IndexArbre=Index;

	/////////////////////////////////////////////////////////////////////////////
	//
	// Estructura dels nodes de l'arbre
	//
	/////////////////////////////////////////////////////////////////////////////
	
	this.Nodes=new Array();	
	this.Posicio=0; // Indica en tot moment la posició del Node actual.
	this.Nodes[0]=new Node(0);
	
	/////////////////////////////////////////////////////////////////////////////
	//
	// OUTPUT
	//
	/////////////////////////////////////////////////////////////////////////////

	this.LlenguatgeEscriptura=LLENGUATGE_MATEMATIC_ASCII;
	this.SimplificarMultiplicacionsPerUnitat=true; // 1*(3x+1)--> 3x+1
	this.EstalviarSimbolMultiplicacioAmbSumesRestes=false; // 3(5+1)

	this.EstalviarSimbolMultiplicarAmbArrels=true;
	this.NomesDivisionsEnHoritzontal=false;

	this.EstalviarExponentUnitat=true;	// A^1 --> A
	this.EscripturaAmbCodisEspecials=false; 

	this.TextOperacionsEncadenadesOperacions="";
	this.TextOperacionsEncadenadesResultats="";
	this.TextOperacionsEncadenadesOperands="";

	this.AfegirParentesisAnullat=false; // Per a escriure operacions encadenades

	
	/////////////////////////////////////////////////////////////////////////////
	//
	// INPUT
	//
	/////////////////////////////////////////////////////////////////////////////

	this.MyAnalitzador=new AnalitzadorText();

	/////////////////////////////////////////////////////////////////////////////
	//
	// MODIFICACIONS
	//
	/////////////////////////////////////////////////////////////////////////////

	this.MyCalculadora= new Calculadora();
	this.MaximaProfunditat=0;
	this.PosicioMaximaProfunditat=0;
}

/************************************************************************************
*
* Arbre -->  Reset
*
************************************************************************************/

Arbre.prototype.Reset = function() {
	//Esborra tots els nodes de l'arbre, però no toca la configuració
	this.Nodes=new Array();
	this.Nodes[0]=new Node(0);
	this.Posicio=0;
}

Arbre.prototype.InicialitzarArbre = function(){
	// Buida de contingut numèric l'arbre actual però deixa la seva estructura i 
	// les seves operacions. 
	for (var i=0;i<this.Nodes.length;i++) {
		this.Nodes[i].BrancaCompleta=false;
		this.Nodes[i].NCiclesBranca=this.MaxNCiclesBranca;
		this.Nodes[i].NodeFet=false;
		this.Nodes[i].ResultatProposatPare=false;
		this.Nodes[i].ResetNombre(); // Esborra contingut (si no és fix)
	}
	this.Posicio=0;
}

/************************************************************************************
*
* Arbre -->  Rutines comuns --> Gestió de les posicions
*
************************************************************************************/

Arbre.prototype.PosicioFinalPos= function(Posicio) {
	// Determina si el Node Posicio és una posició final o no.
	// El criteri és si els fills són el propi node	
	if (this.Nodes[Posicio]==undefined) {
		return true;
	}
	if (this.Nodes[Posicio].PosicioD==Posicio) return true;
	else return false;
}
Arbre.prototype.PosicioFinal= function() {
	// Determina si el Node actual és una posició final o no.
	return (this.PosicioFinalPos(this.Posicio));
}

Arbre.prototype.PosicioInicial= function() {
	// Determina si el Node actual és una posició inicial o no.
	// El criteri és si el pare és el propi node.
	if (this.Nodes[this.Posicio].PosicioPare==this.Posicio) return true;
	else return false;
}
Arbre.prototype.PosicioPare = function() {
	if (this.PosicioInicial()) return (this.Posicio);
	else return (this.Nodes[this.Posicio].PosicioPare);
}
Arbre.prototype.PosicioD=function() {
	if (this.PosicioFinal()) {
		return 0;
	} else {
		return (this.Nodes[this.Posicio].PosicioD);
	}
}
Arbre.prototype.PosicioE=function() {
	if (this.PosicioFinal()) {
		return 0;
	} else {
		return (this.Nodes[this.Posicio].PosicioE);
	}
}
Arbre.prototype.PosicioPare=function() {
	if (this.PosicioInicial()) {
		return 0;
	} else {
		return (this.Nodes[this.Posicio].PosicioPare);
	}
}
Arbre.prototype.Operacio = function () {
	return (this.Nodes[this.Posicio].Nombre.Operacio);
}
Arbre.prototype.OperacioD= function() {
	if (this.PosicioFinal()) {
		return -1;
	} else {
		return (this.Nodes[this.PosicioD()].Nombre.Operacio);
	}
}
Arbre.prototype.OperacioE= function() {
	if (this.PosicioFinal()) {
		return -1;
	} else {
		return (this.Nodes[this.PosicioE()].Nombre.Operacio);
	}
}
Arbre.prototype.EsNombrePos = function (Pos) {
	if (this.Nodes[Pos].Nombre.EsOperacio()) return (false);
	else return (true);
}
Arbre.prototype.EsNombreE = function () {
	return (this.EsNombrePos(this.PosicioE()));
}
Arbre.prototype.EsNombreD = function () {
	return (this.EsNombrePos(this.PosicioD()));
}
Arbre.prototype.ValorNumericPos = function (Pos) {
	return (this.Nodes[Pos].Nombre.ValorNumeric());
}
Arbre.prototype.ValorNumericE=function () {
	return (this.ValorNumericPos(this.PosicioE()));
}
Arbre.prototype.ValorNumericD=function () {
	return (this.ValorNumericPos(this.PosicioD()));
}
Arbre.prototype.ValorsIguals = function (PosicioA,PosicioB) {
	// comprova si dos posicions de l'arbre tenen el mateix valor 
	// numèric
	if (!this.Nodes[PosicioA].Nombre.Contingut) return (false);
	if (!this.Nodes[PosicioB].Nombre.Contingut) return (false);
	if (this.ValorNumericPos(PosicioA)==this.ValorNumericPos(PosicioB)) return (true);
	return (false);
}

Arbre.prototype.ValorsIgualsAbsoluts = function (PosicioA,PosicioB) {
	// comprova si dos posicions de l'arbre tenen el mateix valor 
	// numèric en valor absolut
	if (!this.Nodes[PosicioA].Nombre.Contingut) return (false);
	if (!this.Nodes[PosicioB].Nombre.Contingut) return (false);
	if (Math.abs(this.ValorNumericPos(PosicioA))==Math.abs(this.ValorNumericPos(PosicioB))) return (true);
	return (false);
}

Arbre.prototype.TipusPos = function (Pos) {
	return (this.Nodes[Pos].Nombre.Tipus);
}
Arbre.prototype.Tipus= function () {
	return (this.TipusPos(this.Posicio));
}
Arbre.prototype.TipusE= function () {
	return (this.TipusPos(this.PosicioE()));
}
Arbre.prototype.TipusD= function () {
	return (this.TipusPos(this.PosicioD()));
}

/************************************************************************************
*
* Arbre --> Rutines comuns --> Generació d'arbres i nodes
*
************************************************************************************/


Arbre.prototype.AfegirNode = function (PosicioDelPare) {
	// Afegeix un node nou a l'arbre, que penja del node PosicioDelPare
	// Retorna la seva posició.
	var PosicioDelNode=this.Nodes.length;
	this.Nodes[PosicioDelNode]=new Node(PosicioDelPare);
	this.Nodes[PosicioDelNode].PosicioD=PosicioDelNode; // és posició final
	this.Nodes[PosicioDelNode].PosicioE=PosicioDelNode; 	
	return (PosicioDelNode);
}

Arbre.prototype.GenerarDescendencia = function () {
	// Genera Nodes Dreta i Esquerra a la posició actual
	if (!this.PosicioFinal()) return; //Si ja té fills no es pot.
	var PosicioFill=this.AfegirNode(this.Posicio);
	this.Nodes[this.Posicio].PosicioE=PosicioFill;
	PosicioFill=this.AfegirNode(this.Posicio);
	this.Nodes[this.Posicio].PosicioD=PosicioFill;
}
Arbre.prototype.EliminarDescendencia = function () {
	// Elimina Nodes Dreta i Esquerra a la posició actual
	if (this.PosicioFinal()) return; //Si ja és final no fa res.
	this.Nodes[this.Posicio].PosicioE=this.Posicio;
	this.Nodes[this.Posicio].PosicioD=this.Posicio;
}

/***********************************************************************************\
*
* Arbre --> OUTPUT
*
************************************************************************************/

/************************************************************************************
*
* Arbre --> OUTPUT --> Resultat final
*
************************************************************************************/

Arbre.prototype.EscriureValorFinalArbre = function(TheLlenguatgeMatematic){
	// Retorna el valor final de l'arbre, el seu resultat numèric.
	// El LlenguatgeMatematic pot ser:
	//	LLENGUATGE_MATEMATIC_ASCII
	//	LLENGUATGE_MATEMATIC_OPEN_OFFICE
	// 	LLENGUATGE_MATEMATIC_MSWORD
	//	LLENGUATGE_MATEMATIC_TEX_MOODLE
	//	LLENGUATGE_MATEMATIC_MATHML

	this.LlenguatgeEscriptura=TheLlenguatgeMatematic;
	this.Posicio=0;
	this.EscriurePosicioFinal();
	return (this.AfegirCapICua(this.Nodes[0].TextBranca));
}

/************************************************************************************
*
* Arbre --> OUTPUT --> Tot l'arbre d'operacions.
*
************************************************************************************/

Arbre.prototype.EscriureArbre= function(MyLlenguatgeMatematic,PosicioMarcada){
	//Retorna l'escriptura associada a l'arbre.
	//Si PosicioMarcada>=0 remarca la posició
	if (!PosicioMarcada) PosicioMarcada=-1;
	this.LlenguatgeEscriptura=MyLlenguatgeMatematic;
	this.EscripturaAmbCodisEspecials=false;
	this.EscriureBrancaRecursivament(0,PosicioMarcada);
	var Text=this.Nodes[0].TextBranca;
	Text=this.AfegirCapICua(Text);
	return (Text);
}
	
Arbre.prototype.EscriureBrancaRecursivament= function(PosicioBranca,PosicioMarcada){
	//Retorna l'escriptura associada a l'arbre.
	this.Posicio=PosicioBranca;
	if (this.PosicioFinal()) {
		this.EscriurePosicioFinal();
		return;
	}
	this.Posicio=PosicioBranca;
	this.EscriureBrancaRecursivament(this.PosicioD(),PosicioMarcada);
	this.Posicio=PosicioBranca;
	this.EscriureBrancaRecursivament(this.PosicioE(),PosicioMarcada);
	this.Posicio=PosicioBranca;
	this.EscriureOperacio();
	this.Posicio=PosicioBranca;
	// Si la Posició és la posició a remarcar, la remarca
	if (this.Posicio==PosicioMarcada) {
		if (this.LlenguatgeEscriptura==0) {
			this.Nodes[this.Posicio].TextBranca="<b>"+this.Nodes[this.Posicio].TextBranca+"</b/>";
		}
		if (this.LlenguatgeEscriptura==4) {
			this.Nodes[this.Posicio].TextBranca='<mo>[</mo>'+this.Nodes[this.Posicio].TextBranca+"<mo>]</mo>";

		}
	}
}

/************************************************************************************
*
* Arbre --> OUTPUT --> Tot l'arbre d'operacions i el seu resultat amb el símbol "="
*
************************************************************************************/

Arbre.prototype.EscriureArbreIResultat= function(MyLlenguatgeMatematic){
	//Retorna l'escriptura associada a l'arbre i el seu resultat
	this.LlenguatgeEscriptura=MyLlenguatgeMatematic;
	this.EscripturaAmbCodisEspecials=false;
	this.EscriureBrancaRecursivament(0,-1);
	var Text1=this.Nodes[0].TextBranca;

	this.Posicio=0;
	this.EscriurePosicioFinal();
	var Text2=this.Nodes[0].TextBranca;

	// Unim amb un símbol "="
	var Text="";
	switch(MyLlenguatgeMatematic) {
		case LLENGUATGE_MATEMATIC_OPEN_OFFICE: 	Text=Text1+" = "+Text2;
							break;
		case LLENGUATGE_MATEMATIC_MSWORD: 	Text=Text1+" = "+Text2;
							break;
		case LLENGUATGE_MATEMATIC_TEX_MOODLE: 	Text=Text1+" = "+Text2;
							break;
		case LLENGUATGE_MATEMATIC_MATHML: 	Text=Text1+"<mo>=</mo>"+Text2;
							break;
		default:				Text=Text1+" = "+Text2;
	}
	Text=this.AfegirCapICua(Text);
	return (Text);
}

/************************************************************************************
*
* Arbre --> OUTPUT --> Només els nombres utilitzats separats per ###
*
************************************************************************************/

Arbre.prototype.EscriureNombresDelArbre= function(MyLlenguatgeMatematic){
	// Genera una cadena amb tots els nombres de l'arbre separats per ###
	// No necessàriament ha de ser una operació encadenada.
	this.LlenguatgeEscriptura=MyLlenguatgeMatematic;
	return (this.EscriureNombresDelArbreRecursivament(0));
}

Arbre.prototype.EscriureNombresDelArbreRecursivament= function(PosicioActual){
	// Si és una posició final, retornem el seu valor
	this.Posicio=PosicioActual;
	if (this.PosicioFinal()) {
		this.EscriurePosicioFinal();
		return(this.Nodes[PosicioActual].TextBranca);
			}
	// Si no, retornem la unió de la part dreta i la part esquerra
	var TextDreta=this.EscriureNombresDelArbreRecursivament(this.PosicioD());
	this.Posicio=PosicioActual;
	var TextEsquerra=this.EscriureNombresDelArbreRecursivament(this.PosicioE());
	return(TextDreta+"###"+TextEsquerra);
}

/************************************************************************************
*
* Arbre --> OUTPUT --> Elements complementaris a la cadena de sortida
*
************************************************************************************/

Arbre.prototype.AfegirCapICua = function(Text) {
	// Afegim codis especials davant i darrera.

	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_TEX_MOODLE) {
		Text="$$ " + Text + " $$";
	}

	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MATHML) {
		Text='<math>' + Text + "</math>";
	}
	
	return (Text);
}
/************************************************************************************
*
* Arbre --> OUTPUT --> Operacions encadenades
*
************************************************************************************/

Arbre.prototype.EscriureArbreOperacionsEncadenades= function(MyLlenguatgeMatematic){
	// Genera les variables 
	//	this.TextOperacionsEncadenadesOperacions 
	// 	this.TextOperacionsEncadenadesResultats
	//  	this.TextOperacionsEncadenadesOperands 
	// amb la cadena d'operacions separades per "###"
	this.TextOperacionsEncadenadesOperacions="";
	this.TextOperacionsEncadenadesResultats="";
	this.TextOperacionsEncadenadesOperands="";
	this.LlenguatgeEscriptura=MyLlenguatgeMatematic;
	this.EscriureArbreOperacionsEncadenadesRecursivament(0);
}

Arbre.prototype.EscriureArbreOperacionsEncadenadesRecursivament= function(PosicioActual){
	// Escrivim la part dreta, que és un nombre
	this.Posicio=PosicioActual;
	this.Posicio=this.PosicioD();	
	this.EscriurePosicioFinal();

	// Agafem el valor protegit per al operand per a que no surtin coses com --9
	var Text=this.AfegirCapICua(this.Nodes[this.Posicio].TextBrancaProtegit);
	this.TextOperacionsEncadenadesOperands= Text + "###"+ this.TextOperacionsEncadenadesOperands;
	
	this.Posicio=PosicioActual;

	// Afegim l'operació actual a la cadena d'operacions
	var Text=this.AfegirCapICua(this.NomOperacioPosicioActual());
	this.TextOperacionsEncadenadesOperacions= Text + "###"+ this.TextOperacionsEncadenadesOperacions;

	// Afegim el resultat actual a la cadena d'operacions.

	this.EscriurePosicioFinal();
	var Text=this.AfegirCapICua(this.Nodes[this.Posicio].TextBranca);
	this.TextOperacionsEncadenadesResultats=Text + "###" + this.TextOperacionsEncadenadesResultats;

	// Passem a l'anterior recursivament.
	this.Posicio=this.PosicioE();
	if (this.PosicioFinal()) {
		// Si estem al final afegim l'últim nombre
		this.EscriurePosicioFinal();
		this.TextOperacionsEncadenadesOperacions= "N###"+ this.TextOperacionsEncadenadesOperacions;
		this.TextOperacionsEncadenadesResultats=this.Nodes[this.Posicio].TextBranca + "###" + this.TextOperacionsEncadenadesResultats;
		this.TextOperacionsEncadenadesOperands=this.Nodes[this.Posicio].TextBranca + "###"+ this.TextOperacionsEncadenadesOperands;
		return;
	}		
	this.EscriureArbreOperacionsEncadenadesRecursivament(this.Posicio);		
}
	
Arbre.prototype.NomOperacioPosicioActual= function(Pos){
	Token="?";
	switch(this.Operacio()) {
		case 0 : //NOMBRE
			Token="N";
			break;
		case 1: // SUMAR
			Token="+";
			if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MATHML) {
				Token="<mo>+</mo>";
			}
			break;

		case 2: // RESTAR
			Token="-";
			if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MATHML) {
				Token="<mo>-</mo>";
			}
			break;

		case 3: // MULTIPLICAR
			Token=this.SeleccionarSimbolMultiplicacio();
			break;

		case 4: // DIVIDIR
			Token=this.SeleccionarSimbolDivisio();
			break;

		case 5: // ELEVAR
			Token="^";
			break;

		case 6: // RADICAR
			Token="R";
			break;

		case 9: // IGUALTAT
			Token="=";
			break;
		default: // ???
			Token="?";
	}
	return (Token);
}

/************************************************************************************
*
* Arbre --> OUTPUT --> Posició Final
*
************************************************************************************/

Arbre.prototype.EscriurePosicioFinal= function() {
	// Escrivim el nombre que hi ha a la posició (no necessàriament ha de ser un 
	// nombre pot ser el resultat d'una operació)
	//
	// 
	//
	var PosicionsDecimals=3;
	if (MyGenerador.Items[6]) {
		if (MyGenerador.Items[6].Items[4]) PosicionsDecimals=MyGenerador.Items[6].Items[4].Valor;
	}
	this.Nodes[this.Posicio].Nombre.EscriureNombre(this.LlenguatgeEscriptura,PosicionsDecimals);
	this.Nodes[this.Posicio].TextBranca=this.Nodes[this.Posicio].Nombre.TextNombre;
	this.Nodes[this.Posicio].TextIniciaAmbMenys=this.Nodes[this.Posicio].Nombre.TextIniciaAmbMenys;
	if (this.Nodes[this.Posicio].Nombre.CodisEspecials)  this.EscripturaAmbCodisEspecials=true;	
	// Si el nombre comença amb "-" cal generar un TextProtegit adequat
	if (this.Nodes[this.Posicio].TextIniciaAmbMenys) {
		this.Nodes[this.Posicio].TextBrancaProtegit=this.AfegirParentesis(this.Nodes[this.Posicio].TextBranca);
	} 
	else {
		this.Nodes[this.Posicio].TextBrancaProtegit=this.Nodes[this.Posicio].TextBranca;
	}	
	if (this.Nodes[this.Posicio].Nombre.TextFix) {
		// L'escriptura de paraules en MathML demana prefix XML
		if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MATHML) {
			this.Nodes[this.Posicio].TextBranca='<mi>' + this.Nodes[this.Posicio].TextBranca + "</mi>";
			this.Nodes[this.Posicio].TextBrancaProtegit='<mi>' + this.Nodes[this.Posicio].TextBrancaProtegit + "</mi>";
		}
	}

}

/************************************************************************************
*
* Arbre --> OUTPUT --> Operació
*
************************************************************************************/

Arbre.prototype.EscriureOperacio= function() {
	switch (this.Operacio()) {
		case SUMAR : this.EscriureOperacioSumar();break;
		case RESTAR : this.EscriureOperacioRestar();break;
		case MULTIPLICAR : this.EscriureOperacioMultiplicar();break;
		case DIVIDIR : this.EscriureOperacioDividir();break;
		case ELEVAR : this.EscriureOperacioElevar();break;
		case RADICAR : this.EscriureOperacioRadicar();break;
		default: return -4;		
	}
}

/************************************************************************************
*
* Arbre --> OUTPUT --> Operació --> Sumar
*
************************************************************************************/

Arbre.prototype.EscriureOperacioSumar= function(){
	var NomOperacio="";
	var TextE="";
	var TextD="";

	// Generem la codificació del símbol "+"

	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MATHML) {
		NomOperacio="<mo>+</mo>";
		this.EscripturaAmbCodisEspecials=true;
	}
	else NomOperacio="+";
	
	TextE=this.Nodes[this.PosicioE()].TextBranca;
	
	// Si la part dreta comença amb "-" cal agafar el text protegit 
	// per exemple," 2 "+ " -3 + 1 "--> " 2 " + " (-3) + 1 "

	if (this.Nodes[this.PosicioD()].TextIniciaAmbMenys) 
		TextD=this.Nodes[this.PosicioD()].TextBrancaProtegit;
	else TextD=this.Nodes[this.PosicioD()].TextBranca;
		
	// Escrivim l'operació

	this.Nodes[this.Posicio].TextBranca=TextE+" "+NomOperacio+" "+TextD;

	// Escrivim l'operació protegida 

	this.Nodes[this.Posicio].TextIniciaAmbMenys=this.Nodes[this.PosicioE()].TextIniciaAmbMenys;
	
	if (this.Nodes[this.PosicioE()].TextIniciaAmbMenys) {
		this.Nodes[this.Posicio].TextBrancaProtegit=this.Nodes[this.PosicioE()].TextBrancaProtegit+" "+NomOperacio+" "+TextD;
	}
	else {		
		this.Nodes[this.Posicio].TextBrancaProtegit=this.Nodes[this.Posicio].TextBranca;
	}
}


/************************************************************************************
*
* Arbre --> OUTPUT --> Operació --> Restar
*
************************************************************************************/

Arbre.prototype.EscriureOperacioRestar= function(){
	var NomOperacio="";
	var TextE="";
	var TextD="";

	// Generem la codificació del símbol "-"

	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MATHML) {
		NomOperacio="<mo>-</mo>";
		this.EscripturaAmbCodisEspecials=true;
	}
	else NomOperacio="-";
	
	TextE=this.Nodes[this.PosicioE()].TextBranca;
	TextD=this.Nodes[this.PosicioD()].TextBranca	
	
	// Si l'operació Dreta és una suma o una resta cal afegir-ne parèntesis
	// Exemple: " 3 " - " 4 + 1 "  --> " 3 " - " ( 4 + 1 ) "	

	if (this.OperacioD()==SUMAR || this.OperacioD()==RESTAR) 
		TextD=this.AfegirParentesis(TextD);
	else {
		//Si no va entre parèntesis,cal mirar si la PosicioD comença
		//amb el signe "-"
		// Si la PosicioD comença amb "-" cal agafar-ne la protegida.
		if (this.Nodes[this.PosicioD()].TextIniciaAmbMenys) 
			TextD=this.Nodes[this.PosicioD()].TextBrancaProtegit;
		else TextD=this.Nodes[this.PosicioD()].TextBranca;
	}	 		

	// Si OperacioE és el nombre 0 , 0 - B --> -B i comença per menys.

	if (this.EsNombreE()) {
		if (this.Nodes[this.PosicioE()].Nombre.EsZero()) {
			this.Nodes[this.Posicio].TextBranca=NomOperacio+" "+TextD;
			this.Nodes[this.Posicio].TextIniciaAmbMenys=true;
			this.Nodes[this.Posicio].TextBrancaProtegit=this.AfegirParentesis(this.Nodes[this.Posicio].TextBranca);
			return;
		}
	}

	// És una resta normal, escrivim l'operació

	this.Nodes[this.Posicio].TextBranca=TextE+" "+NomOperacio+" "+TextD;

	// Escrivim l'operació protegida 

	this.Nodes[this.Posicio].TextIniciaAmbMenys=this.Nodes[this.PosicioE()].TextIniciaAmbMenys;
	
	if (this.Nodes[this.PosicioE()].TextIniciaAmbMenys) {
		this.Nodes[this.Posicio].TextBrancaProtegit=this.Nodes[this.PosicioE()].TextBrancaProtegit+" "+NomOperacio+" "+TextD;
	}
	else {		
		this.Nodes[this.Posicio].TextBrancaProtegit=this.Nodes[this.Posicio].TextBranca;
	}
}

/************************************************************************************
*
* Arbre --> OUTPUT --> Operació --> Multiplicar
*
************************************************************************************/

Arbre.prototype.EscriureOperacioMultiplicar= function(){
	//Escriu una multiplicació.	
	var PartDretaJaProtegida=false;
	var SimbolMultiplicacio=this.SeleccionarSimbolMultiplicacio();
	
	// Si es multiplica per 1 no cal posar-lo
	
	if (this.SimplificarMultiplicacionsPerUnitat) {
		if (this.EsNombreE()) {
			if (this.ValorNumericE()==1) {
				this.Nodes[this.Posicio].TextBranca=this.Nodes[this.PosicioD()].TextBranca;
				this.Nodes[this.Posicio].TextBrancaProtegit=this.Nodes[this.PosicioD()].TextBrancaProtegit;
				this.Nodes[this.Posicio].TextIniciaAmbMenys=this.Nodes[this.PosicioD()].TextIniciaAmbMenys;
				return;
			}
		}
		if (this.EsNombreD()) {
			if (this.ValorNumericD()==1) {
				this.Nodes[this.Posicio].TextBranca=this.Nodes[this.PosicioE()].TextBranca;
				this.Nodes[this.Posicio].TextBrancaProtegit=this.Nodes[this.PosicioE()].TextBrancaProtegit;
				this.Nodes[this.Posicio].TextIniciaAmbMenys=this.Nodes[this.PosicioE()].TextIniciaAmbMenys;
				return;
			}
		}
	}
	var TextE=this.Nodes[this.PosicioE()].TextBranca;
	var TextD=this.Nodes[this.PosicioD()].TextBranca;
	var TextProtegitE=false;//Indica si la part Esquerra estarà protegida.			
	// Si D és una suma o una resta cal afegir parèntesis
	if (this.OperacioD()==SUMAR || this.OperacioD()==RESTAR) {
		TextD=this.AfegirParentesis(TextD);
		if (this.EstalviarSimbolMultiplicacioAmbSumesRestes) SimbolMultiplicacio="";
		PartDretaJaProtegida=true;
	}
	// Si E és una suma o una resta cal afegir parèntesis

	if (this.OperacioE()==SUMAR || this.OperacioE()==RESTAR) {
		TextE=this.AfegirParentesis(TextE);
		TextProtegitE=true;
		//En principi no s'estalvia el símbol de multiplicació
		//Perquè no queda bé una expressió com (3 + 4)7
	}

	// Si D és un literal ens podem estalviar el símbol de multiplicar
	if (this.Nodes[this.PosicioD()].Nombre.TextFix==true) SimbolMultiplicacio="";

	// Si E és una arrel ens podem estalviar el símbol de multiplicar

	if (this.EstalviarSimbolMultiplicarAmbArrels) {
		if (this.OperacioD()==RADICAR) SimbolMultiplicacio="";
	}
	
	// Si D comença amb "-" cal agafar l'expressió D "protegida" amb parèntesis
	if (this.Nodes[this.PosicioD()].TextIniciaAmbMenys && PartDretaJaProtegida==false) {
		TextD=this.Nodes[this.PosicioD()].TextBrancaProtegit;
	}

	// Escrivim l'operació
	
	this.Nodes[this.Posicio].TextBranca=TextE+" "+SimbolMultiplicacio+" "+TextD;

	// Escrivim la versió protegida

	if (TextProtegitE) {
		//La part Esquerra ja s'ha protegit amb parèntesis
		this.Nodes[this.Posicio].TextBrancaProtegit=this.Nodes[this.Posicio].TextBranca;
		this.Nodes[this.Posicio].TextIniciaAmbMenys=false;
	} 
	else {
		//La part Esquerra no s'ha protegit ara
		this.Nodes[this.Posicio].TextBrancaProtegit=this.Nodes[this.PosicioE()].TextBrancaProtegit+SimbolMultiplicacio+" "+TextD;
		this.Nodes[this.Posicio].TextIniciaAmbMenys=this.Nodes[this.PosicioE()].TextIniciaAmbMenys;
	}
}	

Arbre.prototype.SeleccionarSimbolMultiplicacio= function () {
	//Retorna el símbol de la multiplicació.
	var CodiOperacio="x";
	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_ASCII || 
		this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MSWORD ||
		this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_OPEN_OFFICE) {
		if (MyGenerador.Items[6].Items[3].Valor==1) CodiOperacio="·"; // Un punt flotant
		if (MyGenerador.Items[6].Items[3].Valor==2) CodiOperacio="x"; // Un aspa representat per la lletra x
		if (MyGenerador.Items[6].Items[3].Valor==3) CodiOperacio="*"; // Un asterisc
		if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_OPEN_OFFICE)
			CodiOperacio=" "+CodiOperacio+" ";
	}
	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_TEX_MOODLE) {
		if (MyGenerador.Items[6].Items[3].Valor==1) {
			CodiOperacio="\\cdot"; 
			this.EscripturaAmbCodisEspecials=true;
		}
		if (MyGenerador.Items[6].Items[3].Valor==2) {
			CodiOperacio="\\times";
			this.EscripturaAmbCodisEspecials=true;
 		}
		if (MyGenerador.Items[6].Items[3].Valor==3) {
			CodiOperacio="*"; 
		}
	}
	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MATHML) {
		if (MyGenerador.Items[6].Items[3].Valor==1) {
			CodiOperacio="<mo>&middot;</mo>"; 
			this.EscripturaAmbCodisEspecials=true;
		}
		if (MyGenerador.Items[6].Items[3].Valor==2) {
			CodiOperacio="<mo>&#xD7;</mo>";
			this.EscripturaAmbCodisEspecials=true;
 		}
		if (MyGenerador.Items[6].Items[3].Valor==3) {
			CodiOperacio="<mo>*</mo>";
			this.EscripturaAmbCodisEspecials=true;
 
		}
	}
	return (CodiOperacio);
}	

/************************************************************************************
*
* Arbre --> OUTPUT --> Operació --> Dividir
*
************************************************************************************/

Arbre.prototype.EscriureOperacioDividir= function(){
	//Genera la codificació d'una divisió
	if (this.TestEscriureOperacioDividirHoritzontal())
		this.EscriureOperacioDividirHoritzontal();
	else this.EscriureOperacioDividirVertical();
}

Arbre.prototype.TestEscriureOperacioDividirHoritzontal = function (){
	// Determina si cal escriure la divisió en horitzontal (true)
	// o en vertical (false)
	if (this.NomesDivisionsEnHoritzontal) return (true);
	//if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_ASCII) return (true);   // <-- TO DO encara no tinc la codificació vertical de l'escriptura ASCII
	if (this.LlenguatgeEscriptura!=LLENGUATGE_MATEMATIC_MATHML) return (true);   

	if (MyGenerador.Items[6].Items[1].Valor==1) {
		//
		// No entenc molt bé perquè vaig posar aquests filtres...
		//
		if (this.EsNombreD()) {
			var p=this.PosicioD();
			if (this.Nodes[p].Nombre.Tipus==2) return (false);
		}
		if (this.EsNombreE()) {
			var p=this.PosicioE();
			if (this.Nodes[p].Nombre.Tipus==2) return (false);
		}
		return(true);
	}
	return (false);
}

Arbre.prototype.EscriureOperacioDividirHoritzontal = function() {
	//Genera la codificació d'una divisió en horitzontal
	var SimbolDivisio=this.SeleccionarSimbolDivisio();
	var TextE=this.Nodes[this.PosicioE()].TextBranca;
	var TextD=this.Nodes[this.PosicioD()].TextBranca;
	var TextProtegitE=false; //Indica si la part Esquerra estarà protegida.			
	//Si l'esquerra és una operació, cal afegir parèntesis.
	if (!this.EsNombreE()) {
		TextE=this.AfegirParentesis(TextE);
		TextProtegitE=true;
	}	
	//Si la dreta és una operació, cal afegir parèntesis.
	//o si comença amb menys
	if (!this.EsNombreD()) {
		TextD=this.AfegirParentesis(TextD);
	}
	else {
		if (this.Nodes[this.PosicioD()].TextIniciaAmbMenys) {
			TextD=this.AfegirParentesis(TextD)
		}
	}

	this.Nodes[this.Posicio].TextBranca=TextE+" "+SimbolDivisio+" "+TextD;

	if (TextProtegitE) {
		//La part Esquerra ja s'ha protegit amb parèntesis
		this.Nodes[this.Posicio].TextBrancaProtegit=this.Nodes[this.Posicio].TextBranca;
		this.Nodes[this.Posicio].TextIniciaAmbMenys=false;
	} 
	else {
		//La part Esquerra no s'ha protegit ara
		this.Nodes[this.Posicio].TextBrancaProtegit=this.Nodes[this.PosicioE()].TextBrancaProtegit+SimbolDivisio+" "+TextD;
		this.Nodes[this.Posicio].TextIniciaAmbMenys=this.Nodes[this.PosicioE()].TextIniciaAmbMenys;
	}		
	
}

Arbre.prototype.SeleccionarSimbolDivisio= function () {
	//Retorna el símbol de la divisió (en horitzontal).
	var CodiOperacio="/"; // Per defecte és una barra.
	if (MyGenerador.Items[6].Items[2].Valor==2) { // El símbol de la divisió tipus calculadora Casio
		if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_TEX_MOODLE) {
			CodiOperacio="\\div";
		}
		if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MSWORD) {
			CodiOperacio="÷";
		}
		if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MATHML) {
			CodiOperacio="<mo>÷</mo>";
		}
		if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_ASCII) {
			CodiOperacio="&divide;";
		}		
	}
	else {
		if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_TEX_MOODLE) {
			CodiOperacio="\\div";
		}
		if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MSWORD) {
			CodiOperacio="/";
		}
		if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MATHML) {
			CodiOperacio="<mo>/</mo>";
		}
		if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_ASCII) {
			CodiOperacio="/";
		}		
	}
	return (CodiOperacio);
}

Arbre.prototype.EscriureOperacioDividirVertical = function() {
	//Genera la codificació d'una divisió en vertical
	var Text="";
	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MATHML) {
		var TextE=this.Nodes[this.PosicioE()].TextBranca;
		if (this.Nodes[this.PosicioE()].Nombre.Operacio==4) {
			TextE="<mo>&emsp;</mo>"+TextE+"<mo>&emsp;</mo>";
		}
		var TextD=this.Nodes[this.PosicioD()].TextBranca;
		if (this.Nodes[this.PosicioD()].Nombre.Operacio==4) {
			TextD="<mo>&emsp;</mo>"+TextD+"<mo>&emsp;</mo>";
		}
		Text="<mfrac> <mrow>" + TextE + "</mrow> <mrow>" + TextD + "</mrow> </mfrac> ";
		this.Nodes[this.Posicio].TextBranca=Text;
		this.Nodes[this.Posicio].TextBrancaProtegit=Text; // En vertical no cal protegir.
		this.Nodes[this.Posicio].TextIniciaAmbMenys=false;
		this.EscripturaAmbCodisEspecials=true;
		return;
 
	}
	BUGenEscriureOperacioDividirVertical();
}


/************************************************************************************
*
* Arbre --> OUTPUT --> Operació --> Elevar
*
************************************************************************************/

Arbre.prototype.EscriureOperacioElevar= function(){
	var TextE=this.Nodes[this.PosicioE()].TextBranca;
	var TextD=this.Nodes[this.PosicioD()].TextBranca;
	var TextEAmbParentesis=false;	// Per a evitar afegir dues vegades parèntesis
	var Text;
	// Si tenim una potència del tipus A^1 queda com a A
	if (this.EsNombreD()) {
		if (this.ValorNumericD()==1) {
			if (this.EstalviarExponentUnitat) {
				this.Nodes[this.Posicio].TextBranca=TextE;
				this.Nodes[this.Posicio].TextBrancaProtegit=this.Nodes[this.PosicioE()].TextBrancaProtegit;
				this.Nodes[this.Posicio].TextIniciaAmbMenys=this.Nodes[this.PosicioE()].TextIniciaAmbMenys;
				return;
			}
		}
	}

	// Si cal, afegim parèntesis a la base

	// Si la base és una operació, cal afegir parèntesis.

	if (!this.EsNombreE()) {
		if (!TextEAmbParentesis) {
			TextE=this.AfegirParentesis(TextE);
			TextEAmbParentesis=true;
		}
	}
	
	//Si l'esquerra és una fracció (amb denominador <>1) cal afegir-ne parèntesis
	
	if (this.EsNombreE()) {
		if (this.Nodes[this.PosicioE()].Nombre.Tipus==2) {
			if (!TextEAmbParentesis) {
				TextE=this.AfegirParentesis(TextE);
				TextEAmbParentesis=true;
			}
		}
	}	

	// Si l'esquerra comença per - , cal afegir-ne parèntesis
	
	if (!TextEAmbParentesis) {
		if (this.Nodes[this.PosicioE()].TextIniciaAmbMenys) {
			TextE=this.AfegirParentesis(TextE);	
			TextEAmbParentesis=true;
		}
	}	

	// Escrivim l'operació:

	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MATHML) {
		Text="<msup> <mrow>" + TextE + "</mrow> <mrow> " + TextD + "</mrow> </msup>";
	}

	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_ASCII) {
		// Si l'exponent no és un nombre enter positiu, cal afegir parèntesis
		if (!this.TestExponentEnterPositiu()) {
			TextD=this.AfegirParentesis(TextD);
		}
     		Text= TextE + " ^ " + TextD;
	}     	
	
	this.Nodes[this.Posicio].TextBranca=Text;
	// Una potència mai comença per "-"   -A^B --> (-A)^B
	this.Nodes[this.Posicio].TextBrancaProtegit=Text;
	this.Nodes[this.Posicio].TextIniciaAmbMenys=false;			
}		        

Arbre.prototype.TestExponentEnterPositiu= function(){
	if (this.EsNombreD()) {
		if (this.Nodes[this.PosicioD()].Nombre.Tipus==1) {
	 		if (this.ValorNumericD()>0) {
				return (true);
			}
		}
	}
	return (false);
}		


/************************************************************************************
*
* Arbre --> OUTPUT --> Operació --> Radicar
*
************************************************************************************/

Arbre.prototype.EscriureOperacioRadicar= function(){
	var TextE=this.Nodes[this.PosicioE()].TextBranca;
	var TextD=this.Nodes[this.PosicioD()].TextBranca;
	var Text;
	// Si l'índex és 2, ho tenim en compte, perquè normalment és un símbol especial
	var AvisArrelQuadrada=false;
	if (this.EsNombreD()) {
		if (this.Nodes[this.PosicioD()].Nombre.Tipus==1) {
	 		if (this.ValorNumericD()==2) {
				AvisArrelQuadrada=true;
			}
		}
	}
	
	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_ASCII) {
		Text=TextE + " ^ (1/" + TextD +")";
	}

	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MSWORD) {
		this.EscripturaAmbCodisEspecials=true;
		if (AvisArrelQuadrada) Text= " \R(" + TextE + ") ";
		else Text= " \R(" + TextD + ";" + TextE + ") ";
	}

	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_OPEN_OFFICE) { // <-- TO DO: Codificació OO de les arrels.
		Text=TextE + " ^ ( 1 / " + TextE +" )";
	}

	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_TEX_MOODLE) {
		this.EscripturaAmbCodisEspecials=true;
		if (AvisArrelQuadrada) Text= "\\sqrt(" + TextE + ") ";
		else Text= "\\sqrt[" + TextD + "]\\{" + TextE + "\\} ";
	}				

	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MATHML) {
		this.EscripturaAmbCodisEspecials=true;
		if (AvisArrelQuadrada) Text= "<msqrt> " + TextE + "</msqrt>";
		else Text= "<mroot>" + "<mrow>" + TextE + "</mrow>" + " <mrow>" + TextD + "</mrow> " + "</mroot>";
	}				

	this.Nodes[this.Posicio].TextBranca=Text;
	// Una arrel mai comença per "-" 
	this.Nodes[this.Posicio].TextBrancaProtegit=Text;
	this.Nodes[this.Posicio].TextIniciaAmbMenys=false;			
}  

/************************************************************************************
*
* Arbre --> OUTPUT --> Parèntesis
*
************************************************************************************/

Arbre.prototype.AfegirParentesis = function(Text){
	//Retorna Text amb uns parèntesis afegits.
	if (this.AfegirParentesisAnullat==true) return (Text);
	var ParentesisDreta=")";
	var ParentesisEsquerra="(";
	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_ASCII) {
		// Per defecte
	}
	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_OPEN_OFFICE) {
		// Per defecte
	}
	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MSWORD) {
		ParentesisEsquerra="\B(";
		ParentesisDreta=")";
		this.CodisEspecialsEscriptura=true;
	}
	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_TEX_MOODLE) {
		ParentesisEsquerra="\\left(";
		ParentesisDreta="\\right)";
		this.CodisEspecialsEscriptura=true;
	}
	if (this.LlenguatgeEscriptura==LLENGUATGE_MATEMATIC_MATHML) {
		ParentesisEsquerra="<mo>(</mo><mrow>";
		ParentesisDreta="</mrow><mo>)</mo>";
		this.CodisEspecialsEscriptura=true;
	}
	return(ParentesisEsquerra+Text+ParentesisDreta);	
}

function NodeConstruir() {
	this.NCiclesBranca=0;
	this.BrancaConstruida=false;
	this.NOperacionsBranca=0;
}

/***********************************************************************************\
*
* Arbre --> MODIFICACIONS
*
************************************************************************************/

/************************************************************************************
*
* Arbre --> MODIFICACIONS --> Avaluar arbre
*
************************************************************************************/

Arbre.prototype.AvaluarArbre = function () {
	// Realitza totes les operacions numèriques de l'arbre.
	// Torna <0 si no ha pogut, 1 = OK
	//	-1 = Arbre amb posició final no numèrica.
	//	1 = OK
	return (this.AvaluarBrancaRecursivament(0));
}
Arbre.prototype.AvaluarBrancaRecursivament = function (PosicioBranca) {
	// Avalua la branca indicada.
	this.Posicio=PosicioBranca;
	
	// Si és una posició final no cal fer res
	
	if (this.PosicioFinal()) {
		if (!this.Nodes[this.Posicio].Nombre.Contingut) return (-1);
		else return (1);
	}	
	// Si no, fem les subbranques recursivament i després l'operació
	var Status=this.AvaluarBrancaRecursivament(this.PosicioD());
	if (Status<0) return (Status);
	this.Posicio=PosicioBranca;
	Status=this.AvaluarBrancaRecursivament(this.PosicioE());
	if (Status<0) return (Status);
	this.Posicio=PosicioBranca;	
	return (this.AvaluarNode());
}

Arbre.prototype.AvaluarNode = function () {
	// Recalcula el resultat del node de la posició actual.
	// Se suposa que hi ha una operació
	this.MyCalculadora.NombreA=this.Nodes[this.PosicioE()].Nombre;
	this.MyCalculadora.NombreB=this.Nodes[this.PosicioD()].Nombre;
	switch (this.Operacio()) {
		case SUMAR : this.MyCalculadora.Sumar();break;
		case RESTAR : this.MyCalculadora.Restar();break;
		case MULTIPLICAR : this.MyCalculadora.Multiplicar();break;
		case DIVIDIR : this.MyCalculadora.Dividir();break;
		case ELEVAR : this.MyCalculadora.Elevar();break;
		case RADICAR : this.MyCalculadora.Radicar();break;
		case IGUALTAT : this.MyCalculadora.Igualar();break;
		default: BUGOperacio();		
	}
	if (this.MyCalculadora.CodiError<0) return (this.MyCalculadora.CodiError);
	this.PassarResultatCalculadoraAPosicio(this.Posicio);
	return (1);
}
Arbre.prototype.PassarResultatCalculadoraAPosicio = function(Pos) {
	this.Nodes[Pos].Nombre.Tipus=this.MyCalculadora.NombreR.Tipus;
	this.Nodes[Pos].Nombre.Num=this.MyCalculadora.NombreR.Num;
	this.Nodes[Pos].Nombre.Den=this.MyCalculadora.NombreR.Den;
	this.Nodes[Pos].Nombre.Dec=this.MyCalculadora.NombreR.Dec;
	this.Nodes[Pos].Nombre.Contingut=this.MyCalculadora.NombreR.Contingut;
	this.Nodes[Pos].Nombre.TextFix=this.MyCalculadora.NombreR.TextFix;
	this.Nodes[Pos].Nombre.NDecimalsPrecisio=this.MyCalculadora.NombreR.NDecimalsPrecisio;
}

/************************************************************************************
*
* Arbre --> MODIFICACIONS --> Avaluar step-by-step
*
************************************************************************************/

Arbre.prototype.AvaluarUnicaOperacio = function() {
	// Només fa un pas en l'avaluació de l'arbre, trobant una de les operacions 
	// amb més profunditat
	// Serveix per a que KIWIS pugui funcionar step-by-step
	// Retorna  < 0  (Status) si no ha pugut fer-ne cap.
	// Retorna 0 si ha arribat al final.
	// Retorna 1 si encara no.
	// La rutina suposa que prèviament s'ha cridat a la rutina
	//  DeterminarPosicioMaximaProfunditatArbre
	this.Posicio=this.PosicioMaximaProfunditat;
	var Status=this.AvaluarNode();
	if (Status<0) return (Status);
	this.Posicio=this.PosicioMaximaProfunditat;
	this.Nodes[this.Posicio].Nombre.Operacio=0;
	this.Nodes[this.Posicio].PosicioD=this.Posicio;
	this.Nodes[this.Posicio].PosicioE=this.Posicio;
	if (this.PosicioMaximaProfunditat==0) return (0);
	return (1);
}

/************************************************************************************
*
* Arbre --> MODIFICACIONS --> Avaluar step-by-step
* --> Determinar profunditat de les branques
*
************************************************************************************/

Arbre.prototype.DeterminarPosicioMaximaProfunditatArbre = function() {
	// Per a que el mòdul KIWIS calculi l'operació combinada step-by-step
	// cal determinar quina són les operacions més profundes.
	// Aquesta rutina determina la profunditat de cada operació de l'arbre
	// Queda enregistrat en this.MaximaProfunditat i this.PosicioMaximaProfunditat
	this.MaximaProfunditat=0;
	this.PosicioMaximaProfunditat=0;
	this.DeterminarProfunditatBranca(0,1);
}
Arbre.prototype.DeterminarProfunditatBranca = function(PosicioBranca,ProfunditatActual) {
	// Determina la profunditat de la branca actual
	this.Posicio=PosicioBranca;
	// Si és una posició final no cal fer res
	if (this.PosicioFinal()) return;
	// Si és una operació, mirem si és de profunditat màxima
	if (ProfunditatActual>this.MaximaProfunditat) {
		this.MaximaProfunditat=ProfunditatActual;
		this.PosicioMaximaProfunditat=this.Posicio;
	}
	// Mirem les subbranques recursivament
	this.DeterminarProfunditatBranca(this.PosicioD(),ProfunditatActual+1);
	this.Posicio=PosicioBranca;
	this.DeterminarProfunditatBranca(this.PosicioE(),ProfunditatActual+1);
	this.Posicio=PosicioBranca;	
}	
	

/************************************************************************************
*
* Arbre --> MODIFICACIONS --> Substituir divisions per fraccions
*
************************************************************************************/

Arbre.prototype.SubstituirDivisionsPerFraccions = function () {
	// Quan s'efectua l'input de Kiwis, les expressions com 3/5 s'interpreten 
	// en principi com a divisions. Aquesta rutina les passa a fraccions

	this.SubstituirDivisionsPerFraccionsRecursivament(0);
}
Arbre.prototype.SubstituirDivisionsPerFraccionsRecursivament = function (PosicioBranca) {
	// Substitueix en la branca indicada i a les seves subbranques
	this.Posicio=PosicioBranca;
	
	// Si és una posició final no cal fer res
	
	if (this.PosicioFinal()) return;

	// Ha de ser una divisió

	if (this.Operacio()==DIVIDIR) {
		if (this.EsNombreE() && this.TipusE()==NOMBRE_ENTER) {
			if (this.EsNombreD() && this.TipusD()==NOMBRE_ENTER) {
				this.SubstituirNodeDivisioPerFraccio();
				return;
			}
		}
	}
	
	// si no, fem recursivament les subbranques				
	this.SubstituirDivisionsPerFraccionsRecursivament(this.PosicioE());
	this.Posicio=PosicioBranca;
	this.SubstituirDivisionsPerFraccionsRecursivament(this.PosicioD());
}

Arbre.prototype.SubstituirNodeDivisioPerFraccio = function () {
	// Substitueix una divisió d'enters per una fracció equivalent
	var Num=this.ValorNumericE();
	var Den=this.ValorNumericD();
	this.EliminarDescendencia();
	this.Nodes[this.Posicio].Nombre.InFraccio(Num,Den,true);
}

/************************************************************************************
*
* Arbre --> MODIFICACIONS --> Substituir Restar a zero per Negatius
*
************************************************************************************/

Arbre.prototype.SubstituirRestarAZeroPerNegatius = function () {
	// Quan s'efectua l'input de Kiwis, les expressions com -3 s'interpreten 
	// en principi com a restes a 0: 0-3 i compten com a dues operacions

	this.SubstituirRestarAZeroPerNegatiusRecursivament(0);
}
Arbre.prototype.SubstituirRestarAZeroPerNegatiusRecursivament = function (PosicioBranca) {
	// Substitueix en la branca indicada i a les seves subbranques
	this.Posicio=PosicioBranca;
	
	// Si és una posició final no cal fer res
	
	if (this.PosicioFinal()) return;

	// Ha de ser una divisió

	if (this.Operacio()==RESTAR) {
		if (this.EsNombreE()) {
			if (this.EsNombreD()) {
				if (this.Nodes[this.PosicioE()].Nombre.EsZero()) {
					this.SubstituirNodeRestarAZeroPerNegatiu();
					return;
				}
			}
		}
	}
	
	// si no, fem recursivament les subbranques				
	this.SubstituirRestarAZeroPerNegatiusRecursivament(this.PosicioE());
	this.Posicio=PosicioBranca;
	this.SubstituirRestarAZeroPerNegatiusRecursivament(this.PosicioD());
}

Arbre.prototype.SubstituirNodeRestarAZeroPerNegatiu = function () {
	// Substitueix una resta a 0 per un nombre negatiu
	var Valor=this.ValorNumericD();
	var ValorNegat=-Valor;
	var NDecimals=this.Nodes[this.PosicioD()].NDecimalsPrecisio;
	this.EliminarDescendencia();
	this.Nodes[this.Posicio].Nombre.InputPosicioFinalNombre(ValorNegat,NDecimals);
}

/************************************************************************************
*
* Arbre --> MODIFICACIONS --> Nombre d'operacions de l'arbre
*
************************************************************************************/

Arbre.prototype.NombreOperacionsArbre = function () {
	// Compta el nombre d'operacions que té l'arbre (no modifica res)
	return (this.NombreOperacionsArbreRecursivament(0));
}

Arbre.prototype.NombreOperacionsArbreRecursivament=function(PosicioBranca) {
	var NOperacions;
	this.Posicio=PosicioBranca;
	if (this.PosicioFinal()) return (0);
	NOperacions=this.NombreOperacionsArbreRecursivament(this.PosicioE());
	this.Posicio=PosicioBranca;
	NOperacions=NOperacions+this.NombreOperacionsArbreRecursivament(this.PosicioD());
	return (NOperacions+1);
}

/***********************************************************************************\
*
* Arbre --> INPUT
*
************************************************************************************/

/************************************************************************************
*
* Arbre --> INPUT --> INTERFACE
*
************************************************************************************/

Arbre.prototype.InputArbre = function (TextExpressio,NDecimalsPrecisio){
	// Genera un arbre nou amb l'expressió donada per TextExpressio
	// Es pot especificar el nombre de decimals amb el que treballem
	// -1 vol dir infinits.
	// Retorna Status
	this.Reset();
	this.Nodes[0].TextBranca=TextExpressio;
	return(this.InputBrancaRecursivament(0,NDecimalsPrecisio));
}
Arbre.prototype.InputBrancaRecursivament = function (PosicioBranca,NDecimalsPrecisio) {
	// Completa la branca actual en funció del seu text d'entrada
	// de forma recursiva.
	// Retorna Status

	this.Posicio=PosicioBranca;
	var Text=this.Nodes[this.Posicio].TextBranca;
	var Status=this.MyAnalitzador.AnalitzarText(Text);
	
	// EXPRESSIÓ ENTRE PARÈNTESIS
		
	while (Status==11) {
		// Treiem un a un tots els parèntesis exteriors
		Text=this.MyAnalitzador.TextOutput;
		Status=this.MyAnalitzador.AnalitzarText(Text);
	}	

	// ERROR
	
	if (Status<0) return (Status); 
	
	// NOMBRE	
	
	if (Status==8) {	
		var TextNombre=this.MyAnalitzador.TextOutput;
		if (this.Nodes[this.Posicio].Nombre.InputPosicioFinalNombre(TextNombre,NDecimalsPrecisio)<0) {
			this.MyAnalitzador.TextError=TextNombre;		
			return (-5);
		} 
		return (1);
	}

	// LITERAL
	
	if (Status==10) {	
		var TextLiteral=this.MyAnalitzador.TextOutput;
		if (this.Nodes[this.Posicio].Nombre.InputPosicioFinalLiteral(TextLiteral)<0) {
			this.MyAnalitzador.TextError=TextLiteral;		
			return (-7);
		} 
		return (1);
	}	

	// Expressions amb operacions

	this.GenerarDescendencia();

	// NEGACIÓ

	if (Status==15) {
		this.Nodes[this.Posicio].Nombre.Operacio=2;	// Restar (a zero)
		this.Nodes[this.PosicioE()].Nombre.InZero();
		this.Nodes[this.PosicioD()].TextBranca=this.MyAnalitzador.TextOutput;
		//Generem recursivament la subbranca Dreta
		Status=this.InputBrancaRecursivament(this.PosicioD(),NDecimalsPrecisio);
		if (Status<0) return (Status);
		return (1);
	}
		
	// OPERACIÓ BINÀRIA ( per exclusió = 17 )
	
	this.Nodes[this.Posicio].Nombre.Operacio=this.MyAnalitzador.OperacioMinimaPrioritat;	
	this.Nodes[this.PosicioE()].TextBranca=this.MyAnalitzador.PartEsquerra();
	this.Nodes[this.PosicioD()].TextBranca=this.MyAnalitzador.PartDreta();
	
	// Generem recursivament la subbranca Esquerra
	var OldPosicio=this.Posicio;
	Status=this.InputBrancaRecursivament(this.PosicioE(),NDecimalsPrecisio);
	if (Status<0) return (Status);
	
	// I generem recursivament la subbranca dreta
	this.Posicio=OldPosicio;
	Status=this.InputBrancaRecursivament(this.PosicioD(),NDecimalsPrecisio);
	if (Status<0) return (Status);
	return (1);
}

/************************************************************************************
*
* Arbre --> INPUT --> Analitzador de Text
*
************************************************************************************/

function AnalitzadorText() {
	// Objecte per a dividir una expressió combinada que entra en .AnalitzarText
	// en dues parts: PartDreta Operacio PartEsquerra
	// on Operacio és una operació de l'expressió amb mínima prioritat.
	// S'utilitza de forma recursiva per a generar l'arbre d'operacions associat
	// a una cadena de text

	// INPUT:
	// el paràmetre de la rutina AnalitzarText

	// OUTPUT:
	// L'Status que retorna la rutina AnalitzarText
	// < 0 --> Error de sintaxi, >0 OK

	// OperacioMinimaPrioritat indica el codi de la Operació amb mínima prioritat
	// PartDreta() i PartEsquerra() donen els sectors de la cadena separats.
	// TextOutput indica el text d'entrada net de parèntesis 
	// PosicioError on s'ha trobat l'error de sintaxi



	this.PosicioError=0;			// Posició del text on està l'error.

	this.OperacioMinimaPrioritat=0;		 
	this.IniciPosicioMinimaPrioritat;
	this.FinalPosicioMinimaPrioritat;
	this.TextOutput="";			// Text interior del parèntesis 
	this.StatusTextOutput=0;		

	// Variables de la funció TreureParaula

	this.IniciParaulaActual=0; 		// Guarda el inici de la paraula actual
	this.FinalParaulaActual=0;		// Guarda el final de la paraula actual
	this.Paraula="";			// on queda la Paraula llegida
	this.StatusParaula=0;			// on queda l'status de la paraula llegida
	this.NParentesisObrir=0;
	this.NParentesisTancar=0;
	
	// Variables de la funció TreureLletra

	this.TextInput="";			// és el text a analitzar.
	this.PosicioText=0;			// és la posició actual de lectura de la
						// cadena TextInput
	this.PosicioLletraAnterior=0;
						
	this.Lletra="";				// On queda la lletra llegida.
}

AnalitzadorText.prototype.AnalitzarText = function(Text){
	// Rutina principal del Analitzador de Text.
	// Interpreta el Text com una cadena
	// Operand - Operador Binari - Operand - Operador Binari - Operand ...
	// i determina un dels Operador Binari que tingui mínima prioritat.
	// queda registrada en la variable OperacioMinimaPrioritat 
	// i la seva posició en IniciPosicioMinimaPrioritat
	// Torna Status
	// < 0 --> Error de sintaxis
	// > 0 --> OK
		

	var NOperacions=0;	
	var NOperacionsIgual=0; 	// En principi només pot haver un igual
	var Status=0;

	// Iniciem les variables.

	this.OperacioMinimaPrioritat=0; // OPERACIO_NO_DEFINIDA (té prioritat infinita).
	this.PosicioText=0;		// Posició del text inicial
	this.TextInput=Text;

	// Llegim el primer operand. (pot no haver res més)

	Status=this.TreureOperand();	
	if (Status<0) return (Status);
	if (Status==2) return (-11); 	// Error entrada buida.
	
	// Guardem la paraula actual per si l'expressió d'entrada no té operacions binàries
	// retorna el nombre, literal o el contingut de l'expressió entre parèntesis
	this.TextOutput=this.Paraula;
	this.StatusTextOutput=Status;

	var final=false;
	while (final==false) {
		
		// Llegim un operador binari
	
		Status=this.TreureOperacioBinaria();
		if (Status<0) return (Status);
		if (Status==2) {
			// Si només hi ha un operand retorna el seu contingut
			// en la variable TextOutput;
			if (NOperacions==0) return (this.StatusTextOutput);
			return (17); // Expressió amb operacions binàries
		}
			
		// Mirem si té mínima prioritat.

		var CodiOperacio=this.PassarStatusACodiOperacioBinaria(Status);

		if (this.Prioritat(this.OperacioMinimaPrioritat)>=this.Prioritat(CodiOperacio)) {
			// Si l'operació actual té menor prioritat,la guardem.
			// És menor o igual per a que agafi sempre la de més a la 
			// dreta del text.
			this.OperacioMinimaPrioritat=CodiOperacio;
			this.IniciPosicioMinimaPrioritat=this.IniciParaulaActual;
			this.FinalPosicioMinimaPrioritat=this.PosicioText;
		}

		if (Status==13) {
			// Només pot haver un igual en el text.
			NOperacionsIgual=NOperacionsIgual+1;
			if (NOperacionsIgual>1) {
				this.PosicioError=this.PosicioText;
				return (-9); //Més d'un igual en el mateix text.	
			}
		}
		
		NOperacions=NOperacions+1;

		// Llegim un Operand

		Status=this.TreureOperand();
		if (Status<0) return (Status);
		if (Status==2) return (-8);
	}

}

AnalitzadorText.prototype.TreureOperand =function() {
	var Status=this.TreureParaula();
	if (Status<0) return (Status);
	if (Status==2) return (Status);
	if (Status==4) {	// Operació restar --> Negació
		while (Status==4) {
			Status=this.TreureParaula();
		}
		if (Status<0) return (Status); 
		if (!this.EsOperand(Status)) return (-8);// S'esperava un operand
		return (15);	// Una resta davant és una negació
	}
	if (!this.EsOperand(Status)) return (-8);
	return (Status);
}

AnalitzadorText.prototype.TreureOperacioBinaria =function() {
	var Status=this.TreureParaula();
	if (Status==2) return (Status);
	if (Status<0) return (Status);
	if (this.EsOperand(Status)) {
		// Si no hi ha operació explícita, se suposa que és una operació.
		// La paraula llegida és l'operand, que cal tornar a llegir,
		// per tant retrocedim
		this.PosicioText=this.IniciParaulaActual;
		return (16);
	}
	if (!this.EsOperacioBinaria(Status)) return (-4); //S'esperava una operació;
	return (Status);
}

AnalitzadorText.prototype.PartDreta = function(){
	var Text=this.TextInput.slice(this.FinalPosicioMinimaPrioritat);
	return (Text);
}

AnalitzadorText.prototype.PartEsquerra = function(){
	var Text=this.TextInput.slice(0,this.IniciPosicioMinimaPrioritat);
	return (Text);
}

AnalitzadorText.prototype.Prioritat = function(CodiOperacio) {
	// Dóna un valor numèric a la prioritat de l'operació
	if (CodiOperacio==6) return (6); 	//Radicar.
	if (CodiOperacio==5) return (6); 	//Elevar.
	if (CodiOperacio==4) return (5); 	//Dividir.
	if (CodiOperacio==3) return (4); 	//Multiplicar.
	if (CodiOperacio==2) return (3); 	//Restar.
	if (CodiOperacio==1) return (2); 	//Sumar.
	if (CodiOperacio==9) return (1); 	//Igualtat.
	return (99); 				//Si no hi ha operació, la prioritat és 
						// infinita	
}

/************************************************************************************
*
* Arbre --> INPUT --> Analitzador de Text --> Treure Paraula
*
************************************************************************************/

AnalitzadorText.prototype.TreureParaula = function(){
	// Extreu del TextInput la següent paraula, a partir de la posició PosicioText
	// Torna Status
	// < 0 --> Error de sintaxis.
	// > 0 --> OK

	// Guardem la posició actual
	this.IniciParaulaActual=this.PosicioText;

	// Eliminem els espais buits que hi ha abans de la paraula.
	var Status=this.TreureLletra();
	while(Status==1) Status=this.TreureLletra();
	if (Status<0) return (Status);
	if (Status==2) return (Status);

	this.Paraula="";

	// El status de la paraula queda determinat per l'status de la primera lletra
	// N'hi ha que cal agafar més d'una lletra

	// Literal

	if (Status==10) {
		//Treu un Literal. 
		// Després de la primera lletra, pot estar compost
		// per més lletras, dígits, o el símbol "."
		// o qualsevol cosa que no estigui reservada.
		while (Status==10 || Status==9 || Status==8) {
			this.Paraula=this.Paraula+this.Lletra;
			Status=this.TreureLletra();
			if (Status<0) return (Status);
		}
		this.RetrocedirLletra(); // Recuperem la última lletra llegida.
		return (10);
	}

	// Nombre

	if (Status==8 || Status==9) {
		//Treu un nombre.
		//Només pot haver una única coma decimal.
		var NComesDecimal=0;
		while (Status==8 || Status==9) {
			this.Paraula=this.Paraula+this.Lletra;
			if (Status==9) {
				NComesDecimal=NComesDecimal+1;
					if (NComesDecimal>1) {
					this.PosicioError=this.PosicioText;
					return (-2);	//Dues comes decimals al mateix nombre
				}
			}
			Status=this.TreureLletra();
			if (Status<0) return (Status);
		}
		this.RetrocedirLletra(); // Recuperem la última lletra llegida.
		return (8);
	}

	// Expressió dintre de parèntesis.
	
	if (Status==11) {
		this.NParentesisObrir=1;
		this.NParentesisTancar=0;

		// Eliminem el primer parèntesis
		Status=this.TreureLletra();
		if (Status<0) return (Status);
		this.RecomptarParentesis(Status);	
	
		while(!this.TestParentesisFinal() && Status!=2) {
			this.Paraula=this.Paraula+this.Lletra;
			Status=this.TreureLletra();
			if (Status<0) return (Status);
			this.RecomptarParentesis(Status);	
		}
		if (!this.TestParentesisFinal()) return (-6); // Error de recompte de parèntesis
		// Eliminem l'últim parèntesis
		//Status=this.TreureLletra();
		//if (Status<0) return (Status);
		return (11);
	}

	// Operació (per exclusió)
	this.Paraula=this.Lletra;
	return (Status);

}

AnalitzadorText.prototype.RecomptarParentesis = function(Status) {
	if (Status==11) this.NParentesisObrir=this.NParentesisObrir+1;
	if (Status==12) this.NParentesisTancar=this.NParentesisTancar+1;
}

AnalitzadorText.prototype.TestParentesisFinal = function() {
	if (this.NParentesisObrir==this.NParentesisTancar) return (true);
	else return (false);
}

/************************************************************************************
*
* Arbre --> INPUT --> Analitzador de Text --> Treure lletra
*
************************************************************************************/

AnalitzadorText.prototype.TreureLletra = function(){
	// Llegeix la següent Lletra o Token de la cadena TextInput;
	// Des de la posició PosicioText actual. i avança PosicioText.
	// La posicioText inicial és 0.
	// Retorna Status de la lletra i la lletra llegida en la variable Lletra
	// < 0 --> Error de sintaxis.
	// >=0 --> OK

	// Guarda la posició d'abans de la lletra
	this.PosicioLletraAnterior=this.PosicioText;

	if (this.PosicioText>=this.TextInput.length) return (2); // Final de cadena

	this.Lletra=this.TextInput.substring(this.PosicioText,this.PosicioText+1);
	
	this.PosicioText=this.PosicioText+1;
	if (this.Lletra==" ") return (1);
	if (this.Lletra=="+") return (3);	
	if (this.Lletra=="-") return (4);	
	if (this.Lletra=="*") return (5);	
	if (this.Lletra=="/") return (6);	
	if (this.Lletra=="^") return (7);
	if (this.Lletra==".") return (9);
	if (this.Lletra=="(") return (11);
	if (this.Lletra==")") return (12);
	if (this.Lletra=="=") return (13);
	if (this.Lletra=="¨") return (14);
	if (this.Lletra=="0") return (8);
	if (this.Lletra.charCodeAt(0)>="1".charCodeAt(0) && 
		this.Lletra.charCodeAt(0)<="9".charCodeAt(0)) return (8);
	return (10);	// Qualsevol cosa no especial s'interpreta com literal
}

AnalitzadorText.prototype.RetrocedirLletra = function(){
	// Si hem llegit massa, cal tornar endarrera.
	this.PosicioText=this.PosicioLletraAnterior;
}

/************************************************************************************
*
* Arbre --> INPUT --> Analitzador de Text --> Gestió dels Codis Status
*
************************************************************************************/

AnalitzadorText.prototype.PassarStatusACodiOperacioBinaria =function (Status) {
	//Passa una operació binària en Status a Codi
	if (Status==3) return (1);  // SUMAR
	if (Status==4) return (2);  // RESTAR
	if (Status==5) return (3);  // MULTIPLICAR	
	if (Status==6) return (4);  // DIVIDIR
	if (Status==7) return (5);  // ELEVAR
	if (Status==13) return (9); // IGUALTAT
	if (Status==14) return (6); // RADICAR
	if (Status==16) return (3); // MULTIPLICACIÓ IMPLÍCITA
	BUGenPassarOperacioParaulaAAnalitzar();
}

AnalitzadorText.prototype.EsOperand =function(Status) {
	// Retorna true si Status és un operand
	if (Status==8) return (true);  	// Nombre
	if (Status==11) return (true);  // Expressió en parèntesis
	if (Status==10) return (true);  // Expressió literal
	if (Status==15) return (true);  // Expressió negada
	return (false);
}

AnalitzadorText.prototype.EsOperacioBinaria =function(Status) {
	// Retorna true si Status és una operació binària
	if (Status==3) return (true);  	// Sumar
	if (Status==4) return (true);  	// Restar
	if (Status==5) return (true);  	// Multiplicar
	if (Status==6) return (true);  	// Dividir
	if (Status==7) return (true);  	// Elevar
	if (Status==13) return (true); 	// Igualtat
	if (Status==14) return (true); 	// Radicar
	if (Status==16) return (true); 	// Multiplicació implícita
	return (false);
}



/************************************************************************************
*
* Nombres aleatoris.
*
************************************************************************************/

function GenerarEnterAleatoriAcotat(Minim,Maxim) {
	// Retorna un nombre enter aleatori entre Minim i Maxim INCLOSOS
	// Suposem Minim>0, Maxim >0, 
	// Aquesta rutina centralitza tota la generació de nombres aleatoris de BeWooM
	if (Minim<0) {
		Minim=-Minim;
	}
	if (Maxim<0) {
		Maxim=-Maxim;
	}
	if (Minim>Maxim) {
		var NombreAuxiliar=Minim;
		Minim=Maxim;
		Maxim=NombreAuxiliar;
	}
	return (Math.round(Math.random()*(Maxim-Minim)+Minim));
}

/************************************************************************************
*
* Taula de nombres primers.
*
************************************************************************************/

function TaulaNombresPrimers(TheIndex) {
	// Variables relacionades amb la factorització.
	this.NombresPrimers=[1,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,
			71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151];
	this.IndexActual=TheIndex;
}	
TaulaNombresPrimers.prototype.NPrimer = function (IndexPrimer) {
	return (this.NombresPrimers[IndexPrimer]);
}
TaulaNombresPrimers.prototype.NombrePrimerAnterior = function() {
	if (this.IndexActual<2) return;
	this.IndexActual=this.IndexActual-1;
	this.ActualitzarFinestra();
}
TaulaNombresPrimers.prototype.NombrePrimerPosterior = function() {
	if (this.IndexActual>=this.NombresPrimers.length-1) return;
	this.IndexActual=this.IndexActual+1;
	this.ActualitzarFinestra();
}
TaulaNombresPrimers.prototype.ActualitzarFinestra = function() {
	var MaximPrimer=this.NombresPrimers[this.IndexActual];
	document.getElementById("PrimerMax").value=MaximPrimer;
}
TaulaNombresPrimers.prototype.MaxPrimer = function () {
	return (this.NombresPrimers.length);
}

/***********************************************************************************\
*
* Mòdul Kiwis del projecte Col·lectiva 2.0
* 
************************************************************************************/

function Kiwis() {
	this.Arbre = new Arbre(1);
	this.StatusInput=0;		// Codi de l'error produït en l'INPUT
	this.NDecimalsPrecisio=2;	// Precisió dels nombres decimals
					// -1 vol dir infinit.
}

/************************************************************************************
*
* Kiwis --> INPUT
*
************************************************************************************/

Kiwis.prototype.Input = function(TextInput,LlenguatgeCodificacio) {
	
	// Introduïm la seqüència d'operacions
	
	this.StatusInput=this.Arbre.InputArbre(TextInput+"",this.NDecimalsPrecisio);
	if (this.StatusInput!=1) return (this.StatusInput); 

	// Avaluem l'arbre	

	this.StatusInput=this.Arbre.AvaluarArbre();

	// Si alguna cosa no ha anat bé tornem el codi de l'error.

	if (this.StatusInput!=1) return (this.StatusInput); 

	// Si tot va bé tornem ""

	return ("");
}

/************************************************************************************
*
* Kiwis --> OUTPUT
*
************************************************************************************/

Kiwis.prototype.OutputExpressio = function(LlenguatgeCodificacio) {
	return (this.Arbre.EscriureArbre(LlenguatgeCodificacio));
}

Kiwis.prototype.OutputResultat = function(LlenguatgeCodificacio) {
	return (this.Arbre.EscriureValorFinalArbre(LlenguatgeCodificacio));
}

/************************************************************************************
*
* Kiwis --> Gestió de Nombres i Expressions
*
************************************************************************************/

Kiwis.prototype.CompararNombres = function (TextA,TextB,ExigirFraccionsSimplificades){
	// Retorna true si són nombres i són perfectament iguals. False si no.
	// Si ExigirFraccionsSimplificades=true llavors 1/2 no és igual a 2/4
	//this.NDecimalsPrecisio=-1; //Infinita precissió decimal
	this.Arbre.MyCalculadora.NoSimplificarFraccions=false;
	if (ExigirFraccionsSimplificades==true) this.Arbre.MyCalculadora.NoSimplificarFraccions=true;
	var Resultat=this.Input(TextA + "=" + TextB,0);
	//this.Arbre.MyCalculadora.NoSimplificarFraccions=false;
	if (Resultat!="") return (false);
	var Resultat=this.OutputResultat(0);
	if (Resultat=="false") return (false);
	// Només s'accepten entrades numèriques.
	this.Arbre.SubstituirDivisionsPerFraccions();
	this.Arbre.SubstituirRestarAZeroPerNegatius();
	// Torna a fer les subtitucions de divisions per a detectar
	// fraccions negatives com -5/7
	this.Arbre.SubstituirDivisionsPerFraccions();
	if (this.Arbre.NombreOperacionsArbre()>1) return (false);
	return (true);		
}

Kiwis.prototype.CompararExpressions = function (TextA,TextB,ExigirFraccionsSimplificades){
	// Retorna true si són iguals. false si no.
	//this.NDecimalsPrecisio=-1; //Infinita precissió decimal
	this.Arbre.MyCalculadora.NoSimplificarFraccions=false;
	if (ExigirFraccionsSimplificades==true) this.Arbre.MyCalculadora.NoSimplificarFraccions=true;
	var Resultat=this.Input(TextA + "=" + TextB,0);
	//this.Arbre.MyCalculadora.NoSimplificarFraccions=false;
	if (Resultat!="") return (false);
	var Resultat=this.OutputResultat(0);
	if (Resultat=="false") return (false);
	return (true);	
}


