﻿// declare defaults
var
    NPC_DEFAULT = 1000,         // Default Number of PCs
    ET_DEFAULT = 0.14,          // Default Energy Tariff (in $USD)
    ED_DEFAULT = false,         // Default Education Vertical (false = all other verticals)
    PCOHDNOPS_DEFAULT = 24,     // Default PC On Hours Per Day, No PS Installed
    PCOHDWITHPS_DEFAULT = 9,    // Default PC On Hours Per Day, PS Installed
    PCMTO_DEFAULT = 33,         // Default % PCs Manually Turned Off
    PCCO_DEFAULT = 110,         // Default PC Consumption On
    PCCS_DEFAULT = 10,          // Default PC Consumption Standby
    MCO_DEFAULT = 30,           // Default Monitor Consumption On
    MCS_DEFAULT = 1.5,          // Default Monitor Consumption Standby
    CS_DEFAULT = "$",           // Default Currency Symbol (US)
    MAINTP_DEFAULT = 0,         // Default Maintenance Periods Per Year
    MAINTD_DEFAULT = 4,         // Default Maintenance Duration (hours)
    MOHD_DEFAULT = 9,           // Default Monitor On Hours Per Day
    PSPEduc = 8.670,              // Power Save Price for Education
    PSPCorp = 19.45;             // Power Save Price for Corporate (and all other)

// declare working variables
var
    NPC,                        // Number of PCs field
    ET,                         // Energy Tariff field
    ED,                         // Education Vertical (false = all other verticals)

    PCOHDNOPS,                  // PC On Hours Per Day, NO PS Installed
    PCOHDWITHPS,                // PC On Hours Per Day, PS Installed
    MOHD,                       // Monitor On Hours Per Day

    PCMTO,                      // % PCs Manually Turned Off
    BDY = 260,                  // Business Days Per Year
    SDY = 180,                  // School Days Per Year

    PCCO,                       // PC Consumption On
    PCCS,                       // PC Consumption Standby
    LCDCO,                      // LCD Monitor Consumption On
    LCDCS,                      // LCD Monitor Consumption Standby
    CRTCO,                      // CRT Monitor Consumption On
    CRTCS,                      // CRT Monitor Consumption Standby

    PCOHYNoPS,                  // PC On Hours Per Year, NO PS Installed
    PCOHYWithPS,                // PC On Hours Per Year, PS Installed
    PCNHYNoPS,                  // PC Off Hours Per Year, NO PS Installed
    PCNHYWithPS,                // PC Off Hours Per Year, PS Installed
    MOHYNoPS,                   // Monitor On Hours Per Year, NO PS Installed
    MOHYWithPS,                 // Monitor On Hours Per Year, PS Installed
    MNHYNoPS,                   // Monitor Off Hours Per Year, NO PS Installed
    MNHYWithPS,                 // Monitor Off Hours Per Year, PS Installed

    PCCYNoPS,                   // PC Consumption Per Year, NO PS Installed
    PCCYWithPS,                 // PC Consumption Per Year, PS Installed
    PCCYMTO,                    // PC Consumption Per Year for PCs Manually Turned Off
    MCY,                        // Monitor Consumption Per Year (regardless of Manual Turn-Off)

    TCYNoPS,                    // Total Energy Consumption Per Year, NO PS Installed
    TCYWithPS,                  // Total Energy Consumption Per Year, With PS Installed
    TCYMTO,                     // Total Energy Consumption Per Year for PCs Manually Turned Off

    ECYNoPS,                    // Total Energy Cost Per Year, NO PS Installed
    ECYWithPS,                  // Total Energy Cost Per Year, PS Installed
    ECYMTO,                     // Total Energy Cost Per Year for PCs Manually Turned Off
    TCANoPS,                    // Total Energy Cost All Computers NO PS Installed
    TCAWithPS,                  // Total Energy Cost All Computers With PS Installed

    PSI,                        // Power Save Cost (or Power Save Investment)
    CEC,                        // Current Energy Cost (same as TCANoPS, used for clarity in later calculation)
    ROS,                        // Rate of Savings Per Month
    TBE,                        // Time to Break Even in Months
    ESO,                        // Energy Savings Opportunity (or Energy Consumption Savings)

    CS = CS_DEFAULT,            // Currency symbol for this customer
    PSP,                        // Power Save Price for this customer (including maintenance)
    
    MAINTP,                     // Maintenance Periods Per Year
    MAINTD,                     // Maintenance Duration (hours)
    
    // diagram variables
    D = new Diagram(),
    yMax = 70,
    xMax = 12,
    yScale = 1000,
    yGrids = 8,
    savings_at_max_x,
    roi_at_savings_max_y;

drawGrid();

