Private/ResourceGraphWorker.ps1

# Resource Graph parallel engine — Copyright (c) NCS Dojo. All Rights Reserved.

function Invoke-ResourceGraphCollection {
    param(
        [hashtable[]]$Collectors,
        [array]$SubscriptionBatches,
        [string]$AccessToken,
        [int]$MaxThreads = 50,
        [System.Collections.Specialized.OrderedDictionary]$CollectorStatus
    )

    $workerScript = {
        param($Token, $CollectorName, $Query, $SubscriptionIds, $BatchIndex, $MaxRetries)

        $headers = @{ Authorization = "Bearer $Token"; 'Content-Type' = 'application/json' }
        $results = [System.Collections.Generic.List[object]]::new()
        $warnings = [System.Collections.Generic.List[string]]::new()
        $sw = [System.Diagnostics.Stopwatch]::StartNew()
        $truncated = $false
        $pageNum = 0
        $skipToken = $null

        do {
            $pageNum++
            $bodyObj = @{
                query         = $Query
                subscriptions = @($SubscriptionIds)
                options       = @{ resultFormat = 'objectArray'; '$top' = 1000 }
            }
            if ($skipToken) { $bodyObj.options.'$skipToken' = $skipToken }
            $bodyJson = $bodyObj | ConvertTo-Json -Depth 10

            $success = $false
            for ($attempt = 1; $attempt -le $MaxRetries; $attempt++) {
                try {
                    $webResponse = Invoke-WebRequest -Method POST `
                        -Uri "https://management.azure.com/providers/Microsoft.ResourceGraph/resources?api-version=2022-10-01" `
                        -Headers $headers -Body $bodyJson -UseBasicParsing

                    $quotaRemaining = 0
                    try { $quotaRemaining = [int]($webResponse.Headers['x-ms-user-quota-remaining'] | Select-Object -First 1) } catch {}

                    if ($quotaRemaining -le 2 -and $quotaRemaining -gt 0) {
                        $quotaResets = ($webResponse.Headers['x-ms-user-quota-resets-after'] | Select-Object -First 1)
                        if ($quotaResets) {
                            $parts   = $quotaResets -split ':'
                            $waitSec = ([int]$parts[0]*3600) + ([int]$parts[1]*60) + ([int]$parts[2]) + 1
                            Start-Sleep -Seconds $waitSec
                        }
                    }

                    $resp    = $webResponse.Content | ConvertFrom-Json
                    $success = $true
                    break
                }
                catch {
                    $statusCode = 0
                    if ($_.Exception.PSObject.Properties['Response'] -and $_.Exception.Response) {
                        $statusCode = [int]$_.Exception.Response.StatusCode
                    }
                    if ($statusCode -eq 429) {
                        $retryAfter = 5
                        try { $raH = $_.Exception.Response.Headers['Retry-After']; if ($raH) { $retryAfter = [int]($raH | Select-Object -First 1) } } catch {}
                        Start-Sleep -Seconds ([Math]::Max($retryAfter, [Math]::Pow(2, $attempt)))
                        continue
                    }
                    if ($attempt -lt $MaxRetries) {
                        Start-Sleep -Seconds ([Math]::Pow(2, $attempt))
                        continue
                    }
                    throw $_
                }
            }
            if (-not $success) { throw "[$CollectorName batch $BatchIndex] Failed after $MaxRetries retries." }

            if ($resp.PSObject.Properties['data'] -and $resp.data) {
                foreach ($row in $resp.data) { $results.Add($row) }
            }
            if ($resp.PSObject.Properties['resultTruncated'] -and $resp.resultTruncated -eq 'true') {
                $truncated = $true
            }
            $skipToken = if ($resp.PSObject.Properties['$skipToken']) { $resp.'$skipToken' } else { $null }
        } while ($skipToken)

        $sw.Stop()
        return [PSCustomObject]@{
            Collector = $CollectorName; BatchIndex = $BatchIndex
            Results = @($results); Count = $results.Count; Pages = $pageNum
            DurationSeconds = [Math]::Round($sw.Elapsed.TotalSeconds, 2)
            Truncated = $truncated; Warnings = @($warnings); Status = "Success"
        }
    }

    foreach ($coll in $Collectors) {
        $CollectorStatus[$coll.Name] = @{
            fileName = $coll.FileName; label = $coll.Label
            rowCount = 0; uniqueResourceCount = 0; durationSeconds = 0
            status = "Pending"; warnings = @(); errors = @()
        }
    }

    $totalJobs   = $Collectors.Count * $SubscriptionBatches.Count
    $threadCount = [Math]::Min($totalJobs, $MaxThreads)

    $pool = [RunspaceFactory]::CreateRunspacePool(1, $threadCount)
    $pool.Open()
    $jobs = @()

    foreach ($coll in $Collectors) {
        for ($b = 0; $b -lt $SubscriptionBatches.Count; $b++) {
            $ps = [PowerShell]::Create().AddScript($workerScript)
            [void]$ps.AddParameter("Token",           $AccessToken)
            [void]$ps.AddParameter("CollectorName",   $coll.Name)
            [void]$ps.AddParameter("Query",           $coll.Query)
            [void]$ps.AddParameter("SubscriptionIds", $SubscriptionBatches[$b])
            [void]$ps.AddParameter("BatchIndex",      $b)
            [void]$ps.AddParameter("MaxRetries",      5)
            $ps.RunspacePool = $pool
            $jobs += @{ PS = $ps; Handle = $ps.BeginInvoke(); Collector = $coll.Name; Batch = $b }
        }
    }

    $completed = 0
    foreach ($job in $jobs) {
        try {
            $result = $job.PS.EndInvoke($job.Handle)
            if ($null -ne $result -and @($result).Count -gt 0) {
                $r = @($result)[0]
                $s = $CollectorStatus[$job.Collector]
                $s['rowCount'] = $s['rowCount'] + [int]$r.Count
                $s['durationSeconds'] = [Math]::Max($s['durationSeconds'], $r.DurationSeconds)
                $s['status'] = "Success"
                if ($r.Warnings) { $s['warnings'] = $s['warnings'] + @($r.Warnings) }

                if (-not $s.ContainsKey('_results')) { $s['_results'] = [System.Collections.Generic.List[object]]::new() }
                foreach ($row in @($r.Results)) { if ($null -ne $row) { $s['_results'].Add($row) } }
            }
        }
        catch {
            $CollectorStatus[$job.Collector]['status'] = "Error"
            $CollectorStatus[$job.Collector]['errors'] = @($CollectorStatus[$job.Collector]['errors']) + @($_.ToString())
            Write-Log "[$($job.Collector) batch $($job.Batch)] ERROR: $_" -Level ERROR
        }
        finally { $job.PS.Dispose() }
        $completed++
        if ($completed % 10 -eq 0) { Write-Host " RG $completed/$totalJobs" -ForegroundColor Gray }
    }
    $pool.Close(); $pool.Dispose()

    foreach ($coll in $Collectors) {
        $s = $CollectorStatus[$coll.Name]
        $displayCount = $s['rowCount']
        if ($s.ContainsKey('_results') -and $coll.UniqueField) {
            $seen = @{}
            foreach ($r in @($s['_results'])) {
                if ($null -ne $r -and $r.PSObject.Properties[$coll.UniqueField]) {
                    $k = "$($r.$($coll.UniqueField))"
                    if ($r.PSObject.Properties['subscriptionId']) { $k = "$($r.subscriptionId)/$k" }
                    $seen[$k] = $true
                }
            }
            if ($seen.Count -gt 0) { $displayCount = $seen.Count }
        }
        Write-Log " $($coll.Name): $displayCount $($coll.Label)" -Level $(if ($s['status'] -eq 'Error') { 'ERROR' } else { 'SUCCESS' })
    }
}

