/*
	Hare, a javascript singlespeed and fixed-gear cycling calculator

	http://jkiv.ca/hare/
*/

function calculate()
{
	/*
		Calculates and updates predetermined fields in the document from which this is called.
	*/
	
	var na = '-';	// Value in case of NaN or Infinity (see check_nan_infinity())
	
	var fg = Math.abs(document.getElementById("front_gear").value);
	var rg = Math.abs(document.getElementById("rear_gear").value);
	var cd = Math.abs(document.getElementById("crank_diameter").value);
	var td = Math.abs(document.getElementById("tire_diameter").value);
	
	var g_gcd = gcd(fg,rg);		// Remember GCD of gear ratio
	
	document.getElementById("gear_ratio").innerHTML=check_nan_infinity(fg/rg, -1, na);
	document.getElementById("gain_ratio").innerHTML=check_nan_infinity((td/cd)*(fg/rg), 2, na);
	document.getElementById("gear_inches").innerHTML=check_nan_infinity(td*fg/rg, 2, na);
	document.getElementById("development_in").innerHTML=check_nan_infinity((fg/rg)*td*3.14159265, 2, na);
	document.getElementById("development_m").innerHTML=check_nan_infinity((fg/rg)*td*3.14159265*0.0254, 3, na);
	
	/*
		If the simplified numerator is odd, ambidextrousity doubles number
		of skid patches.  Otherwise, the number of skid patches is the same
		as the simplified denominator.
	*/
	if (document.getElementById("ambidextrous").checked && (fg/g_gcd)%2 == 1)
	{
		document.getElementById("skid_patches").innerHTML=check_nan_infinity((rg/g_gcd)*2, -1, na);
	}
	else
	{
		document.getElementById("skid_patches").innerHTML=check_nan_infinity((rg/g_gcd), -1, na);
	}
	
	// Get selected unit...
	var u;
	for(i=0; i<document.hare.speed_unit.length; i++)
	{
		if( document.hare.speed_unit[i].checked == true )
			u = document.hare.speed_unit[i].value;
	}
	
	
	// Convert inches-per-minute to other unit by factor f
	var f = 0.000423333333;	// mps by default
	switch(u)
	{
		case "mps":
			f = 0.000423333333;	// Meters per second
			break;
		case "kph":
			f = 0.001524; // Kilometers per hour
			break;
		case "fps":
			f = 0.00138888889; // Feet per second
			break;
		case "mph":
			f = 0.000946969697; // Miles per hour
			break;
	}
	
	for(i=10; i<=200; i=i+10)
	{
		document.getElementById(i + "RPM").innerHTML=check_nan_infinity((fg/rg)*td*3.14159265*i*f, 1, '-');
	}
	
	// Update permalink
	document.getElementById("permalink").href = 'http://jkiv.ca/hare/?f='+fg+'&r='+rg+'&cl='+(document.getElementById("crank_diameter").options.selectedIndex + 1)+'&td='+(document.getElementById("tire_diameter").options.selectedIndex + 1)+'&a='+(document.getElementById("ambidextrous").checked?'1':'0')+'&s='+u;
}

if (!Number.toFixed)
{
	
	/*
		Define toFixed if it doesn't exist.
		
		Convert value to a representation with x decimal places.
	*/
	Number.prototype.toFixed=function(x)
	{
		var temp=this;
		temp=Math.round(temp*Math.pow(10,x))/Math.pow(10,x);
		return temp;
	};
}

function check_nan_infinity(a, n, alt_value)
{
	/*
		Returns alt_value in the event that a is NaN or infinity.
		Otherwise, return a (n=0) or fixed decimal of a to n places.
	*/
	if (parseFloat(a).toString() == "NaN" || parseFloat(a).toString() == "Infinity")
	{
		return alt_value;
	}
	else
	{
		if (n >= 0)
			return a.toFixed(n);
		else
			return a;
	}
}

function gcd(a,b)
{
	/*
		Calculates the GCD of a and b.
	*/
	var t;

	// Prevent crashes -- check for NaN and Infinity
	a = check_nan_infinity(a, 0);
	b = check_nan_infinity(b, 0);

	if (a<0)
		a=-a;
	if (b<0)
		b=-b;
	
	while (b > 0)
	{
	   t=b;
	   b=a%b;
	   a=t;
	}
	
	return a;
}	

