
function  validateNumeric( strValue ) {
/******************************************************************************
DESCRIPTION: Validates that a string contains only valid numbers.

PARAMETERS:
   strValue - String to be tested for validity
   
RETURNS:
   True if valid, otherwise false.
******************************************************************************/
  var objRegExp  =  /(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/; 
 
  //check for numeric characters 
  return objRegExp.test(strValue);
}

var harmonicas=new Array();
var harmonicaNames=new Array();
var harmonicaNamesAll=new Array();
var harmonicaNumbers=new Array();
var overblows= new Array();
var altoverblows= new Array();
var doubledNotes= new Array();
var turns= new Array();
var nrOfRowsHarmonica =new Array();
var centerRowHarmonica =new Array();
var highestNumberOfRows=4; //start op 0, 1 ob, 1 od, blow, draw en number rij

for (i=0;i<states.length;i+=3){
k=i/3+1;
	if (validateNumeric(states[i][0])){
		harmonicaNames[k]=states[i][0]+" "+states[i][1];
		harmonicaNamesAll[k]=states[i][0]+" "+states[i][1];
		harmonicaNumbers[k]=states[i][0];
	}
	else {
		harmonicaNamesAll[k]=" - "+states[i][0]+" "+states[i][1];
		harmonicaNumbers[k]=harmonicaNumbers[k-1]; 
		// als deze geen nummer heeft is het een sub versie van de voorgaande
	}
}

function loadHarmonica(harNr){
	i=(harNr-1)*3;
	if (!harmonicas[harNr]){
			turn=false;
			maxBlowBend=1;
			maxDrawBend=1;
			k=i/3+1;
			cols=states[i+1].length-1;
			var newHar = new Array(cols);
			overblows[k]=new Array();
			altoverblows[k]=new Array();
			doubledNotes[k]= new Array();
			turns[k]=new Array();

			//calculate the maximum Number of rows
			blowoffset=0;
			drawoffset=0;

			for (c=1;c<=cols;c++){
				var blow=noteNames[(states[i+1][c])]+blowoffset;
				var prevblow=noteNames[(states[i+1][c-1])]+blowoffset;
				if (!prevblow && blow>=11 )drawoffset+=12;
				if (!prevblow && (noteNames[states[i+2][c]]>=9) && blow<7){
					blowoffset+=12;
					blow+=12;
				}
				var draw=noteNames[states[i+2][c]]+drawoffset;
				var prevdraw=noteNames[states[i+2][c-1]]+drawoffset;

				if(blow<prevblow && ((prevblow-blow)>4)){
					blowoffset+=12;
					blow+=12;
				}
				if(draw<prevdraw && ((prevdraw-draw)>4)){
					drawoffset+=12;
					draw+=12;
				}
				if(blow<draw){
					if((draw-blow)>maxDrawBend)maxDrawBend=draw-blow-1;
				}
				if(blow>draw){
					if((blow-draw)>maxBlowBend)maxBlowBend=blow-draw-1;
				}
			}
			nrOfRowsHarmonica[k]=maxBlowBend+3+maxDrawBend-1;
			centerRowHarmonica[k]=maxBlowBend+1;
			if (nrOfRowsHarmonica[k]>highestNumberOfRows)highestNumberOfRows=nrOfRowsHarmonica[k];
			
			//find the turns,bends and overbends
			blowoffset=0;
			drawoffset=0;

			for (c=1;c<=cols;c++){
				blowBend=1;
				drawBend=1;
				overblow=0;
				overdraw=0;
				newCol=new Array(nrOfRowsHarmonica[k]);
				colIndex=0;
				// volstoppen
				while (colIndex<nrOfRowsHarmonica[k]){
					newCol[colIndex]=0;
					colIndex++;
				}
				colIndex=0;
				
				var blow=noteNames[(states[i+1][c])]+blowoffset;
				var prevblow=noteNames[(states[i+1][c-1])]+blowoffset;
				
				//uitzonderingen: rare inversies
				if (!prevblow && blow>=11)drawoffset+=12;
				// well de blowbend tuning maar niet de inversies							
				if (!prevblow && (noteNames[states[i+2][c]]>=9  && blow<7)){
					blowoffset+=12;
					blow+=12;
				}
				var draw=noteNames[states[i+2][c]]+drawoffset;
				var prevdraw=noteNames[states[i+2][c-1]]+drawoffset;

				if(blow<prevblow && ((prevblow-blow)>4)){
					blowoffset+=12;
					blow+=12;
				}
				if(draw<prevdraw && ((prevdraw-draw)>4)){
					drawoffset+=12;
					draw+=12;
				}
				
				if (states[i+1][c]==states[i+1][c-1])doubledNotes[k][c-1]=1;
				if (states[i+1][c]==states[i+2][c-1])doubledNotes[k][c]=1;
				
				var nextblow=noteNames[(states[i+1][c+1])]+blowoffset;
				var nextdraw=noteNames[states[i+2][c+1]]+drawoffset;
				if(nextblow<blow){
					nextblow+=12;
				}
				if(nextdraw<draw){
					nextdraw+=12;
				}


				if(blow<draw){
					if (!turn){
						turns[k][(turns[k].length)]=c-1;
						turn=true;
					}
					overblow=draw+1;
					if (!(overblow<nextblow && overblow<nextdraw)&& nextblow){
						altoverblows[k][c]=overblow;					
					}
					overblows[k][c]=overblow;
					while (colIndex<maxBlowBend-1)colIndex++;
					newCol[colIndex]=overblow;
					colIndex+=4; // de normale noten voorbij
					bendOffset=1;
					while (bendOffset<=maxDrawBend){
						if(draw-bendOffset>blow) newCol[colIndex]=draw-bendOffset;
						bendOffset++;
						colIndex++;
					}
				}
				if(blow>draw){
					if (turn){
						turns[k][(turns[k].length)]=c-1;
						turn=false;
					}
					while (colIndex<=maxBlowBend){
						if ((blow-(maxBlowBend-colIndex))>draw) newCol[colIndex]=blow-(maxBlowBend-colIndex);
						colIndex++;
					}
					overdraw=blow+1;
					overblows[k][c]=overdraw;
					newCol[centerRowHarmonica[k]+2]=overdraw;
					if (!(overdraw<nextdraw && overdraw<nextblow)&& nextblow){
					    altoverblows[k][c]=overdraw;
					}
				}
				newCol[centerRowHarmonica[k]-1]=blow;
				newCol[centerRowHarmonica[k]+1]=draw;
				newHar[c-1]=newCol;
			}
			harmonicas[k]=newHar;
		}
}