# SIG # Begin signature block
# MII9FwYJKoZIhvcNAQcCoII9CDCCPQQCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDS2tWWq4B/ahT2
# x/mn7OTWIb5jLIOndzRUM0+1DmSqm6CCIdwwggXMMIIDtKADAgECAhBUmNLR1FsZ
# lUgTecgRwIeZMA0GCSqGSIb3DQEBDAUAMHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jvc29mdCBJZGVu
# dGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAy
# MDAeFw0yMDA0MTYxODM2MTZaFw00NTA0MTYxODQ0NDBaMHcxCzAJBgNVBAYTAlVT
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jv
# c29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRo
# b3JpdHkgMjAyMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALORKgeD
# Bmf9np3gx8C3pOZCBH8Ppttf+9Va10Wg+3cL8IDzpm1aTXlT2KCGhFdFIMeiVPvH
# or+Kx24186IVxC9O40qFlkkN/76Z2BT2vCcH7kKbK/ULkgbk/WkTZaiRcvKYhOuD
# PQ7k13ESSCHLDe32R0m3m/nJxxe2hE//uKya13NnSYXjhr03QNAlhtTetcJtYmrV
# qXi8LW9J+eVsFBT9FMfTZRY33stuvF4pjf1imxUs1gXmuYkyM6Nix9fWUmcIxC70
# ViueC4fM7Ke0pqrrBc0ZV6U6CwQnHJFnni1iLS8evtrAIMsEGcoz+4m+mOJyoHI1
# vnnhnINv5G0Xb5DzPQCGdTiO0OBJmrvb0/gwytVXiGhNctO/bX9x2P29Da6SZEi3
# W295JrXNm5UhhNHvDzI9e1eM80UHTHzgXhgONXaLbZ7LNnSrBfjgc10yVpRnlyUK
# xjU9lJfnwUSLgP3B+PR0GeUw9gb7IVc+BhyLaxWGJ0l7gpPKWeh1R+g/OPTHU3mg
# trTiXFHvvV84wRPmeAyVWi7FQFkozA8kwOy6CXcjmTimthzax7ogttc32H83rwjj
# O3HbbnMbfZlysOSGM1l0tRYAe1BtxoYT2v3EOYI9JACaYNq6lMAFUSw0rFCZE4e7
# swWAsk0wAly4JoNdtGNz764jlU9gKL431VulAgMBAAGjVDBSMA4GA1UdDwEB/wQE
# AwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIftJqhSobyhmYBAcnz1AQ
# T2ioojAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0BAQwFAAOCAgEAr2rd5hnn
# LZRDGU7L6VCVZKUDkQKL4jaAOxWiUsIWGbZqWl10QzD0m/9gdAmxIR6QFm3FJI9c
# Zohj9E/MffISTEAQiwGf2qnIrvKVG8+dBetJPnSgaFvlVixlHIJ+U9pW2UYXeZJF
# xBA2CFIpF8svpvJ+1Gkkih6PsHMNzBxKq7Kq7aeRYwFkIqgyuH4yKLNncy2RtNwx
# AQv3Rwqm8ddK7VZgxCwIo3tAsLx0J1KH1r6I3TeKiW5niB31yV2g/rarOoDXGpc8
# FzYiQR6sTdWD5jw4vU8w6VSp07YEwzJ2YbuwGMUrGLPAgNW3lbBeUU0i/OxYqujY
# lLSlLu2S3ucYfCFX3VVj979tzR/SpncocMfiWzpbCNJbTsgAlrPhgzavhgplXHT2
# 6ux6anSg8Evu75SjrFDyh+3XOjCDyft9V77l4/hByuVkrrOj7FjshZrM77nq81YY
# uVxzmq/FdxeDWds3GhhyVKVB0rYjdaNDmuV3fJZ5t0GNv+zcgKCf0Xd1WF81E+Al
# GmcLfc4l+gcK5GEh2NQc5QfGNpn0ltDGFf5Ozdeui53bFv0ExpK91IjmqaOqu/dk
# ODtfzAzQNb50GQOmxapMomE2gj4d8yu8l13bS3g7LfU772Aj6PXsCyM2la+YZr9T
# 03u4aUoqlmZpxJTG9F9urJh4iIAGXKKy7aIwggabMIIEg6ADAgECAhMzAAFKynTD
# 32l/wWVjAAAAAUrKMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ
# RCBWZXJpZmllZCBDUyBFT0MgQ0EgMDQwHhcNMjYwNTIyMTg0NjAwWhcNMjYwNTI1
# MTg0NjAwWjBfMQswCQYDVQQGEwJDQTEQMA4GA1UECBMHQWxiZXJ0YTEQMA4GA1UE
# BxMHQ2FsZ2FyeTEVMBMGA1UEChMMRGFycmVuIE1heWVzMRUwEwYDVQQDEwxEYXJy
# ZW4gTWF5ZXMwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCkZwmcQMXn
# +D7c3CZDJIY60kPXr6G/+R80J6b8AfQ59+KS7LpbCoo8qTlQmMdE9KBz8OVpBZl+
# fGeunRaYE11tRzfNDUNRo47bUXn9WLC9ppHR7fD1rBa0M2/4CHSF8XmpGMhchi78
# 8GTxSvo8PVbeQmcWu1OZc6c0v7VTa+WMn8pPxBadjuBzQLfu8W7ZM93yk9gM3zgY
# w7rpOXTK88g9hgAqa44c2hawBH+x+YOzex/pN/ANevNKyMukAhKGTDSrdT1gA/zu
# spyhqBY3/3mQGPJw1vDoE6dtaCEqEP4zA58O/33WbG5N89Ux5VULO2xqf2KBrT9k
# QQ5WJqqMkCEyVMATF1Yw6xrDybkTantakYrOu8WVCQu1yVTQK4Phkp9jSd7Wi6KO
# RhArBg/PVPD/Az0Vk5k2x9RFYGD8a3LZGNZJW007eCAsuvM6yiNTNhMefekgQIhD
# cV1FOpcHdIX1CG9jArNoWrJv1JcwRp0tdliqwqzCzgD6u6QzqlEoyNMCAwEAAaOC
# AdMwggHPMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMDoGA1UdJQQzMDEG
# CisGAQQBgjdhAQAGCCsGAQUFBwMDBhkrBgEEAYI3YYuPpXGB3qaBQNv/tAST5rkV
# MB0GA1UdDgQWBBR8+HgjLac+sCuRRa+VLYY9BnDgbTAfBgNVHSMEGDAWgBSa8VR3
# dQyHFjdGoKzeefn0f8F46TBnBgNVHR8EYDBeMFygWqBYhlZodHRwOi8vd3d3Lm1p
# Y3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBJRCUyMFZlcmlmaWVk
# JTIwQ1MlMjBFT0MlMjBDQSUyMDA0LmNybDB0BggrBgEFBQcBAQRoMGYwZAYIKwYB
# BQUHMAKGWGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWlj
# cm9zb2Z0JTIwSUQlMjBWZXJpZmllZCUyMENTJTIwRU9DJTIwQ0ElMjAwNC5jcnQw
# VAYDVR0gBE0wSzBJBgRVHSAAMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWlj
# cm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTANBgkqhkiG9w0B
# AQwFAAOCAgEAJblhyAPmRmpYbfdjQC/PjC8rC2crvirs/FxHLmkL8b3wHRS1LVXb
# f4Jb8tw/z2aRLnA41qHH2HE+uwgq1zLLUJBMvP8V8ypcSFuhmq60RMo3Fh2XhdrH
# ZTkfv0rrz1wYSjtZOyNXfapK+8aox/eETeDPd4XuiIGSn2ReDTETvoJc9VOcGH1F
# CF7Z0OaB1yMyEfEF6LrqmlvFvFD9RGX0wt/lCn0MObH0x+1gIAtdb/8tL3uZ5IW1
# kCig5zD7LTOAbZY55IKPY0ivNThclR9M2psbZxSFKx+I9awnneooDmTOKFQcp6/8
# VMp62/EGCJUB1NVMGmZ1Cz7pMREwIj9svI9Bsa9ZnG2HFpdV9cmsw+Hjjr+Dy/nj
# n5cH41ols2TrnZtj1zz2bUplpU/GRPPl4lf+kBEIgf4Ds46T8AFKcxHdN9hr0oLA
# MKlhTEvUEkTL1yq5AhTOI0aqdBwUHVyOQDMsrZVY0zUaZF4YBr8PzW+QE5YF/oOv
# P5+GSYzjcTArJlIvk/RAjxy2p0YKuZXNMG3vG+z9q+D4hJbM9YRvfPpdlWvtBovn
# 5TgHGKUX4Qo+ovMLcR1YoBwPlNgXN9I3VjvjpaY7/moRqjt7sw3RekZtYeWRmnFn
# joIkoZUP1fb94LlojFPXIhLKePZdH1WuMBS5dtndYNZVS14Zf098bvkwggabMIIE
# g6ADAgECAhMzAAFKynTD32l/wWVjAAAAAUrKMA0GCSqGSIb3DQEBDAUAMFoxCzAJ
# BgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNV
# BAMTIk1pY3Jvc29mdCBJRCBWZXJpZmllZCBDUyBFT0MgQ0EgMDQwHhcNMjYwNTIy
# MTg0NjAwWhcNMjYwNTI1MTg0NjAwWjBfMQswCQYDVQQGEwJDQTEQMA4GA1UECBMH
# QWxiZXJ0YTEQMA4GA1UEBxMHQ2FsZ2FyeTEVMBMGA1UEChMMRGFycmVuIE1heWVz
# MRUwEwYDVQQDEwxEYXJyZW4gTWF5ZXMwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAw
# ggGKAoIBgQCkZwmcQMXn+D7c3CZDJIY60kPXr6G/+R80J6b8AfQ59+KS7LpbCoo8
# qTlQmMdE9KBz8OVpBZl+fGeunRaYE11tRzfNDUNRo47bUXn9WLC9ppHR7fD1rBa0
# M2/4CHSF8XmpGMhchi788GTxSvo8PVbeQmcWu1OZc6c0v7VTa+WMn8pPxBadjuBz
# QLfu8W7ZM93yk9gM3zgYw7rpOXTK88g9hgAqa44c2hawBH+x+YOzex/pN/ANevNK
# yMukAhKGTDSrdT1gA/zuspyhqBY3/3mQGPJw1vDoE6dtaCEqEP4zA58O/33WbG5N
# 89Ux5VULO2xqf2KBrT9kQQ5WJqqMkCEyVMATF1Yw6xrDybkTantakYrOu8WVCQu1
# yVTQK4Phkp9jSd7Wi6KORhArBg/PVPD/Az0Vk5k2x9RFYGD8a3LZGNZJW007eCAs
# uvM6yiNTNhMefekgQIhDcV1FOpcHdIX1CG9jArNoWrJv1JcwRp0tdliqwqzCzgD6
# u6QzqlEoyNMCAwEAAaOCAdMwggHPMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQD
# AgeAMDoGA1UdJQQzMDEGCisGAQQBgjdhAQAGCCsGAQUFBwMDBhkrBgEEAYI3YYuP
# pXGB3qaBQNv/tAST5rkVMB0GA1UdDgQWBBR8+HgjLac+sCuRRa+VLYY9BnDgbTAf
# BgNVHSMEGDAWgBSa8VR3dQyHFjdGoKzeefn0f8F46TBnBgNVHR8EYDBeMFygWqBY
# hlZodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQl
# MjBJRCUyMFZlcmlmaWVkJTIwQ1MlMjBFT0MlMjBDQSUyMDA0LmNybDB0BggrBgEF
# BQcBAQRoMGYwZAYIKwYBBQUHMAKGWGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w
# a2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwSUQlMjBWZXJpZmllZCUyMENTJTIwRU9D
# JTIwQ0ElMjAwNC5jcnQwVAYDVR0gBE0wSzBJBgRVHSAAMEEwPwYIKwYBBQUHAgEW
# M2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5
# Lmh0bTANBgkqhkiG9w0BAQwFAAOCAgEAJblhyAPmRmpYbfdjQC/PjC8rC2crvirs
# /FxHLmkL8b3wHRS1LVXbf4Jb8tw/z2aRLnA41qHH2HE+uwgq1zLLUJBMvP8V8ypc
# SFuhmq60RMo3Fh2XhdrHZTkfv0rrz1wYSjtZOyNXfapK+8aox/eETeDPd4XuiIGS
# n2ReDTETvoJc9VOcGH1FCF7Z0OaB1yMyEfEF6LrqmlvFvFD9RGX0wt/lCn0MObH0
# x+1gIAtdb/8tL3uZ5IW1kCig5zD7LTOAbZY55IKPY0ivNThclR9M2psbZxSFKx+I
# 9awnneooDmTOKFQcp6/8VMp62/EGCJUB1NVMGmZ1Cz7pMREwIj9svI9Bsa9ZnG2H
# FpdV9cmsw+Hjjr+Dy/njn5cH41ols2TrnZtj1zz2bUplpU/GRPPl4lf+kBEIgf4D
# s46T8AFKcxHdN9hr0oLAMKlhTEvUEkTL1yq5AhTOI0aqdBwUHVyOQDMsrZVY0zUa
# ZF4YBr8PzW+QE5YF/oOvP5+GSYzjcTArJlIvk/RAjxy2p0YKuZXNMG3vG+z9q+D4
# hJbM9YRvfPpdlWvtBovn5TgHGKUX4Qo+ovMLcR1YoBwPlNgXN9I3VjvjpaY7/moR
# qjt7sw3RekZtYeWRmnFnjoIkoZUP1fb94LlojFPXIhLKePZdH1WuMBS5dtndYNZV
# S14Zf098bvkwggcoMIIFEKADAgECAhMzAAAAFydFCQuLh6/GAAAAAAAXMA0GCSqG
# SIb3DQEBDAUAMGMxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y
# cG9yYXRpb24xNDAyBgNVBAMTK01pY3Jvc29mdCBJRCBWZXJpZmllZCBDb2RlIFNp
# Z25pbmcgUENBIDIwMjEwHhcNMjYwMzI2MTgxMTMxWhcNMzEwMzI2MTgxMTMxWjBa
# MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSsw
# KQYDVQQDEyJNaWNyb3NvZnQgSUQgVmVyaWZpZWQgQ1MgRU9DIENBIDA0MIICIjAN
# BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAgsdk/gMPZioBlcyfk6tDzJ+PRt4r
# SLGKW8ewpS0kRxXtURC3T3GdbCKljobEn8ussqhGqQpRh/SXvRVwNXEIGb76UG5I
# PkCJ1S6/9BD61QQsKzPepW0SNj8TXgsFxvS7MltoRuikIIp7Q5jQgaOM6QyK9++6
# ZVXUpYmZulAe6x8JrwZ0dNkE+rZ66lqtoocwepUSVUxM7odDmn8yDHjJ2DNPsfr3
# uRDix3X4qvh14jH/SW+2Cx7WIMhyIiQO201i6hUixmk4e2ZW8W7C1wPdTjq6BKb+
# zo8xbrt7ZKQvRX5QOA6dhLquPqj5sVKnxqfk19IC0SafTSTs8yC43Ew965BRRW8V
# L9ccoOmr4rxQy7aCgYTNk3dd/LphNaTTmnGp7kmLTxyHkB5geoWhYuuGrywS8E0w
# Jv0W4rfOtHBV0e9sKvuUIeIUpnsx6ilxEVj6VQXvgD6yeCKnPmj3jJiJKAlmUDtt
# h5yzRVBUl44sMiG4L5R/yyACRKk2n088Q2YCoZS1O86+oMLKt1jaXGECOjbsVp8I
# d1VQw8he6J0KirOS5e25XlTdGPFb6oBOOaacgW78Kjf0bp+XzAgkc92mDGNJGYSj
# vdnj+7eMx6meW0DAIGdLRNj8/429MIspFBfz3KDqqpN71S4kQ2LLer3dxhDDczKV
# FL0HLwRuOvgjiG8CAwEAAaOCAdwwggHYMA4GA1UdDwEB/wQEAwIBhjAQBgkrBgEE
# AYI3FQEEAwIBADAdBgNVHQ4EFgQUmvFUd3UMhxY3RqCs3nn59H/BeOkwVAYDVR0g
# BE0wSzBJBgRVHSAAMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0
# LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTAZBgkrBgEEAYI3FAIEDB4K
# AFMAdQBiAEMAQTASBgNVHRMBAf8ECDAGAQH/AgEAMB8GA1UdIwQYMBaAFNlBKbAP
# D2Ns72nX9c0pnqRIajDmMHAGA1UdHwRpMGcwZaBjoGGGX2h0dHA6Ly93d3cubWlj
# cm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQl
# MjBDb2RlJTIwU2lnbmluZyUyMFBDQSUyMDIwMjEuY3JsMH0GCCsGAQUFBwEBBHEw
# bzBtBggrBgEFBQcwAoZhaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j
# ZXJ0cy9NaWNyb3NvZnQlMjBJRCUyMFZlcmlmaWVkJTIwQ29kZSUyMFNpZ25pbmcl
# MjBQQ0ElMjAyMDIxLmNydDANBgkqhkiG9w0BAQwFAAOCAgEAkHVaGf1NJt/Jdoim
# mRZbMWr6baaDi8mkdWvWStk0hdZDpxSYTA7HuipAoLL3qIhI101XOl7fOiCh5++j
# ZOamQdAV79ojEUNoIgCZmL2XJrLaGanwdjNynecJyYVCTrRf2+h7KknpWOp4axdO
# s6K9ZQ5g0IsQWXCwfc0dfkSkLKNY3pDcWLlJPh2jd5NUue6pNDv/2G5MFNJhCwlt
# ODebyAjGceU+XOzav+7i721YQnQ+39m2aQOFO7zpAdaKAeAGhEd6Y6CdDGneSxco
# ujWvafWbv4ay3jo1ORSLUuWMbKr5X18QE4Sde+gppGLLSkZsrUh2eyYSkX1envWX
# 7ZPzg2/wiuKRlQFarDn+N9+20BqzhxwkNyLzfYJp1Lg4fCXb24XqFjx8SDdRgebF
# ImOfOLVze8XQ/CwkrEaib0PHu2t4GVk4FYroEbNUFqvjdBvTY3uiR5TdQoyXoYHv
# h+TxpLSY2vo7hhK9D/rpEpHC+qmmcRUE4d0gyO9Zb1vvt25fxM3ekjvDfVHcPq3q
# Mr0Rwsk4krKZWUEgU1SXT5qN6gqRrshxbT6OQgZ9/xT04qiXdzPQR6KindBvSpoO
# nxnALxcJyzVwNpKL+9u8EZYy98qX6i+4gE/2J6cbpekcB0ZXDn/XQxoNUUb6/djT
# /wllVyG+vIHkdq71PzbH5rYxdcAwggeeMIIFhqADAgECAhMzAAAAB4ejNKN7pY4c
# AAAAAAAHMA0GCSqGSIb3DQEBDAUAMHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVN
# aWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jvc29mdCBJZGVudGl0
# eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAyMDAe
# Fw0yMTA0MDEyMDA1MjBaFw0zNjA0MDEyMDE1MjBaMGMxCzAJBgNVBAYTAlVTMR4w
# HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xNDAyBgNVBAMTK01pY3Jvc29m
# dCBJRCBWZXJpZmllZCBDb2RlIFNpZ25pbmcgUENBIDIwMjEwggIiMA0GCSqGSIb3
# DQEBAQUAA4ICDwAwggIKAoICAQCy8MCvGYgo4t1UekxJbGkIVQm0Uv96SvjB6yUo
# 92cXdylN65Xy96q2YpWCiTas7QPTkGnK9QMKDXB2ygS27EAIQZyAd+M8X+dmw6SD
# tzSZXyGkxP8a8Hi6EO9Zcwh5A+wOALNQbNO+iLvpgOnEM7GGB/wm5dYnMEOguua1
# OFfTUITVMIK8faxkP/4fPdEPCXYyy8NJ1fmskNhW5HduNqPZB/NkWbB9xxMqowAe
# WvPgHtpzyD3PLGVOmRO4ka0WcsEZqyg6efk3JiV/TEX39uNVGjgbODZhzspHvKFN
# U2K5MYfmHh4H1qObU4JKEjKGsqqA6RziybPqhvE74fEp4n1tiY9/ootdU0vPxRp4
# BGjQFq28nzawuvaCqUUF2PWxh+o5/TRCb/cHhcYU8Mr8fTiS15kRmwFFzdVPZ3+J
# V3s5MulIf3II5FXeghlAH9CvicPhhP+VaSFW3Da/azROdEm5sv+EUwhBrzqtxoYy
# E2wmuHKws00x4GGIx7NTWznOm6x/niqVi7a/mxnnMvQq8EMse0vwX2CfqM7Le/sm
# bRtsEeOtbnJBbtLfoAsC3TdAOnBbUkbUfG78VRclsE7YDDBUbgWt75lDk53yi7C3
# n0WkHFU4EZ83i83abd9nHWCqfnYa9qIHPqjOiuAgSOf4+FRcguEBXlD9mAInS7b6
# V0UaNwIDAQABo4ICNTCCAjEwDgYDVR0PAQH/BAQDAgGGMBAGCSsGAQQBgjcVAQQD
# AgEAMB0GA1UdDgQWBBTZQSmwDw9jbO9p1/XNKZ6kSGow5jBUBgNVHSAETTBLMEkG
# BFUdIAAwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br
# aW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIA
# QwBBMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUyH7SaoUqG8oZmAQHJ89Q
# EE9oqKIwgYQGA1UdHwR9MHsweaB3oHWGc2h0dHA6Ly93d3cubWljcm9zb2Z0LmNv
# bS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9u
# JTIwUm9vdCUyMENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAyMC5jcmwwgcMG
# CCsGAQUFBwEBBIG2MIGzMIGBBggrBgEFBQcwAoZ1aHR0cDovL3d3dy5taWNyb3Nv
# ZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBJZGVudGl0eSUyMFZlcmlm
# aWNhdGlvbiUyMFJvb3QlMjBDZXJ0aWZpY2F0ZSUyMEF1dGhvcml0eSUyMDIwMjAu
# Y3J0MC0GCCsGAQUFBzABhiFodHRwOi8vb25lb2NzcC5taWNyb3NvZnQuY29tL29j
# c3AwDQYJKoZIhvcNAQEMBQADggIBAH8lKp7+1Kvq3WYK21cjTLpebJDjW4ZbOX3H
# D5ZiG84vjsFXT0OB+eb+1TiJ55ns0BHluC6itMI2vnwc5wDW1ywdCq3TAmx0KWy7
# xulAP179qX6VSBNQkRXzReFyjvF2BGt6FvKFR/imR4CEESMAG8hSkPYso+GjlngM
# 8JPn/ROUrTaeU/BRu/1RFESFVgK2wMz7fU4VTd8NXwGZBe/mFPZG6tWwkdmA/jLb
# p0kNUX7elxu2+HtHo0QO5gdiKF+YTYd1BGrmNG8sTURvn09jAhIUJfYNotn7OlTh
# tfQjXqe0qrimgY4Vpoq2MgDW9ESUi1o4pzC1zTgIGtdJ/IvY6nqa80jFOTg5qzAi
# RNdsUvzVkoYP7bi4wLCj+ks2GftUct+fGUxXMdBUv5sdr0qFPLPB0b8vq516slCf
# RwaktAxK1S40MCvFbbAXXpAZnU20FaAoDwqq/jwzwd8Wo2J83r7O3onQbDO9TyDS
# tgaBNlHzMMQgl95nHBYMelLEHkUnVVVTUsgC0Huj09duNfMaJ9ogxhPNThgq3i8w
# 3DAGZ61AMeF0C1M+mU5eucj1Ijod5O2MMPeJQ3/vKBtqGZg4eTtUHt/BPjN74SsJ
# syHqAdXVS5c+ItyKWg3Eforhox9k3WgtWTpgV4gkSiS4+A09roSdOI4vrRw+p+fL
# 4WrxSK5nMYIakTCCGo0CAQEwcTBaMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWlj
# cm9zb2Z0IENvcnBvcmF0aW9uMSswKQYDVQQDEyJNaWNyb3NvZnQgSUQgVmVyaWZp
# ZWQgQ1MgRU9DIENBIDA0AhMzAAFKynTD32l/wWVjAAAAAUrKMA0GCWCGSAFlAwQC
# AQUAoF4wEAYKKwYBBAGCNwIBDDECMAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcC
# AQQwLwYJKoZIhvcNAQkEMSIEILzUnzKmXWBKrQlvDVLEN7jKip0acKEJGeoLY0RR
# WuDXMA0GCSqGSIb3DQEBAQUABIIBgGFztWmjEqwoC1E/Tbnt1reX6Usgty7XiyD9
# owRBBzFccXzqI29iJfQhxF0wxlkvHKgy7hepG9997Q5V8Jgp5LcEDNhbwaTaQvhX
# Ws7/6QTZ4W89gw4c/MtaTTOjXj4MX3mJjISzBRf8NaXTByhdZTFdkBpUac072Y9/
# idKnPaFCZx5s1c2xhhLU6uQQP9l8IvOkDXV9LHrefKettY+PA71spHW8m/nP/ceh
# hEjWutFH5V+Eudk2yR+LDjK9pGd9uJO661mHYUCs1YQa5plhsNW3qzJS0LcB8uxV
# H1zqrphnIc/gronq6Ojr5xS8HgKIT9hmqKJg6uylC4sGJsApvgAF/EGiMFY5XN39
# 4b6yZ2V21O8bId0kAbNPgWiH5qGF/EepaxBYtONj5q8FjL9qfm/wFKFXOVgLZOtq
# Wc2uQv0Jt7zTHdgMmYLaPJI2oF7ONYl92Q0zUbMrkto8CN3VjMG9HjL5WGTgPoEO
# E6YQDhR7UR/5XSWOIA48f2zvXhg/NaGCGBEwghgNBgorBgEEAYI3AwMBMYIX/TCC
# F/kGCSqGSIb3DQEHAqCCF+owghfmAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFiBgsq
# hkiG9w0BCRABBKCCAVEEggFNMIIBSQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl
# AwQCAQUABCAs+znXOzr6fwIH/4PGAusEBU7GNsYLcLYRPhZP3EcpUgIGaeiBPwq2
# GBMyMDI2MDUyMzAzMDcwMi4xMjFaMASAAgH0oIHhpIHeMIHbMQswCQYDVQQGEwJV
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1l
# cmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046N0QwMC0w
# NUUwLUQ5NDcxNTAzBgNVBAMTLE1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWUgU3Rh
# bXBpbmcgQXV0aG9yaXR5oIIPITCCB4IwggVqoAMCAQICEzMAAAAF5c8P/2YuyYcA
# AAAAAAUwDQYJKoZIhvcNAQEMBQAwdzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1p
# Y3Jvc29mdCBDb3Jwb3JhdGlvbjFIMEYGA1UEAxM/TWljcm9zb2Z0IElkZW50aXR5
# IFZlcmlmaWNhdGlvbiBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDIwMB4X
# DTIwMTExOTIwMzIzMVoXDTM1MTExOTIwNDIzMVowYTELMAkGA1UEBhMCVVMxHjAc
# BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0
# IFB1YmxpYyBSU0EgVGltZXN0YW1waW5nIENBIDIwMjAwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQCefOdSY/3gxZ8FfWO1BiKjHB7X55cz0RMFvWVGR3eR
# wV1wb3+yq0OXDEqhUhxqoNv6iYWKjkMcLhEFxvJAeNcLAyT+XdM5i2CgGPGcb95W
# JLiw7HzLiBKrxmDj1EQB/mG5eEiRBEp7dDGzxKCnTYocDOcRr9KxqHydajmEkzXH
# OeRGwU+7qt8Md5l4bVZrXAhK+WSk5CihNQsWbzT1nRliVDwunuLkX1hyIWXIArCf
# rKM3+RHh+Sq5RZ8aYyik2r8HxT+l2hmRllBvE2Wok6IEaAJanHr24qoqFM9WLeBU
# Sudz+qL51HwDYyIDPSQ3SeHtKog0ZubDk4hELQSxnfVYXdTGncaBnB60QrEuazvc
# ob9n4yR65pUNBCF5qeA4QwYnilBkfnmeAjRN3LVuLr0g0FXkqfYdUmj1fFFhH8k8
# YBozrEaXnsSL3kdTD01X+4LfIWOuFzTzuoslBrBILfHNj8RfOxPgjuwNvE6YzauX
# i4orp4Sm6tF245DaFOSYbWFK5ZgG6cUY2/bUq3g3bQAqZt65KcaewEJ3ZyNEobv3
# 5Nf6xN6FrA6jF9447+NHvCjeWLCQZ3M8lgeCcnnhTFtyQX3XgCoc6IRXvFOcPVrr
# 3D9RPHCMS6Ckg8wggTrtIVnY8yjbvGOUsAdZbeXUIQAWMs0d3cRDv09SvwVRd61e
# vQIDAQABo4ICGzCCAhcwDgYDVR0PAQH/BAQDAgGGMBAGCSsGAQQBgjcVAQQDAgEA
# MB0GA1UdDgQWBBRraSg6NS9IY0DPe9ivSek+2T3bITBUBgNVHSAETTBLMEkGBFUd
# IAAwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9w
# cy9Eb2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsG
# AQQBgjcUAgQMHgoAUwB1AGIAQwBBMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgw
# FoAUyH7SaoUqG8oZmAQHJ89QEE9oqKIwgYQGA1UdHwR9MHsweaB3oHWGc2h0dHA6
# Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMElkZW50
# aXR5JTIwVmVyaWZpY2F0aW9uJTIwUm9vdCUyMENlcnRpZmljYXRlJTIwQXV0aG9y
# aXR5JTIwMjAyMC5jcmwwgZQGCCsGAQUFBwEBBIGHMIGEMIGBBggrBgEFBQcwAoZ1
# aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQl
# MjBJZGVudGl0eSUyMFZlcmlmaWNhdGlvbiUyMFJvb3QlMjBDZXJ0aWZpY2F0ZSUy
# MEF1dGhvcml0eSUyMDIwMjAuY3J0MA0GCSqGSIb3DQEBDAUAA4ICAQBfiHbHfm21
# WhV150x4aPpO4dhEmSUVpbixNDmv6TvuIHv1xIs174bNGO/ilWMm+Jx5boAXrJxa
# gRhHQtiFprSjMktTliL4sKZyt2i+SXncM23gRezzsoOiBhv14YSd1Klnlkzvgs29
# XNjT+c8hIfPRe9rvVCMPiH7zPZcw5nNjthDQ+zD563I1nUJ6y59TbXWsuyUsqw7w
# XZoGzZwijWT5oc6GvD3HDokJY401uhnj3ubBhbkR83RbfMvmzdp3he2bvIUztSOu
# FzRqrLfEvsPkVHYnvH1wtYyrt5vShiKheGpXa2AWpsod4OJyT4/y0dggWi8g/tgb
# hmQlZqDUf3UqUQsZaLdIu/XSjgoZqDjamzCPJtOLi2hBwL+KsCh0Nbwc21f5xvPS
# wym0Ukr4o5sCcMUcSy6TEP7uMV8RX0eH/4JLEpGyae6Ki8JYg5v4fsNGif1OXHJ2
# IWG+7zyjTDfkmQ1snFOTgyEX8qBpefQbF0fx6URrYiarjmBprwP6ZObwtZXJ23jK
# 3Fg/9uqM3j0P01nzVygTppBabzxPAh/hHhhls6kwo3QLJ6No803jUsZcd4JQxiYH
# Hc+Q/wAMcPUnYKv/q2O444LO1+n6j01z5mggCSlRwD9faBIySAcA9S8h22hIAcRQ
# qIGEjolCK9F6nK9ZyX4lhthsGHumaABdWzCCB5cwggV/oAMCAQICEzMAAABV2d1p
# Jij5+OIAAAAAAFUwDQYJKoZIhvcNAQEMBQAwYTELMAkGA1UEBhMCVVMxHjAcBgNV
# BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1
# YmxpYyBSU0EgVGltZXN0YW1waW5nIENBIDIwMjAwHhcNMjUxMDIzMjA0NjQ5WhcN
# MjYxMDIyMjA0NjQ5WjCB2zELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0
# b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh
# dGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUG
# A1UECxMeblNoaWVsZCBUU1MgRVNOOjdEMDAtMDVFMC1EOTQ3MTUwMwYDVQQDEyxN
# aWNyb3NvZnQgUHVibGljIFJTQSBUaW1lIFN0YW1waW5nIEF1dGhvcml0eTCCAiIw
# DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL25H5IeWUiz9DAlFmn2sPymaFWb
# vYkMfK+ScIWb3a1IvOlIwghUDjY0Gp6yMRhfYURiGS0GedIB6ywvuH6VBCX3+bdO
# FcAclgtv21jrpOjZmk4fSaT2Q3BszUfeUJa8o3xI7ZfoMY9dszTxHQAz6ZVX87fH
# GEVhQcfxW33IdPJOj/ae419qtYxT21MVmCfsTshgtWioQxmOW/vMC9/b+qgtBxSM
# f798vm3qfmhF6KCvFaHlivrM32hY16PGE3L0PFC+LM7vRxU7mTb+r76CeybvqOWk
# 4+dbKYftPhV1t/E5S/6wwXeYmu/Y7JC7Tnh2w45G5Y4pcM3oHMb/YuPRdOWa0v+R
# C2QgmNVWqjuxDiylWscXQDuaMtb29AcdGUVV9ZsRY2M2sthAtOdZOshiR5ufMtaH
# tiCkWv0jNfgUxrHurxzYuUNneWZ6EfQDgFAw8CSCKkSOK2c9jEop4ddVq10xvbqx
# drqMneVXvvIcXrPQAXj9j2ECpV2EwMb3Wnmpw00P78JpzPsk3Fs61ZvOGd/F1RcO
# Bu6f2TWdp7HL7+rq7tgHr13MldbfIWu4lpoYYE1gTQa1Yrg5XN4j7zs9klT2z3qo
# cmPzV8DWQgIHNh+aTs7bujMEMQyI7Xt1zPxZCgcR6H0tmmzU/9BxvsWbRalCQ2sY
# GyWupTdc4e7KY7kPAgMBAAGjggHLMIIBxzAdBgNVHQ4EFgQUVgRfEG3cCAPwyL+p
# yRbKwdesZbYwHwYDVR0jBBgwFoAUa2koOjUvSGNAz3vYr0npPtk92yEwbAYDVR0f
# BGUwYzBhoF+gXYZbaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwv
# TWljcm9zb2Z0JTIwUHVibGljJTIwUlNBJTIwVGltZXN0YW1waW5nJTIwQ0ElMjAy
# MDIwLmNybDB5BggrBgEFBQcBAQRtMGswaQYIKwYBBQUHMAKGXWh0dHA6Ly93d3cu
# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwUHVibGljJTIw
# UlNBJTIwVGltZXN0YW1waW5nJTIwQ0ElMjAyMDIwLmNydDAMBgNVHRMBAf8EAjAA
# MBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDBmBgNVHSAE
# XzBdMFEGDCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1p
# Y3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wCAYGZ4EMAQQC
# MA0GCSqGSIb3DQEBDAUAA4ICAQBSHuGSVHvalCnFnlsqXIQefH1xP2SFr9g+Vz+f
# 5P7QeywjfQb5jUlSmd1XnJUDPe/MHxL7r3TEElL+mNtG6CDPAytStSFPXD9tTBtB
# MYh8Wqo64pH9qm361yIqeBH979mzWCkMQsTd0nM6dUl9B+7qiti+ToXwxIl39eYq
# LuYYfhD2mqqePXMzUKSQzkf73yYIVHP6nLJQz4aAmaWcfG9jg78sBkDV8KpW7Jgk
# tuLhphJEN1B+SVHjenPdcmrFXIUu/K4jK5ukfWaQIjuaXzSjBlNjC5tQN6adPfA3
# GxUwHPeR4ekL5If/9vBf13tmzBW+gy+0sNGTveb9IL9GU8iX8UvywsX62nhCCPRU
# hTigDBKdczRUrNrntBhowbfchBDFML8avRMRc9Gmc2JvIryX336SFQ51//q1UU2H
# MSJEMhWLJSIWJVhfUowsOa+PampIzETYfFvTu2mqKJUlWZXkGYxrdCvCczJcqeoa
# dpW1ul6kcdnDh228SQ8ZhDc6IRlM4iNd5SNoNgX+aom3wuGyjUaSaPZWxPB1G2NK
# iYhPLt0lPHg0Gskj1zhISY8UQkMMDr3o2JgRuT+wnJEDQUp55ddvhSkSoD6I9DL/
# s+TjIY/c9jLaW5xywJHqdKHUApRMsghv7kebSua1upmR+TquelFktDSOjVdSRkuy
# a4uoxTGCB0Mwggc/AgEBMHgwYTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0Eg
# VGltZXN0YW1waW5nIENBIDIwMjACEzMAAABV2d1pJij5+OIAAAAAAFUwDQYJYIZI
# AWUDBAIBBQCgggScMBEGCyqGSIb3DQEJEAIPMQIFADAaBgkqhkiG9w0BCQMxDQYL
# KoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI2MDUyMzAzMDcwMlowLwYJKoZI
# hvcNAQkEMSIEIA7uscZhU5nw1CDFPhadvAawyE5opXI0tr2sG5rgiEdcMIG5Bgsq
# hkiG9w0BCRACLzGBqTCBpjCBozCBoAQg2Lk8l2SGYru/ff7+D2qrJnkswcYdK6pG
# Ku7GGGr4/s0wfDBlpGMwYTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29m
# dCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGlt
# ZXN0YW1waW5nIENBIDIwMjACEzMAAABV2d1pJij5+OIAAAAAAFUwggNeBgsqhkiG
# 9w0BCRACEjGCA00wggNJoYIDRTCCA0EwggIpAgEBMIIBCaGB4aSB3jCB2zELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9z
# b2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNO
# OjdEMDAtMDVFMC1EOTQ3MTUwMwYDVQQDEyxNaWNyb3NvZnQgUHVibGljIFJTQSBU
# aW1lIFN0YW1waW5nIEF1dGhvcml0eaIjCgEBMAcGBSsOAwIaAxUAHTtUAYJlv7bg
# WVeRBo4X7FeHDeqgZzBlpGMwYTELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0Eg
# VGltZXN0YW1waW5nIENBIDIwMjAwDQYJKoZIhvcNAQELBQACBQDtuzUwMCIYDzIw
# MjYwNTIyMjAwNDAwWhgPMjAyNjA1MjMyMDA0MDBaMHQwOgYKKwYBBAGEWQoEATEs
# MCowCgIFAO27NTACAQAwBwIBAAICGHcwBwIBAAICErgwCgIFAO28hrACAQAwNgYK
# KwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoDAqAKMAgCAQACAwehIKEKMAgCAQAC
# AwGGoDANBgkqhkiG9w0BAQsFAAOCAQEAbBmjkAE+36J5CJp24JpY0PU8rfLXYOs+
# EYEqvNojdE9645WYDnpz3n6YQz03isy2cdwkk4Bto+7UcFVFDrJQzoSrSyt7rruY
# +Qb39SefpkZYfO6Wy48XKKVXnKtfqYjWgI0MBZquogiS0PDDkWq5YgVYYtLwGVRr
# 3v4gOE/nH1wRzX9nxTM187hVtEdJPFYPuXrK+nBvdG9jz4xGdZlBciI2I3dP5Tbv
# wBa9AaxVDa7alGjaWmPu7JzzAE4paORz0k3nerXs6z/SVz5imgGMO/L8y7xXx+f0
# SbeXOCQCHmxunOI0RbzXag/80quDzrZ/buP9/P5roqEPWcn0tX5mCjANBgkqhkiG
# 9w0BAQEFAASCAgC6EolYA/QOIOEXXNAMl33zuNH/sBJqO7LQlib2k+WA1sZ6PiQh
# 4RaQFZ0z1JghSwWrlYQAJ3d3lLx0jMHggSKjCpqjS15RW//xYhoBFDh74p7+d3HY
# ovo+fKxuGUqlaCUYjskRbQ1b6quP8qQZB+3YZAP3Yyzoo5UjVsA2cz4agd813Icr
# j7JX12fI2Zj6oUQuyHNLNopmbjBD3465O9Jg5qCjiD2S+5VE5Nq4EVCmCMhGNnfj
# ldsFOoFnOuXGZ+uP+7jnh9/X6drD2SUZYrVyYEnH2TMs0y6WK3LEi+2hp8nBvuuk
# foeJDUoQfchQcpCLWu/4tK67x/O4YnluBm9joieadzWZYZ3vhcgHGZmGbYhmN3AE
# 9McZ9nSo2eIiABwPFENWmgX93IHmn/lYSLL4lB7y5EWu6vQT/a1JBjNowSqgoZiM
# KdsLRFYZZS92gSONjiQVair2EMV/nbI3KxzRAFieFO9dFzrG4mDckESf5TnvQfto
# 4OijASPTGBGpuDaWP6qWEJKwUYloTXlxL/6sh7cdfIUlXmE3EouhoI4y4xBU/ZNK
# mxwA0FADPXt0xdlduXO5Tzs0FOQpiMcuRt5YD4uF1cUcdmfh1CEhdwxzNYRxNXFW
# Onkk9oGw9+Y6nUnNc9wBk/BjNAh6exM9GnOlgFg3rI3egT0opdoCAxH3Ng==
# SIG # End signature block