// JavaScript Document
//RSP Calculator
// Ayinde Yakubu, Copyright (c) 2003, Unisen Inc


//This method contains a percentage to ordinary number
function percent(value)
{
   var tempvalue =  value / 100.0;
   displayMessage ( "value: " + value + " result " + tempvalue);
   return tempvalue;
}

//-- varify that input is valid
function verifyInput(fieldName)
{
  // 
  // 
  //
}
// -- Converts str into ordinal numbers e.g. 11.24% to 0.1124
// 
function preparePercent(str)
{ 
    var val = str;
    if ( isNaN(str) )
	{ 
	    val = extractLastSign(str, "%");
	}
	result = percent(val);
	return result;
}

// -
//Utility Methods
function isEmpty(field)
{
  return ( field.value==null || field.value=="");
}
// -- Convert string that may contain dollar sign and commas into 
// number e.g. $82,999.92 is converted to 82999.92. The string
//can contain any number of commas and $ sign 
//
function prepareNumber(str)
{
   if ( str == null )
   {
      return 0;
   }
   if ( isNaN(str) == false )
   {
       return    str.valueOf();
   }
   
   var tempStr = str;
   if ( str.lastIndexOf("$") != -1 ) 
   {
       tempArray1 = str.split("$");
	   tempStr = tempArray1.join("");
   }
   var tempStr2 = tempStr;
   if ( tempStr.lastIndexOf(",") != - 1 )
   {
       tempArray2  = tempStr.split(",");
       tempStr2 = tempArray2.join("");
   }
   var result = parseFloat(tempStr2.valueOf());   

   return result;
}
// -- 
// retrieve selected item 
//
function makeIncomeChoice(fieldName)
{
   var option=document.rrspForm.incomeFreqOptions.options[document.rrspForm.incomeFreqOptions.selectedIndex].text;
   document.rrspForm.incomeFreq.value=lookup(option);
}

function makeContribChoice(fieldName)
{
   var option=document.rrspForm.contribOptions.options[document.rrspForm.contribOptions.selectedIndex].text;
   document.rrspForm.contribFreq.value=lookup(option);
}

// -- String formatting routines
// - Take 12122.34639 and return $12,122.35
// -- 

function convertToMoney(amount)
{
  var _dollars=parseInt(amount);
  var _cents=parseInt((amount - _dollars)*100);
  var _negative = _dollars <0;
  if(_negative)
  {  _dollars = -_dollars;
     _cents=-_cents;
  }
  
  while(_cents.toString().length < 2)
     _cents="0"+_cents;
  
  var _dA=_dollars.toString().split("");
  var _d="";
  for(var i=_dA.length-1;i>=0;i--)
  {
    var _comma="";
	if((_dA.length-i)%3==0 && i!=0)_comma=",";
    _d=_comma+_dA[i]+_d;
  }
  var _neg_sign=_negative?"-":"";
  var _result=""+_neg_sign+_d+"."+_cents;
  return _result;
}

// truncate a number to some specified digits after the decimal
function truncateNumber(value, dec)
{
   var decPlace = parseInt(dec);
   var str = value.toString();
   var result = str;
   var pos = str.indexOf(".");
   if ( pos != - 1 ) {
      var parts = str.split(".");
      var tempStr =  parts[1].substr(0, decPlace);
      result = parts[0] + "." + tempStr;
   }   	  
   
   return result;
}
//Extracts % sign from the rate input
function extractLastSign(aItem, aSign)
{
   var result="";
   if ( aItem != null && aSign != null )
   {
       pos=aItem.lastIndexOf(aSign);
	   if (pos != - 1 )
	   {
	      result=aItem.substr(0,pos);
	   }
	   else
	   {
	      result=aItem;
	   }
   }
  // alert(result);
   return result;
}

//Display a simple alert or message box
function displayMessage(value)
{
   if ( debugOn == true )
   {
       //alert (value);
   }
   else 
   { 
     // document.write("<em>" + value + "</em>");
   }
}


// -Method to perform a look up given a description
// It simulates a map
function lookup(description)
{
   for ( i = 0; i < MAP_SIZE; i++)
   {   
      var period = gPeriods[i];
      if ( description == gPeriods[i] ) 
	  {
	     return gPeriodValue[i];
	  }
   }
   //If none found, default to yearly
   return 1;
}

//Deflated Interest Factor
//The rate of inflation is deducted from the expected rate of
//of return. Will be used if payment is not increased due to inflation
function deflatedInterestFactor(inflR, ror)
{  
   var deflatedIntFact =  ( (1.0 - inflR ) * ( 1.0 + ror ) - 1.0);
   displayMessage("deflated Interest Factor" + deflatedIntFact);
   return deflatedIntFact;
}

//Inflated Interest Factor. The rate of inflation is added to the expected rate
//of return. Will be used if the payment is increased due to inflation.
function inflatedInterestFactor(inflationRate, expectedROR)
{
   var inflatedIntFact = (( 1.0 + inflationRate ) * ( 1.0 + expectedROR ) - 1 );
   displayMessage("inflated Interest Factor" + inflatedIntFact);
   return inflatedIntFact;
}


//Annual Income required in dollars. The current value of the required
//income in today's dollars based on the amount and the number of 
//payment per year.
function annualIncomeInTodayDollars(requiredIncome , paymentPerYear)
{
    var annualIncome = requiredIncome * paymentPerYear;
    displayMessage("Annual Income in Today Dollars" + annualIncome);
    return annualIncome;
}

//Annual income required in future dollars. The future value of the desired income
//at retirement with inflation rate applied
function annualIncomeInFutureDollars(requiredIncome, inflationRate, yearsToRetire)
{
    var tempval = Math.pow ( (1.0 + inflationRate), yearsToRetire);
	var fv = (requiredIncome*tempval);
    displayMessage("Annual Income in Future Dollars" + fv);
	return fv;
}

