????

Your IP : 216.73.216.152


Current Path : C:/Windows/System32/en-US/
Upload File :
Current File : C:/Windows/System32/en-US/energy.dll.mui

MZ����@���	�!�L�!This program cannot be run in DOS mode.

$��<߱�R���R���R�U�����R�U�P���R�Rich��R�PEL�!�

�X�@ д8.rdata�@@.rsrc� �@@�]5�
T88�]5�$��8.rdata8x.rdata$zzzdbg �.rsrc$01�+Щ.rsrc$02 `(�K���dT�K��pf1�z��[9���]5�X	�8�P�x������#9�?0�@H�E`�Fx�L��M��N��O��P��Q�R �S8�XP�Yh�^��_��e��f��k��l��m�n(�o@�pX�qp�r��s��t��w��x��~���0��H�`�x�	`	����	����	���
���N
����
���
� ��
�8�:�P�	h	x	�	�	�	�	�	�	�	�			(	8	H	X	h	x	�	�	�	�	�	�	�	�			(	8	H	X	h	x	�	�	�	�	�	�	�	�					(		8		H	t+��,,���.��/���0��|3p��8���=��LD(�tJJ��P��Wz�D\���_P�@d��g"�,k���lp�DtN��v��x���~	�����L���������
����̹l�8��� �X�x���P�����$������@���6��0�H�������%�,�l���ݟ�x����S����8�F� ��̀T�MUIIDR_SLEEPSTUDY_LOCAL_HTMLIDR_SLEEPSTUDY_TEMPLATE_CSS#IDR_SLEEPSTUDY_TEMPLATE_DATA_LOADERIDR_SLEEPSTUDY_TEMPLATE_HTMLIDR_SLEEPSTUDY_TEMPLATE_JSIDR_XML_BATTERY_TRANSFORMIDR_XML_DEFAULT_TRANSFORM.XSL"IDR_XML_SLEEPDIAGNOSTICS_TRANSFORMIDR_XML_SLEEPSTUDY_TRANSFORM�����w���
�g=��w���n�t�%�o����MUIen-USAnalysis FailureZAnalysis was unsuccessful. This can be caused by a corrupted trace file or dropped events.Analysis Error\Analysis was partially unsuccessful. Some results are available, but they may be incomplete.Analysis Success`Analysis was successful. No energy efficiency problems were found.  No information was returned.System InformationSystem InformationSystem Information Details
Computer NameSystem ManufacturerSystem Product Name	BIOS DateBIOS VersionOS Build Number
Platform Role
Process CountThread Count
Plugged InPAPlatform Timer ResolutionPlatform Timer Resolution,The default platform timer resolution is 15.6ms (15625000ns) and should be used whenever the system is idle.  If the timer resolution is increased, processor power management technologies may not be effective.  The timer resolution may be increased due to multimedia playback or graphical animations.&Current Timer Resolution (100ns units)"Maximum Timer Period (100ns units)Outstanding Timer RequestiA program or service has requested a timer resolution smaller than the platform maximum timer resolution.Requested PeriodRequesting Process IDRequesting Process Path Outstanding Kernel Timer RequestxA kernel component or device driver has requested a timer resolution smaller than the platform maximum timer resolution.Requested Period
Request CountuA program or service has requested a timer resolution equal to or greater than the platform maximum timer resolution.Timer Request StackWThe stack of modules responsible for the lowest platform timer setting in this process.Calling ModulePower PolicyActive Power PlanThe current power plan in use	Plan GUID#Power Plan Personality (On Battery)NThe personality of the current power plan when the system is on battery power.Personality7Power Plan Personality is High Performance (On Battery)[The current power plan personality is High Performance when the system is on battery power.%Display timeout disabled (On Battery)GThe display is not configured to turn off after a period of inactivity.$Display timeout is long (On Battery)BThe display is configured to turn off after longer than 5 minutes.Timeout (seconds)$Dim timeout is disabled (On Battery)PThe display is not configured to automatically dim after a period of inactivity. Dim timeout is long (On Battery)KThe display is configured to automatically dim after longer than 5 minutes.Timeout (seconds)"Disk idle is disabled (On Battery)IThe disk is not configured to turn off after a period of disk inactivity.!Disk timeout is long (On Battery)@The disk is configured to turn off after longer than 30 minutes.Timeout (seconds)&Sleep timeout is disabled (On Battery)SThe computer is not configured to automatically sleep after a period of inactivity."Sleep timeout is long (On Battery)OThe computer is configured to automatically sleep after longer than 30 minutes.Timeout (seconds)8Minimum processor performance state is 100% (On Battery)\The processor is not configured to automatically reduce power consumption based on activity.8Minimum processor performance state is high (On Battery)`The lowest processor performance state is greater than 75% of the maximum processor performance.4Minimum performance state (% of maximum performance)/Processor idle states are disabled (On Battery)[The current processor power management policy has disabled low-power processor idle states..USB Selective Suspend is disabled (On Battery)EThe current power policy has globally disabled USB selective suspend.=802.11 Radio Power Policy is Maximum Performance (On Battery)rThe current power policy for 802.11-compatible wireless network adapters is not configured to use low-power modes.)PCI Express ASPM is disabled (On Battery)cThe current power policy for PCI Express Active State Power Management (ASPM) is configured to Off.#Power Plan Personality (Plugged In)HThe personality of the current power plan when the system is plugged in.7Power Plan Personality is High Performance (Plugged In)UThe current power plan personality is High Performance when the system is plugged in.%Display timeout disabled (Plugged In)GThe display is not configured to turn off after a period of inactivity.$Display timeout is long (Plugged In)CThe display is configured to turn off after longer than 10 minutes.$Dim timeout is disabled (Plugged In)PThe display is not configured to automatically dim after a period of inactivity. Dim timeout is long (Plugged In)LThe display is configured to automatically dim after longer than 10 minutes."Disk idle is disabled (Plugged In)IThe disk is not configured to turn off after a period of disk inactivity.PA!Disk timeout is long (Plugged In)@The disk is configured to turn off after longer than 30 minutes.&Sleep timeout is disabled (Plugged In)SThe computer is not configured to automatically sleep after a period of inactivity."Sleep timeout is long (Plugged In)OThe computer is configured to automatically sleep after longer than 30 minutes.8Minimum processor performance state is 100% (Plugged In)\The processor is not configured to automatically reduce power consumption based on activity.8Minimum processor performance state is high (Plugged In)`The lowest processor performance state is greater than 75% of the maximum processor performance./Processor idle states are disabled (Plugged In)[The current processor power management policy has disabled low-power processor idle states..USB Selective Suspend is disabled (Plugged In)EThe current power policy has globally disabled USB selective suspend.=802.11 Radio Power Policy is Maximum Performance (Plugged In)rThe current power policy for 802.11-compatible wireless network adapters is not configured to use low-power modes.)PCI Express ASPM is disabled (Plugged In)cThe current power policy for PCI Express Active State Power Management (ASPM) is configured to Off.Video Quality (On Battery)YEnables Windows Media Player to optimize for quality or power savings when playing video.Quality ModeVideo quality (Plugged In)YEnables Windows Media Player to optimize for quality or power savings when playing video.PASystem Availability RequestsSystem Required RequestWThe program has made a request to prevent the system from automatically entering sleep.Requesting ProcessSystem Required RequestWThe service has made a request to prevent the system from automatically entering sleep.Requesting ServiceSystem Required Request`The device or driver has made a request to prevent the system from automatically entering sleep.Requesting Driver InstanceRequesting Driver DevicePASystem Required Request^A kernel component has made a request to prevent the system from automatically entering sleep.Display Required RequestcThe program has made a request to prevent the display from automatically entering a low-power mode.Away Mode Request3The program has made a request to enable Away Mode.Away Mode Request3The service has made a request to enable Away Mode.Execution Required Request6The program has made a request for execution-required.Execution Required Request6The service has made a request for execution-required.USB Suspend)USB Device not Entering Selective Suspend�This device did not enter the USB Selective Suspend state.  Processor power management may be prevented when this USB device is not in the Selective Suspend state.  Note that this issue will not prevent the system from sleeping.Host Controller IDHost Controller Location	Device ID	Port Path,USB Device Rarely Entering Selective Suspend�This device intermittently entered the USB Selective Suspend state during the trace.  Processor power management may be prevented when this USB device is not in the Selective Suspend state.  Note that this issue will not prevent the system from sleeping.Time Suspended (%)Reason\This Bluetooth USB device does not support selective suspend because it is not self powered.cThis Bluetooth USB device does not support selective suspend because it is not remote wake capable.PACPU UtilizationProcessor utilization is low�The average processor utilization during the trace was very low.  The system will consume less power when the average processor utilization is very low.PAAverage Utilization (%)!Processor utilization is moderate0The average processor utilization during the trace was moderate.  The system will consume less power when the average processor utilization is very low.  Review processor utilization for individual processes to determine which applications and services contribute the most to total processor utilization.Processor utilization is high,The average processor utilization during the trace was high.  The system will consume less power when the average processor utilization is very low.  Review processor utilization for individual processes to determine which applications and services contribute the most to total processor utilization.:Individual process with significant processor utilization.sThis process is responsible for a significant portion of the total processor utilization recorded during the trace.Process NamePIDAverage Utilization (%)ModuleAverage Module Utilization (%)BatteryBattery Information
Battery IDManufacturerManufacture Date
Serial Number	Chemistry	Long TermCycle CountDesign CapacityLast Full ChargeLast Full Charge (%)fThe battery stored less than 50% of the Designed Capacity the last time the battery was fully charged.Last Full Charge (%)PALast Full Charge (%)fThe battery stored less than 40% of the Designed Capacity the last time the battery was fully charged.Battery Capacity Unknown[The battery capacity could not be determined.  This may indicate a firmware (BIOS) problem.SealedPA&Platform Power Management CapabilitiesSupported Sleep StatesPSleep states allow the computer to enter low-power modes after a period of inactivity.  The S3 sleep state is the default sleep state for Windows platforms.  The S3 sleep state consumes only enough power to preserve memory contents and allow the computer to resume working quickly.  Very few platforms support the S1 or S2 Sleep states.S1 Sleep SupportedS2 Sleep SupportedS3 Sleep SupportedS4 Sleep SupportedkThe S1 sleep state has been disabled because of a known incompatibility with the hardware in this computer.�Windows automatically disables sleep on some computers with hardware which is not compatible with sleep.  Installing the latest firmware (BIOS) may resolve this issue.kThe S2 sleep state has been disabled because of a known incompatibility with the hardware in this computer.�Windows automatically disables sleep on some computers with hardware which is not compatible with sleep.  Installing the latest firmware (BIOS) may resolve this issue.kThe S3 sleep state has been disabled because of a known incompatibility with the hardware in this computer.�Windows automatically disables sleep on some computers with hardware which is not compatible with sleep.  Installing the latest firmware (BIOS) may resolve this issue.+System firmware (BIOS) does not support S3.BThe hardware in this computer does not support the S3 sleep state.7System firmware (BIOS) does not support S4 (Hibernate).HThe hardware in this computer does not support the S4 (Hibernate) state.kThe S3 sleep state has been disabled because of a known incompatibility with the hardware in this computer.�Windows automatically disables sleep on some computers with hardware which is not compatible with sleep.  Installing the latest firmware (BIOS) may resolve this issue."Sleep is disabled in power policy.;The system administrator has disabled sleep on this system.PALHibernate has been disabled because the system has too much physical memory.UHibernate has been disabled because of an unknown problem with the storage subsystem.\Hibernate has been disabled because the Hibernation file could not be generated or accessed.7Sleep is disabled because a legacy driver is installed.�Sleep requires all device drivers to be compatible with Plug-and-Play and Power Management.  If a legacy driver is installed, sleep is automatically disabled.Driver NameGThe S1 sleep state has been temporarily disabled by a system component.jThe computer may not transition to sleep when the following components are installed or tasks are ongoing.?Microsoft Basic Display Driver or Microsoft Basic Render Driver
Hypervisor9The system is booted from a virtual hard disk file (VHD).GThe S2 sleep state has been temporarily disabled by a system component.jThe computer may not transition to sleep when the following components are installed or tasks are ongoing.PAGThe S3 sleep state has been temporarily disabled by a system component.jThe computer may not transition to sleep when the following components are installed or tasks are ongoing.MThe S4 (Hibernate) state has been temporarily disabled by a system component.jThe computer may not transition to sleep when the following components are installed or tasks are ongoing.)Adaptive Display Brightness is supported.`This computer enables Windows to automatically control the brightness of the integrated display.#Adaptive Display Brightness Support�This computer does not allow Windows to automatically control the brightness of the integrated display.  Installing the latest system firmware (BIOS) may resolve this issue.'Processor Power Management CapabilitiesvEffective processor power management enables the computer to automatically balance performance and energy consumption.GroupIndexIdle (C) State CountPerformance (P) State CountThrottle (T) State CountACPI C2 State Failed Validation�There is a problem with the definition of the C2 idle state on this computer.  Installing the latest system firmware (BIOS) may resolve this issue.ACPI C3 Failed Validation�There is a problem with the definition of the C3 idle state on this computer.  Installing the latest system firmware (BIOS) may resolve this issue.&ACPI Throttle States Failed Validation�There is a problem with the definition of throttle states on this computer.  Installing the latest system firmware (BIOS) may resolve this issue."ACPI _CST Object Failed Validation�There is a problem with the definition of the ACPI _CST object on this computer.  Installing the latest system firmware (BIOS) may resolve this issue."ACPI _CSD Object Failed Validation�There is a problem with the definition of the ACPI _CSD object on this computer.  Installing the latest system firmware (BIOS) may resolve this issue."ACPI _PCT Object Failed Validation�There is a problem with the definition of the ACPI _PCT object on this computer.  Installing the latest system firmware (BIOS) may resolve this issue."ACPI _PSS Object Failed Validation�There is a problem with the definition of the ACPI _PSS object on this computer.  Installing the latest system firmware (BIOS) may resolve this issue."ACPI XPSS Object Failed Validation�There is a problem with the definition of the ACPI XPSS object on this computer.  Installing the latest system firmware (BIOS) may resolve this issue."ACPI _PPC Object Failed Validation�There is a problem with the definition of the ACPI _PPC object on this computer.  Installing the latest system firmware (BIOS) may resolve this issue."ACPI _PSD Object Failed Validation�There is a problem with the definition of the ACPI _PSD object on this computer.  Installing the latest system firmware (BIOS) may resolve this issue."ACPI _PTC Object Failed Validation�There is a problem with the definition of the ACPI _PTC object on this computer.  Installing the latest system firmware (BIOS) may resolve this issue."ACPI _TSS Object Failed Validation�There is a problem with the definition of the ACPI _TSS object on this computer.  Installing the latest system firmware (BIOS) may resolve this issue."ACPI _TPC Object Failed Validation�There is a problem with the definition of the ACPI _TPC object on this computer.  Installing the latest system firmware (BIOS) may resolve this issue."ACPI _TSD Object Failed Validation�There is a problem with the definition of the ACPI _TSD object on this computer.  Installing the latest system firmware (BIOS) may resolve this issue.2Processor Idle State Domain Member Count Incorrect�There is a problem with the number of processors defined as members of a processor idle domain.  Installing the latest system firmware (BIOS) may resolve this issue.	Domain IDExpected Member CountActual Member CountEProcessor Performance or Throttle State Domain Member Count Incorrect�There is a problem with the number of processors defined as members of a processor performance or throttle state domain.  Installing the latest system firmware (BIOS) may resolve this issue.Processor Idle States Disabled�Processor idle states have been automatically disabled due to a known incompatibility with the hardware in this computer.  Installing the latest system firmware (BIOS) may resolve this issue.%Processor Performance States Disabled�Processor performance states have been automatically disabled due to a known incompatibility with the hardware in this computer.  Installing the latest system firmware (BIOS) may resolve this issue."Processor Throttle States Disabled�Processor throttle states have been automatically disabled due to a known incompatibility with the hardware in this computer.  Installing the latest system firmware (BIOS) may resolve this issue.9PCI Express Active-State Power Management (ASPM) Disabled�PCI Express Active-State Power Management (ASPM) has been disabled due to a known incompatibility with the hardware in this computer.5Wireless access point does not support WMM Power Save�The wireless access point the computer is connected to does not support WMM Power Save Mode. The wireless network adapter cannot enter Power Save mode to save energy as defined in Wireless Adapter Power Policy.SSIDMAC AddressConnected Standby Support�Connected standby allows the computer to enter a low-power mode in which it is always on and connected. If supported, connected standby is used instead of system sleep states.Connected Standby Supported"ACPI PCCP Object Failed Validation�There is a problem with the definition of the ACPI PCCP object on this computer.  Installing the latest system firmware (BIOS) may resolve this issue."ACPI _CPC Object Failed Validation�There is a problem with the definition of the ACPI _CPC object on this computer.  Installing the latest system firmware (BIOS) may resolve this issue.Idle State CountIdle State TypeNominal Frequency (MHz)Maximum Performance PercentageLowest Performance PercentageLowest Throttle PercentagePerformance Controls TypeNone*ACPI Performance (P) / Throttle (T) StatesPlatform Clocking Control0ACPI Collaborative Processor Performance ControlPower Engine PluginACPI Idle (C) States
Windows To GoBConnected Standby has been disabled due to non-compliant hardware.�This computer has indicated support for Connected Standby however one or more hardware components fails to comply with the requirements for this state. The following component(s) do not fulfill these requirements:Storage HardwareWireless Network AdapterMobile Broadband HardwareAudio Hardware	Compliant
Not CompliantMicro Power Engine PluginMHibernate has been disabled because the hardware is not capable to hibernate.NHibernate has been disabled because lack of resource for BOOT virtual address.KHibernate has been disabled because lack of resource for hibernate context.QHibernate has been disabled because lack of resource for hibernate preallocation.Device DriversMDevices with missing or misconfigured drivers can increase power consumption.PADevice Name	Device ID
Device StatusDevice Problem CodeUnknown DeviceSleep StudyWNote: This report does not contain information for the first Connected Standby session. The first Connected Standby session started in an earlier time frame. If interested in the earlier time frame, use &lt;code&gt;powercfg sleepstudy -duration DURATION&lt;/code&gt;. For example, to analyze the past 10 days:&lt;br /&gt;&lt;pre&gt;powercfg sleepstudy -duration 10&lt;/pre&gt;$Analysis errors found for Activators$Analysis errors found for Fx Devices$Analysis errors found for PDC phasesGThe sum of the durations of PDC phases is greater than the CS duration.PASystem Event LogDevice NamePAPP Information

�4VS_VERSION_INFO��
|O
|O?�StringFileInfo�040904B0LCompanyNameMicrosoft CorporationbFileDescriptionPower Efficiency Diagnosticsh$FileVersion10.0.20348.1 (WinBuild.160101.0800)6InternalNameenergy.dll�.LegalCopyright� Microsoft Corporation. All rights reserved.FOriginalFilenameenergy.dll.muij%ProductNameMicrosoft� Windows� Operating System>
ProductVersion10.0.20348.1DVarFileInfo$Translation	�<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:ms="urn:schemas-microsoft-com:xslt" xmlns:slp="http://schemas.microsoft.com/sleepstudy/2012" xmlns:js="http://microsoft.com/kernel">
    <head>
        <title>System Power Report</title>
        
        <!--These includes are inlined/replaced in the local report by the local SPR generator.-->
        <style type="text/css">
            /*__SPR_CSS__*/
        </style>
        <script>
            /*__SPR_JS__*/
        </script>
        <script>
            /*__SPR_DATA_LOADER__*/
        </script>
    </head>
    <body>
        <!--This div is inlined with the content of sleepstudy-report-template.html-->
        <div id="spr-template" hidden>
            <!--__SPR_TEMPLATE__-->
        </div>

        <div id="spr-header" class="spr-header">
            <h1 class="spr-h1">System Power Report</h1>
        </div>

        <!--This div is replaced with the generated output.-->
        <div id="spr-content"></div>
    </body>
</html>
.spr-header {
    letter-spacing: 0.02em;
    color: #000000;
    background-color: #ffffff;
    margin: 0em 5.5em 0em 5.5em;
}

.spr-content {
    letter-spacing: 0.02em;
    color: #000000;
    background-color: #ffffff;
    margin: 0em 5.5em 0em 5.5em;
}

.spr-header, .spr-content {
    font-family: "Segoe UI", "Segoe UI Web", "Segoe UI Symbol", "Helvetica Neue", "BBAlpha Sans", "S60 Sans", Arial, sans-serif;
}

.spr-h1 {
    font-size: 42pt;
    color: #0078D6;
}

.spr-h2 {
    font-size: 15pt;
    color: #0078D6;
    margin-top: 2em;
    margin-bottom: 0em;
    letter-spacing: 0.08em;
}

.spr-h3 {
    font-size: 14pt;
}

.spr-h4 {
    font-size: 12pt;
}

.spr-h3, .spr-h4, .spr-h5 {
    margin-top: 1em;
    margin-bottom: 0em;
    letter-spacing: 0.08em;
}

.spr-h1, .spr-h2, .spr-h3, .spr-h4, .spr-h5 {
    padding: 0px;
    font-weight: 400;
    line-height: normal;
}

.spr-blank {
    background-color: #ffffff;
}

.spr-centered {
    text-align: center;
}

.spr-date {
    display: inline-block;
    width: 5.5em;
}

.spr-download-container {
    margin: 1em 0;
}

.spr-explanation {
    font-size: 10pt;
    color: #000000;
    margin-bottom: 1em;
}

.spr-label {
    font-family: 'Segoe UI Semibold';
    font-size: 85%;
    color: #000000;
}

.spr-content input[type="radio"] + label {
    margin: 3px 6px 3px 3px;
}

.spr-label-details {
    text-indent: 40px;
    font-size: 85%;
    color: #000000;
}

.spr-symbol {
    font-family: 'Segoe UI Symbol';
}

.spr-table {
    border-width: 0;
    table-layout: fixed;
    letter-spacing: 0.02em;
    color: #000000;
    margin-bottom: 10px;
}

.spr-table-defs {
    background-color: transparent;
}

.spr-content thead {
    font-family: 'Segoe UI Semibold';
    font-size: 85%;
}

.spr-time {
    text-align: right;
    width: 4.2em;
    display: inline-block;
}

.graphline-none, .graphline-dotted, .graphline-solid, .graphline-neutral,
.graphline-low, .graphline-moderate, .graphline-high .graphline-nonclean {
    font-weight: bold;
}

.graphline-none { color: #000000; }

.graphline-dotted { color: #000000; }

.graphline-solid { color: #000000; }

.graphline-neutral { color: #000000; }

.graphline-low { color: #2a7a2a; }

.graphline-moderate { color: #a26609; }

.graphline-high { color: #970d00; }

.graphline-nonclean { color: #a72aa7;}

.top-blocker td, #summary-table td {
    padding: 0;
}

.top-blocker td a, #summary-table td a {
    padding: 0 0.3em 0 0.3em;
    display: block;
    height: 100%;
}

.top-blocker a:link, .top-blocker a:active, .top-blocker a:visited,
#summary-table a:link, #summary-table a:active, #summary-table a:visited {
    text-decoration: none;
    color: #000000;
}

#summary-table th,
.session-summary th,
.top-blocker th,
.pdc-phases th,
.device-components th {
    background-color: transparent;
}

#summary-table tbody tr,
.session-summary tbody tr,
.top-blocker tbody tr,
.device-components tbody tr,
.pdc-phases tbody tr {
    background-color: #e0e0e0;
}

#summary-table .row-neutral,
.session-summary .row-neutral,
.top-blocker .row-neutral,
.device-components .row-neutral,
.pdc-phases .row-neutral {
    background-color: #e0e0e0;
}

#summary-table .row-low,
.session-summary .row-low,
.top-blocker .row-low,
.device-components .row-low,
.pdc-phases .row-low {
    background-color: #ace3ac;
}

#summary-table .row-moderate,
.session-summary .row-moderate,
.top-blocker .row-moderate,
.device-components .row-moderate,
.pdc-phases .row-moderate {
    background-color: #fcd69a;
}

#summary-table .row-high,
.session-summary .row-high,
.top-blocker .row-high,
.device-components .row-high,
.pdc-phases .row-high {
    background-color: #ffb2aa;
}

#summary-table .row-info,
.session-summary .row-info,
.top-blocker .row-info,
.device-components .row-info,
.pdc-phases .row-info {
    background-color: #86becb;
}

#summary-table .row-nonclean,
.session-summary .row-nonclean,
.top-blocker .row-nonclean,
.device-components .row-nonclean,
.pdc-phases .row-nonclean {
    background-color: #EE82EE;
}

#summary-table tbody tr:hover,
.top-blocker tbody tr:hover {
    background-color: #f0f0f0;
}

#summary-table .row-neutral:hover,
.top-blocker .row-neutral:hover {
    background-color: #f0f0f0;
}

#summary-table .row-low:hover,
.top-blocker .row-low:hover {
    background-color: #caedca;
}

#summary-table .row-moderate:hover,
.top-blocker .row-moderate:hover {
    background-color: #fde5c0;
}

#summary-table .row-high:hover,
.top-blocker .row-high:hover {
    background-color: #ffd5d1;
}

#summary-table .row-nonclean:hover,
.top-blocker .row-nonclean:hover {
    background-color:#D8BFD8;
}

div.analysis-container {
    margin-bottom: 10px;
    border: 1px solid #ffffff;
}

div.analysis-container h1 {
    padding: 10px;
    font-size: 14px;
    margin: 0px;
    cursor: pointer;
}

div.analysis-body, div.analysis-body-collapsed {
    padding: 10px;
}

div.analysis-body { display: block; }

div.analysis-body-collapsed { display: none; }

.analysis-base {
    background-color: #f7f7f7;
}

.analysis-base h1 {
    color: #000000;
    background-color: #d0d0d0;
}

.analysis-base h1:hover {
    background-color: #dfdfdf;
}

.analysis-neutral {
    background-color: #f0f0f0;
}

.analysis-neutral h1 {
    color: #000000;
    background-color: #d0d0d0;
}

.analysis-neutral h1:hover {
    background-color: #dfdfdf;
}

.analysis-high {
    background-color: #ffd5d1;
}

.analysis-high h1 {
    color: #000000;
    background-color: #ff8e83;
}

.analysis-high h1:hover {
    background-color: #ffb2aa;
}

.analysis-moderate {
    background-color: #fde5c0;
}

.analysis-moderate h1 {
    color: #000000;
    background-color: #fbc674;
}

.analysis-moderate h1:hover {
    background-color: #fcd69a;
}

.analysis-low {
    background-color: #caedca;
}

.analysis-low h1 {
    color: #000000;
    background-color: #8fd98f;
}

.analysis-low h1:hover {
    background-color: #ace3ac;
}

.analysis-info {
    background-color: #b2e5e5;
}

.analysis-info h1 {
    color: #000000;
    background-color: rgba(26,163, 163, 0.5);
}

.analysis-info h1:hover {
    background-color: #86becb;
}

.analysis-empty {
    color: #a0a0a0;
    font-size: 14px;
    padding: 10px;
    font-weight: bold;
}

.expander {
    font-family: "Consolas";
    font-weight: bold;
}

.scroll-top-button {
    border: 1px solid #cdced0;
    background-color: #ffffff;
    padding: 5px 5px 6px 5px;
    font-size: 12px;
    float: left;
    border-radius: 100px;
    margin-left: -60px;
    margin-top: 2px; 
}

.scroll-top-button:hover {
    background-color: #f0f0f0;
    cursor: pointer;
}

#legend {
    background-color: #fafafa;
    margin-bottom: 2.2em;
    border-spacing: 0;
}

#legend .spr-caption {
    padding: 5px 0px 5px 0px;
    font-weight: bold;
}

#legend thead {
    background-color: #dfdfdf;
}

#legend td, #legend th {
    padding: 4px 5px 4px 5px;
}

#legend .spanner {
    text-align: center;
    background-color: #dfdfdf;
    font-size: 85%;
    font-weight: bold;
    padding: 3px;
}

#legend td.percent {
    text-align: left;
}
PADwindow.onload = function() {
    var LocalSprData = '__LOCAL_SPR_DATA__';
    var SourceElement = document.getElementById("spr-template");
    var DestinationElement = document.getElementById("spr-content");
    SourceElement.parentNode.removeChild(SourceElement);
    DOMBuilder.ProcessDocument(document, SourceElement, DestinationElement, LocalSprData);
};<!--This file is included in both the locally generated report and the WDP report-->
<div class="spr-content">
    <div id="spr-metadata" hidden>
        <span>Report Version: V3</span>
    </div>
    <div data-ignore>
        <div data-define-template="metadata-container-template">
            <div class="analysis-container analysis-info" data-if="($Scope.Entries.length !== 0) || ($Scope.Children.length !== 0)">
                <h1 class="spr-h1" onclick="Collapser.TogglePanel(this)"><span class="expander">+ </span>${$Scope.FriendlyName}</h1>
                <div class="analysis-body-collapsed">
                    <table class="spr-table" data-if="$Scope.Entries.length !== 0">
                        <tbody>
                            <tr class="row-info" data-foreach="$Scope.Entries">
                                <td class="spr-label">${$Scope.Name}</td>
                                <td style="width: 3em"> </td>
                                <td class="spr-centered" data-bind="$Scope.Value"></td>
                            </tr>
                        </tbody>
                    </table>
                    <div data-foreach="$Scope.Children" data-apply-template="metadata-container-template"></div>
                </div>
            </div>
        </div>
        <div data-define-template="session-entry-template"
             class="row-${ACTIVITY_LEVEL_NAMES[$Scope.ActivityLevel]}"
             data-override-type="tr"
             data-post-process="SummaryTableBuilder.PostProcessSessionRow($Node, $Scope)">

            <!-- Session ID -->
            <div class="spr-centered" data-override-type="td">${$Scope.SessionId}</div>
            <!-- Entry Time -->
            <div class="spr-symbol" data-override-type="td">
                <span class="spr-date">${SummaryTableBuilder.SelectDate($Scope.EntryTimestampLocal)}</span>
                <span class="spr-time">${SummaryTableBuilder.SelectTime($Scope.EntryTimestampLocal)}</span>
            </div>
            <div data-apply-template="session-entry-detailed-template"></div>
            <div class="spr-blank" data-override-type="td"></div>
        </div>
        <div data-define-template="session-entry-detailed-template" data-collapse>
            <!-- Session Duration -->
            <div class="spr-symbol spr-centered" data-override-type="td">${Formatter.FormatDuration($Scope.Duration)}</div>
            <!-- Session Type -->
            <div class="spr-centered" data-override-type="td">${SESSION_TYPE_NAMES[$Scope.Type]}</div>
            <div data-scope="Utils.GetSessionBatteryInformation($Scope)" data-collapse>
                <!-- Session Energy Change -->
                <div data-collapse>
                    <div data-if="$Scope.HasDischargeInformation" data-collapse>
                        <div class="spr-symbol spr-centered" data-override-type="td">${Formatter.FormatNumber($Scope.Discharge)} mWh</div>
                        <div class="spr-symbol spr-centered" data-override-type="td">${Formatter.FormatNumber($Scope.DischargePercent)}% of battery</div>
                    </div>
                    <div data-else data-collapse>
                        <div class="spr-centered" data-override-type="td">-</div>
                        <div class="spr-centered" data-override-type="td">-</div>
                    </div>
                </div>
                <!-- Session Change Rate -->
                <div data-collapse>
                    <div data-if="$Scope.HasDrainRate" data-collapse>
                        <div class="spr-symbol spr-centered" data-override-type="td">${Formatter.FormatNumber($Scope.DrainRate)} mW</div>
                    </div>
                    <div data-else data-collapse>
                        <div class="spr-centered" data-override-type="td">-</div>
                    </div>
                </div>
            </div>
            <div class="spr-centered" data-override-type="td">${$Scope.OnAc ? 'Charge' : 'Drain'}</div>
            <!-- Session Low Power State Time-->
            <div data-scope="{
                                Duration: $Scope.Duration,
                                Sw: MetadataUtils.GetMetadataValue($Scope.Metadata,
                                                                   'Info.SwLowPowerStateTime'),
                                Hw: MetadataUtils.GetMetadataValue($Scope.Metadata,
                                                                   'Info.HwLowPowerStateTime')
                             }"
                 data-collapse>
                <div data-if="($Scope.Sw !== undefined) && ($Scope.Hw !== undefined)" data-collapse>
                    <div class="spr-centered" data-override-type="td">SW: ${Math.round(100 * $Scope.Sw / $Scope.Duration / 10)}%</div>
                    <div data-collapse>
                        <div class="spr-centered" data-if="$Scope.Sw === 0 || $Scope.Hw === undefined" data-override-type="td">-</div>
                        <div class="spr-centered" data-else data-override-type="td">HW: ${Math.round(100 * $Scope.Hw / $Scope.Duration / 10)}%</div>
                    </div>
                </div>
                <div data-else data-collapse>
                    <div class="spr-centered" data-override-type="td" colspan="2">-</div>
                </div>
            </div>
            <!-- Session Battery Capacity At Start -->
            <div class="spr-symbol spr-centered" data-override-type="td">${Formatter.FormatSessionEnterBatteryPercent($Scope)}</div>
        </div>
        <div data-define-template="top-offender-entry-template"
             class="row-${ACTIVITY_LEVEL_NAMES[$Scope.ActivityLevel]}"
             data-override-type="tr"
             data-post-process="DOMBuilder.InsertTableRowLinks($Node, `#offender-${$Scope.ScenarioId}-${$Scope.BlockerId}`)">


            <div data-override-type="td">${$Scope.Name}</div>
            <div data-override-type="td" class=spr-centered>${BLOCKER_TYPE_NAMES[$Scope.Type]}</div>
            <div data-override-type="td" class="spr-symbol spr-centered">${$Scope.ActiveTimePercent}%</div>
            <div data-override-type="td" class=spr-centered>${Formatter.FormatDuration($Scope.ActiveTime)}</div>
        </div>
        <div data-define-template="session-blocker-template">
            <div class="analysis-container analysis-${ACTIVITY_LEVEL_NAMES[$Scope.ActivityLevel]}" id="offender-${$Scope.ScenarioId}-${$Scope.BlockerId}">
                <h1 class="spr-h1" onclick="Collapser.TogglePanel(this)"><span class="expander">+ </span>${$Scope.Name}</h1>
                <div class="analysis-body-collapsed">
                    <table class="spr-table spr-table-defs">
                        <thead>
                            <th class="spr-label">% ACTIVE TIME</th>
                            <th class="spr-label">ACTIVE TIME</th>
                        </thead>
                        <tbody>
                            <tr>
                                <td class="spr-symbol spr-centered">${$Scope.ActiveTimePercent}%</td>
                                <td class=spr-centered>${Formatter.FormatDuration($Scope.ActiveTime)}</td>
                            </tr>
                        </tbody>
                    </table>
                    <div data-if="$Scope.Children !== 0">
                        <div data-foreach="$Scope.Children" data-apply-template="session-blocker-template"></div>
                    </div>
                    <div data-scope="MetadataUtils.ParseMetadataTree($Scope.Metadata)"
                         data-apply-template="metadata-container-template">
                    </div>
                </div>
            </div>
        </div>

        <!-- Generic session templates-->
        <div data-define-template="session-generic-header-template">
            <table class="spr-table session-summary">
                <colgroup>
                    <col style="width: 2em"/>
                    <col style="width: 11em;"/>
                    <col style="width: 5em;"/>
                    <col style="width: 10em"/>
                    <col style="width: 16em"/>
                    <col style="width: 16em"/>
                    <col style="width: 6em;"/>
                </colgroup>
                <thead>
                    <tr>
                        <th></th>
                        <th>START TIME</th>
                        <th>DURATION</th>
                        <th>STATE</th>
                        <th>ENTRY REASON</th>
                        <th>EXIT REASON</th>
                        <th>% CAPACITY REMAINING AT START</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    <tr class="row-${ACTIVITY_LEVEL_NAMES[$Scope.ActivityLevel]}">
                        <td class="spr-centered">${$Scope.SessionId}</td>
                        <td class="spr-symbol">
                            <span class="spr-date">${Utils.ParseDateFromDateTime($Scope.EntryTimestampLocal)}</span>
                            <span class="spr-time">${Utils.ParseTimeFromDateTime($Scope.EntryTimestampLocal)}</span>
                        </td>
                        <td class="spr-symbol spr-centered">${Formatter.FormatDuration($Scope.Duration)}</td>
                        <td class="spr-centered">${SESSION_TYPE_NAMES[$Scope.Type]}</td>
                        <td class="spr-centered">${$Scope.EnterReason}</td>
                        <td class="spr-centered">${$Scope.ExitReason}</td>
                        <td class="spr-symbol spr-centered">${Formatter.FormatSessionEnterBatteryPercent($Scope)}</td>
                    </tr>
                </tbody>
            </table>
            <div data-scope="MetadataUtils.ParseMetadataTree($Scope.Metadata)"
                 data-apply-template="metadata-container-template">
            </div>
        </div>
        <div data-define-template="session-generic-srum-data-template">
            <h4 class="spr-h4">Srum Data</h4>
            <div class="spr-explanation">
            Data obtained from the SRUM database.
            * in Power Estimation means the power value is from energy meter.
            Otherwise, it is from software model estimation.
            </div>
            <div data-scope="$Scope.EnergyMeterData" class="analysis-container analysis-${$Scope.length == 0 ? 'neutral' : 'info'}">
                <h1 class="spr-h1" onclick="Collapser.TogglePanel(this)"><span class="expander">+ </span> Energy Meter</h1>
                <div class="analysis-body-collapsed">
                    <div data-if="$Scope.length == 0">
                        <div class="analysis-empty">No energy meter data obtained.</div>
                    </div>
                    <div data-else>
                        <table class="spr-table pdc-phases">
                            <thead>
                                <th>Power Rail</th>
                                <th>Energy (mJ)</th>
                                <th>Power (mW)</th>
                            </thead>
                            <tbody>
                                <tr data-foreach="SrumTableBuilder.SortEnergyEstimationRecords($Scope)" class="row-info">
                                    <td>${$Scope.RailId}</td>
                                    <td class=spr-centered>${$Scope.EnergyConsumption}</td>
                                    <td class=spr-centered>${$Scope.PowerConsumption}</td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
            <div data-scope="$Scope.PowerEstimationData" class="analysis-container analysis-${$Scope.Values.length == 0 ? 'neutral' : 'info'}">
                <h1 class="spr-h1" onclick="Collapser.TogglePanel(this)"><span class="expander">+ </span> Power Estimation</h1>
                <div class="analysis-body-collapsed">
                    <div data-if="$Scope.Values.length == 0">
                        <div class="analysis-empty">No power estimation data obtained.</div>
                    </div>
                    <div data-else>
                        <table class="spr-table pdc-phases">
                            <thead>
                                <th>APP ID</th>
                                <th>TOTAL (mW)</th>
                                <th>CPU (mW)${$Scope.CpuEnergyMeasured ? '*' : ''}</th>
                                <th>DISPLAY (mW)${$Scope.DisplayEnergyMeasured ? '*' : ''}</th>
                                <th>DISK (mW)${$Scope.DiskEnergyMeasured ? '*' : ''}</th>
                                <th>MBB (mW)${$Scope.MbbEnergyMeasured ? '*' : ''}</th>
                                <th>NETWORK (mW)${$Scope.NetworkEnergyMeasured ? '*' : ''}</th>
                                <th>SOC (mW)${$Scope.SocEnergyMeasured ? '*' : ''}</th>
                                <th>LOSS (mW)</th>
                                <th>OTHER (mW)</th>
                            </thead>
                            <tbody>
                                <tr data-foreach="SrumTableBuilder.SortPowerEstimationRecords($Scope.Values)" class="row-info">
                                    <td>${$Scope.AppId} [${$Scope.UserId}]</td>
                                    <td class=spr-centered>${$Scope.TotalPowerConsumption}</td>
                                    <td class=spr-centered>${$Scope.CpuPowerConsumption}</td>
                                    <td class=spr-centered>${$Scope.DisplayPowerConsumption}</td>
                                    <td class=spr-centered>${$Scope.DiskPowerConsumption}</td>
                                    <td class=spr-centered>${$Scope.MbbPowerConsumption}</td>
                                    <td class=spr-centered>${$Scope.NetworkPowerConsumption}</td>
                                    <td class=spr-centered>${$Scope.SocPowerConsumption}</td>
                                    <td class=spr-centered>${$Scope.LossPowerConsumption}</td>
                                    <td class=spr-centered>${$Scope.OtherPowerConsumption}</td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
        <div data-define-template="session-generic-template">
            <div data-scope="$Scope.SrumData"
                 data-if="typeof($Scope) !== 'undefined'"
                 data-apply-template="session-generic-srum-data-template">
            </div>
        </div>

        <!-- Active session templates -->
        <div data-define-template="session-active-template">
            <div data-apply-template="session-generic-header-template"></div>
            <div data-if="typeof($Scope.ScreenBrightnessHistogram) !== 'undefined'">
                <h4 class="spr-h4">Screen Brightness Duration Histogram</h4>
                <div class="spr-explanation">Duration in seconds at various screen brightness levels</div>
                <canvas width="864" height="300" data-histogram="$Scope.ScreenBrightnessHistogram"> </canvas>
            </div>
            <div data-if="typeof($Scope.LuxHistogram) !== 'undefined'">
                <h4 class="spr-h4">Lux Duration Histogram</h4>
                <div class="spr-explanation">Duration in seconds at various lux levels</div>
                <canvas width="864" height="300" data-histogram="$Scope.LuxHistogram"> </canvas>
            </div>
            <div data-scope="$Scope.SearchIndexerData" data-if="typeof($Scope) !== 'undefined' && $Scope.HasSearchIndexerData">
                <h4 class="spr-h4">Search Indexer Data</h4>
                <div data-if="$Scope.Query.length !== 0" class="analysis-container analysis-info">
                    <h1 class="spr-h1" onclick="Collapser.TogglePanel(this)"><span class="expander">+ </span>Query Events:</h1>
                    <div class="analysis-body-collapsed">
                        <table class="spr-table pdc-phases">
                            <thead>
                            <th>Max Cursors Used</th>
                            <th>Protocol Count</th>
                            <th>Protocol String</th>
                            </thead>
                            <tbody>
                                <tr data-foreach="$Scope.Query" class="row-info">
                                    <td class=spr-centered>${$Scope.MaxCursorsUsed}</td>
                                    <td class=spr-centered>${$Scope.ProtocolCount}</td>
                                    <td class=spr-centered>${$Scope.ProtocolString}</td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
                <div data-if="$Scope.Flush.length !== 0" class="analysis-container analysis-info">
                    <h1 class="spr-h1" onclick="Collapser.TogglePanel(this)"><span class="expander">+ </span>Flush Events:</h1>
                    <div class="analysis-body-collapsed">
                        <table class="spr-table pdc-phases">
                            <thead>
                                <th>Max Key Count</th>
                                <th>Max Documents</th>
                                <th>Max Word List</th>
                            </thead>
                            <tbody>
                                <tr data-foreach="$Scope.Flush" class="row-info">
                                    <td class=spr-centered>${$Scope.MaxKeyCount}</td>
                                    <td class=spr-centered>${$Scope.MaxDocuments}</td>
                                    <td class=spr-centered>${$Scope.MaxWordList}</td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
                <div data-if="$Scope.Merge.length !== 0" class="analysis-container analysis-info">
                    <h1 class="spr-h1" onclick="Collapser.TogglePanel(this)"><span class="expander">+ </span>Merge Events:</h1>
                    <div class="analysis-body-collapsed">
                        <table class="spr-table pdc-phases">
                            <thead>
                                <th>Pre-Merge Indice Count</th>
                                <th>Pre-Merge Level</th>
                                <th>Pre-Merge Min ID</th>
                                <th>Pre-Merge Max ID</th>
                                <th>Post-Merge Indice Count</th>
                                <th>Post-Merge Level</th>
                                <th>Post-Merge Min ID</th>
                                <th>Post-Merge Max ID</th>
                            </thead>
                            <tbody>
                                <tr data-foreach="$Scope.Merge" class="row-info">
                                    <td class=spr-centered>${$Scope.PreMergeIndiceCount}</td>
                                    <td class=spr-centered>${$Scope.PreMergeLevel}</td>
                                    <td class=spr-centered>${$Scope.PreMergeMinId}</td>
                                    <td class=spr-centered>${$Scope.PreMergeMaxId}</td>
                                    <td class=spr-centered>${$Scope.PostMergeIndiceCount}</td>
                                    <td class=spr-centered>${$Scope.PostMergeLevel}</td>
                                    <td class=spr-centered>${$Scope.PostMergeMinId}</td>
                                    <td class=spr-centered>${$Scope.PostMergeMaxId}</td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
                <div data-if="$Scope.FileSysChange.length !== 0" class="analysis-container analysis-info">
                    <h1 class="spr-h1" onclick="Collapser.TogglePanel(this)"><span class="expander">+ </span>Indexing File Events:</h1>
                    <div class="analysis-body-collapsed">
                        <table class="spr-table pdc-phases">
                            <thead>
                                <th>FAT Items Processed</th>
                                <th>NTFS Items Processed</th>
                            <tbody>
                                <tr data-foreach="$Scope.FileSysChange" class="row-info">
                                    <td class=spr-centered>${$Scope.TotalFATItemsProcessed}</td>
                                    <td class=spr-centered>${$Scope.TotalNTFSItemsProcessed}</td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
                <div data-if="$Scope.IndexingFile.length !== 0" class="analysis-container analysis-info">
                    <h1 class="spr-h1" onclick="Collapser.TogglePanel(this)"><span class="expander">+ </span>Indexing File Events:</h1>
                    <div class="analysis-body-collapsed">
                        <table class="spr-table pdc-phases">
                            <thead>
                                <th>IndexingFile Aggregation Data Metric</th>
                                <th>Content Type Count</th>
                                <th>Content Type String</th>
                            </thead>
                            <tbody>
                                <tr data-foreach="$Scope.IndexingFile" class="row-info">
                                    <td class=spr-centered>${$Scope.IndexingFileAggregationDataMetric}</td>
                                    <td class=spr-centered>${$Scope.DataTypeCount}</td>
                                    <td class=spr-centered>${$Scope.DataTypeString}</td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
                <div data-if="$Scope.QueryResults.length !== 0" class="analysis-container analysis-info">
                    <h1 class="spr-h1" onclick="Collapser.TogglePanel(this)"><span class="expander">+ </span>Query Results Events:</h1>
                    <div class="analysis-body-collapsed">
                        <table class="spr-table pdc-phases">
                            <thead>
                                <th>Results Requested</th>
                                <th>Results Returned</th>
                            </thead>
                            <tbody>
                                <tr data-foreach="$Scope.QueryResults" class="row-info">
                                    <td class=spr-centered>${$Scope.TotalResultsRequested}</td>
                                    <td class=spr-centered>${$Scope.TotalResultsReturned}</td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
            <div data-apply-template="session-generic-template"></div>
        </div>

        <!-- Sleep and Screen Off session templates -->
        <div data-define-template="session-modern-standby-header-template">
            <table class="spr-table session-summary">
                <colgroup>
                    <col style="width: 2em" />
                    <col style="width: 11em;" />
                    <col style="width: 5em;" />
                    <col style="width: 10em;" />
                    <col class="width: 13em;" />
                    <col class="width: 13em;" />
                    <col style="width: 6em;" />
                    <col style="width: 6em;" />
                    <col style="width: 6em;" />
                    <col style="width: 6em;" />
                    <col style="width: 6em;" />
                </colgroup>
                <thead>
                    <tr>
                        <th></th>
                        <th>START TIME</th>
                        <th>DURATION</th>
                        <th>STATE</th>
                        <th colspan="2">ENERGY CHANGE</th>
                        <th colspan="2">CHANGE RATE</th>
                        <th colspan="2">% LOW POWER STATE TIME</th>
                        <th>% CAPACITY REMAINING AT START</th>
                    </tr>
                </thead>
                <tbody>
                    <tr class="row-${ACTIVITY_LEVEL_NAMES[$Scope.ActivityLevel]}">
                        <td class="spr-centered">${$Scope.SessionId}</td>
                        <td class="spr-symbol">
                            <span class="spr-date">${Utils.ParseDateFromDateTime($Scope.EntryTimestampLocal)}</span>
                            <span class="spr-time">${Utils.ParseTimeFromDateTime($Scope.EntryTimestampLocal)}</span>
                        </td>
                        <td data-apply-template="session-entry-detailed-template"></td>
                    </tr>
                </tbody>
            </table>
            <div data-scope="MetadataUtils.ParseMetadataTree($Scope.Metadata)"
                 data-apply-template="metadata-container-template">
            </div>
        </div>
        <div data-define-template="session-modern-standby-template">
            <div data-if="!$Scope.HasTraceSessionData">
                <div data-apply-template="session-generic-header-template"></div>
                <div data-apply-template="session-generic-template"></div>
                <h4 class="spr-h4">This session contains no detailed information about top offenders.</h4>
            </div>
            <div data-else>
                <div data-apply-template="session-modern-standby-header-template"></div>
                <div data-if="typeof($Scope.DripsHistogram) !== 'undefined'">
                    <h4 class="spr-h4">DRIPS Histogram</h4>
                    <div class="spr-explanation">Percent of time spent in DRIPS bucketed by time interval length</div>
                    <canvas width="864"
                            height="300"
                            data-histogram="$Scope.DripsHistogram"
                            data-histogram-range-max="100">
                    </canvas>
                </div>
                <div data-if="typeof($Scope.DripsWakeSources) !== 'undefined'" data-collapse>
                    <div class="analysis-container analysis-${$Scope.DripsWakeSources.length == 0 ? 'neutral' : 'info'}">
                        <h1 class="spr-h1" onclick="Collapser.TogglePanel(this)">
                            <span class="expander">+ </span>DRIPS Wake Sources
                        </h1>
                        <div class="analysis-body-collapsed">
                            <div data-if="$Scope.DripsWakeSources.length == 0" class="analysis-empty">
                                No DRIPS wake source information obtained.
                            </div>
                            <table data-else class="spr-table pdc-phases">
                                <thead>
                                    <th>WAKE SOURCE</th>
                                    <th>WAKE TYPE</th>
                                    <th>COUNT</th>
                                </thead>
                                <tbody>
                                    <tr data-foreach="$Scope.DripsWakeSources" class="row-info">
                                        <td>${$Scope.ReasonDescription}</td>
                                        <td class="spr-centered">${$Scope.Type}</td>
                                        <td class="spr-centered">${$Scope.Count}</td>
                                    </tr>
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
                <h4 class="spr-h4">Top Offenders</h4>
                <div class="spr-explanation">Top 5 Offenders, ranked by active time</div>
                <table style="margin-bottom: 20px" class="spr-table top-blocker">
                    <colgroup>
                    <col/>
                    <col/>
                    <col/>
                    <col/>
                    </colgroup>
                    <thead>
                    <tr>
                        <th>NAME</th>
                        <th>TYPE</th>
                        <th>% ACTIVE TIME</th>
                        <th>ACTIVE TIME</th>
                    </tr>
                    </thead>
                    <tbody>
                        <tr data-foreach="$Scope.TopBlockers" data-apply-template="top-offender-entry-template"></tr>
                    </tbody>
                </table>
                <div class="analysis-container analysis-${Utils.GetBlockerGroupActivityLevel($Scope)}"
                     data-foreach="$Scope.BlockerGroups">
                    
                    <h1 class="spr-h1" onclick="Collapser.TogglePanel(this)"><span class="expander">+ </span>${$Scope.Name}</h1>
                    <div class="analysis-body-collapsed">
                        <div class="analysis-empty" data-if="$Scope.Blockers.length === 0">No ${$Scope.Name} activity reported</div>
                        <div data-if="$Scope.Blockers.length !== 0">
                            <div data-foreach="$Scope.Blockers" data-apply-template="session-blocker-template"></div>
                        </div>
                        <div data-scope="MetadataUtils.ParseMetadataTree($Scope.Metadata)"
                             data-apply-template="metadata-container-template">
                        </div>
                    </div>
                </div>
                <div data-apply-template="session-generic-template"></div>
            </div>
        </div>
    </div>

    <table class="spr-table spr-table-defs">
        <tr>
            <td class="spr-label">COMPUTER NAME</td>
			<td class="spr-blank"> </td>
            <td>${$Scope.SystemInformation.ComputerName}</td>
        </tr>
        <tr>
            <td class="spr-label">SYSTEM PRODUCT NAME</td>
			<td class="spr-blank"> </td>
            <td><span>${$Scope.SystemInformation.SystemManufacturer}</span> <span>${$Scope.SystemInformation.SystemProductName}</span></td>
        </tr>
        <tr>
            <td class="spr-label">BIOS</td>
			<td class="spr-blank"> </td>
            <td><span>${$Scope.SystemInformation.BIOSVersion}</span> <span>${$Scope.SystemInformation.BIOSDate}</span></td>
        </tr>
        <tr>
            <td class="spr-label">OS BUILD</td>
			<td class="spr-blank"> </td>
            <td>${$Scope.SystemInformation.OSBuild}</td>
        </tr>
        <tr>
            <td class="spr-label">MODERN STANDBY ENABLED</td>
			<td class="spr-blank"> </td>
            <td>${$Scope.SystemInformation.ConnectedStandby ? "Yes" : "No"}</td>
        </tr>
        <tr>
            <td class="spr-label">PLATFORM ROLE</td>
			<td class="spr-blank"> </td>
            <td>${$Scope.SystemInformation.PlatformRole}</td>
        </tr>
        <tr>
            <td class="spr-label">REPORT TIME</td>
			<td class="spr-blank"> </td>
            <td data-scope="$Scope.ReportInformation">
                <span>${Utils.ParseDateFromDateTime($Scope.ReportStartTimeLocal)}</span>
                <span>${Utils.ParseTimeFromDateTime($Scope.ReportStartTimeLocal)}</span>
            </td>
        </tr>
    </table>
    <div>
        <h2 class="spr-h2">System Power State Transitions</h2>
        <div class="spr-explanation">Battery drain over the last 3 days</div>
        <canvas width="864" height="400" data-post-process="Timegraph.Draw($Scope, $Node)"> </canvas>
        <table class="spr-table" id="legend">
            <colgroup>
            <col/>
            <col/>
            </colgroup>
            <caption class="spr-caption">Legend</caption>
            <thead>
            <th>GRAPH LINE</th>
            <th>DESCRIPTION</th>
            </thead>
            <tbody>
            <tr>
                <td><span class="graphline-dotted">Dotted</span></td>
                <td colspan="2">AC power </td>
            </tr>
            <tr>
                <td><span class="graphline-solid">Solid</span></td>
                <td colspan="2">Battery power</td>
            </tr>
            <tr>
                <td><span class="graphline-none">No line</span></td>
                <td colspan="2">System powered off</td>
            </tr>
            <tr>
                <td colspan="3" class="spanner"></td>
            </tr>
            <tr>
                <td><span class="graphline-neutral">Grey</span></td>
                <td colspan="2">Active Scenario</td>
            </tr>
            <tr>
                <td><span class="graphline-low">Green</span></td>
                <td>Low System Activity</td>
            </tr>
            <tr>
                <td><span class="graphline-moderate">Orange</span></td>
                <td>Moderate System Activity</td>
            </tr>
            <tr>
                <td><span class="graphline-high">Red</span></td>
                <td>High System Activity</td>
            </tr>
            <tr>
                <td><span class="graphline-nonclean">Violet</span></td>
                <td>Abnormal Shutdown</td>
            </tr>
            </tbody>
        </table>
    </div>
    <div>
        <h2 class="spr-h2">Filter Option</h2>
        <div>
            <h4 class="spr-h4">Session Length:</h4>
            <input type="radio" name="session_length_filter" id="is_all_time" value="AllTime" onchange="SummaryTableBuilder.OnDurationValueChanged(this)" checked=""><label for="is_all_time">All</label>
            <input type="radio" name="session_length_filter" id="is_10_session" value="10:00" onchange="SummaryTableBuilder.OnDurationValueChanged(this)"><label for="is_10_session">&gt;10:00</label>
        </div>
        <div>
            <h4 class="spr-h4">States:</h4>
            <input type="radio" name="session_type_filter" id="is_all_session" value="All" onchange="SummaryTableBuilder.OnStateValueChanged(this)" checked=""/><label for="is_all_session">All</label>
            <input type="radio" name="session_type_filter" id="is_active_session" value="Active" onchange="SummaryTableBuilder.OnStateValueChanged(this)"/><label for="is_active_session">Active</label>
            <input type="radio" name="session_type_filter" id="is_screenoff_session" value="ScreenOff" onchange="SummaryTableBuilder.OnStateValueChanged(this)"/><label for="is_screenoff_session">Screen Off </label>
            <input type="radio" name="session_type_filter" id="is_sleep_session" value="Standby" onchange="SummaryTableBuilder.OnStateValueChanged(this)"/><label for="is_sleep_session">Sleep</label>
            <input type="radio" name="session_type_filter" id="is_hib_session" value="Hibernate" onchange="SummaryTableBuilder.OnStateValueChanged(this)"/><label for="is_hib_session">Hibernate</label>
            <input type="radio" name="session_type_filter" id="is_shutdown_session" value="Shutdown" onchange="SummaryTableBuilder.OnStateValueChanged(this)"/><label for="is_shutdown_session">Shutdown</label>
            <input type="radio" name="session_type_filter" id="is_bug_session" value="BugCheck" onchange="SummaryTableBuilder.OnStateValueChanged(this)"/><label for="is_bug_session">Bug Check</label> 
        </div>
        <table class="spr-table" id="summary-table">
            <colgroup>
                <col style="width: 2em"/>
                <col style="width: 11em;"/>
                <col style="width: 5em;"/>
                <col style="width: 10em;"/>
                <col class="width: 13em;"/>
                <col class="width: 13em;"/>
                <col style="width: 6em;"/>
                <col style="width: 6em;"/>
                <col style="width: 6em;"/>
                <col style="width: 6em;"/>
                <col style="width: 6em;"/>
                <col style="width: 1em;"/>
            </colgroup>
            <thead>
                <tr>
                    <th></th>
                    <th>START TIME</th>
                    <th>DURATION</th>
                    <th>STATE</th>
                    <th colspan="2">ENERGY CHANGE</th>
                    <th colspan="2">CHANGE RATE</th>
                    <th colspan="2">% LOW POWER STATE TIME</th>
                    <th>% CAPACITY REMAINING AT START</th>
                </tr>
            </thead>
            <tbody>
                <tr data-foreach="$Scope.ScenarioInstances" data-apply-template="session-entry-template"></tr>
            </tbody>
        </table>
    </div>
    <h2 class="spr-h2">Analysis Results</h2>
    <div class="spr-explanation">Analysis of issues that might cause poor battery life</div>
    <div data-foreach="$Scope.ScenarioInstances" id="session-${$Scope.SessionId}">
        <div class="scroll-top-button" onclick="Utils.ScrollToTop()">Top</div>
        <h3 class="spr-h3">System Power State: ${SESSION_TYPE_NAMES[$Scope.Type]}</h3>
        <div data-if="$Scope.Type == 0" data-apply-template="session-active-template"></div>
        <div data-else-if="$Scope.Type == 1 || $Scope.Type == 2" data-apply-template="session-modern-standby-template"></div>
        <div data-else>
            <div data-apply-template="session-generic-header-template"></div>
            <div data-apply-template="session-generic-template"></div>
        </div>
    </div>
    <div data-scope="$Scope.Batteries.filter(function (Battery) { return Battery.LongTerm; })">
        <h2 class="spr-h2">Installed Batteries</h2>
        <div class="spr-explanation">Information about each currently installed battery</div>
        <div data-if="$Scope.length === 0">
            <div class="nobatts">No batteries are currently installed.</div>
        </div>
        <div data-else>
            <table class="spr-table spr-table-defs">
                <colgroup>
                    <col style="width: 15em">
                    <col style="width: 14em" data-foreach="$Scope">
                </colgroup>
                <thead>
                    <tr>
                        <td> </td>
                        <td data-foreach="[...Array($Scope.length).keys()]">BATTERY ${$Scope + 1}</td>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td><span class="spr-label">NAME</span></td>
                        <td data-foreach="$Scope">${$Scope.Id}</td>
                    </tr>
                    <tr>
                        <td><span class="spr-label">MANUFACTURER</span></td>
                        <td data-foreach="$Scope">${$Scope.Manufacturer}</td>
                    </tr>
                    <tr>
                        <td><span class="spr-label">SERIAL NUMBER</span></td>
                        <td data-foreach="$Scope">${$Scope.SerialNumber}</td>
                    </tr>
                    <tr>
                        <td><span class="spr-label">CHEMISTRY</span></td>
                        <td data-foreach="$Scope">${$Scope.Chemistry}</td>
                    </tr>
                    <tr>
                        <td><span class="spr-label">DESIGN CAPACITY</span></td>
                        <td data-foreach="$Scope">
                            <div data-if="$Scope.RelativeCapacity">-</div>
                            <div data-else>${$Scope.DesignCapacity}mWh</div>
                        </td>
                    </tr>
                    <tr>
                        <td><span class="spr-label">CAPACITY RATIO</span></td>
                        <td data-foreach="$Scope">${Math.round(100 * $Scope.FullChargeCapacity / $Scope.DesignCapacity)}</td>
                    </tr>
                    <tr>
                        <td><span class="spr-label">CYCLE COUNT</span></td>
                        <td data-foreach="$Scope">${$Scope.CycleCount}</td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>
</div>
PAD"use strict";

var SEC_TO_100NS = 10000000;
var SEC_TO_US = 1000000;
var HOUR_TO_100NS = (60 * 60 * SEC_TO_100NS);
var HOUR_TO_US = (60 * 60 * SEC_TO_US);
var ACTIVITY_LEVEL_NAMES = [
    'neutral',
    'low',
    'moderate',
    'high',
    'nonclean'
];

var BLOCKER_TYPE_NAMES = [
    'Activator',
    'Fx Device',
    'PDC Phase',
    'Reserved Type',
    'Processor',
    'Other',
    'PEP Pre-Veto',
    'SoC Subsystem'
];

var SESSION_TYPE_NAMES = [
    'Active',
    'Screen Off',
    'Sleep',
    'Standby',
    'Hybrid Sleep',
    'Hibernate',
    'Hybrid Shutdown',
    'Shutdown',
    'System Sleep Transition (Unknown Type)',
    'Abnormal Shutdown',
    'Bugcheck',
    'Report Generated'
];

//
// Default attributes for displaying session metadata.
//
// N.B. This is done to limit including this information in every session.
//

var DEFAULT_METADATA_ATTRIBUTES = {
    'Info.DirectedDripsTransitionCount': {
        Name: 'Directed DRIPS Transition Count'
    },
    'Info.EnterReason': {
        Name: 'Enter Reason'
    },
    'Info.ExitReason': {
        Name: 'Exit Reason'
    },
    'Info.HwLowPowerStateTime': {
        Visible: false
    },
    'Info.SwLowPowerStateTime': {
        Visible: false
    },
    'Info.SystemGpuAdapterCount': {
        Name: 'System GPU Adapter Count'
    },

    'Battery.EntryFullChargeCapacity': {
        Name: 'Full Charge Capacity At Entry [mWh]'
    },
    'Battery.EntryRemainingCapacity': {
        Name: 'Remaining Charge Capacity At Entry [mWh]'
    },
    'Battery.ExitFullChargeCapacity': {
        Name: 'Full Charge Capacity At Exit [mWh]'
    },
    'Battery.ExitRemainingCapacity': {
        Name: 'Remaining Charge Capacity At Exit [mWh]'
    },

    'Settings.ConnectedStandby': {
        Name: 'Networking In Standby'
    },
    'Settings.EnergySaverInStandby': {
        Name: 'Energy Saver In Standby'
    },
    'Settings.IsDebuggerEnabled': {
        Name: 'Debug Enabled'
    },
    'Settings.IsLockConsoleTimeoutActive': {
        Name: 'Lock Console Timeout Active'
    },
    'Settings.LockConsoleTimeoutInSeconds': {
        Name: 'Lock Idle Timeout (s)'
    },
    'Settings.PepPreVetoCount': {
        Name: 'PEP Pre-Veto Count'
    },
    'Settings.PowerScheme': {
        Name: 'Power Scheme Personality'
    },
    'Settings.StandbyTimeoutInSeconds': {
        Name: 'Standby Idle Timeout (s)'
    },
    'Settings.VideoTimeoutInSeconds': {
        Name: 'Video Idle Timeout (s)'
    },

    'Settings.Hibernate.BudgetRejectReason': {
        Name: 'Budget Action Reject Reason'
    },
    'Settings.Hibernate.HibernateBudgetPercentage': {
        Name: 'Hibernate Budget [percentage of battery]'
    },
    'Settings.Hibernate.HibernateTimeoutInSeconds': {
        Name: 'Hibernate Timeout [s]'
    },
    'Settings.Hibernate.IsHibernateEnabled': {
        Name: 'Hibernate Enabled'
    },
    'Settings.Hibernate.ReserveRejectReason': {
        Name: 'Reserve Action Reject Reason'
    },
    
    'MSExitPerformance.TotalInMs': {
        Name: 'Total Exit Time'
    },
    'MSExitPerformance.ResiliencyExitTime': {
        Name: 'Time Spent In Resiliency'
    },
    'MSExitPerformance.ResiliencyNotifyExitTime': {
        Name: 'Time Spent In Resiliency Notification'
    },
    'MSExitPerformance.LPEExitTime': {
        Name: 'Time Spent In LPE'
    },
    'MSExitPerformance.DAMExitTime': {
        Name: 'Time Spent In DAM'
    },
    'MSExitPerformance.MaintenanceExitTime': {
        Name: 'Time Spent In Maintenance'
    },
    'MSExitPerformance.PLMExitTime': {
        Name: 'Time Spent In PLM'
    },
    'MSExitPerformance.ShellExitTime': {
        Name: 'Time Spent In Shell'
    },
    'MSExitPerformance.ConnectionExitTime': {
        Name: 'Time Spent In Connection'
    },
    'MSExitPerformance.ScreenOnExitTime': {
        Name: 'Time Spent Turning Display On'
    },
    'MSExitPerformance.GdiOnTime': {
        Name: 'Graphics Device Interface (GDI)'
    },
    'MSExitPerformance.DwmSyncFlushTime': {
        Name: 'Desktop Window Manager (DWM)'
    },
    'MSExitPerformance.MonitorPowerOnTime': {
        Name: 'Monitor Power On'
    },
    'MSExitPerformance.ScreenOnOverhead': {
        Name: 'Request Processing'
    },
    'EventLog.ModernSleepAppliedActionsBitmask': {
        Visible: false
    }
}

//
// Add support for drawing dashed lines to canvas.
//

CanvasRenderingContext2D.prototype.dashedLine = function (x0, y0, x1, y1, dashArray) {
    if (dashArray == null) {
        dashArray = [4, 4];
    }

    var dx = x1 - x0;
    var dy = y1 - y0;
    var distance = Math.sqrt(Math.pow((x1 - x0), 2) + Math.pow((y1 - y0), 2));
    var theta = Math.atan(dy / dx);
    if (dx < 0) {
        theta += Math.PI;
    }

    var i = 0;
    while (distance > 0) {
        var length = Math.min(distance, dashArray[i]);
        x0 += length * Math.cos(theta);
        y0 += length * Math.sin(theta);
        if (i % 2 == 0) {
            this.lineTo(x0, y0);

        } else {
            this.moveTo(x0, y0);
        }

        distance -= length;
        i = (i + 1) % dashArray.length;
    }
};

var Utils = {
    DateFloor: function(Timestamp) {
        var Dt = new Date(Timestamp);
        return Date.parse(Dt.getFullYear() + '/' + (Dt.getMonth() + 1) + '/' + Dt.getDate());
    },
    DateToDayAndMonth: function(Timestamp, DayOffset) {
        var AdjustedDate = new Date(Timestamp + (DayOffset * 24 * 60 * 60 * 1000));
        return Utils.LeftPad(AdjustedDate.getMonth() + 1, 2, '0') + "-" +
               Utils.LeftPad(AdjustedDate.getDate(), 2, '0');
    },
    DaysToMs: function(Days) {
        return (Days * 24 * 60 * 60 * 1000);
    },
    ExpandObjectToArray: function (Obj) {
        var Values = [];
        for (var Property in Obj) {
            Values.push({
                Name: Property,
                Value: Obj[Property]
            });
        }

        return Values;
    },
    GetBlockerGroupActivityLevel: function (BlockerGroup) {
        var ActivityLevel = 0;
        for (var RootBlocker of BlockerGroup.Blockers) {
            if (RootBlocker.ActivityLevel > ActivityLevel) {
                ActivityLevel = RootBlocker.ActivityLevel;
            }
        }

        return ACTIVITY_LEVEL_NAMES[ActivityLevel];
    },
    GetObjectFieldArray: function (Object) {
        var Properties = [];
        for (var Field in Object) {
            Properties.push({
                Key: Field,
                Value: Object[Field]
            });
        }

        return Properties;
    },
    GetSessionBatteryInformation: function (Session) {
        var BatteryInformation = {
            HasDischargeInformation: false,
            HasDrainRate: false
        };

        if ((!Session.BatteryCountChanged) &&
            (Utils.IsNumber(Session.EntryFullChargeCapacity)) &&
            (Session.EntryFullChargeCapacity !== 0) &&
            (Utils.IsNumber(Session.ExitFullChargeCapacity)) &&
            (Session.ExitFullChargeCapacity !== 0)) {

            var BatteryDischarge = Math.round(Session.EntryRemainingCapacity - Session.ExitRemainingCapacity);
            if ((Utils.IsNumber(BatteryDischarge)) &&
                (BatteryDischarge > 0)) {

                BatteryInformation.HasDischargeInformation = true;
                BatteryInformation.Discharge = BatteryDischarge;
                BatteryInformation.DischargePercent =
                    Math.round(100 * BatteryDischarge / Session.EntryFullChargeCapacity);
            }

            var BatteryDrainRate = Math.round(BatteryDischarge * HOUR_TO_US / Session.Duration);
            if ((Utils.IsNumber(BatteryDrainRate)) &&
                (BatteryDrainRate > 0)) {

                BatteryInformation.HasDrainRate = true;
                BatteryInformation.DrainRate = BatteryDrainRate;
            }
        }

        return BatteryInformation;
    },
    IsNumber: function (Value) {
        return (typeof(Value) == "number") &&
               (Value == Value) &&
               (Value != (1 / 0)) &&
               (Value != (-1 / 0));
    },
    LeftPad: function (Value, Length, With) {
        Value = '' + Value;
        while (Value.length < Length) {
            Value = With + Value;
        }

        return Value;
    },
    ParseDateTime: function (DateTime) {
        var DateFormat = /(\d{4})-(\d{2})-(\d{2})[T](\d{2}):(\d{2}):(\d{2})/

        var Match = DateFormat.exec(DateTime);
        return Date.parse(Match[1] + '/' + Match[2] + '/' +
                          Match[3] + ' ' + Match[4] + ':' +
                          Match[5] + ':' + Match[6]);
    },
    ParseDateFromDateTime: function (DateTime) {
        return DateTime.substring(0, DateTime.indexOf('T'));
    },
    ParseTimeFromDateTime: function (DateTime) {
        return DateTime.substring(DateTime.indexOf('T') + 1,
                                  DateTime.length - 1);
    },
    ReverseForEach: function (Array, Callback) {
        for (var i = Array.length - 1; i >= 0; i -= 1) {
            Callback(Array[i]);
        }

        return;
    },
    ScrollToTop: function() {
        var TopElement = document.getElementById('spr-header');
        if (TopElement === null) {
            TopElement = document.getElementById('spr-content');
        }

        TopElement.scrollIntoView(true);
    }
};

var Formatter = {
    FormatDataValue: function (DataValue) {
        if (typeof(DataValue) == 'boolean') {
            return DataValue ? 'YES' : 'NO';
        }

        return DataValue;
    },
    FormatDuration: function (Duration) {
        var SecondsTotal = Math.floor(Duration / SEC_TO_US);
        var MinutesTotal = Math.floor(SecondsTotal / 60);
        var HoursTotal = Math.floor(MinutesTotal / 60);

        var Result = '';
        Result += HoursTotal + ':';
        Result += Utils.LeftPad(MinutesTotal % 60, 2, '0') + ':';
        Result += Utils.LeftPad(SecondsTotal % 60, 2, '0');
        return Result;
    },
    FormatNumber: function (Number) {
        var LocaleString = Math.round(parseFloat(Number + '')).toLocaleString();
        var DecimalIndex = LocaleString.indexOf('.');
        if (DecimalIndex !== -1) {
            LocaleString = LocaleString.substring(0, DecimalIndex);
        }

        return LocaleString;
    },
    FormatSessionEnterBatteryPercent: function (Session) {
        if ((!Session.BatteryCountChanged) &&
            (Utils.IsNumber(Session.EntryRemainingCapacity)) &&
            (Session.EntryRemainingCapacity != 0) &&
            (Utils.IsNumber(Session.EntryFullChargeCapacity) &&
            (Session.EntryFullChargeCapacity != 0))) {

            var Percent = 100 * Session.EntryRemainingCapacity / Session.EntryFullChargeCapacity;
            return Math.round(Percent) + '%';

        } else {
            return '-';
        }
    }
};

var Collapser = {
    GetContainerBody: function (Container) {
        var Children = Container.childNodes;
        var ContainerBody = null;
        for (var i = 0; i < Children.length; i++) {
            if (Children[i].tagName == "DIV" &&
                ((Children[i].className == "analysis-body-collapsed") ||
                 (Children[i].className == "analysis-body"))) {

                ContainerBody = Children[i];
                break;
            }
        }

        return ContainerBody;
    },
    ScrollIntoView: function (TargetId) {
        var TargetElement = document.getElementById(TargetId);
        var Container = TargetElement;
        while (Container != null) {
            if ((Container.className != undefined) && (Container.className.includes('analysis-container'))) {
                var ContainerBody = Collapser.GetContainerBody(Container);
                if (ContainerBody.className == "analysis-body-collapsed") {
                    Collapser.TogglePanel(ContainerBody);
                }
            }

            Container = Container.parentNode;
        }

        TargetElement.scrollIntoView(true);
    },
    TogglePanel: function (ContainerChild) {
        var ContainerParent = ContainerChild.parentNode;
        var ContainerBody = this.GetContainerBody(ContainerParent);
        var Expander = ContainerParent.getElementsByClassName("expander")[0];
        if (ContainerBody.className == "analysis-body-collapsed") {
            ContainerBody.className = "analysis-body";
            Expander.innerHTML = "- ";

        } else {
            ContainerBody.className = "analysis-body-collapsed";
            Expander.innerHTML = "+ ";
        }
    }
}

var HistogramBuilder = {

    //
    // Constants.
    //

    AxisBottom: 25.5,
    AxisLeft: 30.5,
    BarColor: '#1191c1',
    LineColor: '#c0c0c0',
    MaxPadding: 25,
    PaddingTop: 5,
    YTicks: 10,

    //
    // Builder routines.
    //

    BuildHistogramObject: function (HistogramData, CanvasElement, RangeMax) {
        var Histogram = {};
        Histogram.Data = HistogramData;
        Histogram.Canvas = CanvasElement;
        Histogram.BucketCount = HistogramData.length;
        Histogram.Max = RangeMax;
        for (var Datum of HistogramData) {
            Histogram.Max = Math.max(Histogram.Max, Datum.Value);
        }

        return Histogram;
    },
    DrawHistogram: function (Histogram) {
        Histogram.Context = Histogram.Canvas.getContext("2d");
        Histogram.Context.strokeStyle = this.LineColor;
        Histogram.Width = Histogram.Canvas.width;
        Histogram.Height = Histogram.Canvas.height;
        Histogram.TickSpacing = (Histogram.Width - this.AxisLeft) / Histogram.BucketCount;
        this.DrawHistogramFrame(Histogram);
        this.DrawHistogramRange(Histogram);
        this.DrawHistogramDomain(Histogram);
        this.DrawHistogramBuckets(Histogram);
    },
    DrawHistogramBuckets: function (Histogram) {
        var Context = Histogram.Context;
        var TickOffset = this.AxisLeft + this.PaddingTop;

        Context.fillStyle = this.BarColor;
        for (var i = 0; i < Histogram.BucketCount; i += 1) {
            if (Histogram.Data[i].Value !== 0) {
                var BarHeight = Histogram.Data[i].Value;
                BarHeight *= (Histogram.Height - 50);
                BarHeight /= Histogram.Max;
                BarHeight = Math.round(BarHeight);
                Context.fillRect(TickOffset,
                                 Histogram.Height - this.AxisBottom - BarHeight,
                                 Histogram.TickSpacing - 10,
                                 BarHeight);
            }

            TickOffset += Histogram.TickSpacing;
        }
    },
    DrawHistogramDomain: function (Histogram) {
        var Context = Histogram.Context;

        var TickOffset = 2;

        Context.font = '8pt Segoe UI';
        Context.fillStyle = '#00b0f0';
        for (var i = 0; i < Histogram.BucketCount; i += 1) {
            var Entry = Histogram.Data[i];
            Context.fillText(Entry.BucketName,
                             this.AxisLeft + TickOffset,
                             Histogram.Height - 10,
                             Histogram.TickSpacing);

            TickOffset += Histogram.TickSpacing;
        }
    },
    DrawHistogramFrame: function (Histogram) {
        var Context = Histogram.Context;

        Context.beginPath();
        Context.moveTo(this.AxisLeft, this.PaddingTop);
        Context.lineTo(this.AxisLeft, Histogram.Height - this.AxisBottom);
        Context.lineTo(Histogram.Width, Histogram.Height - this.AxisBottom);
        Context.stroke();
    },
    DrawHistogramRange: function (Histogram) {
        var Context = Histogram.Context;
        
        var TickSpacing = Histogram.Height - this.AxisBottom - 25;
        TickSpacing /= this.YTicks;

        var TickIncrement = Math.round(Histogram.Max / this.YTicks);
        var TickOffset = Histogram.Height - this.AxisBottom - TickSpacing;
        var TickValue = TickIncrement;

        Context.font = '12pt Segoe UI';
        Context.fillStyle = '#00b0f0'
        for (var i = 0; i < this.YTicks; i += 1) {
            Context.beginPath();
            Context.moveTo(this.AxisLeft, TickOffset);
            Context.lineTo(this.AxisLeft + 5, TickOffset);
            Context.stroke();
            Context.fillText(TickValue.toString(),
                             0,
                             TickOffset + 5,
                             this.AxisLeft);

            TickValue += TickIncrement;
            TickOffset -= TickSpacing;
        }
    }
};

var MetadataUtils = {
    GetMetadataValue: function (Container, Key) {
        for (var Entry of Container.Values) {
            if (Entry.Key === Key) {
                return Entry.Value;
            }
        }

        return undefined;
    },
    ParseMetadataAttributes: function(AttributeString) {
        var Attributes = {};
        try {
            Attributes = JSON.parse(AttributeString);

        } catch (Error) {
            console.error(`Failed to parse attribute string ${AttributeString}`);
            console.log(Error);
        }

        return Attributes;
    },
    ParseMetadataTree: function (Metadata) {
        var ContainerNodesMap = {};
        var EntryAttributes = {};
        var RootContainer = {
            Entries: [],
            Children: [],
            FriendlyName: Metadata.FriendlyName
        };

        ContainerNodesMap[''] = RootContainer;

        var GetContainer = function(ContainerPath) {
            var Container = ContainerNodesMap[ContainerPath];
            if (Container === undefined) {
                var CurrentContainer = RootContainer;
                var Index = 0;
                while (Index < ContainerPath.length) {
                    var NextIndex = ContainerPath.indexOf('.', Index + 1);
                    if (NextIndex === -1) {
                        NextIndex = ContainerPath.length;
                    }

                    var NextContainerPath =
                        ContainerPath.substring(0, NextIndex);
                    
                    var NextContainer = ContainerNodesMap[NextContainerPath];
                    if (NextContainer === undefined) {
                        NextContainer = {
                            Entries: [],
                            Children: [],
                            FriendlyName: ContainerPath.substring(Index + 1,
                                                                  NextIndex)
                        };

                        if (CurrentContainer !== undefined) {
                            CurrentContainer.Children.push(NextContainer);
                        }

                        ContainerNodesMap[NextContainerPath] = NextContainer;
                    }

                    Index = NextIndex;
                    CurrentContainer = NextContainer;
                }

                Container = CurrentContainer;
            }

            return Container;
        };
        
        var GetMetadataAttributes = function(PropertyPath) {
            var Attributes = EntryAttributes[PropertyPath];
            if (Attributes === undefined) {
                Attributes = {
                    Visible: true,
                    Order: 4294967295
                };

                var Defaults = DEFAULT_METADATA_ATTRIBUTES[PropertyPath];
                if (Defaults !== undefined) {
                    for (var Attribute in Defaults) {
                        Attributes[Attribute] = Defaults[Attribute];
                    }
                }

                EntryAttributes[PropertyPath] = Attributes;
            }

            return Attributes;
        };

        var SetMetadataAttributes = function(PropertyName, NewAttributes) {
            var Attributes = GetMetadataAttributes(PropertyName);
            for (var Attribute in NewAttributes) {
                Attributes[Attribute] = NewAttributes[Attribute];
            }
        };

        for (var Entry of Metadata.Values) {
            var PropertyPath = Entry.Key;
            var PropertyValue = Entry.Value;
            if (PropertyPath.endsWith('._Attributes')) {
                var PropertyName =
                    PropertyPath.substring(0, PropertyPath.length - 12);

                var NewAttributes =
                    MetadataUtils.ParseMetadataAttributes(PropertyValue);

                SetMetadataAttributes(PropertyName, NewAttributes);

            } else if (PropertyPath.endsWith('._Header')) {
                var ContainerPath =
                    PropertyPath.substring(0, PropertyPath.length - 8);
            
                var Container = GetContainer(ContainerPath);
                Container.FriendlyName = PropertyValue;

            } else {
                var Index = PropertyPath.lastIndexOf('.');
                var ContainerPath;
                var PropertyName;
                if (Index === -1) {
                    ContainerPath = '';
                    PropertyName = PropertyPath;

                } else {
                    ContainerPath = PropertyPath.substring(0, Index);
                    PropertyName = PropertyPath.substring(Index + 1);
                }

                var Container = GetContainer(ContainerPath);
                Container.Entries.push({
                    Path: PropertyPath,
                    Name: PropertyName,
                    Value: PropertyValue,
                    Position: Container.Entries.length
                });
            }
        }

        var Stack = [];
        Stack.push({
            Container: RootContainer,
            Index: 0
        });

        while (Stack.length !== 0) {
            var StackEntry = Stack[Stack.length - 1];
            var Container = StackEntry.Container;
            if (StackEntry.Index === 0) {
                for (var Entry of Container.Entries) {
                    var Attributes = GetMetadataAttributes(Entry.Path);
                    for (var Attribute in Attributes) {
                        Entry[Attribute] = Attributes[Attribute];
                    }
                }
    
                Container.Entries = Container.Entries.filter(function (Element) {
                    return Element.Visible;
        
                }).sort(function (Left, Right) {
                    if (Left.Order !== Right.Order) {
                        return Left.Order - Right.Order;
        
                    } else {
                        return Left.Position - Right.Position;
                    }
                });
            }

            if (StackEntry.Index < Container.Children.length) {
                Stack.push({
                    Container: Container.Children[StackEntry.Index],
                    Index: 0
                });

                StackEntry.Index += 1;

            } else {
                Container.Children = Container.Children.filter(function (Child) {
                    return (Child.Entries.length !== 0) || (Child.Children.length !== 0);

                }).sort(function (Left, Right) {
                    if (Left.FriendlyName < Right.FriendlyName) {
                        return -1;

                    } else if (Left.FriendlyName > Right.FriendlyName) {
                        return 1;

                    } else {
                        return 0;
                    }
                });

                Stack.pop();
            }
        }

        return RootContainer;
    }
};

var SrumTableBuilder = {
    SortEnergyEstimationRecords: function(EstimationRecords) {
        return EstimationRecords.filter(function(Element) {
            return Element.EnergyConsumption !== 0;

        }).sort(function(Left, Right) {
            return Right.EnergyConsumption - Left.EnergyConsumption;
        });

    },
    SortPowerEstimationRecords: function(EstimationRecords) {
        return EstimationRecords.filter(function(Element) {
            return Element.TotalPowerConsumption !== 0;

        }).sort(function(Left, Right) {
            return Right.TotalPowerConsumption - Left.TotalPowerConsumption;
        });
    }
};

var SummaryTableBuilder = {
    LastDate: undefined,
    SessionLengthFilter: 'AllTime',
    SessionTypeFilter: 'All',
    TypeFilterTable: {
        'Active': [0],
        'ScreenOff': [1],
        'Standby': [2, 3, 4],
        'Hibernate': [5],
        'Shutdown': [6, 7],
        'BugCheck': [9, 10]
    },
    FilterTableRows: function () {
        var SummaryTable = document.getElementById('summary-table');
        var SummaryTableRows = SummaryTable.getElementsByTagName('tr');
        for (var Index = 0; Index < SummaryTableRows.length; Index += 1) {
            var RowElement = SummaryTableRows[Index];
            var RowScope = RowElement.RowScope;
            if (RowScope === undefined) {
                continue;
            }

            var FilterSession = false;
            if ((this.SessionLengthFilter !== 'AllTime') &&
                (RowScope.Duration < (10 * 60 * SEC_TO_US))) {
                
                FilterSession = true;
            }

            if ((this.SessionTypeFilter !== 'All') &&
                (!this.TypeFilterTable[this.SessionTypeFilter].includes(RowScope.Type))) {

                FilterSession = true;
            }

            if (FilterSession) {
                RowElement.style.display = "none";

            } else {
                RowElement.style.display = "";
            }
        };
    },
    OnDurationValueChanged: function(Element) {
        if (Element.checked) {
            this.SessionLengthFilter = Element.value;
            this.FilterTableRows();
        }

        return;
    },
    OnStateValueChanged: function(Element) {
        if (Element.checked) {
            this.SessionTypeFilter = Element.value;
            this.FilterTableRows();
        }

        return;
    },
    PostProcessSessionRow: function(Node, Scope) {
        Node.RowScope = Scope;
        DOMBuilder.InsertTableRowLinks(Node, `#session-${Scope.SessionId}`);
        return;
    },
    SelectDate: function(DateTime) {
        var Date = Utils.ParseDateFromDateTime(DateTime);
        if (Date == this.LastDate) {
            return ' ';

        } else {
            this.LastDate = Date;
            return Date;
        }
    },
    SelectTime: function(DateTime) {
        return Utils.ParseTimeFromDateTime(DateTime);
    }
};

var Timegraph = {
    AxisTop: 9.5,
    AxisRight: 24.5,
    AxisBottom: 25.5,
    AxisLeft: 25.5,
    Ticks: 10,

    // Maximum number of 24 hour ticks for showing 12 and 6 hour ticks

    Ticks12Hour: 8,
    Ticks6Hour: 4,

    // Shading

    ShadingColor: "#d0d0d0",

    //
    // Line types
    //

    LineTypes: [
        { Color: "none", Dotted: 0 },
        { Color: "#000000", Dotted: 0 },
        { Color: "#2a7a2a", Dotted: 0 },
        { Color: "#a26609", Dotted: 0 },
        { Color: "#970d00", Dotted: 0 },
        { Color: "#000000", Dotted: 1 },
        { Color: "#2a7a2a", Dotted: 1 },
        { Color: "#a26609", Dotted: 1 },
        { Color: "#970d00", Dotted: 1 },
    ],

    Precompute: function (Graph, InputData) {
        var Canvas = Graph.Canvas;
        var Data = [];
        var Min = 0;
        var Max = 0;

        Graph.Height = Canvas.height - Timegraph.AxisTop - Timegraph.AxisBottom;
        Graph.Width = Canvas.width - Timegraph.AxisLeft - Timegraph.AxisRight;
        for (var DrainEntry of InputData) {
            var T0 = Utils.ParseDateTime(DrainEntry.StartTimestampLocal);
            var T1 = Utils.ParseDateTime(DrainEntry.EndTimestampLocal);
            var Y0 = DrainEntry.StartChargeCapcity / DrainEntry.StartFullChargeCapacity;
            var Y1 = DrainEntry.EndChargeCapacity / DrainEntry.EndFullChargeCapacity;
            var YY0 = Timegraph.AxisTop + Graph.Height - Y0 * Graph.Height;
            var YY1 = Timegraph.AxisTop + Graph.Height - Y1 * Graph.Height;
            var Type = 1;
            if ((DrainEntry.Activity >= 1) && (DrainEntry.Activity <= 3)) {
                Type = DrainEntry.Activity + 1;
            }

            if (DrainEntry.OnAc) {
                Type += 4;
            }

            if (Data.length == 0) {
                Min = T0;
                Max = T1;
            }

            if (T0 < Min) {
                Min = T0;
            }

            if (T1 > Max) {
                Max = T1;
            }

            Data.push({
                T0: T0,
                T1: T1,
                YY0: YY0,
                YY1: YY1,
                Type: Type
            });
        }

        if (Graph.StartTime != null) {
            Graph.StartMs = Utils.ParseDateTime(Graph.StartTime);

        } else {
            Graph.StartMs = Min;
        }

        Graph.EndMs = Max;
        Graph.DurationMs = Max - Min;
        Graph.Data = Data;
    },
    DrawFrame: function (Graph) {
        var Context = Graph.Context;
        Context.beginPath();
        Context.moveTo(Timegraph.AxisLeft, Timegraph.AxisTop);
        Context.lineTo(Timegraph.AxisLeft + Graph.Width,
                       Timegraph.AxisTop);

        Context.lineTo(Timegraph.AxisLeft + Graph.Width,
                       Timegraph.AxisTop + Graph.Height);

        Context.lineTo(Timegraph.AxisLeft,
                       Timegraph.AxisTop + Graph.Height);

        Context.lineTo(Timegraph.AxisLeft, Timegraph.AxisTop);
        Context.strokeStyle = "#c0c0c0";
        Context.stroke();
    },
    DrawRange: function (Graph) {
        var Context = Graph.Context;

        Context.font = "12pt Segoe UI";
        Context.fillStyle = "#0078D6";
        Context.fillText("%", 0, Timegraph.AxisTop + 5, Timegraph.AxisLeft);

        var TickSpacing = Graph.Height / 10;
        var Offset = Timegraph.AxisTop + TickSpacing;
        var TickValue = 90;
        for (var I = 0; I < 9; I++) {
            Context.beginPath();
            Context.moveTo(Timegraph.AxisLeft, Offset);
            Context.lineTo(Timegraph.AxisLeft + Graph.Width, Offset);
            Context.stroke();
            Context.fillText(TickValue.toString(),
                             0,
                             Offset + 5,
                             Timegraph.AxisLeft);

            Offset += TickSpacing;
            TickValue -= 10;
        }
    },
    DrawDomain: function (Graph, Start, End) {
        var Context = Graph.Context;
        var Duration = End - Start;
        if (End < Start) {
            return;
        }

        var StartDay = Utils.DateFloor(Start);
        var T0 = StartDay;
        var T1 = Utils.DateFloor(End);
        var DayOffset = 0;
        if (Start > T0) {
            T0 = T0 + Utils.DaysToMs(1);
            DayOffset++;
        }

        if (T0 >= T1) {
            return;
        }

        var Increment =
            Math.max(Math.floor((T1 - T0) / Utils.DaysToMs(Timegraph.Ticks)), 1);

        var IncrementMs = Utils.DaysToMs(Increment);
        var Spacing = (IncrementMs / Duration) * Graph.Width;
        var Offset = (T0 - Start) / Duration;
        var TicksCount = Math.floor((T1 - T0) / IncrementMs);
        for (Offset = Offset * Graph.Width + Timegraph.AxisLeft;
             Offset < (Graph.Width + Timegraph.AxisLeft);
             Offset += Spacing) {

            Context.beginPath();
            Context.moveTo(Offset, Timegraph.AxisTop);
            Context.lineTo(Offset, Timegraph.AxisTop + Graph.Height);
            Context.stroke();
            Context.fillText(Utils.DateToDayAndMonth(StartDay, DayOffset),
                             Offset,
                             Timegraph.AxisTop + Graph.Height + 15,
                             Spacing);

            DayOffset += Increment;
        }
    },
    Plot: function (Graph, Start, End) {
        var Context = Graph.Context
        if (End < Start) {
            return;
        }

        var Duration = End - Start;
        Timegraph.DrawDomain(Graph, Start, End);
        Context.fillStyle = Timegraph.ShadingColor;
        for (var Entry of Graph.Data) {
            if ((Entry.T0 < Start) || (Entry.T0 > End) ||
                (Entry.T1 > End)) {

                continue;
            }

            var X1 = (Entry.T0 - Start) / Duration;
            X1 = X1 * Graph.Width + Timegraph.AxisLeft;

            var X2 = (Entry.T1 - Start) / Duration;
            X2 = X2 * Graph.Width + Timegraph.AxisLeft;

            Context.globalAlpha = 0.3;
            Context.fillRect(X1, Timegraph.AxisTop, (X2 - X1), Graph.Height);
            Context.globalAlpha = 1;
            Context.beginPath();
            Context.strokeStyle = Timegraph.LineTypes[Entry.Type].Color;
            Context.lineWidth = 1.5;
            if (Timegraph.LineTypes[Entry.Type].Dotted == 1) {
                Context.dashedLine(X1, Entry.YY0, X2, Entry.YY1);

            } else {
                Context.moveTo(X1, Entry.YY0);
                Context.lineTo(X2, Entry.YY1);
            }

            Context.stroke();
        }
    },
    Draw: function (Scope, Canvas) {
        var Context = Canvas.getContext('2d');
        if (Context == null) {
            return;
        }

        var Graph = {
            Context: Context,
            Canvas: Canvas,
            StartTime: Scope.ReportInformation.ReportStartTimeLocal,
            EndTime: Scope.ReportInformation.ScanTimeLocal
        };

        Timegraph.Precompute(Graph, Scope.EnergyDrains);
        Timegraph.DrawFrame(Graph);
        Timegraph.DrawRange(Graph);
        Timegraph.Plot(Graph, Graph.StartMs, Graph.EndMs);
    }
};

var DOMBuilder = {
    Document: undefined,
    DocumentTemplates: {},
    DOMRoot: undefined,
    ElementStack: [],
    HistogramList: [],
    PostProcessList: [],
    AddChildElements: function (SourceNode, DestinationNode, CurrentScope) {
        Utils.ReverseForEach(SourceNode.childNodes, function (SourceChildNode) {
            DOMBuilder.ElementStack.push({
                SourceChildNode: SourceChildNode,
                DestinationNode: DestinationNode,
                CurrentScope: CurrentScope,
                Pass: 0
            });
        });

        return;
    },
    CreateFunction: function(Definition) {
        return new Function("$Scope", "$Node", `return ${Definition};`);
    },
    CreateTextFunction: function(Text) {
        return new Function("$Scope", "$Node", `return \`${Text}\`;`);
    },
    EvaluateInCache: function(Cache, Attribute, Definition, FunctionBuilder, CurrentScope, CurrentNode) {
        var CachedFunction = Cache[Attribute];
        if (CachedFunction === undefined) {
            CachedFunction = Cache[Attribute] = FunctionBuilder(Definition);
        }

        try {
            return CachedFunction(CurrentScope, CurrentNode);

        } catch (Error) {
            console.log('Failed to evaluate "' + CachedFunction + '" in scope:');
            console.log(CurrentScope);
            console.error(Error);
            return '';
        }
    },
    EvaluateAttributeInScope: function(Node, Attribute, CurrentScope, CurrentNode) {
        return this.EvaluateInCache(this.GetOrCreateCache(Node),
                                    Attribute,
                                    Node.getAttribute(Attribute),
                                    this.CreateFunction,
                                    CurrentScope,
                                    CurrentNode);
    },
    EvaluateTextAttributeInScope: function(Node, Attribute, CurrentScope, CurrentNode) {
        var AttributeValue = Node.getAttribute(Attribute);
        if ((!AttributeValue.includes('$Scope')) && (!AttributeValue.includes('$Node'))) {
            return AttributeValue;
        }

        return this.EvaluateInCache(this.GetOrCreateCache(Node),
                                    Attribute,
                                    AttributeValue,
                                    this.CreateTextFunction,
                                    CurrentScope,
                                    CurrentNode);
    },
    GetOrCreateCache: function (Node) {
        if (Node.SprEvalCache === undefined) {
            Node.SprEvalCache = {};
        }

        return Node.SprEvalCache;
    },
    InsertTableRowLinks: function (RowNode, Link) {
        for (var Element of RowNode.querySelectorAll('td')) {
            if (Element.childNodes.length == 0) {
                continue;
            }
            
            var LinkElement = this.Document.createElement('a');
            LinkElement.setAttribute('href', Link);
            LinkElement.setAttribute('class', 'row-link');

            //
            // Move all child elements to the LinkElement.
            //

            while (Element.childNodes.length !== 0) {
                LinkElement.appendChild(Element.childNodes[0]);
            }

            Element.appendChild(LinkElement);
        }
        
    },
    ProcessDocument: function (Document, SourceElement, DestinationParent, RootScope) {
        this.Document = Document;

        //
        // Create a new body element to build.
        //

        var DestinationBody = Document.createElement('div');

        //
        // Find all document templates.
        //

        SourceElement.querySelectorAll('[data-define-template]').forEach(function (TemplateElement) {
            var TemplateName = TemplateElement.getAttribute('data-define-template');
            DOMBuilder.DocumentTemplates[TemplateName] = TemplateElement;
        });

        //
        // Traverse the current document elements to build a new DOM to display.
        //

        this.AddChildElements(SourceElement, DestinationBody, RootScope);
        while (this.ElementStack.length > 0) {
            var {
                SourceChildNode,
                DestinationNode,
                CurrentScope,
                Pass
            } = this.ElementStack.pop();

            if (SourceChildNode.nodeType == 8) {
                continue;
            }

            DOMBuilder.ProcessSourceElement(SourceChildNode, DestinationNode, CurrentScope, Pass);
        }

        //
        // Append the generated body into the DestinationParent child list.
        //

        DestinationParent.append(DestinationBody);

        //
        // Process any histogram data buckets.
        //

        while (this.HistogramList.length > 0) {
            HistogramBuilder.DrawHistogram(this.HistogramList.shift());
        }

        //
        // Execute any post process execution for elements.
        //

        while (this.PostProcessList.length > 0) {
            var {
                SourceNode,
                Node,
                Scope
            } = this.PostProcessList.shift();

            this.EvaluateAttributeInScope(SourceNode,
                                          'data-post-process',
                                          Scope,
                                          Node);
        }
    },
    ProcessSourceElement: function(SourceNode, DestinationParentNode, CurrentScope, Pass) {
        if (Pass == 0) {

            //
            // If this is not an ELEMENT_NODE HTML node, then evaluate that without checking for
            // attributes.
            //

            if (SourceNode.nodeType != 1) {
                var DestinationChild;
                if (SourceNode.nodeType == 3) {
                    var DestinationContent =
                        this.EvaluateInCache(this.GetOrCreateCache(SourceNode),
                                             'data-spr-content',
                                             SourceNode.wholeText,
                                             this.CreateTextFunction,
                                             CurrentScope);

                    DestinationChild = new Text(DestinationContent);

                } else {
                    DestinationChild = SourceNode.cloneNode(true);
                }

                DestinationParentNode.appendChild(DestinationChild);
                return;
            }

            //
            // If the source node has requested to be ignored, return now.
            //

            if (SourceNode.hasAttribute('data-ignore')) {
                return;
            }

            //
            // If this source node requested a scope change, evaluate that now.
            //

            if (SourceNode.hasAttribute('data-scope')) {
                CurrentScope = this.EvaluateAttributeInScope(SourceNode,
                                                             'data-scope',
                                                             CurrentScope);
            }
            
            //
            // If the source node has conditionals bound to it, check now.
            //

            if (SourceNode.hasAttribute('data-if')) {
                var ConditionalAttribute = 'data-if';
                while (true) {
                    if (SourceNode !== null) {
                        if (SourceNode.hasAttribute('data-else')) {
                            break;
                        }

                        if (SourceNode.hasAttribute(ConditionalAttribute)) {
                            var Result = this.EvaluateAttributeInScope(SourceNode,
                                                                       ConditionalAttribute,
                                                                       CurrentScope);

                            if (Result) {
                                break;
                            }

                            SourceNode = SourceNode.nextElementSibling;
                            ConditionalAttribute = 'data-else-if'
                            continue;
                        }
                    }

                    return;
                }

            } else if (SourceNode.hasAttribute('data-else') || SourceNode.hasAttribute('data-else-if')) {

                //
                // This node has already been evaluated in the context of the 'data-if' element.
                //

                return;
            }

            //
            // If this source node requested to be expanded, evaluate that now.
            //

            if (SourceNode.hasAttribute('data-foreach')) {
                var RequestedValues =
                    this.EvaluateAttributeInScope(SourceNode,
                                                  'data-foreach',
                                                  CurrentScope);

                Utils.ReverseForEach(RequestedValues, function (ChildScope) {
                    DOMBuilder.ElementStack.push({
                        SourceChildNode: SourceNode,
                        DestinationNode: DestinationParentNode,
                        CurrentScope: ChildScope,
                        Pass: 1
                    });
                });

                //
                // Return back to the processing loop the process the expanded elements.
                //

                return;
            }

            Pass += 1;
        }

        if (Pass == 1) {

            //
            // If the source node has requested to apply a template, replace the source now.
            //

            if (SourceNode.hasAttribute('data-apply-template')) {
                var TemplateName = SourceNode.getAttribute('data-apply-template');
                var TemplateNode = this.DocumentTemplates[TemplateName];
                if ((TemplateNode === undefined) || (TemplateNode === null)) {
                    console.log('Failed to find template with name: ' + TemplateName)
                }

                DOMBuilder.ElementStack.push({
                    SourceChildNode: TemplateNode,
                    DestinationNode: DestinationParentNode,
                    CurrentScope: CurrentScope,
                    Pass: 0
                });

                return;
            }
            
            //
            // If the source node has requested to be collapsed, add all children elements to be
            // added in this node's place.
            //

            if (SourceNode.hasAttribute('data-collapse')) {
                this.AddChildElements(SourceNode, DestinationParentNode, CurrentScope);
                return;
            }

            //
            // Build a new destination node.
            //

            var NodeType = SourceNode.tagName;
            if (SourceNode.hasAttribute('data-override-type')) {
                NodeType = SourceNode.getAttribute('data-override-type');
            }

            var DestinationChildNode = this.Document.createElement(NodeType);

            //
            // Copy non-data attributes.
            //
            
            var SourceAttributes = SourceNode.attributes;
            for (var i = 0; i < SourceAttributes.length; i += 1) {
                var SourceAttribute = SourceAttributes[i];
                if (SourceAttribute.name.startsWith('data-')) {
                    continue;
                }

                var AttributeName = SourceAttribute.name;
                var AttributeValue = this.EvaluateTextAttributeInScope(SourceNode,
                                                                       AttributeName,
                                                                       CurrentScope);
                                                                       
                DestinationChildNode.setAttribute(AttributeName, AttributeValue);
            }

            //
            // If the node has requested any post process execution, then schedule that routine.
            //

            if (SourceNode.hasAttribute('data-post-process')) {
                this.PostProcessList.push({
                    SourceNode: SourceNode,
                    Node: DestinationChildNode,
                    Scope: CurrentScope
                });
            }

            //
            // If the node has requested to be bound to data, evaluate that now.
            //

            if (SourceNode.hasAttribute('data-bind')) {
                var DataValue =
                    this.EvaluateAttributeInScope(SourceNode,
                                                  'data-bind',
                                                  CurrentScope);

                DestinationChildNode.innerText = Formatter.FormatDataValue(DataValue);

            } else if (SourceNode.hasAttribute('data-bind-raw')) {
                DestinationChildNode.innerText =
                    this.EvaluateAttributeInScope(SourceNode,
                                                  'data-bind-raw',
                                                  CurrentScope);

            } else if (SourceNode.hasAttribute('data-histogram')) {
                var HistogramData =
                    this.EvaluateAttributeInScope(SourceNode,
                                                  'data-histogram',
                                                  CurrentScope);

                var HistogramRangeMax = 1;
                if (SourceNode.hasAttribute('data-histogram-range-max')) {
                    HistogramRangeMax =
                        this.EvaluateAttributeInScope(SourceNode,
                                                      'data-histogram-range-max',
                                                      CurrentScope);
                }

                var Histogram =
                    HistogramBuilder.BuildHistogramObject(HistogramData,
                                                          DestinationChildNode,
                                                          HistogramRangeMax);

                this.HistogramList.push(Histogram);

            } else {
                this.AddChildElements(SourceNode, DestinationChildNode, CurrentScope);
            }

            //
            // Append the child to the destination node.
            //

            DestinationParentNode.appendChild(DestinationChildNode);        
        }

        return;
    }
};
P<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ms="urn:schemas-microsoft-com:xslt"
    xmlns:bat="http://schemas.microsoft.com/battery/2012"
    xmlns:js="http://microsoft.com/kernel"
    version="1.0">

  <xsl:output
      method="html"
      omit-xml-declaration="yes"
      indent="no"
      encoding="utf-16" />

  <xsl:variable name="reportInfo" select="/bat:BatteryReport/bat:ReportInformation" />
  <xsl:variable name="systemInfo" select="/bat:BatteryReport/bat:SystemInformation" />
  <xsl:variable name="reportTime" select="string($reportInfo/bat:ScanTime)" />
  <xsl:variable name="localReportTime" select="string($reportInfo/bat:LocalScanTime)" />
  <xsl:variable name="aoac" select="$systemInfo/bat:ConnectedStandby != 0" />
  <xsl:variable name="reportDuration" select="$reportInfo/bat:ReportDuration" />
  <xsl:variable name="graphStart" select="$reportInfo/bat:LocalReportStartTime" />

  <!-- Creates the name of the state of a bat:UsageEntry -->
  <xsl:template match="bat:UsageEntry" mode ="toStateName" >
    <xsl:choose>
      <xsl:when test="@EntryType = 'Suspend'">
        Suspended
      </xsl:when>
      <xsl:when test="@EntryType = 'Active'">
        Active
      </xsl:when>
      <xsl:when test="@EntryType = 'ReportGenerated'">
        Report generated
      </xsl:when>
      <xsl:when test="@EntryType = 'BatteryChanged'">
        Battery changed
      </xsl:when>

      <xsl:otherwise>
        <xsl:choose>
          <xsl:when test="$aoac">
            Connected standby
          </xsl:when>
          <xsl:otherwise>
            Screen off
          </xsl:otherwise>
        </xsl:choose>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <!-- Creates the name of the power source of a bat:UsageEntry -->
  <xsl:template match="bat:UsageEntry" mode ="toPowerSourceName" >
    <xsl:choose>
      <xsl:when test="@EntryType = 'Suspend'">
      </xsl:when>
      <xsl:when test="@Ac = '0'">
        Battery
      </xsl:when>
      <xsl:otherwise>
        AC
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <!-- Creates the "even" or "odd" class for rows. This is used to give the rows alternating colors. -->
  <xsl:template name="classEvenOdd" >
    <xsl:param name="position" />
    <xsl:param name="otherClasses" select="''" />
    <xsl:attribute name="class">
      <xsl:choose>
        <xsl:when test="$position mod 2">even</xsl:when>
        <xsl:otherwise>odd</xsl:otherwise>
      </xsl:choose>
      <xsl:text> </xsl:text>
      <xsl:value-of select="$otherClasses" />
      <xsl:text> </xsl:text>
      <xsl:value-of select="$position" />
    </xsl:attribute>
  </xsl:template>


  <!-- Styles -->
  <xsl:template name="css">
    <style type="text/css">
      body {
          font-family: Segoe UI Light;
          letter-spacing: 0.02em;
          background-color: #181818;
          color: #F0F0F0;
          margin-left: 5.5em;
      }

      h1 {
          color: #11D8E8;
          font-size: 42pt;
      }

      h2 {
          font-size: 15pt;
          color: #11EEF4;
          margin-top: 4em;
          margin-bottom: 0em;
          letter-spacing: 0.08em;
      }

      td {
          padding-left: 0.3em;
          padding-right: 0.3em;
      }

      .nobatts {
          font-family: Segoe UI Semibold;
          background: #272727;
          color: #ACAC60;
          font-size: 13pt;
          padding-left:0.4em;
          padding-right:0.4em;
          padding-top:0.3em;
          padding-bottom:0.3em;
      }

      .explanation {
          color: #777777;
          font-size: 12pt;
          margin-bottom: 1em;
      }

      .explanation2 {
          color: #777777;
          font-size: 12pt;
          margin-bottom: 0.1em;
      }

      table {
          border-width: 0;
          table-layout: fixed;
          font-family: Segoe UI Light;
          letter-spacing: 0.02em;
          background-color: #181818;
          color: #f0f0f0;
      }

      .even { background: #272727; }
      .odd { background: #1E1E1E; }
      .even.suspend { background: #1A1A28; }
      .odd.suspend { background: #1A1A2C; }

      thead {
          font-family: Segoe UI Semibold;
          font-size: 85%;
          color: #BCBCBC;
      }

      text {
          font-size: 12pt;
          font-family: Segoe UI Light;
          fill: #11EEF4;
      }

      .centered { text-align: center; }

      .label {
          font-family: Segoe UI Semibold;
          font-size: 85%;
          color: #BCBCBC;
      }

      .dc.even { background: #40182C; }
      .dc.odd { background: #30141F; }

      td.colBreak {
          padding: 0;
          width: 0.15em;
      }

      td.state { text-align: center; }

      td.hms {
          font-family: Segoe UI Symbol;
          text-align: right;
          padding-right: 3.4em;
      }

      td.dateTime { font-family: Segoe UI Symbol; }
      td.nullValue { text-align: center; }

      td.percent {
          font-family: Segoe UI Symbol;
          text-align: right;
          padding-right: 2.5em;
      }

      col:first-child { width: 13em; }
      col.col2 { width: 10.4em; }
      col.percent { width: 7.5em; }

      td.mw {
          text-align: right;
          padding-right: 2.5em;
      }

      td.acdc { text-align: center; }

      span.date {
          display: inline-block;
          width: 5.5em;
      }

      span.time {
          text-align: right;
          width: 4.2em;
          display: inline-block;
      }

      text { font-family: Segoe UI Symbol; }

      .noncontigbreak {
          height: 0.3em;
          background-color: #1A1A28;
      }
    </style>
  </xsl:template>

  <xsl:template name="jsDateUtil">
    <xsl:text disable-output-escaping="yes">
    // Formats a number using the current locale (to handle the 1000's separator).
    // The result is rounded so no decimal point is shown.
    function numberToLocaleString(value) {
        var localeString = Math.round(parseFloat(value + '')).toLocaleString();
        return localeString.substring(0, localeString.indexOf('.'));
    }

    function padLeft(number, length) {
        var str = '' + number;
        while (str.length &lt; length) {
            str = '0' + str;
        }

        return str;
    }

    // Returns the number of milliseconds between 2 date-times represented as strings.
    function msBetween(startTime, endTime) {
        return startTime &gt; endTime
               ? msBetween(endTime, startTime)
               : parseDateTime(endTime) - parseDateTime(startTime);
    }

    var dateFormat = /(\d{4})-(\d{2})-(\d{2})[T](\d{2}):(\d{2}):(\d{2})/

    // Parses a date-time string and returns a Date (i.e. number of milliseconds)
    function parseDateTime(value) {
        if (!value) {
            return 0;
        }

        var match = dateFormat.exec(value)
        if (!match) {
            return 0;
        }

        return Date.parse(match[1] + '/' + match[2] + '/' +
                          match[3] + ' ' + match[4] + ':' +
                          match[5] + ':' + match[6])
    }

    // Parses just the date portion of a date-time string and returns a Date
    // (i.e. number of milliseconds)
    function parseDate(value) {
        if (!value) {
            return 0;
        }

        var match = dateFormat.exec(value)
        if (!match) {
            return 0;
        }

        return Date.parse(match[1] + '/' + match[2] + '/' + match[3])
    }

    var durationFormat = /P((\d+)D)?T((\d+)H)?((\d+)M)?(\d+)S/

    // Convert a string of the form P10DT1H15M40S to a count of milliseconds
    function parseDurationToMs(value) {
        var match = durationFormat.exec(value)
        if (!match) {
            return 0
        }

        var days = parseInt(match[2] || '0');
        var hrs = parseInt(match[4] || '0');
        var mins = parseInt(match[6] || '0');
        var secs = parseInt(match[7] || '0');
        return ((((((days * 24) + hrs) * 60) + mins) * 60) +  secs) * 1000;
    }

    // Converts milliseconds to days
    function msToDays(ms) {
        return (ms / 1000 / 60 / 60 / 24);
    }

    function daysToMs(days) {
        return (days * 24 * 60 * 60 * 1000);
    }

    // Formats a number of milliseconds as h:mm:ss
    function formatDurationMs(value) {
        var ms = parseInt(value);
        var secs = ms / 1000;
        var mins = secs / 60;
        var hrs = Math.floor(mins / 60);
        mins = Math.floor(mins % 60);
        secs = Math.floor(secs % 60);
        return hrs + ':' + padLeft(mins,2) + ':' + padLeft(secs,2);
    }

    // Converts a millisecond timestamp to a day and month string
    // Note: dayOffset is forward from date.
    function dateToDayAndMonth(ms, dayOffset) {
        var adjustedDate = new Date(ms + (dayOffset * 24 * 60 * 60 * 1000));
        return padLeft(adjustedDate.getMonth() + 1, 2) + "-" +
               padLeft(adjustedDate.getDate(), 2);
    }

    // Takes a millisecond timestamp and returns a new millisecond timestamp
    // rounded down to the current day.
    function dateFloor(ms) {
        var dt = new Date(ms);
        return Date.parse(dt.getFullYear() + '/' + (dt.getMonth() + 1) + '/' + dt.getDate());
    }
    </xsl:text>
  </xsl:template>

  <xsl:template name="jsTimegraph">
    <xsl:text disable-output-escaping="yes">
    Timegraph = {
        axisTop: 9.5,
        axisRight: 24.5,
        axisBottom: 25.5,
        axisLeft: 25.5,
        ticks: 10,

        // Maximum number of 24 hour ticks for showing 12 and 6 hour ticks

        ticks12Hour: 8,
        ticks6Hour: 4,

        // Shading

        lineColor: "#B82830",
        shadingColor: "#4d1d35",

        precompute: function (graph) {
            var canvas = graph.canvas;
            var data = graph.data;
            var min = 0;
            var max = 0;

            graph.height = canvas.height - Timegraph.axisTop - Timegraph.axisBottom;
            graph.width = canvas.width - Timegraph.axisLeft - Timegraph.axisRight;
            for (var i = 0; i &lt; data.length; i++) {
                data[i].t0 = parseDateTime(data[i].x0);
                data[i].t1 = parseDateTime(data[i].x1);

                if (i == 0) {
                    min = data[i].t0;
                    max = data[i].t1;
                }

                if (data[i].t0 &lt; min) {
                    min = data[i].t0;
                }

                if (data[i].t1 &gt; max) {
                    max = data[i].t1;
                }

                data[i].yy0 =
                    Timegraph.axisTop + graph.height - data[i].y0 * graph.height;

                data[i].yy1 =
                    Timegraph.axisTop + graph.height - data[i].y1 * graph.height;
            }

            if (graph.startTime != null) {
                graph.startMs = parseDateTime(graph.startTime);

            } else {
                graph.startMs = min;
            }

            graph.endMs = max;
            graph.durationMs = max - min;
        },

        drawFrame: function (graph) {
            var canvas = graph.canvas;
            var context = graph.context;

            graph.width =
                canvas.width - Timegraph.axisRight - Timegraph.axisLeft;

            graph.height =
                canvas.height - Timegraph.axisTop - Timegraph.axisBottom;

            context.beginPath();
            context.moveTo(Timegraph.axisLeft, Timegraph.axisTop);
            context.lineTo(Timegraph.axisLeft + graph.width,
                           Timegraph.axisTop);

            context.lineTo(Timegraph.axisLeft + graph.width,
                           Timegraph.axisTop + graph.height);

            context.lineTo(Timegraph.axisLeft,
                           Timegraph.axisTop + graph.height);

            context.lineTo(Timegraph.axisLeft, Timegraph.axisTop);
            context.strokeStyle = "#c0c0c0";
            context.stroke();
        },

        drawRange: function (graph) {
            var canvas = graph.canvas;
            var context = graph.context;

            context.font = "12pt Segoe UI";
            context.fillStyle = "#00b0f0";
            context.fillText("%", 0, Timegraph.axisTop + 5, Timegraph.axisLeft);

            var tickSpacing = graph.height / 10;
            var offset = Timegraph.axisTop + tickSpacing;
            var tickValue = 90;
            for (var i = 0; i &lt; 9; i++) {
                context.beginPath();
                context.moveTo(Timegraph.axisLeft, offset);
                context.lineTo(Timegraph.axisLeft + graph.width,
                               offset);

                context.stroke();
                context.fillText(tickValue.toString(),
                                 0,
                                 offset + 5,
                                 Timegraph.axisLeft);

                offset += tickSpacing;
                tickValue -= 10;
            }
        },

        drawDomain: function (graph, start, end) {
            var canvas = graph.canvas;
            var context = graph.context;
            var data = graph.data;
            var duration = end - start;
            if ((end &lt; start)) {
                return;
            }

            var startDay = dateFloor(start);
            var t0 = startDay;
            var t1 = dateFloor(end);
            var dayOffset = 0;
            if (start &gt; t0) {
                t0 = t0 + daysToMs(1);
                dayOffset++;
            }

            if (t0 &gt;= t1) {
                return;
            }

            var increment =
                Math.max(Math.floor((t1 - t0) / daysToMs(Timegraph.ticks)), 1);

            var incrementMs = daysToMs(increment);
            var spacing = (incrementMs / duration) * graph.width;
            var offset = (t0 - start) / duration;
            var ticksCount = Math.floor((t1 - t0) / incrementMs);
            for (offset = offset * graph.width + Timegraph.axisLeft;
                 offset &lt; (graph.width + Timegraph.axisLeft);
                 offset += spacing) {

                context.beginPath();
                context.moveTo(offset, Timegraph.axisTop);
                context.lineTo(offset, Timegraph.axisTop + graph.height);
                context.stroke();
                context.fillText(dateToDayAndMonth(startDay, dayOffset),
                                 offset,
                                 Timegraph.axisTop + graph.height + 15,
                                 spacing);

                dayOffset += increment;
            }
        },

        plot: function (graph, start, end) {
            var canvas = graph.canvas;
            var context = graph.context
            var data = graph.data;

            if ((end &lt; start)) {
                return;
            }

            var duration = end - start;
            Timegraph.drawDomain(graph, start, end);
            context.fillStyle = Timegraph.shadingColor;
            for (var i = 0; i &lt; data.length - 1; i++) {
                if ((data[i].t0 &lt; start) || (data[i].t0 &gt; end) ||
                    (data[i].t1 &gt; end)) {

                    continue;
                }

                var x1 = (data[i].t0 - start) / duration;
                x1 = x1 * graph.width + Timegraph.axisLeft;

                var x2 = (data[i].t1 - start) / duration;
                x2 = x2 * graph.width + Timegraph.axisLeft;

                context.globalAlpha = 0.3;
                context.fillRect(x1, Timegraph.axisTop, (x2 - x1), graph.height);
                context.globalAlpha = 1;
                context.beginPath();
                context.strokeStyle = Timegraph.lineColor;
                context.lineWidth = 1.5;
                context.moveTo(x1, data[i].yy0);
                context.lineTo(x2, data[i].yy1);
                context.stroke();
            }
        },

        draw: function (graph) {
            var canvas = document.getElementById(graph.element);
            if (canvas == null) {
                return;
            }

            var context = canvas.getContext('2d');
            if (context == null) {
                return;
            }

            graph.width = 0;
            graph.height = 0;
            graph.context = context;
            graph.canvas = canvas;

            Timegraph.precompute(graph);
            Timegraph.drawFrame(graph);
            Timegraph.drawRange(graph);
            Timegraph.plot(graph, graph.startMs, graph.endMs);
        }
    };
    </xsl:text>
  </xsl:template>

  <xsl:template name="javascript">
    <xsl:param name="energyDrains" />

    <script type="text/javascript">
    <xsl:call-template name="jsDateUtil" />
    <xsl:call-template name="jsTimegraph" />

    <xsl:apply-templates select="$energyDrains" mode="jsEnergyDrains" />

    <xsl:text disable-output-escaping="yes">
    function main() {
        Timegraph.draw({
            element: "drain-graph",
            data: drainGraphData,
            startTime: "</xsl:text><xsl:value-of select="$graphStart" /><xsl:text disable-output-escaping="yes">",
            endTime: "</xsl:text><xsl:value-of select="$reportInfo/bat:LocalScanTime" /><xsl:text disable-output-escaping="yes">",
        });
    }

    if (window.addEventListener != null) {
        window.addEventListener("load", main, false);

    } else if (window.attachEvent != null) {
        window.attachEvent("onload", main);
    }
    </xsl:text>
    </script>
  </xsl:template>

  <xsl:template match="bat:Drain" mode="jsEnergyDrains">
    <xsl:text>{ </xsl:text>
    <xsl:text>x0: "</xsl:text><xsl:value-of select="@LocalStartTimestamp" /><xsl:text>", </xsl:text>
    <xsl:text>x1: "</xsl:text><xsl:value-of select="@LocalEndTimestamp" /><xsl:text>", </xsl:text>
    <xsl:text>y0: </xsl:text><xsl:value-of select="@StartChargeCapacity div @StartFullChargeCapacity" /><xsl:text>, </xsl:text>
    <xsl:text>y1: </xsl:text><xsl:value-of select="@EndChargeCapacity div @EndFullChargeCapacity" /><xsl:text> </xsl:text>
    <xsl:text>}, &#xa;</xsl:text>
  </xsl:template>

  <xsl:template match="bat:EnergyDrains" mode="jsEnergyDrains">
    <xsl:text>
    drainGraphData = [
    </xsl:text>
    <xsl:apply-templates select="bat:Drain" mode="jsEnergyDrains" />
    <xsl:text>
    ];
    </xsl:text>
  </xsl:template>

  <!-- The top section of the report. Gives information about the system. -->
  <xsl:template name="header">
    <h1>
      Battery report
    </h1>
    <table style="margin-bottom: 6em;">
      <col />
      <tr>
        <td class="label">
          COMPUTER NAME
        </td>
        <td>
          <xsl:value-of select="$systemInfo/bat:ComputerName" />
        </td>
      </tr>
      <tr>
        <td class="label">
          SYSTEM PRODUCT NAME
        </td>
        <td>
          <xsl:value-of select="$systemInfo/bat:SystemManufacturer" />
          <xsl:text> </xsl:text>
          <xsl:value-of select="$systemInfo/bat:SystemProductName" />
        </td>
      </tr>
      <tr>
        <td class="label">
          BIOS
        </td>
        <td>
          <xsl:value-of select="$systemInfo/bat:BIOSVersion" />
          <xsl:text> </xsl:text>
          <xsl:value-of select="$systemInfo/bat:BIOSDate" />
        </td>
      </tr>
      <tr>
        <td class="label">
          OS BUILD
        </td>
        <td>
          <xsl:value-of select="$systemInfo/bat:OSBuild" />
        </td>
      </tr>
      <tr>
        <td class="label">
          PLATFORM ROLE
        </td>
        <td>
          <xsl:value-of select="$systemInfo/bat:PlatformRole" />
        </td>
      </tr>
      <tr>
        <td class="label">
          CONNECTED STANDBY
        </td>
        <td>
          <xsl:choose>
            <xsl:when test="$aoac">
              <xsl:text>Supported</xsl:text>
            </xsl:when>
            <xsl:otherwise>
              <xsl:text>Not supported</xsl:text>
            </xsl:otherwise>
          </xsl:choose>
        </td>
      </tr>
      <tr>
        <td class="label">
          REPORT TIME
        </td>
        <td class="dateTime">
          <xsl:call-template name="formatDateTime">
            <xsl:with-param name="dateTime" select="$localReportTime" />
          </xsl:call-template>
        </td>
      </tr>
    </table>
  </xsl:template>

  <!-- The list of installed batteries -->
  <xsl:template match="bat:Batteries" >
    <!-- Only look at "long term" batteries (i.e. not UPS batteries) -->
    <xsl:variable name="longTermBatts" select="bat:Battery[bat:LongTerm != 0]" />

    <h2>
      Installed batteries
    </h2>
    <div class="explanation">
      Information about each currently installed battery
    </div>

    <xsl:choose>
      <xsl:when test="count($longTermBatts) = 0">
        <!-- No batteries currently installed -->
        <div style="margin-top:1.5em;">
          <span class="nobatts">No batteries are currently installed</span>
        </div>
      </xsl:when>
      <xsl:otherwise>
        <table>
          <colgroup>
            <col style="width: 15em;" />
            <xsl:for-each select="$longTermBatts">
              <col style="width: 14em;" />
            </xsl:for-each>
          </colgroup>
          <thead>
            <tr>
              <td>
                <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
                <xsl:text> </xsl:text>
              </td>
              <xsl:for-each select="$longTermBatts">
                <td>
                  BATTERY
                  <xsl:value-of select="position()"/>
                </td>
              </xsl:for-each>
            </tr>
          </thead>
          <tr>
            <td>
              <span class="label">NAME</span>
            </td>
            <xsl:for-each select="$longTermBatts">
              <td>
                <xsl:call-template name="dashIfEmpty">
                  <xsl:with-param name="str" select="bat:Id"/>
                </xsl:call-template>
              </td>
            </xsl:for-each>
          </tr>
          <tr>
            <td>
              <span class="label">MANUFACTURER</span>
            </td>
            <xsl:for-each select="$longTermBatts">
              <td>
                <xsl:call-template name="dashIfEmpty">
                  <xsl:with-param name="str" select="bat:Manufacturer"/>
                </xsl:call-template>
              </td>
            </xsl:for-each>
          </tr>
          <tr>
            <td>
              <span class="label">SERIAL NUMBER</span>
            </td>
            <xsl:for-each select="$longTermBatts">
              <td>
                <xsl:call-template name="dashIfEmpty">
                  <xsl:with-param name="str" select="bat:SerialNumber"/>
                </xsl:call-template>
              </td>
            </xsl:for-each>
          </tr>
          <tr>
            <td>
              <span class="label">CHEMISTRY</span>
            </td>
            <xsl:for-each select="$longTermBatts">
              <td>
                <xsl:call-template name="dashIfEmpty">
                  <xsl:with-param name="str" select="bat:Chemistry"/>
                </xsl:call-template>
              </td>
            </xsl:for-each>
          </tr>
          <tr>
            <td>
              <span class="label">DESIGN CAPACITY</span>
            </td>

            <xsl:for-each select="$longTermBatts">
              <td>
                <xsl:choose>
                  <!-- If RelativeCapacity=1, the units reported for the battery are not mWh -->
                  <xsl:when test="bat:RelativeCapacity = 1">
                    -
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:call-template name="mWh">
                      <xsl:with-param name="value" select="bat:DesignCapacity"/>
                    </xsl:call-template>
                  </xsl:otherwise>
                </xsl:choose>
              </td>
            </xsl:for-each>
          </tr>

          <!-- Small break to hint that the next 2 values are special (they can change over time) -->
          <tr style="height:0.4em;"></tr>

          <tr>
            <td>
              <span class="label">FULL CHARGE CAPACITY</span>
            </td>
            <xsl:for-each select="$longTermBatts">
              <td>
                <xsl:choose>
                  <!-- If RelativeCapacity=1, the units reported for the battery are not mWh -->
                  <xsl:when test="bat:RelativeCapacity = 1">
                    -
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:call-template name="mWh">
                      <xsl:with-param name="value" select="bat:FullChargeCapacity"/>
                    </xsl:call-template>
                  </xsl:otherwise>
                </xsl:choose>
              </td>
            </xsl:for-each>
          </tr>
          <tr>
            <td>
              <span class="label">CYCLE COUNT</span>
            </td>
            <xsl:for-each select="$longTermBatts">
              <td>
                <xsl:call-template name="dashIfEmpty">
                  <xsl:with-param name="str" select="bat:CycleCount"/>
                </xsl:call-template>
              </td>
            </xsl:for-each>
          </tr>
        </table>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="bat:RecentUsage" mode="recentUsage">
    <h2>Recent usage</h2>
    <div class="explanation">
      Power states over the last <xsl:value-of select="$reportDuration" /> days
    </div>
    <table>
      <colgroup>
        <col />
        <col class="col2" />
        <col style="width: 4.2em;" />
        <col class="percent" />
        <col style="width: 11em;" />
      </colgroup>
      <thead>
        <tr>
          <td>
            START TIME
          </td>
          <td class="centered">
            STATE
          </td>
          <td class="centered">
            SOURCE
          </td>
          <td colspan="2"  class="centered">
            CAPACITY REMAINING
          </td>
        </tr>
      </thead>

      <xsl:choose>
        <xsl:when test="count(bat:UsageEntry)">
          <xsl:apply-templates select="bat:UsageEntry" mode="recentUsage"  />
        </xsl:when>
        <xsl:otherwise>
          <!-- No data. Show one line of dashes -->
          <tr class="even">
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
          </tr>
        </xsl:otherwise>
      </xsl:choose>

    </table>
  </xsl:template>

  <xsl:template match="bat:UsageEntry" mode="recentUsage">
    <tr>
      <xsl:choose>
        <xsl:when test="@BatteryChanged != 0">
          <xsl:call-template name="classEvenOdd">
            <xsl:with-param name="position" select="position()"/>
            <xsl:with-param name="otherClasses" select="'batt'"/>
          </xsl:call-template>
        </xsl:when>
        <xsl:when test="@EntryType = 'Suspend'">
          <xsl:call-template name="classEvenOdd">
            <xsl:with-param name="position" select="position()" />
            <xsl:with-param name="otherClasses" select="'suspend'" />
          </xsl:call-template>
        </xsl:when>
        <xsl:when test="@Ac = 0">
          <xsl:call-template name="classEvenOdd">
            <xsl:with-param name="position" select="position()" />
            <xsl:with-param name="otherClasses" select="'dc'" />
          </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
          <xsl:call-template name="classEvenOdd">
            <xsl:with-param name="position" select="position()" />
          </xsl:call-template>
        </xsl:otherwise>
      </xsl:choose>

      <td class="dateTime">
        <xsl:call-template name="formatDateTime">
          <xsl:with-param name="dateTime" select="@LocalTimestamp" />
          <xsl:with-param name="showDate" select ="js:parseDate(string(@LocalTimestamp)) != js:parseDate(string(preceding-sibling::*[1]/@LocalTimestamp))" />
        </xsl:call-template>
      </td>
      <td class="state">
        <xsl:apply-templates mode="toStateName" select="." />
      </td>
      <td class="acdc">
        <xsl:apply-templates mode="toPowerSourceName" select="." />
      </td>

      <!-- Capacity remaining -->
      <xsl:call-template name="percentCell">
        <xsl:with-param name="value" select="round(100 * @ChargeCapacity div @FullChargeCapacity)" />
      </xsl:call-template>

      <xsl:call-template name="mWhCell">
        <xsl:with-param name="value" select="@ChargeCapacity" />
      </xsl:call-template>

    </tr>
  </xsl:template>

  <xsl:template match="bat:EnergyDrains" mode="energyDrainGraph">
    <h2>Battery usage</h2>
    <div class="explanation">
      Battery drains over the last <xsl:value-of select="$reportDuration" /> days
    </div>

    <canvas id="drain-graph" width="864" height="400"></canvas>
  </xsl:template>

  <xsl:template match="bat:RecentUsage" mode="batteryUsage">
    <table>
      <colgroup>
        <col/>
        <col class="col2" />
        <col style="width: 10em;" />
        <col class="percent" />
        <col style="width: 11em;" />
      </colgroup>
      <thead>
        <tr>
          <td>
            START TIME
          </td>
          <td class="centered">
            STATE
          </td>
          <td class="centered">
            DURATION
          </td>
          <td class="centered" colspan="2">
            ENERGY DRAINED
          </td>
        </tr>
      </thead>

      <xsl:variable name="batteryUsageEntries" select="bat:UsageEntry[@Ac = '0' and (@EntryType = 'Active' or @EntryType = 'ConnectedStandby')]" />

      <xsl:choose>
        <xsl:when test="count(ms:node-set($batteryUsageEntries))">
          <xsl:apply-templates select="ms:node-set($batteryUsageEntries)" mode="batteryUsage"  />
        </xsl:when>
        <xsl:otherwise>
          <!-- No data. Show one line of dashes -->
          <tr class="even">
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
          </tr>
        </xsl:otherwise>
      </xsl:choose>

    </table>
  </xsl:template>

  <!-- Outputs the "Battery usage" table contents -->
  <xsl:template match="bat:UsageEntry" mode="batteryUsage">
    <tr>
      <xsl:call-template name="classEvenOdd">
        <xsl:with-param name="position" select="position()" />
        <xsl:with-param name="otherClasses" select="'dc'" />
      </xsl:call-template>
      <td class="dateTime">
        <xsl:call-template name="formatDateTime">
          <xsl:with-param name="dateTime" select="@LocalTimestamp" />
          <xsl:with-param name="showDate" select ="js:parseDate(string(@LocalTimestamp)) != js:parseDate(string(preceding-sibling::*[1]/@LocalTimestamp)) or position() = '1'" />
        </xsl:call-template>
      </td>
      <td class="state">
        <xsl:apply-templates mode="toStateName" select="." />
      </td>
      <td class="hms">
        <xsl:value-of select="js:formatDurationMs(string(@Duration div 10000))" />
      </td>

      <!-- Energy drained -->
      <xsl:call-template name="percentCell">
        <xsl:with-param name="value" select="round(100 * @Discharge div @FullChargeCapacity)" />
      </xsl:call-template>

      <xsl:call-template name="mWhCell">
        <xsl:with-param name="value" select="@Discharge" />
      </xsl:call-template>

    </tr>

    <!-- If the next entry is not running on batteries, include a small gap to make apparent that the usage
         isn't contiguous. -->
    <xsl:if test="position() != last() and @IsNextOnBattery != '1'">
      <tr class="noncontigbreak">
        <td colspan="5">
          <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
          <xsl:text> </xsl:text>
        </td>
      </tr>
    </xsl:if>
  </xsl:template>

  <!-- Outputs the Usage history report -->
  <xsl:template match="/bat:BatteryReport/bat:History" mode="usageHistory">
    <h2>
      Usage history
    </h2>
    <div class="explanation2">
      History of system usage on AC and battery
    </div>
    <table>
      <colgroup>
        <col/>
        <col class="col2" />
        <col style="width: 10em;" />
        <col style="" />
        <col style="width: 10em;" />
        <col style="width: 10em;" />
        <col style="" />
      </colgroup>
      <thead>
        <tr>
          <td>
            <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
            <xsl:text> </xsl:text>
          </td>
          <td colspan="2" class="centered">
            BATTERY DURATION
          </td>

          <!-- Break between columns -->
          <td class="colBreak" >
            <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
            <xsl:text> </xsl:text>
          </td>

          <td colspan="3" class="centered">
            AC DURATION
          </td>
        </tr>
        <tr>
          <td>
            PERIOD
          </td>
          <td class="centered">
            ACTIVE
          </td>
          <td class="centered">
            CONNECTED STANDBY
          </td>

          <!-- Break between columns -->
          <td class="colBreak" >
            <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
            <xsl:text> </xsl:text>
          </td>

          <td class="centered">
            ACTIVE
          </td>
          <td class="centered">
            CONNECTED STANDBY
          </td>
        </tr>
      </thead>

      <xsl:choose>
        <xsl:when test="count(bat:HistoryEntry)">
          <xsl:apply-templates select="bat:HistoryEntry" mode="usageHistory" />
        </xsl:when>
        <xsl:otherwise>
          <!-- No data. Show one line of dashes -->
          <tr class="even">
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <!-- Break between columns -->
            <td class="colBreak" >
              <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
              <xsl:text> </xsl:text>
            </td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
          </tr>
        </xsl:otherwise>
      </xsl:choose>

    </table>
  </xsl:template>

  <!-- Outputs a date range as 2 dates if the dates are more than 24 hours apart, otherwise the start date only -->
  <xsl:template match="/bat:BatteryReport/bat:History/bat:HistoryEntry" mode="dateRange">
    <xsl:value-of select="substring-before(@LocalStartDate, 'T')" />
    <xsl:if test="js:msBetween(string(@LocalStartDate), string(@LocalEndDate)) > (24 * 60 * 60 * 1000)">
      - <xsl:value-of select="substring-before(@LocalEndDate, 'T')" />
    </xsl:if>
  </xsl:template>

  <!-- Outputs a row in the Usage history report -->
  <xsl:template match="/bat:BatteryReport/bat:History/bat:HistoryEntry" mode="usageHistory">
    <tr>
      <xsl:call-template name="classEvenOdd">
        <xsl:with-param name="position" select="position()" />
      </xsl:call-template>
      <td class="dateTime">
        <xsl:apply-templates select="."  mode="dateRange" />
      </td>

      <xsl:variable name="ActiveDcTime" select="js:parseDurationToMs(string(@ActiveDcTime))" />
      <xsl:choose>
        <xsl:when test="$ActiveDcTime = 0">
          <td class="nullValue">-</td>
        </xsl:when>
        <xsl:otherwise>
          <td class="hms">
            <xsl:value-of select="js:formatDurationMs($ActiveDcTime)"/>
          </td>
        </xsl:otherwise>
      </xsl:choose>

      <xsl:variable name="CsDcTime" select="js:parseDurationToMs(string(@CsDcTime))" />
      <xsl:choose>
        <xsl:when test="$CsDcTime = 0">
          <td class="nullValue">-</td>
        </xsl:when>
        <xsl:otherwise>
          <td class="hms">
            <xsl:value-of select="js:formatDurationMs($CsDcTime)"/>
          </td>
        </xsl:otherwise>
      </xsl:choose>

      <!-- Break between columns -->
      <td class="colBreak" >
        <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
        <xsl:text> </xsl:text>
      </td>

      <xsl:variable name="ActiveAcTime" select="js:parseDurationToMs(string(@ActiveAcTime))" />
      <xsl:choose>
        <xsl:when test="$ActiveAcTime = 0">
          <td class="nullValue">-</td>
        </xsl:when>
        <xsl:otherwise>
          <td class="hms">
            <xsl:value-of select="js:formatDurationMs($ActiveAcTime)"/>
          </td>
        </xsl:otherwise>
      </xsl:choose>

      <xsl:variable name="CsAcTime" select="js:parseDurationToMs(string(@CsAcTime))" />
      <xsl:choose>
        <xsl:when test="$CsAcTime = 0">
          <td class="nullValue">-</td>
        </xsl:when>
        <xsl:otherwise>
          <td class="hms">
            <xsl:value-of select="js:formatDurationMs($CsAcTime)"/>
          </td>
        </xsl:otherwise>
      </xsl:choose>

    </tr>
  </xsl:template>

  <xsl:template match="/bat:BatteryReport/bat:History" mode="batteryCapacityHistory">
    <h2>
      Battery capacity history
    </h2>
    <div class="explanation">
      Charge capacity history of the system's batteries
    </div>
    <table>
      <colgroup>
        <col/>
        <col class="col2"/>
        <col style="width: 10em;" />
      </colgroup>
      <thead>
        <tr>
          <td>
            <span>PERIOD</span>
          </td>
          <td class="centered">
            FULL CHARGE CAPACITY
          </td>
          <td class="centered">
            DESIGN CAPACITY
          </td>
        </tr>
      </thead>


      <xsl:choose>
        <xsl:when test="count(bat:HistoryEntry)">
          <xsl:apply-templates select="bat:HistoryEntry" mode="batteryCapacityHistory" />
        </xsl:when>
        <xsl:otherwise>
          <!-- No data. Show one line of dashes -->
          <tr class="even">
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
          </tr>
        </xsl:otherwise>
      </xsl:choose>

    </table>
  </xsl:template>

  <!-- Outputs a row in the Battery capacity history report -->
  <xsl:template match="/bat:BatteryReport/bat:History/bat:HistoryEntry" mode="batteryCapacityHistory">
    <tr>
      <xsl:call-template name="classEvenOdd">
        <xsl:with-param name="position" select="position()" />
      </xsl:call-template>
      <td class="dateTime">
        <xsl:apply-templates select="."  mode="dateRange" />
      </td>
      <xsl:call-template name="mWhCell">
        <xsl:with-param name="value" select="@FullChargeCapacity"/>
      </xsl:call-template>
      <xsl:call-template name="mWhCell">
        <xsl:with-param name="value" select="@DesignCapacity"/>
      </xsl:call-template>
    </tr>
  </xsl:template>

  <!-- Outputs the Battery life estimates report -->
  <xsl:template match="/bat:BatteryReport/bat:History" mode="batteryLifeEstimates">
    <h2>
      Battery life estimates
    </h2>
    <div class="explanation2">
      Battery life estimates based on observed drains
    </div>
    <table>
      <colgroup>
        <col/>
        <col class="col2"/>
        <col style="width: 10em;" />
        <col style="" />
        <col style="width: 10em;" />
        <col style="width: 10em;" />
        <col style="width: 10em;" />
      </colgroup>
      <thead>
        <tr class="rowHeader">
          <td>
            <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
            <xsl:text> </xsl:text>
          </td>
          <td colspan="2" class="centered">
            AT FULL CHARGE
          </td>

          <!-- Break between columns -->
          <td class="colBreak" >
            <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
            <xsl:text> </xsl:text>
          </td>

          <td colspan="2" class="centered">
            AT DESIGN CAPACITY
          </td>
        </tr>
        <tr class="rowHeader">
          <td>
            PERIOD
          </td>
          <td class="centered">
            <span>ACTIVE</span>
          </td>
          <td class="centered">
            <span>CONNECTED STANDBY</span>
          </td>

          <!-- Break between columns -->
          <td class="colBreak" >
            <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
            <xsl:text> </xsl:text>
          </td>

          <td class="centered">
            <span>ACTIVE</span>
          </td>
          <td class="centered">
            <span>CONNECTED STANDBY</span>
          </td>
        </tr>
      </thead>

      <xsl:choose>
        <xsl:when test="count(bat:HistoryEntry)">
          <xsl:apply-templates select="bat:HistoryEntry" mode="batteryLifeEstimates" />
        </xsl:when>
        <xsl:otherwise>
          <!-- No data. Show one line of dashes -->
          <tr class="even">
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <!-- Break between columns -->
            <td class="colBreak" >
              <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
              <xsl:text> </xsl:text>
            </td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
          </tr>
        </xsl:otherwise>
      </xsl:choose>

    </table>
    <div class="explanation2" style="margin-top: 1em; margin-bottom: 0.4em;">
      Current estimate of battery life based on all observed drains since OS install
    </div>
    <table >
      <colgroup>
        <col />
        <col class="col2"/>
        <col style="width: 10em;" />
        <col style="" />
        <col style="width: 10em;" />
        <col style="width: 10em;" />
        <col style="width: 10em;" />
      </colgroup>
      <tr class="even"  style="vertical-align:top">
        <td>
          Since OS install
        </td>
        <xsl:variable name="runtimeEstimates" select="/bat:BatteryReport/bat:RuntimeEstimates"/>
        <xsl:variable name="fullChargeActiveRuntimeEstimate" select="js:parseDurationToMs(string($runtimeEstimates/bat:FullChargeCapacity/bat:ActiveRuntime))" />
        <xsl:variable name="fullChargeConnectedStandbyRuntimeEstimate" select="js:parseDurationToMs(string($runtimeEstimates/bat:FullChargeCapacity/bat:ConnectedStandbyRuntime))" />
        <xsl:variable name="designActiveRuntimeEstimate" select="js:parseDurationToMs(string($runtimeEstimates/bat:DesignCapacity/bat:ActiveRuntime))" />
        <xsl:variable name="designConnectedStandbyRuntimeEstimate" select="js:parseDurationToMs(string($runtimeEstimates/bat:DesignCapacity/bat:ConnectedStandbyRuntime))" />

        <xsl:choose>
          <xsl:when test="$fullChargeActiveRuntimeEstimate = 0">
            <td class="nullValue">-</td>
          </xsl:when>
          <xsl:otherwise>
            <td class="hms">
              <xsl:value-of select="js:formatDurationMs($fullChargeActiveRuntimeEstimate)"/>
            </td>
          </xsl:otherwise>
        </xsl:choose>

        <xsl:choose>
          <xsl:when test="$fullChargeConnectedStandbyRuntimeEstimate = 0">
            <td class="nullValue">-</td>
          </xsl:when>
          <xsl:otherwise>
            <td class="hms">
              <div style="height:1em;">
                <xsl:value-of select="js:formatDurationMs($fullChargeConnectedStandbyRuntimeEstimate)"/>
              </div>
              <span style="font-size:9pt; ">
                <xsl:call-template name="percent">
                  <xsl:with-param name="value" select="round(5760000000 div $fullChargeConnectedStandbyRuntimeEstimate)" />
                </xsl:call-template>
                / 16 h
              </span>
            </td>
          </xsl:otherwise>
        </xsl:choose>

        <!-- Break between columns -->
        <td class="colBreak" >
          <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
          <xsl:text> </xsl:text>
        </td>

        <xsl:choose>
          <xsl:when test="$designActiveRuntimeEstimate = 0">
            <td class="nullValue">-</td>
          </xsl:when>
          <xsl:otherwise>
            <td class="hms">
              <xsl:value-of select="js:formatDurationMs($designActiveRuntimeEstimate)"/>
            </td>
          </xsl:otherwise>
        </xsl:choose>

        <xsl:choose>
          <xsl:when test="$designConnectedStandbyRuntimeEstimate= 0">
            <td class="nullValue">-</td>
          </xsl:when>
          <xsl:otherwise>
            <td class="hms">
              <div style="height:1em;">
                <xsl:value-of select="js:formatDurationMs($designConnectedStandbyRuntimeEstimate)"/>
              </div>
              <span style="font-size:9pt; ">
                <xsl:call-template name="percent">
                  <xsl:with-param name="value" select="round(5760000000 div $designConnectedStandbyRuntimeEstimate)" />
                </xsl:call-template>
                / 16 h
              </span>
            </td>
          </xsl:otherwise>
        </xsl:choose>


      </tr>
    </table>
  </xsl:template>

  <!-- Outputs a row in the Battery life estimates report -->
  <xsl:template match="bat:HistoryEntry" mode="batteryLifeEstimates">

    <xsl:variable name="fullChargeActiveRuntimeEstimate" select="js:parseDurationToMs(string(@EstimatedFullChargeActiveTime))" />
    <xsl:variable name="fullChargeConnectedStandbyRuntimeEstimate" select="js:parseDurationToMs(string(@EstimatedFullChargeCsTime))" />
    <xsl:variable name="designActiveRuntimeEstimate" select="js:parseDurationToMs(string(@EstimatedDesignActiveTime))" />
    <xsl:variable name="designConnectedStandbyRuntimeEstimate" select="js:parseDurationToMs(string(@EstimatedDesignCsTime))" />


    <tr style="vertical-align:top">
      <xsl:call-template name="classEvenOdd">
        <xsl:with-param name="position" select="position()" />
      </xsl:call-template>
      <td class="dateTime">
        <xsl:apply-templates select="."  mode="dateRange" />
      </td>

      <xsl:choose>
        <xsl:when test="$fullChargeActiveRuntimeEstimate = 0">
          <td class="nullValue">-</td>
        </xsl:when>
        <xsl:otherwise>
          <td class="hms">
            <xsl:value-of select="js:formatDurationMs($fullChargeActiveRuntimeEstimate)"/>
          </td>
        </xsl:otherwise>
      </xsl:choose>

      <xsl:choose>
        <xsl:when test="$fullChargeConnectedStandbyRuntimeEstimate= 0">
          <td class="nullValue">-</td>
        </xsl:when>
        <xsl:otherwise>
          <td class="hms">
            <div style="height:1em;">
              <xsl:value-of select="js:formatDurationMs($fullChargeConnectedStandbyRuntimeEstimate)"/>
            </div>
            <span style="font-size:9pt; ">
              <xsl:call-template name="percent">
                <xsl:with-param name="value" select="round(5760000000 div $fullChargeConnectedStandbyRuntimeEstimate)" />
              </xsl:call-template>
              / 16 h
            </span>
          </td>
        </xsl:otherwise>
      </xsl:choose>

      <!-- Break between columns -->
      <td class="colBreak" >
        <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
        <xsl:text> </xsl:text>
      </td>


      <xsl:choose>
        <xsl:when test="$designActiveRuntimeEstimate = 0">
          <td class="nullValue">-</td>
        </xsl:when>
        <xsl:otherwise>
          <td class="hms">
            <xsl:value-of select="js:formatDurationMs($designActiveRuntimeEstimate)"/>
          </td>
        </xsl:otherwise>
      </xsl:choose>

      <xsl:choose>
        <xsl:when test="$designConnectedStandbyRuntimeEstimate= 0">
          <td class="nullValue">-</td>
        </xsl:when>
        <xsl:otherwise>
          <td class="hms">
            <div style="height:1em;">
              <xsl:value-of select="js:formatDurationMs($designConnectedStandbyRuntimeEstimate)"/>
            </div>
            <span style="font-size:9pt; ">
              <xsl:call-template name="percent">
                <xsl:with-param name="value" select="round(5760000000 div $designConnectedStandbyRuntimeEstimate)" />
              </xsl:call-template>
              / 16 h
            </span>
          </td>
        </xsl:otherwise>
      </xsl:choose>

    </tr>
  </xsl:template>


  <!-- Matches the root node. This starts the XSL processing. -->
  <xsl:template match="/" >
    <html>
      <head>
        <!-- Support the latest IE -->
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />

        <!-- All times are displayed using local time. Store the offset at which the report was generated in
             case someone needs to calculate the UTC times (although this is not entirely sufficient if the
             machine has moved timezones during the report period. -->
        <meta name="ReportUtcOffset" content="{$reportInfo/bat:UtcOffset}" />

        <title>Battery report</title>

        <!-- CSS styles -->
        <xsl:call-template name="css" />

        <!-- JavaScript -->
        <xsl:call-template name="javascript">
          <xsl:with-param name="energyDrains" select="/bat:BatteryReport/bat:EnergyDrains" />
        </xsl:call-template>
      </head>

      <body>

        <!-- Describe the machine -->
        <xsl:call-template name="header" />

        <!-- Installed batteries -->
        <xsl:apply-templates select="/bat:BatteryReport/bat:Batteries" />

        <!-- Recent usage-->
        <xsl:apply-templates select="/bat:BatteryReport/bat:RecentUsage" mode="recentUsage" />

        <!-- Usage Graph -->
        <xsl:apply-templates select="/bat:BatteryReport/bat:EnergyDrains" mode="energyDrainGraph" />

        <!-- Battery usage-->
        <xsl:apply-templates select="/bat:BatteryReport/bat:RecentUsage" mode="batteryUsage" />

        <xsl:variable name="history" select="/bat:BatteryReport/bat:History" />

        <!-- Usage history -->
        <xsl:apply-templates select="$history" mode="usageHistory" />

        <!-- Battery capacity history -->
        <xsl:apply-templates select="$history" mode="batteryCapacityHistory" />

        <!-- Battery life estimates -->
        <xsl:apply-templates select="$history" mode="batteryLifeEstimates" />
        <br />
        <br />
        <br />
      </body>
    </html>
  </xsl:template>

  <!-- Formats a date-time for display -->
  <xsl:template name="formatDateTime">
    <xsl:param name="dateTime"/>
    <xsl:param name="showDate" select="true()" />
    <xsl:variable name="date" select="substring-before($dateTime, 'T')"/>
    <xsl:variable name="time" select="translate(substring-after($dateTime, 'T'), 'T ', '')"/>

    <span class="date">
      <xsl:if test="$showDate">
        <xsl:value-of select="$date"/>
      </xsl:if>
      <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
      <xsl:text> </xsl:text>
    </span>
    <span class="time">
      <xsl:value-of select="$time"/>
    </span>
  </xsl:template>

  <!-- Outputs the given string, or a dash ('-') if the string is empty -->
  <xsl:template name="dashIfEmpty">
    <xsl:param name="str"/>
    <xsl:variable name="s" select="normalize-space($str)" />
    <xsl:choose>
      <xsl:when test="string-length($s) = 0">
        -
      </xsl:when>
      <xsl:when test="$s = '0'">
        -
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$s"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Formats a mWh value -->
  <xsl:template name="mWh">
    <xsl:param name="value"/>
    <xsl:variable name="number" select="number($value)" />
    <xsl:choose>
      <!-- Test for not NaN, not 0, and not Infinity -->
      <xsl:when test="$number != 0 and $number = $number and $number != (1 div 0) and $number != (-1 div 0)">
        <xsl:value-of select="js:numberToLocaleString($number)"/> mWh
      </xsl:when>
      <xsl:otherwise>
        -
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Formats a mWh value for a table cell -->
  <xsl:template name="mWhCell">
    <xsl:param name="value"/>
    <xsl:variable name="number" select="number($value)" />
    <xsl:choose>
      <!-- Test for not NaN, not 0, and not Infinity -->
      <xsl:when test="$number != 0 and $number = $number and $number != (1 div 0) and $number != (-1 div 0)">
        <td class="mw">
          <xsl:value-of select="js:numberToLocaleString($number)"/> mWh
        </td>
      </xsl:when>
      <xsl:otherwise>
        <td class="nullValue">-</td>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Formats a % value -->
  <xsl:template name="percent">
    <xsl:param name="value"/>
    <xsl:choose>
      <xsl:when test="$value &gt; 0 and $value &lt; (1 div 0)">
        <xsl:value-of select="$value"/> %
      </xsl:when>
      <xsl:otherwise>-</xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Formats a % value for a table cell -->
  <xsl:template name="percentCell">
    <xsl:param name="value" />
    <xsl:choose>
      <xsl:when test="$value &gt; 0 and $value &lt; (1 div 0)">
        <td class="percent">
          <xsl:value-of select="$value"/> %
        </td>
      </xsl:when>
      <xsl:otherwise>
        <td class="nullValue">-</td>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <ms:script implements-prefix="js">
    <![CDATA[
    // Formats a number using the current locale (to handle the 1000's separator).
    // The result is rounded so no decimal point is shown.
    function numberToLocaleString(value) {
      // Work out the decimal separator
      var _sep = /\./.test((1.1).toLocaleString())? '.' : ',';
      // Regular expression to trim decimal places
      var re = new RegExp( '\\' + _sep + '\\d+$');
      return Math.round(value).toLocaleString().replace(re,'');
    }

    function padLeft(number, length) {
      var str = '' + number;
      while (str.length < length) {
        str = '0' + str;
      }
      return str;
    }

    // Returns the number of milliseconds between 2 date-times represented as strings.
    function msBetween(startTime, endTime) {
      return startTime > endTime
          ? msBetween(endTime, startTime)
          : parseDateTime(endTime) - parseDateTime(startTime);
    }


    var dateFormat = /(\d{4})-(\d{2})-(\d{2})[T](\d{2}):(\d{2}):(\d{2})/

    // Parses a date-time string and returns a Date (i.e. number of milliseconds)
    function parseDateTime(value) {
      if (!value) {
        return 0;
      }
      var match = dateFormat.exec(value)
      if (!match) {
        return 0;
      }
      return Date.parse(match[1] + '/' + match[2] + '/' + match[3] + ' ' + match[4] + ':' + match[5] + ':' + match[6])
    }

    // Parses just the date portion of a date-time string and returns a Date (i.e. number of milliseconds)
    function parseDate(value) {
      if (!value) {
        return 0;
      }
      var match = dateFormat.exec(value)
      if (!match) {
        return 0;
      }
      return Date.parse(match[1] + '/' + match[2] + '/' + match[3])
    }

    var durationFormat = /P((\d+)D)?T((\d+)H)?((\d+)M)?(\d+)S/

    // Convert a string of the form P10DT1H15M40S to a count of milliseconds
    function parseDurationToMs(value) {
      var match = durationFormat.exec(value)
      if (!match) {
        return 0
      }
      var days = parseInt(match[2] || '0');
      var hrs = parseInt(match[4] || '0');
      var mins = parseInt(match[6] || '0');
      var secs = parseInt(match[7] || '0');
      return ((((((days * 24) + hrs) * 60) + mins) * 60) +  secs) * 1000;
    }

    // Formats a number of milliseconds as h:mm:ss
    function formatDurationMs(value) {
      var ms = parseInt(value);
      var secs = ms / 1000;
      var mins = secs / 60;
      var hrs = Math.floor(mins / 60);
      mins = Math.floor(mins % 60);
      secs = Math.floor(secs % 60);
      return hrs + ':' + padLeft(mins,2) + ':' + padLeft(secs,2);
    }

    // Converts a string representing a date time to a day and month string
    function dateToDayAndMonth(date, dayOffset) {
      var adjustedDate = new Date(parseDate(date) - (dayOffset * 24 * 60 * 60 * 1000));
      return padLeft(adjustedDate.getMonth() + 1, 2) + "-" + adjustedDate.getDate();
    }
    ]]>
  </ms:script>
</xsl:stylesheet>


P<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:eew="http://schemas.microsoft.com/energy/2007" version="1.0">
    <xsl:output method="html" indent="yes"/>

    <xsl:template match="/">
        <html>
            <head>
                <style>
                    
                    body {
                        font-family: Verdana, Arial, Helvetica, sans-serif; 
                        font-size: x-small; 
                        margin-right:1.5em}

                    .log-entry {margin-bottom:1em;}

                    
                    .error-log-entry {background-color:#ffcccc; padding:4pt;}

                    
                    .warning-log-entry {background-color:#ffffc6; padding:4pt;}

                    
                    .info-log-entry {background-color:#ffffff; padding:4pt;}

                    
                    .log-entry-header {font-weight:bold;}

                    .log-entry-content {margin: 2pt; }

                    
                    .expander  {
                        display: block; 
                        left: 0em; 
                        width: 1em; 
                        float: left; 
                        color:red; 
                        font-family:'Courier New'; 
                        font-weight:bold; 
                        text-decoration:none;
                        padding-top:6pt;}

                    td {
                        font-size:x-small;
                        font-weight: bold;
                    }

                    .log-entry-content table {
;
                    }

                    .log-entry-content td {
                        padding: 3pt;
                    }

                    .detail-name {
                        font-weight:normal;
                    }

                <!-- error log entry --><!-- warning log entry --><!-- info log entry --><!-- log entry header line --><!-- button - contains +/-/nbsp --></style>
            </head>
            <body class="st">
                <xsl:apply-templates/>
            </body>

        </html>
    </xsl:template>

    <!-- Template for the root of the report -->
    <xsl:template match="eew:EnergyReport">
        <h2>Power Efficiency Diagnostics Report</h2>
       <table>
           <tr>
               <td class="detail-name">Computer Name</td>
               <td>
                   <xsl:value-of select="eew:Troubleshooter[@guid='c78b52e3-9cd7-4802-979c-57ca1283dafa']/eew:AnalysisLog/eew:LogEntry[@guid='3d053cee-9926-4ac0-a4e1-63ab80c63af0']/eew:Details/eew:Detail[@guid='300b5d9f-434e-45b0-80d2-4bd55b168ef3']/eew:Value"/>
               </td>
           </tr>
           <tr>
               <td class="detail-name">Scan Time</td>
               <td>
                   <xsl:value-of select="eew:ReportInformation/eew:ScanTime"/>
               </td>
           </tr>
           <tr>
               <td class="detail-name">Scan Duration</td>
               <td>
                   <xsl:value-of select="substring-before(substring-after(eew:ReportInformation/eew:ScanDuration, 'PT'), 'S')"/> seconds
               </td>
           </tr>
           <tr>
               <td class="detail-name">System Manufacturer</td>
               <td>
                   <xsl:value-of select="eew:Troubleshooter[@guid='c78b52e3-9cd7-4802-979c-57ca1283dafa']/eew:AnalysisLog/eew:LogEntry[@guid='3d053cee-9926-4ac0-a4e1-63ab80c63af0']/eew:Details/eew:Detail[@guid='a49d84bf-a8c7-4c26-8f54-eefccac2f084']/eew:Value"/>
               </td>
           </tr>
           <tr>
               <td class="detail-name">System Product Name</td>
               <td>
                   <xsl:value-of select="eew:Troubleshooter[@guid='c78b52e3-9cd7-4802-979c-57ca1283dafa']/eew:AnalysisLog/eew:LogEntry[@guid='3d053cee-9926-4ac0-a4e1-63ab80c63af0']/eew:Details/eew:Detail[@guid='ceddb6e2-626c-4efe-ae58-c7b241693909']/eew:Value"/>
               </td>
           </tr>
           <tr>
               <td class="detail-name">BIOS Date</td>
               <td>
                   <xsl:value-of select="eew:Troubleshooter[@guid='c78b52e3-9cd7-4802-979c-57ca1283dafa']/eew:AnalysisLog/eew:LogEntry[@guid='3d053cee-9926-4ac0-a4e1-63ab80c63af0']/eew:Details/eew:Detail[@guid='b586008a-e3ca-457a-8f48-30fe0de3facf']/eew:Value"/>
               </td>
           </tr>
           <tr>
               <td class="detail-name">BIOS Version</td>
               <td>
                   <xsl:value-of select="eew:Troubleshooter[@guid='c78b52e3-9cd7-4802-979c-57ca1283dafa']/eew:AnalysisLog/eew:LogEntry[@guid='3d053cee-9926-4ac0-a4e1-63ab80c63af0']/eew:Details/eew:Detail[@guid='c85bfef6-93e7-4f1a-a35d-20655dab095d']/eew:Value"/>
               </td>
           </tr>
           <tr>
               <td class="detail-name">OS Build</td>
               <td>
                   <xsl:value-of select="eew:Troubleshooter[@guid='c78b52e3-9cd7-4802-979c-57ca1283dafa']/eew:AnalysisLog/eew:LogEntry[@guid='3d053cee-9926-4ac0-a4e1-63ab80c63af0']/eew:Details/eew:Detail[@guid='31dc51fd-a872-4546-a54f-ae0da74cdf9f']/eew:Value"/>
               </td>
           </tr>
           <tr>
               <td class="detail-name">Platform Role</td>
               <td>
                   <xsl:value-of select="eew:Troubleshooter[@guid='c78b52e3-9cd7-4802-979c-57ca1283dafa']/eew:AnalysisLog/eew:LogEntry[@guid='3d053cee-9926-4ac0-a4e1-63ab80c63af0']/eew:Details/eew:Detail[@guid='8838163d-e78c-4858-9432-9b034382e9f6']/eew:Value"/>
               </td>
           </tr>
           <tr>
               <td class="detail-name">Plugged In</td>
               <td>
                   <xsl:value-of select="eew:Troubleshooter[@guid='c78b52e3-9cd7-4802-979c-57ca1283dafa']/eew:AnalysisLog/eew:LogEntry[@guid='3d053cee-9926-4ac0-a4e1-63ab80c63af0']/eew:Details/eew:Detail[@guid='9fd5343d-fcb1-42ac-9566-8a8e8409a60b']/eew:Value"/>
               </td>
           </tr>
           <tr>
               <td class="detail-name">Process Count</td>
               <td>
                   <xsl:value-of select="eew:Troubleshooter[@guid='c78b52e3-9cd7-4802-979c-57ca1283dafa']/eew:AnalysisLog/eew:LogEntry[@guid='3d053cee-9926-4ac0-a4e1-63ab80c63af0']/eew:Details/eew:Detail[@guid='d64ab9ff-6978-4c37-ac17-9494347b673b']/eew:Value"/>
               </td>
           </tr>
           <tr>
               <td class="detail-name">Thread Count</td>
               <td>
                   <xsl:value-of select="eew:Troubleshooter[@guid='c78b52e3-9cd7-4802-979c-57ca1283dafa']/eew:AnalysisLog/eew:LogEntry[@guid='3d053cee-9926-4ac0-a4e1-63ab80c63af0']/eew:Details/eew:Detail[@guid='375cbf0f-61d5-42b8-a0fd-16c198b7b32f']/eew:Value"/>
               </td>
           </tr>
           <tr>
               <td class="detail-name">Report GUID</td>
               <td>
                   {<xsl:value-of select="eew:ReportInformation/eew:ReportGuid"/>}
               </td>
           </tr>
       </table>
       <h3>Analysis Results</h3>
       <xsl:if test="eew:ReportInformation/eew:DroppedEvents &gt; 0 or eew:ReportInformation/eew:DroppedBuffers &gt; 0">
            Warning: Events were dropped during tracing. This may result in incomplete analysis results.
       </xsl:if>
       <!-- select all error log entries, then warning, then informational. -->
       <h4>Errors</h4>
       <xsl:apply-templates select="eew:Troubleshooter[@guid!='c78b52e3-9cd7-4802-979c-57ca1283dafa']/eew:AnalysisLog/eew:LogEntry[eew:Severity='Error']"/>
       <h4>Warnings</h4>
       <xsl:apply-templates select="eew:Troubleshooter[@guid!='c78b52e3-9cd7-4802-979c-57ca1283dafa']/eew:AnalysisLog/eew:LogEntry[eew:Severity='Warning']"/>
       <h4>Information</h4>
       <xsl:apply-templates select="eew:Troubleshooter[@guid!='c78b52e3-9cd7-4802-979c-57ca1283dafa']/eew:AnalysisLog/eew:LogEntry[eew:Severity='Informational']"/>
    </xsl:template>

    <!-- Template for individual analysis log table entries. --> 
    <xsl:template name="GenericLogEntry" match="eew:LogEntry">
        <div class="log-entry">
            <div>
                <xsl:attribute name="class">
                    <xsl:choose>
                        <xsl:when test="eew:Severity='Error'">
                            error-log-entry
                        </xsl:when>
                        <xsl:when test="eew:Severity='Warning'">
                            warning-log-entry
                        </xsl:when>
                        <xsl:otherwise>
                            info-log-entry
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:attribute>
                <div class="log-entry-header">
                    <xsl:value-of select="../../eew:Name"/>:<xsl:value-of select="eew:Name"/>
                </div>
                <div class="log-entry-content">
                    <div class="log-entry-description">
                        <xsl:value-of select="eew:Description"/>
                    </div>
                    <xsl:apply-templates/>
                    <span></span>
                </div>
            </div>
        </div>
    </xsl:template>

    <!-- Template for special-cased log entries -->

    <!-- Timer Resolution Stack -->
    <xsl:template match="eew:LogEntry[@guid='f84b604c-98bb-47ba-a789-75cde4996a87']">
        <!-- Apply the generic template if an outstanding timer request exists with the same PID. Otherwise, show nothing. -->
        <xsl:variable name="TimerStackProcessId" select="eew:Details/eew:Detail[@guid='01ee080e-57de-431b-8016-8354fb450f1b']/eew:Value"/>
        <xsl:if test="parent::*/eew:LogEntry[@guid='436954b1-cc2d-4740-9f97-23d1f2c1210e']/eew:Details/eew:Detail[@guid='0ce5eb38-d897-4749-8210-242e77718472'][eew:Value = $TimerStackProcessId]">
            <xsl:call-template name="GenericLogEntry"/>
        </xsl:if>
    </xsl:template>

    <!-- Template for generic analysis log table details. --> 
    
    <!-- Template for analysis log detail list. --> 
    <xsl:template match="eew:Details">
        <table>
            <xsl:apply-templates/>
        </table>
    </xsl:template>

    <!-- Template for generic analysis log table details. --> 
    <xsl:template match="eew:Detail">
        <tr>
            <td>
                <span class="detail-name">
                    <xsl:value-of select="eew:Name"/>
                </span>
            </td>
            <td> 
                <xsl:value-of select="eew:Value"/>
            </td>
        </tr>
    </xsl:template>

    <!-- Template for special-cased analysis log details -->

    <!-- Power Plan Personality.Personality -->
    <xsl:template match="eew:Detail[(@guid='fc84c527-7c74-42c0-a8c5-cc6e1a60b961') or (@guid='b7f44371-d8a6-423d-8417-f2a9a1028f7f')]">
        <tr>
            <td>
                <span class="detail-name">
                    <xsl:value-of select="eew:Name"/>
                </span>
            </td>
            <td> 
                <xsl:choose>
                    <xsl:when test="eew:Value=0">
                        Power Saver
                    </xsl:when>
                    <xsl:when test="eew:Value=1">
                        High Performance
                    </xsl:when>
                    <xsl:when test="eew:Value=2">
                        Balanced
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="eew:Value"/>
                    </xsl:otherwise>
                </xsl:choose>
            </td>
        </tr>
    </xsl:template>

    <!-- Active Power Plan.Plan GUID -->
    <xsl:template match="eew:Detail[@guid='abf6ffeb-c575-4031-87b6-0ef12a886fee']">
        <tr>
            <td>
                <span class="detail-name">
                    Plan Name
                </span>
            </td>
            <td>
                <xsl:choose>
                    <xsl:when test="eew:Value='{a1841308-3541-4fab-bc81-f71556f20b4a}'">
                        OEM Power Saver
                    </xsl:when>
                    <xsl:when test="eew:Value='{8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c}'">
                        OEM High Performance
                    </xsl:when>
                    <xsl:when test="eew:Value='{381b4222-f694-41f0-9685-ff5bb260df2e}'">
                        OEM Balanced
                    </xsl:when>
                    <xsl:otherwise>
                        Custom
                    </xsl:otherwise>
                </xsl:choose>
            </td>
        </tr>
        <tr>
            <td>
                <span class="detail-name">
                    <xsl:value-of select="eew:Name"/>
                </span>
            </td>
            <td> 
                <xsl:value-of select="eew:Value"/>
            </td>
        </tr>
    </xsl:template>

    <!-- Video Quality.Setting -->
    <xsl:template match="eew:Detail[(@guid='23438ed2-d803-4d94-8f66-cfbf094797e7') or (@guid='dc3d55c6-2f0c-4397-bdc4-d2d9a3148969')]">
        <tr>
            <td>
                <span class="detail-name">
                    <xsl:value-of select="eew:Name"/>
                </span>
            </td>
            <td> 
                <xsl:choose>
                    <xsl:when test="eew:Value=0">
                        Optimize for Video Quality
                    </xsl:when>
                    <xsl:when test="eew:Value=1">
                        Balance Video Quality and Power Savings
                    </xsl:when>
                    <xsl:when test="eew:Value=2">
                        Optimize for Power Savings
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="eew:Value"/>
                    </xsl:otherwise>
                </xsl:choose>
            </td>
        </tr>
    </xsl:template>


    <!-- Battery Information.Manufacture Date -->
    <xsl:template match="eew:Detail[@guid='1b9d5465-63f4-4c5d-8259-93effc455084']">
        <xsl:if test="eew:Value!=''">
            <tr>
                <td>
                    <span class="detail-name">
                        <xsl:value-of select="eew:Name"/>
                    </span>
                </td>
                <td> 
                    <xsl:value-of select="eew:Value"/>
                </td>
            </tr>
        </xsl:if>
    </xsl:template>

    <!-- Battery Information.Cycle Count -->
    <xsl:template match="eew:Detail[@guid='17d29a01-f010-4f66-bf60-c121e35cfc2b']">
        <xsl:if test="eew:Value!=''">
            <tr>
                <td>
                    <span class="detail-name">
                        <xsl:value-of select="eew:Name"/>
                    </span>
                </td>
                <td> 
                    <xsl:value-of select="eew:Value"/>
                </td>
            </tr>
        </xsl:if>
    </xsl:template>

    <!-- CPU Utilization.Module -->
    <xsl:template match="eew:Detail[@guid='75067548-7814-4e65-9533-13239cd92ecd']">
        <tr>
            <td> 
                <xsl:value-of select="eew:Value"/>
            </td>
            <td> 
                <xsl:value-of select="following-sibling::node()/eew:Value"/>
            </td>
        </tr>
    </xsl:template>

    <!-- CPU Utilization.Average Module Utilization -->
    <xsl:template match="eew:Detail[@guid='acd9c46d-e149-489a-876d-e1707ed15134']">
    </xsl:template>

    <!-- CPU Utilization.Average Utilization -->
    <xsl:template match="eew:Detail[@guid='9c0f7e30-e8b5-43dd-8c3e-c45bf3101fba']">
        <tr>
            <td>
                <span class="detail-name">
                    <xsl:value-of select="eew:Name"/>
                </span>
            </td>
            <td> 
                <xsl:value-of select="eew:Value"/>
            </td>
        </tr>
        <tr>
            <td>
                <span class="detail-name">
                    Module
                </span>
            </td>
            <td> 
                <span class="detail-name">
                    Average Module Utilization (%)
                </span>
            </td>
        </tr>
    </xsl:template>

    <!-- Timer Stack.Module -->
    <xsl:template match="eew:Detail[@guid='c3b5315f-40d8-47a4-ab56-70a237a8f78f']">
        <tr>
            <td>
                <span class="detail-name">
                    <xsl:if test="preceding-sibling::eew:Detail[1]/attribute::guid!='c3b5315f-40d8-47a4-ab56-70a237a8f78f'">
                        Calling Module Stack
                    </xsl:if>
                </span>
            </td>
            <td> 
                <xsl:if test="eew:Value=''">
                    Unknown Module
                </xsl:if>
                <xsl:value-of select="eew:Value"/>
            </td>
        </tr>
    </xsl:template>

    <!-- Platform Power Management Capabilities.Sx Disabled -->
    <xsl:template match="eew:Detail[(../../@guid='b1e58678-204e-4bd8-b902-09226248d3c7') or (../../@guid='5b2de68c-b12f-47f7-b0f2-394e731a7d02') or (../../@guid='87e0a483-b2fa-436e-b33b-1a00429fe90d') or (../../@guid='26d291ba-d3c9-4371-8fed-99dcb1429273')]">
        <xsl:if test="eew:Value='true'">
            <tr>
                <td>
                    <span>
                        <xsl:value-of select="eew:Name"/>
                    </span>
                </td>
                <td> 
                </td>
            </tr>
        </xsl:if>
    </xsl:template>



    <!-- Template to suppress ouputing raw node content. --> 
    <xsl:template match="*" priority="-9">
    </xsl:template>

</xsl:stylesheet>
P<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ms="urn:schemas-microsoft-com:xslt"
    xmlns:ssd="http://schemas.microsoft.com/systemsleepdiagnostics/2016"
    xmlns:js="http://microsoft.com/kernel"
    version="1.0">

    <xsl:output
        method="html"
        omit-xml-declaration="yes"
        indent="no"
        encoding="utf-16" />

    <xsl:variable name="reportInfo" select="/ssd:SystemSleepDiagnostics/ssd:ReportInformation" />
    <xsl:variable name="reportTime" select="string($reportInfo/ssd:ScanTime)" />
    <xsl:variable name="localReportTime" select="string($reportInfo/ssd:LocalScanTime)" />
    <xsl:variable name="reportDuration" select="$reportInfo/ssd:ReportDuration" />
    <xsl:variable name="graphStart" select="$reportInfo/ssd:LocalReportStartTime" />

    <!-- Creates the name of the state -->
    <xsl:template name="toSleepStartReason">
        <xsl:param name="reason" />
        <xsl:choose>
            <xsl:when test="$reason = 0">
                Button or Lid
            </xsl:when>
            <xsl:when test="$reason = 1">
                Thermal Zone
            </xsl:when>
            <xsl:when test="$reason = 2">
                Battery
            </xsl:when>
            <xsl:when test="$reason = 4">
                Application API
            </xsl:when>
            <xsl:when test="$reason = 5">
                Kernel API
            </xsl:when>
            <xsl:when test="$reason = 6">
                Hibernate from Sleep - Fixed Timeout
            </xsl:when>
            <xsl:when test="$reason = 7">
                System Idle
            </xsl:when>
            <xsl:when test="$reason = 10">
                Battery
            </xsl:when>
            <xsl:when test="$reason = 11">
                Hibernate from Sleep - User Away Predicted
            </xsl:when>
            <xsl:when test="$reason = 12">
                Hibernate from Sleep without Wake - User Away Predicted
            </xsl:when>
            <xsl:otherwise>
                Unknown reason
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <!-- Styles -->
    <xsl:template name="css">
        <style type="text/css">
            body {
            font-family: Segoe UI Light;
            letter-spacing: 0.02em;
            background-color: #ffffff;
            color: #000000;
            margin: 0em 5.5em 0em 5.5em;
            }

            h1 {
            color: #00b0f0;
            font-size: 42pt;
            }

            h2 {
            font-size: 15pt;
            color: #00b0f0;
            margin-top: 2em;
            margin-bottom: 0em;
            letter-spacing: 0.08em;
            }

            h3, h4, h5 {
            margin-top: 1em;
            margin-bottom: 0em;
            letter-spacing: 0.08em;
            }

            td {
            padding-left: 0.3em;
            padding-right: 0.3em;
            }

            .nobatts {
            margin-top: 1.5em;
            font-family: Segoe UI Semibold;
            background: #f0f0f0;
            color: #a0a0a0;
            font-size: 13pt;
            padding-left:0.4em;
            padding-right:0.4em;
            padding-top:0.3em;
            padding-bottom:0.3em;
            }

            .explanation {
            color: #777777;
            font-size: 12pt;
            margin-bottom: 1em;
            }

            .explanation2 {
            color: #777777;
            font-size: 12pt;
            margin-bottom: 0.1em;
            }

            table {
            border-width: 0;
            table-layout: fixed;
            font-family: Segoe UI Light;
            letter-spacing: 0.02em;
            color: #000000;
            margin-bottom: 10px;
            }

            table.defs { background-color: transparent; }

            caption {
            padding: 5px 0px 5px 0px;
            font-weight: bold;
            }

            thead {
            font-family: Segoe UI Semibold;
            font-size: 85%;
            }

            text {
            font-size: 12pt;
            font-family: Segoe UI Light;
            fill: #00b0f0;
            }

            .centered { text-align: center; }

            .label {
            font-family: Segoe UI Semibold;
            font-size: 85%;
            color: #acacac;
            }

            #legend {
            background-color: #fafafa;
            margin-bottom: 2.2em;
            border-spacing: 0;
            }

            #legend thead { background-color: #dfdfdf; }
            #legend td, #legend th {
            padding: 4px 5px 4px 5px;
            }

            #legend .spanner {
            text-align: center;
            background-color: #dfdfdf;
            font-size: 85%;
            font-weight: bold;
            padding: 3px;
            }

            #legend td.percent { text-align: left; }

            .graphline-none, .graphline-dotted, .graphline-solid, .graphline-neutral,
            .graphline-low, .graphline-moderate, .graphline-high {
            font-weight: bold;
            }

            .graphline-none { color: #7d7d7d; }
            .graphline-dotted { color: #7d7d7d; }
            .graphline-solid { color: #7d7d7d; }
            .graphline-neutral { color: #7d7d7d; }
            .graphline-low { color: #2a7a2a; }
            .graphline-moderate { color: #cc7e06; }
            .graphline-high { color: #970d00; }

            .top-blocker td, #summary-table td {
            padding: 0;
            }

            .top-blocker td a, #summary-table td a {
            padding: 0 0.3em 0 0.3em;
            display: block;
            height: 100%;
            }

            .top-blocker a:link, .top-blocker a:active, .top-blocker a:visited,
            #summary-table a:link, #summary-table a:active, #summary-table a:visited {
            text-decoration: none;
            color: #000000;
            }

            #summary-table th,
            .session-summary th,
            .top-blocker th,
            .pdc-phases th,
            .device-components th {
            background-color: transparent;
            }

            #summary-table tbody tr,
            .session-summary tbody tr,
            .top-blocker tbody tr,
            .device-components tbody tr,
            .pdc-phases tbody tr {
            background-color: #e0e0e0;
            }

            #summary-table .row-neutral,
            .session-summary .row-neutral,
            .top-blocker .row-neutral,
            .device-components .row-neutral,
            .pdc-phases .row-neutral {
            background-color: #e0e0e0;
            }

            #summary-table .row-low,
            .session-summary .row-low,
            .top-blocker .row-low,
            .device-components .row-low,
            .pdc-phases .row-low {
            background-color: #ace3ac;
            }

            #summary-table .row-moderate,
            .session-summary .row-moderate,
            .top-blocker .row-moderate,
            .device-components .row-moderate,
            .pdc-phases .row-moderate {
            background-color: #fcd69a;
            }

            #summary-table .row-high,
            .session-summary .row-high,
            .top-blocker .row-high,
            .device-components .row-high,
            .pdc-phases .row-high {
            background-color: #ffb2aa;
            }

            #summary-table .row-info,
            .session-summary .row-info,
            .top-blocker .row-info,
            .device-components .row-info,
            .pdc-phases .row-info {
            background-color: #86becb;
            }

            #summary-table tbody tr:hover,
            .top-blocker tbody tr:hover {
            background-color: #f0f0f0;
            }

            #summary-table .row-neutral:hover,
            .top-blocker .row-neutral:hover {
            background-color: #f0f0f0;
            }

            #summary-table .row-low:hover,
            .top-blocker .row-low:hover {
            background-color: #caedca;
            }

            #summary-table .row-moderate:hover,
            .top-blocker .row-moderate:hover {
            background-color: #fde5c0;
            }

            #summary-table .row-high:hover,
            .top-blocker .row-high:hover {
            background-color: #ffd5d1;
            }

            td.colBreak { padding: 0; width: 0.15em; }

            td.state { text-align: center; }
            td.chargeOrDrain { text-align: center; }
            td.percentLowPowerStateTime { text-align: center; }
            td.percent { font-family: Segoe UI Symbol; text-align: center; }
            td.hms { font-family: Segoe UI Symbol; text-align: center; }
            td.dateTime { font-family: Segoe UI Symbol; }
            td.blank { background-color: #ffffff; }
            td.nullValue { text-align: center; }
            td.center { text-align: center; }

            col.percent { width: 7.5em; }

            td.mw {
            font-family: Segoe UI Symbol;
            text-align: center;
            }

            td.acdc { text-align: center; }

            span.date {
            display: inline-block;
            width: 5.5em;
            }

            span.time {
            text-align: right;
            width: 4.2em;
            display: inline-block;
            }

            text { font-family: Segoe UI Symbol; }

            .noncontigbreak {
            height: 0.3em;
            background-color: #1A1A28;
            }

            div.analysis-container {
            margin-bottom: 10px;
            border: 1px solid #ffffff;
            }

            div.analysis-container h1 {
            padding: 10px;
            font-size: 14px;
            margin: 0px;
            cursor: pointer;
            }

            div.analysis-body, div.analysis-body-collapsed {
            padding: 10px;
            }

            div.analysis-body { display: block; }
            div.analysis-body-collapsed { display: none; }

            .analysis-base { background-color: #f7f7f7; }
            .analysis-base h1 { color: #a0a0a0; background-color: #d0d0d0; }
            .analysis-base h1:hover { background-color: #dfdfdf; }

            .analysis-neutral { background-color: #f0f0f0; }
            .analysis-neutral h1 { color: #a0a0a0; background-color: #d0d0d0; }
            .analysis-neutral h1:hover { background-color: #dfdfdf; }

            .analysis-high { background-color: #ffd5d1; }
            .analysis-high h1 { background-color: #ff8e83; color: #970d00; }
            .analysis-high h1:hover { background-color: #ffb2aa; }

            .analysis-moderate { background-color: #fde5c0; }
            .analysis-moderate h1 { background-color: #fbc674; color: #cc7e06; }
            .analysis-moderate h1:hover { background-color: #fcd69a; }

            .analysis-low { background-color: #caedca; }
            .analysis-low h1 { background-color: #8fd98f; color: #2a7a2a; }
            .analysis-low h1:hover { background-color: #ace3ac; }

            .analysis-info { background-color: #b2e5e5; }
            .analysis-info h1 { background-color: #1aa3a3; color: #0b5e56; }
            .analysis-info h1:hover { background-color: #86becb; }

            .analysis-empty {
            color: #a0a0a0;
            font-size: 14px;
            padding: 10px;
            font-weight: bold;
            }
        </style>
        <!-- split the css into two style tags to get around the locstudio 8192 character limit -->
        <style>
            .expander { font-family: "Consolas"; font-weight: bold; }
            .warning { background-color: #fde5c0; }
            .warning h1 { background-color: #fbc674; color: #cc7e06; }
            .warning h1:hover { background-color: #fcd69a; }
            .error { background-color: #ffd5d1; }
            .error h1 { background-color: #ff8e83; color: #970d00; }
            .error h1:hover { background-color: #ffb2aa; }
            code { font-family: "Consolas"; }

            pre {
            font-family: "Consolas";
            display: block;
            border: 1px dashed #b0b0b0;
            padding: 10px;
            margin: 10px 0px 10px 0px;
            }

            .scroll-top-button {
            border: 2px solid #000000;
            background-color: #ffffff;
            padding: 5px 3px 5px 3px;
            font-size: 12px;
            font-family: Segoe UI Semibold;
            float: left;
            border-radius: 18px;
            margin-top: 15px;
            margin-left: -60px;
            }

            .scroll-top-button:hover {
            background-color: #f0f0f0;
            cursor: pointer;
            }

            .scenario-details, .scenario-details-collapsed {
            padding: 5px;
            background-color: #f0f0f0;
            width: 864px;
            border-left: 2px solid #ffffff;
            }

            .scenario-details { display: block; }
            .scenario-details-collapsed { display: none; }

            .details-expander {
            background-color: #dfdfdf;
            font-weight: bold;
            cursor: pointer;
            }

            .details-expander:hover { background-color: #cfcfcf; }

            ul { list-style: square; }
        </style>
    </xsl:template>

    <!-- JavaScript for the page -->
    <xsl:template name="jsUtil">
    <xsl:text disable-output-escaping="yes">
    // Add support for drawing dashed lines to Canvas
    CanvasRenderingContext2D.prototype.dashedLine = function (x0, y0, x1, y1, dashArray) {
        if (dashArray == null) {
            dashArray = [4, 4];
        }

        var dx = x1 - x0;
        var dy = y1 - y0;
        var distance = Math.sqrt(Math.pow((x1 - x0), 2) + Math.pow((y1 - y0), 2));
        var theta = Math.atan(dy / dx);
        if (dx &lt; 0) {
            theta += Math.PI;
        }

        var i = 0;
        while (distance &gt; 0) {
            var length = Math.min(distance, dashArray[i]);
            x0 += length * Math.cos(theta);
            y0 += length * Math.sin(theta);
            if (i % 2 == 0) {
                this.lineTo(x0, y0);

            } else {
                this.moveTo(x0, y0);
            }

            distance -= length;
            i = (i + 1) % dashArray.length;
        }
    };
    </xsl:text>
    </xsl:template>

    <xsl:template name="jsDateUtil">
    <xsl:text disable-output-escaping="yes">
    // Formats a number using the current locale (to handle the 1000's separator).
    // The result is rounded so no decimal point is shown.
    function numberToLocaleString(value) {
        var localeString = Math.round(parseFloat(value + '')).toLocaleString();
        return localeString.substring(0, localeString.indexOf('.'));
    }

    function padLeft(number, length) {
        var str = '' + number;
        while (str.length &lt; length) {
            str = '0' + str;
        }

        return str;
    }

    // Returns the number of milliseconds between 2 date-times represented as strings.
    function msBetween(startTime, endTime) {
        return startTime &gt; endTime
               ? msBetween(endTime, startTime)
               : parseDateTime(endTime) - parseDateTime(startTime);
    }

    var dateFormat = /(\d{4})-(\d{2})-(\d{2})[T](\d{2}):(\d{2}):(\d{2})/

    // Parses a date-time string and returns a Date (i.e. number of milliseconds)
    function parseDateTime(value) {
        if (!value) {
            return 0;
        }

        var match = dateFormat.exec(value)
        if (!match) {
            return 0;
        }

        return Date.parse(match[1] + '/' + match[2] + '/' +
                          match[3] + ' ' + match[4] + ':' +
                          match[5] + ':' + match[6])
    }

    // Parses just the date portion of a date-time string and returns a Date
    // (i.e. number of milliseconds)
    function parseDate(value) {
        if (!value) {
            return 0;
        }

        var match = dateFormat.exec(value)
        if (!match) {
            return 0;
        }

        return Date.parse(match[1] + '/' + match[2] + '/' + match[3])
    }

    var durationFormat = /P((\d+)D)?T((\d+)H)?((\d+)M)?(\d+)S/

    // Convert a string of the form P10DT1H15M40S to a count of milliseconds
    function parseDurationToMs(value) {
        var match = durationFormat.exec(value)
        if (!match) {
            return 0
        }

        var days = parseInt(match[2] || '0');
        var hrs = parseInt(match[4] || '0');
        var mins = parseInt(match[6] || '0');
        var secs = parseInt(match[7] || '0');
        return ((((((days * 24) + hrs) * 60) + mins) * 60) +  secs) * 1000;
    }

    // Converts milliseconds to days
    function msToDays(ms) {
        return (ms / 1000 / 60 / 60 / 24);
    }

    function daysToMs(days) {
        return (days * 24 * 60 * 60 * 1000);
    }

    // Formats a number of milliseconds as h:mm:ss
    function formatDurationMs(value) {
        var ms = parseInt(value);
        var secs = ms / 1000;
        var mins = secs / 60;
        var hrs = Math.floor(mins / 60);
        mins = Math.floor(mins % 60);
        secs = Math.floor(secs % 60);
        return hrs + ':' + padLeft(mins,2) + ':' + padLeft(secs,2);
    }

    // Converts a millisecond timestamp to a day and month string
    // Note: dayOffset is forward from date.
    function dateToDayAndMonth(ms, dayOffset) {
        var adjustedDate = new Date(ms + (dayOffset * 24 * 60 * 60 * 1000));
        return padLeft(adjustedDate.getMonth() + 1, 2) + "-" +
               padLeft(adjustedDate.getDate(), 2);
    }

    // Takes a millisecond timestamp and returns a new millisecond timestamp
    // rounded down to the current day.
    function dateFloor(ms) {
        var dt = new Date(ms);
        return Date.parse(dt.getFullYear() + '/' + (dt.getMonth() + 1) + '/' + dt.getDate());
    }
    </xsl:text>
    </xsl:template>

    <xsl:template name="jsTimegraph">
    <xsl:text disable-output-escaping="yes">
    Timegraph = {
        axisTop: 9.5,
        axisRight: 24.5,
        axisBottom: 25.5,
        axisLeft: 25.5,
        ticks: 10,

        // Maximum number of 24 hour ticks for showing 12 and 6 hour ticks

        ticks12Hour: 360,
        ticks6Hour: 180,

        // Shading

        shadingColor: "#d0d0d0",

        precompute: function (graph) {
            var canvas = graph.canvas;
            var data = graph.data;
            var min = 0;
            var max = 0;

            graph.height = canvas.height - Timegraph.axisTop - Timegraph.axisBottom;
            graph.width = canvas.width - Timegraph.axisLeft - Timegraph.axisRight;
            for (var i = 0; i &lt; data.length; i++) {
                data[i].t0 = parseDateTime(data[i].x0);
                data[i].t1 = parseDateTime(data[i].x1);

                if (i == 0) {
                    min = data[i].t0;
                    max = data[i].t1;
                }

                if (data[i].t0 &lt; min) {
                    min = data[i].t0;
                }

                if (data[i].t1 &gt; max) {
                    max = data[i].t1;
                }

                data[i].yy0 =
                    Timegraph.axisTop + graph.height - data[i].y0 * graph.height;

                data[i].yy1 =
                    Timegraph.axisTop + graph.height - data[i].y1 * graph.height;
            }

            if (graph.startTime != null) {
                graph.startMs = parseDateTime(graph.startTime);

            } else {
                graph.startMs = min;
            }

            graph.endMs = max;
            graph.durationMs = max - min;
        },

        drawFrame: function (graph) {
            var canvas = graph.canvas;
            var context = graph.context;

            graph.width =
                canvas.width - Timegraph.axisRight - Timegraph.axisLeft;

            graph.height =
                canvas.height - Timegraph.axisTop - Timegraph.axisBottom;

            context.beginPath();
            context.moveTo(Timegraph.axisLeft, Timegraph.axisTop);
            context.lineTo(Timegraph.axisLeft + graph.width,
                           Timegraph.axisTop);

            context.lineTo(Timegraph.axisLeft + graph.width,
                           Timegraph.axisTop + graph.height);

            context.lineTo(Timegraph.axisLeft,
                           Timegraph.axisTop + graph.height);

            context.lineTo(Timegraph.axisLeft, Timegraph.axisTop);
            context.strokeStyle = "#c0c0c0";
            context.stroke();
        },

        drawRange: function (graph) {
            var canvas = graph.canvas;
            var context = graph.context;

            context.font = "12pt Segoe UI";
            context.fillStyle = "#00b0f0";
            context.fillText("%", 0, Timegraph.axisTop + 5, Timegraph.axisLeft);

            var tickSpacing = graph.height / 10;
            var offset = Timegraph.axisTop + tickSpacing;
            var tickValue = 90;
            for (var i = 0; i &lt; 9; i++) {
                context.beginPath();
                context.moveTo(Timegraph.axisLeft, offset);
                context.lineTo(Timegraph.axisLeft + graph.width,
                               offset);

                context.stroke();
                context.fillText(tickValue.toString(),
                                 0,
                                 offset + 5,
                                 Timegraph.axisLeft);

                offset += tickSpacing;
                tickValue -= 10;
            }
        },

        drawDomain: function (graph, start, end) {
            var canvas = graph.canvas;
            var context = graph.context;
            var data = graph.data;
            var duration = end - start;
            if ((end &lt; start)) {
                return;
            }

            var startDay = dateFloor(start);
            var t0 = startDay;
            var t1 = dateFloor(end);
            var dayOffset = 0;
            if (start &gt; t0) {
                t0 = t0 + daysToMs(1);
                dayOffset++;
            }

            if (t0 &gt;= t1) {
                return;
            }

            var increment =
                Math.max(Math.floor((t1 - t0) / daysToMs(Timegraph.ticks)), 1);

            var incrementMs = daysToMs(increment);
            var spacing = (incrementMs / duration) * graph.width;
            var offset = (t0 - start) / duration;
            var ticksCount = Math.floor((t1 - t0) / incrementMs);
            for (offset = offset * graph.width + Timegraph.axisLeft;
                 offset &lt; (graph.width + Timegraph.axisLeft);
                 offset += spacing) {

                context.beginPath();
                context.moveTo(offset, Timegraph.axisTop);
                context.lineTo(offset, Timegraph.axisTop + graph.height);
                context.stroke();
                context.fillText(dateToDayAndMonth(startDay, dayOffset),
                                 offset,
                                 Timegraph.axisTop + graph.height + 15,
                                 spacing);

                dayOffset += increment;
            }
        },

        plot: function (graph, start, end) {
            var canvas = graph.canvas;
            var context = graph.context
            var data = graph.data;

            if ((end &lt; start)) {
                return;
            }

            var duration = end - start;
            Timegraph.drawDomain(graph, start, end);
            context.fillStyle = Timegraph.shadingColor;
            for (var i = 0; i &lt; data.length - 1; i++) {
                if ((data[i].t0 &lt; start) || (data[i].t0 &gt; end) ||
                    (data[i].t1 &gt; end)) {

                    continue;
                }

                var x1 = (data[i].t0 - start) / duration;
                x1 = x1 * graph.width + Timegraph.axisLeft;

                var x2 = (data[i].t1 - start) / duration;
                x2 = x2 * graph.width + Timegraph.axisLeft;

                context.globalAlpha = 0.3;
                context.fillRect(x1, Timegraph.axisTop, (x2 - x1), graph.height);
                context.globalAlpha = 1;
                context.beginPath();
                context.strokeStyle = graph.lineTypes[data[i].type].color;
                context.lineWidth = 1.5;
                if (graph.lineTypes[data[i].type].dotted == 1) {
                    context.dashedLine(x1, data[i].yy0, x2, data[i].yy1);

                } else {
                    context.moveTo(x1, data[i].yy0);
                    context.lineTo(x2, data[i].yy1);
                }

                context.stroke();
            }
        },

        draw: function (graph) {
            var canvas = document.getElementById(graph.element);
            if (canvas == null) {
                return;
            }

            var context = canvas.getContext('2d');
            if (context == null) {
                return;
            }

            graph.width = 0;
            graph.height = 0;
            graph.context = context;
            graph.canvas = canvas;

            Timegraph.precompute(graph);
            Timegraph.drawFrame(graph);
            Timegraph.drawRange(graph);
            Timegraph.plot(graph, graph.startMs, graph.endMs);
        }
    };
    </xsl:text>
    </xsl:template>

    <xsl:template name="jsCollapser">
    <xsl:text disable-output-escaping="yes">
    Collapser = {
        topActiveBlockerDivs: {},
        detailsContainers: {},

        getContainerBody: function (container) {
            var children = container.childNodes;
            var containerBody = null;
            for (var i = 0; i &lt; children.length; i++) {
                if (children[i].tagName == "DIV" &amp;&amp;
                    (children[i].className == "analysis-body-collapsed" ||
                     children[i].className == "analysis-body")) {

                    containerBody = children[i];
                    break;
                }
            }

            return containerBody;
        },

        togglePanel: function (container) {
            var containerBody = Collapser.getContainerBody(container);
            if (containerBody == null) {
                return;
            }

            var heading = container.getElementsByTagName("H1")[0];
            var expander = heading.getElementsByClassName("expander")[0];
            if (containerBody.className == "analysis-body-collapsed") {
                containerBody.className = "analysis-body";
                expander.innerHTML = "- ";

            } else {
                containerBody.className = "analysis-body-collapsed";
                expander.innerHTML = "+ ";
            }
        },

        toggleDetails: function (element) {
            if (element.className == "scenario-details-collapsed") {
                element.className = "scenario-details";

            } else {
                element.className = "scenario-details-collapsed";
            }
        },

        initializePanels: function () {
            var elements = document.getElementsByClassName("analysis-container");
            for (var i = 0; i &lt; elements.length; i++) {
                var element = elements[i];
                var heading = element.getElementsByTagName("h1")[0];
                if (heading == null) {
                    continue;
                }

                heading.onclick = function () {
                    var container = this.parentNode;
                    Collapser.togglePanel(container);
                };
            }
        },

        initializeDetails: function() {
            var elements = document.getElementsByClassName("details-expander");
            for (var i = 0; i &lt; elements.length; i++) {
                var element = elements[i];
                var targetId = "details-" + element.id.replace("details-expand-", "");
                var targetElement = document.getElementById(targetId);
                Collapser.detailsContainers[element.id] = targetElement;
                element.onclick = function () {
                    var targetElement = Collapser.detailsContainers[this.id];
                    Collapser.toggleDetails(targetElement);
                };
            }
        },

        initializeLinks: function () {
            var links = document.getElementsByClassName("top-active-link");
            for (var i = 0; i &lt; links.length; i++) {
                var link = links[i];
                var targetId = link.getAttribute("href").substring(1);
                var targetElement = document.getElementById(targetId);
                if (targetElement.tagName.toLowerCase() == "tr") {
                    // tr, tbody, table, div.analysis-body-*, div.analysis-container
                    Collapser.topActiveBlockerDivs[targetId] =
                        targetElement.parentNode.parentNode.parentNode.parentNode;

                } else {
                    Collapser.topActiveBlockerDivs[targetId] = targetElement;
                }

                link.onclick = function () {
                    var targetId = this.getAttribute("href").substring(1);
                    var targetContainer = Collapser.topActiveBlockerDivs[targetId];
                    var container = targetContainer;
                    while ((container != null) &amp;&amp; (container.tagName == "DIV")) {
                        var containerBody = Collapser.getContainerBody(container);
                        if (containerBody == null) {
                            return;
                        }

                        if (containerBody.className == "analysis-body-collapsed") {
                            Collapser.togglePanel(container);
                        }

                        container = container.parentNode.parentNode;
                    }

                    targetContainer.scrollIntoView(true);
                };
            }
        },

        initializeCollapser: function () {
            Collapser.initializePanels();
            Collapser.initializeDetails();
            TableDecorator.decorate({
                element: ".top-blocker",
                withClass: "top-active-link"
            });

            Collapser.initializeLinks();
        },

        initialize: function () {
            if (window.addEventListener != null) {
                window.addEventListener("load", Collapser.initializeCollapser, false);

            } else if (window.attachEvent != null) {
                window.attachEvent("onload", Collapser.initializeCollapser);
            }
        }
    };
    </xsl:text>
    </xsl:template>

    <xsl:template name="jsTableDecorator">
    <xsl:text disable-output-escaping="yes">
    TableDecorator = {
        decorateTable: function (table, linkClass) {
            if (table == null) {
                return;
            }

            var rows = table.getElementsByTagName("tr");
            for (var i = 0; i &lt; rows.length; i++) {
                var row = rows[i];
                var anchor = row.getElementsByClassName("row-link")[0];
                if (anchor == null || anchor.tagName.toLowerCase() != "a") {
                    continue;
                }

                var link = anchor.getAttribute("href");
                for (var j = 0; j &lt; row.children.length; j++) {
                    var cell = row.children[j];
                    if (cell == anchor.parentNode) {
                        continue;
                    }

                    var classString = "";
                    if (linkClass != null) {
                        classString = " class=\"" + linkClass + "\"";
                    }

                    cell.innerHTML =
                        "&lt;a href=\"" + link + "\"" + classString + "&gt;" +
                        cell.innerHTML + "&lt;/a&gt;";
                }
            }
        },

        decorate: function (tableData) {
            var selection = tableData.element;
            if (selection.charAt(0) == ".") {
                var className = selection.substring(1);
                var elements = document.getElementsByClassName(className);
                for (var i = 0; i &lt; elements.length; i++) {
                    if (elements[i].tagName.toLowerCase() == "table") {
                        TableDecorator.decorateTable(elements[i], tableData.withClass);
                    }
                }

            } else if (selection.charAt(0) == "#") {
                var idName = selection.substring(1);
                var element = document.getElementById(idName);
                if (element.tagName.toLowerCase() == "table") {
                    TableDecorator.decorateTable(element, tableData.withClass);
                }
            }
        },
    };
    </xsl:text>
    </xsl:template>

    <xsl:template name="jsScrollTop">
    <xsl:text disable-output-escaping="yes">
    function initializeScrollTop() {
        var elements = document.getElementsByClassName("scroll-top-button");
        for (var i = 0; i &lt; elements.length; i++) {
            var element = elements[i];
            element.onclick = function () {
                window.scroll(0, 0);
                window.location.replace("#");
                if (typeof window.history.replaceState == "function") {
                    history.replaceState({}, "", window.location.href.slice(0, -1));
                }
            }
        }
    }
    </xsl:text>
    </xsl:template>

    <xsl:template name="javascript">
        <xsl:param name="idleTimes" />

        <script type="text/javascript">
            <xsl:call-template name="jsUtil" />
            <xsl:call-template name="jsDateUtil" />
            <xsl:call-template name="jsTimegraph" />
            <xsl:call-template name="jsScrollTop" />
            <xsl:call-template name="jsCollapser" />
            <xsl:call-template name="jsTableDecorator" />
                Collapser.initialize();

            <xsl:text disable-output-escaping="yes">
                idleTimeGraphLineTypes = [
                    { color: "none", dotted: 0 },
                    { color: "#7d7d7d", dotted: 0 },
                    { color: "#2a7a2a", dotted: 0 },
                    { color: "#cc7e06", dotted: 0 },
                    { color: "#970d00", dotted: 0 },
                    { color: "#7d7d7d", dotted: 1 },
                    { color: "#2a7a2a", dotted: 1 },
                    { color: "#cc7e06", dotted: 1 },
                    { color: "#970d00", dotted: 1 },
                ];
            </xsl:text>

            <xsl:apply-templates select="$idleTimes" mode="jsIdleTime" />

            <xsl:text disable-output-escaping="yes">
                function main() {
            </xsl:text>
            <xsl:text disable-output-escaping="yes">
                    TableDecorator.decorate({element: "#summary-table"});
            </xsl:text>
            <xsl:apply-templates select="$idleTimes" mode="jsMainIdleTime" />
            <xsl:text disable-output-escaping="yes">

                    initializeScrollTop();
                }

                if (window.addEventListener != null) {
                    window.addEventListener("load", main, false);

                } else if (window.attachEvent != null) {
                    window.attachEvent("onload", main);
                }
            </xsl:text>
        </script>
    </xsl:template>


    <xsl:template match="ssd:IdleTime" mode="jsMainIdleTime">
        <xsl:text>
            Timegraph.draw({
                element: "idle-time-graph-</xsl:text>
        <xsl:value-of select="position()" />
        <xsl:text>",
                data: idleTimeGraphData_</xsl:text>
        <xsl:value-of select="position()" />
        <xsl:text>,
                rangeMax: 100,
                lineTypes: idleTimeGraphLineTypes,
                startTime: "</xsl:text>
        <xsl:value-of select="@LocalStartTimestamp" />
        <xsl:text disable-output-escaping="yes">",
                endTime: "</xsl:text>
        <xsl:value-of select="@LocalEndTimestamp" />
        <xsl:text disable-output-escaping="yes">"
            });
            &#xa;
        </xsl:text>
    </xsl:template>

    <xsl:template match="ssd:IdleTime" mode="jsIdleTime">
        <xsl:text>idleTimeGraphData_</xsl:text>
        <xsl:value-of select="position()" />
        <xsl:text> = [&#xa;</xsl:text>
        <xsl:apply-templates select="ssd:Datapoint" mode="jsIdleTime" />
        <xsl:text>
            ];
        </xsl:text>
    </xsl:template>

    <xsl:template match="ssd:Datapoint" mode="jsIdleTime">
        <xsl:text>{ </xsl:text>
        <xsl:text>x0: "</xsl:text>
        <xsl:value-of select="@LocalStartTimestamp" />
        <xsl:text>", </xsl:text>
        <xsl:text>x1: "</xsl:text>
        <xsl:value-of select="@LocalEndTimestamp" />
        <xsl:text>", </xsl:text>
        <xsl:text>y0: </xsl:text>
        <xsl:value-of select="@AccumulatedIdleTime div @MaxAccumulatedTime" />
        <xsl:text>, </xsl:text>
        <xsl:text>y1: </xsl:text>
        <xsl:value-of select="@AccumulatedIdleTime div @MaxAccumulatedTime" />
        <xsl:text>, </xsl:text>
        <xsl:text>type: </xsl:text>
        <xsl:variable name="systemIsIdle">
            <xsl:choose>
                <xsl:when test="@SystemIdle = '1'">2</xsl:when>
                <xsl:otherwise>4</xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:value-of select="$systemIsIdle" />
        <xsl:text>}, &#xa;</xsl:text>
    </xsl:template>

    <!-- Formats a date-time for display -->
    <xsl:template name="formatDateTime">
        <xsl:param name="dateTime"/>
        <xsl:param name="showDate" select="true()" />
        <xsl:variable name="date" select="substring-before($dateTime, 'T')"/>
        <xsl:variable name="time" select="translate(substring-after($dateTime, 'T'), 'T ', '')"/>

        <span class="date">
            <xsl:if test="$showDate">
                <xsl:value-of select="$date"/>
            </xsl:if>
            <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
            <xsl:text> </xsl:text>
        </span>
        <span class="time">
            <xsl:value-of select="$time"/>
        </span>
    </xsl:template>

    <xsl:template name="systemInformation">
        <table class="defs">
            <col />
            <tr>
                <td class="label">
                    REPORT TIME
                </td>
                <td>
                    <xsl:variable name="date" select="substring-before($localReportTime, 'T')"/>
                    <xsl:variable name="time" select="translate(substring-after($localReportTime, 'T'), 'T ', '')"/>

                    <span>
                        <xsl:value-of select="$date"/>
                        <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
                        <xsl:text> </xsl:text>
                    </span>
                    <span>
                        <xsl:value-of select="$time"/>
                    </span>
                </td>
            </tr>
        </table>
    </xsl:template>

    <xsl:template match="ssd:UserAbsenceSessions" mode="summaryTable">
        <table id="summary-table">
            <colgroup>
                <col style="width: 2em" />
                <col style="width: 11em;" />
                <col style="width: 5em;" />
                <col style="width: 5em;" />
            </colgroup>
            <thead>
                <tr>
                    <th></th>
                    <th>TIME USER WENT IDLE</th>
                    <th>IDLE DURATION</th>
                    <th>SLEEP STATE ENTERED</th>
                </tr>
            </thead>

            <xsl:choose>
                <xsl:when test="count(ssd:Session)">
                    <xsl:apply-templates select="ssd:Session" mode="summaryTable"  />
                </xsl:when>
                <xsl:otherwise>
                    <!-- No data. Show one line of dashes -->
                    <tr>
                        <td class="nullValue">-</td>
                        <td class="nullValue">-</td>
                        <td class="nullValue">-</td>
                        <td class="nullValue">-</td>
                    </tr>
                </xsl:otherwise>
            </xsl:choose>
        </table>
    </xsl:template>

    <xsl:template match="ssd:Session" mode="summaryTable">
        <tr>
            <xsl:attribute name="class">
                <xsl:text>row-low</xsl:text>
            </xsl:attribute>
            <td class="centered">
                <a>
                    <xsl:attribute name="href">
                        <xsl:text>#user-not-present-session-</xsl:text>
                        <xsl:value-of select="position()" />
                    </xsl:attribute>
                    <xsl:attribute name="class">
                        <xsl:text>row-link</xsl:text>
                    </xsl:attribute>
                    <xsl:value-of select="position()" />
                </a>
            </td>
            <td class="dateTime">
                <xsl:call-template name="formatDateTime">
                    <xsl:with-param name="dateTime" select="@NotPresentLocalTimestamp" />
                    <xsl:with-param name="showDate" select="js:parseDate(string(@NotPresentLocalTimestamp)) != js:parseDate(string(preceding-sibling::*[1]/@NotPresentLocalTimestamp))" />
                </xsl:call-template>
            </td>
            <td class="hms">
                <xsl:value-of select="js:formatDurationMs(string(@NotPresentDuration div 10000))" />
            </td>
            <td class="centered">
                <xsl:value-of select="js:createSleepIntervalString(string(@SleepState))" />
            </td>
        </tr>

    </xsl:template>

    <xsl:template match="ssd:UserAbsenceSessions" mode="analysisResults">
        <xsl:apply-templates select="ssd:Session" mode="analysisResults" />
    </xsl:template>

    <xsl:template match="ssd:Session" mode="analysisResults">
        <a>
            <xsl:attribute name="name">
                <xsl:text>user-not-present-session-</xsl:text>
                <xsl:value-of select="position()" />
            </xsl:attribute>
        </a>
        <div class="scroll-top-button">Top</div>
        <h3>
            User Not Present Session <xsl:value-of select="position()" />
        </h3>
        <table class="session-summary">
            <colgroup>
                <col style="width: 2em" />
                <col style="width: 11em;" />
                <col style="width: 5em;" />
                <col style="width: 5em;" />
            </colgroup>
            <thead>
                <tr>
                    <th></th>
                    <th>TIME USER WENT IDLE</th>
                    <th>IDLE DURATION</th>
                    <th>SLEEP STATE ENTERED</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <xsl:attribute name="class">
                        <xsl:text>row-low</xsl:text>
                    </xsl:attribute>
                    <td class="centered">
                        <xsl:value-of select="position()" />
                    </td>
                    <td class="dateTime">
                        <xsl:call-template name="formatDateTime">
                            <xsl:with-param name="dateTime" select="@NotPresentLocalTimestamp" />
                        </xsl:call-template>
                    </td>
                    <td class="hms">
                        <xsl:value-of select="js:formatDurationMs(string(@NotPresentDuration div 10000))" />
                    </td>
                    <td class="centered">
                        <xsl:value-of select="js:createSleepIntervalString(string(@SleepState))" />
                    </td>
                </tr>
            </tbody>
        </table>

        <xsl:if test="count(ssd:Runtime/ssd:IdleTime)">
            <h4>Idle Time Graph</h4>
            <div class="explanation">Diagnostics of system idle.</div>
            <canvas>
                <xsl:attribute name="id">
                    <xsl:text>idle-time-graph-</xsl:text>
                    <xsl:value-of select="position()" />
                </xsl:attribute>
                <xsl:attribute name="width">
                    <xsl:text>864</xsl:text>
                </xsl:attribute>
                <xsl:attribute name="height">
                    <xsl:text>300</xsl:text>
                </xsl:attribute>
                <xsl:text> </xsl:text>
            </canvas>
        </xsl:if>

        <xsl:apply-templates select="ssd:Runtime/ssd:PowerRequests" mode="analysisTopLevel" />
        <xsl:apply-templates select="ssd:Runtime/ssd:IdleEvents" mode="analysisTopLevel" />
        <xsl:apply-templates select="ssd:SleepIntervals" mode="analysisTopLevel" />
      <xsl:apply-templates select="ssd:SmartUserPresenceInformation" />
    </xsl:template>

    <xsl:template match="ssd:PowerRequests" mode="analysisTopLevel">
        <div>
            <xsl:attribute name="class">
                <xsl:text>analysis-container </xsl:text>
                <xsl:text>analysis-</xsl:text>
                <xsl:value-of select="@ActivityLevel" />
            </xsl:attribute>
            <h1>
                <span class="expander">+ </span>Power Requests
            </h1>
            <div class="analysis-body-collapsed">
                <xsl:choose>
                    <xsl:when test="count(ssd:PowerRequest)">
                        <xsl:apply-templates select="ssd:PowerRequest" />
                    </xsl:when>
                    <xsl:otherwise>
                        <div class="analysis-empty">No power requests present during this session.</div>
                    </xsl:otherwise>
                </xsl:choose>
            </div>
        </div>
    </xsl:template>

    <xsl:template match="ssd:PowerRequest">
        <div>
            <xsl:attribute name="class">
                <xsl:text>analysis-container </xsl:text>
                <xsl:text>analysis-</xsl:text>
                <xsl:value-of select="@ActivityLevel" />
            </xsl:attribute>
            <h1>
                <span class="expander">+ </span>
                <xsl:value-of select="@Caller" />
            </h1>
            <div class="analysis-body-collapsed">
                <table class="defs">
                    <tr>
                        <td class="label">START TIME</td>
                        <td class="label">DURATION</td>
                        <td class="label">TYPE</td>
                        <td class="label">TOKEN</td>
                    </tr>
                    <tr>
                        <td class="percent">
                            <xsl:value-of select="@LocalStartTime" />
                        </td>
                        <td class="center">
                            <xsl:value-of select="js:formatDurationMs(string(@Duration div 10000))" />
                        </td>
                        <td class="center">
                            <xsl:value-of select="@Type" />
                        </td>
                        <td class="center">
                            <xsl:value-of select="@Token" />
                        </td>
                    </tr>
                </table>
            </div>
        </div>
    </xsl:template>

    <xsl:template match="ssd:IdleEvents" mode="analysisTopLevel">
        <div>
            <xsl:attribute name="class">
                <xsl:text>analysis-container </xsl:text>
                <xsl:text>analysis-info</xsl:text>
            </xsl:attribute>
            <h1>
                <span class="expander">+ </span>System Idle Events
            </h1>
            <div class="analysis-body-collapsed">
                <xsl:choose>
                    <xsl:when test="count(ssd:Event) = 0">
                        <div class="analysis-empty">No system idle events present during this session.</div>
                    </xsl:when>
                    <xsl:otherwise>
                        <table class="pdc-phases">
                            <thead>
                                <th>EVENT</th>
                                <th>FROM START</th>
                                <th>TIME</th>
                            </thead>
                            <tbody>
                                <xsl:apply-templates select="ssd:Event" />
                            </tbody>
                        </table>
                    </xsl:otherwise>
                </xsl:choose>
            </div>
        </div>
    </xsl:template>

    <xsl:template match="ssd:Event">
        <tr>
            <xsl:attribute name="class">
                <xsl:text>row-info</xsl:text>
            </xsl:attribute>
            <td>
                <xsl:value-of select="@Info" />
            </td>
            <td class="center">
                <xsl:value-of select="js:formatDurationMs(string(@OffsetStart div 10000))" />
            </td>
            <td class="dateTime">
                <xsl:call-template name="formatDateTime">
                    <xsl:with-param name="dateTime" select="@LocalTimestamp" />
                </xsl:call-template>
            </td>
        </tr>
    </xsl:template>

    <xsl:template match="ssd:SmartUserPresenceInformation">
        <div>
            <xsl:attribute name="class">
                <xsl:text>analysis-container </xsl:text>
                <xsl:text>analysis-info</xsl:text>
            </xsl:attribute>
            <h1>
                <span class="expander">+ </span>
                Smart User Presence Prediction Information
            </h1>
            <div class="analysis-body-collapsed">
                <table class="defs">
                    <tr>
                        <td class="label">SUPPORTED</td>
                        <td class="label">GLOBAL USER PRESENT</td>
                        <td class="label">USER PREDICTION MODE</td>
                        <td class="label">MIN CONFIDENCE</td>
                        <td class="label">SUSPEND COUNT</td>
                        <td class="label">LAST USER AWAY END</td>
                    </tr>
                    <tr>
                        <td class="center">
                            <xsl:value-of select="ssd:Supported" />
                        </td>
                        <td class="center">
                            <xsl:value-of select="ssd:GlobalUserPresent" />
                        </td>
                        <td class="center">
                            <xsl:value-of select="ssd:UserPredictionMode" />
                        </td>
                        <td class="center">
                            <xsl:value-of select="ssd:MinConfidence" />
                        </td>
                        <td class="center">
                            <xsl:value-of select="ssd:SuspendCount" />
                        </td>
                        <td class="dateTime">
                            <xsl:call-template name="formatDateTime">
                                <xsl:with-param name="dateTime" select="ssd:LastUserAwayEndLocalTimestamp" />
                            </xsl:call-template>
                        </td>
                    </tr>
                </table>
                <xsl:apply-templates select="ssd:Intervals" mode="smartUserPresence" />
                <xsl:apply-templates select="ssd:Events" mode="smartUserPresence" />
            </div>
        </div>
    </xsl:template>
  
    <xsl:template match="ssd:Intervals" mode="smartUserPresence">
        <div>
            <xsl:attribute name="class">
                <xsl:text>analysis-container </xsl:text>
                <xsl:text>analysis-info</xsl:text>
            </xsl:attribute>
            <h1>
                <span class="expander">+ </span>Weekly Prediction Intervals
            </h1>
            <div class="analysis-body-collapsed">
                <xsl:choose>
                    <xsl:when test="count(ssd:UserIntervals)">
                        <xsl:apply-templates select="ssd:UserIntervals" />
                    </xsl:when>
                    <xsl:otherwise>
                        <div class="analysis-empty">No intervals.</div>
                    </xsl:otherwise>
                </xsl:choose>
            </div>
        </div>
    </xsl:template>
  
    <xsl:template match="ssd:UserIntervals">
        <div>
            <xsl:attribute name="class">
                <xsl:text>analysis-container </xsl:text>
                <xsl:text>analysis-info</xsl:text>
            </xsl:attribute>
            <h1>
                <span class="expander">+ </span>Intervals for User Sid
                <xsl:value-of select="ssd:UserSid" />
            </h1>
            <table class="defs">
                <tr>
                    <td class="label">INTERVAL NUMBER</td>
                    <td class="label">WEEKLY START OFFSET</td>
                    <td class="label">WEEKLY END OFFSET</td>
                    <td class="label">CONFIDENCE</td>
                </tr>
                <xsl:apply-templates select="ssd:Interval" mode="smartUserPresence" />
            </table>
            <div class="analysis-body-collapsed">
            </div>
        </div>
    </xsl:template>  
  
    <xsl:template match="ssd:Interval" mode="smartUserPresence">
        <tr>
            <td class="center">
                <xsl:value-of select="position()" />
            </td>
            <td class="center">
                <xsl:value-of select="js:formatDurationMs(string(ssd:WeeklyStartOffsetInUs div 1000))" />
            </td>
            <td class="center">
                <xsl:value-of select="js:formatDurationMs(string(ssd:WeeklyEndOffsetInUs div 1000))" />
            </td>
            <td class="center">
                <xsl:value-of select="ssd:Confidence" />
            </td>
        </tr>
    </xsl:template>  
  
    <xsl:template match="ssd:Events" mode="smartUserPresence">
        <div>
            <xsl:attribute name="class">
                <xsl:text>analysis-container </xsl:text>
                <xsl:text>analysis-info</xsl:text>
            </xsl:attribute>
            <h1>
                <span class="expander">+ </span>Events
            </h1>
            <div class="analysis-body-collapsed">
                <xsl:choose>
                    <xsl:when test="count(ssd:Event) = 0">
                        <div class="analysis-empty">No smart user presence events present during this session.</div>
                    </xsl:when>
                    <xsl:otherwise>
                        <table class="pdc-phases">
                            <thead>
                                <th>EVENT</th>
                                <th>FROM START</th>
                                <th>TIME</th>
                            </thead>
                            <tbody>
                                <xsl:apply-templates select="ssd:Event" />
                            </tbody>
                        </table>
                    </xsl:otherwise>
                </xsl:choose>
            </div>
        </div>
    </xsl:template>

    <xsl:template match="ssd:SleepIntervals" mode="analysisTopLevel">
        <div>
            <xsl:attribute name="class">
                <xsl:text>analysis-container </xsl:text>
                <xsl:text>analysis-info</xsl:text>
            </xsl:attribute>
            <h1>
                <span class="expander">+ </span>Sleep Intervals
            </h1>
            <div class="analysis-body-collapsed">
                <xsl:choose>
                    <xsl:when test="count(ssd:SleepInterval)">
                        <xsl:apply-templates select="ssd:SleepInterval" />
                    </xsl:when>
                    <xsl:otherwise>
                        <div class="analysis-empty">The system did not sleep during this session.</div>
                    </xsl:otherwise>
                </xsl:choose>
            </div>
        </div>
    </xsl:template>

    <xsl:template match="ssd:SleepInterval">
        <div>
            <xsl:attribute name="class">
                <xsl:text>analysis-container </xsl:text>
                <xsl:text>analysis-</xsl:text>
                <xsl:choose>
                    <xsl:when test="@ProbablyClean = '1'">low</xsl:when>
                    <xsl:otherwise>high</xsl:otherwise>
                </xsl:choose>
            </xsl:attribute>
            <h1>
                <span class="expander">+ </span>
                <xsl:value-of select="js:createSleepIntervalString(string(@State))" />
            </h1>
            <div class="analysis-body-collapsed">
                <table class="defs">
                    <tr>
                        <td class="label">START TIME</td>
                        <td class="label">DURATION</td>
                        <td class="label">STATE</td>
                        <td class="label">ACTION</td>
                        <td class="label">REASON</td>
                        <td class="label">ID</td>
                        <td class="label">STATUS</td>
                        <td class="label">SUCCESSFUL</td>
                    </tr>
                    <tr>
                        <td class="percent">
                            <xsl:value-of select="@LocalStartTime" />
                        </td>
                        <td class="center">
                            <xsl:value-of select="js:formatDurationMs(string(@Duration div 10000))" />
                        </td>
                        <td class="center">
                            <xsl:value-of select="js:createSleepIntervalString(string(@State))" />
                        </td>
                        <td class="center">
                            <xsl:value-of select="@Action" />
                        </td>
                        <td class="center">
                            <xsl:call-template name="toSleepStartReason">
                                <xsl:with-param name="reason" select="@Reason" />
                            </xsl:call-template>
                        </td>
                        <td class="center">
                            <xsl:value-of select="@Id" />
                        </td>
                        <td class="center">
                            <xsl:value-of select="@Status" />
                        </td>
                        <td class="center">
                            <xsl:value-of select="@ProbablyClean" />
                        </td>
                    </tr>
                </table>
            </div>
        </div>
    </xsl:template>

    <!-- Matches the root node. This starts the XSL processing. -->
    <xsl:template match="/" >

        <html>
            <head>
                <!-- Support the latest IE -->
                <meta http-equiv="X-UA-Compatible" content="IE=edge" />

                <!-- All times are displayed using local time. Store the offset at which the report was generated in
             case someone needs to calculate the UTC times (although this is not entirely sufficient if the
             machine has moved timezones during the report period. -->
                <meta name="ReportUtcOffset" content="{$reportInfo/ssd:UtcOffset}" />

                <title>System Sleep Diagnostics</title>

                <!-- CSS styles -->
                <xsl:call-template name="css"/>

                <!-- JavaScript -->
                <xsl:call-template name="javascript">
                    <xsl:with-param name="idleTimes" select="/ssd:SystemSleepDiagnostics/ssd:UserAbsenceSessions/ssd:Session/ssd:Runtime/ssd:IdleTime" />
                </xsl:call-template>

            </head>

            <body>

                <h1>System Sleep Diagnostics</h1>

                <!-- Describe the machine -->
                <xsl:call-template name="systemInformation" />

                <!-- Summary Table -->
                <h2>User Not Present Intervals</h2>
                <xsl:apply-templates select="/ssd:SystemSleepDiagnostics/ssd:UserAbsenceSessions" mode="summaryTable" />

                <!-- Analysis results -->
                <h2>Analysis Results</h2>
                <div class="explanation">Analysis of intervals where the user went away and the machine might not have slept when the user expected it to.</div>
                <xsl:apply-templates select="/ssd:SystemSleepDiagnostics/ssd:UserAbsenceSessions" mode="analysisResults" />

                <br />
                <br />
                <br />
            </body>
        </html>
    </xsl:template>

    <ms:script implements-prefix="js">
        <![CDATA[
    // Formats a number using the current locale (to handle the 1000's separator).
    // The result is rounded so no decimal point is shown.
    function numberToLocaleString(value) {
      var localeString = Math.round(parseFloat(value + '')).toLocaleString();
      return localeString.substring(0, localeString.indexOf('.'));
    }

    function padLeft(number, length) {
      var str = '' + number;
      while (str.length < length) {
        str = '0' + str;
      }
      return str;
    }

    var dateFormat = /(\d{4})-(\d{2})-(\d{2})[T](\d{2}):(\d{2}):(\d{2})/

    // Parses a date-time string and returns a Date (i.e. number of milliseconds)
    function parseDateTime(value) {
      if (!value) {
        return 0;
      }
      var match = dateFormat.exec(value)
      if (!match) {
        return 0;
      }
      return Date.parse(match[1] + '/' + match[2] + '/' + match[3] + ' ' + match[4] + ':' + match[5] + ':' + match[6])
    }

    // Parses just the date portion of a date-time string and returns a Date (i.e. number of milliseconds)
    function parseDate(value) {
      if (!value) {
        return 0;
      }
      var match = dateFormat.exec(value)
      if (!match) {
        return 0;
      }
      return Date.parse(match[1] + '/' + match[2] + '/' + match[3])
    }

    var durationFormat = /P((\d+)D)?T((\d+)H)?((\d+)M)?(\d+)S/

    // Convert a string of the form P10DT1H15M40S to a count of milliseconds
    function parseDurationToMs(value) {
      var match = durationFormat.exec(value)
      if (!match) {
        return 0
      }
      var days = parseInt(match[2] || '0');
      var hrs = parseInt(match[4] || '0');
      var mins = parseInt(match[6] || '0');
      var secs = parseInt(match[7] || '0');
      return ((((((days * 24) + hrs) * 60) + mins) * 60) +  secs) * 1000;
    }

    // Formats a number of milliseconds as h:mm:ss
    function formatDurationMs(value) {
      var ms = parseInt(value);
      var secs = ms / 1000;
      var mins = secs / 60;
      var hrs = Math.floor(mins / 60);
      mins = Math.floor(mins % 60);
      secs = Math.floor(secs % 60);
      return hrs + ':' + padLeft(mins,2) + ':' + padLeft(secs,2);
    }

    // Converts a string representing a date time to a day and month string
    function dateToDayAndMonth(date, dayOffset) {
      var adjustedDate = new Date(parseDate(date) - (dayOffset * 24 * 60 * 60 * 1000));
      return padLeft(adjustedDate.toLocaleDateString());
    }


    // Format sleep interval strings to present a more friendly name in the
    // report.
    function createSleepIntervalString(state) {
        var _state = parseInt(state); // SYSTEM_POWER_STATE
        var str;

        if (_state == 1) {
            str = 'Working';
        } else if (_state == 2) {
            str = 'Sleeping1';
        } else if (_state == 3) {
            str = 'Sleeping2';
        } else if (_state == 4) {
            str = 'Sleeping3';
        } else if (_state == 5) {
            str = 'Hibernate';
        } else if (_state == 6) {
            str = 'Shutdown';
        } else {
            str = 'Invalid';
        }

        return str;
    }
    ]]>
    </ms:script>
</xsl:stylesheet>
P<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ms="urn:schemas-microsoft-com:xslt"
    xmlns:slp="http://schemas.microsoft.com/sleepstudy/2012"
    xmlns:js="http://microsoft.com/kernel"
    version="1.0">

  <xsl:output
      method="html"
      omit-xml-declaration="yes"
      indent="no"
      encoding="utf-16" />

  <xsl:variable name="reportInfo" select="/slp:SleepStudy/slp:ReportInformation" />
  <xsl:variable name="systemInfo" select="/slp:SleepStudy/slp:SystemInformation" />
  <xsl:variable name="reportTime" select="string($reportInfo/slp:ScanTime)" />
  <xsl:variable name="localReportTime" select="string($reportInfo/slp:LocalScanTime)" />
  <xsl:variable name="aoac" select="$systemInfo/slp:ConnectedStandby != 0"/>
  <xsl:variable name="reportDuration" select="$reportInfo/slp:ReportDuration" />
  <xsl:variable name="graphStart" select="$reportInfo/slp:LocalReportStartTime" />
  <xsl:variable name="singleTraceFile" select="$reportInfo/slp:SingleTraceFile" />

  <!-- Styles -->
  <xsl:template name="css">
    <style type="text/css">
      body {
      font-family: Segoe UI Light;
      letter-spacing: 0.02em;
      background-color: #ffffff;
      color: #000000;
      margin: 0em 5.5em 0em 5.5em;
      }

      h1 {
      color: #00b0f0;
      font-size: 42pt;
      }

      h2 {
      font-size: 15pt;
      color: #00b0f0;
      margin-top: 2em;
      margin-bottom: 0em;
      letter-spacing: 0.08em;
      }

      h3, h4, h5 {
      margin-top: 1em;
      margin-bottom: 0em;
      letter-spacing: 0.08em;
      }

      td {
      padding-left: 0.3em;
      padding-right: 0.3em;
      }

      .nobatts {
      margin-top: 1.5em;
      font-family: Segoe UI Semibold;
      background: #f0f0f0;
      color: #a0a0a0;
      font-size: 13pt;
      padding-left:0.4em;
      padding-right:0.4em;
      padding-top:0.3em;
      padding-bottom:0.3em;
      }

      .explanation {
      color: #777777;
      font-size: 12pt;
      margin-bottom: 1em;
      }

      .explanation2 {
      color: #777777;
      font-size: 12pt;
      margin-bottom: 0.1em;
      }

      table {
      border-width: 0;
      table-layout: fixed;
      font-family: Segoe UI Light;
      letter-spacing: 0.02em;
      color: #000000;
      margin-bottom: 10px;
      }

      table.defs { background-color: transparent; }

      caption {
      padding: 5px 0px 5px 0px;
      font-weight: bold;
      }

      thead {
      font-family: Segoe UI Semibold;
      font-size: 85%;
      }

      text {
      font-size: 12pt;
      font-family: Segoe UI Light;
      fill: #00b0f0;
      }

      .centered { text-align: center; }

      .label {
      font-family: Segoe UI Semibold;
      font-size: 85%;
      color: #acacac;
      }

      .labeldetails {
      text-indent: 40px;
      font-family: Segoe UI Semibold;
      font-size: 85%;
      color: #acacac;
      }

      #legend {
      background-color: #fafafa;
      margin-bottom: 2.2em;
      border-spacing: 0;
      }

      #legend thead { background-color: #dfdfdf; }
      #legend td, #legend th {
      padding: 4px 5px 4px 5px;
      }

      #legend .spanner {
      text-align: center;
      background-color: #dfdfdf;
      font-size: 85%;
      font-weight: bold;
      padding: 3px;
      }

      #legend td.percent { text-align: left; }

      .graphline-none, .graphline-dotted, .graphline-solid, .graphline-neutral,
      .graphline-low, .graphline-moderate, .graphline-high .graphline-nonclean {
      font-weight: bold;
      }

      .graphline-none { color: #7d7d7d; }
      .graphline-dotted { color: #7d7d7d; }
      .graphline-solid { color: #7d7d7d; }
      .graphline-neutral { color: #7d7d7d; }
      .graphline-low { color: #2a7a2a; }
      .graphline-moderate { color: #cc7e06; }
      .graphline-high { color: #970d00; }
      .graphline-nonclean { color: #FF00FF;}

      .top-blocker td, #summary-table td {
      padding: 0;
      }

      .top-blocker td a, #summary-table td a {
      padding: 0 0.3em 0 0.3em;
      display: block;
      height: 100%;
      }

      .top-blocker a:link, .top-blocker a:active, .top-blocker a:visited,
      #summary-table a:link, #summary-table a:active, #summary-table a:visited {
      text-decoration: none;
      color: #000000;
      }

      #summary-table th,
      .session-summary th,
      .top-blocker th,
      .pdc-phases th,
      .device-components th {
      background-color: transparent;
      }

      #summary-table tbody tr,
      .session-summary tbody tr,
      .top-blocker tbody tr,
      .device-components tbody tr,
      .pdc-phases tbody tr {
      background-color: #e0e0e0;
      }

      #summary-table .row-neutral,
      .session-summary .row-neutral,
      .top-blocker .row-neutral,
      .device-components .row-neutral,
      .pdc-phases .row-neutral {
      background-color: #e0e0e0;
      }

      #summary-table .row-low,
      .session-summary .row-low,
      .top-blocker .row-low,
      .device-components .row-low,
      .pdc-phases .row-low {
      background-color: #ace3ac;
      }

      #summary-table .row-moderate,
      .session-summary .row-moderate,
      .top-blocker .row-moderate,
      .device-components .row-moderate,
      .pdc-phases .row-moderate {
      background-color: #fcd69a;
      }

      #summary-table .row-high,
      .session-summary .row-high,
      .top-blocker .row-high,
      .device-components .row-high,
      .pdc-phases .row-high {
      background-color: #ffb2aa;
      }

      #summary-table .row-info,
      .session-summary .row-info,
      .top-blocker .row-info,
      .device-components .row-info,
      .pdc-phases .row-info {
      background-color: #86becb;
      }

      #summary-table .row-nonclean,
      .session-summary .row-nonclean,
      .top-blocker .row-nonclean,
      .device-components .row-nonclean,
      .pdc-phases .row-nonclean {
      background-color: #EE82EE;
      }

      #summary-table tbody tr:hover,
      .top-blocker tbody tr:hover {
      background-color: #f0f0f0;
      }

      #summary-table .row-neutral:hover,
      .top-blocker .row-neutral:hover {
      background-color: #f0f0f0;
      }

      #summary-table .row-low:hover,
      .top-blocker .row-low:hover {
      background-color: #caedca;
      }

      #summary-table .row-moderate:hover,
      .top-blocker .row-moderate:hover {
      background-color: #fde5c0;
      }

      #summary-table .row-high:hover,
      .top-blocker .row-high:hover {
      background-color: #ffd5d1;
      }

      #summary-table .row-nonclean:hover,
      .top-blocker .row-nonclean:hover {
      background-color:#D8BFD8;
      }

      td.colBreak { padding: 0; width: 0.15em; }

      td.state { text-align: center; }
      td.chargeOrDrain { text-align: center; }
      td.percentLowPowerStateTime { text-align: center; }
      td.percent { font-family: Segoe UI Symbol; text-align: center; }
      td.hms { font-family: Segoe UI Symbol; text-align: center; }
      td.dateTime { font-family: Segoe UI Symbol; }
      td.blank { background-color: #ffffff; }
      td.nullValue { text-align: center; }
      td.center { text-align: center; }

      col.percent { width: 7.5em; }

      td.mw {
      font-family: Segoe UI Symbol;
      text-align: center;
      }

      td.acdc { text-align: center; }

      span.date {
      display: inline-block;
      width: 5.5em;
      }

      span.time {
      text-align: right;
      width: 4.2em;
      display: inline-block;
      }

      text { font-family: Segoe UI Symbol; }

      .noncontigbreak {
      height: 0.3em;
      background-color: #1A1A28;
      }

      div.analysis-container {
      margin-bottom: 10px;
      border: 1px solid #ffffff;
      }

      div.analysis-container h1 {
      padding: 10px;
      font-size: 14px;
      margin: 0px;
      cursor: pointer;
      }

      div.analysis-body, div.analysis-body-collapsed {
      padding: 10px;
      }

      div.analysis-body { display: block; }
      div.analysis-body-collapsed { display: none; }

      .analysis-base { background-color: #f7f7f7; }
      .analysis-base h1 { color: #a0a0a0; background-color: #d0d0d0; }
      .analysis-base h1:hover { background-color: #dfdfdf; }

      .analysis-neutral { background-color: #f0f0f0; }
      .analysis-neutral h1 { color: #a0a0a0; background-color: #d0d0d0; }
      .analysis-neutral h1:hover { background-color: #dfdfdf; }

      .analysis-high { background-color: #ffd5d1; }
      .analysis-high h1 { background-color: #ff8e83; color: #970d00; }
      .analysis-high h1:hover { background-color: #ffb2aa; }

      .analysis-moderate { background-color: #fde5c0; }
      .analysis-moderate h1 { background-color: #fbc674; color: #cc7e06; }
      .analysis-moderate h1:hover { background-color: #fcd69a; }

      .analysis-low { background-color: #caedca; }
      .analysis-low h1 { background-color: #8fd98f; color: #2a7a2a; }
      .analysis-low h1:hover { background-color: #ace3ac; }

      .analysis-info { background-color: #b2e5e5; }
      .analysis-info h1 { background-color: #1aa3a3; color: #0b5e56; }
      .analysis-info h1:hover { background-color: #86becb; }

      .analysis-empty {
      color: #a0a0a0;
      font-size: 14px;
      padding: 10px;
      font-weight: bold;
      }
    </style>
    <!-- split the css into two style tags to get around the locstudio 8192 character limit -->
    <style>
      .expander { font-family: "Consolas"; font-weight: bold; }
      .warning { background-color: #fde5c0; }
      .warning h1 { background-color: #fbc674; color: #cc7e06; }
      .warning h1:hover { background-color: #fcd69a; }
      .error { background-color: #ffd5d1; }
      .error h1 { background-color: #ff8e83; color: #970d00; }
      .error h1:hover { background-color: #ffb2aa; }
      code { font-family: "Consolas"; }

      pre {
      font-family: "Consolas";
      display: block;
      border: 1px dashed #b0b0b0;
      padding: 10px;
      margin: 10px 0px 10px 0px;
      }

      .scroll-top-button {
      border: 2px solid #000000;
      background-color: #ffffff;
      padding: 5px 3px 5px 3px;
      font-size: 12px;
      font-family: Segoe UI Semibold;
      float: left;
      border-radius: 18px;
      margin-top: 15px;
      margin-left: -60px;
      }

      .scroll-top-button:hover {
      background-color: #f0f0f0;
      cursor: pointer;
      }

      .scenario-details, .scenario-details-collapsed {
      padding: 5px;
      background-color: #f0f0f0;
      width: 864px;
      border-left: 2px solid #ffffff;
      }

      .scenario-details { display: block; }
      .scenario-details-collapsed { display: none; }

      .details-expander {
      background-color: #dfdfdf;
      font-weight: bold;
      cursor: pointer;
      }

      .details-expander:hover { background-color: #cfcfcf; }

      ul { list-style: square; }
    </style>
  </xsl:template>

  <!-- JavaScript for the page -->
  <xsl:template name="jsUtil">
    <xsl:text disable-output-escaping="yes">
    // Add support for drawing dashed lines to Canvas
    CanvasRenderingContext2D.prototype.dashedLine = function (x0, y0, x1, y1, dashArray) {
        if (dashArray == null) {
            dashArray = [4, 4];
        }

        var dx = x1 - x0;
        var dy = y1 - y0;
        var distance = Math.sqrt(Math.pow((x1 - x0), 2) + Math.pow((y1 - y0), 2));
        var theta = Math.atan(dy / dx);
        if (dx &lt; 0) {
            theta += Math.PI;
        }

        var i = 0;
        while (distance &gt; 0) {
            var length = Math.min(distance, dashArray[i]);
            x0 += length * Math.cos(theta);
            y0 += length * Math.sin(theta);
            if (i % 2 == 0) {
                this.lineTo(x0, y0);

            } else {
                this.moveTo(x0, y0);
            }

            distance -= length;
            i = (i + 1) % dashArray.length;
        }
    };
    </xsl:text>
  </xsl:template>

  <xsl:template name="jsDateUtil">
    <xsl:text disable-output-escaping="yes">
    // Formats a number using the current locale (to handle the 1000's separator).
    // The result is rounded so no decimal point is shown.
    function numberToLocaleString(value) {
        var localeString = Math.round(parseFloat(value + '')).toLocaleString();
        return localeString.substring(0, localeString.indexOf('.'));
    }

    function padLeft(number, length) {
        var str = '' + number;
        while (str.length &lt; length) {
            str = '0' + str;
        }

        return str;
    }

    // Returns the number of milliseconds between 2 date-times represented as strings.
    function msBetween(startTime, endTime) {
        return startTime &gt; endTime
               ? msBetween(endTime, startTime)
               : parseDateTime(endTime) - parseDateTime(startTime);
    }

    var dateFormat = /(\d{4})-(\d{2})-(\d{2})[T](\d{2}):(\d{2}):(\d{2})/

    // Parses a date-time string and returns a Date (i.e. number of milliseconds)
    function parseDateTime(value) {
        if (!value) {
            return 0;
        }

        var match = dateFormat.exec(value)
        if (!match) {
            return 0;
        }

        return Date.parse(match[1] + '/' + match[2] + '/' +
                          match[3] + ' ' + match[4] + ':' +
                          match[5] + ':' + match[6])
    }

    // Parses just the date portion of a date-time string and returns a Date
    // (i.e. number of milliseconds)
    function parseDate(value) {
        if (!value) {
            return 0;
        }

        var match = dateFormat.exec(value)
        if (!match) {
            return 0;
        }

        return Date.parse(match[1] + '/' + match[2] + '/' + match[3])
    }

    var durationFormat = /P((\d+)D)?T((\d+)H)?((\d+)M)?(\d+)S/

    // Convert a string of the form P10DT1H15M40S to a count of milliseconds
    function parseDurationToMs(value) {
        var match = durationFormat.exec(value)
        if (!match) {
            return 0
        }

        var days = parseInt(match[2] || '0');
        var hrs = parseInt(match[4] || '0');
        var mins = parseInt(match[6] || '0');
        var secs = parseInt(match[7] || '0');
        return ((((((days * 24) + hrs) * 60) + mins) * 60) +  secs) * 1000;
    }

    // Converts milliseconds to days
    function msToDays(ms) {
        return (ms / 1000 / 60 / 60 / 24);
    }

    function daysToMs(days) {
        return (days * 24 * 60 * 60 * 1000);
    }

    // Formats a number of milliseconds as h:mm:ss
    function formatDurationMs(value) {
        var ms = parseInt(value);
        var secs = ms / 1000;
        var mins = secs / 60;
        var hrs = Math.floor(mins / 60);
        mins = Math.floor(mins % 60);
        secs = Math.floor(secs % 60);
        return hrs + ':' + padLeft(mins,2) + ':' + padLeft(secs,2);
    }

    // Converts a millisecond timestamp to a day and month string
    // Note: dayOffset is forward from date.
    function dateToDayAndMonth(ms, dayOffset) {
        var adjustedDate = new Date(ms + (dayOffset * 24 * 60 * 60 * 1000));
        return padLeft(adjustedDate.getMonth() + 1, 2) + "-" +
               padLeft(adjustedDate.getDate(), 2);
    }

    // Takes a millisecond timestamp and returns a new millisecond timestamp
    // rounded down to the current day.
    function dateFloor(ms) {
        var dt = new Date(ms);
        return Date.parse(dt.getFullYear() + '/' + (dt.getMonth() + 1) + '/' + dt.getDate());
    }

    var osstate = "All";
    var duration = "Alltime";

  // Actions values based on os power state radio button selection.
  function osStateValueChanged() {
    if (document.getElementById('is_bug_session').checked) {
        osstate = document.getElementById("is_bug_session").value;
    } else if (document.getElementById('is_all_session').checked) {
        osstate = document.getElementById("is_all_session").value;
    } else if (document.getElementById('is_shutdown_session').checked) {
        osstate = document.getElementById("is_shutdown_session").value;
    } else if (document.getElementById('is_screenoff_session').checked) {
        osstate = document.getElementById("is_screenoff_session").value;
    } else if (document.getElementById('is_sleep_session').checked) {
        osstate = document.getElementById("is_sleep_session").value;
    } else if (document.getElementById('is_hib_session').checked) {
        osstate = document.getElementById("is_hib_session").value;
    } else if (document.getElementById('is_active_session').checked) {
        osstate = document.getElementById("is_active_session").value;
    }

    searchTable(osstate, duration);
  }

  // Actions values based on "duration" radio button selection.
  function durationValueChanged() {
    if (document.getElementById('is_all_time').checked) {
        duration = document.getElementById("is_all_time").value;

    } else if (document.getElementById('is_10_session').checked) {
        duration = document.getElementById("is_10_session").value;
    }

    searchTable(osstate, duration);
  }

  // Summary table selection logic based on radio button selection.
  function searchTable(osstate, duration) {
    var foundstate, foundduration, table, tr, td, i, j, k;
    table = document.getElementById("summary-table");
    tr = table.getElementsByTagName("tr");
    for (i = 0; i &lt; tr.length; i++) {
        td = tr[i].getElementsByTagName("td");
        //TODO: to optimize this we need to use getElementsByClassName.
        for (j = 0; j &lt; td.length; j++) {
            if (td[j].className == "hms") {
                if (duration == "10:00") {
                    var dur = td[j].textContent;
                    var HourNum = parseInt(dur);
                    var subduration = dur.substr(dur.indexOf(":") + 1);
                    var MinNum = parseInt(subduration);
                    if (HourNum >=1 || MinNum >= 10) {
                        foundduration = true;
                    }
                }
            }

            if ((osstate != "All") &amp;&amp; td[j].className == "state") {
                // in case of shutdown compare with all shutdown variant.
                if ((osstate == "Shutdown")) {
                    if ((td[j].textContent == "Shutdown") || (td[j].textContent == "Shutdown (Hybrid)")) {
                        foundstate = true;
                    }
                }
                // in case of standby AoAc or S3, compare sleep
                if ((osstate == "Standby")) {
                    if ((td[j].textContent == "Sleep") || (td[j].textContent == "Sleep (Hybrid)")) {
                        foundstate = true;
                    }
                }
                // in case of screen off, compare screen off.
                if ((osstate == "ScreenOff")) {
                    if ((td[j].textContent == "Screen Off")) {
                        foundstate = true;
                    }
                }

                if (osstate == "Bug Check") {
                    if ((td[j].textContent == "Bugcheck") || (td[j].textContent == "Abnormal Shutdown")) {
                        foundstate = true;
                    }

                } else if (td[j].textContent == osstate) {
                    foundstate = true;
                }
            }
        } // end of inner for loop.

        // make decision what to show and what to hide.
        if (duration == "10:00" &amp;&amp; (osstate != "All")) {
            if (foundstate &amp;&amp; foundduration) {
                tr[i].style.display = "";
                foundstate = false;
                foundduration = false;

            } else {
                if (td.length) {
                    tr[i].style.display = "none";
                }
            }
        }

        if (duration == "10:00" &amp;&amp; (osstate == "All")) {
            if (foundduration) {
                tr[i].style.display = "";
                foundstate = false;
                foundduration = false;

            } else {
                if (td.length) {
                    tr[i].style.display = "none";
                }
            }
        }

        if (duration == "Alltime" &amp;&amp; (osstate == "All")) {
            tr[i].style.display = "";
            foundstate = false;
            foundduration = false;
        }

        if (duration == "Alltime" &amp;&amp; (osstate != "All")) {
            if (foundstate) {
                tr[i].style.display = "";
                foundstate = false;
                foundduration = false;

            } else {
                if (td.length) {
                    tr[i].style.display = "none";
                }
            }
        }

        foundstate = false;
        foundduration = false;
    }
}
    </xsl:text>
  </xsl:template>

  <xsl:template name="jsTimegraph">
    <xsl:text disable-output-escaping="yes">
    Timegraph = {
        axisTop: 9.5,
        axisRight: 24.5,
        axisBottom: 25.5,
        axisLeft: 25.5,
        ticks: 10,

        // Maximum number of 24 hour ticks for showing 12 and 6 hour ticks

        ticks12Hour: 8,
        ticks6Hour: 4,

        // Shading

        shadingColor: "#d0d0d0",

        precompute: function (graph) {
            var canvas = graph.canvas;
            var data = graph.data;
            var min = 0;
            var max = 0;

            graph.height = canvas.height - Timegraph.axisTop - Timegraph.axisBottom;
            graph.width = canvas.width - Timegraph.axisLeft - Timegraph.axisRight;
            for (var i = 0; i &lt; data.length; i++) {
                data[i].t0 = parseDateTime(data[i].x0);
                data[i].t1 = parseDateTime(data[i].x1);

                if (i == 0) {
                    min = data[i].t0;
                    max = data[i].t1;
                }

                if (data[i].t0 &lt; min) {
                    min = data[i].t0;
                }

                if (data[i].t1 &gt; max) {
                    max = data[i].t1;
                }

                data[i].yy0 =
                    Timegraph.axisTop + graph.height - data[i].y0 * graph.height;

                data[i].yy1 =
                    Timegraph.axisTop + graph.height - data[i].y1 * graph.height;
            }

            if (graph.startTime != null) {
                graph.startMs = parseDateTime(graph.startTime);

            } else {
                graph.startMs = min;
            }

            graph.endMs = max;
            graph.durationMs = max - min;
        },

        drawFrame: function (graph) {
            var canvas = graph.canvas;
            var context = graph.context;

            graph.width =
                canvas.width - Timegraph.axisRight - Timegraph.axisLeft;

            graph.height =
                canvas.height - Timegraph.axisTop - Timegraph.axisBottom;

            context.beginPath();
            context.moveTo(Timegraph.axisLeft, Timegraph.axisTop);
            context.lineTo(Timegraph.axisLeft + graph.width,
                           Timegraph.axisTop);

            context.lineTo(Timegraph.axisLeft + graph.width,
                           Timegraph.axisTop + graph.height);

            context.lineTo(Timegraph.axisLeft,
                           Timegraph.axisTop + graph.height);

            context.lineTo(Timegraph.axisLeft, Timegraph.axisTop);
            context.strokeStyle = "#c0c0c0";
            context.stroke();
        },

        drawRange: function (graph) {
            var canvas = graph.canvas;
            var context = graph.context;

            context.font = "12pt Segoe UI";
            context.fillStyle = "#00b0f0";
            context.fillText("%", 0, Timegraph.axisTop + 5, Timegraph.axisLeft);

            var tickSpacing = graph.height / 10;
            var offset = Timegraph.axisTop + tickSpacing;
            var tickValue = 90;
            for (var i = 0; i &lt; 9; i++) {
                context.beginPath();
                context.moveTo(Timegraph.axisLeft, offset);
                context.lineTo(Timegraph.axisLeft + graph.width,
                               offset);

                context.stroke();
                context.fillText(tickValue.toString(),
                                 0,
                                 offset + 5,
                                 Timegraph.axisLeft);

                offset += tickSpacing;
                tickValue -= 10;
            }
        },

        drawDomain: function (graph, start, end) {
            var canvas = graph.canvas;
            var context = graph.context;
            var data = graph.data;
            var duration = end - start;
            if ((end &lt; start)) {
                return;
            }

            var startDay = dateFloor(start);
            var t0 = startDay;
            var t1 = dateFloor(end);
            var dayOffset = 0;
            if (start &gt; t0) {
                t0 = t0 + daysToMs(1);
                dayOffset++;
            }

            if (t0 &gt;= t1) {
                return;
            }

            var increment =
                Math.max(Math.floor((t1 - t0) / daysToMs(Timegraph.ticks)), 1);

            var incrementMs = daysToMs(increment);
            var spacing = (incrementMs / duration) * graph.width;
            var offset = (t0 - start) / duration;
            var ticksCount = Math.floor((t1 - t0) / incrementMs);
            for (offset = offset * graph.width + Timegraph.axisLeft;
                 offset &lt; (graph.width + Timegraph.axisLeft);
                 offset += spacing) {

                context.beginPath();
                context.moveTo(offset, Timegraph.axisTop);
                context.lineTo(offset, Timegraph.axisTop + graph.height);
                context.stroke();
                context.fillText(dateToDayAndMonth(startDay, dayOffset),
                                 offset,
                                 Timegraph.axisTop + graph.height + 15,
                                 spacing);

                dayOffset += increment;
            }
        },

        plot: function (graph, start, end) {
            var canvas = graph.canvas;
            var context = graph.context
            var data = graph.data;

            if ((end &lt; start)) {
                return;
            }

            var duration = end - start;
            Timegraph.drawDomain(graph, start, end);
            context.fillStyle = Timegraph.shadingColor;
            for (var i = 0; i &lt; data.length - 1; i++) {
                if ((data[i].t0 &lt; start) || (data[i].t0 &gt; end) ||
                    (data[i].t1 &gt; end)) {

                    continue;
                }

                var x1 = (data[i].t0 - start) / duration;
                x1 = x1 * graph.width + Timegraph.axisLeft;

                var x2 = (data[i].t1 - start) / duration;
                x2 = x2 * graph.width + Timegraph.axisLeft;

                context.globalAlpha = 0.3;
                context.fillRect(x1, Timegraph.axisTop, (x2 - x1), graph.height);
                context.globalAlpha = 1;
                context.beginPath();
                context.strokeStyle = graph.lineTypes[data[i].type].color;
                context.lineWidth = 1.5;
                if (graph.lineTypes[data[i].type].dotted == 1) {
                    context.dashedLine(x1, data[i].yy0, x2, data[i].yy1);

                } else {
                    context.moveTo(x1, data[i].yy0);
                    context.lineTo(x2, data[i].yy1);
                }

                context.stroke();
            }
        },

        draw: function (graph) {
            var canvas = document.getElementById(graph.element);
            if (canvas == null) {
                return;
            }

            var context = canvas.getContext('2d');
            if (context == null) {
                return;
            }

            graph.width = 0;
            graph.height = 0;
            graph.context = context;
            graph.canvas = canvas;

            Timegraph.precompute(graph);
            Timegraph.drawFrame(graph);
            Timegraph.drawRange(graph);
            Timegraph.plot(graph, graph.startMs, graph.endMs);
        }
    };
    </xsl:text>
  </xsl:template>

  <xsl:template name="jsHistogram">
    <xsl:text disable-output-escaping="yes">
    Histogram = {

        // Constants

        yTicks: 10,
        axisLeft: 30.5,
        axisBottom: 25.5,
        paddingTop: 5,
        maxPadding: 25,
        barColor: "#1191c1",

        // Functions

        precompute: function (graph) {
            var canvas = graph.canvas;
            var bucketCount = 0;
            for (var i = 0; i &lt; graph.data.length; i++) {
                if (graph.data[i].value > graph.max) {
                    graph.max = graph.data[i].value;
                }

                bucketCount++;
            }

            if (graph.rangeMax != null) {
                graph.max = Math.max(graph.max, graph.rangeMax);
            }

            graph.bucketCount = bucketCount;
            graph.tickSpacing = (canvas.width - Histogram.axisLeft) / bucketCount;
            graph.height = canvas.height;
            graph.width = canvas.width;
        },

        drawFrame: function (graph) {
            var context = graph.context;
            var canvas = graph.canvas;

            context.beginPath();
            context.moveTo(Histogram.axisLeft, Histogram.paddingTop);
            context.lineTo(Histogram.axisLeft,
                           canvas.height - Histogram.axisBottom);

            context.lineTo(canvas.width,
                           canvas.height - Histogram.axisBottom);

            context.stroke();
        },

        drawDomain: function (graph) {
            var context = graph.context;
            var tickOffset = 0;

            context.font = "8pt Segoe UI";
            context.fillStyle = "#00b0f0";
            for (var i = 0; i &lt; graph.bucketCount; i++) {
                context.fillText(graph.data[i].interval,
                                 Histogram.axisLeft + tickOffset + 2,
                                 graph.height - 10,
                                 graph.tickSpacing);

                tickOffset += graph.tickSpacing;
            }
        },

        drawRange: function (graph) {
            var context = graph.context;
            var tickSpacing = (graph.height - Histogram.axisBottom - 25) /
                              Histogram.yTicks;

            var tickIncrement = Math.round(graph.max / Histogram.yTicks);
            var tickOffset = graph.height - Histogram.axisBottom -
                             tickSpacing;

            var tickValue = tickIncrement;
            context.font = "12pt Segoe UI";
            context.fillStyle = "#00b0f0";
            for (var i = 0; i &lt; Histogram.yTicks; i++) {
                context.beginPath();
                context.moveTo(Histogram.axisLeft, tickOffset);
                context.lineTo(Histogram.axisLeft + 5, tickOffset);
                context.stroke();
                context.fillText(tickValue.toString(),
                                 0,
                                 tickOffset + 5,
                                 Histogram.axisLeft);

                tickValue += tickIncrement;
                tickOffset -= tickSpacing;
            }
        },

        plot: function (graph) {
            var tickOffset = 0;
            var context = graph.context;
            context.fillStyle = Histogram.barColor;
            for (var i = 0; i &lt; graph.bucketCount; i++) {
                if (graph.data[i].value == 0) {
                    tickOffset += graph.tickSpacing;;
                    continue;
                }

                var barHeight =
                    Math.round((graph.data[i].value * (graph.height - 50)) / graph.max);

                context.fillRect(Histogram.axisLeft + tickOffset + Histogram.paddingTop,
                                 graph.height - Histogram.axisBottom - barHeight,
                                 graph.tickSpacing - 10,
                                 barHeight);

                tickOffset += graph.tickSpacing;
            }
        },

        draw: function (graph) {
            var canvas = document.getElementById(graph.element);
            if (canvas == null) {
                return;
            }

            var context = canvas.getContext("2d");
            if (context == null) {
                return;
            }

            if (graph.data == null) {
                return;
            }

            graph.bucketCount = 0;
            graph.max = 0;
            graph.tickSpacing = 0;
            graph.width = 0;
            graph.height = 0;
            graph.context = context;
            graph.canvas = canvas;

            context.strokeStyle = "#c0c0c0";

            Histogram.precompute(graph);
            Histogram.drawFrame(graph);
            Histogram.drawRange(graph);
            Histogram.drawDomain(graph);
            Histogram.plot(graph);
        }
    };
    </xsl:text>
  </xsl:template>

  <xsl:template name="jsCollapser">
    <xsl:text disable-output-escaping="yes">
    Collapser = {
        topActiveBlockerDivs: {},
        detailsContainers: {},

        getContainerBody: function (container) {
            var children = container.childNodes;
            var containerBody = null;
            for (var i = 0; i &lt; children.length; i++) {
                if (children[i].tagName == "DIV" &amp;&amp;
                    (children[i].className == "analysis-body-collapsed" ||
                     children[i].className == "analysis-body")) {

                    containerBody = children[i];
                    break;
                }
            }

            return containerBody;
        },

        togglePanel: function (container) {
            var containerBody = Collapser.getContainerBody(container);
            if (containerBody == null) {
                return;
            }

            var heading = container.getElementsByTagName("H1")[0];
            var expander = heading.getElementsByClassName("expander")[0];
            if (containerBody.className == "analysis-body-collapsed") {
                containerBody.className = "analysis-body";
                expander.innerHTML = "- ";

            } else {
                containerBody.className = "analysis-body-collapsed";
                expander.innerHTML = "+ ";
            }
        },

        toggleDetails: function (element) {
            if (element.className == "scenario-details-collapsed") {
                element.className = "scenario-details";

            } else {
                element.className = "scenario-details-collapsed";
            }
        },

        initializePanels: function () {
            var elements = document.getElementsByClassName("analysis-container");
            for (var i = 0; i &lt; elements.length; i++) {
                var element = elements[i];
                var heading = element.getElementsByTagName("h1")[0];
                if (heading == null) {
                    continue;
                }

                heading.onclick = function () {
                    var container = this.parentNode;
                    Collapser.togglePanel(container);
                };
            }
        },

        initializeDetails: function() {
            var elements = document.getElementsByClassName("details-expander");
            for (var i = 0; i &lt; elements.length; i++) {
                var element = elements[i];
                var targetId = "details-" + element.id.replace("details-expand-", "");
                var targetElement = document.getElementById(targetId);
                Collapser.detailsContainers[element.id] = targetElement;
                element.onclick = function () {
                    var targetElement = Collapser.detailsContainers[this.id];
                    Collapser.toggleDetails(targetElement);
                };
            }
        },

        initializeLinks: function () {
            var links = document.getElementsByClassName("top-active-link");
            for (var i = 0; i &lt; links.length; i++) {
                var link = links[i];
                var targetId = link.getAttribute("href").substring(1);
                var targetElement = document.getElementById(targetId);
                if (targetElement.tagName.toLowerCase() == "tr") {
                    // tr, tbody, table, div.analysis-body-*, div.analysis-container
                    Collapser.topActiveBlockerDivs[targetId] =
                        targetElement.parentNode.parentNode.parentNode.parentNode;

                } else {
                    Collapser.topActiveBlockerDivs[targetId] = targetElement;
                }

                link.onclick = function () {
                    var targetId = this.getAttribute("href").substring(1);
                    var targetContainer = Collapser.topActiveBlockerDivs[targetId];
                    var container = targetContainer;
                    while ((container != null) &amp;&amp; (container.tagName == "DIV")) {
                        var containerBody = Collapser.getContainerBody(container);
                        if (containerBody == null) {
                            return;
                        }

                        if (containerBody.className == "analysis-body-collapsed") {
                            Collapser.togglePanel(container);
                        }

                        container = container.parentNode.parentNode;
                    }

                    targetContainer.scrollIntoView(true);
                };
            }
        },

        initializeCollapser: function () {
            Collapser.initializePanels();
            Collapser.initializeDetails();
            TableDecorator.decorate({
                element: ".top-blocker",
                withClass: "top-active-link"
            });

            Collapser.initializeLinks();
        },

        initialize: function () {
            if (window.addEventListener != null) {
                window.addEventListener("load", Collapser.initializeCollapser, false);

            } else if (window.attachEvent != null) {
                window.attachEvent("onload", Collapser.initializeCollapser);
            }
        }
    };
    </xsl:text>
  </xsl:template>

  <xsl:template name="jsTableDecorator">
    <xsl:text disable-output-escaping="yes">
    TableDecorator = {
        decorateTable: function (table, linkClass) {
            if (table == null) {
                return;
            }

            var rows = table.getElementsByTagName("tr");
            for (var i = 0; i &lt; rows.length; i++) {
                var row = rows[i];
                var anchor = row.getElementsByClassName("row-link")[0];
                if (anchor == null || anchor.tagName.toLowerCase() != "a") {
                    continue;
                }

                var link = anchor.getAttribute("href");
                for (var j = 0; j &lt; row.children.length; j++) {
                    var cell = row.children[j];
                    if (cell == anchor.parentNode) {
                        continue;
                    }

                    var classString = "";
                    if (linkClass != null) {
                        classString = " class=\"" + linkClass + "\"";
                    }

                    cell.innerHTML =
                        "&lt;a href=\"" + link + "\"" + classString + "&gt;" +
                        cell.innerHTML + "&lt;/a&gt;";
                }
            }
        },

        decorate: function (tableData) {
            var selection = tableData.element;
            if (selection.charAt(0) == ".") {
                var className = selection.substring(1);
                var elements = document.getElementsByClassName(className);
                for (var i = 0; i &lt; elements.length; i++) {
                    if (elements[i].tagName.toLowerCase() == "table") {
                        TableDecorator.decorateTable(elements[i], tableData.withClass);
                    }
                }

            } else if (selection.charAt(0) == "#") {
                var idName = selection.substring(1);
                var element = document.getElementById(idName);
                if (element.tagName.toLowerCase() == "table") {
                    TableDecorator.decorateTable(element, tableData.withClass);
                }
            }
        },
    };
    </xsl:text>
  </xsl:template>

  <xsl:template name="jsScrollTop">
    <xsl:text disable-output-escaping="yes">
    function initializeScrollTop() {
        var elements = document.getElementsByClassName("scroll-top-button");
        for (var i = 0; i &lt; elements.length; i++) {
            var element = elements[i];
            element.onclick = function () {
                window.scroll(0, 0);
                window.location.replace("#");
                if (typeof window.history.replaceState == "function") {
                    history.replaceState({}, "", window.location.href.slice(0, -1));
                }
            }
        }
    }
    </xsl:text>
  </xsl:template>

  <xsl:template name="javascript">
    <xsl:param name="sessions" />
    <xsl:param name="dripsBuckets" />
    <xsl:param name="energyDrains" />

    <script type="text/javascript">
      <xsl:call-template name="jsUtil" />
      <xsl:call-template name="jsDateUtil" />
      <xsl:call-template name="jsTimegraph" />
      <xsl:call-template name="jsHistogram" />
      <xsl:call-template name="jsScrollTop" />
      <xsl:call-template name="jsCollapser" />
      <xsl:call-template name="jsTableDecorator" />
      Collapser.initialize();

      <xsl:apply-templates select="$sessions" mode="jsScreenOnHistograms" />
      <xsl:apply-templates select="$dripsBuckets" mode="jsDripsBuckets" />
      <xsl:apply-templates select="$energyDrains" mode="jsEnergyDrains" />

      <xsl:text disable-output-escaping="yes">
    drainGraphLineTypes = [
        { color: "none", dotted: 0 },
        { color: "#7d7d7d", dotted: 0 },
        { color: "#2a7a2a", dotted: 0 },
        { color: "#cc7e06", dotted: 0 },
        { color: "#970d00", dotted: 0 },
        { color: "#7d7d7d", dotted: 1 },
        { color: "#2a7a2a", dotted: 1 },
        { color: "#cc7e06", dotted: 1 },
        { color: "#970d00", dotted: 1 },
    ];

    function main() {
    </xsl:text>
      <xsl:if test="$singleTraceFile = 'false'">
        <xsl:text disable-output-escaping="yes">
        TableDecorator.decorate({element: "#summary-table"});
      </xsl:text>
      </xsl:if>
      <xsl:apply-templates select="$sessions" mode="jsMainScreenOnHistograms" />
      <xsl:apply-templates select="$dripsBuckets" mode="jsMainDripsBuckets" />
      <xsl:text disable-output-escaping="yes">
        Timegraph.draw({
            element: "drain-graph",
            data: drainGraphData,
            lineTypes: drainGraphLineTypes,
            startTime: "</xsl:text><xsl:value-of select="$graphStart" /><xsl:text disable-output-escaping="yes">",
            endTime: "</xsl:text><xsl:value-of select="$reportInfo/slp:LocalScanTime" /><xsl:text disable-output-escaping="yes">"
        });

        initializeScrollTop();
    }

    if (window.addEventListener != null) {
        window.addEventListener("load", main, false);

    } else if (window.attachEvent != null) {
        window.attachEvent("onload", main);
    }
    </xsl:text>
    </script>
  </xsl:template>

  <xsl:template match="slp:Drain" mode="jsEnergyDrains">
    <xsl:text>{ </xsl:text>
    <xsl:text>x0: "</xsl:text>
    <xsl:value-of select="@LocalStartTimestamp" />
    <xsl:text>", </xsl:text>
    <xsl:text>x1: "</xsl:text>
    <xsl:value-of select="@LocalEndTimestamp" />
    <xsl:text>", </xsl:text>
    <xsl:text>y0: </xsl:text>
    <xsl:value-of select="@StartChargeCapacity div @StartFullChargeCapacity" />
    <xsl:text>, </xsl:text>
    <xsl:text>y1: </xsl:text>
    <xsl:value-of select="@EndChargeCapacity div @EndFullChargeCapacity" />
    <xsl:text>, </xsl:text>
    <xsl:text>type: </xsl:text>
    <xsl:variable name="activityType">
      <xsl:choose>
        <xsl:when test="@Activity = 'low'">2</xsl:when>
        <xsl:when test="@Activity = 'moderate'">3</xsl:when>
        <xsl:when test="@Activity = 'high'">4</xsl:when>
        <xsl:otherwise>1</xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="acType">
      <xsl:choose>
        <xsl:when test="@Ac = 0">0</xsl:when>
        <xsl:otherwise>4</xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:value-of select="$activityType + $acType" />
    <xsl:text>}, &#xa;</xsl:text>
  </xsl:template>

  <xsl:template match="slp:EnergyDrains" mode="jsEnergyDrains">
    <xsl:text>
    drainGraphData = [
    </xsl:text>
    <xsl:apply-templates select="slp:Drain" mode="jsEnergyDrains" />
    <xsl:text>
    ];
    </xsl:text>
  </xsl:template>

  <xsl:template match="slp:DripsBuckets" mode="jsMainDripsBuckets">
    <xsl:text>
    Histogram.draw({
        element: "drips-histogram-</xsl:text>
    <xsl:value-of select="slp:DripBucketId/@DripBucketUniqueId"/>
    <xsl:text>",
        data: dripsBuckets_</xsl:text>
    <xsl:value-of select="position()" />
    <xsl:text>,
        rangeMax: 100
    });&#xa;</xsl:text>
  </xsl:template>

  <xsl:template match="slp:DripsBuckets" mode="jsDripsBuckets">
    <xsl:text>dripsBuckets_</xsl:text>
    <xsl:value-of select="position()" />
    <xsl:text> = [&#xa;</xsl:text>
    <xsl:apply-templates select="slp:DripsBucket" mode="jsDripsBuckets" />
    <xsl:text>
      ];
    </xsl:text>
  </xsl:template>

  <xsl:template match="slp:DripsBucket" mode="jsDripsBuckets">
    <xsl:text>{ interval : "</xsl:text>
    <xsl:value-of select="@Interval" />
    <xsl:text>", value : </xsl:text>
    <xsl:value-of select="@TotalTimePercent" />
    <xsl:text> },&#xa;</xsl:text>
    <xsl:text></xsl:text>
  </xsl:template>

  <xsl:template match="slp:ScenarioInstances" mode="jsMainScreenOnHistograms">
    <xsl:choose>
      <xsl:when test="boolean(slp:ScenarioInstance|slp:OsStateInstance|slp:RecentUsageInstance)  and boolean(slp:OsStateInstance)">
        <xsl:apply-templates select="*" mode="jsMainBrightnessDuration">
          <xsl:sort select="@OsStateId" data-type="number" order="ascending"/>
        </xsl:apply-templates>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="*" mode="jsMainBrightnessDuration">
          <xsl:sort select="@LocalTimestamp"/>
        </xsl:apply-templates>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:choose>
      <xsl:when test="boolean(slp:ScenarioInstance|slp:OsStateInstance|slp:RecentUsageInstance)  and boolean(slp:OsStateInstance)">
        <xsl:apply-templates select="*" mode="jsMainLuxDuration">
          <xsl:sort select="@OsStateId" data-type="number" order="ascending"/>
        </xsl:apply-templates>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="*" mode="jsMainLuxDuration">
          <xsl:sort select="@LocalTimestamp"/>
        </xsl:apply-templates>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="slp:ScenarioInstances" mode="jsScreenOnHistograms">
    <xsl:choose>
      <xsl:when test="boolean(slp:ScenarioInstance|slp:OsStateInstance|slp:RecentUsageInstance)  and boolean(slp:OsStateInstance)">
        <xsl:apply-templates select="*" mode="jsBrightnessDuration">
          <xsl:sort select="@OsStateId" data-type="number" order="ascending"/>
        </xsl:apply-templates>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="*" mode="jsBrightnessDuration">
          <xsl:sort select="@LocalTimestamp"/>
        </xsl:apply-templates>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:choose>
      <xsl:when test="boolean(slp:ScenarioInstance|slp:OsStateInstance|slp:RecentUsageInstance)  and boolean(slp:OsStateInstance)">
        <xsl:apply-templates select="*" mode="jsLuxDuration">
          <xsl:sort select="@OsStateId" data-type="number" order="ascending"/>
        </xsl:apply-templates>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="*" mode="jsLuxDuration">
          <xsl:sort select="@LocalTimestamp"/>
        </xsl:apply-templates>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="slp:ScenarioInstance|slp:OsStateInstance|slp:RecentUsageInstance" mode="jsMainBrightnessDuration">
    <xsl:if test="slp:ScreenBrightnessHistogram">
      <xsl:text>
      Histogram.draw({
          element: "brightness-duration-</xsl:text>
      <xsl:value-of select="position()" />
      <xsl:text>",
          data: brightnessDuration_</xsl:text>
      <xsl:value-of select="position()" />
      <xsl:text>,
          rangeMax: 1
      });&#xa;</xsl:text>
    </xsl:if>
  </xsl:template>

  <xsl:template match="slp:ScenarioInstance|slp:OsStateInstance|slp:RecentUsageInstance" mode="jsBrightnessDuration">
    <xsl:if test="slp:ScreenBrightnessHistogram">
      <xsl:text>brightnessDuration_</xsl:text>
      <xsl:value-of select="position()" />
      <xsl:text> = [&#xa;</xsl:text>
      <xsl:apply-templates select="slp:ScreenBrightnessHistogram/slp:Brightness" mode="jsBrightnessDuration" />
      <xsl:text>
        ];
      </xsl:text>
    </xsl:if>
  </xsl:template>

  <xsl:template match="slp:Brightness" mode="jsBrightnessDuration">
    <xsl:text>{ interval : "</xsl:text>
    <xsl:value-of select="@Level" />
    <xsl:text>", value : </xsl:text>
    <xsl:value-of select="@DurationSec" />
    <xsl:text> },&#xa;</xsl:text>
    <xsl:text></xsl:text>
  </xsl:template>

  <xsl:template match="slp:ScenarioInstance|slp:OsStateInstance|slp:RecentUsageInstance" mode="jsMainLuxDuration">
    <xsl:if test="slp:LuxHistogram">
      <xsl:text>
      Histogram.draw({
          element: "lux-duration-</xsl:text>
      <xsl:value-of select="position()" />
      <xsl:text>",
          data: luxDuration_</xsl:text>
      <xsl:value-of select="position()" />
      <xsl:text>,
          rangeMax: 1
      });&#xa;</xsl:text>
    </xsl:if>
  </xsl:template>

  <xsl:template match="slp:ScenarioInstance|slp:OsStateInstance|slp:RecentUsageInstance" mode="jsLuxDuration">
    <xsl:if test="slp:LuxHistogram">
      <xsl:text>luxDuration_</xsl:text>
      <xsl:value-of select="position()" />
      <xsl:text> = [&#xa;</xsl:text>
      <xsl:apply-templates select="slp:LuxHistogram/slp:Lux" mode="jsLuxDuration" />
      <xsl:text>
        ];
      </xsl:text>
    </xsl:if>
  </xsl:template>

  <xsl:template match="slp:Lux" mode="jsLuxDuration">
    <xsl:text>{ interval : "</xsl:text>
    <xsl:value-of select="@Level" />
    <xsl:text>", value : </xsl:text>
    <xsl:value-of select="@DurationSec" />
    <xsl:text> },&#xa;</xsl:text>
    <xsl:text></xsl:text>
  </xsl:template>

  <xsl:template match="slp:Warning">
    <div class="analysis-container warning">
      <h1>
        <span class="expander">+ </span>
        <xsl:value-of select="@Header" />
      </h1>
      <div class="analysis-body-collapsed">
        <xsl:value-of select="@Body" disable-output-escaping="yes" />
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:Warnings">
    <xsl:apply-templates select="slp:Warning" />
  </xsl:template>

  <xsl:template name="systemInformation">
    <table class="defs">
      <col />
      <xsl:if test="boolean($systemInfo)">
        <tr>
          <td class="label">
            COMPUTER NAME
          </td>
          <td>
            <xsl:value-of select="$systemInfo/slp:ComputerName" />
          </td>
        </tr>
        <tr>
          <td class="label">
            SYSTEM PRODUCT NAME
          </td>
          <td>
            <xsl:value-of select="$systemInfo/slp:SystemManufacturer" />
            <xsl:text> </xsl:text>
            <xsl:value-of select="$systemInfo/slp:SystemProductName" />
          </td>
        </tr>
        <tr>
          <td class="label">
            BIOS
          </td>
          <td>
            <xsl:value-of select="$systemInfo/slp:BIOSVersion" />
            <xsl:text> </xsl:text>
            <xsl:value-of select="$systemInfo/slp:BIOSDate" />
          </td>
        </tr>
        <tr>
          <td class="label">
            OS BUILD
          </td>
          <td>
            <xsl:value-of select="$systemInfo/slp:OSBuild" />
          </td>
        </tr>
        <tr>
          <td class="label">
            PLATFORM ROLE
          </td>
          <td>
            <xsl:value-of select="$systemInfo/slp:PlatformRole" />
          </td>
        </tr>
      </xsl:if>
      <tr>
        <td class="label">
          REPORT TIME
        </td>
        <td>
          <xsl:variable name="date" select="substring-before($localReportTime, 'T')"/>
          <xsl:variable name="time" select="translate(substring-after($localReportTime, 'T'), 'T ', '')"/>

          <span>
            <xsl:value-of select="$date"/>
            <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
            <xsl:text> </xsl:text>
          </span>
          <span>
            <xsl:value-of select="$time"/>
          </span>
        </td>
      </tr>
    </table>
  </xsl:template>

  <xsl:template name="batteryDrainGraph">
    <canvas id="drain-graph" width="864" height="400">&#160;</canvas>

    <table id="legend">
      <colgroup>
        <col />
        <col />
      </colgroup>
      <caption>Legend</caption>
      <thead>
        <th>GRAPH LINE</th>
        <th>DESCRIPTION</th>
      </thead>
      <tbody>
        <tr>
          <td>
            <span class="graphline-dotted">Dotted</span>
          </td>
          <td colspan="2">AC power </td>
        </tr>
        <tr>
          <td>
            <span class="graphline-solid">Solid</span>
          </td>
          <td colspan="2">Battery power</td>
        </tr>
        <tr>
          <td>
            <span class="graphline-none">No line</span>
          </td>
          <td colspan="2">System powered off</td>
        </tr>
        <tr>
          <td colspan="3" class="spanner"></td>
        </tr>
        <tr>
          <td>
            <span class="graphline-neutral">Grey</span>
          </td>
          <td colspan="2">Active Scenario</td>
        </tr>
        <tr>
          <td>
            <span class="graphline-low">Green</span>
          </td>
          <td>Low System Activity</td>
        </tr>
        <tr>
          <td>
            <span class="graphline-moderate">Orange</span>
          </td>
          <td>Moderate System Activity</td>
        </tr>
        <tr>
          <td>
            <span class="graphline-high">Red</span>
          </td>
          <td>High System Activity</td>
        </tr>
        <tr>
          <td>
            <span class="graphline-nonclean">Violet</span>
          </td>
          <td>Abnormal Shutdown</td>
        </tr>
      </tbody>
    </table>
  </xsl:template>

  <xsl:template match="slp:ScenarioInstances" mode="summaryTable">
    <h2>
      Filter Option.
    </h2>
    <h4>Session Length:</h4>
    <input type="radio" name="session1" id="is_all_time" value="Alltime" onchange="js:durationValueChanged()" checked=""/>
    <label>All</label>
    <xsl:text> </xsl:text>
    <input type="radio" name="session1" id="is_10_session" value="10:00" onchange="js:durationValueChanged()"/>
    <label>> 10 min </label>
    <h4>States:</h4>
    <input type="radio" name="session" id="is_all_session" value="All" onchange="js:osStateValueChanged()" checked=""/>
    <label>All</label>
    <xsl:text> </xsl:text>
    <input type="radio" name="session" id="is_active_session" value="Active" onchange="js:osStateValueChanged()"/>
    <label>Active</label>
    <xsl:text> </xsl:text>
    <input type="radio" name="session" id="is_screenoff_session" value="ScreenOff" onchange="js:osStateValueChanged()" />
    <label>Screen Off </label>
    <input type="radio" name="session" id="is_sleep_session" value="Standby" onchange="js:osStateValueChanged()" />
    <label>Sleep</label>
    <xsl:text> </xsl:text>
    <input type="radio" name="session" id="is_hib_session" value="Hibernate" onchange="js:osStateValueChanged()"/>
    <label>Hibernate</label>
    <xsl:text> </xsl:text>
    <input type="radio" name="session" id="is_shutdown_session" value="Shutdown" onchange="js:osStateValueChanged()"/>
    <label>Shutdown</label>
    <xsl:text> </xsl:text>
    <input type="radio" name="session" id="is_bug_session" value="Bug Check" onchange="js:osStateValueChanged()"/>
    <label>Bug Check</label>
    <xsl:text> </xsl:text>

    <table id="summary-table">
        <colgroup>
        <col style="width: 2em" />
        <col style="width: 11em;" />
        <col style="width: 5em;" />
        <col style="width: 10em;" />
        <col class="width: 13em;" />
        <col class="width: 13em;" />
        <col style="width: 6em;" />
        <col style="width: 6em;" />
        <col style="width: 6em;" />
        <col style="width: 6em;" />
        <col style="width: 6em;" />
        <!-- Hack to make the colgroups play well with both when we do display
             the HW DRIPS cell and when we do not and the DRIPS cell spans
             two columns -->
        <col style="width: 1em;" />
      </colgroup>
      <thead>
        <tr>
          <th></th>
          <th>START TIME</th>
          <th>DURATION</th>
          <th>STATE</th>
          <th colspan="2">ENERGY CHANGE</th>
          <th colspan="2">CHANGE RATE</th>
          <th colspan="2">% LOW POWER STATE TIME</th>
          <th>% CAPACITY REMAINING AT START</th>
        </tr>
      </thead>

      <xsl:choose>
        <xsl:when test="boolean(slp:ScenarioInstance|slp:OsStateInstance|slp:RecentUsageInstance)  and boolean(slp:OsStateInstance)">
          <xsl:apply-templates select="*" mode="summaryTable">
            <xsl:sort select="@OsStateId" data-type="number" order="ascending"/>
          </xsl:apply-templates>
        </xsl:when>
        <xsl:otherwise>
          <xsl:apply-templates select="*" mode="summaryTable">
            <xsl:sort select="@LocalTimestamp"/>
          </xsl:apply-templates>
        </xsl:otherwise>
      </xsl:choose>

      <!-- No data. Show one line of dashes -->
      <xsl:choose>
        <xsl:when test ="not(boolean(slp:ScenarioInstance|slp:OsStateInstance|slp:RecentUsageInstance))" >
          <tr>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
            <td class="nullValue">-</td>
          </tr>
        </xsl:when>
      </xsl:choose>
    </table>
  </xsl:template>

  <!-- Outputs the "Battery usage" table contents -->
  <xsl:template match="slp:ScenarioInstance|slp:OsStateInstance|slp:RecentUsageInstance" mode="summaryTable">
    <tr>
      <xsl:attribute name="class">
        <xsl:text>row-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <td class="centered">
        <a>
          <xsl:attribute name="href">
            <xsl:text>#connected-standby-session-</xsl:text>
            <xsl:value-of select="position()" />
          </xsl:attribute>
          <xsl:attribute name="class">
            <xsl:text>row-link</xsl:text>
          </xsl:attribute>
          <xsl:value-of select="position()" />
        </a>
      </td>
      <td class="dateTime">
        <xsl:call-template name="formatDateTime">
          <xsl:with-param name="dateTime" select="@LocalTimestamp" />
          <xsl:with-param name="showDate" select="js:parseDate(string(@LocalTimestamp)) != js:parseDate(string(preceding-sibling::*[1]/@LocalTimestamp))" />
        </xsl:call-template>
      </td>

      <!-- Duration -->
      <td class="hms">
        <xsl:choose>
          <xsl:when test="boolean(@Duration)">
            <xsl:value-of select="js:formatDurationMs(string(@Duration div 10000))" />
          </xsl:when>
          <xsl:otherwise>
            <xsl-text>-</xsl-text>
          </xsl:otherwise>
        </xsl:choose>
      </td>

      <!-- State -->
      <td class="state">
        <xsl:value-of select="@Type" />
      </td>

      <!-- Energy change -->
      <xsl:call-template name="mWhCell">
        <xsl:with-param name="batteryDrain" select="@Discharge" />
        <xsl:with-param name="batteryCapacity" select="@FullChargeCapacity" />
        <xsl:with-param name="batteryCountChanged" select="@BatteryCountChanged" />
      </xsl:call-template>

      <!-- Change rate -->
      <xsl:call-template name="mWCell">
        <xsl:with-param name="energyDrain" select="@EnergyDrain" />
        <xsl:with-param name="batteryCountChanged" select="@BatteryCountChanged" />
      </xsl:call-template>

      <!-- Charge/Drain -->
      <td class="chargeOrDrain">
        <xsl:choose>
          <xsl:when test="boolean(@Ac)">
            <xsl:choose>
              <xsl:when test="boolean(@SpmScenarioStopReason)">
                <xsl:value-of select="js:createChargeDrainString(string(@Ac), string(@SpmScenarioStopReason))" />
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="js:createChargeDrainString(string(@Ac), '17')" />
              </xsl:otherwise>
            </xsl:choose>
          </xsl:when>
          <xsl:otherwise>
            <xsl-text>-</xsl-text>
          </xsl:otherwise>
        </xsl:choose>
      </td>

      <!-- % Low Power State Time -->
      <xsl:choose>
        <xsl:when test="boolean(@HwLowPowerStateTime) and (@LowPowerStateTime != 0)">
          <td class="percentLowPowerStateTime">
            SW: <xsl:value-of select="round(100 * @LowPowerStateTime div @Duration)" />%
          </td>
          <td class="percentLowPowerStateTime">
            HW: <xsl:value-of select="round(100 * @HwLowPowerStateTime div @Duration)" />%
          </td>
        </xsl:when>
        <xsl:when test="boolean(@HwLowPowerStateTime) and (@LowPowerStateTime = 0)">
          <td class="percentLowPowerStateTime">
            SW: <xsl:value-of select="round(100 * @LowPowerStateTime div @Duration)" />%
          </td>
          <td class="percentLowPowerStateTime">
            HW: -
          </td>
        </xsl:when>
        <xsl:otherwise>
          <td class="percentLowPowerStateTime" colspan="2">
            <xsl:choose>
              <xsl:when test="boolean(@LowPowerStateTime)">
                SW: <xsl:value-of select="round(100 * @LowPowerStateTime div @Duration)" />%
              </xsl:when>
              <xsl:otherwise>
                <xsl-text>-</xsl-text>
              </xsl:otherwise>
            </xsl:choose>
          </td>
        </xsl:otherwise>
      </xsl:choose>

      <!-- Start Capacity remaining -->
      <xsl:call-template name="percentCell">
        <xsl:with-param name="remainingCapacity" select="@EntryRemainingCapacity" />
        <xsl:with-param name="fullCapacity" select="@EntryFullCapacity" />
        <xsl:with-param name="batteryCountChanged" select="@BatteryCountChanged" />
      </xsl:call-template>

      <!-- Hack to make the colgroups play well with both when we do display
           the HW DRIPS cell and when we do not and the DRIPS cell spans
           two columns -->
      <td class="blank"></td>
    </tr>

  </xsl:template>

  <xsl:template match="slp:ScenarioInstances" mode="analysisResults">
    <xsl:choose>
      <xsl:when test ="boolean(slp:OsStateInstance)" >
        <xsl:apply-templates select="*" mode="analysisResults">
          <xsl:sort select="@OsStateId" data-type="number" order="ascending"/>
        </xsl:apply-templates>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="*" mode="analysisResults">
          <xsl:sort select="@LocalTimestamp"/>
        </xsl:apply-templates>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="slp:OsStateInstance" mode="analysisResults">
    <a>
      <xsl:attribute name="name">
        <xsl:text>connected-standby-session-</xsl:text>
        <xsl:value-of select="position()" />
      </xsl:attribute>
    </a>
    <div class="scroll-top-button">Top</div>
    <h3>
      System Power State:  <xsl:value-of select="@Type" />
    </h3>
    <table class="session-summary">
      <colgroup>
        <col style="width: 2em" />
        <col style="width: 11em;" />
        <col style="width: 5em;" />
        <col style="width: 10em" />
        <col style="width: 16em" />
        <col style="width: 16em" />
        <col style="width: 6em;" />
      </colgroup>
      <thead>
        <tr>
          <th></th>
          <th>START TIME</th>
          <th>DURATION</th>
          <th>STATE</th>
          <th>ENTRY REASON</th>
          <th>EXIT REASON</th>
          <th>% CAPACITY REMAINING AT START</th>
          <th></th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <xsl:attribute name="class">
            <xsl:text>row-</xsl:text>
            <xsl:value-of select="@ActivityLevel" />
          </xsl:attribute>
          <td class="centered">
            <xsl:value-of select="position()" />
          </td>

          <!-- Start Time -->
          <td class="dateTime">
            <xsl:call-template name="formatDateTime">
              <xsl:with-param name="dateTime" select="@LocalTimestamp" />
            </xsl:call-template>
          </td>

          <!-- Duration -->
          <td class="hms">
            <xsl:choose>
              <xsl:when test="boolean(@Duration)">
                <xsl:value-of select="js:formatDurationMs(string(@Duration div 10000))" />
              </xsl:when>
              <xsl:otherwise>
                <xsl-text>-</xsl-text>
              </xsl:otherwise>
            </xsl:choose>
          </td>

          <td class="OsState" align="center">
            <xsl:value-of select="@Type" />
          </td>

          <td class="EntryReason" align="center">
            <xsl:value-of select="@EntryReason" />
          </td>

          <td class="ExitReason" align="center">
            <xsl:value-of select="@ExitReason" />
          </td>

          <!-- Start Capacity remaining -->
            <xsl:call-template name="percentCell">
              <xsl:with-param name="remainingCapacity" select="@EntryRemainingCapacity" />
              <xsl:with-param name="fullCapacity" select="@EntryFullCapacity" />
              <xsl:with-param name="batteryCountChanged" select="@BatteryCountChanged" />
            </xsl:call-template>

        </tr>
      </tbody>
    </table>
    <xsl:apply-templates select="slp:CustomData" mode="analysisTopLevel" />
  </xsl:template>

  <xsl:template match="slp:CustomData" mode="analysisTopLevel">
    <xsl:apply-templates select="slp:CustomDataHeading" />
    <xsl:apply-templates select="slp:OSStateCustomData" />
  </xsl:template>

  <xsl:template match="slp:CustomDataHeading">
    <h4>
      <xsl:value-of select="@Head"/>
    </h4>
  </xsl:template>

  <xsl:template match="slp:OSStateCustomData">
    <h4>OS State Data</h4>
    <div class="explanation">
      Data obtained from the Event Viewer Logger.
    </div>
    <div>
      <xsl:attribute name="class">
        <xsl:text>analysis-container </xsl:text>
        <xsl:text>analysis-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <h1>
        <span class="expander">+ </span>Detailed OS State Data
      </h1>
      <div class="analysis-body-collapsed">
        <xsl:choose>
          <xsl:when test="count(slp:OSStateRecord) = 0">
            <div class="analysis-empty">No data obtained.</div>
          </xsl:when>
          <xsl:otherwise>
            <table class="pdc-phases">
              <thead>
                <th>Name</th>
                <th>Value</th>
              </thead>
              <tbody>
                <xsl:apply-templates select="slp:OSStateRecord">
                </xsl:apply-templates>
              </tbody>
            </table>
          </xsl:otherwise>
        </xsl:choose>
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:OSStateRecord">
    <tr>
      <xsl:attribute name="class">
        <xsl:text>row-info</xsl:text>
      </xsl:attribute>
      <td class="center">
        <xsl:value-of select="@Name" />
      </td>
      <td class="center">
        <xsl:value-of select="@Value" />
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="slp:ScenarioInstance" mode="analysisResults">
    <xsl-text></xsl-text>
    <a>
      <xsl:attribute name="name">
        <xsl:text>connected-standby-session-</xsl:text>
        <xsl:value-of select="position()" />
      </xsl:attribute>
    </a>
    <div class="scroll-top-button">Top</div>
    <h3>
      System Power State:  <xsl:value-of select="@Type" />
    </h3>
    <table class="session-summary">
      <colgroup>
        <col style="width: 2em" />
        <col style="width: 11em;" />
        <col style="width: 5em;" />
        <col style="width: 10em;" />
        <col class="width: 13em;" />
        <col class="width: 13em;" />
        <col style="width: 6em;" />
        <col style="width: 6em;" />
        <col style="width: 6em;" />
        <col style="width: 6em;" />
        <col style="width: 6em;" />
      </colgroup>
      <thead>
        <tr>
          <th></th>
          <th>START TIME</th>
          <th>DURATION</th>
          <th>STATE</th>
          <th colspan="2">ENERGY CHANGE</th>
          <th colspan="2">CHANGE RATE</th>
          <th colspan="2">% LOW POWER STATE TIME</th>
          <th>% CAPACITY REMAINING AT START</th>
          <th></th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <xsl:attribute name="class">
            <xsl:text>row-</xsl:text>
            <xsl:value-of select="@ActivityLevel" />
          </xsl:attribute>
          <td class="centered">
            <xsl:value-of select="position()" />
          </td>
          <td class="dateTime">
            <xsl:call-template name="formatDateTime">
              <xsl:with-param name="dateTime" select="@LocalTimestamp" />
            </xsl:call-template>
          </td>
          <td class="hms">
            <xsl:value-of select="js:formatDurationMs(string(@Duration div 10000))" />
          </td>

          <!-- State -->
          <td class="state">
            <xsl:value-of select="@Type" />
          </td>

          <!-- Energy change -->
          <xsl:call-template name="mWhCell">
            <xsl:with-param name="batteryDrain" select="@Discharge" />
            <xsl:with-param name="batteryCapacity" select="@FullChargeCapacity" />
            <xsl:with-param name="batteryCountChanged" select="@BatteryCountChanged" />
          </xsl:call-template>

          <!-- Change rate -->
          <xsl:call-template name="mWCell">
            <xsl:with-param name="energyDrain" select="@EnergyDrain" />
            <xsl:with-param name="batteryCountChanged" select="@BatteryCountChanged" />
          </xsl:call-template>

          <!-- Charge/Drain -->
          <td class="chargeOrDrain">
            <xsl:value-of select="js:createChargeDrainString(string(@Ac), string(@SpmScenarioStopReason))" />
          </td>

          <!-- % Low Power State Time -->
          <xsl:choose>
            <xsl:when test="@HwLowPowerStateTime or @LowPowerStateTime">
              <xsl:choose>
                <xsl:when test="boolean(@HwLowPowerStateTime) and (@LowPowerStateTime != 0)">
                  <td class="percentLowPowerStateTime">
                    SW: <xsl:value-of select="round(100 * @LowPowerStateTime div @Duration)" />%
                  </td>
                  <td class="percentLowPowerStateTime">
                    HW: <xsl:value-of select="round(100 * @HwLowPowerStateTime div @Duration)" />%
                  </td>
                </xsl:when>
                <xsl:when test="boolean(@HwLowPowerStateTime) and (@LowPowerStateTime = 0)">
                  <td class="percentLowPowerStateTime">
                    SW: <xsl:value-of select="round(100 * @LowPowerStateTime div @Duration)" />%
                  </td>
                  <td class="percentLowPowerStateTime">
                    HW: -
                  </td>
                </xsl:when>
                <xsl:otherwise>
                  <td class="percentLowPowerStateTime" colspan="2">
                    SW: <xsl:value-of select="round(100 * @LowPowerStateTime div @Duration)" />%
                  </td>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:when>
            <xsl:otherwise>
              <td class="percentLowPowerStateTime" colspan="2">-</td>
            </xsl:otherwise>
          </xsl:choose>

          <!-- Start Capacity remaining -->
          <xsl:call-template name="percentCell">
            <xsl:with-param name="remainingCapacity" select="@EntryRemainingCapacity" />
            <xsl:with-param name="fullCapacity" select="@EntryFullCapacity" />
            <xsl:with-param name="batteryCountChanged" select="@BatteryCountChanged" />
          </xsl:call-template>

          <!-- More information expander -->
          <td>
            <xsl:attribute name="class">
              <xsl:text>details-expander</xsl:text>
            </xsl:attribute>
            <xsl:attribute name="id">
              <xsl:text>details-expand-</xsl:text>
              <xsl:value-of select="position()" />
            </xsl:attribute>
            &#8942;
          </td>
        </tr>
      </tbody>
    </table>
    <div>
      <xsl:attribute name="class">
        <xsl:text>scenario-details-collapsed</xsl:text>
      </xsl:attribute>
      <xsl:attribute name="id">
        <xsl:text>details-</xsl:text>
        <xsl:value-of select="position()" />
      </xsl:attribute>
      <table class="defs">
        <xsl:choose>
          <xsl:when test="@EntryRemainingCapacity">
            <tr>
              <td class="label">REMAINING CHARGE CAPACITY AT ENTRY</td>
              <td>
                <xsl:value-of select="@EntryRemainingCapacity" /> mWh
              </td>
            </tr>
          </xsl:when>
        </xsl:choose>
        <xsl:choose>
          <xsl:when test="@EntryFullCapacity">
            <tr>
              <td class="label">FULL CHARGE CAPACITY AT ENTRY</td>
              <td>
                <xsl:value-of select="@EntryFullCapacity" /> mWh
              </td>
            </tr>
          </xsl:when>
        </xsl:choose>
        <xsl:choose>
          <xsl:when test="@ExitRemainingCapacity">
            <tr>
              <td class="label">REMAINING CHARGE CAPACITY AT EXIT</td>
              <td>
                <xsl:value-of select="@ExitRemainingCapacity" /> mWh
              </td>
            </tr>
          </xsl:when>
        </xsl:choose>
        <xsl:choose>
          <xsl:when test="@ExitFullCapacity">
            <tr>
              <td class="label">FULL CHARGE CAPACITY AT EXIT</td>
              <td>
                <xsl:value-of select="@ExitFullCapacity" /> mWh
              </td>
            </tr>
          </xsl:when>
        </xsl:choose>
        <xsl:choose>
          <xsl:when test="@DisconnectedStandby">
            <tr>
              <td class="label">NETWORKING IN STANDBY</td>
              <td>
                <xsl:choose>
                  <xsl:when test="@DisconnectedStandby = '0'">Connected</xsl:when>
                  <xsl:otherwise>Disconnected</xsl:otherwise>
                </xsl:choose>
              </td>
            </tr>
          </xsl:when>
        </xsl:choose>
        <xsl:choose>
          <xsl:when test="@EnergySaverPolicy">
            <tr>
              <td class="label">ENERGY SAVER IN STANDBY</td>
              <td>
                <xsl:choose>
                  <xsl:when test="@EnergySaverPolicy = '0'">OFF</xsl:when>
                  <xsl:otherwise>ON</xsl:otherwise>
                </xsl:choose>
              </td>
            </tr>
          </xsl:when>
        </xsl:choose>
        <xsl:choose>
          <xsl:when test="@IsDebuggerEnabled">
            <tr>
              <td class="label">DEBUG ENABLED</td>
              <td>
                <xsl:choose>
                  <xsl:when test="@IsDebuggerEnabled = '0'">NO</xsl:when>
                  <xsl:otherwise>YES</xsl:otherwise>
                </xsl:choose>
              </td>
            </tr>
          </xsl:when>
        </xsl:choose>
        <xsl:choose>
          <xsl:when test="@IsLockConsoleTimeoutActive">
            <tr>
              <td class="label">LOCK CONSOLE TIMEOUT ACTIVE</td>
              <td>
                <xsl:choose>
                  <xsl:when test="@IsLockConsoleTimeoutActive = '0'">NO</xsl:when>
                  <xsl:otherwise>YES</xsl:otherwise>
                </xsl:choose>
              </td>
            </tr>
          </xsl:when>
        </xsl:choose>
        <xsl:choose>
          <xsl:when test="@SystemGpuAdapterCount">
            <tr>
              <td class="label">SYSTEM GPU ADAPTER COUNT</td>
              <td>
                <xsl:value-of select="@SystemGpuAdapterCount" />
              </td>
            </tr>
          </xsl:when>
        </xsl:choose>
        <xsl:choose>
          <xsl:when test="@PreVetoCount">
            <tr>
              <td class="label">PEP PRE-VETO COUNT</td>
              <td>
                <xsl:value-of select="@PreVetoCount" />
              </td>
            </tr>
          </xsl:when>
        </xsl:choose>
        <tr>
          <td class="label">ENTER REASON</td>
          <td>
            <xsl:choose>
              <xsl:when test="@CsEnterReasonPdcSignalReasonDetails">
                <xsl:value-of select="concat(@CsEnterReason, ' : ', @CsEnterReasonPdcSignalReasonDetails)" />
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="@CsEnterReason" />
              </xsl:otherwise>
            </xsl:choose>
          </td>
        </tr>
        <xsl:if test="@CsEnterReasonPdcSignalReasonDetails and (@CsEnterReasonPdcSignalUnknown != 0)">
          <tr>
            <td class="label">ENTER PDC SIGNAL CLASS</td>
            <td>
              <xsl:value-of select="@CsEnterReasonPdcSignalClassGuid" />
            </td>
          </tr>
          <tr>
            <td class="label">ENTER PDC SIGNAL PROVIDER</td>
            <td>
              <xsl:value-of select="@CsEnterReasonPdcSignalProviderGuid" />
            </td>
          </tr>
        </xsl:if>
        <tr>
          <td class="label">EXIT REASON</td>
          <td>
            <xsl:choose>
              <xsl:when test="@CsExitReasonPdcSignalReasonDetails">
                <xsl:value-of select="concat(@CsExitReason, ' : ', @CsExitReasonPdcSignalReasonDetails)" />
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="@CsExitReason" />
              </xsl:otherwise>
            </xsl:choose>
          </td>
        </tr>
        <xsl:if test="@CsExitReasonPdcSignalReasonDetails and (@CsExitReasonPdcSignalUnknown != 0)">
          <tr>
            <td class="label">EXIT PDC SIGNAL CLASS</td>
            <td>
              <xsl:value-of select="@CsExitReasonPdcSignalClassGuid" />
            </td>
          </tr>
          <tr>
            <td class="label">EXIT PDC SIGNAL PROVIDER</td>
            <td>
              <xsl:value-of select="@CsExitReasonPdcSignalProviderGuid" />
            </td>
          </tr>
        </xsl:if>
        <xsl:choose>
          <xsl:when test="@DirectedDripsTransitionCount">
            <tr>
              <td class="label">DIRECTED DRIPS TRANSITIONS</td>
              <td>
                <xsl:value-of select="@DirectedDripsTransitionCount" />
              </td>
            </tr>
          </xsl:when>
        </xsl:choose>
        <xsl:choose>
          <xsl:when test="@CsExitLatencyInMs">
            <tr>
              <td class="label">EXIT LATENCY [ms]</td>
              <td>
                <xsl:value-of select="@CsExitLatencyInMs" />
              </td>
            </tr>
          </xsl:when>
        </xsl:choose>
      </table>
      <xsl:choose>
          <xsl:when test="@CsExitLatencyInMs">
            <table>
              <tr>
                <th align="left">CS EXIT LATENCY PHASE BREAKDOWN [ms]</th>
              </tr>
              <tr>
                <td class="label"  colspan="16">CS EXIT TIME SPENT IN RESILIENCY</td>
                <td>
                  <xsl:value-of select="@CsExitTimeSpentInResiliency" />
                </td>
              </tr>
              <tr>
                <td class="label"  colspan="16">CS EXIT TIME SPENT IN RESILIENCY NOTIFICATION</td>
                <td>
                  <xsl:value-of select="@CsExitTimeSpentInResiliencyNotif" />
                </td>
              </tr>
              <tr>
                <td class="label" colspan="16">CS EXIT TIME SPENT IN LOW POWER EPOCH</td>
                <td>
                  <xsl:value-of select="@CsExitTimeSpentInLowPower" />
                </td>
              </tr>
              <tr>
                <td class="label"  colspan="16">CS EXIT TIME SPENT IN DAM</td>
                <td>
                  <xsl:value-of select="@CsExitTimeSpentInDam" />
                </td>
              </tr>
              <tr>
                <td class="label"  colspan="16">CS EXIT TIME SPENT IN MAINTENANCE</td>
                <td>
                  <xsl:value-of select="@CsExitTimeSpentInMaintenance" />
                </td>
              </tr>
              <tr>
                <td class="label"  colspan="16">CS EXIT TIME SPENT IN PLM</td>
                <td>
                  <xsl:value-of select="@CsExitTimeSpentInPlm" />
                </td>
              </tr>
              <tr>
                <td class="label"  colspan="16">CS EXIT TIME SPENT IN SHELL</td>
                <td>
                  <xsl:value-of select="@CsExitTimeSpentInPresence" />
                </td>
              </tr>
              <tr>
                <td class="label"  colspan="16">CS EXIT TIME SPENT IN CONNECTION</td>
                <td>
                  <xsl:value-of select="@CsExitTimeSpentInConnection" />
                </td>
              </tr>
              <tr>
                <td class="label"  colspan="16">CS EXIT TIME SPENT TURNING SCREEN ON</td>
                <td>
                  <xsl:value-of select="@CsExitTimeSpentInScreenOn" />
                </td>
              </tr>
              <tr>
                <td class="labeldetails"  colspan="16">GRAPHICS DEVICE INTERFACE (GDI)</td>
                <td>
                  <xsl:value-of select="@GdiOnTime" />
                </td>
              </tr>
              <tr>
                <td class="labeldetails"  colspan="16">DESKTOP WINDOW MANAGER (DWM)</td>
                <td>
                  <xsl:value-of select="@DwmSyncFlushTime" />
                </td>
              </tr>
              <tr>
                <td class="labeldetails"  colspan="16">MONITOR POWER ON</td>
                <td>
                  <xsl:value-of select="@MonitorPowerOnTime" />
                </td>
              </tr>
              <tr>
                <td class="labeldetails"  colspan="16">REQUEST PROCESSING</td>
                <td>
                  <xsl:value-of select="@ScreenOnOverhead" />
                </td>
              </tr>
            </table>
          </xsl:when>
      </xsl:choose>
      <xsl:choose>
        <xsl:when test="@Type = 'Screen Off'">
          <table>
            <tr>
              <th align="left">SESSION TIMEOUT VALUES [seconds]</th>
            </tr>
            <tr>
              <td class="label" colspan="16">TURN OFF DISPLAY AFTER TIMEOUT</td>
              <td>
                <xsl:value-of select="@VideoTimeoutInSec" />
              </td>
            </tr>
            <tr>
              <td class="label" colspan="16">CONSOLE LOCK DISPLAY OFF TIMEOUT</td>
              <td>
                <xsl:value-of select="@LockConsoleTimeoutInSec" />
              </td>
            </tr>
            <tr>
              <td class="label" colspan="16">SLEEP AFTER TIMEOUT</td>
              <td>
                <xsl:value-of select="@StandbyTimeoutInSec" />
              </td>
            </tr>
          </table>
        </xsl:when>
      </xsl:choose>
      <table>
        <tr>
          <th align="left">HIBERNATE SETTINGS</th>
        </tr>
        <tr>
          <td class="label" colspan="16">HIBERNATE ENABLED</td>
          <td>
            <xsl:choose>
              <xsl:when test="@IsHibernateEnabled = '0'">NO</xsl:when>
              <xsl:otherwise>YES</xsl:otherwise>
            </xsl:choose>
          </td>
        </tr>
        <xsl:choose>
          <xsl:when test="@IsHibernateEnabled = '0'"></xsl:when>
          <xsl:otherwise>
            <tr>
              <td class="label" colspan="16">HIBERNATE TIMEOUT</td>
              <td>
                <xsl:value-of select="@HibernateTimeoutInSec" />
              </td>
            </tr>
            <tr>
              <td class="label" colspan="16">HIBERNATE BUDGET [percentage of battery]</td>
              <td>
                <xsl:value-of select="@HibernateBudgetPercentage" />
              </td>
            </tr>
          </xsl:otherwise>
        </xsl:choose>
      </table>
    </div>

    <xsl:if test="count(slp:DripsBuckets)">
      <h4>DRIPS Histogram</h4>
      <div class="explanation">Percent of time spent in DRIPS bucketed by time interval length</div>
      <canvas>
        <xsl:attribute name="id">
          <xsl:text>drips-histogram-</xsl:text>
          <xsl:value-of select="slp:DripsBuckets/slp:DripBucketId/@DripBucketUniqueId"/>
        </xsl:attribute>
        <xsl:attribute name="width">
          <xsl:text>864</xsl:text>
        </xsl:attribute>
        <xsl:attribute name="height">
          <xsl:text>300</xsl:text>
        </xsl:attribute>
        <xsl:text> </xsl:text>
      </canvas>
    </xsl:if>

    <xsl:apply-templates select="slp:DripsWakeSources" />
    <xsl:apply-templates select="slp:TopBlockers" mode="analysisTopLevel" />
    <xsl:apply-templates select="slp:Activators" mode="analysisTopLevel" />
    <xsl:apply-templates select="slp:Processors" mode="analysisTopLevel" />
    <xsl:apply-templates select="slp:Devices" mode="analysisTopLevel" />
    <xsl:apply-templates select="slp:Phases" mode="analysisTopLevel" />
    <xsl:apply-templates select="slp:PepPreVetoes" mode="analysisTopLevel" />
    <xsl:apply-templates select="slp:SocSubsystems" mode="analysisTopLevel" />
    <xsl:apply-templates select="slp:Blockers" mode="analysisTopLevel" />
    <xsl:apply-templates select="slp:SrumData" mode="analysisTopLevel" />
  </xsl:template>

  <xsl:template match="slp:TopBlockers" mode="analysisTopLevel">
    <h4>Top Offenders</h4>
    <div class="explanation">
      Top 5 offenders, ranked by active time
    </div>

    <table style="margin-bottom: 20px" class="top-blocker">
      <colgroup>
        <col />
        <col />
        <col />
        <col />
      </colgroup>
      <thead>
        <tr>
          <th>
            NAME
          </th>
          <th>
            TYPE
          </th>
          <th>
            % ACTIVE TIME
          </th>
          <th>
            ACTIVE TIME
          </th>
        </tr>
      </thead>
      <tbody>
        <xsl:apply-templates select="slp:TopBlocker" />
      </tbody>
    </table>
  </xsl:template>

  <xsl:template name="activeTime">
    <xsl:param name="time" />
    <xsl:choose>
      <xsl:when test="$time = 'invalid'">n/a</xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="js:formatDurationMs(string($time div 10000))" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template name="activeTimePercent">
    <xsl:param name="timePercent" />
    <xsl:choose>
      <xsl:when test="$timePercent = 'invalid'">n/a</xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$timePercent" />%
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="slp:TopBlocker">
    <tr>
      <xsl:attribute name="class">
        <xsl:text>row-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>

      <td>
        <a>
          <xsl:attribute name="href">
            <xsl:text>#offender-</xsl:text>
            <xsl:value-of select="@Id" />
          </xsl:attribute>
          <xsl:attribute name="class">
            <xsl:text>top-active-link row-link</xsl:text>
          </xsl:attribute>
          <xsl:choose>
            <xsl:when test="@Name = ''">Unknown</xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="@Name" />
            </xsl:otherwise>
          </xsl:choose>
        </a>
      </td>
      <td class="center">
        <xsl:value-of select="@Type" />
      </td>
      <td class="percent">
        <xsl:call-template name="activeTimePercent">
          <xsl:with-param name="timePercent" select="@SegmentActiveTimePercent" />
        </xsl:call-template>
      </td>
      <td class="center">
        <xsl:call-template name="activeTime">
          <xsl:with-param name="time" select="@ActiveTime" />
        </xsl:call-template>
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="slp:Errors" mode="blockerErrors">
    <div class="analysis-container error">
      <h1>
        <span class="expander">+ </span>
        <xsl:value-of select="@Header" />
      </h1>
      <div class="analysis-body-collapsed">
        <ul>
          <xsl:for-each select=".">
            <li>
              <xsl:value-of select="slp:Error" />
            </li>
          </xsl:for-each>
        </ul>
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:Processors" mode="analysisTopLevel">
    <div>
      <xsl:attribute name="class">
        <xsl:text>analysis-container </xsl:text>
        <xsl:text>analysis-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <h1>
        <span class="expander">+ </span>Processors
      </h1>
      <div class="analysis-body-collapsed">
        <xsl:apply-templates select="slp:Errors" mode="blockerErrors" />
        <xsl:choose>
          <xsl:when test="count(slp:Processor)">
            <xsl:apply-templates select="slp:Processor" />
          </xsl:when>
          <xsl:otherwise>
            <div class="analysis-empty">No processor activity reported.</div>
          </xsl:otherwise>
        </xsl:choose>
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:Processor">
    <div>
      <xsl:attribute name="class">
        <xsl:text>analysis-container </xsl:text>
        <xsl:text>analysis-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <xsl:if test="@Id">
        <xsl:attribute name="id">
          <xsl:text>offender-</xsl:text>
          <xsl:value-of select="@Id" />
        </xsl:attribute>
      </xsl:if>
      <h1>
        <span class="expander">+ </span>
        <xsl:value-of select="@Name" />
      </h1>
      <div class="analysis-body-collapsed">
        <table class="defs">
          <tr>
            <td class="label">% ACTIVE TIME</td>
            <td class="label">ACTIVE TIME</td>
          </tr>
          <tr>
            <td class="percent">
              <xsl:call-template name="activeTimePercent">
                <xsl:with-param name="timePercent" select="@SegmentActiveTimePercent" />
              </xsl:call-template>
            </td>
            <td class="center">
              <xsl:call-template name="activeTime">
                <xsl:with-param name="time" select="@ActiveTime" />
              </xsl:call-template>
            </td>
          </tr>
        </table>
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:Activators" mode="analysisTopLevel">
    <div>
      <xsl:attribute name="class">
        <xsl:text>analysis-container </xsl:text>
        <xsl:text>analysis-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <h1>
        <span class="expander">+ </span>Activators
      </h1>
      <div class="analysis-body-collapsed">
        <xsl:apply-templates select="slp:Errors" mode="blockerErrors" />
        <xsl:choose>
          <xsl:when test="count(slp:Activator)">
            <xsl:apply-templates select="slp:Activator" />
          </xsl:when>
          <xsl:otherwise>
            <div class="analysis-empty">No activator activity reported.</div>
          </xsl:otherwise>
        </xsl:choose>
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:Activator">
    <div>
      <xsl:attribute name="class">
        <xsl:text>analysis-container </xsl:text>
        <xsl:text>analysis-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <xsl:if test="@Id">
        <xsl:attribute name="id">
          <xsl:text>offender-</xsl:text>
          <xsl:value-of select="@Id" />
        </xsl:attribute>
      </xsl:if>
      <h1>
        <span class="expander">+ </span>
        <xsl:value-of select="@Name" />
      </h1>
      <div class="analysis-body-collapsed">
        <table class="defs">
          <tr>
            <td class="label">% ACTIVE TIME</td>
            <td class="label">ACTIVE TIME</td>
          </tr>
          <tr>
            <td class="percent">
              <xsl:call-template name="activeTimePercent">
                <xsl:with-param name="timePercent" select="@SegmentActiveTimePercent" />
              </xsl:call-template>
            </td>
            <td class="center">
              <xsl:call-template name="activeTime">
                <xsl:with-param name="time" select="@ActiveTime" />
              </xsl:call-template>
            </td>
          </tr>
        </table>
        <xsl:apply-templates select="slp:CustomData" />
        <xsl:apply-templates select="slp:Blockers" />
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:Phase">
    <tr>
      <xsl:if test="boolean(@Id)">
        <xsl:attribute name="id">
          <xsl:text>offender-</xsl:text>
          <xsl:value-of select="@Id" />
        </xsl:attribute>
      </xsl:if>
      <xsl:attribute name="class">
        <xsl:text>row-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <td>
        <xsl:value-of select="@Name" />
      </td>
      <td class="percent">
        <xsl:call-template name="activeTimePercent">
          <xsl:with-param name="timePercent" select="@SegmentActiveTimePercent" />
        </xsl:call-template>
      </td>
      <td class="center">
        <xsl:call-template name="activeTime">
          <xsl:with-param name="time" select="@ActiveTime" />
        </xsl:call-template>
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="slp:Phases" mode="analysisTopLevel">
    <div>
      <xsl:attribute name="class">
        <xsl:text>analysis-container </xsl:text>
        <xsl:text>analysis-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <h1>
        <span class="expander">+ </span>PDC Phases
      </h1>
      <div class="analysis-body-collapsed">
        <xsl:apply-templates select="slp:Errors" mode="blockerErrors" />
        <table class="pdc-phases">
          <thead>
            <th>PHASE</th>
            <th>% TIME</th>
            <th>TIME</th>
          </thead>
          <tbody>
            <xsl:apply-templates select="slp:Phase" />
          </tbody>
        </table>
        <xsl:choose>
          <xsl:when test="count(slp:PhaseBlockers)">
            <xsl:apply-templates select="slp:PhaseBlockers" />
          </xsl:when>
        </xsl:choose>
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:PhaseBlockers">
    <div>
      <xsl:attribute name="class">
        <xsl:text>analysis-container </xsl:text>
        <xsl:text>analysis-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <h1>
        <span class="expander">+ </span>
        <xsl:value-of select="@Name"/>
      </h1>
      <div class="analysis-body-collapsed">
        <xsl:apply-templates select="slp:Blocker" />
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:Devices" mode="analysisTopLevel">
    <div>
      <xsl:attribute name="class">
        <xsl:text>analysis-container </xsl:text>
        <xsl:text>analysis-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <h1>
        <span class="expander">+ </span>Fx Devices
      </h1>
      <div class="analysis-body-collapsed">
        <xsl:apply-templates select="slp:Errors" mode="blockerErrors" />
        <xsl:choose>
          <xsl:when test="count(slp:Device)">
            <xsl:apply-templates select="slp:Device" />
          </xsl:when>
          <xsl:otherwise>
            <div class="analysis-empty">No device activity reported.</div>
          </xsl:otherwise>
        </xsl:choose>
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:Device">
    <div>
      <xsl:attribute name="class">
        <xsl:text>analysis-container </xsl:text>
        <xsl:text>analysis-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <xsl:if test="@Id">
        <xsl:attribute name="id">
          <xsl:text>offender-</xsl:text>
          <xsl:value-of select="@Id" />
        </xsl:attribute>
      </xsl:if>
      <h1>
        <span class="expander">+ </span>
        <xsl:value-of select="@Name" />
      </h1>
      <div class="analysis-body-collapsed">
        <xsl:if test="@ActiveTime and @SegmentActiveTimePercent and @ActiveTime != 0">
          <table class="defs">
            <tr>
              <td class="label">% ACTIVE TIME</td>
              <td class="label">ACTIVE TIME</td>
            </tr>
            <tr>
              <td class="percent">
                <xsl:call-template name="activeTimePercent">
                  <xsl:with-param name="timePercent" select="@SegmentActiveTimePercent" />
                </xsl:call-template>
              </td>
              <td class="center">
                <xsl:call-template name="activeTime">
                  <xsl:with-param name="time" select="@ActiveTime" />
                </xsl:call-template>
              </td>
            </tr>
          </table>
        </xsl:if>
        <xsl:apply-templates select="slp:Blockers" />
        <table class="device-components">
          <xsl:choose>
            <xsl:when test="count(slp:Component)">
              <thead>
                <tr>
                  <th>COMPONENT</th>
                  <th>% ACTIVE TIME</th>
                  <th>ACTIVE TIME</th>
                </tr>
              </thead>
            </xsl:when>
          </xsl:choose>
          <tbody>
            <xsl:choose>
              <xsl:when test="count(slp:Component)">
                <xsl:apply-templates select="slp:Component" />
              </xsl:when>
              <xsl:otherwise>
                <td>
                  <xsl:attribute name="colspan">
                    <xsl:text>3</xsl:text>
                  </xsl:attribute>
                  <xsl:attribute name="class">
                    <xsl:text>row-</xsl:text>
                    <xsl:value-of select="@ActivityLevel" />
                  </xsl:attribute>
                  No active components.
                </td>
              </xsl:otherwise>
            </xsl:choose>
          </tbody>
        </table>
        <xsl:apply-templates select="slp:ComponentBlockers" />
        <xsl:apply-templates select="slp:CustomData" />
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:Component">
    <tr>
      <xsl:attribute name="class">
        <xsl:text>row-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <td class="center">
        <xsl:value-of select="@Index" />
      </td>
      <td class="percent">
        <xsl:call-template name="activeTimePercent">
          <xsl:with-param name="timePercent" select="@SegmentActiveTimePercent" />
        </xsl:call-template>
      </td>
      <td class="center">
        <xsl:call-template name="activeTime">
          <xsl:with-param name="time" select="@ActiveTime" />
        </xsl:call-template>
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="slp:PepPreVetoes" mode="analysisTopLevel">
    <div>
      <xsl:attribute name="class">
        <xsl:text>analysis-container </xsl:text>
        <xsl:text>analysis-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <xsl:if test="@Id">
        <xsl:attribute name="id">
          <xsl:text>offender-</xsl:text>
          <xsl:value-of select="@Id" />
        </xsl:attribute>
      </xsl:if>
      <h1>
        <span class="expander">+ </span>PEP Pre-Vetoes
      </h1>
      <div class="analysis-body-collapsed">
        <xsl:choose>
          <xsl:when test="count(slp:Blocker)">
            <xsl:apply-templates select="slp:Blocker" />
          </xsl:when>
          <xsl:otherwise>
            <div class="analysis-empty">No PEP pre-veto activity reported.</div>
          </xsl:otherwise>
        </xsl:choose>
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:SocSubsystems" mode="analysisTopLevel">
    <div>
      <xsl:attribute name="class">
        <xsl:text>analysis-container </xsl:text>
        <xsl:text>analysis-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <xsl:if test="@Id">
        <xsl:attribute name="id">
          <xsl:text>offender-</xsl:text>
          <xsl:value-of select="@Id" />
        </xsl:attribute>
      </xsl:if>
      <h1>
        <span class="expander">+ </span>SoC Subsystems
      </h1>
      <div class="analysis-body-collapsed">
        <xsl:choose>
          <xsl:when test="count(slp:Blocker)">
            <xsl:apply-templates select="slp:Blocker" />
          </xsl:when>
          <xsl:otherwise>
            <div class="analysis-empty">No SoC subsystem activity reported.</div>
          </xsl:otherwise>
        </xsl:choose>
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:Blockers" mode="analysisTopLevel">
    <xsl:if test="count(slp:Blocker)">
      <div>
        <xsl:attribute name="class">
          <xsl:text>analysis-container </xsl:text>
          <xsl:text>analysis-</xsl:text>
          <xsl:value-of select="@ActivityLevel" />
        </xsl:attribute>
        <h1>
          <span class="expander">+ </span>Other
        </h1>
        <div class="analysis-body-collapsed">
          <xsl:apply-templates select="slp:Blocker" />
        </div>
      </div>
    </xsl:if>
  </xsl:template>

  <xsl:template match="slp:Blocker">
    <div>
      <xsl:attribute name="class">
        <xsl:text>analysis-container </xsl:text>
        <xsl:text>analysis-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <xsl:if test="@Id">
        <xsl:attribute name="id">
          <xsl:text>offender-</xsl:text>
          <xsl:value-of select="@Id" />
        </xsl:attribute>
      </xsl:if>
      <h1>
        <span class="expander">+ </span>
        <xsl:value-of select="@Name" />
      </h1>
      <div class="analysis-body-collapsed">
        <table class="defs">
          <tr>
            <td class="label">% ACTIVE TIME</td>
            <td class="label">ACTIVE TIME</td>
          </tr>
          <tr>
            <td class="percent">
              <xsl:call-template name="activeTimePercent">
                <xsl:with-param name="timePercent" select="@SegmentActiveTimePercent" />
              </xsl:call-template>
            </td>
            <td class="center">
              <xsl:call-template name="activeTime">
                <xsl:with-param name="time" select="@ActiveTime" />
              </xsl:call-template>
            </td>
          </tr>
        </table>
        <xsl:apply-templates select="slp:CustomData" />
        <xsl:apply-templates select="slp:Blocker" />
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:Blockers">
    <xsl:apply-templates select="slp:Blocker" />
  </xsl:template>

  <xsl:template match="slp:ComponentBlockers">
    <xsl:apply-templates select="slp:Blocker" />
  </xsl:template>

  <xsl:template match="slp:CustomData">
    <table class="defs">
      <xsl:apply-templates select="slp:Data" />
    </table>
  </xsl:template>

  <xsl:template match="slp:Data">
    <tr>
      <td class="label">
        <xsl:value-of select="@Key" />
      </td>
      <td>
        <xsl:value-of select="@Value" />
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="slp:SrumData" mode="analysisTopLevel">
    <h4>Srum Data</h4>
    <div class="explanation">
      Data obtained from the SRUM database.
      * in Power Estimation means the power value is from energy meter.
      Otherwise, it is from software model estimation.
    </div>

    <xsl:apply-templates select="slp:EnergyMeterData" />
    <xsl:apply-templates select="slp:PowerEstimationData" />
    <!--Restoring EnergyEstimationData.This allows the RS1 XML format to be
        successfully parsed on a machine running current RS2 and later
        builds.-->
    <xsl:apply-templates select="slp:EnergyEstimationData" />
  </xsl:template>

  <xsl:template match="slp:EnergyMeterData">
    <div>
      <xsl:attribute name="class">
        <xsl:text>analysis-container </xsl:text>
        <xsl:text>analysis-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <h1>
        <span class="expander">+ </span>Energy Meter
      </h1>
      <div class="analysis-body-collapsed">
        <xsl:choose>
          <xsl:when test="count(slp:EnergyMeterRecord) = 0">
            <div class="analysis-empty">No energy meter data obtained.</div>
          </xsl:when>
          <xsl:otherwise>
            <table class="pdc-phases">
              <thead>
                <th>Power Rail</th>
                <th>Energy (mJ)</th>
                <th>Power (mW)</th>
              </thead>
              <tbody>
                <xsl:apply-templates select="slp:EnergyMeterRecord[@EnergyConsumption != '0']">
                  <xsl:sort select="@AppId" data-type="text" order="ascending"/>
                </xsl:apply-templates>
              </tbody>
            </table>
          </xsl:otherwise>
        </xsl:choose>
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:EnergyMeterRecord">
    <tr>
      <xsl:attribute name="class">
        <xsl:text>row-info</xsl:text>
      </xsl:attribute>
      <td>
        <xsl:value-of select="@RailId" />
      </td>
      <td class="center">
        <xsl:value-of select="@EnergyConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@PowerConsumption" />
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="slp:EnergyEstimationData">
    <div>
      <xsl:attribute name="class">
        <xsl:text>analysis-container </xsl:text>
        <xsl:text>analysis-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <h1>
        <span class="expander">+ </span>Energy Estimation
      </h1>
      <div class="analysis-body-collapsed">
        <xsl:choose>
          <xsl:when test="count(slp:EnergyEstimationRecord) = 0">
            <div class="analysis-empty">No energy estimation data obtained.</div>
          </xsl:when>
          <xsl:otherwise>
            <table class="pdc-phases">
              <thead>
                <th>APP ID</th>
                <th>TOTAL (mJ)</th>
                <xsl:choose>
                  <xsl:when test="@CpuEnergyMeasured != '0'">
                    <th>CPU (mJ)*</th>
                  </xsl:when>
                  <xsl:otherwise>
                    <th>CPU (mJ)</th>
                  </xsl:otherwise>
                </xsl:choose>
                <xsl:choose>
                  <xsl:when test="@DisplayEnergyMeasured != '0'">
                    <th>DISPLAY (mJ)*</th>
                  </xsl:when>
                  <xsl:otherwise>
                    <th>DISPLAY (mJ)</th>
                  </xsl:otherwise>
                </xsl:choose>
                <xsl:choose>
                  <xsl:when test="@DiskEnergyMeasured != '0'">
                    <th>DISK (mJ)*</th>
                  </xsl:when>
                  <xsl:otherwise>
                    <th>DISK (mJ)</th>
                  </xsl:otherwise>
                </xsl:choose>
                <xsl:choose>
                  <xsl:when test="@MbbEnergyMeasured != '0'">
                    <th>MBB (mJ)*</th>
                  </xsl:when>
                  <xsl:otherwise>
                    <th>MBB (mJ)</th>
                  </xsl:otherwise>
                </xsl:choose>
                <xsl:choose>
                  <xsl:when test="@NetworkEnergyMeasured != '0'">
                    <th>NETWORK (mJ)*</th>
                  </xsl:when>
                  <xsl:otherwise>
                    <th>NETWORK (mJ)</th>
                  </xsl:otherwise>
                </xsl:choose>
                <xsl:choose>
                  <xsl:when test="@SocEnergyMeasured != '0'">
                    <th>SOC (mJ)*</th>
                  </xsl:when>
                  <xsl:otherwise>
                    <th>SOC (mJ)</th>
                  </xsl:otherwise>
                </xsl:choose>
                <th>LOSS (mJ)</th>
                <th>OTHER (mJ)</th>
              </thead>
              <tbody>
                <xsl:apply-templates select="slp:EnergyEstimationRecord[@TotalEnergyConsumption != '0']">
                  <xsl:sort select="@TotalEnergyConsumption" data-type="number" order="descending"/>
                </xsl:apply-templates>
              </tbody>
            </table>
          </xsl:otherwise>
        </xsl:choose>
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:EnergyEstimationRecord">
    <tr>
      <xsl:attribute name="class">
        <xsl:text>row-info</xsl:text>
      </xsl:attribute>
      <td>
        <xsl:value-of select="@AppId" /> [<xsl:value-of select="@UserId" />]
      </td>
      <td class="center">
        <xsl:value-of select="@TotalEnergyConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@CpuEnergyConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@DisplayEnergyConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@DiskEnergyConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@MbbEnergyConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@NetworkEnergyConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@SocEnergyConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@LossEnergyConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@OtherEnergyConsumption" />
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="slp:PowerEstimationData">
    <div>
      <xsl:attribute name="class">
        <xsl:text>analysis-container </xsl:text>
        <xsl:text>analysis-</xsl:text>
        <xsl:value-of select="@ActivityLevel" />
      </xsl:attribute>
      <h1>
        <span class="expander">+ </span>Power Estimation
      </h1>
      <div class="analysis-body-collapsed">
        <xsl:choose>
          <xsl:when test="count(slp:PowerEstimationRecord) = 0">
            <div class="analysis-empty">No power estimation data obtained.</div>
          </xsl:when>
          <xsl:otherwise>
            <table class="pdc-phases">
              <thead>
                <th>APP ID</th>
                <th>TOTAL (mW)</th>
                <xsl:choose>
                  <xsl:when test="@CpuEnergyMeasured != '0'">
                    <th>CPU (mW)*</th>
                  </xsl:when>
                  <xsl:otherwise>
                    <th>CPU (mW)</th>
                  </xsl:otherwise>
                </xsl:choose>
                <xsl:choose>
                  <xsl:when test="@DisplayEnergyMeasured != '0'">
                    <th>DISPLAY (mW)*</th>
                  </xsl:when>
                  <xsl:otherwise>
                    <th>DISPLAY (mW)</th>
                  </xsl:otherwise>
                </xsl:choose>
                <xsl:choose>
                  <xsl:when test="@DiskEnergyMeasured != '0'">
                    <th>DISK (mW)*</th>
                  </xsl:when>
                  <xsl:otherwise>
                    <th>DISK (mW)</th>
                  </xsl:otherwise>
                </xsl:choose>
                <xsl:choose>
                  <xsl:when test="@MbbEnergyMeasured != '0'">
                    <th>MBB (mW)*</th>
                  </xsl:when>
                  <xsl:otherwise>
                    <th>MBB (mW)</th>
                  </xsl:otherwise>
                </xsl:choose>
                <xsl:choose>
                  <xsl:when test="@NetworkEnergyMeasured != '0'">
                    <th>NETWORK (mW)*</th>
                  </xsl:when>
                  <xsl:otherwise>
                    <th>NETWORK (mW)</th>
                  </xsl:otherwise>
                </xsl:choose>
                <xsl:choose>
                  <xsl:when test="@SocEnergyMeasured != '0'">
                    <th>SOC (mW)*</th>
                  </xsl:when>
                  <xsl:otherwise>
                    <th>SOC (mW)</th>
                  </xsl:otherwise>
                </xsl:choose>
                <th>LOSS (mW)</th>
                <th>OTHER (mW)</th>
              </thead>
              <tbody>
                <xsl:apply-templates select="slp:PowerEstimationRecord[@TotalPowerConsumption != '0']">
                  <xsl:sort select="@TotalPowerConsumption" data-type="number" order="descending"/>
                </xsl:apply-templates>
              </tbody>
            </table>
          </xsl:otherwise>
        </xsl:choose>
      </div>
    </div>
  </xsl:template>

  <xsl:template match="slp:PowerEstimationRecord">
    <tr>
      <xsl:attribute name="class">
        <xsl:text>row-info</xsl:text>
      </xsl:attribute>
      <td>
        <xsl:value-of select="@AppId" /> [<xsl:value-of select="@UserId" />]
      </td>
      <td class="center">
        <xsl:value-of select="@TotalPowerConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@CpuPowerConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@DisplayPowerConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@DiskPowerConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@MbbPowerConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@NetworkPowerConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@SocPowerConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@LossPowerConsumption" />
      </td>
      <td class="center">
        <xsl:value-of select="@OtherPowerConsumption" />
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="slp:SearchIndexerData">
    <xsl:if test="*">
      <h4>Search Indexer Data</h4>
      <xsl:if test="count(slp:Query) > 0">
        <div>
          <xsl:attribute name="class">
            <xsl:text>analysis-container analysis-info</xsl:text>
          </xsl:attribute>
          <h1>
            <span class="expander">+ </span>Query Events:
            <xsl:value-of select="slp:Query/@TotalNumberOfEvents" />
          </h1>
          <div class="analysis-body-collapsed">
            <table class="pdc-phases">
              <thead>
                <th>Max Cursors Used</th>
                <th>Protocol Count</th>
                <th>Protocol String</th>
              </thead>
              <tbody>
                <xsl:apply-templates select="slp:Query" />
              </tbody>
            </table>
          </div>
        </div>
      </xsl:if>

      <xsl:if test="count(slp:Flush) > 0">
        <div>
          <xsl:attribute name="class">
            <xsl:text>analysis-container analysis-info</xsl:text>
          </xsl:attribute>
          <h1>
            <span class="expander">+ </span>Flush Events:
            <xsl:value-of select="slp:Flush/@TotalNumberOfEvents" />
          </h1>
          <div class="analysis-body-collapsed">
            <table class="pdc-phases">
              <thead>
                <th>Max Key Count</th>
                <th>Max Documents</th>
                <th>Max Word List</th>
              </thead>
              <tbody>
                <xsl:apply-templates select="slp:Flush" />
              </tbody>
            </table>
          </div>
        </div>
      </xsl:if>

      <xsl:if test="count(slp:Merge) > 0">
        <div>
          <xsl:attribute name="class">
            <xsl:text>analysis-container analysis-info</xsl:text>
          </xsl:attribute>
          <h1>
            <span class="expander">+ </span>Merge Events:
            <xsl:value-of select="slp:Merge/@TotalNumberOfEvents" />
          </h1>
          <div class="analysis-body-collapsed">
            <table class="pdc-phases">
              <thead>
                <th>Pre-Merge Indice Count</th>
                <th>Pre-Merge Level</th>
                <th>Pre-Merge Min ID</th>
                <th>Pre-Merge Max ID</th>
                <th>Post-Merge Indice Count</th>
                <th>Post-Merge Level</th>
                <th>Post-Merge Min ID</th>
                <th>Post-Merge Max ID</th>
              </thead>
              <tbody>
                <xsl:apply-templates select="slp:Merge" />
              </tbody>
            </table>
          </div>
        </div>
      </xsl:if>

      <xsl:if test="count(slp:FileSysChange) > 0">
        <div>
          <xsl:attribute name="class">
            <xsl:text>analysis-container analysis-info</xsl:text>
          </xsl:attribute>
          <h1>
            <span class="expander">+ </span>File System Change Events:
            <xsl:value-of select="slp:FileSysChange/@TotalNumberOfEvents" />
          </h1>
          <div class="analysis-body-collapsed">
            <table class="pdc-phases">
              <thead>
                <th>FAT Items Processed</th>
                <th>NTFS Items Processed</th>
              </thead>
              <tbody>
                <xsl:apply-templates select="slp:FileSysChange" />
              </tbody>
            </table>
          </div>
        </div>
      </xsl:if>

      <xsl:if test="count(slp:IndexingFile) > 0">
        <div>
          <xsl:attribute name="class">
            <xsl:text>analysis-container analysis-info</xsl:text>
          </xsl:attribute>
          <h1>
            <span class="expander">+ </span>Indexing File Events:
            <xsl:value-of select="slp:IndexingFile/@TotalNumberOfEvents" />
          </h1>
          <div class="analysis-body-collapsed">
            <table class="pdc-phases">
              <thead>
                <th>IndexingFile Aggregation Data Metric</th>
                <th>Content Type Count</th>
                <th>Content Type String</th>
              </thead>
              <tbody>
                <xsl:apply-templates select="slp:IndexingFile" />
              </tbody>
            </table>
          </div>
        </div>
      </xsl:if>

      <xsl:if test="count(slp:EnteringIdle) > 0">
        <div>
          <xsl:attribute name="class">
            <xsl:text>analysis-container analysis-info</xsl:text>
          </xsl:attribute>
          <h1>
            <span class="expander">- </span>Entering Idle Events:
            <xsl:value-of select="slp:EnteringIdle/@TotalNumberOfEvents" />
          </h1>
        </div>
      </xsl:if>

      <xsl:if test="count(slp:QueryResults) > 0">
        <div>
          <xsl:attribute name="class">
            <xsl:text>analysis-container analysis-info</xsl:text>
          </xsl:attribute>
          <h1>
            <span class="expander">+ </span>Query Results Events:
            <xsl:value-of select="slp:QueryResults/@TotalNumberOfEvents" />
          </h1>
          <div class="analysis-body-collapsed">
            <table class="pdc-phases">
              <thead>
                <th>Results Requested</th>
                <th>Results Returned</th>
              </thead>
              <tbody>
                <xsl:apply-templates select="slp:QueryResults" />
              </tbody>
            </table>
          </div>
        </div>
      </xsl:if>
    </xsl:if>
  </xsl:template>

  <xsl:template match="slp:Query">
    <tr>
      <xsl:attribute name="class">
        <xsl:text>row-info</xsl:text>
      </xsl:attribute>
      <td class="center">
        <xsl:value-of select="@MaxCursorsUsed" />
      </td>
      <td class="center">
        <xsl:value-of select="@ProtocolCount" />
      </td>
      <td class="center">
        <xsl:value-of select="@ProtocolString" />
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="slp:Flush">
    <tr>
      <xsl:attribute name="class">
        <xsl:text>row-info</xsl:text>
      </xsl:attribute>
      <td class="center">
        <xsl:value-of select="@MaxKeyCount" />
      </td>
      <td class="center">
        <xsl:value-of select="@MaxDocuments" />
      </td>
      <td class="center">
        <xsl:value-of select="@MaxWordList" />
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="slp:Merge">
    <tr>
      <xsl:attribute name="class">
        <xsl:text>row-info</xsl:text>
      </xsl:attribute>
      <td class="center">
        <xsl:value-of select="@PreMergeIndiceCount" />
      </td>
      <td class="center">
        <xsl:value-of select="@PreMergeLevel" />
      </td>
      <td class="center">
        <xsl:value-of select="@PreMergeMinId" />
      </td>
      <td class="center">
        <xsl:value-of select="@PreMergeMaxId" />
      </td>
      <td class="center">
        <xsl:value-of select="@PostMergeIndiceCount" />
      </td>
      <td class="center">
        <xsl:value-of select="@PostMergeLevel" />
      </td>
      <td class="center">
        <xsl:value-of select="@PostMergeMinId" />
      </td>
      <td class="center">
        <xsl:value-of select="@PostMergeMaxId" />
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="slp:FileSysChange">
    <tr>
      <xsl:attribute name="class">
        <xsl:text>row-info</xsl:text>
      </xsl:attribute>
      <td class="center">
        <xsl:value-of select="@TotalFATItemsProcessed" />
      </td>
      <td class="center">
        <xsl:value-of select="@TotalNTFSItemsProcessed" />
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="slp:IndexingFile">
    <tr>
      <xsl:attribute name="class">
        <xsl:text>row-info</xsl:text>
      </xsl:attribute>
       <td class="center">
        <xsl:value-of select="@IndexingFileAggregationDataMetric" />
      </td>
      <td class="center">
        <xsl:value-of select="@DataTypeCount" />
      </td>
      <td class="center">
        <xsl:value-of select="@DataTypeString" />
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="slp:QueryResults">
    <tr>
      <xsl:attribute name="class">
        <xsl:text>row-info</xsl:text>
      </xsl:attribute>
      <td class="center">
        <xsl:value-of select="@TotalResultsRequested" />
      </td>
      <td class="center">
        <xsl:value-of select="@TotalResultsReturned" />
      </td>
    </tr>
  </xsl:template>

  <!-- Screen on detailed data -->
  <xsl:template match="slp:RecentUsageInstance" mode="analysisResults">
    <xsl-text></xsl-text>
    <a>
      <xsl:attribute name="name">
        <xsl:text>connected-standby-session-</xsl:text>
        <xsl:value-of select="position()" />
      </xsl:attribute>
    </a>
    <div class="scroll-top-button">Top</div>
    <h3>
      System Power State:  <xsl:value-of select="@Type" />
    </h3>
    <table class="session-summary">
      <colgroup>
        <col style="width: 2em" />
        <col style="width: 11em;" />
        <col style="width: 5em;" />
        <col style="width: 10em;" />
        <col class="width: 13em;" />
        <col class="width: 13em;" />
        <col style="width: 6em;" />
        <col style="width: 6em;" />
        <col style="width: 6em;" />
        <col style="width: 6em;" />
        <col style="width: 6em;" />
      </colgroup>
      <thead>
        <tr>
          <th></th>
          <th>START TIME</th>
          <th>DURATION</th>
          <th>STATE</th>
          <th colspan="2">ENERGY CHANGE</th>
          <th colspan="2">CHANGE RATE</th>
          <th colspan="2">% LOW POWER STATE TIME</th>
          <th>% CAPACITY REMAINING AT START</th>
          <th></th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <xsl:attribute name="class">
            <xsl:text>row-</xsl:text>
            <xsl:value-of select="@ActivityLevel" />
          </xsl:attribute>
          <td class="centered">
            <xsl:value-of select="position()" />
          </td>
          <td class="dateTime">
            <xsl:call-template name="formatDateTime">
              <xsl:with-param name="dateTime" select="@LocalTimestamp" />
            </xsl:call-template>
          </td>
          <td class="hms">
            <xsl:value-of select="js:formatDurationMs(string(@Duration div 10000))" />
          </td>

          <!-- State -->
          <td class="state">
            <xsl:value-of select="@Type" />
          </td>

          <!-- Energy change -->
          <xsl:call-template name="mWhCell">
            <xsl:with-param name="batteryDrain" select="@Discharge" />
            <xsl:with-param name="batteryCapacity" select="@FullChargeCapacity" />
            <xsl:with-param name="batteryCountChanged" select="@BatteryCountChanged" />
          </xsl:call-template>

          <!-- Change rate -->
          <xsl:call-template name="mWCell">
            <xsl:with-param name="energyDrain" select="@EnergyDrain" />
            <xsl:with-param name="batteryCountChanged" select="@BatteryCountChanged" />
          </xsl:call-template>

          <!-- Charge/Drain -->
          <td class="chargeOrDrain">
            <xsl:value-of select="js:createChargeDrainString(string(@Ac), '17')" />
          </td>

          <!-- % Low Power State Time -->
          <td class="nullValue" colspan="2">-</td>

          <!-- Start Capacity remaining -->
          <xsl:call-template name="percentCell">
            <xsl:with-param name="remainingCapacity" select="@EntryRemainingCapacity" />
            <xsl:with-param name="fullCapacity" select="@EntryFullCapacity" />
            <xsl:with-param name="batteryCountChanged" select="@BatteryCountChanged" />
          </xsl:call-template>
        </tr>
      </tbody>
    </table>

    <xsl:if test="slp:ScreenOnSessionGuid">
      <h4>
        <xsl:value-of select="concat('Session ID: ', slp:ScreenOnSessionGuid)"/>
      </h4>
    </xsl:if>
    <xsl:if test="slp:ScreenOnEntryReason">
      <h4>
        <xsl:value-of select="concat('Entry reason: ', slp:ScreenOnEntryReason)"/>
      </h4>
    </xsl:if>
    <xsl:if test="slp:ScreenOnExitReason">
      <h4>
        <xsl:value-of select="concat('Exit reason: ', slp:ScreenOnExitReason)"/>
      </h4>
    </xsl:if>

    <xsl:if test="slp:ScreenBrightnessHistogram">
      <h4>Screen Brightness Duration Histogram</h4>
      <div class="explanation">Duration in seconds at various screen brightness levels</div>
      <canvas>
        <xsl:attribute name="id">
          <xsl:text>brightness-duration-</xsl:text>
          <xsl:value-of select="position()" />
        </xsl:attribute>
        <xsl:attribute name="width">
          <xsl:text>864</xsl:text>
        </xsl:attribute>
        <xsl:attribute name="height">
          <xsl:text>300</xsl:text>
        </xsl:attribute>
        <xsl:text> </xsl:text>
      </canvas>
    </xsl:if>

    <xsl:if test="slp:LuxHistogram">
      <h4>Lux Duration Histogram</h4>
      <div class="explanation">Duration in seconds at various lux levels</div>
      <canvas>
        <xsl:attribute name="id">
          <xsl:text>lux-duration-</xsl:text>
          <xsl:value-of select="position()" />
        </xsl:attribute>
        <xsl:attribute name="width">
          <xsl:text>864</xsl:text>
        </xsl:attribute>
        <xsl:attribute name="height">
          <xsl:text>300</xsl:text>
        </xsl:attribute>
        <xsl:text> </xsl:text>
      </canvas>
    </xsl:if>

    <xsl:apply-templates select="slp:SearchIndexerData" />
    <xsl:apply-templates select="slp:SrumData" mode="analysisTopLevel" />
  </xsl:template>


  <!-- The list of installed batteries -->
  <xsl:template match="slp:Batteries" >
    <!-- Look only at "long term" batteries (i.e. not UPS batteries) -->
    <xsl:variable name="longTermBatts" select="slp:Battery[slp:LongTerm != 0]" />

    <h2>
      Installed batteries
    </h2>
    <div class="explanation">
      Information about each currently installed battery
    </div>

    <xsl:choose>
      <xsl:when test="count($longTermBatts) = 0">
        <!-- No batteries currently installed -->
        <div class="nobatts">
          No batteries are currently installed.
        </div>
      </xsl:when>
      <xsl:otherwise>
        <table class="defs">
          <colgroup>
            <col style="width: 15em;" />
            <xsl:for-each select="$longTermBatts">
              <col style="width: 14em;" />
            </xsl:for-each>
          </colgroup>
          <thead>
            <tr>
              <td>
                <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
                <xsl:text> </xsl:text>
              </td>
              <xsl:for-each select="$longTermBatts">
                <td>
                  BATTERY
                  <xsl:value-of select="position()"/>
                </td>
              </xsl:for-each>
            </tr>
          </thead>
          <tr>
            <td>
              <span class="label">NAME</span>
            </td>
            <xsl:for-each select="$longTermBatts">
              <td>
                <xsl:call-template name="dashIfEmpty">
                  <xsl:with-param name="str" select="slp:Id"/>
                </xsl:call-template>
              </td>
            </xsl:for-each>
          </tr>
          <tr>
            <td>
              <span class="label">MANUFACTURER</span>
            </td>
            <xsl:for-each select="$longTermBatts">
              <td>
                <xsl:call-template name="dashIfEmpty">
                  <xsl:with-param name="str" select="slp:Manufacturer"/>
                </xsl:call-template>
              </td>
            </xsl:for-each>
          </tr>
          <tr>
            <td>
              <span class="label">SERIAL NUMBER</span>
            </td>
            <xsl:for-each select="$longTermBatts">
              <td>
                <xsl:call-template name="dashIfEmpty">
                  <xsl:with-param name="str" select="slp:SerialNumber"/>
                </xsl:call-template>
              </td>
            </xsl:for-each>
          </tr>
          <tr>
            <td>
              <span class="label">CHEMISTRY</span>
            </td>
            <xsl:for-each select="$longTermBatts">
              <td>
                <xsl:call-template name="dashIfEmpty">
                  <xsl:with-param name="str" select="slp:Chemistry"/>
                </xsl:call-template>
              </td>
            </xsl:for-each>
          </tr>
          <tr>
            <td>
              <span class="label">DESIGN CAPACITY</span>
            </td>

            <xsl:for-each select="$longTermBatts">
              <td>
                <xsl:choose>
                  <!-- If RelativeCapacity=1, the units reported for the battery are not mWh -->
                  <xsl:when test="slp:RelativeCapacity = 1">
                    -
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:call-template name="mWh">
                      <xsl:with-param name="value" select="slp:DesignCapacity"/>
                    </xsl:call-template>
                  </xsl:otherwise>
                </xsl:choose>
              </td>
            </xsl:for-each>
          </tr>

          <!-- Small break to hint that the next 2 values are special (they can change over time) -->
          <tr style="height:0.4em;"></tr>

          <tr>
            <td>
              <span class="label">CAPACITY RATIO</span>
            </td>
            <xsl:for-each select="$longTermBatts">
              <td>
                <xsl:value-of select="round(100 * slp:FullChargeCapacity div slp:DesignCapacity)" />%
              </td>
            </xsl:for-each>
          </tr>

          <tr>
            <td>
              <span class="label">CYCLE COUNT</span>
            </td>
            <xsl:for-each select="$longTermBatts">
              <td>
                <xsl:call-template name="dashIfEmpty">
                  <xsl:with-param name="str" select="slp:CycleCount"/>
                </xsl:call-template>
              </td>
            </xsl:for-each>
          </tr>
        </table>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Matches the root node. This starts the XSL processing. -->
  <xsl:template match="/" >

    <html>
      <head>
        <!-- Support the latest IE -->
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />

        <!-- All times are displayed using local time. Store the offset at which the report was generated in
             case someone needs to calculate the UTC times (although this is not entirely sufficient if the
             machine has moved timezones during the report period. -->
        <meta name="ReportUtcOffset" content="{$reportInfo/slp:UtcOffset}" />

        <title>System Power Report</title>

        <!-- CSS styles -->
        <xsl:call-template name="css"/>

        <!-- JavaScript -->
        <xsl:call-template name="javascript">
          <xsl:with-param name="sessions" select="/slp:SleepStudy/slp:ScenarioInstances" />
          <xsl:with-param name="dripsBuckets" select="/slp:SleepStudy/slp:ScenarioInstances/slp:ScenarioInstance/slp:DripsBuckets" />
          <xsl:with-param name="energyDrains" select="/slp:SleepStudy/slp:EnergyDrains" />
        </xsl:call-template>
      </head>

      <body>

        <h1>System Power Report</h1>

        <!-- Report warnings, if any -->
        <xsl:apply-templates select="/slp:SleepStudy/slp:Warnings" />

        <!-- Describe the machine -->
        <xsl:call-template name="systemInformation" />

        <!-- Summary Table -->
        <xsl:if test="$singleTraceFile = 'false'">
          <h2>System Power State Transitions</h2>
          <xsl:choose>
            <xsl:when test="boolean(/slp:SleepStudy/slp:EnergyDrains)">
              <div class="explanation">
                Battery drains over the last <xsl:value-of select="$reportDuration" /> days
              </div>
              <xsl:call-template name="batteryDrainGraph" />
            </xsl:when>
            <xsl:otherwise>
              <div class="explanation">
                Connected Standby transitions over the last <xsl:value-of select="$reportDuration" /> days
              </div>
            </xsl:otherwise>
          </xsl:choose>
          <xsl:apply-templates select="/slp:SleepStudy/slp:ScenarioInstances" mode="summaryTable" />
        </xsl:if>

        <!-- Analysis results -->
        <h2>Analysis Results</h2>
        <div class="explanation">Analysis of issues that might cause poor battery life</div>
        <xsl:apply-templates select="/slp:SleepStudy/slp:ScenarioInstances" mode="analysisResults" />

        <!-- Installed batteries -->
        <xsl:apply-templates select="/slp:SleepStudy/slp:Batteries" />

        <br />
        <br />
        <br />
      </body>
    </html>
  </xsl:template>

  <!-- Formats a date-time for display -->
  <xsl:template name="formatDateTime">
    <xsl:param name="dateTime"/>
    <xsl:param name="showDate" select="true()" />
    <xsl:variable name="date" select="substring-before($dateTime, 'T')"/>
    <xsl:variable name="time" select="translate(substring-after($dateTime, 'T'), 'T ', '')"/>

    <span class="date">
      <xsl:if test="$showDate">
        <xsl:value-of select="$date"/>
      </xsl:if>
      <!-- Include some space so that the tag doesn't self-close (HTML requirement) -->
      <xsl:text> </xsl:text>
    </span>
    <span class="time">
      <xsl:value-of select="$time"/>
    </span>
  </xsl:template>

  <!-- Outputs the given string, or a dash ('-') if the string is empty -->
  <xsl:template name="dashIfEmpty">
    <xsl:param name="str"/>
    <xsl:variable name="s" select="normalize-space($str)" />
    <xsl:choose>
      <xsl:when test="string-length($s) = 0">
        -
      </xsl:when>
      <xsl:when test="$s = '0'">
        -
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$s"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Formats a mWh value -->
  <xsl:template name="mWh">
    <xsl:param name="value"/>
    <xsl:variable name="number" select="number($value)" />
    <xsl:choose>
      <!-- Test for not NaN, not 0, and not Infinity -->
      <xsl:when test="$number != 0 and $number = $number and $number != (1 div 0) and $number != (-1 div 0)">
        <xsl:value-of select="js:numberToLocaleString($number)"/> mWh
      </xsl:when>
      <xsl:otherwise>
        -
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Formats a mWh value for a table cell -->
  <xsl:template name="mWhCell">
    <xsl:param name="batteryDrain"/>
    <xsl:param name="batteryCapacity"/>
    <xsl:param name="batteryCountChanged"/>
    <xsl:choose>
      <!-- Test for not NaN, not 0, and not Infinity -->
      <xsl:when test="($batteryCountChanged = 0 and $batteryDrain &gt; 0 and $batteryDrain = $batteryDrain and $batteryDrain != (1 div 0) and $batteryDrain != (-1 div 0))
                      and ($batteryCapacity != 0 and $batteryCapacity = $batteryCapacity and $batteryCapacity != (1 div 0) and $batteryCapacity != (-1 div 0))">
        <td class="mw">
          <xsl:value-of select="js:numberToLocaleString(number($batteryDrain))"/> mWh
        </td>
        <td class="mw">
          <xsl:value-of select="js:numberToLocaleString(round(100 * $batteryDrain div $batteryCapacity))"/>% of battery
        </td>
      </xsl:when>
      <xsl:otherwise>
        <td class="nullValue">-</td>
        <td class="nullValue">-</td>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Formats a % value -->
  <xsl:template name="percent">
    <xsl:param name="value"/>
    <xsl:choose>
      <xsl:when test="$value &gt; 0 and $value &lt; (1 div 0)">
        <xsl:value-of select="$value"/>%
      </xsl:when>
      <xsl:otherwise>-</xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Formats an energy value for a table cell -->
  <xsl:template name="mWCell">
    <xsl:param name="energyDrain" />
    <xsl:param name="batteryCountChanged"/>
    <xsl:choose>
      <xsl:when test="($batteryCountChanged = 0 and $energyDrain &gt; 0 and $energyDrain &lt; (1 div 0))">
        <td class="mw">
          <xsl:value-of select="js:numberToLocaleString(round($energyDrain))"/> mW
        </td>
      </xsl:when>
      <xsl:otherwise>
        <td class="nullValue">-</td>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Formats a % value for a table cell -->
  <xsl:template name="percentCell">
    <xsl:param name="remainingCapacity"/>
    <xsl:param name="fullCapacity"/>
    <xsl:param name="batteryCountChanged"/>
    <xsl:choose>
      <!-- Test for not NaN, not 0, and not Infinity -->
      <xsl:when test="($batteryCountChanged = 0 and $remainingCapacity &gt; 0 and $remainingCapacity = $remainingCapacity and $remainingCapacity != (1 div 0) and $remainingCapacity != (-1 div 0))
                      and ($fullCapacity != 0 and $fullCapacity = $fullCapacity and $fullCapacity != (1 div 0) and $fullCapacity != (-1 div 0))">
        <td class="mw">
          <xsl:value-of select="js:numberToLocaleString(round(100 * $remainingCapacity div $fullCapacity))"/>%
        </td>
      </xsl:when>
      <xsl:otherwise>
        <td class="nullValue">-</td>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Formats the DRIPS Wake Reasons table entry -->
  <xsl:template match="slp:DripsWakeSources">
    <div>
      <xsl:attribute name="class">
        <xsl:text>analysis-container </xsl:text>
        <xsl:choose>
          <xsl:when test="count(slp:DripsWakeSource) = 0">
            <xsl:text>analysis-neutral</xsl:text>
          </xsl:when>
          <xsl:otherwise>
            <xsl:text>analysis-info</xsl:text>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:attribute>
      <h1>
        <span class="expander">+ </span>DRIPS Wake Sources
      </h1>
      <div class="analysis-body-collapsed">
        <xsl:choose>
          <xsl:when test="count(slp:DripsWakeSource) = 0">
            <div class="analysis-empty">No DRIPS wake source information obtained.</div>
          </xsl:when>
          <xsl:otherwise>
            <table class="pdc-phases">
              <thead>
                <th>WAKE SOURCE</th>
                <th>WAKE TYPE</th>
                <th>COUNT</th>
              </thead>
              <tbody>
                <xsl:for-each select="slp:DripsWakeSource">
                  <xsl:sort select="@Count" data-type="number" order="descending" />
                  <tr class="row-info">
                    <td>
                      <xsl:value-of select="@ReasonDescription" />
                    </td>
                    <td class="center">
                      <xsl:value-of select="@Type" />
                    </td>
                    <td class="center">
                      <xsl:value-of select="js:numberToLocaleString(number(@Count))" />
                    </td>
                  </tr>
                </xsl:for-each>
              </tbody>
            </table>
          </xsl:otherwise>
        </xsl:choose>
      </div>
    </div>
  </xsl:template>

  <ms:script implements-prefix="js">
    <![CDATA[
    // Formats a number using the current locale (to handle the 1000's separator).
    // The result is rounded so no decimal point is shown.
    function numberToLocaleString(value) {
      var localeString = Math.round(parseFloat(value + '')).toLocaleString();
      return localeString.substring(0, localeString.indexOf('.'));
    }

    function padLeft(number, length) {
      var str = '' + number;
      while (str.length < length) {
        str = '0' + str;
      }
      return str;
    }

    // Returns the number of milliseconds between 2 date-times represented as strings.
    function msBetween(startTime, endTime) {
      return startTime > endTime
          ? msBetween(endTime, startTime)
          : parseDateTime(endTime) - parseDateTime(startTime);
    }


    var dateFormat = /(\d{4})-(\d{2})-(\d{2})[T](\d{2}):(\d{2}):(\d{2})/

    // Parses a date-time string and returns a Date (i.e. number of milliseconds)
    function parseDateTime(value) {
      if (!value) {
        return 0;
      }
      var match = dateFormat.exec(value)
      if (!match) {
        return 0;
      }
      return Date.parse(match[1] + '/' + match[2] + '/' + match[3] + ' ' + match[4] + ':' + match[5] + ':' + match[6])
    }

    // Parses just the date portion of a date-time string and returns a Date (i.e. number of milliseconds)
    function parseDate(value) {
      if (!value) {
        return 0;
      }
      var match = dateFormat.exec(value)
      if (!match) {
        return 0;
      }
      return Date.parse(match[1] + '/' + match[2] + '/' + match[3])
    }

    var durationFormat = /P((\d+)D)?T((\d+)H)?((\d+)M)?(\d+)S/

    // Convert a string of the form P10DT1H15M40S to a count of milliseconds
    function parseDurationToMs(value) {
      var match = durationFormat.exec(value)
      if (!match) {
        return 0
      }
      var days = parseInt(match[2] || '0');
      var hrs = parseInt(match[4] || '0');
      var mins = parseInt(match[6] || '0');
      var secs = parseInt(match[7] || '0');
      return ((((((days * 24) + hrs) * 60) + mins) * 60) +  secs) * 1000;
    }

    // Formats a number of milliseconds as h:mm:ss
    function formatDurationMs(value) {
      var ms = parseInt(value);
      var secs = ms / 1000;
      var mins = secs / 60;
      var hrs = Math.floor(mins / 60);
      mins = Math.floor(mins % 60);
      secs = Math.floor(secs % 60);
      return hrs + ':' + padLeft(mins,2) + ':' + padLeft(secs,2);
    }

    // Converts a string representing a date time to a day and month string
    function dateToDayAndMonth(date, dayOffset) {
      var adjustedDate = new Date(parseDate(date) - (dayOffset * 24 * 60 * 60 * 1000));
      return padLeft(adjustedDate.toLocaleDateString());
    }

    // Format Charge and Drain strings that sometimes reflect extra text
    // for special cases around transitioning from CS to S4/S5 due to:
    // - transitioning to S4 due to a critically low battery,
    // - transitioning to S4 or S5 due to a thermal condition,
    // - doze to S4 after a specified duration in CS.
    function createChargeDrainString(onAc, scenarioStopReason) {
        var _onAc = parseInt(onAc);                             // BOOLEAN
        var _scenarioStopReason = parseInt(scenarioStopReason); // SLEEPSTUDY_SPM_SCENARIO_STOP_REASON
        var str;
        if (_onAc) {
            str = 'Charge';
        } else {
            str = 'Drain';
        }

        if(onAc == -1) {
            str ='-';
        }

        if (_scenarioStopReason == 1) {             // PolicyDeviceThermalZone
            str = str + ' (thermal)';
        } else if (_scenarioStopReason == 2) {      // PolicyDeviceBattery
            str = str + ' (critical battery)';
        } else if (_scenarioStopReason == 6) {      // PolicyImmediateDozeS4
            str = str + ' (dozed to hibernate)';
        } else if (_scenarioStopReason == 11) {      // PolicyImmediateDozeS4Predicted
            str = str + ' (dozed to hibernate because the user was predicted to be away)';
        } else if (_scenarioStopReason == 12) {      // PolicyImmediateDozeS4PredictedNoWake
            str = str + ' (dozed to hibernate because the user was predicted to be away)';
        } else if (_scenarioStopReason == 13) {      // PolicyImmediateDozeS4AdaptiveBudget
            str = str + ' (dozed to hibernate because the standby battery budget was exceeded)';
        } else if (_scenarioStopReason == 14) {      // PolicyImmediateDozeS4AdaptiveReserveNoWake
            str = str + ' (dozed to hibernate because the reserve battery level was reached)';
        } else if (_scenarioStopReason == 16) {     // SpmScenarioStopReasonUnspecified
            str = str + ' (unspecified sleep reason)';
        } else if (_scenarioStopReason == 17) {     // SpmScenarioStopReasonCsExit
            str = str;      // nop
        } else if (_scenarioStopReason == 18) {     // SpmScenarioStopReasonInternalSegmentTransition
            str = str;      // nop
        } else {
            str = str + ' (unrecognized sleep reason ' + _scenarioStopReason + ')';
        }

        return str;
    }
    ]]>
  </ms:script>
</xsl:stylesheet>
PADPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDING