/*--------------------------------------------------------------------------.
|  Software: SolarSaver Calculator - core functions                       	|
|   Version: 1.0                                                            |
|   Contact: sander@lighthousesolar.com      								|                
| ------------------------------------------------------------------------- |
|     Admin: Sander Pick (project admininistrator)                          |
|   Authors: Sander Pick                         							|
| Copyright (c) 2009-Today Lighthouse Solar. All Rights Reserved.       	|                     
| ------------------------------------------------------------------------- |
|   License: Distributed under the General Public License (GPL)             |
|            http://www.gnu.org/licenses/licenses.html#GPL                  |
| This program is distributed in the hope that it will be useful - WITHOUT  |
| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
| FITNESS FOR A PARTICULAR PURPOSE.                                         |
'--------------------------------------------------------------------------*/
function PPA(energy,desiredIRR,term,down){this.energy=energy;this.desiredIRR=desiredIRR;this.term=term;this.down=down;this.pMin=0;this.pMax=7000;this.rate=.1;this.xcelRate=.1;this.utilInc=.07;this.power=this.energy/(1391/12);if(this.power>this.pMax)this.unitCost=-.0002*this.pMax+6.39-.5;else if(this.power<this.pMin)this.unitCost=0;else this.unitCost=-.0002*this.power+6.39-.5;this.totalCost=this.unitCost*this.power;do{this.cashFlows=new Array();for(var i=0;i<this.term;i++){var cf=new CashFlow(this.rate,this.down,this.energy/1000,this.power,this.unitCost,i+1);this.cashFlows.push(cf.net);this.worth=cf.worth;this.price=cf.price}this.cashFlows.unshift(-1*this.price);this.irr=getIRR(this.cashFlows);if(this.irr>this.desiredIRR)this.rate-=.0001;if(this.irr<this.desiredIRR)this.rate+=.0001}while(Math.round(this.irr*1000)/1000!=this.desiredIRR);this.ppaCost=(12*(this.energy/1000)*this.term*this.rate)+this.down;this.xcelCost=0;var r=this.xcelRate;for(var j=0;j<this.term;j++){this.xcelCost+=12*r*this.energy/1000;r=this.utilInc*r+r}this.ppaSavings=Math.round(this.xcelCost-this.ppaCost);if(this.ppaSavings<0)this.ppaSavings=0;this.l_rate=.1;this.fm_pay=0;do{for(var i=0;i<this.term;i++){var cf=new CashFlow(this.l_rate,this.down,this.energy/1000,this.power,this.unitCost,i+1);this.fm_pay+=cf.m_pay}this.fm_pay/=this.term;this.cashFlows=new Array();for(var i=0;i<this.term;i++){var cf=new CashFlow(this.l_rate,this.down,this.energy/1000,this.power,this.unitCost,i+1,this.fm_pay*.93);this.cashFlows.push(cf.net)}this.cashFlows.unshift(-1*this.price);this.irr=getIRR(this.cashFlows);if(this.irr>this.desiredIRR)this.l_rate-=.0001;if(this.irr<this.desiredIRR)this.l_rate+=.0001}while(Math.round(this.irr*1000)/1000!=this.desiredIRR);this.leaseCost=(12*this.term*this.fm_pay)+this.down;this.leaseSavings=Math.round(this.xcelCost-this.leaseCost);if(this.leaseSavings<0)this.leaseSavings=0}function CashFlow(r,d,e,p,c,n,fixed){this.r=r;this.d=d;this.e=e;this.p=p;this.c=c;this.n=n;var ER=.9887;var IR=.07;var SOREC=.11;var RI=0;var STR=.0065;var ITR=.35;var MF=.15;var PC=500;var MACRS=new Array(.2,.32,.192,.115,.115,.058);var kwh=12*this.e*Math.pow(ER,this.n-1);var m_pay=kwh*this.r/12;var s_rev=kwh*SOREC;var p_rev=(!fixed)?kwh*this.r:12*fixed*1;var rev=s_rev+p_rev;var t_exp=0;var i_exp=this.p*IR;var m_exp=(-i_exp+rev)*MF;var exp=t_exp+i_exp+m_exp;var i_ppac=this.p*this.c;var t_ppac=this.p*STR*(this.c-1.1);var r_ppac=this.p*2;var n_ppac=i_ppac+t_ppac+PC-r_ppac-this.d;var c_ppac=.3*n_ppac;var ppac=n_ppac-c_ppac;var a_dep=i_ppac+t_ppac-c_ppac/2;var n_dep=(this.n>MACRS.length)?0:MACRS[this.n-1]*a_dep;var dep=ITR*n_dep;var r_net=rev-exp;var t_net=ITR*r_net;var net=r_net+dep-t_net;this.net=net;this.worth=i_ppac+t_ppac+PC;this.price=ppac;this.m_pay=m_pay}function getIRR(cashFlows,estimatedResult){var result;if(cashFlows&&cashFlows.length>0){if(cashFlows[0]!=0.0){var noOfCashFlows=cashFlows.length;var sumCashFlows=0.0;var noOfNegativeCashFlows=0;var noOfPositiveCashFlows=0;for(var i=0;i<noOfCashFlows;i++){sumCashFlows+=cashFlows[i];if(cashFlows[i]>0){noOfPositiveCashFlows++}else if(cashFlows[i]<0){noOfNegativeCashFlows++}}if(noOfNegativeCashFlows>0&&noOfPositiveCashFlows>0){var irrGuess=0.1;if(estimatedResult){irrGuess=estimatedResult;if(irrGuess<=0.0)irrGuess=0.5}var irr=0.0;if(sumCashFlows<0){irr=-irrGuess}else{irr=irrGuess}var minDistance=.0000001;var cashFlowStart=cashFlows[0];var maxIteration=50;var wasHi=false;var cashValue=0.0;for(var i=0;i<=maxIteration;i++){cashValue=cashFlowStart;for(var j=1;j<noOfCashFlows;j++){cashValue+=cashFlows[j]/Math.pow(1.0+irr,j)}if(Math.abs(cashValue)<0.01){result=irr;break}if(cashValue>0.0){if(wasHi){irrGuess/=2}irr+=irrGuess;if(wasHi){irrGuess-=minDistance;wasHi=false}}else{irrGuess/=2;irr-=irrGuess;wasHi=true}if(irrGuess<=minDistance){result=irr;break}}}}}return result}function rnd(n,d){return Math.round(n*Math.pow(10,d))/Math.pow(10,d)}