// ---
//  Required Savings at retirement. This refers to the total amount of savings
//  required to sustain income requirement for the total number of years
// ---
function reqSavAtRetireSimple(annualIncomeFD, expectedROR, yearsFundToLast)
{
   var negYears = (-1.0) * yearsFundToLast;
   var tempOne = Math.pow((1.0 + expectedROR), negYears);
   var tempTwo = expectedROR/(1.0 + expectedROR);
   
   var requiredSavings = annualIncomeFD * ( (1.0 - tempOne)/tempTwo);
   displayMessage("required savings simple" + requiredSavings);
   return requiredSavings;
}

// - RequiredSavings at Retirement if Income increases with inflation
// - The total amount of savings required to sustain income requirements for the total
//   number of years if income increases with inflation.
// --
function reqSavAtRetireIncInflation(annualIncomeFD, expectedROR, inflationRate, yearsFundToLast)
{
   var deflatedFactor = deflatedInterestFactor(inflationRate, expectedROR);
   var negYears = (-1.0) * yearsFundToLast;
   var tempOne = Math.pow((1.0 + deflatedFactor), negYears);
   var tempTwo = (deflatedFactor/(1.0 + deflatedFactor));
   
   
   var requiredSavings = annualIncomeFD * ( ( 1.0 - tempOne)/tempTwo);
  // alert (requiredSavings);
  
   //alert("required savings income increase with inflation" + requiredSavings);
   return requiredSavings;
   
}

// - Current RRSP Assets (Future Value). 
// The future value of the present RRSP at retirement time without any further
// contributions
// -
function currentRRSPFutureValueNoContrib(currentRRSP, expectedROR, yearsToRetire)
{
   var tempOne = Math.pow((1.0 + expectedROR ) , yearsToRetire);
  //alert (tempOne);
   var fv = currentRRSP * tempOne;
   displayMessage("Future value of current rrsp" + fv);
   return fv;
}

// --Total Annual Contributions
// The total amount of contributions per year
// -- 
function totalAnnualContribMethod(contribAmount, contributionFactor)
{
   var totalContrib = contribAmount * contributionFactor;
   displayMessage("Total annual contribution" + totalContrib);
   return totalContrib;
}

//--
//Future value of current assets
//The future value of present RRSP at retirement with further contributions
//--
function currentRRSPFutureValueWithContrib(currentRRSP, expectedROR, noOfPeriods, totalAnnualContrib)
{  
   var one = new Number(1.0);
   var tROR = one + expectedROR;
   var tperiod = new Number(noOfPeriods);
   var tempOne = Math.pow(tROR, noOfPeriods);

   var tPeriods =  one + tperiod ;
   var tempExp = Math.pow(tROR, tPeriods);
   
   var futureValue = (currentRRSP * tempOne) + totalAnnualContrib * ((tempExp - tROR)/expectedROR);
   displayMessage("Future value of current rrsp with contrib" + futureValue);   
   return futureValue;
}

//---
//Future value of current assets if contribution increases with inflation.
//The future value of the present RRSP asset at retirement time with further contributions
//that increase with inflation
//
//
//  Balance(n) = P(1 + r)^n + c[((1 + r1)^{n + 1} - (1 + r1))/r1]
// Where P : Principal
//       C : Contribution part
//       r : Expected ROR
//       r1: Expected ROR with inflation rate added
//---
function currentRRSPFutureValueWithContribInflate(currentRRSP, expectedROR, inflationRate, noOfPeriods, totalAnnualContrib)
{

   
   //var str = new String(inflatedIntr);
   //var pos = str.indexOf(".");
   //var truncIntr = str.substr(pos, 5).valueOf();
   //inflatedIntr = truncIntr;
   
   var addedIntr = new Number(1.0) + new Number(expectedROR);
   //alert(addedIntr);
   
   var principalCompoundIntr = Math.pow(addedIntr, noOfPeriods);
   //alert(principalCompoundIntr);

  //Calculate the principal part   
   var principalGrowthPart = currentRRSP * principalCompoundIntr;
   //alert(principalGrowthPart);


   //Calculate interest rates with inflation
   var inflatedIntr = inflatedInterestFactor(inflationRate, expectedROR);
   //alert(inflatedIntr);

   var addedInflatedIntr = new Number(1.0) + new Number(inflatedIntr);
   //alert("Sum Inflated Intr Rate: " +addedInflatedIntr);
   
   //alert("A.No of periods: " + noOfPeriods);
   var periods = new Number(noOfPeriods)  + new Number(1.0);
   //alert("B.No of periods: " + noOfPeriods);
   var contribCompoundIntr = Math.pow(addedInflatedIntr, periods);
   //alert(contribCompoundIntr);
    
   //Calculate the contribution part
   var contribGrowth = (contribCompoundIntr -  addedInflatedIntr)/inflatedIntr;
   var contribPart =  totalAnnualContrib *  contribGrowth ;
   
   var fv = principalGrowthPart + contribPart;
   
   //alert("Final-> " + fv);
   displayMessage("future value if contrib increases with inflation " + fv);
   
   return fv;
}

// ---
// Net Amount Required.
// The difference between the future values of current RRSP assets with contributions and 
// required savings at retirement
// ---
function netAmountRequired( requiredSavingAtRetirement, futureValueOfRRSP)
{
    var netAmount = requiredSavingAtRetirement - futureValueOfRRSP;
    displayMessage("Net amount required" + netAmount);
	return netAmount;
}

// ---
// Required Total Annual Contribution Amount
// The amount of contribution required annually over the years to retirement in order
// to meet the net amount 
// ---
function requiredTotalAnnualContrib(netAmountRequired, expectedROR, yearsToRetirement )
{  
   var sumROR = 1.0 + expectedROR;
   var incrYear  = new Number(1.0) + new Number(yearsToRetirement);
   var tempOne = Math.pow(sumROR, incrYear);
   
   var requiredTotalAmt = netAmountRequired / ((tempOne - sumROR)/expectedROR);
   displayMessage("required total amount " + requiredTotalAmt);
   
   return requiredTotalAmt;
}

// ---
// Required Contribution Amount
// The required amount of contribution per year
// ---
function requiredContribPerPeriod(requiredTotalAmt, reqContrPerYear)
{
     var amount = requiredTotalAmt / reqContrPerYear;
	 displayMessage("Required Contrib per period " + amount );
	 return amount;
}	

function rifDrawdownCalculator(rifdForm) {
    //extract all parameters
    var interestRateOnLoan = preparePercent(rifdForm.txtIROL.value, "%");
    var marginalTaxRate = preparePercent(rifdForm.txtMTR.value, "%");
    var rateOfReturn = preparePercent(rifdForm.txtROR.value, "%");
    var startingBalance  = prepareNumber(rifdForm.txtSB.value);
    var loan  = prepareNumber(rifdForm.txtLOAN.value);
    var annualWithdrawalPercent  = preparePercent(rifdForm.txtAW.value, "%");
    var isTwentyYears = rifdForm.radYEARS[1].checked;
   
    //perform necessary calculations
    var interestPaid = interestRateOnLoan * loan;
    var rateOfReturnMult = parseFloat(1) + rateOfReturn;
    var year1 = calcEndOfYearBalance(startingBalance, rateOfReturnMult, annualWithdrawalPercent);
    var year2 = calcEndOfYearBalance(year1, rateOfReturnMult, annualWithdrawalPercent);
    var year3 = calcEndOfYearBalance(year2, rateOfReturnMult, annualWithdrawalPercent); 
    var year4 = calcEndOfYearBalance(year3, rateOfReturnMult, annualWithdrawalPercent); 
    var year5 = calcEndOfYearBalance(year4, rateOfReturnMult, annualWithdrawalPercent); 
    var year6 = calcEndOfYearBalance(year5, rateOfReturnMult, annualWithdrawalPercent); 
    var year7 = calcEndOfYearBalance(year6, rateOfReturnMult, annualWithdrawalPercent); 
    var year8 = calcEndOfYearBalance(year7, rateOfReturnMult, annualWithdrawalPercent); 
    var year9 = calcEndOfYearBalance(year8, rateOfReturnMult, annualWithdrawalPercent); 
    var year10 = calcEndOfYearBalance(year9, rateOfReturnMult, annualWithdrawalPercent); 
    var year11 = calcEndOfYearBalance(year10, rateOfReturnMult, annualWithdrawalPercent); 
    var year12 = calcEndOfYearBalance(year11, rateOfReturnMult, annualWithdrawalPercent); 
    var year13 = calcEndOfYearBalance(year12, rateOfReturnMult, annualWithdrawalPercent); 
    var year14 = calcEndOfYearBalance(year13, rateOfReturnMult, annualWithdrawalPercent); 
    var year15 = calcEndOfYearBalance(year14, rateOfReturnMult, annualWithdrawalPercent); 
    var year16 = calcEndOfYearBalance(year15, rateOfReturnMult, annualWithdrawalPercent); 
    var year17 = calcEndOfYearBalance(year16, rateOfReturnMult, annualWithdrawalPercent); 
    var year18 = calcEndOfYearBalance(year17, rateOfReturnMult, annualWithdrawalPercent); 
    var year19 = calcEndOfYearBalance(year18, rateOfReturnMult, annualWithdrawalPercent); 
    var year20 = calcEndOfYearBalance(year19, rateOfReturnMult, annualWithdrawalPercent);     
    
    var year1Withdrawal = startingBalance * annualWithdrawalPercent;
    var year2Withdrawal = year1 * annualWithdrawalPercent;
    var year3Withdrawal = year2 * annualWithdrawalPercent;
    var year4Withdrawal = year3 * annualWithdrawalPercent;
    var year5Withdrawal = year4 * annualWithdrawalPercent;
    var year6Withdrawal = year5 * annualWithdrawalPercent;
    var year7Withdrawal = year6 * annualWithdrawalPercent;
    var year8Withdrawal = year7 * annualWithdrawalPercent;
    var year9Withdrawal = year8 * annualWithdrawalPercent;
    var year10Withdrawal = year9 * annualWithdrawalPercent; 
    var year11Withdrawal = startingBalance * annualWithdrawalPercent;
    var year12Withdrawal = year1 * annualWithdrawalPercent;
    var year13Withdrawal = year2 * annualWithdrawalPercent;
    var year14Withdrawal = year3 * annualWithdrawalPercent;
    var year15Withdrawal = year4 * annualWithdrawalPercent;
    var year16Withdrawal = year5 * annualWithdrawalPercent;
    var year17Withdrawal = year6 * annualWithdrawalPercent;
    var year18Withdrawal = year7 * annualWithdrawalPercent;
    var year19Withdrawal = year8 * annualWithdrawalPercent;
    var year20Withdrawal = year9 * annualWithdrawalPercent; 
    
    var years = isTwentyYears ? new Number(20) : new Number(10);
    var totalWithdrawal = parseFloat(year1Withdrawal) + parseFloat(year2Withdrawal) + parseFloat(year3Withdrawal) + parseFloat(year4Withdrawal) + parseFloat(year5Withdrawal) +
                          parseFloat(year6Withdrawal) + parseFloat(year7Withdrawal) + parseFloat(year8Withdrawal) + parseFloat(year9Withdrawal) + parseFloat(year10Withdrawal);
    if(isTwentyYears) {
        totalWithdrawal = parseFloat(totalWithdrawal) + parseFloat(year11Withdrawal) + parseFloat(year12Withdrawal) + parseFloat(year13Withdrawal) + parseFloat(year14Withdrawal) + parseFloat(year15Withdrawal) +
                          parseFloat(year16Withdrawal) + parseFloat(year17Withdrawal) + parseFloat(year18Withdrawal) + parseFloat(year19Withdrawal) + parseFloat(year20Withdrawal);
    }
    var averageWithdrawal = totalWithdrawal / years;
    
    var subTotal = interestPaid + averageWithdrawal;       
    
    var year1M = calcRIFMeltdown(startingBalance, rateOfReturnMult, year1Withdrawal, interestPaid);
    var year2M = calcRIFMeltdown(year1M, rateOfReturnMult, year2Withdrawal, interestPaid);
    var year3M = calcRIFMeltdown(year2M, rateOfReturnMult, year3Withdrawal, interestPaid);
    var year4M = calcRIFMeltdown(year3M, rateOfReturnMult, year4Withdrawal, interestPaid);
    var year5M = calcRIFMeltdown(year4M, rateOfReturnMult, year5Withdrawal, interestPaid);
    var year6M = calcRIFMeltdown(year5M, rateOfReturnMult, year6Withdrawal, interestPaid);
    var year7M = calcRIFMeltdown(year6M, rateOfReturnMult, year7Withdrawal, interestPaid);
    var year8M = calcRIFMeltdown(year7M, rateOfReturnMult, year8Withdrawal, interestPaid);
    var year9M = calcRIFMeltdown(year8M, rateOfReturnMult, year9Withdrawal, interestPaid);
    var year10M = calcRIFMeltdown(year9M, rateOfReturnMult, year10Withdrawal, interestPaid);
    var year11M = calcRIFMeltdown(year10M, rateOfReturnMult, year11Withdrawal, interestPaid);
    var year12M = calcRIFMeltdown(year11M, rateOfReturnMult, year12Withdrawal, interestPaid);
    var year13M = calcRIFMeltdown(year12M, rateOfReturnMult, year13Withdrawal, interestPaid);
    var year14M = calcRIFMeltdown(year13M, rateOfReturnMult, year14Withdrawal, interestPaid);
    var year15M = calcRIFMeltdown(year14M, rateOfReturnMult, year15Withdrawal, interestPaid);
    var year16M = calcRIFMeltdown(year15M, rateOfReturnMult, year16Withdrawal, interestPaid);
    var year17M = calcRIFMeltdown(year16M, rateOfReturnMult, year17Withdrawal, interestPaid);
    var year18M = calcRIFMeltdown(year17M, rateOfReturnMult, year18Withdrawal, interestPaid);
    var year19M = calcRIFMeltdown(year18M, rateOfReturnMult, year19Withdrawal, interestPaid);
    var year20M = calcRIFMeltdown(year19M, rateOfReturnMult, year20Withdrawal, interestPaid);
   
    var year1IV = loan * rateOfReturnMult;
    var year2IV = year1IV * rateOfReturnMult;                 
    var year3IV = year2IV * rateOfReturnMult;                 
    var year4IV = year3IV * rateOfReturnMult;                 
    var year5IV = year4IV * rateOfReturnMult;                 
    var year6IV = year5IV * rateOfReturnMult;                 
    var year7IV = year6IV * rateOfReturnMult;                 
    var year8IV = year7IV * rateOfReturnMult;                 
    var year9IV = year8IV * rateOfReturnMult;                 
    var year10IV = year9IV * rateOfReturnMult;                 
    var year11IV = year10IV * rateOfReturnMult;
    var year12IV = year11IV * rateOfReturnMult;                 
    var year13IV = year12IV * rateOfReturnMult;                 
    var year14IV = year13IV * rateOfReturnMult;                 
    var year15IV = year14IV * rateOfReturnMult;                 
    var year16IV = year15IV * rateOfReturnMult;                 
    var year17IV = year16IV * rateOfReturnMult;                 
    var year18IV = year17IV * rateOfReturnMult;                 
    var year19IV = year18IV * rateOfReturnMult;                 
    var year20IV = year19IV * rateOfReturnMult;       
    
    var yearsIV = isTwentyYears ? year20IV : year10IV;
    var investmentsAfterLoan =  yearsIV - loan;
    var capitalGainsTax = investmentsAfterLoan * marginalTaxRate * 0.5;
    var yearsTotal = isTwentyYears ? year20 : year10;
    var yearsMeltdown = isTwentyYears ? year20M : year10M;  
    var taxOnRif =  yearsMeltdown * marginalTaxRate;
    var taxOnRifNo = yearsTotal * marginalTaxRate;
    var taxPayable = parseFloat(capitalGainsTax) + parseFloat(taxOnRif);
    var afterTaxValue = parseFloat(yearsMeltdown) + parseFloat(yearsIV) - parseFloat(taxPayable);
    var afterTaxValueNoRIF = parseFloat(yearsTotal) - parseFloat(taxOnRifNo);
    var netInvestments = afterTaxValue - loan; 
      
    //display results
    display_number(startingBalance, 'divSB', MILLION_FORMAT);
    display_number(startingBalance, 'divNoSB', MILLION_FORMAT);
    display_number(loan, 'divDL', TEN_THOUSAND_FORMAT);
    display_number(interestPaid, 'divLAI', TEN_THOUSAND_FORMAT);
    display_number(averageWithdrawal, 'divRIFW', TEN_THOUSAND_FORMAT);
    display_number(averageWithdrawal, 'divNoRIFW', TEN_THOUSAND_FORMAT);
    display_number(interestPaid, 'divDAW', MILLION_FORMAT);
    display_number(subTotal, 'divSUB', MILLION_FORMAT);
    display_number(averageWithdrawal, 'divNoSUB', MILLION_FORMAT);
    display_number(yearsMeltdown, 'divRIFV', MILLION_FORMAT);
    display_number(yearsTotal, 'divNoRIFV', MILLION_FORMAT);
    display_number(yearsIV, 'divIV', MILLION_FORMAT);
    display_number(taxPayable, 'divNTP', MILLION_FORMAT);
    display_number(taxOnRifNo, 'divNoNTP', MILLION_FORMAT);
    display_number(afterTaxValue, 'divATV', MILLION_FORMAT);
    display_number(afterTaxValueNoRIF, 'divNoATV', MILLION_FORMAT);
    display_number(loan, 'divLB', MILLION_FORMAT);
    display_number(netInvestments, 'divNATI', MILLION_FORMAT);
    display_number(afterTaxValueNoRIF, 'divNoNATI', MILLION_FORMAT);
    display_number((netInvestments - afterTaxValueNoRIF), 'divDA', MILLION_FORMAT);
        
    display_number(year1Withdrawal, 'divYear1', TEN_THOUSAND_FORMAT);
    display_number(year2Withdrawal, 'divYear2', TEN_THOUSAND_FORMAT);
    display_number(year3Withdrawal, 'divYear3', TEN_THOUSAND_FORMAT);
    display_number(year4Withdrawal, 'divYear4', TEN_THOUSAND_FORMAT);
    display_number(year5Withdrawal, 'divYear5', TEN_THOUSAND_FORMAT);
    display_number(year6Withdrawal, 'divYear6', TEN_THOUSAND_FORMAT);
    display_number(year7Withdrawal, 'divYear7', TEN_THOUSAND_FORMAT);
    display_number(year8Withdrawal, 'divYear8', TEN_THOUSAND_FORMAT);
    display_number(year9Withdrawal, 'divYear9', TEN_THOUSAND_FORMAT);
    display_number(year10Withdrawal, 'divYear10', TEN_THOUSAND_FORMAT);
    
    if(isTwentyYears) {
        display_number(year11Withdrawal, 'divYear11', TEN_THOUSAND_FORMAT);
        display_number(year12Withdrawal, 'divYear12', TEN_THOUSAND_FORMAT);
        display_number(year13Withdrawal, 'divYear13', TEN_THOUSAND_FORMAT);
        display_number(year14Withdrawal, 'divYear14', TEN_THOUSAND_FORMAT);
        display_number(year15Withdrawal, 'divYear15', TEN_THOUSAND_FORMAT);
        display_number(year16Withdrawal, 'divYear16', TEN_THOUSAND_FORMAT);
        display_number(year17Withdrawal, 'divYear17', TEN_THOUSAND_FORMAT);
        display_number(year18Withdrawal, 'divYear18', TEN_THOUSAND_FORMAT);
        display_number(year19Withdrawal, 'divYear19', TEN_THOUSAND_FORMAT);
        display_number(year20Withdrawal, 'divYear20', TEN_THOUSAND_FORMAT);
    } else {
        display_number(EMPTY_FORMAT, 'divYear11', EMPTY_FORMAT);
        display_number(EMPTY_FORMAT, 'divYear12', EMPTY_FORMAT);
        display_number(EMPTY_FORMAT, 'divYear13', EMPTY_FORMAT);
        display_number(EMPTY_FORMAT, 'divYear14', EMPTY_FORMAT);
        display_number(EMPTY_FORMAT, 'divYear15', EMPTY_FORMAT);
        display_number(EMPTY_FORMAT, 'divYear16', EMPTY_FORMAT);
        display_number(EMPTY_FORMAT, 'divYear17', EMPTY_FORMAT);
        display_number(EMPTY_FORMAT, 'divYear18', EMPTY_FORMAT);
        display_number(EMPTY_FORMAT, 'divYear19', EMPTY_FORMAT);
        display_number(EMPTY_FORMAT, 'divYear20', EMPTY_FORMAT);       
    }
}

