KGRKJGETMRETU895U-589TY5MIGM5JGB5SDFESFREWTGR54TY
Server : Apache/2.4.58 (Win64) OpenSSL/3.1.3 PHP/8.2.12
System : Windows NT SERVER-PC 10.0 build 26200 (Windows 11) AMD64
User : ServerPC ( 0)
PHP Version : 8.2.12
Disable Function : NONE
Directory :  C:/Windows/System32/nb-NO/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : C:/Windows/System32/nb-NO/energy.dll.mui
MZ����@���	�!�L�!This program cannot be run in DOS mode.

$�X=��9S��9S��9S������9S���Q��9S�Rich�9S�PELk���!&(

P�t@  $8.rdata�@@.rsrc $ &@@k��
lPPk��$����8.rdata8.rdata$voltmdP�.rdata$zzzdbg �.rsrc$01�+.rsrc$02 �NCM6����e�]�ε&�p>#�k��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�hx��������(8HXhx��������(8HXhx��������		(	8	H	t+��,,���.���/���0���3f�:���?��4G���M&��T��\���a��@eL��i��hl<��pR��qX�Py0��{��l}6����	�,���Ȕ�����������������*���h�T���$�����x�@�h���F���4�$�0�T���������&��l�%��4������������F�p����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���^�c���C���J�w���n�t�%�o����MUInb-NOMislykket analyse[Analysen var mislykket. Dette kan skyldes en skadet sporingsfil eller forkastede hendelser.Analysefeil_Analysen var delvis mislykket. Noen resultater er tilgjengelige, men de kan v�re ufullstendige.Vellykket analyse_Analysen var vellykket. Fant ingen problemer med str�mforbruk. Ingen informasjon ble returnert.SysteminformasjonSysteminformasjonSystemdetaljerDatamaskinnavnSystemprodusentProduktnavn for system	BIOS-datoBIOS-versjonByggnummer for operativsystemPlattftormrolleAntall prosesser
Tr�dtellerG�r p� str�m Tidtakeroppl�sning for plattform Tidtakeroppl�sning for plattform+Standard tidtakeroppl�sning for plattformen er 15,6 ms (15 625 000 ns) og skal brukes n�r systemet er inaktivt. Hvis tidtakeroppl�sningen �kes, kan det f�re til at str�mstyringsteknologiene ikke fungerer. Tidtakeroppl�sningen kan �kes p� grunn av avspilling av multimedia eller grafiske animasjoner.PA2Gjeldende tidtakeroppl�sning (i enheter p� 100 ns).Maksimal tidtakerperiode (i enheter p� 100 ns)Utest�ende tidtakerforesp�rsel}Et program eller en tjeneste har bedt om en lavere tidtakeroppl�sning enn den maksimale tidtakeroppl�sningen for plattformen.�nsket periodeProsess-ID for foresp�rselProsessbane for foresp�rsel)Utest�ende tidtakerforesp�rsel fra kjerne�En kjernekomponent eller enhetsdriver har bedt om en tidtakeroppl�sning som er lavere enn maksimal tidtakeroppl�sning for plattformen.�nsket periodeAntall foresp�rsler�Et program eller en tjeneste har bedt om en tidtakeroppl�sning som er lik eller st�rre enn maksimal tidtakeroppl�sning for plattformen.Tidtakerforesp�rselsstakkeStakken av moduler som er ansvarlig for den laveste plattformtidtakerinnstillingen i denne prosessen.OppringingsmodulPAStr�mpolicyAktiv str�mstyringsplanGjeldende str�mstyringsplan	Plan-GUID4Personlighet for str�mstyringsplan (p� batteristr�m)SPersonligheten for gjeldende str�mstyringsplan n�r systemet kj�res p� batteristr�m.PersonlighetBPersonlighet for str�mstyringsplan er H�y ytelse (p� batteristr�m)_Gjeldende personlighet for str�mstyringsplan er H�y ytelse n�r systemet kj�res p� batteristr�m.0Tidsavbrudd for skjerm deaktivert (batteridrift)NSkjermen er ikke konfigurert for � sl� seg av etter en periode uten aktivitet..Tidsavbrudd for skjerm er langt (batteridrift)DSkjermen er konfigurert for � sl� seg av etter mer enn fem minutter.Tidsavbrudd (sekunder)7Tidsavbrudd for lysdemping er deaktivert (batteridrift)PAOSkjermen er ikke konfigurert for � dempe lyset etter en periode uten aktivitet.2Tidsavbrudd for lysdemping er langt (batteridrift)NSkjermen er konfigurert for � dempe lyset automatisk etter mer enn 5 minutter.Tidsavbrudd (sekunder)1Tidsavbrudd for disk er deaktivert (batteridrift)PDisken er ikke konfigurert for � sl� seg av etter en periode uten diskaktivitet.,Tidsavbrudd for disk er langt (batteridrift)ADisken er konfigurert for � sl� seg av etter mer enn 30 minutter.Tidsavbrudd (sekunder)7Tidsavbrudd for hvilemodus er deaktivert (batteridrift)bDatamaskinen er ikke konfigurert for � g� i hvilemodus automatisk etter en periode uten aktivitet.2Tidsavbrudd for hvilemodus er langt (batteridrift)WDatamaskinen er konfigurert for � g� i hvilemodus automatisk etter mer enn 30 minutter.Tidsavbrudd (sekunder)=Minimum ytelsestilstand for prosessor er 100 % (batteridrift)]Prosessoren er ikke konfigurert for � redusere str�mforbruket automatisk basert p� aktivitet.PA;Minimum ytelsestilstand for prosessor er h�y (batteridrift)]Den laveste ytelsestilstanden for prosessoren er h�yere enn 75 % av maksimal ytelsestilstand..Minimum ytelsestilstand (% av maksimal ytelse)>Inaktive tilstander for prosessor er deaktivert (batteridrift)wGjeldende str�mstyringspolicy for prosessoren har deaktivert inaktive tilstander med lavt str�mforbruk for prosessoren.6Selektiv USB-deaktivering er deaktivert (batteridrift)GGjeldende str�mpolicy har deaktivert selektiv USB-deaktivering globalt.FStr�mpolicy for 802.11-nettverkskort er maksimal ytelse (batteridrift)lGjeldende str�mpolicy for 802.11-kompatible nettverkskort er ikke konfigurert for � bruke str�msparingsmodi.-PCI Express ASPM er deaktivert (batteridrift)YGjeldende str�mpolicy for PCI Express Active State Power Management (ASPM) er deaktivert./Personlighet for str�mstyringsplan (koblet til)JPersonligheten for gjeldende str�mstyringsplan n�r systemet er koblet til.=Personlighet for str�mstyringsplan er H�y ytelse (koblet til)VGjeldende personlighet for str�mstyringsplan er H�y ytelse n�r systemet er koblet til.0Tidsavbrudd for skjerm deaktivert (g�r p� str�m)NSkjermen er ikke konfigurert for � sl� seg av etter en periode uten aktivitet..Tidsavbrudd for skjerm er langt (g�r p� str�m)CSkjermen er konfigurert for � sl� seg av etter mer enn 10 minutter.7Tidsavbrudd for lysdemping er deaktivert (g�r p� str�m)OSkjermen er ikke konfigurert for � dempe lyset etter en periode uten aktivitet.2Tidsavbrudd for lysdemping er langt (g�r p� str�m)OSkjermen er konfigurert for � dempe lyset automatisk etter mer enn 10 minutter.1Tidsavbrudd for disk er deaktivert (g�r p� str�m)PDisken er ikke konfigurert for � sl� seg av etter en periode uten diskaktivitet.PA,Tidsavbrudd for disk er langt (g�r p� str�m)ADisken er konfigurert for � sl� seg av etter mer enn 30 minutter.7Tidsavbrudd for hvilemodus er deaktivert (g�r p� str�m)bDatamaskinen er ikke konfigurert for � g� i hvilemodus automatisk etter en periode uten aktivitet.2Tidsavbrudd for hvilemodus er langt (g�r p� str�m)WDatamaskinen er konfigurert for � g� i hvilemodus automatisk etter mer enn 30 minutter.=Minimum ytelsestilstand for prosessor er 100 % (g�r p� str�m)]Prosessoren er ikke konfigurert for � redusere str�mforbruket automatisk basert p� aktivitet.;Minimum ytelsestilstand for prosessor er h�y (g�r p� str�m)]Den laveste ytelsestilstanden for prosessoren er h�yere enn 75 % av maksimal ytelsestilstand.>Inaktive tilstander for prosessor er deaktivert (g�r p� str�m)wGjeldende str�mstyringspolicy for prosessoren har deaktivert inaktive tilstander med lavt str�mforbruk for prosessoren.6Selektiv USB-deaktivering er deaktivert (g�r p� str�m)GGjeldende str�mpolicy har deaktivert selektiv USB-deaktivering globalt.PAFStr�mpolicy for 802.11-nettverkskort er maksimal ytelse (g�r p� str�m)lGjeldende str�mpolicy for 802.11-kompatible nettverkskort er ikke konfigurert for � bruke str�msparingsmodi.-PCI Express ASPM er deaktivert (g�r p� str�m)YGjeldende str�mpolicy for PCI Express Active State Power Management (ASPM) er deaktivert.Videokvalitet (batteridrift)gGj�r at Windows Media Player kan optimaliseres for kvalitet eller str�msparing ved avspilling av video.KvalitetsmodusVideokvalitet (g�r p� str�m)gGj�r at Windows Media Player kan optimaliseres for kvalitet eller str�msparing ved avspilling av video.%Foresp�rsler om systemtilgjengelighet"Foresp�rsel n�dvendig for systemetHProgrammet har bedt om at systemet ikke skal g� i hvilemodus automatisk.Prosess for foresp�rselSystem Required RequestGTjenesten har bedt om at systemet ikke skal g� i hvilemodus automatisk.Tjeneste for foresp�rselSystem Required RequestTEnheten eller driveren har bedt om at systemet ikke skal g� i hvilemodus automatisk.Driverforekomst for foresp�rselDriverenhet for foresp�rselPASystem Required RequestPEn kjernekomponent har bedt om at systemet ikke skal g� i hvilemodus automatisk.Vis obligatorisk foresp�rselEProgrammet har bedt om at skjermen ikke skal g� i str�msparingsmodus.Foresp�rsel om frav�rsmodus1Programmet har bedt om at frav�rsmodus aktiveres.Foresp�rsel om frav�rsmodus0Tjenesten har bedt om at frav�rsmodus aktiveres. Foresp�rsel om n�dvendig kj�ring<Programmet har lagt inn en foresp�rsel om n�dvendig kj�ring. Foresp�rsel om n�dvendig kj�ring;Tjenesten har lagt inn en foresp�rsel om n�dvendig kj�ring.USB-deaktivering#USB-enhet ikke selektivt deaktivert�Denne enheten gikk ikke over i USB selektivt deaktivert tilstand. Str�mstyring for prosessoren kan bli hindret n�r denne USB-enheten ikke g�r over i selektivt deaktivert tilstand. Merk at dette ikke vil hindre systemet i � g� i hvilemodus.Vertskontroller-IDVertskontrollerplassering	Enhets-IDPortbane&USB-enhet sjelden selektivt deaktivertDenne enheten gikk bare periodevis over i USB selektivt deaktivert tilstand under sporingen. Str�mstyring for prosessoren kan bli hindret hvis denne USB-enheten ikke er i selektivt deaktivert tilstand. Merk at dette ikke vil hindre systemet i � g� i hvilemodus.Deaktiveringstid (%)GrunngDenne Bluetooth USB-enheten st�tter ikke selektiv deaktivering fordi den er ikke selvforsynt med str�m.cDenne Bluetooth USB-enheten st�tter ikke selektiv deaktivering fordi den kan ikke startes eksternt.ProsessorutnyttelseProsessorutnyttelsen er lavkGjennomsnittlig prosessorutnyttelse under sporingen var sv�rt lav, som betyr at systemet bruker lite str�m.PAGjennomsnittlig utnyttelse (%)Prosessorutnyttelsen er moderat*Gjennomsnittlig prosessorutnyttelse under sporingen var moderat. Systemet bruker mindre str�m n�r gjennomsnittlig prosessorutnyttelse er sv�rt lav. Kontroller prosessorutnyttelsen til enkeltprosesser for � finne ut hvilke programmer og tjenester som bidrar mest til den totale prosessorutnyttelsen.Prosessorutnyttelsen er h�y&Gjennomsnittlig prosessorutnyttelse under sporingen var h�y. Systemet bruker mindre str�m n�r gjennomsnittlig prosessorutnyttelse er sv�rt lav. Kontroller prosessorutnyttelsen til enkeltprosesser for � finne ut hvilke programmer og tjenester som bidrar mest til den totale prosessorutnyttelsen.0Enkeltprosess med betydelig prosessorutnyttelse.pDenne prosessen st�r for en betydelig del av den totale prosessorutnyttelsen som ble registrert under sporingen.ProsessnavnPIDGjennomsnittlig utnyttelse (%)Modul#Gjennomsnittlig modulutnyttelse (%)BatteriBatteriinformasjon
Batteri-ID	ProdusentProduksjonsdatoSerienummerKjemiLangtidsbatteriSyklusantallSpesifisert kapasitetSiste fulladingSiste fullading (%)XBatteriet lagret mindre enn 50 % av spesifisert kapasitet forrige gang det ble fulladet.Siste fullading (%)Siste fullading (%)XBatteriet lagret mindre enn 40 % av spesifisert kapasitet forrige gang det ble fulladet.Ukjent batterikapasitetZBatterikapasiteten kunne ikke fastsl�s. Dette kan tyde p� et problem med fastvaren (BIOS).	ForsegletPA%Str�mstyringsfunksjoner for plattformSt�ttede hvilemodi[Hvilemodi gj�r det mulig for datamaskinen � g� over i str�msparingsmodi etter en periode uten aktivitet. S3-hvilemodus er standard hvilemodus for Windows-plattformer. S3-hvilemodus bruker bare tilstrekkelig str�m til � bevare innholdet i minnet og til at datamaskinen kan startes raskt opp igjen. Sv�rt f� plattformer st�tter S1- og S2-hvilemodus.St�tter S1-hvilemodusSt�tter S2-hvilemodusSt�tter S3-hvilemodusSt�tter S4-hvilemodusgS1-hvilemodus er deaktivert p� grunn av en kjent inkompatibilitet med maskinvaren i denne datamaskinen.�Windows deaktiverer hvilemodus automatisk p� noen datamaskiner med maskinvare som ikke er kompatibel med hvilemodus. Problemet kan kanskje l�ses ved � installere den nyeste fastvaren (BIOS).PAgS2-hvilemodus er deaktivert p� grunn av en kjent inkompatibilitet med maskinvaren i denne datamaskinen.�Windows deaktiverer hvilemodus automatisk p� noen datamaskiner med maskinvare som ikke er kompatibel med hvilemodus. Problemet kan kanskje l�ses ved � installere den nyeste fastvaren (BIOS).gS3-hvilemodus er deaktivert p� grunn av en kjent inkompatibilitet med maskinvaren i denne datamaskinen.�Windows deaktiverer hvilemodus automatisk p� noen datamaskiner med maskinvare som ikke er kompatibel med hvilemodus. Problemet kan kanskje l�ses ved � installere den nyeste fastvaren (BIOS).'Systemfastvaren (BIOS) st�tter ikke S3.<Maskinvaren i denne datamaskinen st�tter ikke S3-hvilemodus.4Systemfastvaren (BIOS) st�tter ikke S4 (dvalemodus).IMaskinvaren i denne datamaskinen st�tter ikke S4-hvilemodus (dvalemodus).gS3-hvilemodus er deaktivert p� grunn av en kjent inkompatibilitet med maskinvaren i denne datamaskinen.�Windows deaktiverer hvilemodus automatisk p� noen datamaskiner med maskinvare som ikke er kompatibel med hvilemodus. Problemet kan kanskje l�ses ved � installere den nyeste fastvaren (BIOS).)Hvilemodus er deaktivert i str�mpolicyen.<Systemansvarlig har deaktivert hvilemodus p� dette systemet.ADvalemodus er deaktivert fordi systemet har for mye fysisk minne.UDvalemodus er deaktivert p� grunn av et ukjent problem med undersystemet for lagring.PDvalemodus er deaktivert fordi dvalemodusfilen ikke kunne genereres eller �pnes.=Hvilemodus er deaktivert fordi en eldre driver er installert.�Hvilemodus krever at alle enhetsdrivere er kompatible med Plug and Play og str�mstyring. Hvis en eldre driver blir installert, blir hvilemodus automatisk deaktivert.
Drivernavn=S1-hvilemodus er automatisk deaktivert av en systemkomponent.mDatamaskinen vil kanskje ikke g� over i hvilemodus n�r f�lgende komponenter installeres eller oppgaver p�g�r.UMicrosoft grunnleggende skjermdriver eller Microsoft grunnleggende gjengivelsesdriver
Hypervisor7Systemet startes opp fra en virtuell harddiskfil (VHD).>S2-hvilemodus er midlertidig deaktivert av en systemkomponent.mDatamaskinen vil kanskje ikke g� over i hvilemodus n�r f�lgende komponenter installeres eller oppgaver p�g�r.PA>S3-hvilemodus er midlertidig deaktivert av en systemkomponent.mDatamaskinen vil kanskje ikke g� over i hvilemodus n�r f�lgende komponenter installeres eller oppgaver p�g�r.KS4-hvilemodus (dvalemodus) er midlertidig deaktivert av en systemkomponent.mDatamaskinen vil kanskje ikke g� over i hvilemodus n�r f�lgende komponenter installeres eller oppgaver p�g�r.'St�tter justerbar lysstyrke for skjerm.YP� denne datamaskinen kan Windows automatisk styre lysstyrken p� den integrerte skjermen.)St�tte for justerbar lysstyrke for skjerm�Denne datamaskinen tillater ikke at Windows automatisk styrer lysstyrken p� den integrerte skjermen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).%Str�mstyringsfunksjoner for prosessorvEffektiv str�mstyring for prosessoren gj�r at datamaskinen automatisk kan skape balanse mellom ytelse og str�mforbruk.GruppeIndeksAntall inaktive tilstander (C)Antall ytelsestilstander (P)!Antall begrensningstilstander (T)*Mislykket validering av C2-tilstand i ACPI�Det er et problem med definisjonen av den inaktive tilstanden C2 p� denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).*Mislykket validering av C3-tilstand i ACPI�Det er et problem med definisjonen av den inaktive tilstanden C3 p� denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).5Mislykket validering av begrensningstilstander i ACPI�Det er et problem med definisjonen av begrensningstilstander p� denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).(Mislykket validering av ACPI _CST-objekt�Det er et problem med definisjonen av ACPI _CST-objektet p� denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).(Mislykket validering av ACPI _CSD-objekt�Det er et problem med definisjonen av ACPI _CSD-objektet p� denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).(Mislykket validering av ACPI _PCT-objekt�Det er et problem med definisjonen av ACPI _PCT p� denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).(Mislykket validering av ACPI _PSS-objekt�Det er et problem med definisjonen av ACPI _PSS-objektet p� denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).(Mislykket validering av ACPI XPSS-objekt�Det er et problem med definisjonen av ACPI XPSS-objektet p� denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).(Mislykket validering av ACPI _PPC-objekt�Det er et problem med definisjonen av ACPI _PPC-objektet p� denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).(Mislykket validering av ACPI _PSD-objekt�Det er et problem med definisjonen av ACPI _PSD-objektet p� denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).(Mislykket validering av ACPI _PTC-objekt�Det er et problem med definisjonen av ACPI _PTC-objektet p� denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).(Mislykket validering av ACPI _TSS-objekt�Det er et problem med definisjonen av ACPI _TSS-objektet p� denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).(Mislykket validering av ACPI _TPC-objekt�Det er et problem med definisjonen av ACPI _TPC-objektet p� denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).(Mislykket validering av ACPI _TSD-objekt�Det er et problem med definisjonen av ACPI _TSD-objektet p� denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).@Feil antall medlemmer av domene for inaktive prosessortilstander�Det er et problem med antall prosessorer som er definert som medlemmer av et domene for prosessorinaktivitet. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).	Domene-IDForventet medlemsantallFaktisk medlemsantallYFeil antall medlemmer av domene for ytelses- eller begrensningstilstander for prosessorer�Det er et problem med antall prosessorer som er definert som medlemmer av et domene for ytelses- eller begrensningstilstander. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).'Inaktive prosessortilstander deaktivert�Inaktive prosessortilstander er automatisk deaktivert p� grunn av en kjent inkompatibilitet med maskinvaren i denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).*Ytelsestilstander for prosessor deaktivert�Ytelsestilstander for prosessor er automatisk deaktivert p� grunn av en kjent inkompatibilitet med maskinvaren i denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS)./Begrensningstilstander for prosessor deaktivert�Begrensningstilstander for prosessor er automatisk deaktivert p� grunn av en kjent inkompatibilitet med maskinvaren i denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).;PCI Express Active-State Power Management (ASPM) deaktivert�PCI Express Active-State Power Management (ASPM) er deaktivert p� grunn av en kjent inkompatibilitet med maskinvaren i denne datamaskinen.4Tr�dl�st tilgangspunkt st�tter ikke WMM-str�msparing�Det tr�dl�se tilgangspunktet som datamaskinen er koblet til st�tter ikke WMM-str�msparing. Det tr�dl�se nettverkskortet kan ikke g� i str�msparingsmodus for � spare energi slik det defineres i str�mpolicyen for tr�dl�st nettverkskort.SSIDMAC-adresseSt�tte for tilkoblet ventemodus�Tilkoblet ventemodus lar datamaskinen g� i tilstand for lavt str�mforbruk der den alltid er p� og tilkoblet. Hvis dette st�ttes, brukes tilkoblet ventemodus i stedet for systemdeaktivering.PASt�tter tilkoblet ventemodus(Mislykket validering av ACPI PCCP-objekt�Det er et problem med definisjonen av ACPI PCCP-objektet p� denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).(Mislykket validering av ACPI _CPC-objekt�Det er et problem med definisjonen av ACPI _CPC-objektet p� denne datamaskinen. Problemet kan kanskje l�ses ved � installere den nyeste systemfastvaren (BIOS).Antall inaktive tilstanderInaktiv tilstandstypeNominell frekvens (MHz)Maksimal ytelsesprosentLaveste ytelsesprosentLaveste throttle-prosentYtelseskontrolltypeIngen3ACPI Ytelsestilstand (P) / Begrensningstilstand (T)Plattformklokkekontroll/Prosessorytelseskontroll med samarbeidende ACPIPlugin-modul for str�mmotorACPI Inaktivitetstilstander (C)
Windows To GoJTilkoblet ventemodus er deaktivert p� grunn av ikke-kompatibel maskinvare.�Denne datamaskinen har angitt st�tte for tilkoblet ventemodus, men �n eller flere maskinvarekomponenter samsvarer ikke med kravene for denne tilstanden. F�lgende komponent(er) oppfyller ikke disse kravene:LagringsmaskinvareTr�dl�st nettverkskortMaskinvare for mobilt bredb�nd
Lydmaskinvare
KompatibelIkke kompatibel Plugin-modul for mikrokraftmotorGDvale modus er deaktivert fordi maskin varen ikke kan g� i dvale modus.TDvale modus er deaktivert fordi ressurs mangel for den virtuelle OPPSTARTS adressen.PAMDvale modus er deaktivert fordi ressursen mangler for � f� en dvale kontekst.WDvalemodus er deaktivert p� grunn av ressursmangel for forh�ndstildeling av dvalemodus.
EnhetsdrivereJEnheter med manglende eller feilkonfigurerte drivere kan �ke str�mforbruk.PA
Enhetsnavn	Enhets-IDEnhetsstatusKode for enhetsproblemUkjent enhetPAHvilestudie`Obs!  Denne rapporten inneholder ikke informasjon for den f�rste �kten for tilkoblet ventemodus.ADen f�rste �kten for tilkoblet ventemodus startet i en tidligere tidsramme. Hvis du er interessert i den tidligere tidsrammen, bruker du &lt;code&gt;powercfg sleepstudy -duration DURATION&lt;/code&gt;. Hvis du for eksempel vil analyse de siste ti dagene:&lt;br /&gt;&lt;pre&gt;powercfg sleepstudy -duration 10&lt;/pre&gt;#Analysefeil funnet for aktiveringer!Analysefeil funnet for Fx-enheter Analysefeil funnet for PDC-faser@Summen av varighetene til PDC-faser er st�rre enn CS-varigheten.SystemhendelsesloggPA
EnhetsnavnPP Informasjon

�4VS_VERSION_INFO��
(�e
(�e?�StringFileInfo�041404B0LCompanyNameMicrosoft CorporationTFileDescriptionStr�msparingsdiagnosen'FileVersion10.0.26100.3624 (WinBuild.160101.0800)6InternalNameenergy.dllp&LegalCopyright� Microsoft Corporation. Med enerett.FOriginalFilenameenergy.dll.muij%ProductNameOperativsystemet Microsoft� Windows�DProductVersion10.0.26100.3624DVarFileInfo$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;
}

/*
   container-root and container-group provide the base styling for all containers.
   container-group must also be provided with one of the container-* classes to
   provide the background and hover styling.
*/

ul.container-root {
    padding: 0;
    list-style: none;
}

li.container-group {
    margin-top: 5px;
    margin-bottom: 5px;
    border: 1px solid #ffffff;
}

li.container-group > span {
    padding: 10px;
    font-size: 14px;
    display: block;
    color: #000000;
    cursor: pointer;
}

li.container-group > ul {
    padding: 10px;
    list-style: none;
}

li.container-group[aria-expanded="false"] > ul {
    display: none;
}

li.container-group[aria-expanded="true"] > ul {
    display: block;
}

li.container-group[aria-expanded="false"] > span::before {
    content: "+ ";
    font-family: "Consolas";
    font-weight: bold;
}

li.container-group[aria-expanded="true"] > span::before {
    content: "- ";
    font-family: "Consolas";
    font-weight: bold;
}

/*
   container-* classes must provide a background-color for
    - li.container-*
    - li.container-* > span
    - li.container-* > span:hover
    - li.container-* > ul
*/

li.container-high {
    background-color: #ffd5d1;
}

li.container-high > span {
    background-color: #ff8e83;
}

li.container-high > span:hover {
    background-color: #ffb2aa;
}

li.container-high > ul {
    background-color: #ffd5d1;
}


li.container-info {
    background-color: #b2e5e5
}

li.container-info > span {
    background-color: rgba(26,163, 163, 0.5);
}

li.container-info > span:hover {
    background-color: #86becb;
}

li.container-info > ul {
    background-color: #b2e5e5;
}


li.container-invalid {
    background-color: #e753e7
}

li.container-invalid > span {
    background-color: #e753e7;
}

li.container-invalid > span:hover {
    background-color: #e753e7;
}

li.container-invalid > ul {
    background-color: #e753e7;
}


li.container-low {
    background-color: #caedca;
}

li.container-low > span {
    background-color: #8fd98f;
}

li.container-low > span:hover {
    background-color: #ace3ac;
}

li.container-low > ul {
    background-color: #caedca;
}


li.container-moderate {
    background-color: #fde5c0;
}

li.container-moderate > span {
    background-color: #fbc674;
}

li.container-moderate > span:hover {
    background-color: #fcd69a;
}

li.container-moderate > ul {
    background-color: #fde5c0;
}


li.container-neutral {
    background-color: #f0f0f0;
}

li.container-neutral > span {
    background-color: #d0d0d0;
}

li.container-neutral > span:hover {
    background-color: #dfdfdf;
}

li.container-neutral > ul {
    background-color: #f0f0f0;
}

.analysis-empty {
    color: #6d6d6d;
    font-size: 14px;
    padding: 10px;
    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;
}

/*
   The following media queries targets a max-width of 600px
   simply to both meet reflow, but also make some adjustments for 
   smaller viewports that aren't as small as reflow, but can benfit
   from the revised styling.
*/

@media screen and (max-width: 600px) {

    /*
       Allow content that is allowed the bi-directional scrolling exception
       without making the entire page have bi-directional scrolling, which
       does not meet the intent of the rule.
    */

    .reflow-wrap {
        overflow: auto;
    }

    .reflow-wrap table {
        min-width: 600px;
    }

    .analysis-container .analysis-body .reflow-wrap table {
        min-width: 300px;
    }

    .spr-header, 
    .spr-content {
        margin: 0 1rem;
    }
}

/*
   This media query is specific to help meet the
   256px height requiremnt for Reflow, but this is
   more strictly scoped to the exact Reflow height
   requirement, so as to not unnecessarily make content 
   'too short' for small screens which still have larger
   height presentations.
*/

@media screen and (max-height: 256px) {
    .reflow-wrap {
        overflow: auto; /* repeated just incase the 600px width mq is not met */
        max-height: 245px;
    }
}
Pwindow.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="container-group-template" data-collapse>
            <li class="container-group container-info"
                role="treeitem"
                aria-expanded="false"
                data-if="($Scope.Children.length !== 0) || ($Scope.Entries.length !== 0)">

                <span>${$Scope.FriendlyName}</span>
                <ul role="group">
                    <li role="treeitem"
                        data-if="$Scope.Entries.length !== 0">
                         
                        <div class=reflow-wrap>
                            <table class="spr-table"
                                   aria-label="${$Scope.FriendlyName}"
                                   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>
                    </li>
                    <div data-foreach="$Scope.Children" data-apply-template="container-group-template"></div>
                </ul>
            </li>
        </div>
        <div data-define-template="blocker-container-group-template" data-collapse>
            <li class="container-group container-${ACTIVITY_LEVEL_NAMES[$Scope.ActivityLevel]}"
                role="treeitem"
                aria-expanded="false"
                id="offender-${$Scope.ScenarioId}-${$Scope.BlockerId}">
            
                <span>${$Scope.Name}</span>
                <ul role="group">
                    <li role="treeitem">
                        <div class=reflow-wrap>
                            <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>
                        <div data-if="typeof($Scope.BlockingTimeBuckets) !== 'undefined'">
                            <div class=reflow-wrap>
                                <table class="spr-table spr-table-defs">
                                    <thead>
                                        <th class="spr-label">BLOCKING TIME INTERVAL</th>
                                        <th class="spr-label">INSTANCE COUNT</th>
                                    </thead>
                                    <tbody>
                                        <tr class="row-info" data-foreach="$Scope.BlockingTimeBuckets">
                                            <td class="spr-label">${$Scope.BucketName}</td>
                                            <td class="spr-centered" data-bind="$Scope.Value"></td>
                                        </tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </li>
                    <div data-foreach="$Scope.Children" data-apply-template="blocker-container-group-template"></div>
                    <div data-scope="MetadataUtils.ParseMetadataTree($Scope)"
                         data-apply-template="container-group-template">
                    </div>
                </ul>
            </li>
        </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-descriptor="Session Id"
                 data-override-type="td">${$Scope.SessionId}</div>

            <!-- Entry Time -->
            <div class="spr-symbol"
                 data-descriptor="Session Enter Time"
                 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>
        <div data-define-template="session-entry-detailed-template" data-collapse>
            <!-- Session Duration -->
            <div class="spr-symbol spr-centered"
                 data-descriptor="Session Duration"
                 data-override-type="td">${Formatter.FormatDuration($Scope.Duration)}</div>

            <!-- Session Type -->
            <div class="spr-centered"
                 data-descriptor="Session Type"
                 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-descriptor="Discharge" data-override-type="td">${Formatter.FormatNumber($Scope.Discharge)} mWh</div>
                        <div class="spr-symbol spr-centered" data-descriptor="Discharge Percent" data-override-type="td">${Formatter.FormatNumber($Scope.DischargePercent)}% of battery</div>
                    </div>
                    <div data-else data-collapse>
                        <div class="spr-centered" data-descriptor="Discharge" data-override-type="td">-</div>
                        <div class="spr-centered" data-descriptor="Discharge Percent" 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-descriptor="Drain Rate" data-override-type="td">${Formatter.FormatNumber($Scope.DrainRate)} mW</div>
                    </div>
                    <div data-else data-collapse>
                        <div class="spr-centered" data-descriptor="Drain Rate" data-override-type="td">-</div>
                    </div>
                </div>
            </div>
            <div class="spr-centered" data-descriptor="Discharge State" 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-descriptor="Software DRIPS" 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-descriptor="HW DRIPS" data-override-type="td">-</div>
                        <div class="spr-centered" data-else data-descriptor="Hardware DRIPS" 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-descriptor="Software/Hardware DRIPS" data-override-type="td" colspan="2">-</div>
                </div>
            </div>
            <!-- Session Battery Capacity At Start -->
            <div class="spr-symbol spr-centered" data-descriptor="Battery Percentage" 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-descriptor="Blocker Name" data-override-type="td">${$Scope.Name}</div>
            <div data-descriptor="Blocker Type" data-override-type="td" class=spr-centered>${BLOCKER_TYPE_NAMES[$Scope.Type]}</div>
            <div data-descriptor="Blocker Active Time Percent" data-override-type="td" class="spr-symbol spr-centered">${$Scope.ActiveTimePercent}%</div>
            <div data-descriptor="Blocker Active Time" data-override-type="td" class=spr-centered>${Formatter.FormatDuration($Scope.ActiveTime)}</div>
        </div>

        <!-- Generic session templates-->
        <div data-define-template="session-generic-header-template">
            <div class=reflow-wrap>
                <table class="spr-table session-summary">
                    <colgroup>
                        <col style="width: 5em"/>
                        <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>SESSION ID</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" data-descriptor="Session Id">${$Scope.SessionId}</td>
                            <td class="spr-symbol" data-descriptor="Session Enter Time">
                                <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" data-descriptor="Session Duration">${Formatter.FormatDuration($Scope.Duration)}</td>
                            <td class="spr-centered" data-descriptor="Session Type">${SESSION_TYPE_NAMES[$Scope.Type]}</td>
                            <td class="spr-centered" data-descriptor="Session Enter Reason">${$Scope.EnterReason}</td>
                            <td class="spr-centered" data-descriptor="Session Exit Reason">${$Scope.ExitReason}</td>
                            <td class="spr-symbol spr-centered" data-descriptor="Session Battery Percent">${Formatter.FormatSessionEnterBatteryPercent($Scope)}</td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <div data-scope="MetadataUtils.ParseMetadataTree($Scope)"
                 data-if="$Scope.Children.length !== 0"
                 data-collapse>

                <h4 class="spr-h4" id="session_${$Scope.SessionId}_metadata_header">${$Scope.FriendlyName}</h4>
                <ul class="container-root"
                    role="tree"
                    aria-labelledby="session_${$Scope.SessionId}_metadata_header"
                    data-post-process="Collapser.InitializeCollapsedTree($Node)">
    
                    <div data-foreach="$Scope.Children" data-apply-template="container-group-template"></div>
                </ul>
            </div>
        </div>
        <div data-define-template="session-generic-srum-data-template" data-collapse>
            <h4 class="spr-h4" id="session_${$Scope.SessionId}_srum_header">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>
            <ul class="container-root"
                role="tree"
                aria-labelledby="session_${$Scope.SessionId}_srum_header"
                data-post-process="Collapser.InitializeCollapsedTree($Node)">
            
                <li class="container-group container-${$Scope.length == 0 ? 'neutral' : 'info'}"
                    role="treeitem"
                    aria-expanded="false"
                    data-scope="$Scope.SrumData.EnergyMeterData">
                
                    <span>Energy Meter</span>
                    <ul role="group">
                        <li role="treeitem"
                            data-if="$Scope.length === 0">
                        
                            <div class="analysis-empty">No energy meter data obtained.</div>
                        </li>
                        <li role="treeitem"
                            data-else>

                            <div class=reflow-wrap>
                                <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>
                        </li>
                    </ul>
                </li>
                <li class="container-group container-${$Scope.Values.length == 0 ? 'neutral' : 'info'}"
                    role="treeitem"
                    aria-expanded="false"
                    data-scope="$Scope.SrumData.PowerEstimationData">
                
                    <span>Power Estimation</span>
                    <ul role="group">
                        <li role="treeitem"
                            data-if="$Scope.Values.length === 0">
                        
                            <div class="analysis-empty">No power estimation data obtained.</div>
                        </li>
                        <li role="treeitem"
                            data-else>

                            <div class=reflow-wrap>
                                <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>NPU (mW)${$Scope.NpuEnergyMeasured ? '*' : ''}</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.NpuPowerConsumption}</td>
                                            <td class=spr-centered>${$Scope.LossPowerConsumption}</td>
                                            <td class=spr-centered>${$Scope.OtherPowerConsumption}</td>
                                        </tr>
                                    </tbody>
                                </table>
                            </div>
                        </li>
                    </ul>
                </li>
            </ul>
        </div>
        <div data-define-template="session-generic-template">
            <div data-scope="$Scope"
                 data-if="typeof($Scope.SrumData) !== '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>
                <div class=reflow-wrap>
                    <canvas width="864" 
                            height="300"
                            tabindex="0"
                            role="img"
                            aria-label="${HistogramUtils.GetHistogramText($Scope.ScreenBrightnessHistogram, 'ScreenBrightness')}"
                            data-histogram="$Scope.ScreenBrightnessHistogram">
                            Screen Brightness Duration Histogram Graph
                    </canvas>
                </div>
            </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>
                <div class=reflow-wrap>
                    <canvas width="864"
                            height="300"
                            tabindex="0"
                            role="img"
                            aria-label="${HistogramUtils.GetHistogramText($Scope.LuxHistogram, 'Lux')}"
                            data-histogram="$Scope.LuxHistogram">
                            Lux Duration Histogram Graph
                    </canvas>
                </div>
            </div>
            <div data-if="typeof($Scope.SearchIndexerData) !== 'undefined' && $Scope.SearchIndexerData.HasSearchIndexerData">
                <h4 class="spr-h4" id="session_${$Scope.SessionId}_si_header">Search Indexer Data</h4>
                <ul class="container-root"
                    role="tree"
                    aria-labelledby="session_${$Scope.SessionId}_si_header"
                    data-post-process="Collapser.InitializeCollapsedTree($Node)">
                
                    <li class="container-group container-info"
                        role="treeitem"
                        aria-expanded="false"
                        data-scope="$Scope.SearchIndexerData.Query"
                        data-if="$Scope.length !== 0">
                    
                        <span>Query Events</span>
                        <ul role="group">
                            <li role="treeitem">
                                <div class=reflow-wrap>
                                    <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" 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>
                            </li>
                        </ul>
                    </li>
                    <li class="container-group container-info"
                        role="treeitem"
                        aria-expanded="false"
                        data-scope="$Scope.SearchIndexerData.Flush"
                        data-if="$Scope.length !== 0">
                    
                        <span>Flush Events</span>
                        <ul role="group">
                            <li role="treeitem">
                                <div class=reflow-wrap>
                                    <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" 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>
                            </li>
                        </ul>
                    </li>
                    <li class="container-group container-info"
                        role="treeitem"
                        aria-expanded="false"
                        data-scope="$Scope.SearchIndexerData.Merge"
                        data-if="$Scope.length !== 0">
                    
                        <span>Merge Events</span>
                        <ul role="group">
                            <li role="treeitem">
                                <div class=reflow-wrap>
                                    <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" 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>
                            </li>
                        </ul>
                    </li>
                    <li class="container-group container-info"
                        role="treeitem"
                        aria-expanded="false"
                        data-scope="$Scope.SearchIndexerData.FileSysChange"
                        data-if="$Scope.length !== 0">
                    
                        <span>File System Change Events</span>
                        <ul role="group">
                            <li role="treeitem">
                                <div class=reflow-wrap>
                                    <table class="spr-table pdc-phases">
                                        <thead>
                                            <th>FAT Items Processed</th>
                                            <th>NTFS Items Processed</th>
                                        </thead>
                                        <tbody>
                                            <tr data-foreach="$Scope" class="row-info">
                                                <td class=spr-centered>${$Scope.TotalFATItemsProcessed}</td>
                                                <td class=spr-centered>${$Scope.TotalNTFSItemsProcessed}</td>
                                            </tr>
                                        </tbody>
                                    </table>
                                </div>
                            </li>
                        </ul>
                    </li>
                    <li class="container-group container-info"
                        role="treeitem"
                        aria-expanded="false"
                        data-scope="$Scope.SearchIndexerData.IndexingFile"
                        data-if="$Scope.length !== 0">
                    
                        <span>Indexing File Events</span>
                        <ul role="group">
                            <li role="treeitem">
                                <div class=reflow-wrap>
                                    <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" 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>
                            </li>
                        </ul>
                    </li>
                    <li class="container-group container-info"
                        role="treeitem"
                        aria-expanded="false"
                        data-scope="$Scope.SearchIndexerData.QueryResults"
                        data-if="$Scope.length !== 0">
                    
                        <span>Query Results Events</span>
                        <ul role="group">
                            <li role="treeitem">
                                <div class=reflow-wrap>
                                    <table class="spr-table pdc-phases">
                                        <thead>
                                            <th>Results Requested</th>
                                            <th>Results Returned</th>
                                        </thead>
                                        <tbody>
                                            <tr data-foreach="$Scope" class="row-info">
                                                <td class=spr-centered>${$Scope.TotalResultsRequested}</td>
                                                <td class=spr-centered>${$Scope.TotalResultsReturned}</td>
                                            </tr>
                                        </tbody>
                                    </table>
                                </div>
                            </li>
                        </ul>
                    </li>
                </ul>
            </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">
            <div class=reflow-wrap>
                <table class="spr-table session-summary">
                    <colgroup>
                        <col style="width: 5em" />
                        <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>SESSION ID</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" data-descriptor="Session Id">${$Scope.SessionId}</td>
                            <td class="spr-symbol" data-descriptor="Session Enter Time">
                                <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>
            <div data-scope="MetadataUtils.ParseMetadataTree($Scope)"
                 data-if="($Scope.Children.length !== 0) || (typeof($Scope.DripsWakeSources) !== 'undefined')"
                 data-collapse>

                <h4 class="spr-h4" id="session_${$Scope.SessionId}_metadata_header">${$Scope.FriendlyName}</h4>
                <ul class="container-root"
                    role="tree"
                    aria-labelledby="session_${$Scope.SessionId}_metadata_header"
                    data-post-process="Collapser.InitializeCollapsedTree($Node)">
    
                    <div data-foreach="$Scope.Children" data-apply-template="container-group-template"></div>
                    <div data-if="typeof($Scope.DripsWakeSources) !== 'undefined'" data-collapse>
                        <li class="container-group container-${$Scope.DripsWakeSources.length == 0 ? 'neutral' : 'info'}"
                            role="treeitem"
                            aria-expanded="false">
                        
                            <span>DRIPS Wake Sources</span>
                            <ul role="group">
                                <li role="treeitem" data-if="$Scope.DripsWakeSources.length == 0">
                                    <div class="analysis-empty">No DRIPS wake source information obtained.</div>
                                </li>
                                <li role="treeitem" data-else>
                                    <div class=reflow-wrap>
                                        <table 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>
                                </li>
                            </ul>
                        </li>
                    </div>
                </ul>
            </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>
                <div class="spr-h4">This session contains no detailed information about top offenders.</div>
            </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>
                    <div class=reflow-wrap>
                        <canvas width="864"
                                height="300"
                                tabindex="0"
                                role="img"
                                aria-label="${HistogramUtils.GetHistogramText($Scope.DripsHistogram, 'Drips')}"
                                data-histogram="$Scope.DripsHistogram"
                                data-histogram-range-max="100">
                                DRIPS Histogram Graph
                        </canvas>
                    </div>
                </div>
                <div data-if="$Scope.TopBlockers !== undefined"> 
                    <h4 class="spr-h4">Top Offenders</h4>
                    <div class="spr-explanation">Top 5 Offenders, ranked by active time</div>
                    <div class=reflow-wrap>
                        <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>
                </div>
                <div>
                    <h4 class="spr-h4" id="session_${$Scope.SessionId}_blockers_header">Session Blockers</h4>
                    <ul class="container-root"
                        role="tree"
                        aria-labelledby="session_${$Scope.SessionId}_blockers_header"
                        data-post-process="Collapser.InitializeCollapsedTree($Node)">
                    
                        <li class="container-group container-${Utils.GetBlockerGroupActivityLevel($Scope)}"
                            role="treeitem"
                            aria-expanded="false"
                            data-foreach="$Scope.BlockerGroups">
                        
                            <span>${$Scope.Name}</span>
                            <ul role="group">
                                <li role="treeitem" data-if="$Scope.Blockers.length == 0">
                                    <div class="analysis-empty">No ${$Scope.Name} activity reported</div>
                                </li>
                                <div data-foreach="$Scope.Blockers" data-apply-template="blocker-container-group-template"></div>
                                <div data-scope="MetadataUtils.ParseMetadataTree($Scope)"
                                     data-apply-template="container-group-template">
                                </div>
                            </ul>
                        </li>
                    </ul>
                </div>
                <div data-apply-template="session-generic-template"></div>
            </div>
        </div>
    </div>

    <div class=reflow-wrap>
        <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">OS VERSION</td>
    			<td class="spr-blank"> </td>
                <td>${$Scope.SystemInformation.OSVer}</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.ScanTimeLocal)}</span>
                    <span>${Utils.ParseTimeFromDateTime($Scope.ScanTimeLocal)}</span>
                </td>
            </tr>
        </table>
    </div>
    <div>
        <h2 class="spr-h2">System Power State Transitions</h2>
        <div class="spr-explanation">Battery drain over the last ${$Scope.ReportInformation.ReportDuration} days</div>
        <div class=reflow-wrap>
            <canvas width="864"
                    height="400"
                    tabindex="0"
                    role="img"
                    aria-label="Battery Drain Table"
                    data-post-process="Timegraph.Draw($Scope, $Node)">
                    Battery Drain Table
            </canvas>
        </div>
        <div class=reflow-wrap>
            <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>
    <div>
        <h2 class="spr-h2">Filter Option</h2>
        <div data-override-type="form">
            <div>
                <div class="spr-h4">Session Length:</div>
                <input type="radio" name="session_length_filter" id="is_all_time" value="AllTime" onchange="SummaryTableFilterer.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="SummaryTableFilterer.OnDurationValueChanged(this)"><label for="is_10_session">&gt;10 Minutes</label>
            </div>
        </div>
        <div data-override-type="form">
            <div>
                <div class="spr-h4">States:</div>
                <input type="radio" name="session_type_filter" id="is_all_session" value="All" onchange="SummaryTableFilterer.OnStateValueChanged(this)" checked=""/><label for="is_all_session">All</label>
                <input type="radio" name="session_type_filter" id="is_active_session" value="Active" onchange="SummaryTableFilterer.OnStateValueChanged(this)"/><label for="is_active_session">Active</label>
                <input type="radio" name="session_type_filter" id="is_screenoff_session" value="ScreenOff" onchange="SummaryTableFilterer.OnStateValueChanged(this)"/><label for="is_screenoff_session">Screen Off </label>
                <input type="radio" name="session_type_filter" id="is_sleep_session" value="Standby" onchange="SummaryTableFilterer.OnStateValueChanged(this)"/><label for="is_sleep_session">Sleep</label>
                <input type="radio" name="session_type_filter" id="is_hib_session" value="Hibernate" onchange="SummaryTableFilterer.OnStateValueChanged(this)"/><label for="is_hib_session">Hibernate</label>
                <input type="radio" name="session_type_filter" id="is_shutdown_session" value="Shutdown" onchange="SummaryTableFilterer.OnStateValueChanged(this)"/><label for="is_shutdown_session">Shutdown</label>
                <input type="radio" name="session_type_filter" id="is_bug_session" value="BugCheck" onchange="SummaryTableFilterer.OnStateValueChanged(this)"/><label for="is_bug_session">Bug Check</label> 
            </div>
        </div>
        <div class=reflow-wrap>
            <table class="spr-table" id="summary-table" aria-label="Session Summary Table">
                <colgroup>
                    <col style="width: 5em"/>
                    <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>SESSION ID</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>
    </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">
        <div class="scroll-top-button" onclick="Utils.ScrollToTop()" role="button" name="top">Top</div>
        <h3 class="spr-h3"
            id="session-${$Scope.SessionId}"
            aria-label="Session ${$Scope.SessionId}: ${SESSION_TYPE_NAMES[$Scope.Type]}">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>
            <div class=reflow-wrap>
                <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>
</div>
PAD"use strict";

const KEYCODE_ENTER = 13;
const KEYCODE_ARROW_LEFT = 37;
const KEYCODE_ARROW_UP = 38;
const KEYCODE_ARROW_RIGHT = 39;
const KEYCODE_ARROW_DOWN = 40;

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',
    'invalid',
    'invalid'
];

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.AusterityMode': {
        Name: 'Processes Disabled in Standby'
    },
    'Info.DirectedDripsTransitionCount': {
        Name: 'Directed DRIPS Transition Count'
    },
    'Info.EnterReason': {
        Name: 'Enter Reason'
    },
    'Info.ExitReason': {
        Name: 'Exit Reason'
    },
    'Info.HwLowPowerStateTime': {
        Visible: false
    },
    'Info.InputSuppressionActionCount': {
        Name: 'Input Suppression Action Count'
    },
    'Info.PowerButtonSuppressionActionCount': {
        Name: 'Power Button Suppression Action Count'
    },
    'Info.SwLowPowerStateTime': {
        Visible: false
    },
    'Info.SystemGpuAdapterCount': {
        Name: 'System GPU Adapter Count'
    },
    'Info.TimerRebasePercent': {
        Name: 'DRIPS Timer Rebasing Percentage'
    },
    'Info.TotalNqmEngagedCount': {
        Visible: false
    },
    'Info.TotalNqmEngagedTime': {
        Visible: false
    },
    'Info.TotalWcmEngagedTime': {
        Visible: false
    },
    'Info.TotalWcmEngagedCount': {
        Visible: false
    },

    '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]'
    },
    'Battery.EntryChargeLimitingMode': {
        Name: 'Charge Limiting Mode Enabled At Entry'
    },
    'Battery.EntryChargingStatePowerSupplyPresent': {
        Name: 'Charging State Power Supply Present At Entry'
    },
    'Battery.EntryChargingStateAdequate': {
        Name: 'Charging State Adequate At Entry'
    },
    'Battery.EntryTripPointSupported': {
        Name: 'Trip Point Supported At Entry'
    },
    'Battery.ExitChargeLimitingMode': {
        Name: 'Charge Limiting Mode Enabled At Exit'
    },
    'Battery.ExitChargingStatePowerSupplyPresent': {
        Name: 'Charging State Power Supply Present At Exit'
    },
    'Battery.ExitChargingStateAdequate': {
        Name: 'Charging State Adequate At Exit'
    },
    'Battery.ExitTripPointSupported': {
        Name: 'Trip Point Supported At Exit'
    },

    'Settings.BIRequestActive': {
        Name: 'BI Request Active'
    },
    'Settings.ConnectedStandby': {
        Name: 'Networking In Standby'
    },
    'Settings.EnergySaverInStandby': {
        Name: 'Energy Saver In Standby'
    },
    'Settings.IdleWakeSkipPolicy': {
        Visible: false
    },
    '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.RemainingSleepTimeoutInSeconds': {
        Name: 'Remaining Sleep Timeout (s)'
    },
    'Settings.IdleTimeoutSource': {
        Name: 'Remaining Sleep Timeout Source'
    },
    'Settings.RemoteDesktopEnabled': {
        Name: 'Remote Desktop Enabled'
    },
    'Settings.StandbyTimeoutInSeconds': {
        Name: 'Standby Idle Timeout (s)'
    },
    'Settings.UserConnectivityPolicy': {
        Name: 'User Connectivity Setting'
    },
    'Settings.VideoTimeoutInSeconds': {
        Name: 'Video Idle Timeout (s)'
    },

    'Settings.Hibernate.HibernateTimeoutInSeconds': {
        Name: 'Hibernate Timeout [s]'
    },
    'Settings.Hibernate.IsHibernateEnabled': {
        Name: 'Hibernate Enabled'
    },
    'Settings.Hibernate.ReserveRejectReason': {
        Name: 'Reserve Action Reject Reason'
    },
    'Settings.Hibernate.RSBudgetPercentage': {
        Name: 'RS Budget [percentage of battery]'
    },
    'Settings.Hibernate.RSBudgetRefreshCount': {
        Name: 'RS Budget Refresh Count'
    },
    'Settings.Hibernate.RSBudgetRefreshInterval': {
        Name: 'RS Budget Refresh Interval [s]'
    },
    'Settings.Hibernate.RSBudgetRejectReason': {
        Name: 'RS Action Reject Reason'
    },
    'Settings.Hibernate.RSBatteryPercentageOnEnter': {
        Name: 'RS Battery Percentage On Enter'
    },
    'Settings.Hibernate.StandbyBudgetPercentage': {
        Name: 'Hibernate Budget [percentage of battery]'
    },
    'Settings.Hibernate.StandbyBudgetRefreshCount': {
        Name: 'Hibernate Budget Refresh Count'
    },
    'Settings.Hibernate.StandbyBudgetRefreshInterval': {
        Name: 'Hibernate Budget Refresh Interval [s]'
    },
    'Settings.Hibernate.StandbyBudgetRejectReason': {
        Name: 'Hibernate Budget Action Reject Reason'
    },
    'Settings.Hibernate.StandbyBatteryPercentageOnEnter': {
        Name: 'Hibernate Battery Percentage On Enter'
    },
    'Settings.TimerRebaseThresholdInSeconds': {
        Visible: false
    },

    '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
        };
        var ShowBatteryDrainInfo = [
            0,      // Active
            1,      // ScreenOff
            2       // ModernSleep
        ];

        if ((ShowBatteryDrainInfo.includes(Session.Type)) &&
            (!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;
    },
    InnerText: function (Element) {
        return Element.textContent.trim().replaceAll(/\s+/g, ' ');
    },
    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 ((Utils.IsNumber(Session.EntryRemainingCapacity)) &&
            (Utils.IsNumber(Session.EntryFullChargeCapacity) &&
            (Session.EntryFullChargeCapacity != 0))) {

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

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

var TreeItem = function (Navigator, TreeItemNode, ParentTreeItem) {
    this.Navigator = Navigator;
    this.TreeItemNode = TreeItemNode;
    this.ParentTreeItem = ParentTreeItem;
    this.IsCollapsed = true;
    this.IsExpandable = TreeItemNode.getElementsByTagName('ul').length !== 0;
    this.IsVisible = false;

    TreeItemNode.setAttribute('tabindex', '-1');
    TreeItemNode.addEventListener('click', this.HandleClick.bind(this));
    TreeItemNode.addEventListener('keydown', this.HandleKeyDown.bind(this));
};

TreeItem.prototype.HandleClick = function (Event) {
    if (this.IsExpandable !== false) {
        if (this.IsCollapsed === false) {
            this.Navigator.CollapseTreeItem(this);

        } else {
            this.Navigator.ExpandTreeItem(this);
        }
    }
    
    Event.stopPropagation();
    return;
};

TreeItem.prototype.HandleKeyDown = function (Event) {
    if (Event.altKey || Event.ctrlKey || Event.metaKey || Event.shift) {
        return;
    }

    var HandledEvent = false;
    switch (Event.keyCode) {
        case KEYCODE_ENTER:
            Event.currentTarget.dispatchEvent(new MouseEvent('click', {
                'view': window,
                'bubbles': true,
                'cancelable': true
            }));
            
            HandledEvent = true;
            break;
        
        case KEYCODE_ARROW_UP:
            this.Navigator.MoveFocusToPreviousItem(this);
            HandledEvent = true;
            break;
        
        case KEYCODE_ARROW_DOWN:
            this.Navigator.MoveFocusToNextItem(this);
            HandledEvent = true;
            break;
        
        case KEYCODE_ARROW_RIGHT:
            if (this.IsExpandable) {
                if (this.IsCollapsed) {
                    this.Navigator.ExpandTreeItem(this);

                } else {
                    this.Navigator.MoveFocusToNextItem(this);
                }
            }

            HandledEvent = true;
            break;
        
        case KEYCODE_ARROW_LEFT:
            if (this.IsExpandable && !this.IsCollapsed) {
                this.Navigator.CollapseTreeItem(this);
                
            } else if (this.ParentTreeItem) {
                this.Navigator.MoveFocusToParentItem(this);
            }

            HandledEvent = true;
            break;
    }

    if (HandledEvent !== false) {
        Event.stopPropagation();
        Event.preventDefault();
    }
};

var TreeNavigator = function (RootTreeNode) {
    this.RootTreeNode = RootTreeNode;
    this.TreeItems = [];
};

TreeNavigator.prototype.Initialize = function () {
    var FindTreeItems = function (Navigator, TreeNode, ParentTreeItem) {
        var ChildElement = TreeNode.firstElementChild;
        var PreviousTreeItem = ParentTreeItem;
        while (ChildElement) {
            if (ChildElement.tagName.toLowerCase() === 'li') {
                var ChildTreeItem = new TreeItem(Navigator, ChildElement, ParentTreeItem);
                Navigator.TreeItems.push(ChildTreeItem);
                PreviousTreeItem = ChildTreeItem;
            }

            if (ChildElement.firstElementChild) {
                FindTreeItems(Navigator, ChildElement, PreviousTreeItem);
            }

            ChildElement = ChildElement.nextElementSibling;
        }
    };
    
    FindTreeItems(this, this.RootTreeNode, undefined);
    if (this.TreeItems.length !== 0) {
        this.TreeItems[0].TreeItemNode.setAttribute('tabindex', '0');
    }

    this.UpdateVisibleTreeItems();
};

TreeNavigator.prototype.CollapseTreeItem = function (TreeItem) {
    TreeItem.TreeItemNode.setAttribute('aria-expanded', 'false');
    TreeItem.IsCollapsed = true;
    this.UpdateVisibleTreeItems();
};

TreeNavigator.prototype.ExpandTreeItem = function (TreeItem) {
    TreeItem.TreeItemNode.setAttribute('aria-expanded', 'true');
    TreeItem.IsCollapsed = false;
    this.UpdateVisibleTreeItems();
};

TreeNavigator.prototype.MoveFocusToNextItem = function (CurrentTreeItem) {
    var NextItem = undefined;
    for (var Index = this.TreeItems.length - 1; Index >= 0; Index -= 1) {
        var TreeItem = this.TreeItems[Index];
        if (TreeItem == CurrentTreeItem) {
            break;
        }

        if (TreeItem.IsVisible) {
            NextItem = TreeItem;
        }
    }

    if (NextItem) {
        this.SetFocusedItem(NextItem);
    }
};

TreeNavigator.prototype.MoveFocusToParentItem = function (TreeItem) {
    this.SetFocusedItem(TreeItem.ParentTreeItem);
};

TreeNavigator.prototype.MoveFocusToPreviousItem = function (CurrentTreeItem) {
    var PreviousItem = undefined;
    for (var Index = 0; Index < this.TreeItems.length; Index += 1) {
        var TreeItem = this.TreeItems[Index];
        if (TreeItem == CurrentTreeItem) {
            break;
        }

        if (TreeItem.IsVisible) {
            PreviousItem = TreeItem;
        }
    }

    if (PreviousItem) {
        this.SetFocusedItem(PreviousItem);
    }
};

TreeNavigator.prototype.SetFocusedItem = function (FocusedTreeItem) {
    for (var Index = 0; Index < this.TreeItems.length; Index += 1) {
        var TreeItem = this.TreeItems[Index];
        if (TreeItem == FocusedTreeItem) {
            TreeItem.TreeItemNode.setAttribute('tabIndex', '0');
            TreeItem.TreeItemNode.focus();

        } else {
            TreeItem.TreeItemNode.setAttribute('tabIndex', '-1');
        }
    }
};

TreeNavigator.prototype.UpdateVisibleTreeItems = function () {
    for (var Index = 0; Index < this.TreeItems.length; Index += 1) {
        var TreeItem = this.TreeItems[Index];
        var ParentNode = TreeItem.TreeItemNode.parentNode;
        TreeItem.IsVisible = true;
        while (ParentNode !== this.RootTreeNode) {
            if (ParentNode.getAttribute('aria-expanded') == 'false') {
                TreeItem.IsVisible = false;
                break;
            }

            ParentNode = ParentNode.parentNode;
        }
    }
};

var Collapser = {
    InitializeCollapsedTree: function (RootTreeNode) {
        new TreeNavigator(RootTreeNode).Initialize();
    }
}

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 HistogramTextValues = {
    'ScreenBrightness' : {
        Base:   'Screen Brightness Duration Histogram.',
        Begin:  ' For brightness ',
        Middle: ' duration was in the ',
        End:    ' seconds range.'
    },
    'Drips' : {
        Base:   'Drips Histogram.',
        Begin:  ' ',
        Middle: ' percent of Drips time spent in timer interval of ',
        End:    '.'
    },
    'Lux' : {
        Base:   'Lux Duration Histogram.',
        Begin:  ' For lux level ',
        Middle: ' duration was in the ',
        End:    ' seconds range.'
    }
}

var HistogramUtils = {
    GetHistogramText: function (HistogramData, HistogramLabel) {
        var TextValues = HistogramTextValues[HistogramLabel];
        var Text = TextValues.Base;

        for (var Entry of HistogramData) {
            var BucketName = Entry.BucketName;
            var Value = Entry.Value;
            if(Value != 0){
                Text += TextValues.Begin + Value.toString() + TextValues.Middle + BucketName + TextValues.End;
            }
        }
        return Text;
    }
};

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 (SessionData) {
        var Metadata = SessionData.Metadata;
        var ContainerNodesMap = {};
        var EntryAttributes = {};
        var RootContainer = {
            Entries: [],
            Children: [],
            FriendlyName: Metadata.FriendlyName,
            SessionId: SessionData.SessionId,
            DripsWakeSources: SessionData.DripsWakeSources
        };

        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,
    PostProcessSessionRow: function(Node, Scope) {
        Node.RowScope = {
            Duration: Scope.Duration,
            Type: Scope.Type
        };
        
        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 SummaryTableFilterer = {
    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;
    },
};

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;
        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) {
        var RowNodeElements = RowNode.querySelectorAll('td');
        var NavigatorText = '';
        for (var Element of RowNodeElements) {
            if (Element.childNodes.length == 0) {
                continue;
            }

            var LinkElement = this.Document.createElement('a');
            LinkElement.setAttribute('href', Link);
            LinkElement.setAttribute('class', 'row-link');
            LinkElement.setAttribute('tabindex', '-1');

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

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

            Element.appendChild(LinkElement);

            var ElementText = Utils.InnerText(Element);
            if (Element.hasAttribute('data-descriptor')) {
                ElementText = Element.getAttribute('data-descriptor') + ': ' + ElementText;
            }

            if (NavigatorText !== '') {
                NavigatorText += ', ';
            }

            NavigatorText += ElementText;
        }

        //
        // Set the first link element to be navigatable by keyboard and contain
        // a description for the whole session row.
        //

        if (NavigatorText !== '') {
            var FirstLink = RowNodeElements[0].children[0];
            FirstLink.setAttribute('tabindex', '0');
            FirstLink.setAttribute('aria-label', NavigatorText);
        }
    },
    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);
        }

        //
        // Cleanup any references to globals that are no longer needed.
        //

        HistogramBuilder = undefined;
        MetadataUtils = undefined;
        SrumTableBuilder = undefined;
        SummaryTableBuilder = undefined;
        Timegraph = undefined;
        DOMBuilder = undefined;
    },
    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-')) {
                    if (SourceAttribute.name !== 'data-descriptor') {
                        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 (SourceNode.hasAttribute('data-tabindex')) {
                DestinationChildNode.setAttribute(
                    'tabindex',
                    SourceNode.getAttribute('data-tabindex'));
            }

            //
            // 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>
          <th>
            START TIME
          </th>
          <th class="centered">
            STATE
          </th>
          <th class="centered">
            SOURCE
          </th>
          <th colspan="2"  class="centered">
            CAPACITY REMAINING
          </th>
        </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>
          <th>
            START TIME
          </th>
          <th class="centered">
            STATE
          </th>
          <th class="centered">
            DURATION
          </th>
          <th class="centered" colspan="2">
            ENERGY DRAINED
          </th>
        </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>Rapport fra strømsparingsdiagnose</h2>
       <table>
           <tr>
               <td class="detail-name">Datamaskinnavn</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">Skanningstidspunkt</td>
               <td>
                   <xsl:value-of select="eew:ReportInformation/eew:ScanTime"/>
               </td>
           </tr>
           <tr>
               <td class="detail-name">Skanningsvarighet</td>
               <td>
                   <xsl:value-of select="substring-before(substring-after(eew:ReportInformation/eew:ScanDuration, 'PT'), 'S')"/> sekunder
               </td>
           </tr>
           <tr>
               <td class="detail-name">Systemprodusent</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">Produktnavn for system</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-dato</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-versjon</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">Operativsystembygg</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">Plattformrolle</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">Går på strøm</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">Antall prosesser</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">Trådteller</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">Rapport-GUID</td>
               <td>
                   {<xsl:value-of select="eew:ReportInformation/eew:ReportGuid"/>}
               </td>
           </tr>
       </table>
       <h3>Analyseresultater</h3>
       <xsl:if test="eew:ReportInformation/eew:DroppedEvents &gt; 0 or eew:ReportInformation/eew:DroppedBuffers &gt; 0">
            Advarsel: Hendelser ble fjernet under sporing. Det kan gi ufullstendige analyseresultater.
       </xsl:if>
       <!-- select all error log entries, then warning, then informational. -->
       <h4>Feil</h4>
       <xsl:apply-templates select="eew:Troubleshooter[@guid!='c78b52e3-9cd7-4802-979c-57ca1283dafa']/eew:AnalysisLog/eew:LogEntry[eew:Severity='Error']"/>
       <h4>Advarsler</h4>
       <xsl:apply-templates select="eew:Troubleshooter[@guid!='c78b52e3-9cd7-4802-979c-57ca1283dafa']/eew:AnalysisLog/eew:LogEntry[eew:Severity='Warning']"/>
       <h4>Informasjon</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">
                        Strømsparing
                    </xsl:when>
                    <xsl:when test="eew:Value=1">
                        Høy ytelse
                    </xsl:when>
                    <xsl:when test="eew:Value=2">
                        Balansert
                    </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">
                    Navn på plan
                </span>
            </td>
            <td>
                <xsl:choose>
                    <xsl:when test="eew:Value='{a1841308-3541-4fab-bc81-f71556f20b4a}'">
                        OEM Strømsparing
                    </xsl:when>
                    <xsl:when test="eew:Value='{8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c}'">
                        OEM Høy ytelse
                    </xsl:when>
                    <xsl:when test="eew:Value='{381b4222-f694-41f0-9685-ff5bb260df2e}'">
                        OEM Balansert
                    </xsl:when>
                    <xsl:otherwise>
                        Egendefinert
                    </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">
                        Optimaliser for videokvalitet
                    </xsl:when>
                    <xsl:when test="eew:Value=1">
                        Balanser videokvalitet og strømsparing
                    </xsl:when>
                    <xsl:when test="eew:Value=2">
                        Optimaliser for strømsparing
                    </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">
                    Modul
                </span>
            </td>
            <td> 
                <span class="detail-name">
                    Gjennomsnittlig volumutnyttelse (%)
                </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'">
                        Oppringingsmodulstakk
                    </xsl:if>
                </span>
            </td>
            <td> 
                <xsl:if test="eew:Value=''">
                    Ukjent modul
                </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>
<?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 == 17) {     // SpmScenarioStopReasonUnspecified
            str = str + ' (unspecified sleep reason)';
        } else if (_scenarioStopReason == 18) {     // SpmScenarioStopReasonCsExit
            str = str;      // nop
        } else if (_scenarioStopReason == 19) {     // SpmScenarioStopReasonInternalSegmentTransition
            str = str;      // nop
        } else {
            str = str + ' (unrecognized sleep reason ' + _scenarioStopReason + ')';
        }

        return str;
    }
    ]]>
  </ms:script>
</xsl:stylesheet>
PADPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDING

Anon7 - 2021