
	/***************************************************************
	 *															   *
	 *   OLIGO CLASS FOR CALCULATING AND VERIFYING THE SEQUENCE    *
	 *															   *
	 ***************************************************************/

	/**
	 * Constructor of class Oligo
	 * @param char character
	 */
	function Oligo() {
	
		// Class variables and arrays
		this.sequence = null;
		// Counter for recognizing tripplets
		this.seqCounter = 0;
		// Basen array
		this.basen = new Array("A", "C", "G", "T");
		// Wobbels array
		this.wobbels = new Array("B", "D", "H", "K", "M", "N", "R", "S", "V", "W", "Y");
		// Modifikationen array
		this.modifikationen = new Array("U", "I");
		// Phosphorthionat-Bindungen
		this.phosBindungen = new Array("*");
		
		// Mehthods
		this.setSequence = setSequence;
		this.getSequence = getSequence;
		this.evaluateSequence = evaluateSequence;
		this.removeSpaces = removeSpaces;
		this.validateSequenceLetters = validateSequenceLetters;
		this.countWobbels = countWobbels;
		this.countBasen = countBasen;
		this.countAll = countAll;
		this.convertToTripplets = convertToTripplets;
		this.getTrippletNumbers = getTrippletNumbers;
		this.calcODToNMol = calcODToNMol;
		this.calcMolekularGewicht = calcMolekularGewicht;
		this.calcNMolToNg = calcNMolToNg;
		this.getNumOligos = getNumOligos;
		this.countNumTripplets = countNumTripplets;
	}

	/**
	 * Evaluate the sequence and check 
	 * for error.
	 * @param String sequence
	 * @return String newSequence
	 */
	function evaluateSequence(seqString) {

		var seqNoSpaces = this.removeSpaces(seqString);
		var checkedSequence = this.validateSequenceLetters(seqNoSpaces);

		if(checkedSequence != seqNoSpaces) {
			alert("Bitte geben Sie nur Basen, Wobbels und Modifikationen ein!");
		}

		return this.convertToTripplets(checkedSequence);
	}

	function convertToTripplets(seqString) {
		var x=0;
		var newSequence = "";
		
		for(i=0; i < seqString.length; i++) {
			newSequence+=seqString.substr(i,1);

			if(seqString.substr(i+1,1) != this.phosBindungen[0]) {
				if(x == 2) {
					newSequence+=" ";
					x=0;
				} else {
					x++;
				}
			}
		}		
		return newSequence
	}

	/**
	 * Check if only allowed letters have been used.
	 * @param String sequence to check
	 * @return boolean check
	 */
	function validateSequenceLetters(seqString) {
		var allLetters = new Array();
		var seqUpperCase = seqString.toUpperCase();
		var newSequence = "";
		
		// concat basen, wobbels and modifikationen
		allLetters = this.basen.concat(this.wobbels.concat(this.modifikationen.concat(this.phosBindungen)));
		// add phosBindungen
		
		// go through all the letters in the sequence
		for(i=0; i < seqUpperCase.length; i++) {
			var letterFound=0;
			// go through all the letters in the letter array
			for(a=0; a < allLetters.length; a++) {
				// check if the letter from the sequence is in the letter array
				if(seqUpperCase.substr(i,1) == allLetters[a]) {
					letterFound++;
				}
			}
			// if a letter didn´t exist in the letter array, increment error
			if(letterFound != 0) {
				if(seqUpperCase.substr(i,1) == this.phosBindungen[0] && seqUpperCase.substr(i,1) == seqUpperCase.substr(i-1,1)) {
					// don´t add to sequence string
				}
				else {
					newSequence += seqUpperCase.substr(i,1);
				}

			}
		}
		return newSequence;
	}

	/**
	 * Remove all spaces before checking
	 * the string.
	 * @param String sequence
	 * @return String seqNoSpaces
	 */
	function removeSpaces(seqString) {
		var seqNoSpaces = "";
		
		for(i=0; i < seqString.length; i++) {
			if(seqString.substr(i,1) != " ") {
				seqNoSpaces+=seqString.substr(i,1);
			}
		}
		return seqNoSpaces;
	}

	/**
	 * Return the sequence String
	 * @return String sequence
	 */
	function getSequence() {
		return this.sequence;
	}
	
	/**
	 * Set the sequence string
	 * @param String sequence
	 */
	function setSequence(seqString) {
		this.sequence = seqString;
	}

	/**
	 * Count the number of basen in the
	 * sequence string.
	 * @param String sequence
	 * @return int num_basen
	 */
	function countBasen(seqString) {
		num_basen = 0;

		// go through all the letters in the sequence
		for(i=0; i < seqString.length; i++) {
			// go through all the letters in the basen array
			for(b=0; b < this.basen.length; b++) {
				// check if the letter from the sequence is in the basen array
				if(seqString.substr(i,1) == this.basen[b]) {
					num_basen++;
				}
			}
			for(w=0; w < this.wobbels.length; w++) {
				// check if the letter from the sequence is in the wobbels array
				if(seqString.substr(i,1) == this.wobbels[w]) {
					num_basen++;
				}
			}
		}
		return num_basen;
	}

	/**
	 * Count the number of wobbles in the
	 * sequence string.
	 * @param String sequence
	 * @return int num_wobbels
	 */
	function countWobbels(seqString) {
		num_wobbels = 0;

		// go through all the letters in the sequence
		for(i=0; i < seqString.length; i++) {
			// go through all the letters in the wobbels array
			for(w=0; w < this.wobbels.length; w++) {
				// check if the letter from the sequence is in the wobbels array
				if(seqString.substr(i,1) == this.wobbels[w]) {
					num_wobbels++;
				}
			}
		}
		return num_wobbels;
	}

	/**
	 * Count the number of letters in the
	 * sequence string.
	 * @param String sequence
	 * @return int num_all
	 */
	function countAll(seqString) {
		var num_all=0;
		var num_basen = this.countBasen(seqString);
		var num_wobbels = this.countWobbels(seqString);
		num_all = num_basen + num_wobbels;
		return num_all;
	}

	function getTrippletNumbers(seqString) {
		var tripplet_string = "";
		var tripplet_count = 0;

		// go through all the letters in the sequence
		for(i=0; i < seqString.length; i++) {
			if(seqString.substr(i+1,1) == " ") {
				tripplet_string += tripplet_count;
				tripplet_count += 3;
			}
			else {
				tripplet_string += "   ";
			}
		}
		return tripplet_string;
	}

	function countNumTripplets(seqString) {
		var tripplet_count = 0;

		// go through all the letters in the sequence
		for(i=0; i < seqString.length; i++) {
			if(seqString.substr(i+1,1) == " ") {
				tripplet_count += 3;
			}
		}
		alert(tripplet_count);
		return tripplet_count;		
	}

	/**
	 * Count the number of oligos in a sequence, i.e. the amount
	 * of a particaular letter.
	 * @param String sequence
	 * @param String letter
	 */
	function getNumOligos(seqString, letter) {
		var count=0;
		
		// go through all the letters in the sequence
		for(i=0; i < seqString.length; i++) {
			if(seqString.substr(i,1) == letter) {
				count++;
			}
		}
		return count;
	}

	/**
	 * Function fopr calculation from OD to nMol
	 * @ param String masstab_value
	 * @ param String hplc
	 * @ param String basenZahl
	 */
	function calcODToNMol(massstab_id, hplc, seqString) {
		var newOD = new Array();
		var nMol = new Array();
		var a = this.getNumOligos(seqString, "A");
		var g = this.getNumOligos(seqString, "G");
		var c = this.getNumOligos(seqString, "C");
		var t = this.getNumOligos(seqString, "T");

		// Get OD value depending on wether hplc is selected or not
		if(hplc == 1) {
			//var _od = od[massstab_id].gereinigtHPLC;
			var _od = od[massstab_id].minLiefermenge;
		} else {
			var _od = od[massstab_id].minLiefermenge;
		}

		// If two numbers exist, split the string
		if(_od.search(/-/) > 0) {
			newOD = _od.split("-");

			// Register new values
			nMol[0] = Math.round(Number((newOD[0] * 1000) / ((16*a)+(12*g)+(7*c)+(9.6*t))));
			nMol[1] = Math.round(Number((newOD[1] * 1000) / ((16*a)+(12*g)+(7*c)+(9.6*t))));

			if(isNaN(nMol[0]) || isNaN(nMol[1]) || String(nMol[0]).lastIndexOf("Infinity") != -1 || String(nMol[1]).lastIndexOf("Infinity") != -1) {
				nMol[0] = "-";
			} else {
				var roundNmol1 = ((Math.round(nMol[0]*10))*0.1);
				result1 = String(roundNmol1).replace(/\./, ",");
				if(String(result1).lastIndexOf(",") == -1) {
					result1 = result1 + ",0";
				}
				nMol[0] = result1;

				var roundNmol2 = ((Math.round(nMol[1]*10))*0.1);
				result2 = String(roundNmol2).replace(/\./, ",");
				if(String(result2).lastIndexOf(",") == -1) {
					result2 = result2 + ",0";
				}
				//nMol[1] = result2;
			}


		} else if(_od != "-") {
			newOD[0] = _od;
			// Register new values
			nMol[0] = Math.round(Number((newOD[0] * 1000) / ((16*a)+(12*g)+(7*c)+(9.6*t))));

			if(isNaN(nMol[0]) || String(nMol[0]).lastIndexOf("Infinity") != -1) {
				nMol[0] = "-";
			} else {
				var roundNmol1 = ((Math.round(nMol[0]*10))*0.1);
				result1 = String(roundNmol1).replace(/\./, ",");
				if(String(result1).lastIndexOf(",") == -1) {
					result1 = result1 + ",0";
				}
				nMol[0] = result1;
			}

		}
		return nMol;
	}

	/**
	 * Das Molekulargewicht des Oligos
	 * @param String sequence
	 * @return int result
	 */
	function calcMolekularGewicht(seqString) {
		var a = this.getNumOligos(seqString, "A");
		var g = this.getNumOligos(seqString, "G");
		var c = this.getNumOligos(seqString, "C");
		var t = this.getNumOligos(seqString, "T");
		
		var result = Math.round(Number(((a*312.2)+(g*328.2)+(c*288.2)+(t*303.2))-61));

		if(isNaN(result) || result < 0 || String(result).lastIndexOf("Infinity") != -1) {
			result = "-";
		} else {
			var roundResult = ((Math.round(result*10))*0.1);
			result = String(roundResult).replace(/\./, ",");
			if(String(result).lastIndexOf(",") == -1) {
				result = result + ",0";
			}
		}
		return result;
	}

	/**
	 * From nMol to ng
	 * @param int nMol
	 * @param int MW
	 * @return int result
	 */
	function calcNMolToNg(nMol, MW) {
		var result1 = 0;
		var result2 = 0;

		if(nMol.length > 1) {
			result1 = (parseFloat(nMol[0]) * parseFloat(MW));
			result2 = (parseFloat(nMol[1]) * parseFloat(MW));

			if(isNaN(result1) || isNaN(result2) || String(result1).lastIndexOf("Infinity") != -1 || String(result2).lastIndexOf("Infinity") != -1) {
				result = "-";
			} else {
				var roundResult1 = ((Math.round(result1*10))*0.1);
				result1 = String(roundResult1).replace(/\./, ",");
				if(String(result1).lastIndexOf(",") == -1) {
					result1 = result1 + ",0";
				}

				var roundResult2 = ((Math.round(result2*10))*0.1);
				result2 = String(roundResult2).replace(/\./, ",");
				if(String(result2).lastIndexOf(",") == -1) {
					result2 = result2 + ",0";
				}

				result = result1 + "-" + result2;	
			}

		} else {
			result = (parseFloat(nMol[0]) * parseFloat(MW));

			if(isNaN(result) || result < 0 || String(result).lastIndexOf("Infinity") != -1) {
				result = "-";
			} else {
				var roundResult = ((Math.round(result*10))*0.1);
				result = String(roundResult).replace(/\./, ",");
				if(String(result).lastIndexOf(",") == -1) {
					result = result + ",0";
				}
			}
		}
		return result;
	}


	function calcR24Temp(seqString) {
		var a = this.getNumOligos(seqString, "A");
		var g = this.getNumOligos(seqString, "G");
		var c = this.getNumOligos(seqString, "C");
		var t = this.getNumOligos(seqString, "T");
		var u = this.getNumOligos(seqString, "U");
		var i = this.getNumOligos(seqString, "I");

		var r24temp = (2*(a+t+u)+i + 4*(g+c) + 2*i);
		if(isNaN(r24temp) || r24temp < 0 || String(r24temp).lastIndexOf("Infinity") != -1) {
			result = "-";
		} else {
			var r24RoundTemp = ((Math.round(r24temp*10))*0.1);
			result = String(r24RoundTemp).replace(/\./, ",");
			if(String(result).lastIndexOf(",") == -1) {
				result = result + ",0";
			}
		}
		return result;
	}

	function calcRgcTemp(seqString) {
		var a = this.getNumOligos(seqString, "A");
		var g = this.getNumOligos(seqString, "G");
		var c = this.getNumOligos(seqString, "C");
		var t = this.getNumOligos(seqString, "T");
		var u = this.getNumOligos(seqString, "U");
		var i = this.getNumOligos(seqString, "I");


		if (a+g+c+t+i+u != 0) var rgctemp = (64.9 + (41*g+41*c+20.5*i-675)/(a+g+c+t+i+u));
		else var rgctemp = 0;
		if(isNaN(rgctemp) || result < 0 || String(rgctemp).lastIndexOf("rgctemp") != -1) {
			result = "-";
		} else {
			var rgcRoundTemp = ((Math.round(rgctemp*10))/10);
			result = String(rgcRoundTemp).replace(/\./, ",");
			if(String(result).lastIndexOf(",") == -1) {
				result = result + ",0";
			}
		}
		return result;
	}

	/***************************************************************
	 *															   *
	 *            OD CLASS FOR HOLDING OD INFORMATION              *
	 *															   *
	 ***************************************************************/

	function OD(_orderNr, _synthesemassstab, _minLiefermenge, _gereinigtHPLC) {
		this.orderNr = _orderNr;
		this.synthesemassstab = _synthesemassstab;
		this.minLiefermenge = _minLiefermenge;
		this.gereinigtHPLC = _gereinigtHPLC;
	}

	var od = new Array();
	od[0] = new OD("A999.1", "Nanomaßstab", "3", "-");
	od[1] = new OD("A999.2", "Sequenziermaßstab", "10", "5");
	od[2] = new OD("A999.3", "0,2 umol-Maßstab", "20", "10-15");
	od[3] = new OD("A999.4", "1,0 umol-Maßstab", "100", "30-50");
	
	var og = new Oligo();

	
	