function calcRIFMeltdown(balance, rateOfReturnMult, yearWithdrawal, interestPaid) {
    return (rateOfReturnMult * balance) - yearWithdrawal - interestPaid;
}

function calcEndOfYearBalance(balance, rateOfReturnMult, annualWithdrawalPercent) {
    return (rateOfReturnMult * balance) - (annualWithdrawalPercent * balance);
}

/**
 * The main driver called by the rspml.htm form submission 
 * RSP Montly Loan Payment Calculator
 */
function rspMonthlyCalculator(rspmlForm)
{
   //extract all parameters
   var amountToBorrow = prepareNumber(rspmlForm.txtATB.value);    
   var interestRate  = preparePercent(rspmlForm.txtIR.value, "%");
   var interestRatePerMonth = interestRate/12;
   var term = prepareNumber(rspmlForm.selectTERM.options[rspmlForm.selectTERM.selectedIndex].text);
   var numberOfDaysDeferralMonths = prepareNumber(rspmlForm.selectNDD.selectedIndex);
   var numberOfDaysDeferral = prepareNumber(rspmlForm.selectNDD.options[rspmlForm.selectNDD.selectedIndex].text); 
   var netPresentValue = amountToBorrow;
   
   if(numberOfDaysDeferralMonths > 0 ) {
        term = term - numberOfDaysDeferralMonths;
        var accumulatedInterest = round_decimals(amountToBorrow * interestRate * ((numberOfDaysDeferral-30)/365),2);
        netPresentValue = parseFloat(amountToBorrow) + accumulatedInterest;
   }
   
   var pmt = calculate_payment(netPresentValue, interestRatePerMonth, term);
   
   if(isNaN(pmt)) {
        display_number("0.00",'divMP',"0.00");
        display_number("0.00",'divCOB',"0.00");
   } else {
        display_number(pmt,'divMP',"0.00");
        var costOfBorrowing = (pmt * term) - amountToBorrow;
        display_number(costOfBorrowing,'divCOB',"0.00");
   } 
   render_text(term, 'divNOP');
}

/**
 * The main driver called by the leverage.htm form submission 
 * Leverage Calculator
 */
function leverageCalculator(levForm) {
   //extract all parameters
   var totalMonthlyPayment = prepareNumber(levForm.txtTMP.value);    
   var interestRate  = preparePercent(levForm.txtLIR.value, "%");
   var rateOfReturn  = preparePercent(levForm.txtROR.value, "%");
   var marginalTaxRateInc = preparePercent(levForm.txtMTRRI.value, "%");
   var marginalTaxRateCG = preparePercent(levForm.txtMTRCP.value, "%");
   
   //common to investment loan and pac
   var months = new Number(12);
   var years = new Number(20);
   var term = new Number(240);
   var rateOfReturnPerMonth = rateOfReturn / months;
   
   //perform calculations investment loan
   var loanAmount =  months * totalMonthlyPayment / interestRate;
   var montlyLoanInterestPayment = loanAmount * interestRate / months;
   var annualLoanInterestCost = montlyLoanInterestPayment * months;
   var potentialTaxRefund = annualLoanInterestCost * marginalTaxRateInc;
   var bookValueIL = loanAmount + (years * potentialTaxRefund);
   var futureValue = future_value(loanAmount, rateOfReturnPerMonth, term);
   var futureValueTR = future_valuePMT(potentialTaxRefund, rateOfReturn, years);
   var futureValueTotal = parseFloat(futureValue) + parseFloat(futureValueTR);
   var netValue = futureValueTotal - loanAmount;
   var capitalGain = futureValueTotal - bookValueIL;
   var potentialTax = capitalGain * marginalTaxRateCG;
   var netAfterTaxValue = netValue - potentialTax;
   
   //perform calculations pac only
   var annualSIPInvestment = months * totalMonthlyPayment;
   var bookValueSIP = years * annualSIPInvestment;
   var futureValueSIP = future_valuePMT(totalMonthlyPayment, rateOfReturnPerMonth, term);
   var capitalGainSIP = futureValueSIP - bookValueSIP;
   var potentialTaxSIP = capitalGainSIP * marginalTaxRateCG;
   var netAfterTaxValueSIP = futureValueSIP - potentialTaxSIP;
   
   //display results investment loan
   display_number(loanAmount, "divLA", TEN_THOUSAND_FORMAT);
   display_number(montlyLoanInterestPayment, "divIP", TEN_THOUSAND_FORMAT);
   display_number(annualLoanInterestCost, "divALIC", TEN_THOUSAND_FORMAT);
   display_number(potentialTaxRefund, "divPATR", TEN_THOUSAND_FORMAT);
   display_number(bookValueIL, "divBVI", TEN_THOUSAND_FORMAT);
   display_number(futureValue, "divFLP", TEN_THOUSAND_FORMAT);
   display_number(futureValueTR, "divFTR", TEN_THOUSAND_FORMAT);
   display_number(futureValueTotal, "divTFVI", TEN_THOUSAND_FORMAT);
   display_number(loanAmount, "divLLA", TEN_THOUSAND_FORMAT);
   display_number(netValue, "divNVAP", TEN_THOUSAND_FORMAT);
   display_number(capitalGain, "divCG", TEN_THOUSAND_FORMAT);
   display_number(potentialTax, "divPTL", TEN_THOUSAND_FORMAT);
   display_number(netAfterTaxValue, "divNATV", TEN_THOUSAND_FORMAT);
   
   //display results pac only
   display_number(totalMonthlyPayment, "divPSIP", TEN_THOUSAND_FORMAT);
   display_number(annualSIPInvestment, "divPASIP", TEN_THOUSAND_FORMAT);
   display_number(bookValueSIP, "divPBVI", TEN_THOUSAND_FORMAT);
   display_number(futureValueSIP, "divPFSIP", TEN_THOUSAND_FORMAT);
   display_number(futureValueSIP, "divPTFVI", TEN_THOUSAND_FORMAT);
   display_number(futureValueSIP, "divPNVAP", TEN_THOUSAND_FORMAT);
   display_number(capitalGainSIP, "divPCG", TEN_THOUSAND_FORMAT);
   display_number(potentialTaxSIP, "divPPTL", TEN_THOUSAND_FORMAT);
   display_number(potentialTaxSIP, "divPNATV", TEN_THOUSAND_FORMAT);
   display_number(netAfterTaxValueSIP, "divPNATV", TEN_THOUSAND_FORMAT);
   
   render_text("&nbsp;", 'divDiagram');  
   if(!isNaN(netAfterTaxValue) && netAfterTaxValue > 0 && !isNaN(netAfterTaxValueSIP) && netAfterTaxValueSIP > 0) {
        drawDiagram(netAfterTaxValue, netAfterTaxValueSIP, "Investment&nbsp;Loan", "PAC&nbsp;Only", "Use leverage to boost returns");
   }
}