// diagram variables dependent on an initialized diagram object.
var
    Aroi   = new Area(D.ScreenX(0), D.ScreenY(0), D.ScreenX(0), D.ScreenY(0), "e9cf19", D.ScreenY(0)),
    Amax   = new Area(D.ScreenX(0), D.ScreenY(0), D.ScreenX(0), D.ScreenY(0), "75b418", D.ScreenY(0)),
    Lpower = new Line(D.ScreenX(0), D.ScreenY(0), D.ScreenX(0), D.ScreenY(0), "#888",  1),
    Lcont  = new Line(D.ScreenX(0), D.ScreenY(0), D.ScreenX(0), D.ScreenY(0), "#888",  1),
    Lroi   = new Line(D.ScreenX(0), D.ScreenY(0), D.ScreenX(0), D.ScreenY(0), "#888", 1);

function Recalc()
{
    // calculates the Current Energy Cost, Power Save Investment,
    // Energy Savings Opportunity, and Full Return on Investment.

    // get values from ROI form
    NPC = parseInt(document.getElementById("fldNPC").value);
    ET = parseFloat(document.getElementById("fldET").value);
    ED = document.getElementById("fldED").checked;
    PCOHDWITHPS = parseFloat(document.getElementById("fldPCOHDWITHPS").value);
    PCMTO = parseFloat(document.getElementById("fldPCMTO").value);
    MAINTP = parseInt(document.getElementById("fldMAINTP").value);
    MAINTD = parseInt(document.getElementById("fldMAINTD").value);
    PCCO = parseFloat(document.getElementById("fldPCCO").value);
    PCCS = parseFloat(document.getElementById("fldPCCS").value);
    MCO = parseFloat(document.getElementById("fldMCO").value);
    MCS = parseFloat(document.getElementById("fldMCS").value);

    if(
        isNaN(NPC) || document.getElementById("fldNPC").value.trim() == "" || NPC <= 0
        || isNaN(ET) || document.getElementById("fldET").value.trim() == "" || ET <= 0
        || isNaN(PCOHDWITHPS) || document.getElementById("fldPCOHDWITHPS").value.trim() == "" || PCOHDWITHPS <= 0 || PCOHDWITHPS > 23
        || isNaN(PCMTO) || document.getElementById("fldPCMTO").value.trim() == "" || PCMTO < 0 || PCMTO > 100
        || isNaN(MAINTP) || document.getElementById("fldMAINTP").value.trim() == "" || MAINTP < 0
        || isNaN(MAINTD) || document.getElementById("fldMAINTD").value.trim() == "" || MAINTD < 0.5 || MAINTD > 23
        || isNaN(PCCO) || document.getElementById("fldPCCO").value.trim() == "" || PCCO < 1
        || isNaN(PCCS) || document.getElementById("fldPCCS").value.trim() == "" || PCCS < 1
        || isNaN(MCO) || document.getElementById("fldMCO").value.trim() == "" || MCO < 1
        || isNaN(MCS) || document.getElementById("fldMCS").value.trim() == "" || MCS < 1
      )
    {
        // invalid data or values in ROI form, display all zeros
        divCEC.innerHTML = CS + "0.00 (per year)";
        divPSI.innerHTML = CS + "0.00 (one-time)";
        divESO.innerHTML = CS + "0.00 (per year)";
        divTBE.innerHTML = "0.00 months";
    }
    else
    {
//alert("PCOHYNoPS = " + PCOHYNoPS +
//"\nPCOHYWithPS = " + PCOHYWithPS +
//"\nPCNHYNoPS = " + PCNHYNoPS +
//"\nPCNHYWithPS = " + PCNHYWithPS +
//"\nMOHY = " + MOHY +
//"\nMNHY = " + MNHY +
//"\nPCCYNoPS = " + PCCYNoPS +
//"\nPCCYWithPS = " + PCCYWithPS +
//"\nPCCYMTO = " + PCCYMTO +
//"\nMCY = " + MCY +
//"\nTCYNoPS = " + TCYNoPS +
//"\nTCYWithPS = " + TCYWithPS +
//"\nTCYMTO = " + TCYMTO +
//"\nECYNoPS = " + ECYNoPS +
//"\nECYWithPS = " + ECYWithPS +
//"\nECYMTO = " + ECYMTO +
//"\nTCANoPS = " + TCANoPS +
//"\nTCAWithPS = " + TCAWithPS +
//"\nROS = " + ROS +
//"\nCEC = " + CEC +
//"\nPSI = " + PSI +
//"\nESO = " + ESO +
//"\nTBE = " + TBE);
        // valid data in ROI form

        // calculate single PC/Monitor On and Off Hours Per Year
        PSP = ED ? PSPEduc : PSPCorp;
        PCOHYNoPS = PCOHDNOPS * (ED ? SDY : BDY) + MAINTP * MAINTD;
        PCOHYWithPS = PCOHDWITHPS * (ED ? SDY : BDY);
        PCNHYNoPS = 8760 - PCOHYNoPS;
        PCNHYWithPS = 8760 - PCOHYWithPS;
        MOHY = MOHD * (ED ? SDY : BDY);
        MNHY = 8760 - MOHY;

        // calculate single PC/Monitor Power Consumption Per Year, with and without Manual Turn-Offs
        PCCYNoPS = PCOHYNoPS * PCCO + PCNHYNoPS * PCCS;
        PCCYWithPS = PCOHYWithPS * PCCO + PCNHYWithPS * PCCS;
        PCCYMTO = PCOHYWithPS * PCCO;
        MCY = MOHY * MCO + MNHY * MCS;

        // calculate single PC/Monitor Total Consumption Per Year, with and without Manual Turn-Offs
        TCYNoPS = PCCYNoPS + MCY;
        TCYWithPS = PCCYWithPS + MCY;
        TCYMTO = PCCYMTO + MCY;

        // calculate Total Energy Cost Per Year, with and without Manual Turn-Offs
        ECYNoPS = ET * TCYNoPS / 1000;
        ECYWithPS = ET * TCYWithPS / 1000;
        ECYMTO = ET * TCYMTO / 1000;
        TCANoPS = ECYNoPS * NPC * (100.0 - PCMTO) / 100 + ECYMTO * NPC * PCMTO / 100;
        TCAWithPS = ECYWithPS * NPC * (100 - PCMTO) / 100 + ECYMTO * NPC * PCMTO / 100;

        // make final calculations
        ROS = (TCANoPS - TCAWithPS) / 12;
        CEC = TCANoPS;
        PSI = NPC * PSP;
        ESO = TCANoPS - TCAWithPS;
        TBE = PSI / ROS;

        // render new calculations
        document.getElementById("divCEC").innerHTML = formatCurrency(CEC, CS) + " (per year)";
        document.getElementById("divPSI").innerHTML = formatCurrency(PSI, CS) + " (one-time)";
        document.getElementById("divESO").innerHTML = formatCurrency(ESO, CS) + " (per year)";
        document.getElementById("divTBE").innerHTML = TBE.toFixed(2) + " months";
    }

    // figure out a good yMax based on the amount saved per year
    yMax = parseFloat(ESO * 2 / yScale / 10).toFixed(0) * 8;
    if(yMax < 10)
	    yMax = 10;
	
    //redraw the graph now so the coordinates get updated based on yMax
    drawGrid();

    //TBE = ( ((price_desk * v_num_desktops) + (price_serv * v_num_servers)) / ROS ).toFixed(2);
	
    SavingsAtTBE = savingsAtTime(TBE);
	
    //this line shows savings up until the roi
    Lpower.ResizeTo(D.ScreenX(0), D.ScreenY(0), D.ScreenX(TBE), D.ScreenY(SavingsAtTBE));
	
    //this line shows the roi point
    Lroi.ResizeTo(D.ScreenX(TBE), D.ScreenY(0), D.ScreenX(TBE), D.ScreenY(SavingsAtTBE));
	
    savings_at_max_x = ROS * xMax / yScale;
    if(savings_at_max_x > yMax)
	    savings_at_max_x = yMax;
		
    roi_at_savings_max_y = yScale * yMax / ROS;
    if(roi_at_savings_max_y > xMax)
	    roi_at_savings_max_y = xMax;
	
    //this line continues the saving's line so that visually it continues
    Lcont.ResizeTo(D.ScreenX(TBE), D.ScreenY(SavingsAtTBE), D.ScreenX(roi_at_savings_max_y), D.ScreenY(savings_at_max_x));
	
    Aroi.ResizeTo(D.ScreenX(0), D.ScreenY(0), D.ScreenX(TBE), D.ScreenY(savingsAtTime(TBE)));
    Amax.ResizeTo(D.ScreenX(TBE), D.ScreenY(savingsAtTime(TBE)), D.ScreenX(xMax), D.ScreenY(savingsAtTime(xMax)));
}

