﻿
# **********************************************************
#                     Script parameters
# **********************************************************
Param( 
    [parameter(Mandatory=$true)][int]$Iterations,
    [parameter(Mandatory=$true)][int32]$AnalysisOption,
    [parameter(Mandatory=$false)][switch]$LaunchAppOnly
)

# This try/finally block wraps the whole script so we can always properly dispose of objects.
#
try {

    # Set to true if you need to hang the script at the end to check console output
    $Global:debugFlag = $false
    
    [void] [System.Reflection.Assembly]::LoadWithPartialName("'System.Windows.Forms")

    # **********************************************************
    #                     Definitions
    # **********************************************************
    
    
    # Need to know where our script is so we can use full path to all our dependent files.
    $InvocationPath = Split-Path -Path $MyInvocation.MyCommand.Path -Parent
    $ResourcesPath = Join-Path -Path $InvocationPath resources
    $ScriptsPath = Join-Path -path $InvocationPath scripts
    $FileSetPath = Join-Path -path $InvocationPath content
    $AxeUniversalPath = Convert-Path((Get-Item env:\AssessmentAxeUniversalPath).value)
    $ConfigFile = "$FileSetPath\office_config.csv"
    $OfficeRegionsFile = "$ResourcesPath\office.regions.xml"
    
    
    # load shared definitions
    Import-Module $ScriptsPath\AxePSHelper.psm1 -WarningAction SilentlyContinue
    Import-Module $ScriptsPath\OfficePerfPSModule.psm1 -WarningAction SilentlyContinue
        
    Set-Variable REBOOT_DELAY_SECONDS -option Constant -value 180
    Set-Variable WPRP_FILE -option Constant -value 'office.wprp'
    Set-Variable PROFILE_FILE -option Constant -value 'office.wpaProfile'
    
    Add-Type @"
    
      using System;
      using System.Runtime.InteropServices;
    
      public class WindowHandler 
      {
         [DllImport("user32.dll")]
         [return: MarshalAs(UnmanagedType.Bool)]
         public static extern bool SetForegroundWindow(IntPtr hWnd);
      }
"@
    
    
    #framework files
    $XMLResultsFile = "$AXEResultsPath\results.xml"
    $RebootTempFile = "$AXETempPath\reboot.txt"
    
    $apponly = $false
    if ($LaunchAppOnly)
    {
       $apponly = $true
    }

    # Import the modules and functions    
    try {
        Import-Module "$AxeUniversalPath\UniversalAssessment.psm1" -ErrorAction Stop
    }
    catch {
        throw "Failed to import $AxeUniversalPath\UniversalAssessment.psm1"
    }
    
    #Initialize universal execution framework
    Initialize-UniversalFramework -InvocationPath $InvocationPath -AxeUniversalPath $AxeUniversalPath

    "Init done..." | Log-Info

    function WaitUIReady {
    param (
        [parameter(Mandatory=$true)][string]$Process,
        [parameter(Mandatory=$true)][string]$WindowTitle
    )

        "Trying to find process/window combination ($Process / $WindowTitle)..." | Out-AxeInfo
        Start-Sleep -Milliseconds 100
        while (-not ((Get-Process -Name $Process).MainWindowTitle -match "$WindowTitle")){
            Start-Sleep -Milliseconds 50
        }

        "Found process/window combination ($Process / $WindowTitle)" | Out-AxeInfo
    }


    function TerminateProcessGracefully {
    param (
        [parameter(Mandatory=$true)][string]$Process,
        [parameter(Mandatory=$false)][string]$WindowTitle
    )

        Start-Sleep -Seconds 5

        "Bring window to foreground ($Process/$WindowTitle)..." | Out-AxeInfo

        try {

            [void] [System.Reflection.Assembly]::LoadWithPartialName("'System.Windows.Forms")

            if ($WindowTitle)
            {
                $proc = (Get-Process -Name $Process) | where {$_.MainWindowTitle -match "$WindowTitle"}
            }
            else
            {
                $proc = (Get-Process -Name $Process)
            }

            if ($proc) {

                if (($proc.MainWindowHandle -ne $null) -and ($proc.MainWindowHandle -ne 0)) {
                    [void] [WindowHandler]::SetForegroundWindow($proc.MainWindowHandle)
                }
                else {
                    "Window handle is null. Skipped set focus command." | Out-AxeInfo
                }

                Start-Sleep -Seconds 2

                "Send Alt-F4 to window and wait 5 seconds for graceful exit..." | Out-AxeInfo

                [System.Windows.Forms.SendKeys]::SendWait("%{F4}")
                Start-Sleep -Seconds 5
            }
            else {
                "Cannot find process/window combination..." | Out-AxeInfo
                "Assuming app has focus and sending Alt-F4 anyways..." | Out-AxeInfo

                [System.Windows.Forms.SendKeys]::SendWait("%{F4}")
                Start-Sleep -Seconds 5
            }
        }
        catch {}

        $screenCapturePathBase = "ProcTermination"
        Get-ScreenCapture (Get-Item env:\AssessmentResultsPath).value $screenCapturePathBase

        if (Get-Process -Name $Process -ErrorAction SilentlyContinue) { 
            "Process was not terminated by Alt+F4 keystroke. Killing process." | Out-AxeInfo
            Stop-Process -Name $Process -ErrorAction SilentlyContinue
            Start-Sleep -Seconds 5
        } 
        else { 
            "Process was correctly terminated by Alt+F4 keystroke" | Out-AxeInfo
        }
    }


    function PerformAppLaunch {
    param (
        [parameter(Mandatory=$true)][boolean]$trace,
        [parameter(Mandatory=$false)][boolean]$analysis,
        [parameter(Mandatory=$true)][System.Object]$file,
        [parameter(Mandatory=$false)][int32]$iteration,
        [parameter(Mandatory=$false)][boolean]$apponly
    )

        $p = $FileSetPath + "\" + $file.file
        $p | Out-AxeInfo

        try {
            (ls $p).LastWriteTime = Get-Date 
        }
        catch {
            "Unable to update timestamp" | Out-AxeInfo
        }

        if ($trace) {
            if ($analysis) {
                #start tracing
                "Start tracing with profile: `"OfficeUX_Analysis`"..." | Log-Info
                $profile = "OfficeUX_Analysis"
                Start-ETWTracingFromManifest -Profile $profile -Description "Analysis ETL"
            }
            else {
                #start tracing
                "Start tracing with profile: `"OfficeUX_Timing`"..." | Log-Info
                $profile = "OfficeUX_Timing"
                Start-ETWTracingFromManifest -Profile $profile -Description "Timing ETL"
            }
            Start-Sleep -Seconds 10
        }

        Trace-AxeOperationStart -OpCode 200 -Payload $file.name

        if ($apponly)
        {
            $proc = Start-Process $file.procName
            Start-Sleep -Seconds 30
        }
        else
        {
            if (Test-Path -Path $p) {
                $proc = Start-Process -FilePath "$p" -PassThru
            }
            else {
                    "File not found!" | Out-AxeInfo
            }

            WaitUIReady -Process $file.procName -WindowTitle $file.wndName
        }

        Trace-AxeOperationStop -OpCode 200 -Payload $file.name

        if ($file.custom_keysend -and (-not $apponly)) {
            Start-Sleep -Seconds 10
            [System.Windows.Forms.SendKeys]::SendWait($file.custom_keysend)
            Start-Sleep -Seconds 10
            [System.Windows.Forms.SendKeys]::SendWait("{ESC}")
        }
            
        if ($trace) { 

            "Wait 5 seconds" | Out-AxeInfo
            Start-Sleep -Seconds 5

            if ($analysis) {
                $ETLFile = "$AXEResultsPath\Analysis_$($file.name).etl"
            }
            else {
                $ETLFile = "$AXEResultsPath\Timing_$($file.name)_$iteration.etl"
            }

            Stop-ETWTracingFromManifest -TraceFullName $ETLFile
            
            #double check if the ETL is on disk
            if(-not(test-path $ETLFile))
            {
                throw ("Error saving ETW `"$ETLFile`" ")
            }
        }

        if ($apponly)
        {
            TerminateProcessGracefully -Process $file.procName
        }
        else
        {
            TerminateProcessGracefully -Process $file.procName -WindowTitle $file.wndName
        }
    }


    #*****************************************************************
    #
    #                PREP LOGIC
    #
    #*****************************************************************

    # parameters processing

    if (-not (Test-Path $FileSetPath)) {
         throw [System.IO.FileNotFoundException] "$FileSetPath not found."
    }
    
    if (-not (Test-Path $ConfigFile)) {
        throw [System.IO.FileNotFoundException] "$ConfigFile not found."
    } else {
        $FilesList = Import-Csv -Path "$ConfigFile"
    }

    if (($Iterations -lt 1) -or ($Iterations -gt 10)) {
        throw "Invalid value (@$Iterations) for parameter 'Iterations'. Range: [1..10]"
    }

    # if AnalysisOnly is selected, then then iterations parameter is set to 0 (refers to Timing runs)
    if ($AnalysisOption -eq 3) {
        $Iterations = 0
    }

    # iteration 0 is the "training" run. we skip it if EmptyStandbyList is selected
    $FirstIteration = 0

    "Cancel tracing, just in case some sessions are already running..." | Log-Info
    Cancel-ETWTracing

    #*****************************************************************
    #
    #                TEST LOGIC
    #
    #*****************************************************************

    "Number of files to open: $(([array]$FilesList).count)" | Out-AxeInfo
    "Number of iterations to perform: $($Iterations)" | Out-AxeInfo

    for ($i=$FirstIteration; $i -le ($Iterations + 1); $i++)  {

        $FileCount = 0
        "Iteration $i" | Out-AxeInfo

        foreach ($file in $FilesList) {

            $FileCount += 1 
             "File #$FileCount : $($file.name)" | Out-AxeInfo

            if ($i -eq 0) { # training
               PerformAppLaunch -trace $false -file $file -apponly $apponly
            }
            else {
               if ($i -eq ($Iterations + 1)) { # analysis
                   if ($AnalysisOption -eq 2) { # skip analysis if not selected
                       continue
                   }
                   PerformAppLaunch -trace $true -analysis $true -file $file -apponly $apponly
               }
               else { # timing
                   PerformAppLaunch -trace $true -analysis $false -file $file -iteration $i -apponly $apponly
               }
            }
        }
    }
    
    # Copy the config and regions file for use by results
    Copy-Item -Path $ConfigFile -Destination $AXEResultsPath -Force -ErrorAction Ignore
    Copy-Item -Path $OfficeRegionsFile -Destination $AXEResultsPath -Force -ErrorAction Ignore

    #*****************************************************************
    #
    #                Cleanup
    #
    #*****************************************************************

}
catch
{
    Handle-UniversalFrameworkException -Exception $_
}
finally {

    # Cancel any ETL tracing that might be going on
    #   
    Cancel-ETWTracing

    # We should always properly dispose of this guy.
    #
    "Cleanup..." | Log-Info
    Cleanup-UniversalFramework
}
# SIG # Begin signature block
# MIIoOQYJKoZIhvcNAQcCoIIoKjCCKCYCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBHwKhIDp9p2+ch
# yn/YwjPYMRk10YShrXyy5Qto4S28E6CCDYUwggYDMIID66ADAgECAhMzAAADTU6R
# phoosHiPAAAAAANNMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjMwMzE2MTg0MzI4WhcNMjQwMzE0MTg0MzI4WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDUKPcKGVa6cboGQU03ONbUKyl4WpH6Q2Xo9cP3RhXTOa6C6THltd2RfnjlUQG+
# Mwoy93iGmGKEMF/jyO2XdiwMP427j90C/PMY/d5vY31sx+udtbif7GCJ7jJ1vLzd
# j28zV4r0FGG6yEv+tUNelTIsFmmSb0FUiJtU4r5sfCThvg8dI/F9Hh6xMZoVti+k
# bVla+hlG8bf4s00VTw4uAZhjGTFCYFRytKJ3/mteg2qnwvHDOgV7QSdV5dWdd0+x
# zcuG0qgd3oCCAjH8ZmjmowkHUe4dUmbcZfXsgWlOfc6DG7JS+DeJak1DvabamYqH
# g1AUeZ0+skpkwrKwXTFwBRltAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUId2Img2Sp05U6XI04jli2KohL+8w
# VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh
# dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzUwMDUxNzAfBgNVHSMEGDAW
# gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw
# MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx
# XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB
# ACMET8WuzLrDwexuTUZe9v2xrW8WGUPRQVmyJ1b/BzKYBZ5aU4Qvh5LzZe9jOExD
# YUlKb/Y73lqIIfUcEO/6W3b+7t1P9m9M1xPrZv5cfnSCguooPDq4rQe/iCdNDwHT
# 6XYW6yetxTJMOo4tUDbSS0YiZr7Mab2wkjgNFa0jRFheS9daTS1oJ/z5bNlGinxq
# 2v8azSP/GcH/t8eTrHQfcax3WbPELoGHIbryrSUaOCphsnCNUqUN5FbEMlat5MuY
# 94rGMJnq1IEd6S8ngK6C8E9SWpGEO3NDa0NlAViorpGfI0NYIbdynyOB846aWAjN
# fgThIcdzdWFvAl/6ktWXLETn8u/lYQyWGmul3yz+w06puIPD9p4KPiWBkCesKDHv
# XLrT3BbLZ8dKqSOV8DtzLFAfc9qAsNiG8EoathluJBsbyFbpebadKlErFidAX8KE
# usk8htHqiSkNxydamL/tKfx3V/vDAoQE59ysv4r3pE+zdyfMairvkFNNw7cPn1kH
# Gcww9dFSY2QwAxhMzmoM0G+M+YvBnBu5wjfxNrMRilRbxM6Cj9hKFh0YTwba6M7z
# ntHHpX3d+nabjFm/TnMRROOgIXJzYbzKKaO2g1kWeyG2QtvIR147zlrbQD4X10Ab
# rRg9CpwW7xYxywezj+iNAc+QmFzR94dzJkEPUSCJPsTFMIIHejCCBWKgAwIBAgIK
# YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm
# aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw
# OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD
# VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG
# 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la
# UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc
# 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D
# dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+
# lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk
# kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6
# A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd
# X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL
# 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd
# sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3
# T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS
# 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI
# bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL
# BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD
# uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv
# c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
# MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3
# dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf
# MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF
# BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h
# cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA
# YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn
# 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7
# v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b
# pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/
# KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy
# CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp
# mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi
# hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb
# BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS
# oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL
# gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX
# cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCGgowghoGAgEBMIGVMH4x
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p
# Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAANNTpGmGiiweI8AAAAA
# A00wDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw
# HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEILQB
# fHFUuX7UWrP84Ydy+x3Un6wcZavRmqgOwib68YSZMEIGCisGAQQBgjcCAQwxNDAy
# oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20wDQYJKoZIhvcNAQEBBQAEggEAgNfBJBSZ6FZLLh+KneBMMn3Dua1YsNU79Wjv
# 4qtvq9jDVUaHuOed/cojDCoLN2rGA5Ay7OcgK80PKet92OBoXbzszpMJHm2r4x3a
# j5S2xO3pgdOW/A7nWFMNAhAPKEBFHpehdaNBkTey5IZcCrdRqLd8A+W68UkoWKN3
# IN+rKF3RKrhEvyEOzyxdWwinlUhgQu+yk9u+9F2FSduOh+HM/Jzz1u5IeQVbMWQF
# 1hXYb/Zxev7/HLHF6KhqNf13+JNl2uSyTXsx5imEidQneDu1y1lC9pTE4SRJAAgD
# +jBNaxvkBJwDtgftYAiWOHEbEsLFLO+94jIlBEYxrXLWR7gS5KGCF5QwgheQBgor
# BgEEAYI3AwMBMYIXgDCCF3wGCSqGSIb3DQEHAqCCF20wghdpAgEDMQ8wDQYJYIZI
# AWUDBAIBBQAwggFSBgsqhkiG9w0BCRABBKCCAUEEggE9MIIBOQIBAQYKKwYBBAGE
# WQoDATAxMA0GCWCGSAFlAwQCAQUABCCUTfOXBcPxAAVwMp+3SicfNgZrstXCjXsC
# PpOeqaf37AIGZNTJI1IUGBMyMDIzMDgyMzAxMjk1MC4zMDhaMASAAgH0oIHRpIHO
# MIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQL
# ExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxk
# IFRTUyBFU046QTQwMC0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1l
# LVN0YW1wIFNlcnZpY2WgghHqMIIHIDCCBQigAwIBAgITMwAAAdYnaf9yLVbIrgAB
# AAAB1jANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz
# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv
# cnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAx
# MDAeFw0yMzA1MjUxOTEyMzRaFw0yNDAyMDExOTEyMzRaMIHLMQswCQYDVQQGEwJV
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1l
# cmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046QTQwMC0w
# NUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Uw
# ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDPLM2Om8r5u3fcbDEOXydJ
# tbkW5U34KFaftC+8QyNqplMIzSTC1ToE0zcweQCvPIfpYtyPB3jt6fPRprvhwCks
# Uw9p0OfmZzWPDvkt40BUStu813QlrloRdplLz2xpk29jIOZ4+rBbKaZkBPZ4R4LX
# QhkkHne0Y/Yh85ZqMMRaMWkBM6nUwV5aDiwXqdE9Jyl0i1aWYbCqzwBRdN7CTlAJ
# xrJ47ov3uf/lFg9hnVQcqQYgRrRFpDNFMOP0gwz5Nj6a24GZncFEGRmKwImL+5KW
# PnVgvadJSRp6ZqrYV3FmbBmZtsF0hSlVjLQO8nxelGV7TvqIISIsv2bQMgUBVEz8
# wHFyU3863gHj8BCbEpJzm75fLJsL3P66lJUNRN7CRsfNEbHdX/d6jopVOFwF7omm
# TQjpU37A/7YR0wJDTt6ZsXU+j/wYlo9b22t1qUthqjRs32oGf2TRTCoQWLhJe3cA
# IYRlla/gEKlbuDDsG3926y4EMHFxTjsjrcZEbDWwjB3wrp11Dyg1QKcDyLUs2anB
# olvQwJTN0mMOuXO8tBz20ng/+Xw+4w+W9PMkvW1faYi435VjKRZsHfxIPjIzZ0wf
# 4FibmVPJHZ+aTxGsVJPxydChvvGCf4fe8XfYY9P5lbn9ScKc4adTd44GCrBlJ/JO
# soA4OvNHY6W+XcKVcIIGWwIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFGGaVDY7TQBi
# MCKg2+j/zRTcYsZOMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8G
# A1UdHwRYMFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv
# Y3JsL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBs
# BggrBgEFBQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0
# LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUy
# MDIwMTAoMSkuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUH
# AwgwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4ICAQDUv+RjNidwJxSb
# Mk1IvS8LfxNM8VaVhpxR1SkW+FRY6AKkn2s3On29nGEVlatblIv1qVTKkrUxLYMZ
# 0z+RA6mmfXue2Y7/YBbzM5kUeUgU2y1Mmbin6xadT9DzECeE7E4+3k2DmZxuV+GL
# FYQsqkDbe8oy7+3BSiU29qyZAYT9vRDALPUC5ZwyoPkNfKbqjl3VgFTqIubEQr56
# M0YdMWlqCqq0yVln9mPbhHHzXHOjaQsurohHCf7VT8ct79po34Fd8XcsqmyhdKBy
# 1jdyknrik+F3vEl/90qaon5N8KTZoGtOFlaJFPnZ2DqQtb2WWkfuAoGWrGSA43My
# l7+PYbUsri/NrMvAd9Z+J9FlqsMwXQFxAB7ujJi4hP8BH8j6qkmy4uulU5SSQa6X
# kElcaKQYSpJcSjkjyTDIOpf6LZBTaFx6eeoqDZ0lURhiRqO+1yo8uXO89e6kgBeC
# 8t1WN5ITqXnjocYgDvyFpptsUDgnRUiI1M/Ql/O299VktMkIL72i6Qd4BBsrj3Z+
# iLEnKP9epUwosP1m3N2v9yhXQ1HiusJl63IfXIyfBJaWvQDgU3Jk4eIZSr/2KIj4
# ptXt496CRiHTi011kcwDpdjQLAQiCvoj1puyhfwVf2G5ZwBptIXivNRba34KkD5o
# qmEoF1yRFQ84iDsf/giyn/XIT7YY/zCCB3EwggVZoAMCAQICEzMAAAAVxedrngKb
# SZkAAAAAABUwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
# EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv
# ZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmlj
# YXRlIEF1dGhvcml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIy
# NVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT
# B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE
# AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXI
# yjVX9gF/bErg4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjo
# YH1qUoNEt6aORmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1y
# aa8dq6z2Nr41JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v
# 3byNpOORj7I5LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pG
# ve2krnopN6zL64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg3viS
# kR4dPf0gz3N9QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYr
# bqgSUei/BQOj0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlM
# jgK8QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSL
# W6CmgyFdXzB0kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AF
# emzFER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIu
# rQIDAQABo4IB3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIE
# FgQUKqdS/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWn
# G1M1GelyMFwGA1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEW
# M2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5
# Lmh0bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBi
# AEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV
# 9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3Js
# Lm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAx
# MC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8v
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2
# LTIzLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv
# 6lwUtj5OR2R4sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZn
# OlNN3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1
# bSNU5HhTdSRXud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4
# rPf5KYnDvBewVIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU
# 6ZGyqVvfSaN0DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDF
# NLB62FD+CljdQDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/
# HltEAY5aGZFrDZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2tVdU
# CbFpAUR+fKFhbHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKi
# excdFYmNcP7ntdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTm
# dHRbatGePu1+oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZq
# ELQdVTNYs6FwZvKhggNNMIICNQIBATCB+aGB0aSBzjCByzELMAkGA1UEBhMCVVMx
# EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT
# FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJp
# Y2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOkE0MDAtMDVF
# MC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMK
# AQEwBwYFKw4DAhoDFQD5r3DVRpAGQo9sTLUHeBC87NpK+qCBgzCBgKR+MHwxCzAJ
# BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jv
# c29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUAAgUA6I/BmjAi
# GA8yMDIzMDgyMjIzMjIwMloYDzIwMjMwODIzMjMyMjAyWjB0MDoGCisGAQQBhFkK
# BAExLDAqMAoCBQDoj8GaAgEAMAcCAQACAiCqMAcCAQACAhKhMAoCBQDokRMaAgEA
# MDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEAAgMHoSChCjAI
# AgEAAgMBhqAwDQYJKoZIhvcNAQELBQADggEBAF+P+vYI5nAVMKLZzuKDTypkyGsz
# cERltVOmBhfuSHAHWdJWny4lnCYauOWDJ0eF9wYyeIixbFmF7FSQipTB5IlktuOS
# FKh30qSWPT3vP/KNc2ulOzWwoGrEAt5ZiGdm9/6Cotg6rl9g8WSJkaOhJ5ZIIoyj
# +VzI8B4Fd6OvoQWQC6S2eQHLPTvLZX3OU3In5T11pZUkBL63VP1OkirAZZmH7wog
# 3g1/0nU4ThMh/GkPU9E52YPz8nfe0+ttMemFoBbBa/OynYKgdoiE2Xfay6PGWhFP
# k25p+nQ+qV/a5v0FzPGT3fZ8LWxUSXRqH0YqIVdD0bUJJ7yETFl9iSj+7AQxggQN
# MIIECQIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ
# MA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
# MSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAdYn
# af9yLVbIrgABAAAB1jANBglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0G
# CyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCD+hrMfwJvoONNNCMYiUgTR/Zes
# wvETrVWlA6rJskCuYTCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EINbLTQ1X
# eNM+EBinOEJMjZd0jMNDur+AK+O8P12j5ST8MIGYMIGApH4wfDELMAkGA1UEBhMC
# VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp
# bWUtU3RhbXAgUENBIDIwMTACEzMAAAHWJ2n/ci1WyK4AAQAAAdYwIgQgOLLykD7v
# mwAbIXPhNyhZkvq4uiZ624puG6TAZkSHaoswDQYJKoZIhvcNAQELBQAEggIADlRo
# GURBr9Tk3qRkvAxwOM5ggHi5i5CnHV6QDyFd3TNjIqbrqX8+f2UNB7YML2yg4VXi
# io7E9qjbwsaf0KFkVSFD4GhDEhpDLNq/x6weVCOdHlsfDuBFkaKjQg+iI9hKBpqw
# 1wr6odM+luBTt7dAUAkuK4vfaGrU8q93Rkpmtgs+m+xiTs9272dwetLcKpeWqgaO
# WFLjFMP9uVjmfjrH4L43Xt14aS/xL11xxv3H0Jb5jePY5ggLFMAWQdJJHwjwMxEV
# Af9Kx83aKSwqxFqah7jGxWgueAoYgqEXvrLOGVs8eK4ofuFCRUijQFRCw5SjVVte
# 8RYumwilf4a/GDtKx5Z/YbSxpZMfjFPfn1cgGXKoTjvYxkIO9Bvub01JugeQeONq
# 8EdR0FqfSon5H2F1rQwbydPBqlPAqg3msdS0QiTMvDRqmgmEVhN1Hgo20AuCiDtk
# sDA7RteawdPJSal418M1GBHLGfOUP0EgZUuU+OnbTmrAQJ/jyMIVRdGscHNFNdiE
# /JNWmLuhiakOn2berl/WGTiQYUfl2HqzJ96f28wMty4ht3FuLU1EKqMRs62GOcCK
# 7lOhHdffbGPJ4oCE4RsGa6Gu5N0JK1oOFFR3zhNB7S9xvkVSw9tbmei9lt/9M07t
# Ks5exi+qO3fLCNcQY5pzWkLwRP6zFAKmUZvroY0=
# SIG # End signature block