function drawDiagram(bar1, bar2, bar1txt, bar2txt, title) {
    var yMax = bar1 > bar2 ? bar1 : bar2;
    var D=new Diagram();
    D.SetFrame(150, 20, 500, 360);
    var formattedNumber = "$" + format_number(bar1);
    var formattedNumber2 = "$" + format_number(bar2);
    var r=1;
    var dy = yMax;
    while (Math.abs(dy)>=100) { dy/=10; r*=10; }
    while (Math.abs(dy)<10) { dy*=10; r/=10; }
    var deltay = 10*r*_sign(dy);
    var vMax = Math.ceil(yMax + parseFloat(deltay));
    D.SetBorder(-1, 13, 0, vMax);
    D.SetText("","", title);
    D.XScale=0;
    D.Draw("#c0c0c0", "#004080", false);
    var B = new Bar(D.ScreenX(1), D.ScreenY(bar1), D.ScreenX(2), D.ScreenY(0), "#99cc00", formattedNumber , "#FFFFFF", bar1txt);
    var B2 = new Bar(D.ScreenX(7), D.ScreenY(bar2), D.ScreenX(8), D.ScreenY(0), "#4d4d80", formattedNumber2 , "#FFFFFF", bar2txt);
    D.Write();
    delete D;
}

/**
 * The main driver called by the samm.htm form submission 
 * Four-in-One Calculator
 */