function savingsAtTime(time)
{
    return (ROS * time / yScale).toFixed(2);
}

function drawGrid()
{
    D.SetFrame(330, 35, 660, 210);
    D.SetBorder(0, xMax, 0, yMax);
    D.SetText("<b>Time</b>", "<b>Savings</b>", "<b>Are You Power Saving?</b>");
    D.XGridDelta = 1;
    D.YGridDelta = yMax / yGrids;
    D.XScale = "function MyXScale";
    D.YScale = "function MyYScale";
    D.SetGridColor("#cccccc");
    D.Font = "font-family: Verdana; font-weight: normal; font-size: 11px; line-height: 13pt;";
    D.GetXGrid();
    D.GetYGrid();
    D.Draw("#ffffff", "#000000", false);
}

function MyXScale(value)
{
    return value;
}

function MyYScale(value)
{
    return formatCurrency(Math.round(value * 10) / 10 * 1000, CS).replace(/^([^\.]*).*$/, "$1");
}

function formatCurrency(num, symbol)
{
    // format a number for currency

    num = num.toString().replace(/\$|\,/g, "");
    if(isNaN(num))
        num = "0";
    sign = (num == (num = Math.abs(num)));
    num = Math.floor(num * 100 + 0.50000000001);
    cents = num % 100;
    num = Math.floor(num / 100).toString();
    if(cents < 10)
        cents = "0" + cents;
    for (var i = 0; i < Math.floor((num.length - (1 + i)) / 3); i++)
        num = num.substring(0, num.length - (4 * i + 3)) + "," + num.substring(num.length - (4 * i + 3));
    return (((sign) ? "" : "-") + symbol + num + "." + cents);
}

String.prototype.trim = function()
{
    // trim whitespace on either side of a string
    return this.replace(/^\s+|\s+$/g, "");
}

String.prototype.ltrim = function()
{
    // trim whitespace on left side of a string
    return this.replace(/^\s+/, "");
}

String.prototype.rtrim = function()
{
    // trim whitespace on right side of a string
    return this.replace(/\s+$/, "");
}

function addEvent(obj, evType, fn, useCapture)
{
    if(obj.addEventListener){
        obj.addEventListener(evType, fn, useCapture);
        return true;
    }
    else if(obj.attachEvent)
    {
        var r = obj.attachEvent("on" + evType, fn);
        return r;
    }
}

function PSROI_LoadWindow()
{
    // get page elements for rendering new calculations in Recalc()
    _CEC = document.getElementById("CEC");
    _PSC = document.getElementById("PSI");
    _ESO = document.getElementById("ESO");
    _TBE = document.getElementById("TBE");
    
    // initialize formula variables and form
    NPC = Request.GetParamExists("NPC") ? parseInt(Request.QueryString["NPC"]) : NPC_DEFAULT;
    document.getElementById("fldNPC").value = NPC;
    ET = Request.GetParamExists("ET") ? parseFloat(Request.QueryString["ET"]) : ET_DEFAULT;
    document.getElementById("fldET").value = ET;
    ED = Request.GetParamExists("ED") ? (Request.QueryString["ED"] == "1" ? true : false) : ED_DEFAULT;
    document.getElementById("fldED").checked = ED;
    PCOHDWITHPS = Request.GetParamExists("PCOHDWITHPS") ? parseFloat(Request.QueryString["PCOHDWITHPS"]) : PCOHDWITHPS_DEFAULT;
    document.getElementById("fldPCOHDWITHPS").value = PCOHDWITHPS;
    PCOHDNOPS = PCOHDNOPS_DEFAULT;
    PCMTO = Request.GetParamExists("PCMTO") ? parseFloat(Request.QueryString["PCMTO"]) : PCMTO_DEFAULT;
    document.getElementById("fldPCMTO").value = PCMTO;
    MOHD = MOHD_DEFAULT;
    PCCO = Request.GetParamExists("PCCO") ? parseFloat(Request.QueryString["PCCO"]) : PCCO_DEFAULT;
    document.getElementById("fldPCCO").value = PCCO;
    PCCS = Request.GetParamExists("PCCS") ? parseFloat(Request.QueryString["PCCS"]) : PCCS_DEFAULT;
    document.getElementById("fldPCCS").value = PCCS;
    MCO = Request.GetParamExists("MCO") ? parseFloat(Request.QueryString["MCO"]) : MCO_DEFAULT;
    document.getElementById("fldMCO").value = MCO;
    MCS = Request.GetParamExists("MCS") ? parseFloat(Request.QueryString["MCS"]) : MCS_DEFAULT;
    document.getElementById("fldMCS").value = MCS;
    CS = Request.GetParamExists("CS") ? Request.QueryString["CS"] : CS_DEFAULT;
    document.getElementById("CurrSymbol").innerHTML = CS;
    MAINTP = Request.GetParamExists("MAINTP") ? parseFloat(Request.QueryString["MAINTP"]) : MAINTP_DEFAULT;
    document.getElementById("fldMAINTP").value = MAINTP;
    MAINTD = Request.GetParamExists("MAINTD") ? parseFloat(Request.QueryString["MAINTD"]) : MAINTD_DEFAULT;
    document.getElementById("fldMAINTD").value = MAINTD;

    // initialize calculations and focus Number of PCs field
    Recalc();
    document.getElementById("fldNPC").focus();
}

function PSROIContactMe()
{
    window.close();
    window.opener.location.href = "http://powersavesoftware.com/contact.html";
}