/*
 *
 * Sundance Flying Club
 * Weight and Balance Calculation Tool
 * 9/9/2005
 * version 0.2.1
 *
 * Copyright (c) 2005 David G. Jacobowitz
 * For questions and/or support, please contact:
 *  davej@alumni.virginia.edu
 * Reworked to handle more complex envelopes
 *  Evan Williams June 2007
 * Added 6 seat and graphing capability
 * Evan Oct 2008
 * Rewrote to move adjustables onto each web page
 * Evan Oct 2009
 */



/* New functions to handle envelope
 * We set up new associative array with std array in each element.
 *  Each element in the std array is an x,y coord pair of objects.
 * We can then ask whether the weight and arm pair is inside or outside this envelope.
*/

		var Coord = function (x,y){
			this.x = x;
			this.y = y;
		}

function MIN(x,y){return (x < y?x:y);}
function MAX(x,y){return (x > y?x:y);}

function printCoord(param,name){
	alert('<p>Coords for '+name+':'+param.x+','+param.y+'</p>');
}

function inPolygon(point,poly,vert)
{
  var counter = 0;
  var i;
  var xinters = 0.0;
  INSIDE = 1;
  OUTSIDE = 0;
  p1 = poly[0];
  for (i=1;i<=vert;i++) {
    p2 = poly[i % vert];
    if (point.y > MIN(p1.y,p2.y)) {
      if (point.y <= MAX(p1.y,p2.y)) {
        if (point.x <= MAX(p1.x,p2.x)) {
          if (p1.y != p2.y) {
            xinters = (point.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
            if (p1.x == p2.x || point.x <= xinters)
              counter++;
          }
        }
      }
    }
    p1 = p2;
  }
  if (counter % 2 == 0)
    return(OUTSIDE);
  else
    return(INSIDE);
}

					
function wb_calc1 (funct) {

 /* *** *** *** *** *** *** *** *** *** *** *** *
    No adjustable parameters below this line 
  * *** *** *** *** *** *** *** *** *** *** *** */

 /*
  * Constants
  */
 var lbGal = 5.97;
 
 /*
  * Read user input from the html form
  */
/* var currAcIdx = document.WB_form.ac_selection.selectedIndex;
 var currAc     = document.WB_form.ac_selection.options[currAcIdx].value;
*/
 var ltFPaxLb  = parseFloat(document.WB_form.front_pax_lt.value);
 var rtFPaxLb  = parseFloat(document.WB_form.front_pax_rt.value);
 var ltRPaxLb  = parseFloat(document.WB_form.rear_pax_lt.value);
 var rtRPaxLb  = parseFloat(document.WB_form.rear_pax_rt.value);
 var ltR6PaxLb  = parseFloat(document.WB_form.rear6_pax_lt.value);
 var rtR6PaxLb  = parseFloat(document.WB_form.rear6_pax_rt.value);
 var ltFuelGal    = parseFloat(document.WB_form.fuel_lt.value);
 var rtFuelGal    = parseFloat(document.WB_form.fuel_rt.value);
 if (currAc == "N265AA")
 {
   var ltAuxFuelGal    = parseFloat(document.WB_form.afuel_lt.value);
   var rtAuxFuelGal    = parseFloat(document.WB_form.afuel_rt.value);
 }
 var bag1Lb  = parseFloat(document.WB_form.baggage_1.value);
 if (acRBagArm[currAc]) {
  aBagLb = parseFloat(document.WB_form.baggage_2.value);
 } else {
  aBagLb = 0;
 }

 var oilMom = 0;
 var oilWt = 0;
/* alert("currAc "+currAc); */
 if ((currAc == "N600JG") || (currAc == "N265AA")) { 
	oilMom = 0.001 * acOilWt[currAc] * acOilArm[currAc];
	oilWt =  acOilWt[currAc];
 }
/* alert("Oil - Moment "+oilMom+" wt "+oilWt); */

/* We will grey out seats 3 & 4 for a 2 place airplane 
   and seats 5 & 6 for 2 & 4 seat airplanes            */
 document.getElementById("Rear").bgColor = "silver";
 document.getElementById("Rear6").bgColor = "silver";
 if (places[currAc] >= 4) {
   document.getElementById("Rear").bgColor = "white";
 }
 if (places[currAc] == 6) {
   document.getElementById("Rear6").bgColor = "white";
 }
/* alert("Set the color");  */

 /*
  * Calculate intermediate values from form data
  */
 var totFPaxLb = ltFPaxLb + rtFPaxLb;
 var totRPaxLb = 0.0;
 if (places[currAc] >= 4) {totRPaxLb = ltRPaxLb + rtRPaxLb;}
 var totR6PaxLb = 0.0;
 if (places[currAc] == 6) { totR6PaxLb = ltR6PaxLb + rtR6PaxLb;}
 var totFuelGal = ltFuelGal + rtFuelGal;
 var ltFuelLb    = ltFuelGal *  lbGal;
 var rtFuelLb    = rtFuelGal *  lbGal;
 var totFuelLb = ltFuelLb + rtFuelLb;
 var totAuxFuelGal = 0.0;
 var ltAuxFuelLb = 0.0;
 var rtAuxFualLb = 0.0;
 var totAuxFuelLb = 0.0;
 if (currAc == "N265AA")
  {
   totAuxFuelGal = ltAuxFuelGal + rtAuxFuelGal;
   ltAuxFuelLb    = ltAuxFuelGal *  lbGal;
   rtAuxFuelLb    = rtAuxFuelGal *  lbGal;
   totAuxFuelLb = ltAuxFuelLb + rtAuxFuelLb;
  }
 var aBagLb;


 /*
  * Do the W/B calculations...
  */
 var fPaxMom    = 0.001 *  totFPaxLb * acFPaxArm[currAc];
 var rPaxMom    = 0.001 * totRPaxLb * acRPaxArm[currAc];
 var r6PaxMom   = 0.0;
 if (places[currAc] == 6) {r6PaxMom = 0.001 * totR6PaxLb * acR6PaxArm[currAc];}
 var fuelMom    = 0.001 * totFuelLb   * acFuelArm[currAc];
 var fuelAuxMom = 0.0;
 if (currAc == "N265AA")
 {
   fuelAuxMom    = 0.001 * totAuxFuelLb   * acAuxFuelArm[currAc];
 }
 var bag1Mom    = 0.001 * bag1Lb * acBagArm[currAc];
 var bag2Mom    = 0.001 * aBagLb * acRBagArm[currAc];
 var eMom       = 0.001 * acBasEWt[currAc] *
                                acEArm[currAc];

 var totWt0Gas  = acBasEWt[currAc] +
                            totFPaxLb +
                            totRPaxLb +
                            totR6PaxLb +
                            bag1Lb +
							oilWt +
                            aBagLb;

 var totWt         = totWt0Gas + totFuelLb + totAuxFuelLb;
/* alert("Base wt "+acBasEWt[currAc]+" total "+totWt); */
 var totMom0Gas  = eMom +
                            fPaxMom +
                            rPaxMom +
							r6PaxMom +
                            bag1Mom + 
                            bag2Mom +
							oilMom;

 var totMom         = totMom0Gas + fuelMom + fuelAuxMom;

 var finArm            = (totMom * 1000) / 
                            totWt;
 var finArm0Gas           = (totMom0Gas * 1000) / 
                            totWt0Gas;

 /*
  * Using the data calculated above, repopulate the form's read-only
  * boxes with intermediate data.
  */
/* alert("Filling the form"); */
 document.WB_form.total_front_pax.value  = totFPaxLb.toFixed(2);
 document.WB_form.total_rear_pax.value   = totRPaxLb.toFixed(2);
 document.WB_form.total_rear6_pax.value   = totR6PaxLb.toFixed(2);
 document.WB_form.front_pax_arm.value    = acFPaxArm[currAc].toFixed(2);
 document.WB_form.rear_pax_arm.value     = acRPaxArm[currAc].toFixed(2);
 document.WB_form.rear6_pax_arm.value    = acR6PaxArm[currAc].toFixed(2);
/* Main fuel */
 document.WB_form.fuel_m.value      	= acFuelCap[currAc].toFixed(0);
 document.WB_form.fuel_lt_lbs.value      = ltFuelLb.toFixed(2);
 document.WB_form.fuel_rt_lbs.value      = rtFuelLb.toFixed(2);
 document.WB_form.fuel_total.value       = totFuelGal.toFixed(2);
 document.WB_form.fuel_total_lbs.value   = totFuelLb.toFixed(2);
 document.WB_form.fuel_arm.value         = acFuelArm[currAc].toFixed(2);
/* Aux fuel */
 if (currAc == "N265AA")
 {
   document.WB_form.afuel_m.value      	= acAuxFuelCap[currAc].toFixed(0);
   document.WB_form.afuel_lt_lbs.value      = ltAuxFuelLb.toFixed(2);
   document.WB_form.afuel_rt_lbs.value      = rtAuxFuelLb.toFixed(2);
   document.WB_form.afuel_total.value       = totAuxFuelGal.toFixed(2);
   document.WB_form.afuel_total_lbs.value   = totAuxFuelLb.toFixed(2);
   document.WB_form.afuel_arm.value         = acAuxFuelArm[currAc].toFixed(2);
 }
 document.WB_form.baggage_1_arm.value    = acBagArm[currAc].toFixed(2);
 document.WB_form.baggage_2_arm.value    = acRBagArm[currAc].toFixed(2);  
 document.WB_form.total_baggage_1.value  = bag1Lb.toFixed(2);
 document.WB_form.total_baggage_2.value  = aBagLb.toFixed(2);
 document.WB_form.front_pax_moment.value = fPaxMom.toFixed(2);
 document.WB_form.rear_pax_moment.value  = rPaxMom.toFixed(2);
 document.WB_form.rear6_pax_moment.value  = r6PaxMom.toFixed(2);
 document.WB_form.fuel_moment.value      = fuelMom.toFixed(2);
 document.WB_form.baggage_1_moment.value = bag1Mom.toFixed(2);
 document.WB_form.baggage_2_moment.value = bag2Mom.toFixed(2);
 document.WB_form.total_weight.value     = totWt.toFixed(2);
 document.WB_form.final_moment.value     = totMom.toFixed(2);
 document.WB_form.final_arm.value        = finArm.toFixed(2);
 document.WB_form.empty_weight.value     = acBasEWt[currAc].toFixed(2);
 document.WB_form.empty_arm.value        = acEArm[currAc].toFixed(2);
 document.WB_form.empty_moment.value     = eMom.toFixed(2);
/* alert("Got this far"); */
 /*
  * Only the Cessnas have an aft baggage area. This takes care of that.
  */
 if (!acRBagArm[currAc]) {
  document.WB_form.baggage_2_arm.value    = "n/a";
  document.WB_form.baggage_2_moment.value = "n/a";
  document.WB_form.total_baggage_2.value  = "n/a";
  document.WB_form.baggage_2.value        = "n/a";
  document.getElementById("aftBag").bgColor = "silver";
 } else {
  document.getElementById("aftBag").bgColor = "white";
/*  document.WB_form.baggage_2.value        = 0;       */
 }

/* alert("Past the Cessnas. Airplane is "+currAc); */

 /* Need to handle 2 & 4 place */

 if (places[currAc] == 2) {
  document.WB_form.rear_pax_lt.value    = "n/a";
  document.WB_form.rear_pax_rt.value    = "n/a";
 }
 if (places[currAc] <= 4) {
  document.WB_form.rear6_pax_lt.value    = "n/a";
  document.WB_form.rear6_pax_rt.value    = "n/a";
 } 

 /* 
  * Finally, determine the WB status of the AC
  *
  * This part is new
  */
 var overweight  = (totWt > acMaxWts[currAc]);
 var utility_ok  = ((finArm < acUtCgMax[currAc]) &&
                    (totWt < acUtMaxWt[currAc]));
 var too_much_gas = (totFuelGal > acFuelCap[currAc]);
 var too_much_auxGas = false;
 if (currAc == "N265AA") 
 {
   too_much_auxGas = (totAuxFuelGal > acAuxFuelCap[currAc]);
 }
 /*
  * Now see if we are in the envelope
 */
 
 var currWB = new Coord(finArm,totWt);
 var currWB0Gas = new Coord(finArm0Gas,totWt0Gas);
 var vertices = acEnvel[currAc].length;
 var inEnvelope = inPolygon(currWB,acEnvel[currAc],vertices);
 var inEnvelope0Gas = inPolygon(currWB0Gas,acEnvel[currAc],vertices);
 var minCG = 10000;
 var maxCG = -10000;
 var lCG = 0;
 var ii = 0;
 for (ii=0; ii < vertices; ii++) {
 	lCG = acEnvel[currAc][ii].x;
 	if (lCG < minCG) {minCG = lCG;};
 	if (lCG > maxCG) {maxCG = lCG;};
 	}
 /*
  * Generate a string with interesting W/B information. This is 
  * not the final "result" -- it's mostly for debugging and people
  * who do not trust the script
  */
 var info_message = 
   "Empty weight for " + currAc + " is " +
   acBasEWt[currAc].toFixed(0) + 
   " lbs.\n" + "Max weight is " + 
   acMaxWts[currAc].toFixed(0) + " lbs.\n" +
   "Minimum CG, Normal Category: " +
   minCG.toFixed(1) + 
   "\nMaximum CG, Normal Category: " + 
   maxCG.toFixed(1) + " in.\n";

 if (acUtCgMax[currAc] > 0) {
  info_message += 
   "Maximum CG, Utility Category: " +
   acUtCgMax[currAc].toFixed(1) + " in.\n";
 };
 if (acUtMaxWt[currAc] > 0) {
  info_message += 
   "Max weight, Utility Category: " +
   acUtMaxWt[currAc].toFixed(0) + 
   " lbs.\n";
 }
/*	alert("Result:" + info_message); */
 

 /*
  * Generate a string that tells the overall W/B disposition of the AC,
  * okay or not okay, utility or not, and a warning of whether the tanks
  * can be flown down to empty.
  */
 var stat_message = "";
 if (!overweight && 
     inEnvelope && 
     !too_much_gas &&
     !too_much_auxGas) {
  if (inEnvelope0Gas) {
   /* that's a greenish color 
   document.getElementById("status").bgColor = "#33c33";	*/
   stat_message += "Weight and Balance OKAY.\n";
   if (document.images) {
    document.gonogo.src = "go.jpg";
   }
  } else {
/*   document.bgColor = "yellow";	*/
   if (document.images) {
    document.gonogo.src = "warning.gif";
   }
   stat_message += "Takeoff Weight and Balance OKAY -- landing may not be.\n";
  }
  if (utility_ok) {
   stat_message += "Utility Category operation also OK.\n";
  }
 } else {
  if (document.images) {
   document.gonogo.src = "stop.gif";
  }
  /* a reddish color a little easier on the eyes than "red"
  document.bgColor = "#ff3333";	*/
  stat_message = "AIRCRAFT IS NOT WITHIN W/B LIMITS\n";
  if (overweight) {
   stat_message += "Aircraft is OVERWEIGHT.\n";
  } else {
   stat_message += "CG is out of envelope.\n";
  }
  if (too_much_gas) {
   stat_message =  "TOO MUCH FUEL. Load exceeds capacity by " +
                    (totFuelGal - acFuelCap[currAc]) +
                    " gals.";
  }
  if (too_much_auxGas) {
   stat_message =  "TOO MUCH FUEL - AUX. Load exceeds capacity by " +
                    (totAuxFuelGal - acAuxFuelCap[currAc]) +
                    " gals.";
  }

  if (!inEnvelope0Gas) {
   stat_message += "WARNING! CG out of range at zero fuel.\n";
  }
 }

 
 /*
  * Generate a message with some ancillary notes in it.
  */
 var useful_load = (acMaxWts[currAc] - acBasEWt[currAc]);
 var  note_message = "";
 note_message += acTp[currAc] + "\n" +
                 "Useful load: " + useful_load.toFixed(0) +
                 " lbs.\n"  +
                 acNot[currAc];

 /*
  * Display all the messages.
  */
 document.results.min_max_report.value = info_message;
 document.results.status.value = stat_message;
 document.results.notes.value = note_message;
/* alert("graph time");
 graph_wb(); */
if (funct == 1) { graph_wb();}

/* Here for scope */
/*
 * function to produce a W&B graph
 *  - uses the Google Graph API
*/

 function graph_wb () {

  var vertices = acEnvel[currAc].length;
  var envX = acEnvel[currAc][0].x;
 	  xMax=envX;
	  xMin=envX;
  var envY = acEnvel[currAc][0].y;
	  yMax=envY;
	  yMin=envY;
	
  for (ii=1; ii < vertices; ii++) {
 	xX=acEnvel[currAc][ii].x;
	envX = envX + "," + xX;
 	yY=acEnvel[currAc][ii].y;
	envY = envY + "," + yY;
	xMin=MIN(xX,xMin);
	xMax=MAX(xX,xMax);
	yMin=MIN(yY,yMin);
	yMax=MAX(yY,yMax);
  }

  xMin= 10 * parseInt(xMin/10);
  xMax= 10 * (parseInt(xMax/10)+1);
  yMin= 100 * parseInt(yMin/100);
  yMax= 100 * (parseInt(yMax/100)+1);
  minMax=xMin+","+xMax+","+yMin+","+yMax+","+xMin+","+xMax+","+yMin+","+yMax;
  axisRanges="0,"+xMin+","+xMax+"|1,"+yMin+","+yMax;
/*  alert("minMax "+minMax); */
  fA0G = finArm0Gas;
/*  if (fA0G == finArm) {fA0G = fA0G*1.05;} */
  wtXY="|"+finArm+","+fA0G+"|"+totWt+","+totWt0Gas;

  var graph = "http://chart.apis.google.com/chart?chs=600x400&amp;chd=t:";
/*  alert(graph); */
	graph=graph+envX+"|"+envY;
	graph=graph+wtXY;
/*  alert(graph); */
	graph=graph+"&amp;chds="+minMax;
  graph=graph+"&amp;cht=lxy";
  graph=graph+"&amp;chxt=x,y";
  graph=graph+"&amp;chxr="+axisRanges;
  graph=graph+"&amp;chco=000000,FF0000";
  graph=graph+"&amp;chls=1,1,0|2,2,0";
  graph=graph+"&amp;chm=c,FF0000,1,0,8|d,FF0000,1,1,8";
  graph=graph+"&amp;chg=3,6.7";
/* alert(graph); */
  wbPlot.document.write("<h2 style=\"text-align: center\;\">Weight & Balance Envelope</h2>");
  wbPlot.document.writeln("<img src="+graph+">");
  wbPlot.document.writeln("<p>Cross symbol = take-off weight.<br />Diamond = zero fuel weight</p>");
  wbPlot.document.close();

 }	/*end of graph_wb */

}	/*end of wb_calc */

function clearUserFields() {
 document.WB_form.front_pax_lt.value = 0;
 document.WB_form.front_pax_rt.value = 0;
 document.WB_form.rear_pax_lt.value = 0;
 document.WB_form.rear_pax_rt.value = 0;
 document.WB_form.rear6_pax_lt.value = 0;
 document.WB_form.rear6_pax_rt.value = 0;
 document.WB_form.fuel_lt.value     = 0;
 document.WB_form.fuel_rt.value     = 0
 document.WB_form.baggage_1.value   = 0;
 document.WB_form.baggage_2.value   = 0;
 wb_calc();
}