function sammCalculator(sammForm) {
   //extract all parameters
   var loanAmount = prepareNumber(sammForm.txtLA.value);      
   var interestRate  = preparePercent(sammForm.txtLIR.value, "%");
   var rateOfReturn  = preparePercent(sammForm.txtROR.value, "%");
   var marginalTaxRateInc = preparePercent(sammForm.txtMTRRI.value, "%");
   var marginalTaxRateCG = preparePercent(sammForm.txtMTRCP.value, "%");
   
  //common to investment loan and pac
   var months = new Number(12);
   var years = new Number(20);
   var term = new Number(240);
   var rateOfReturnPerMonth = rateOfReturn / months;
   
   //perform calculations four-in-one
   var monthlyLoanInterestPayment = loanAmount * interestRate / months;
   var monthlySIP = loanAmount / term;
   var monthlyTotalPayment = parseFloat(monthlyLoanInterestPayment) + parseFloat(monthlySIP);
   var annualRSPContribution = monthlySIP * months;
   var totalAnnualLoanInterest = monthlyLoanInterestPayment * months;
   var potentialTaxRefund = (parseFloat(annualRSPContribution) + parseFloat(totalAnnualLoanInterest)) * marginalTaxRateInc;
   var futureValueRSP = future_valuePMT(monthlySIP, rateOfReturnPerMonth, term);
   var futureValueTR = future_valuePMT(potentialTaxRefund, rateOfReturn, years);
   var futureValueTotal = parseFloat(futureValueRSP) + parseFloat(futureValueTR);
   var potentialTaxLiability = futureValueTotal * marginalTaxRateInc;
   var netAfterTaxValue = futureValueTotal - potentialTaxLiability;
   var futureValueOI = future_value(loanAmount, rateOfReturn, years);
   var capitalGains = futureValueOI - loanAmount;
   var potentialTaxLiabilityCG = capitalGains * marginalTaxRateCG;
   var netAfterTaxValueCG = capitalGains - potentialTaxLiabilityCG;
   var totalNetAfterTaxValue = parseFloat(netAfterTaxValue) + parseFloat(netAfterTaxValueCG);
   
   //perform calculations pac only   
   var annualRSPContributionPAC = monthlyTotalPayment * months;
   var potentialTaxRefundPAC = annualRSPContributionPAC * marginalTaxRateInc;
   var futureValueRSPPAC = future_valuePMT(monthlyTotalPayment, rateOfReturnPerMonth, term);
   var futureValueTRPAC = future_valuePMT(potentialTaxRefundPAC, rateOfReturn, years);
   var futureValueTotalPAC = parseFloat(futureValueRSPPAC) + parseFloat(futureValueTRPAC);
   var potentialTaxLiabilityPAC = futureValueTotalPAC * marginalTaxRateInc;
   var netAfterTaxValuePAC = futureValueTotalPAC - potentialTaxLiabilityPAC;
   
   //display results four-in-one
   display_number(monthlyLoanInterestPayment, "divMLIP", TEN_THOUSAND_FORMAT);   
   display_number(monthlySIP, "divMSIP", TEN_THOUSAND_FORMAT);   
   display_number(monthlyTotalPayment, "divTMP", TEN_THOUSAND_FORMAT);   
   display_number(annualRSPContribution, "divARSP", TEN_THOUSAND_FORMAT);   
   display_number(totalAnnualLoanInterest, "divTLI", TEN_THOUSAND_FORMAT);   
   display_number(potentialTaxRefund, "divPATF", TEN_THOUSAND_FORMAT);   
   display_number(futureValueRSP, "divFVRSP", TEN_THOUSAND_FORMAT);   
   display_number(futureValueTR, "divFVATR", TEN_THOUSAND_FORMAT); 
   display_number(futureValueTotal, "divTFVRSP", TEN_THOUSAND_FORMAT); 
   display_number(potentialTaxLiability, "divPTL", TEN_THOUSAND_FORMAT); 
   display_number(netAfterTaxValue, "divNATVRSP", TEN_THOUSAND_FORMAT); 
   display_number(futureValueOI, "divFVOI", TEN_THOUSAND_FORMAT); 
   display_number(loanAmount, "divII", TEN_THOUSAND_FORMAT); 
   display_number(capitalGains, "divCG", TEN_THOUSAND_FORMAT); 
   display_number(potentialTaxLiabilityCG, "divCGPTV", TEN_THOUSAND_FORMAT); 
   display_number(netAfterTaxValueCG, "divNATVOI", TEN_THOUSAND_FORMAT); 
   display_number(totalNetAfterTaxValue, "divTNATV", TEN_THOUSAND_FORMAT); 
   
   //display results pac only
   display_number(monthlyTotalPayment, "divPMSIP", TEN_THOUSAND_FORMAT);   
   display_number(monthlyTotalPayment, "divPTMP", TEN_THOUSAND_FORMAT); 
   display_number(annualRSPContributionPAC, "divPARSP", TEN_THOUSAND_FORMAT);   
   display_number(potentialTaxRefundPAC, "divPPATF", TEN_THOUSAND_FORMAT);   
   display_number(futureValueRSPPAC, "divPFVRSP", TEN_THOUSAND_FORMAT); 
   display_number(futureValueTRPAC, "divPFVATR", TEN_THOUSAND_FORMAT); 
   display_number(futureValueTotalPAC, "divPTFVRSP", TEN_THOUSAND_FORMAT); 
   display_number(potentialTaxLiabilityPAC, "divPPTL", TEN_THOUSAND_FORMAT); 
   display_number(netAfterTaxValuePAC, "divPNATVRSP", TEN_THOUSAND_FORMAT); 
   display_number(netAfterTaxValuePAC, "divPTNATV", TEN_THOUSAND_FORMAT);  
   
   render_text("&nbsp;", 'divDiagram');  
   if(!isNaN(totalNetAfterTaxValue) && totalNetAfterTaxValue > 0 && !isNaN(netAfterTaxValuePAC) && netAfterTaxValuePAC > 0) {
        var sammTitle = "Build your personal pension plan for $" + format_number(monthlyTotalPayment) + " / month";         
        drawDiagram(totalNetAfterTaxValue, netAfterTaxValuePAC, "Four&nbsp;in&nbsp;One", "PAC&nbsp;Only", sammTitle);
   }     
}

function display_number(number, divTag, nan) {
    isNaN(number) ? render_text(nan, divTag)  : render_text(format_number(number), divTag); 
}

function format_number(number) {
    return new NumberFormat(round_decimals(number, 2)).toFormatted();
}

function future_valuePMT(PMT, IR, NP) {
  var FV = IR == 0 ? PMT  * NP : PMT * (Math.pow(1 + IR, NP) - 1) / IR
  return FV;
}

function future_value(PV, IR, NP) {
  var PMT = calculate_payment(PV, IR, NP);
  var FV = IR == 0 ? PV : PMT * (Math.pow(1 + IR, NP) - 1) / IR
  return FV;
}

function calculate_payment(PV, IR, NP) {
  var PMT = ((PV * IR) / (1 - Math.pow(1 + IR, -NP)));
  return PMT;
}

function round_decimals(original_number, decimals) {
  var result1 = original_number * Math.pow(10, decimals)
  var result2 = Math.round(result1)
  var result3 = result2 / Math.pow(10, decimals)
  return (result3)
}

/**
 * The main driver called by the form submission
 */
