tools/PSScriptAnalyzer/PSAction1.AnalyzerRules.psm1

# Action1 Public Repository Material
# Subject to TERMS_OF_USE.md (https://github.com/Action1Corp/PSAction1/blob/main/TERMS_OF_USE.md)
# Provided AS IS
# Use at your own risk
# Review and test before production deployment
# © Action1 Corporation

Set-StrictMode -Version 2.0

. (Join-Path -Path $PSScriptRoot -ChildPath 'Action1.PowerShellHeader.ps1')
. (Join-Path -Path $PSScriptRoot -ChildPath 'Action1.ApprovedNounWords.ps1')

$script:PSAction1RepositoryRoot = Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent

$script:PSAction1ApprovedVerbs = @{}
Get-Verb | ForEach-Object {
    $script:PSAction1ApprovedVerbs[$_.Verb] = $true
}

$script:PSAction1HeaderSearchLineCount = 25

function New-PSAction1DiagnosticRecord {
    param(
        [Parameter(Mandatory = $true)]
        [string] $Message,

        [Parameter(Mandatory = $true)]
        [System.Management.Automation.Language.IScriptExtent] $Extent,

        [Parameter(Mandatory = $true)]
        [string] $RuleName
    )

    $severity = [Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticSeverity]::Warning

    New-Object -TypeName Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord `
        -ArgumentList $Message, $Extent, $RuleName, $severity, $null, $null, $null
}

function Get-PSAction1RelativePath {
    param(
        [Parameter(Mandatory = $true)]
        [string] $Path
    )

    $resolvedPath = [System.IO.Path]::GetFullPath($Path)
    $rootPath = [System.IO.Path]::GetFullPath($script:PSAction1RepositoryRoot)
    $rootPath = $rootPath.TrimEnd([char[]] @('\', '/'))

    if (-not $resolvedPath.StartsWith($rootPath, [System.StringComparison]::OrdinalIgnoreCase)) {
        return $resolvedPath
    }

    $relativePath = $resolvedPath.Substring($rootPath.Length)
    $relativePath.TrimStart([char[]] @('\', '/'))
}

function Test-PSAction1HeaderPresence {
    param(
        [AllowNull()]
        [string[]] $Lines
    )

    if ($null -eq $Lines) {
        return $false
    }

    if ($Lines.Count -lt $script:PSAction1RequiredHeaderLines.Count) {
        return $false
    }

    $lastStartIndex = $Lines.Count - $script:PSAction1RequiredHeaderLines.Count

    for ($startIndex = 0; $startIndex -le $lastStartIndex; $startIndex++) {
        $matchesHeader = $true

        for ($offset = 0; $offset -lt $script:PSAction1RequiredHeaderLines.Count; $offset++) {
            $actualLine = $Lines[$startIndex + $offset]
            $expectedLine = $script:PSAction1RequiredHeaderLines[$offset]

            if ($actualLine -cne $expectedLine) {
                $matchesHeader = $false
                break
            }
        }

        if ($matchesHeader) {
            return $true
        }
    }

    $false
}

function Split-PSAction1NounWord {
    param(
        [AllowNull()]
        [string] $Noun
    )

    if ([string]::IsNullOrWhiteSpace($Noun)) {
        return @()
    }

    $wordMatches = [regex]::Matches($Noun, 'Action1|[A-Z]+(?=[A-Z][a-z]|\d|$)|[A-Z]?[a-z]+|\d+')
    $words = @()

    foreach ($wordMatch in $wordMatches) {
        $words += $wordMatch.Value
    }

    $words
}

function Test-PSAction1PascalCaseNoun {
    param(
        [Parameter(Mandatory = $true)]
        [string] $Noun
    )

    if ($Noun -cnotmatch '^[A-Z][A-Za-z0-9]*$') {
        return $false
    }

    $words = @(Split-PSAction1NounWord -Noun $Noun)

    if ($words.Count -eq 0) {
        return $false
    }

    (($words -join '') -ceq $Noun)
}

function Get-PSAction1NounProofingIssue {
    param(
        [Parameter(Mandatory = $true)]
        [string] $Noun
    )

    $words = @(Split-PSAction1NounWord -Noun $Noun)

    foreach ($word in $words) {
        if (-not $script:PSAction1ApprovedNounWords.ContainsKey($word)) {
            [pscustomobject] @{
                Message = "Noun word '$word' is not in the PSAction1 approved noun-word dictionary."
            }
        }
    }
}

function Measure-PSAction1Header {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [System.Management.Automation.Language.ScriptBlockAst] $ScriptBlockAst
    )

    $scriptPath = $ScriptBlockAst.Extent.File

    if ([string]::IsNullOrWhiteSpace($scriptPath)) {
        return
    }

    if ($ScriptBlockAst.Extent.StartLineNumber -ne 1) {
        return
    }

    $relativePath = Get-PSAction1RelativePath -Path $scriptPath

    if ($relativePath -eq $scriptPath) {
        return
    }

    $extension = [System.IO.Path]::GetExtension($scriptPath)
    $checkedExtensions = @('.ps1', '.psm1', '.psd1')

    if ($checkedExtensions -notcontains $extension) {
        return
    }

    try {
        $headerLines = Get-Content `
            -LiteralPath $scriptPath `
            -TotalCount $script:PSAction1HeaderSearchLineCount `
            -ErrorAction Stop
    }
    catch {
        $message = "Unable to read '$relativePath' while checking the Action1 header. "
        $message += $_.Exception.Message

        New-PSAction1DiagnosticRecord `
            -Message $message `
            -Extent $ScriptBlockAst.Extent `
            -RuleName $PSCmdlet.MyInvocation.InvocationName
        return
    }

    if (Test-PSAction1HeaderPresence -Lines $headerLines) {
        return
    }

    New-PSAction1DiagnosticRecord `
        -Message "File '$relativePath' must include the standard Action1 header near the top." `
        -Extent $ScriptBlockAst.Extent `
        -RuleName $PSCmdlet.MyInvocation.InvocationName
}

