/*array.js
//array manipulation functions
BS2008
BS2009
USE AT YOUR OWN RISK

*/

Array.prototype.interpolate=function(x)
{
 //interpolation of y at x WHERE x is not necessarily an integer
 //Function used by scs_rainfall_oop.js
 //and scs_rainfall.js
 return this[Math.floor(x)]+(this[Math.ceil(x)]-this[Math.floor(x)])*(x-Math.floor(x));
}

Array.prototype.max = function(){
	return Math.max.apply({},this)
}
Array.prototype.min = function(){
	return Math.min.apply({},this)
}

function max_value(A)
{	//max value in array
	alert('function max_value(Array) defined in array.js\nshould not be used.\n make corrections..');
	//console.log('Running max_value(A)..');
	var k=0;
	var maxm=0;

	for(k=0;k<A.length;k++)
	{	//console.log('maxm = '+maxm);
		if(A[k]>maxm){maxm=A[k];}	
	}
	return maxm;
}

function sum(A)
{	//sum of all numbers in array
	var s=0;
	var k=0;
	for(k=0;k<A.length;k++)
	{s+=A[k];}	
	return s;
}

function cumulative(A)
{	//returns array with cumulative value of the elements in A
	//example when A=[2,4,1,9] then C=[2,6,7,16]
	var k=0;
	var C=new Array();

	for(k=0;k<A.length;k++)
	{	var s=0;
		for(var j=0;j<=k;j++)
		{s+=A[j];}

		C[k]=s;
	}	
	return C;
}

function add_first_k_elements(M,k)
{
	//add first k elements of the Martrix M
	var sum=0;
	for(count=0;count<(k);count++)
	{	var sum=sum+eval(M[count]);}
	return sum;
}



function array_into_text(a)
{	//Returns the array data as a text column
	var msg=0;
	for(count=0;count<a.length;count++)
	{	msg=msg+eval(count+1)+'\t\t'+eval((count+1)*5)+'\t\t'+eval(a[count]).toFixed(4)+'\n';}
	return msg;
}

function arrays_into_text2(a,b)
{	//Returns the arrays data as a text columns
	var msg=0;
	for(var count=0;count<a.length;count++)
	{	msg=msg+eval(count+1)+'\t\t'+eval((count+1)*5)+'\t\t'+eval(a[count]).toFixed(4)+'\t'+eval(b[count]).toFixed(4)+'\n';}
	return msg;
}

function rearrange(P)
{	//warning: this function is superceded by Array.prototype.redistribute()
	//Returns array Q
	//P must be pre-sorted to get meaningful output
	//The data is rearranged to form a Hyetograph
	//With Peak at the Middle
	//Other values will be thrown to the left and right of peak alternately
	var Q=new Array();
	var N=P.length;
	var mid=(N+mod(N,2))/2;
	var k=0;

	P.sort(numOrdD);
	Q[mid-1]=P[0];
	for(var k=2;k<=N;k++)
	{
		var j=mid+Math.pow((-1),k)/2*(k-mod(k,2));
		Q[j-1]=P[k-1];
	}
	return Q;
}
Array.prototype.redistribute=function()
{	//This function should supercede the function rearrange(array)
	//Returns array Q
	//P must be pre-sorted to get meaningful output
	//The data is rearranged to form a Hyetograph
	//With Peak at the Middle
	//Other values will be thrown to the left and right of peak alternately

	var Q=new Array();
	var N=this.length;
	var mid=(N+mod(N,2))/2;
	var k=0;

	this.sort(numOrdD);
	Q[mid-1]=this[0];
	for(var k=2;k<=N;k++)
	{
		var j=mid+Math.pow((-1),k)/2*(k-mod(k,2));
		Q[j-1]=this[k-1];
	}
	return Q;
}

Array.prototype.hyetograph=function(fraction)
{
	//console.log('now running array.prototype.hyetograph(fraction)...');
	//redistribute the data to form a hyetograph with peak at the fraction time
	//usage A.hyetograph(0.25)
	var P=new Array();
	P=this.sort(numOrdD);
	var n=P.length;
	var peakPosition=fraction*n;	
	
	var P1=new Array(); //first portion
	var P2=new Array();	//second portion
	//slice P into two arrays
	if(fraction<=0.5)
	{
		P1=P.slice(0,peakPosition*2).redistribute();	//rearrange this portion of array
                //console.log('P1 : '+P1);

		P2=P.slice(peakPosition*2);	//no need to rearrange this portion
                //console.log('P2 : '+P2);

		return P1.concat(P2);
	}
	else
		{
			//thinking
			P1=P.slice(0,(n-peakPosition)*2).redistribute();
                        //console.log('P1 : '+P1);

			P2=P.slice((n-peakPosition)*2);
                        //console.log('P2 : '+P2);
        		return (P2.reverse()).concat(P1);		
		}
}