function rspCalculator(rrspForm)
{
   //extract all parameters
   var expectedROR  = preparePercent(rrspForm.txtROR.value, "%")
   //alert("Expected ROR: " + txtROR);
   
   var inflationRate = preparePercent(rrspForm.inflationRate.value,"%");
   //alert("Inflation rate: " + inflationRate);
   
   var yearsToRetirement = prepareNumber(rrspForm.yearsToRetire.value);
   //alert("Years to retirement: " + yearsToRetirement);
   
   var requiredIncome = prepareNumber(rrspForm.requiredIncome.value);
   //alert("Required Income: " + requiredIncome);
   
   var incomeFrequency = prepareNumber(rrspForm.incomeFreq.value);
   //alert("Income Frequency: " + incomeFrequency);
   
   var contribFreqPerAnnum = prepareNumber(rrspForm.contribFreq.value);
   //alert("Contribution Frequency: " + contribFreqPerAnnum);   
   
   var yearsFundToLast = prepareNumber(rrspForm.txtYearsFundToLast.value);
   //alert("Years funds to Last: " + yearsFundToLast);
   
   var incomeIncreaseWithInflation = identifyRadioSelection(rrspForm.incomeIncreaseWithInflation);
//   alert(incomeIncreaseWithInflation);
   
   var currentRRSP = prepareNumber(rrspForm.currentRRSP.value);
  // alert("Current RRSP Holdings: " + currentRRSP);
   
   var contribAmount = prepareNumber(rrspForm.contribAmount.value);
   //alert("Contribution Amount: " + contribAmount);
   
   var contribIncreaseWithInflation = identifyRadioSelection(rrspForm.contribIncreaseWithInfl);
   //alert("Contribution Increase with inflation: " + contribIncreaseWithInflation);
   
   //Calculate required values
   var deflatedIntrFactor = deflatedInterestFactor(inflationRate,expectedROR);
   var inflatedIntrFactor = inflatedInterestFactor(inflationRate, expectedROR);
   var annualIncomeTodaysDollar = annualIncomeInTodayDollars(requiredIncome, incomeFrequency);
   var annualIncomeInFutureDollar = annualIncomeInFutureDollars(annualIncomeTodaysDollar,inflationRate,yearsToRetirement);
   var requiredSavingsAtRetirement = 0.0;
   
   //Handle savings requirements with and without increase due to inflation
   //alert("Income increase with inflation: " + incomeIncreaseWithInflation);
   if ( incomeIncreaseWithInflation == "no" ) {
		requiredSavingsAtRetirement = reqSavAtRetireSimple(annualIncomeInFutureDollar, expectedROR, yearsFundToLast);
   }
   else {
		requiredSavingsAtRetirement = reqSavAtRetireIncInflation(annualIncomeInFutureDollar, expectedROR, inflationRate, yearsFundToLast);
   }
      
   //Calculate future values of current holdings with and without contributions
   //alert(contribAmount);
   //alert(contribFreqPerAnnum);
   var totalAnnualContrib = totalAnnualContribMethod(contribAmount,contribFreqPerAnnum);
   var futurevalueRRSP = currentRRSPFutureValueNoContrib(currentRRSP, expectedROR, yearsToRetirement);
   var futureValueOfCurrent = futurevalueRRSP;
   
   if ( totalAnnualContrib == 0.0 ){
        futurevalueRRSP = currentRRSPFutureValueNoContrib(currentRRSP, expectedROR, yearsToRetirement);
   }
   
   if (contribIncreaseWithInflation =="no" ) {
       futurevalueRRSP = currentRRSPFutureValueWithContrib(currentRRSP, expectedROR, yearsToRetirement, totalAnnualContrib);
   }
   else { //contribution increases with inflation
       futurevalueRRSP = currentRRSPFutureValueWithContribInflate(currentRRSP, expectedROR, inflationRate, yearsToRetirement, totalAnnualContrib);
   }
   
   //Calculate net amount required
   var netAmountReqd = netAmountRequired(requiredSavingsAtRetirement, futurevalueRRSP);
   
   //Calculate the required total annual contribution amount
   var totalAnnualContribRequired = requiredTotalAnnualContrib(netAmountReqd, expectedROR, yearsToRetirement);
   
   //Required contributions per period
   var reqContribPerPeriod = requiredContribPerPeriod(totalAnnualContribRequired, contribFreqPerAnnum);
   
   //Updates all form fields
   //document.rrspForm.txtdeflatedFactor.value = truncateNumber(deflatedIntrFactor, 4);
   //alert(deflatedIntrFactor);
   //document.rrspForm.txtInflatedFactor.value = truncateNumber(inflatedIntrFactor, 4);
   //alert(inflatedIntrFactor);
   document.rrspForm.txtFVIncome.value = convertToMoney(annualIncomeInFutureDollar);
   //alert(annualIncomeInFutureDollar);   
   document.rrspForm.txtRequiredSavings.value = convertToMoney(requiredSavingsAtRetirement);
   //alert(requiredSavingsAtRetirement);   
   document.rrspForm.txtCurrentRRSPFV.value = convertToMoney(futureValueOfCurrent);
   //alert(futurevalueRRSPNoContrib);   
   document.rrspForm.txtTotalAnnualContrib.value = convertToMoney(totalAnnualContrib);
   //alert(totalAnnualContrib);   
   document.rrspForm.txtRRSPAtRetirement.value = convertToMoney(futurevalueRRSP);
   //alert(futurevalueRRSP);   
   document.rrspForm.txtNetAmountReqd.value = convertToMoney(netAmountReqd);      
   //alert(netAmountReqd);   
   document.rrspForm.txtAdditionalContrib.value = convertToMoney(totalAnnualContribRequired);
   //alert(totalAnnualContribRequired);
   document.rrspForm.txtContribPerPeriod.value  = convertToMoney(reqContribPerPeriod);
   
   
   //reset all variables
   deflatedIntrFactor = 0;
   inflatedIntrFactor = 0;
   annualIncomeInFutureDollar = 0;
   requiredSavingsAtRetirement = 0;
   futurevalueRRSPNoContrib = 0;
   totalAnnualContrib = 0;
   futurevalueRRSP = 0;
   netAmountReqd = 0;      
   totalAnnualContribRequired =0 ;
   reqContribPerPeriod = 0;
}