function Measure-PSAction1CmdletName {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [System.Management.Automation.Language.ScriptBlockAst] $ScriptBlockAst
    )

    $scriptPath = $ScriptBlockAst.Extent.File

    if ([string]::IsNullOrWhiteSpace($scriptPath)) {
        return
    }

    $relativePath = Get-PSAction1RelativePath -Path $scriptPath
    $isPublic = $relativePath -match '^Public[\\/]'
    $isPrivate = $relativePath -match '^Private[\\/]'

    if (-not ($isPublic -or $isPrivate)) {
        return
    }

    $ruleName = $PSCmdlet.MyInvocation.InvocationName
    $functionAsts = $ScriptBlockAst.FindAll({
            param($ast)

            $ast -is [System.Management.Automation.Language.FunctionDefinitionAst]
        }, $true)

    foreach ($functionAst in $functionAsts) {
        $functionName = $functionAst.Name

        if ($functionName -notmatch '^([A-Za-z][A-Za-z0-9]*)-([A-Za-z][A-Za-z0-9]*)$') {
            New-PSAction1DiagnosticRecord `
                -Message "Function '$functionName' must use Verb-Noun naming." `
                -Extent $functionAst.Extent `
                -RuleName $ruleName
            continue
        }

        $verb = $Matches[1]
        $noun = $Matches[2]

        if (-not $script:PSAction1ApprovedVerbs.ContainsKey($verb)) {
            New-PSAction1DiagnosticRecord `
                -Message "Function '$functionName' uses unapproved PowerShell verb '$verb'." `
                -Extent $functionAst.Extent `
                -RuleName $ruleName
        }

        if ($isPublic -and -not $noun.StartsWith('Action1', [System.StringComparison]::Ordinal)) {
            New-PSAction1DiagnosticRecord `
                -Message "Public cmdlet '$functionName' must use the Verb-Action1... naming pattern." `
                -Extent $functionAst.Extent `
                -RuleName $ruleName
        }

        if (-not (Test-PSAction1PascalCaseNoun -Noun $noun)) {
            New-PSAction1DiagnosticRecord `
                -Message "Function '$functionName' must use PascalCase in the noun part." `
                -Extent $functionAst.Extent `
                -RuleName $ruleName
        }

        $proofingIssues = @(Get-PSAction1NounProofingIssue -Noun $noun)

        foreach ($proofingIssue in $proofingIssues) {
            New-PSAction1DiagnosticRecord `
                -Message "Function '$functionName': $($proofingIssue.Message)" `
                -Extent $functionAst.Extent `
                -RuleName $ruleName
        }
    }
}

Export-ModuleMember -Function Measure-PSAction1CmdletName, Measure-PSAction1Header

# SIG # Begin signature block
# MII9MQYJKoZIhvcNAQcCoII9IjCCPR4CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCgrtnco+XodrKX
# fhZhKqYoI84pUECaqNQsxFe7lB9ay6CCIfYwggXMMIIDtKADAgECAhBUmNLR1FsZ
# 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
# 03u4aUoqlmZpxJTG9F9urJh4iIAGXKKy7aIwggaoMIIEkKADAgECAhMzAAMg1FN7
# z5V+A7MkAAAAAyDUMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ
# RCBWZXJpZmllZCBDUyBBT0MgQ0EgMDQwHhcNMjYwNzEzMTUzOTA0WhcNMjYwNzE2
# MTUzOTA0WjBrMQswCQYDVQQGEwJVUzEOMAwGA1UECBMFVGV4YXMxEDAOBgNVBAcT
# B0hvdXN0b24xHDAaBgNVBAoTE0FjdGlvbjEgQ29ycG9yYXRpb24xHDAaBgNVBAMT
# E0FjdGlvbjEgQ29ycG9yYXRpb24wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGK
# AoIBgQCNwDAs5op7APk5uUPYAgbRb2tJNxYsx8JY4aZXu/0qaJJkt3lUJQaCozB7
# ap0g75oMnpmFDCqWbJ9qr0iAddS4niPr6dACq7MtV5VcLDUd/kyl6MEK/jmKODYs
# 7gSoIoq64WZ5gfIjoDCBJP0OpQu2KDP4G5ActlSq/vvAGocmrW8Q8sNPvdEQVLWn
# N3EG7sYZLDpNgdysnufYuMrBVCkmYVLG3T0/JWDIpxyRCVyEv/bH2x++cPb5LC2O
# Ksek8AeW1YXumt2o/ULc2JcIQ6WG/eWgb1vFqSTFT/GntmNUFiKckHI6fiG5ZC4a
# n014W5fCxi8f/xLH5QqVQN5ewk3rVUkf924MIDyBrcH/Zng3dafzM7AGTfBKJjK1
# qGlOZtP6y2BU7CnbTNOmJVCvVM/v4AbMWgh2dcEk6/hlFAN5Tdk/x4wlRsQWRnY/
# 8QPohB2EIRhri3b9g6E1eeY5EkoKORo4OgRWqp6FrTtwh19B3CcDJhg3pnGhTxOI
# PO+CnQMCAwEAAaOCAdQwggHQMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeA
# MDsGA1UdJQQ0MDIGCisGAQQBgjdhAQAGCCsGAQUFBwMDBhorBgEEAYI3YYTGyjWC
# 84fIeoPTzfIboMPaLTAdBgNVHQ4EFgQU4vhJ3Va1KwhpAtZ1EwPqRKGO4j0wHwYD
# VR0jBBgwFoAUayVB3vtrfP0YgAotf492XapzPbgwZwYDVR0fBGAwXjBcoFqgWIZW
# aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIw
# SUQlMjBWZXJpZmllZCUyMENTJTIwQU9DJTIwQ0ElMjAwNC5jcmwwdAYIKwYBBQUH
# AQEEaDBmMGQGCCsGAQUFBzAChlhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp
# b3BzL2NlcnRzL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDUyUyMEFPQyUy
# MENBJTIwMDQuY3J0MFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNo
# dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5o
# dG0wDQYJKoZIhvcNAQEMBQADggIBALaZZMk3OyXrNvHsvv48nfr5zh4J6JnFjeUz
# exIz/FeozYnx7jei51lRo9ImEN8rdmdro4CZhBNKfldByTfXI7bpNXiD2CxWNh5A
# LzQYZsiNAiXsZ+hTSb/7bL7ya3zefMWg2Axe+cUboYUgK5V39VcjGQL3eMQC2UhG
# lWpRvVGe3CM5O1vImYZgJSuydxaVKRcIgfU6pcxhQxClsqGmWT9DHVomUWinD1Sf
# vTNr4FrXtQPtK+uj2uMp1Shlg1X64MnTugLextlfuj+KNg9mQexuzbRirFJzgmAb
# 18tV6Yd85H+/nEDBreRlr3VHsSLKlPgUxyWr5pTVC5jc5Pp/22BXUqd0RV9BmR18
# iqKc5g6bGon6+WCAeqMpH6cX5I6UX47VEU28LL34PlYx+IEB6bqs3lAQRDmF1Rdc
# U3u7zTFGKD6wpKNFY7ygw7snAzNvHlb/Q7M9oVE0/Cvh0VXeMM8AwYfEhnBTTmS9
# kN/FZBmjlOews5BY2Qhm4nMzrrNnLrkvbJUoBDSRBJOpLamVCnSILp0YtzwbTH+V
# 892d9OdgnQ3tDmW0QLRz05nkgbhnQC5FjGQK7KIc8A3ZQsDPdE0trsycaS1i4CDC
# RUi7UIsIVjJW7JPtimo78OE2B7xztH4fI1KtIwBS+fZy4KqmkT4PJMrMJZtM//1D
# g5dnVynnMIIGqDCCBJCgAwIBAgITMwADINRTe8+VfgOzJAAAAAMg1DANBgkqhkiG
# 9w0BAQwFADBaMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
# cmF0aW9uMSswKQYDVQQDEyJNaWNyb3NvZnQgSUQgVmVyaWZpZWQgQ1MgQU9DIENB
# IDA0MB4XDTI2MDcxMzE1MzkwNFoXDTI2MDcxNjE1MzkwNFowazELMAkGA1UEBhMC
# VVMxDjAMBgNVBAgTBVRleGFzMRAwDgYDVQQHEwdIb3VzdG9uMRwwGgYDVQQKExNB
# Y3Rpb24xIENvcnBvcmF0aW9uMRwwGgYDVQQDExNBY3Rpb24xIENvcnBvcmF0aW9u
# MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAjcAwLOaKewD5OblD2AIG
# 0W9rSTcWLMfCWOGmV7v9KmiSZLd5VCUGgqMwe2qdIO+aDJ6ZhQwqlmyfaq9IgHXU
# uJ4j6+nQAquzLVeVXCw1Hf5MpejBCv45ijg2LO4EqCKKuuFmeYHyI6AwgST9DqUL
# tigz+BuQHLZUqv77wBqHJq1vEPLDT73REFS1pzdxBu7GGSw6TYHcrJ7n2LjKwVQp
# JmFSxt09PyVgyKcckQlchL/2x9sfvnD2+SwtjirHpPAHltWF7prdqP1C3NiXCEOl
# hv3loG9bxakkxU/xp7ZjVBYinJByOn4huWQuGp9NeFuXwsYvH/8Sx+UKlUDeXsJN
# 61VJH/duDCA8ga3B/2Z4N3Wn8zOwBk3wSiYytahpTmbT+stgVOwp20zTpiVQr1TP
# 7+AGzFoIdnXBJOv4ZRQDeU3ZP8eMJUbEFkZ2P/ED6IQdhCEYa4t2/YOhNXnmORJK
# CjkaODoEVqqeha07cIdfQdwnAyYYN6ZxoU8TiDzvgp0DAgMBAAGjggHUMIIB0DAM
# BgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDA7BgNVHSUENDAyBgorBgEEAYI3
# YQEABggrBgEFBQcDAwYaKwYBBAGCN2GExso1gvOHyHqD083yG6DD2i0wHQYDVR0O
# BBYEFOL4Sd1WtSsIaQLWdRMD6kShjuI9MB8GA1UdIwQYMBaAFGslQd77a3z9GIAK
# LX+Pdl2qcz24MGcGA1UdHwRgMF4wXKBaoFiGVmh0dHA6Ly93d3cubWljcm9zb2Z0
# LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDUyUy
# MEFPQyUyMENBJTIwMDQuY3JsMHQGCCsGAQUFBwEBBGgwZjBkBggrBgEFBQcwAoZY
# aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQl
# MjBJRCUyMFZlcmlmaWVkJTIwQ1MlMjBBT0MlMjBDQSUyMDA0LmNydDBUBgNVHSAE
# TTBLMEkGBFUdIAAwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQu
# Y29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMA0GCSqGSIb3DQEBDAUAA4IC
# AQC2mWTJNzsl6zbx7L7+PJ36+c4eCeiZxY3lM3sSM/xXqM2J8e43oudZUaPSJhDf
# K3Zna6OAmYQTSn5XQck31yO26TV4g9gsVjYeQC80GGbIjQIl7GfoU0m/+2y+8mt8
# 3nzFoNgMXvnFG6GFICuVd/VXIxkC93jEAtlIRpVqUb1RntwjOTtbyJmGYCUrsncW
# lSkXCIH1OqXMYUMQpbKhplk/Qx1aJlFopw9Un70za+Ba17UD7Svro9rjKdUoZYNV
# +uDJ07oC3sbZX7o/ijYPZkHsbs20YqxSc4JgG9fLVemHfOR/v5xAwa3kZa91R7Ei
# ypT4FMclq+aU1QuY3OT6f9tgV1KndEVfQZkdfIqinOYOmxqJ+vlggHqjKR+nF+SO
# lF+O1RFNvCy9+D5WMfiBAem6rN5QEEQ5hdUXXFN7u80xRig+sKSjRWO8oMO7JwMz
# bx5W/0OzPaFRNPwr4dFV3jDPAMGHxIZwU05kvZDfxWQZo5TnsLOQWNkIZuJzM66z
# Zy65L2yVKAQ0kQSTqS2plQp0iC6dGLc8G0x/lfPdnfTnYJ0N7Q5ltEC0c9OZ5IG4
# Z0AuRYxkCuyiHPAN2ULAz3RNLa7MnGktYuAgwkVIu1CLCFYyVuyT7YpqO/DhNge8
# c7R+HyNSrSMAUvn2cuCqppE+DyTKzCWbTP/9Q4OXZ1cp5zCCBygwggUQoAMCAQIC
# EzMAAAAWMZKNkgJle5oAAAAAABYwDQYJKoZIhvcNAQEMBQAwYzELMAkGA1UEBhMC
# VVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE0MDIGA1UEAxMrTWlj
# cm9zb2Z0IElEIFZlcmlmaWVkIENvZGUgU2lnbmluZyBQQ0EgMjAyMTAeFw0yNjAz
# MjYxODExMjlaFw0zMTAzMjYxODExMjlaMFoxCzAJBgNVBAYTAlVTMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJRCBW
# ZXJpZmllZCBDUyBBT0MgQ0EgMDQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
# AoICAQDKVfrI2+gJMM/0bQ5OVKNdvOASzLbUUMvXuf+Vl7YGuofPaZHVo3gMHF5i
# nT+GMSpIcfIZ9qtXU1UG68ry8vNbQtOL4Nm30ifXpqI1+ByiAWLO1YT0WnzG7XPO
# uoTeeWsNZv5FmjxCsReBZvyzyzCyXZbu1EQfJxWTH4ebUwtAiW9rqMf9eDj/wYhi
# EfNteJV3ZFeibD2ztCHr9JhFdd97XbnCHgQoTIqc02X5xlRKtUGBa++OtHBBjiJ/
# uwBnzTkqu4FjpZjQeJtrmda+ur1CT2jflWIB/ypn7u7V9tvW9wJbJYt/H2EtJ0GO
# NWxJZ7TEu8jWPindOO3lzPP7UtzS/mVDV94HucWaltmsra6zSG8BoEJ87IM8QSb7
# vfm/O41FhYkUv89WIj5ES2O4kxyiMSfe95CMivCuYrRP2hKvx7egPMrWgDDBkxML
# grKZO9hRNUMm8vk3w5b9SogHOyJVhxyFm8aFXfIxgqDF4S0g4bhbhnzljmSlCLlu
# mMZcXFGDjpF2tNoAu3VGFGYtHtTSNVKvZpgB3b4ynaoDkbPf+Wg4523jt4VneasB
# gZhC1srZI2NCnCBBfgjLq04pqEKAWEohyW2K29KSkkHvt5VaE1ac3Yt+oyiOzMS5
# 7tXwQDJLGvLg/OXFO0VNvczDndfIfXYExB/ab2PuMSwd5VIBOwIDAQABo4IB3DCC
# AdgwDgYDVR0PAQH/BAQDAgGGMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRr
# JUHe+2t8/RiACi1/j3ZdqnM9uDBUBgNVHSAETTBLMEkGBFUdIAAwQTA/BggrBgEF
# BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9z
# aXRvcnkuaHRtMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMBIGA1UdEwEB/wQI
# MAYBAf8CAQAwHwYDVR0jBBgwFoAU2UEpsA8PY2zvadf1zSmepEhqMOYwcAYDVR0f
# BGkwZzBloGOgYYZfaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwv
# TWljcm9zb2Z0JTIwSUQlMjBWZXJpZmllZCUyMENvZGUlMjBTaWduaW5nJTIwUENB
# JTIwMjAyMS5jcmwwfQYIKwYBBQUHAQEEcTBvMG0GCCsGAQUFBzAChmFodHRwOi8v
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMElEJTIw
# VmVyaWZpZWQlMjBDb2RlJTIwU2lnbmluZyUyMFBDQSUyMDIwMjEuY3J0MA0GCSqG
# SIb3DQEBDAUAA4ICAQAG1VBeVHTVRBljlcZD3IiMxwPyMjQyLNaEnVu5mODm2hRB
# JfH8GsBLATmrHAc8F47jmk5CnpUPiIguCbw6Z/KVj4Dsoiq228NSLMLewFfGMri7
# uwNGLISC5ccp8vUdADDEIsS2dE+QI9OwkDpv3XuUD7d+hAgcLVcMOl1AsfEZtsZe
# nhGvSYUrm/FuLq0BqEGL9GXM5c+Ho9q8o+Vn/S+GWQN2y+gkRO15s0kI05nUpq/d
# OD4ri9rgVs6tipEd0YZqGgD+CZNiaZWrDTOQbNPncd2F9qOsUa20miYruoT5PwJA
# aI+QQiTE2ZJeMJOkOpzhTUgqVMZwZidEUZKCqudaeQA08WwnkQMfKyHzaU8j48UL
# cU4hUwvMsv7fSurOe9GAdRQCPvF8WcSK5oDHe8VVJM4tv6KKCm91HqLx9JamBgRI
# 6R2SfY3nu26EGznu0rCg/769z8xWm4PVcC2ZaL6VlKVqFp1NsN8YqMyf5t+bbGVb
# 09noFKcJG/UwyGlxRmQBlfeBUQx5/ytlzZzsEnhrJF9fTAfje8j3OdX5lEnePTFQ
# LRlvzZFBqUXnIeQKv3fHQjC9m2fo/Z01DII/qp3d8LhGVUW0BCG04fRwHJNH8iqq
# CG/qofMv+kym2AxBDnHzNgRjL60JOFiBgiurvLhYQNhB95KWojFA6shQnggkMTCC
# B54wggWGoAMCAQICEzMAAAAHh6M0o3uljhwAAAAAAAcwDQYJKoZIhvcNAQEMBQAw
# dzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjFI
# MEYGA1UEAxM/TWljcm9zb2Z0IElkZW50aXR5IFZlcmlmaWNhdGlvbiBSb290IENl
# cnRpZmljYXRlIEF1dGhvcml0eSAyMDIwMB4XDTIxMDQwMTIwMDUyMFoXDTM2MDQw
# MTIwMTUyMFowYzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
# b3JhdGlvbjE0MDIGA1UEAxMrTWljcm9zb2Z0IElEIFZlcmlmaWVkIENvZGUgU2ln
# bmluZyBQQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALLw
# wK8ZiCji3VR6TElsaQhVCbRS/3pK+MHrJSj3Zxd3KU3rlfL3qrZilYKJNqztA9OQ
# acr1AwoNcHbKBLbsQAhBnIB34zxf52bDpIO3NJlfIaTE/xrweLoQ71lzCHkD7A4A
# s1Bs076Iu+mA6cQzsYYH/Cbl1icwQ6C65rU4V9NQhNUwgrx9rGQ//h890Q8JdjLL
# w0nV+ayQ2Fbkd242o9kH82RZsH3HEyqjAB5a8+Ae2nPIPc8sZU6ZE7iRrRZywRmr
# KDp5+TcmJX9MRff241UaOBs4NmHOyke8oU1TYrkxh+YeHgfWo5tTgkoSMoayqoDp
# HOLJs+qG8Tvh8SnifW2Jj3+ii11TS8/FGngEaNAWrbyfNrC69oKpRQXY9bGH6jn9
# NEJv9weFxhTwyvx9OJLXmRGbAUXN1U9nf4lXezky6Uh/cgjkVd6CGUAf0K+Jw+GE
# /5VpIVbcNr9rNE50Sbmy/4RTCEGvOq3GhjITbCa4crCzTTHgYYjHs1NbOc6brH+e
# KpWLtr+bGecy9CrwQyx7S/BfYJ+ozst7+yZtG2wR461uckFu0t+gCwLdN0A6cFtS
# RtR8bvxVFyWwTtgMMFRuBa3vmUOTnfKLsLefRaQcVTgRnzeLzdpt32cdYKp+dhr2
# ogc+qM6K4CBI5/j4VFyC4QFeUP2YAidLtvpXRRo3AgMBAAGjggI1MIICMTAOBgNV
# HQ8BAf8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFNlBKbAPD2Ns
# 72nX9c0pnqRIajDmMFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNo
# dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5o
# dG0wGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDwYDVR0TAQH/BAUwAwEB/zAf
# BgNVHSMEGDAWgBTIftJqhSobyhmYBAcnz1AQT2ioojCBhAYDVR0fBH0wezB5oHeg
# dYZzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0
# JTIwSWRlbnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIwQ2VydGlmaWNhdGUl
# MjBBdXRob3JpdHklMjAyMDIwLmNybDCBwwYIKwYBBQUHAQEEgbYwgbMwgYEGCCsG
# AQUFBzAChnVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01p
# Y3Jvc29mdCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIwUm9vdCUyMENlcnRp
# ZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAyMC5jcnQwLQYIKwYBBQUHMAGGIWh0dHA6
# Ly9vbmVvY3NwLm1pY3Jvc29mdC5jb20vb2NzcDANBgkqhkiG9w0BAQwFAAOCAgEA
# fyUqnv7Uq+rdZgrbVyNMul5skONbhls5fccPlmIbzi+OwVdPQ4H55v7VOInnmezQ
# EeW4LqK0wja+fBznANbXLB0KrdMCbHQpbLvG6UA/Xv2pfpVIE1CRFfNF4XKO8XYE
# a3oW8oVH+KZHgIQRIwAbyFKQ9iyj4aOWeAzwk+f9E5StNp5T8FG7/VEURIVWArbA
# zPt9ThVN3w1fAZkF7+YU9kbq1bCR2YD+MtunSQ1Rft6XG7b4e0ejRA7mB2IoX5hN
# h3UEauY0byxNRG+fT2MCEhQl9g2i2fs6VOG19CNep7SquKaBjhWmirYyANb0RJSL
# WjinMLXNOAga10n8i9jqeprzSMU5ODmrMCJE12xS/NWShg/tuLjAsKP6SzYZ+1Ry
# 358ZTFcx0FS/mx2vSoU8s8HRvy+rnXqyUJ9HBqS0DErVLjQwK8VtsBdekBmdTbQV
# oCgPCqr+PDPB3xajYnzevs7eidBsM71PINK2BoE2UfMwxCCX3mccFgx6UsQeRSdV
# VVNSyALQe6PT12418xon2iDGE81OGCreLzDcMAZnrUAx4XQLUz6ZTl65yPUiOh3k
# 7Yww94lDf+8oG2oZmDh5O1Qe38E+M3vhKwmzIeoB1dVLlz4i3IpaDcR+iuGjH2Td
# aC1ZOmBXiCRKJLj4DT2uhJ04ji+tHD6n58vhavFIrmcxghqRMIIajQIBATBxMFox
# CzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzAp
# BgNVBAMTIk1pY3Jvc29mdCBJRCBWZXJpZmllZCBDUyBBT0MgQ0EgMDQCEzMAAyDU
# U3vPlX4DsyQAAAADINQwDQYJYIZIAWUDBAIBBQCgXjAQBgorBgEEAYI3AgEMMQIw
# ADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAvBgkqhkiG9w0BCQQxIgQgAZ8j
# vIBUvSOvjLIQo/PK9nZqYEG1eKVKzC6nu8o7m/cwDQYJKoZIhvcNAQEBBQAEggGA
# XjANMEvB7+uLAV1UkyGMP1AXsZRPTDAuLwwfEo5irEFpqLTHDU8l2OMdUnW/jpAj
# IAvsZKCq/0jBwAe9DSftuM6k0vAZ4gTD1b84yrzmhP4vaM7i/OQQFvUNUns/fZLa
# dWAQvJNe0neNw7W5qOLkE+zp0/kmfmQchWsjcW4tUbphtnsFx+f1OgVA7pSelihc
# n/KxZmcsR+N3Q+7nLtfIUXBJryZxYYL0qvZW/D1PqfHrmXwAy1hN6NjpXzZeODn+
# FgWULPZWYMM8+2g8wvb3wAaLy8R/rb2T74yrmcVpb3ELVUVhyYfiT8KzBd2BKgAY
# xxcItJo3/FYYrgTV28XeKYlHFg4JLQC+j/Mln1yFuqB3Q8r2eEK9L4VAK3eQ6Y+u
# x0MONfgKdmQjq3DKnE5lgkSWZuUWjkH9zWP50yM/4NZf+LDrTNvTngFx96xD+OAy
# jiCHbYukPD+tEtkyB3h8BBmoD6A+SNpVWWlOydZ2fjGMYLwTzc+4tg/I82lYrNVM
# oYIYETCCGA0GCisGAQQBgjcDAwExghf9MIIX+QYJKoZIhvcNAQcCoIIX6jCCF+YC
# AQMxDzANBglghkgBZQMEAgEFADCCAWIGCyqGSIb3DQEJEAEEoIIBUQSCAU0wggFJ
# AgEBBgorBgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIBBQAEIOdiR6zxiBnUb4RfECUv
# 3V8RU/BJQ43vFNk6Dt9+4p0nAgZqT9WHyX0YEzIwMjYwNzE1MTI1ODEwLjYzNlow
# BIACAfSggeGkgd4wgdsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u
# MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp
# b24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJzAlBgNV
# BAsTHm5TaGllbGQgVFNTIEVTTjpBNTAwLTA1RTAtRDk0NzE1MDMGA1UEAxMsTWlj
# cm9zb2Z0IFB1YmxpYyBSU0EgVGltZSBTdGFtcGluZyBBdXRob3JpdHmggg8hMIIH
# gjCCBWqgAwIBAgITMwAAAAXlzw//Zi7JhwAAAAAABTANBgkqhkiG9w0BAQwFADB3
# MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMUgw
# RgYDVQQDEz9NaWNyb3NvZnQgSWRlbnRpdHkgVmVyaWZpY2F0aW9uIFJvb3QgQ2Vy
# dGlmaWNhdGUgQXV0aG9yaXR5IDIwMjAwHhcNMjAxMTE5MjAzMjMxWhcNMzUxMTE5
# MjA0MjMxWjBhMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
# cmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBp
# bmcgQ0EgMjAyMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJ5851Jj
# /eDFnwV9Y7UGIqMcHtfnlzPREwW9ZUZHd5HBXXBvf7KrQ5cMSqFSHGqg2/qJhYqO
# QxwuEQXG8kB41wsDJP5d0zmLYKAY8Zxv3lYkuLDsfMuIEqvGYOPURAH+Ybl4SJEE
# Snt0MbPEoKdNihwM5xGv0rGofJ1qOYSTNcc55EbBT7uq3wx3mXhtVmtcCEr5ZKTk
# KKE1CxZvNPWdGWJUPC6e4uRfWHIhZcgCsJ+sozf5EeH5KrlFnxpjKKTavwfFP6Xa
# GZGWUG8TZaiTogRoAlqcevbiqioUz1Yt4FRK53P6ovnUfANjIgM9JDdJ4e0qiDRm
# 5sOTiEQtBLGd9Vhd1MadxoGcHrRCsS5rO9yhv2fjJHrmlQ0EIXmp4DhDBieKUGR+
# eZ4CNE3ctW4uvSDQVeSp9h1SaPV8UWEfyTxgGjOsRpeexIveR1MPTVf7gt8hY64X
# NPO6iyUGsEgt8c2PxF87E+CO7A28TpjNq5eLiiunhKbq0XbjkNoU5JhtYUrlmAbp
# xRjb9tSreDdtACpm3rkpxp7AQndnI0Shu/fk1/rE3oWsDqMX3jjv40e8KN5YsJBn
# czyWB4JyeeFMW3JBfdeAKhzohFe8U5w9WuvcP1E8cIxLoKSDzCCBOu0hWdjzKNu8
# Y5SwB1lt5dQhABYyzR3dxEO/T1K/BVF3rV69AgMBAAGjggIbMIICFzAOBgNVHQ8B
# Af8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFGtpKDo1L0hjQM97
# 2K9J6T7ZPdshMFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNodHRw
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0w
# EwYDVR0lBAwwCgYIKwYBBQUHAwgwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEw
# DwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTIftJqhSobyhmYBAcnz1AQT2io
# ojCBhAYDVR0fBH0wezB5oHegdYZzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br
# aW9wcy9jcmwvTWljcm9zb2Z0JTIwSWRlbnRpdHklMjBWZXJpZmljYXRpb24lMjBS
# b290JTIwQ2VydGlmaWNhdGUlMjBBdXRob3JpdHklMjAyMDIwLmNybDCBlAYIKwYB
# BQUHAQEEgYcwgYQwgYEGCCsGAQUFBzAChnVodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMElkZW50aXR5JTIwVmVyaWZpY2F0
# aW9uJTIwUm9vdCUyMENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAyMC5jcnQw
# DQYJKoZIhvcNAQEMBQADggIBAF+Idsd+bbVaFXXnTHho+k7h2ESZJRWluLE0Oa/p
# O+4ge/XEizXvhs0Y7+KVYyb4nHlugBesnFqBGEdC2IWmtKMyS1OWIviwpnK3aL5J
# edwzbeBF7POyg6IGG/XhhJ3UqWeWTO+Czb1c2NP5zyEh89F72u9UIw+IfvM9lzDm
# c2O2END7MPnrcjWdQnrLn1Ntday7JSyrDvBdmgbNnCKNZPmhzoa8PccOiQljjTW6
# GePe5sGFuRHzdFt8y+bN2neF7Zu8hTO1I64XNGqst8S+w+RUdie8fXC1jKu3m9KG
# IqF4aldrYBamyh3g4nJPj/LR2CBaLyD+2BuGZCVmoNR/dSpRCxlot0i79dKOChmo
# ONqbMI8m04uLaEHAv4qwKHQ1vBzbV/nG89LDKbRSSvijmwJwxRxLLpMQ/u4xXxFf
# R4f/gksSkbJp7oqLwliDm/h+w0aJ/U5ccnYhYb7vPKNMN+SZDWycU5ODIRfyoGl5
# 9BsXR/HpRGtiJquOYGmvA/pk5vC1lcnbeMrcWD/26ozePQ/TWfNXKBOmkFpvPE8C
# H+EeGGWzqTCjdAsno2jzTeNSxlx3glDGJgcdz5D/AAxw9Sdgq/+rY7jjgs7X6fqP
# TXPmaCAJKVHAP19oEjJIBwD1LyHbaEgBxFCogYSOiUIr0Xqcr1nJfiWG2GwYe6Zo
# AF1bMIIHlzCCBX+gAwIBAgITMwAAAFZ+j51YCI7pYAAAAAAAVjANBgkqhkiG9w0B
# AQwFADBhMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcg
# Q0EgMjAyMDAeFw0yNTEwMjMyMDQ2NTFaFw0yNjEwMjIyMDQ2NTFaMIHbMQswCQYD
# VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe
# MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3Nv
# ZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046
# QTUwMC0wNUUwLUQ5NDcxNTAzBgNVBAMTLE1pY3Jvc29mdCBQdWJsaWMgUlNBIFRp
# bWUgU3RhbXBpbmcgQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
# CgKCAgEAtKWfm/ul027/d8Rlb8Mn/g0QUvvLqY2Vsy3tI8U2tFSspTZomZOD3BHT
# 8LkR+RrhMJgb1VjAKFNysaK9cLSXifPGSIBrPCgs9P4y24lrJEmrV6Q5z4BmqMhI
# PrZhEvZnWpCS4HO7jYSei/nxmC7/1Er+l5Lg3PmSxb8d2IVcARxSw1B4mxB6XI0n
# kel9wa1dYb2wfGpofraFmxZOxT9eNht4LH0RBSVueba6ZNpjS/0gtfm7qiIiyP6p
# 6PRzTTbMnVqsHnV/d/rW0zHx+Q+QNZ5wUqKmTZJB9hU853+2pX5rDfK32uNY9/WB
# OAmzbqgpEdQkbiMavUMyUDShmycIvgHdQnS207sTj8M+kJL3tOdahPuPqMwsaCCg
# dfwwQx0O9TKe7FSvbAEYs1AnldCl/KHGZCOVvUNqjyL10JLe0/+GD9/ynqXGWFpX
# OjaunvZ/cKROhjN4M5e6xx0b2miqcPii4/ii2ZheKallJET7CKlpFShs3wyg6F/f
# ojQxQvPnbWD4Nyx6lhjWjwmoLcx6w1FSCtavLCly33BLRSlTU4qKUxaa8d7YN7Eq
# pn9XO0SY0umOvKFXrWH7rxl+9iaicitdnTTksAnRjvekdKT3lg7lRMfmfZU8vXNi
# N0UYJzT9EjqjRm0uN/h0oXxPhNfPYqeFbyPXGGxzaYUz6zx3qTcCAwEAAaOCAcsw
# ggHHMB0GA1UdDgQWBBS+tjPyu6tZ/h5GsyLvyz1H+FNIWjAfBgNVHSMEGDAWgBRr
# aSg6NS9IY0DPe9ivSek+2T3bITBsBgNVHR8EZTBjMGGgX6BdhltodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBQdWJsaWMlMjBS
# U0ElMjBUaW1lc3RhbXBpbmclMjBDQSUyMDIwMjAuY3JsMHkGCCsGAQUFBwEBBG0w
# azBpBggrBgEFBQcwAoZdaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j
# ZXJ0cy9NaWNyb3NvZnQlMjBQdWJsaWMlMjBSU0ElMjBUaW1lc3RhbXBpbmclMjBD
# QSUyMDIwMjAuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUH
# AwgwDgYDVR0PAQH/BAQDAgeAMGYGA1UdIARfMF0wUQYMKwYBBAGCN0yDfQEBMEEw
# PwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9j
# cy9SZXBvc2l0b3J5Lmh0bTAIBgZngQwBBAIwDQYJKoZIhvcNAQEMBQADggIBAA4D
# qAXEsO26j/La7Fgn/Qifit8xuZekqZ57+Ye+sH/hRTbEEjGYrZgsqwR/lUUfKCFp
# bZF8msaZPQJOR4YYUEU8XyjLrn8Y1jCSmoxh9l7tWiSoc/JFBw356JAmzGGxeBA2
# EWSxRuTr1AuZe6nYaN8/wtFkiHcs8gMadxXBs6DxVhyu5YnhLPQkfumKm3lFftwE
# 7pieV7f1lskmlgsC6AeSGCzGPZUgCvcH5Tv/Qe9z7bIImSD3SuzhOIwaP+eKQTYf
# 67TifyJKkWQSdGfTA6Kcu41k8LB6oPK+MLk1jbxxK5wPqLSL62xjK04SBXHEJSEn
# sFt0zxWkxP/lgej1DxqUnmrYEdkxvzKSHIAqFWSZul/5hI+vJxvFPhsNQBEk4cSu
# lDkJQpcdVi/gmf/mHFOYhDBjsa15s4L+2sBil3XV/T8RiR66Q8xYvTLRWxd2dVsr
# OoCwnsU4WIeiC0JinCv1WLHEh7Qyzr9RSr4kKJLWdpNYLhgjkojTmEkAjFO774t3
# xB7enbvIF0GOsV19xnCUzq9EGKyt0gMuaphKlNjJ+aTpjWMZDGo+GOKsnp93Hmft
# ml0Syp3F9+M3y+y6WJGUZoIZJq227jDjjEndtpUrh9BdPdVIfVJD/Au81Rzh05UH
# AivorQ3Os8PELHIgiOd9TWzbdgmGzcILt/ddVQERMYIHQzCCBz8CAQEweDBhMQsw
# CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYD
# VQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMAIT
# MwAAAFZ+j51YCI7pYAAAAAAAVjANBglghkgBZQMEAgEFAKCCBJwwEQYLKoZIhvcN
# AQkQAg8xAgUAMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0B
# CQUxDxcNMjYwNzE1MTI1ODEwWjAvBgkqhkiG9w0BCQQxIgQgVF72xRwBuAxn1leo
# 0nOw59U+c9BON7xvRME8arrNVxQwgbkGCyqGSIb3DQEJEAIvMYGpMIGmMIGjMIGg
# BCC2DDMlTaTj8JV3iTg5Xnpe4CSH60143Z+X9o5NBgMMqDB8MGWkYzBhMQswCQYD
# VQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQD
# EylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMAITMwAA
# AFZ+j51YCI7pYAAAAAAAVjCCA14GCyqGSIb3DQEJEAISMYIDTTCCA0mhggNFMIID
# QTCCAikCAQEwggEJoYHhpIHeMIHbMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz
# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv
# cnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25z
# MScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046QTUwMC0wNUUwLUQ5NDcxNTAzBgNV
# BAMTLE1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWUgU3RhbXBpbmcgQXV0aG9yaXR5
# oiMKAQEwBwYFKw4DAhoDFQD/c/cpFSqQWYBeXggyRJ2ZbvYEEaBnMGWkYzBhMQsw
# CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYD
# VQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMDAN
# BgkqhkiG9w0BAQsFAAIFAO4BlD8wIhgPMjAyNjA3MTUwNTA4MTVaGA8yMDI2MDcx
# NjA1MDgxNVowdDA6BgorBgEEAYRZCgQBMSwwKjAKAgUA7gGUPwIBADAHAgEAAgIh
# czAHAgEAAgIb+TAKAgUA7gLlvwIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEE
# AYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBCwUAA4IB
# AQBZ6lbctv/kQC4lyZTJL2i9B/lVpXOHdm95JkXSHWLvWoIgSRSNG/mF8EHi6Au3
# BOndGQEHyasldRmhOF5CZWkJJ5DbSQGD63vORM+TnhjVRy/uommi4G8NLLofrcTm
# 2svDz0f/lE85IWeck6ykUUVn1mdfB+/Xb2H60FGm0Oo4I5v+9o5VYT5Rgf73uryY
# fMcvIjcgsS4Ls6DCSym1jVu/y9rfGyLfjNpQtGkkFyAWH6Quq4O0zIdJGGFAoURm
# KHaRG0HhyO8f/S9QcA9Mu+KoPXg9+FFTXG5tSjmDW+PNGCv8Opx2xCmOjvK93rfi
# qKLNMRuuHfabhyreuH7ZISInMA0GCSqGSIb3DQEBAQUABIICAFsXt3RM219FHNUE
# f/8arwJEpjZJceRxZwM6BRmnxz0x1SmrQvl7VcxumtiKwsAR5K8ZC0GEmbCCM6yu
# nXeS4gVcAHTwOCGI+GCUCQatFmtU8RorO3BQ5RcJBVrDg+w/QQC+ds0fryOAxYt/
# 7fUa7oIbx8SFglAp4theRqfjOxfwOfqK0qeXtNOBKBE1qCwQD7NGM6OeQBkr7BnY
# Oa3kNocrTbhgFiHUOY3bkxHTthR+XciPYDG0BMo6jMYsf/flhw4cNuYlIMAmilHU
# CHUX2hg/S6T0G8uYfDhFtT+kRCIx3FViCX/0S+U9OPLNg6hIMHYiyPPh3P/VjqKR
# 7xI2l/VbJ6qgtPOlO/PlR7IMpoMAWdt8A9632uzmX0iQEQQ5i4GDPJxNMntLy8Lk
# JNboMYU/yDyeC7L1m39LrKsuTPY4XU/3RnCGjZHUNdOPnfb7+zRFhDjJwQfZ7eIx
# SzdI+9QnJ8fzTQmIPtzDFwqLvqTihh4Bz837/TANZHY4leoDrOvELEmEM1j8V+Jf
# /sVpI8/64oDBiDr4DY+RQAESurVwUm24FtunMCp/cUnSZI65G5IhTD9d9QtJ7xF5
# EXTppgXUbF6zIWXTVBZRUscWMzL+17KaqGbG9O0dQjzCmrcIeAphdNhwglg30cbh
# 0xF8+zBCQTIq0YQsygy6KMBQzg8u
# SIG # End signature block