Array.prototype.add=function(B)
{
    //algebrically adds two array's corresponding data value
    var len_A=this.length;
    var len_B=B.length;

    var A=this;

    if(len_A > len_B)
    {var len=len_A;
        //add trailing zeroes to shorter array B
        var tail=new Array();
        for(var k=0;k<(len_A-len_B);k++){tail[k]=0;}
        B=B.concat(tail);
    }
    else
    {var len=len_B;
       //add trailing zeroes to shorter array A
        var tail=new Array();
        for(var k=0;k<(len_B-len_A);k++){tail[k]=0;}
        A=A.concat(tail);
    }

    var C=new Array();
    for(var k=0;k<len;k++)
    {C[k]=A[k]+B[k];}

    return C;
}

Array.prototype.toTable=function(row,col)
{
	//no jquery used
	//put this array starting at the cell (row,col)
	for(var k=0;k<this.length;k++){writeData(row+k-1,col-1,this[k]);}
}

Array.prototype.table=function(tableid,row,col)
{
    //put the array in table
    //start at cell of (row,col)
	//probably a slow method
    //needs jqtable.js
    for(var k=0;k<this.length;k++)
    {
        cell(tableid,row+k,col).text(this[k].toFixed(2));	//show it in cell
        cell(tableid,row+k,col).val(this[k]);	//write to value of cell
    }
}

Array.prototype.alert=function()
	{	//displays array content in alert box
		//usage like this A.alert()
		var msg="";
		for (var k=0;k<this.length;k++){msg=msg+'\n'+k+"  =>  "+this[k];}
		alert(msg);
	}

Array.prototype.write=function()
	{	//write array in the document
		//usage like this A.write()
		var msg="";
		for (var k=0;k<this.length;k++)
			{
				msg=msg+'\n'+k+"  =>  " + this[k]+"<br />";
			}
		document.write(msg);
	}



Array.prototype.max_consequtive_sum=function(n)
{
	//RETURNS AN ARRAY B OF n CONSEQUTIVE ELEMENTS FROM THE ARRAY A WHICH HAS MAXIMUM SUM
	//alert("Running function max_consecutive_sum()...");
	n=parseInt(n);

	//n cannot be greater than the elements in the array
	if(n>this.length){n=this.length;}

	var k=0;
	var i=0;
	var max=0; 
	var startPoint = 0;
	for(var k=0;k<this.length-n+1;k++) 
	{
		var sum=0;
		for(i=0;i<n;i++)
		{sum = sum+this[k+i];}
		if(sum>max)
		{
			max=sum;
			startPoint=k;
		}
	}
	//alert("starts here "+startPoint);
	//alert("the max is" + max);

	//prepare new matrix to return
	var B=new Array();
	for(var m=0;m<n;m++){B[m]=this[startPoint+m];}
	return B;
}

Array.prototype.plot=function(divName,title,xscale,yscale)
{	//console.log("running Array.prototype.plot=function(divName,title,xscale,yscale)...");
	var g = new line_graph();

	//trying to set maximum as little above the highest value
	//var oldMax=max_value(this);	//disabled
	var oldMax=this.max();
	//console.log('oldMax = '+oldMax);
	var newMax=nextBigNumber(parseInt(oldMax));
	//console.log('newMax = ' + newMax);
	g.setMax(newMax);

	g.setScale(parseFloat(yscale));
	for (var k=0;k<this.length;k++)
	{
		//console.log(k+' : '+this[k]);
		g.add(k*xscale,this[k]*yscale);
	}
	g.render(divName, title,300);	//what is 300 for?
}

function nextBigNumber(x)
{
	//RETURNS A MULTIPLE OF 10, 100, 1000 ETC.
	//EXAMPLE nextBigNumber(745.87) RETURNS 1000
	//TO BE USED AS THE MAXIMUM Y AXIS VALUE WHILE PLOTTING
	var digits=String(x).length;
	var result="1";
	for(var i=0;i<digits;i++)
	{result=result+"0";}
	return parseFloat(result);
}

	Array.prototype.gchart=function()
		{
			//gchart utilizes google chart api
			//basically, give data to google and get a png image back
			//9:35 PM 10/4/2008
			
			//Example usage:
			//var A=[100,2,4,8,16,32,64,50,40,30,20,10];
			//$('body').append(A.gchart())	//using jquery

			//alert('gchart()..\nNot Perfect');
			//console.log('gchart()..\nNot Perfect');
			var a='<img src="http://chart.apis.google.com/chart?cht=lxy&chs=300x225&chd=';

			//create x-data points
			//find max y value
			var max_y=Math.max.apply({},this);	//needed for scaling

			var b='t:';
			for(var k=0;k<this.length;k++)
			{	//x-axis
				if(k==this.length-1){var commaChar='';}
				else{var commaChar=',';}
				b=b+eval(k*10)+commaChar;
			}
			b=b+'|';
			for(var k=0;k<this.length;k++)
			{	//y-axis
				if(k==this.length-1){var commaChar='';}
				else{var commaChar=',';}

				b=b+this[k]*90/max_y+commaChar;
			}
			
			var c='&chco=3072F3,ff0000,00aaaa&chls=1,10,2&chg=20,50&chtt=Data|Sample+Only&chxt=x,t,y,r&chxr=2,0,100|1,0,100&chm=s,FF0000,0,-1,5|s,0000ff,1,-1,5|s,00aa00,2,-1,5" alt="gchart error"/>';

			var chartTag=a+b+c;
			//document.write('<fieldset>'+chartTag+'</fieldset>');
			return chartTag;

		}