functions/DailyBuild/Merge-DailyBuildBranch.ps1

<#
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.
#>


[CmdletBinding()]
param(
    [string]$OrganizationUri = $env:SYSTEM_COLLECTIONURI,
    [string]$Project = $env:SYSTEM_TEAMPROJECTID,
    [string]$RepositoryName = $env:BUILD_REPOSITORY_NAME,
    [string]$RepositoryDirectory = $env:BUILD_SOURCESDIRECTORY,
    [string]$DailyBuildBranch = 'daily-build',
    [string]$TargetBranch = 'main',
    [ValidateSet('merge', 'squash')]
    [string]$MergeStrategy = 'merge',
    [int]$DefaultPriority = 100,
    [string]$Pat = $env:DEVOPS_PAT,
    [switch]$SkipUnchangedPush
)

if ($MyInvocation.InvocationName -eq '.') {
    return
}

if ([string]::IsNullOrWhiteSpace($TargetBranch)) {
    $TargetBranch = 'main'
}

if ($DefaultPriority -lt 0) {
    $DefaultPriority = 100
}

if ($env:SYSTEM_DEBUG -eq 'true') {
    $VerbosePreference
    $VerbosePreference = 'Continue'
    $VerbosePreference
    Write-Verbose "PWD: $PWD"
    Write-Verbose "OrganizationUri: $OrganizationUri"
    Write-Verbose "Project: $Project"
    Write-Verbose "RepositoryName: $RepositoryName"
    Write-Verbose "DailyBuildBranch: $DailyBuildBranch"
    Write-Verbose "MergeStrategy: $MergeStrategy"
    Write-Verbose "DefaultPriority: $DefaultPriority"
    Write-Verbose "SkipUnchangedPush: $SkipUnchangedPush"
}

Push-Location -Path $RepositoryDirectory

$gitArgs = @(
    '-c',
    "http.extraheader=AUTHORIZATION: Basic $([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("PAT:$Pat")))"
)

function Resolve-PullRequestPriority {
    param(
        [Parameter(Mandatory = $true)]
        $Labels
    )

    $resolved = $DefaultPriority
    foreach ($label in @($Labels | ForEach-Object { $_.name })) {
        if ($label -match '^priority:(\d+)$') {
            $val = [int]$Matches[1]
            if ($val -lt $resolved) { $resolved = $val }
        }
    }
    return $resolved
}

function Invoke-Git {
    param(
        [Parameter(Mandatory = $true)]
        [string[]]$Args
    )

    Write-Verbose "Running git $($Args -join ' ')"
    & git @gitArgs @Args
    if ($LASTEXITCODE -ne 0) {
        throw "git $($Args -join ' ') failed with exit code $LASTEXITCODE."
    }
}

function Get-CommitIdentity {
    param(
        [Parameter(Mandatory = $true)]
        [string]$Ref
    )

    Write-Verbose "Resolving commit identity for $Ref..."
    $identity = & git @gitArgs 'show' '--no-patch' "--format=%an`n%ae" $Ref
    if ($LASTEXITCODE -ne 0) {
        throw "Failed to resolve commit identity for $Ref. Please verify fetch depth."
    }

    $identityLines = @($identity | Where-Object { $_ -ne $null })
    if ($identityLines.Count -lt 2) {
        throw "Commit identity for $Ref is incomplete."
    }

    return @{
        Name  = $identityLines[0]
        Email = $identityLines[1]
    }
}

function Invoke-GitWithCommitIdentity {
    param(
        [Parameter(Mandatory = $true)]
        [hashtable]$Identity,
        [Parameter(Mandatory = $true)]
        [string[]]$Args
    )

    Write-Verbose "Running git $($Args -join ' ') with identity $($Identity.Name) <$($Identity.Email)>"
    & git @gitArgs '-c' "user.name=$($Identity.Name)" '-c' "user.email=$($Identity.Email)" @Args
    if ($LASTEXITCODE -ne 0) {
        throw "git $($Args -join ' ') failed with exit code $LASTEXITCODE."
    }
}

function Get-BuildResultsUrl {
    $collectionUri = if ($env:SYSTEM_COLLECTIONURI) { $env:SYSTEM_COLLECTIONURI } else { $OrganizationUri }
    if ([string]::IsNullOrWhiteSpace($collectionUri)) {
        return ''
    }

    $buildId = $env:BUILD_BUILDID
    if ([string]::IsNullOrWhiteSpace($buildId)) {
        return ''
    }

    $projectName = if ($env:SYSTEM_TEAMPROJECT) { $env:SYSTEM_TEAMPROJECT } else { $Project }
    $baseUri = $collectionUri.TrimEnd('/')
    $queryParts = @{
        "buildId" = $buildId
        'view'    = 'logs'
        "j"       = $env:SYSTEM_JOBID
        "t"       = $env:SYSTEM_TASKINSTANCEID
        "s"       = $env:SYSTEM_STAGEID
    }

    $queryString = ($queryParts.GetEnumerator() | ForEach-Object { "$($_.Key)=$([uri]::EscapeDataString($_.Value))" }) -join '&'

    return "$baseUri/$([Uri]::EscapeDataString($projectName))/_build/results?$queryString"
}

function Set-PullRequestStatus {
    param(
        [Parameter(Mandatory = $true)]
        [int]$PullRequestId,
        [Parameter(Mandatory = $true)]
        [int]$IterationId,
        [Parameter(Mandatory = $true)]
        [ValidateSet('succeeded', 'failed', 'pending', 'notSet', 'error')]
        [string]$State,
        [Parameter(Mandatory = $true)]
        [string]$Description
    )

    $authHeader = "Basic $([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("PAT:$Pat")))"
    $targetUrl = Get-BuildResultsUrl
    $body = @{
        state       = $State
        description = $Description
        iterationId = $IterationId
        context     = @{
            name  = 'daily-build'
            genre = 'daily-build'
        }
        targetUrl   = $targetUrl
    } | ConvertTo-Json
    Write-Verbose "Posting status to PR !$PullRequestId (iteration: $IterationId): $State - $Description"
    $uri = "$OrganizationUri/$([Uri]::EscapeDataString($Project))/_apis/git/repositories/$repositoryId/pullRequests/$PullRequestId/statuses?api-version=7.1"
    try {
        Invoke-RestMethod -Uri $uri -Method Post -Body $body -ContentType 'application/json' -Headers @{ Authorization = $authHeader } | Out-Null
    }
 catch {
        Write-Warning "Failed to post status to PR !$PullRequestId : $_"
    }
}

function Get-LatestPullRequestIteration {
    param(
        [Parameter(Mandatory = $true)]
        [int]$PullRequestId
    )

    $authHeader = "Basic $([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("PAT:$Pat")))"
    $uri = "$OrganizationUri/$([Uri]::EscapeDataString($Project))/_apis/git/repositories/$repositoryId/pullRequests/$PullRequestId/iterations?includeCommits=false&api-version=7.1"
    
    Write-Verbose "Fetching iterations for PR !$PullRequestId..."
    $response = Invoke-RestMethod -Uri $uri -Method Get -Headers @{ Authorization = $authHeader }

    if (-not $response -or -not $response.value -or $response.value.Count -eq 0) {
        throw "No iterations found for PR !$PullRequestId."
    }

    # The API returns iterations in ascending order; the last one is the current iteration.
    Write-Verbose "Found $($response.value.Count) iterations for PR !$PullRequestId. Returning the latest iteration (ID: $($response.value[-1].id))."
    return $response.value[-1]
}

function Resolve-IterationIdForStatus {
    param(
        [Parameter(Mandatory = $true)]
        $PullRequestItem
    )

    if ($PullRequestItem.PSObject.Properties.Name -contains 'Iteration' -and $PullRequestItem.Iteration -and $PullRequestItem.Iteration.Id) {
        return [int]$PullRequestItem.Iteration.Id
    }

    return 1
}

$env:AZURE_DEVOPS_EXT_PAT = $Pat
$azExtensions = az extension list --query '[].name' --output json | ConvertFrom-Json
if ($azExtensions -notcontains 'azure-devops') {
    az extension add --name azure-devops
}
az devops configure --defaults organization=$OrganizationUri project=$Project

Write-Verbose "Fetching active PRs targeting '$TargetBranch'..."
$prResponse = az repos pr list --repository "$RepositoryName" --target-branch $TargetBranch --status active --query '[?!isDraft]' --output json
$pr = ($prResponse | ConvertFrom-Json)
Write-Verbose "Fetched $($pr.Count) active PRs targeting '$TargetBranch'."
$pr = $pr | Where-Object {
    if (!$_.labels) { $_.labels = @() }
    $labelNames = @($_.labels | ForEach-Object { $_.name })
    $labelNames -notcontains 'AutoMergeIgnore'
}

$pr = $pr | Sort-Object -Property @(
    @{ Expression = { Resolve-PullRequestPriority $_.labels }; Ascending = $true },
    @{ Expression = { $_.pullRequestId }; Ascending = $true }
)

$repositoryId = (az repos show --repository "$RepositoryName" --query id --output tsv).Trim()

Invoke-Git @('fetch', 'origin', $TargetBranch)
Invoke-Git @('checkout', '-B', $DailyBuildBranch, "origin/$TargetBranch")
$mergeLabelScriptPath = Join-Path (Split-Path $PSScriptRoot -Parent) 'ps_modules/D365GitOps/functions/MergeDrivers/Merge-D365LabelFile.ps1'
if (Test-Path -Path $mergeLabelScriptPath) {
    Invoke-Git @('config', 'merge.d365fo-label.driver', "pwsh -File `"$mergeLabelScriptPath`" -Base %O -Ours %A -Theirs %B -MarkerSize %L -FilePath %P")
}
else {
    Write-Verbose -Verbose "Merge label driver script not found at $mergeLabelScriptPath. Skipping merge.d365fo-label.driver configuration."
}
# Module layout (functions/DailyBuild -> functions/MergeDrivers) or extension task layout (ps_modules/D365GitOps).
$mergeXmlScriptPath = @(
    (Join-Path $PSScriptRoot '../MergeDrivers/Merge-D365XmlFile.ps1'),
    (Join-Path $PSScriptRoot 'ps_modules/D365GitOps/functions/MergeDrivers/Merge-D365XmlFile.ps1')
) | Where-Object { Test-Path -LiteralPath $_ -PathType Leaf } | Select-Object -First 1
if ($mergeXmlScriptPath) {
    $mergeXmlScriptPath = (Resolve-Path -LiteralPath $mergeXmlScriptPath).ProviderPath.Replace('\', '/')
    Invoke-Git @('config', 'merge.d365fo-xml.driver', "pwsh -NoProfile -File `"$mergeXmlScriptPath`" -Base %O -Ours %A -Theirs %B -MarkerSize %L -FilePath %P")
}
else {
    Write-Verbose -Verbose "Merge XML driver script Merge-D365XmlFile.ps1 not found. Skipping merge.d365fo-xml.driver configuration."
}
$mergedPRs = @()
$skippedPRs = @()

foreach ($item in $pr) {
    if (-not $item.sourceRefName) {
        Write-Warning "Skipping PR $($item.pullRequestId): missing sourceRefName."
        continue
    }

    if ($item.supportsIterations) {
        $iteration = Get-LatestPullRequestIteration -PullRequestId $item.pullRequestId
        $item | Add-Member -MemberType NoteProperty -Name Iteration -Value $iteration
        if ($item.lastMergeSourceCommit.commitId -ne $item.Iteration.sourceRefCommit.commitId) {
            Write-Warning "Skipping PR $($item.pullRequestId): source branch has new commits since last iteration."
            $skippedPRs += $item
            continue
        }
    }

    $sourceBranch = $item.sourceRefName -replace '^refs/heads/', ''
    $resolvedPriority = Resolve-PullRequestPriority $item.labels
    $sourceIdentity = Get-CommitIdentity "origin/$sourceBranch"
    Write-Host "Merging PR $($item.pullRequestId) from $sourceBranch (priority: $resolvedPriority)"

    try {
        switch ($MergeStrategy) {
            'squash' {
                Invoke-Git @('merge', '--squash', "origin/$sourceBranch")
                Invoke-GitWithCommitIdentity $sourceIdentity @('commit', '-m', "Squash PR !$($item.pullRequestId)")
            }
            default {
                Invoke-GitWithCommitIdentity $sourceIdentity @('merge', '--no-ff', "origin/$sourceBranch", '-m', "Merge PR !$($item.pullRequestId)")
            }
        }
        $mergedPRs += $item
    }
 catch {
        Write-Warning "Merge failed for PR $($item.pullRequestId) ($sourceBranch). Skipping."
        & git merge --abort | Out-Null
        & git reset --hard HEAD | Out-Null
        $skippedPRs += $item
        continue
    }
}

$shouldPush = $true
if ($SkipUnchangedPush) {
    # Silently try to fetch the remote daily-build branch (may not exist yet)
    & git @gitArgs fetch origin $DailyBuildBranch 2>$null | Out-Null
    # Check if the remote ref exists
    & git rev-parse --verify "origin/$DailyBuildBranch" 2>$null | Out-Null
    if ($LASTEXITCODE -eq 0) {
        # Compare trees; exit code 0 means no difference
        & git diff --quiet "origin/$DailyBuildBranch" HEAD
        if ($LASTEXITCODE -eq 0) {
            Write-Host "No content changes vs 'origin/$DailyBuildBranch' - skipping push."
            $shouldPush = $false
        }
    }
}

if ($shouldPush) {
    Invoke-Git @('push', '--force', 'origin', $DailyBuildBranch)
}

foreach ($item in $mergedPRs) {
    try {
        $iterationId = Resolve-IterationIdForStatus -PullRequestItem $item
        Set-PullRequestStatus -PullRequestId $item.pullRequestId -IterationId $iterationId -State 'succeeded' -Description "Merged into daily-build (iteration: $iterationId) $($item.lastMergeSourceCommit.commitId)"
    }
 catch {
        Write-Warning "Failed to post status for PR $($item.pullRequestId): $_"
    }
}
foreach ($item in $skippedPRs) {
    try {
        $iterationId = Resolve-IterationIdForStatus -PullRequestItem $item
        Set-PullRequestStatus -PullRequestId $item.pullRequestId -IterationId $iterationId -State 'failed' -Description "Merge conflict - skipped (iteration: $iterationId) $($item.lastMergeSourceCommit.commitId)"
    }
 catch {
        Write-Warning "Failed to post status for PR $($item.pullRequestId): $_"
    }
}

Write-Host ''
Write-Host '=== Daily Build Summary ==='
if ($mergedPRs.Count -gt 0) {
    $mergedList = ($mergedPRs | ForEach-Object { "!$($_.pullRequestId)" }) -join ', '
    Write-Host "Merged: $mergedList"
}
else {
    Write-Host 'Merged: (none)'
}
if ($skippedPRs.Count -gt 0) {
    $skippedList = ($skippedPRs | ForEach-Object { "!$($_.pullRequestId) (merge conflict)" }) -join ', '
    Write-Host "Skipped: $skippedList"
}
else {
    Write-Host 'Skipped: (none)'
}

# SIG # Begin signature block
# MII2lgYJKoZIhvcNAQcCoII2hzCCNoMCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDCISS7Cg53ihzk
# tg/59vnjWm3xuAM4Kb3ezeBILOtcPaCCGzQwggXMMIIDtKADAgECAhBUmNLR1FsZ
# 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
# 03u4aUoqlmZpxJTG9F9urJh4iIAGXKKy7aIwggaSMIIEeqADAgECAhMzAAiWokxQ
# x66HAhz8AAAACJaiMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ
# RCBWZXJpZmllZCBDUyBFT0MgQ0EgMDMwHhcNMjYxMDE4MDI1MDQ0WhcNMjYxMDIx
# MDI1MDQ0WjBVMQswCQYDVQQGEwJTSTESMBAGA1UEBxMJTGp1YmxqYW5hMRgwFgYD
# VQQKEw9CRS10ZXJuYSBkLm8uby4xGDAWBgNVBAMTD0JFLXRlcm5hIGQuby5vLjCC
# AaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAJdNhrUWIlPmS3c09jFX4He0
# J2ix0cJSDdCoG/rBpushZFn6q5hTOfiTnH970F7MQgY9LFMzSJ+H9qvmmzT1TEdV
# AehGdgC/AOlvm39uxZRnhumCOeR1HW4aG5G5v5PpxGmXJvMWN7AEZyJ58JJ8KkDF
# u6jxDXhKRZ84iYsgJWFC67i6lsVbHcE94knXw5hTypj1HZ+2Krh6gmYm3kgeqI0O
# 9UrUED5Z421D9ZWJHLNNbuUs8A17YOAML3+1Df/arSmLpeWRJ3F3hOViZRAWc0nt
# 7Xub+593HSL6YkyYRbTcIHHlRlg4xJ4/N6eoacE7d/3/VnFv9q9UGj5iA1g1hdJT
# bkOu+yaXausyD+QYSN4C7fSzsRXxisFJMXW5YCgY9F9bZMAyCNyhl4jxJe+4c8de
# /omI+uro3+JJsi/LZVLa1j8YG1pePEeoc1OjyjIuM3v+uii2DPcqqzqzb9nvBTkS
# Q9P4hVaH2qvplTxSQT2bLFhH4qXzW2br2QRX+vRERQIDAQABo4IB1DCCAdAwDAYD
# VR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwOwYDVR0lBDQwMgYKKwYBBAGCN2EB
# AAYIKwYBBQUHAwMGGisGAQQBgjdhpOaoI4H67850gfzolDeutrtWMB0GA1UdDgQW
# BBQNYRcTYM26/9pbC1jzU9rO+1c97TAfBgNVHSMEGDAWgBRrXqU0wwXFYkohWo6r
# c2Bi1KxjhTBnBgNVHR8EYDBeMFygWqBYhlZodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBJRCUyMFZlcmlmaWVkJTIwQ1MlMjBF
# T0MlMjBDQSUyMDAzLmNybDB0BggrBgEFBQcBAQRoMGYwZAYIKwYBBQUHMAKGWGh0
# dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIw
# SUQlMjBWZXJpZmllZCUyMENTJTIwRU9DJTIwQ0ElMjAwMy5jcnQwVAYDVR0gBE0w
# SzBJBgRVHSAAMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNv
# bS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTANBgkqhkiG9w0BAQwFAAOCAgEA
# ZKezAUaS2Jm1GOnzuWmqfAKI1PXAP5E+sgfqsDxdZRoQzzQcuqJiBWCZhOe0BEFY
# OmkRXEnspD21MfIHSyRIk9VPmU9mFWqAv+jX/pQ0l8oPIowCLxo8xwiXRCXFs3bv
# Hn9FUPyr/JW0V7396uC+Y33SxXusVMf6b59n0nKAahOHtajGn2SXYDZiBbW6bLe9
# E+kGWygf9E9hMLVYSeN1ecnjAuDOmZ18GifAnVT+Um+u7OLXU5Il2zhn7Hbx2Ti4
# /coiRrPonrb5FvO6AKv9F5JQco5yyAPP63RB5rLEsos5f2phsEG4PJqQkOV8BK02
# EN63hCkp3tmKccH27H1+aWMcYdBT7q4PL7IKxp9osz5OJPpnL7/7MYbDuOKHfZKS
# ys+Gm5fqopr/UiB9m+Ul0siycMfltpgZxte1nLxFDpcKebacUnvumdLbOnmIplRQ
# eCA/po0gjh2xvcdgNbZRc/sOIE407rWgZ8t91YdvtEAZrMOumbuyUtOzS4bKs3/W
# 3NzBvgtPEjP4cKHrefYiD6d2lljA/arXWIBNyc62FW8Uqz5ltn5aqeYjFQEuPD2B
# FX2x46InMMIcoQfbYI6ItQuzkROjf+twmPN0ufKD0EWOVsL5qxLEW/s6/XZczvl0
# hDizRrkBbBlrb38oLjGhepN8ZFhS6NCangB5g5jY+nkwggcoMIIFEKADAgECAhMz
# AAAAFQU+bhmOkynZAAAAAAAVMA0GCSqGSIb3DQEBDAUAMGMxCzAJBgNVBAYTAlVT
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xNDAyBgNVBAMTK01pY3Jv
# c29mdCBJRCBWZXJpZmllZCBDb2RlIFNpZ25pbmcgUENBIDIwMjEwHhcNMjYwMzI2
# MTgxMTI4WhcNMzEwMzI2MTgxMTI4WjBaMQswCQYDVQQGEwJVUzEeMBwGA1UEChMV
# TWljcm9zb2Z0IENvcnBvcmF0aW9uMSswKQYDVQQDEyJNaWNyb3NvZnQgSUQgVmVy
# aWZpZWQgQ1MgRU9DIENBIDAzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
# AgEA4PTLPQKqLw5zHj7zDnvism4QnfPpaJM2DkZUt5AVV7HnnG8hsAXLHp5ZuWy7
# TBj44iBS8wUBfoIZVVf1NvauRnHXhBAQh00xoS9pKCKy3OFK5YjEXG7/ZjjLUf5e
# /8QJr9BceASR59XR7d+376wal5ioynxn+Q6cjv/oZ1e0xK3jLUtfYjvm42f/R56Y
# NzwpNHu2Em0UxZMfexWcEVqQuLNzXqUX0V0If1jAI+yZrGHlWaIYuExecltiTKyW
# asB3MsyWWLQ9h5Z6OWRCZHYmXBGsRzqG5sDtOmdSfXNt6bPTxiIRmqtbCixAM/Q6
# HOay5GFhrXg67HCoQKdpCHP6GJR/SI+gZDqqoFiDRJBLQvGTRtTGpPod6OuWo9Ik
# CpncVuyGWhzuXLsqDIvirWH13iCIN7FSG0thC/JFLbAxnRKjagKv4rKk4tY16i3u
# oiqdZ4tUj3bz1vRtNwk7GBevG/8riEEcG3aAQl3pjDSQktHaKwkWOG9lgAMuJ4O0
# gDXBIKwYGX+d+fkHy1OYRs6yoyKWzGm2rlm+RSllCpDLD3FxZF0VjuJ6Cj5uClpR
# cqajqWyfyjjVUXiJcR0EXoADgcyIUQe4K/SA0NbHNjIDoEPsVRluKKuBw9JnwIsI
# si7JGa5GkOyaGp2IwTXEfUUtumMQFW3AbS4rRU8wiBIOWXUCAwEAAaOCAdwwggHY
# MA4GA1UdDwEB/wQEAwIBhjAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQUa16l
# NMMFxWJKIVqOq3NgYtSsY4UwVAYDVR0gBE0wSzBJBgRVHSAAMEEwPwYIKwYBBQUH
# AgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0
# b3J5Lmh0bTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTASBgNVHRMBAf8ECDAG
# AQH/AgEAMB8GA1UdIwQYMBaAFNlBKbAPD2Ns72nX9c0pnqRIajDmMHAGA1UdHwRp
# MGcwZaBjoGGGX2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01p
# Y3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDb2RlJTIwU2lnbmluZyUyMFBDQSUy
# MDIwMjEuY3JsMH0GCCsGAQUFBwEBBHEwbzBtBggrBgEFBQcwAoZhaHR0cDovL3d3
# dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBJRCUyMFZl
# cmlmaWVkJTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAyMDIxLmNydDANBgkqhkiG
# 9w0BAQwFAAOCAgEAXW4iPM8Fy1/IJSRIf/ENtlDAlIVgTuOmfRT4cDkd5nZakVS5
# GDqJ/zHM1MK4w4cd1/fUjx+T0n5ZBqE75zvWVhzOWBVWKTuzWLgfpn1UhgBmcIhj
# gElpNItge75/ZxJSSZqIl8boHx+WHQbK1IE7dABTV5M5qk4JPktR8W9bv9BwqhB1
# WT5NgP+niV2G7aUTORXM9NI4rFJfQUWYEnmzg1fOWwczr3qsgt39D5xwsUSTYTG/
# MT/7Af1SO6X9q4Xkle86lEr/L5/3yDG5V3mlSJaaqKvEj/QSTIxPwqFVycZ5GUET
# NRWu5Dfcs7b0XjocUoD4KWcf15f45MMhBVSUwXwad7E4HyHP6Zqr9nobWpC9gBI+
# /BJjj0KIcSU98Ml/j+/BgNubS6QL8490TDB3fM9fGbrlYvutDAMxqTgEh9S/DZa9
# 32UWZ0Dvqcsntgwr2Jh2iH3VIGCap+56McRlb/PfkWhE4dbYAg78DaRQkhu75eQO
# GpKPtn8eNPa/U1o1wuzon9SEOWScweEX/BrwYh2I7zJh6ZXnadRRkS3UkRVaQt/z
# iqWWOmryKmae/vKT/1kD/dNw3YK7wE+luMTzgcVz2uLRpLDd0rqiWohWB0jcngbn
# 5/IrHro1uCGwUmxw+AT6mxd6mfu5xvXf3fxtvy8eJB/XApgX5rGXUpB5rpAwggee
# MIIFhqADAgECAhMzAAAAB4ejNKN7pY4cAAAAAAAHMA0GCSqGSIb3DQEBDAUAMHcx
# CzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBG
# BgNVBAMTP01pY3Jvc29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0
# aWZpY2F0ZSBBdXRob3JpdHkgMjAyMDAeFw0yMTA0MDEyMDA1MjBaFw0zNjA0MDEy
# MDE1MjBaMGMxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y
# YXRpb24xNDAyBgNVBAMTK01pY3Jvc29mdCBJRCBWZXJpZmllZCBDb2RlIFNpZ25p
# bmcgUENBIDIwMjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCy8MCv
# GYgo4t1UekxJbGkIVQm0Uv96SvjB6yUo92cXdylN65Xy96q2YpWCiTas7QPTkGnK
# 9QMKDXB2ygS27EAIQZyAd+M8X+dmw6SDtzSZXyGkxP8a8Hi6EO9Zcwh5A+wOALNQ
# bNO+iLvpgOnEM7GGB/wm5dYnMEOguua1OFfTUITVMIK8faxkP/4fPdEPCXYyy8NJ
# 1fmskNhW5HduNqPZB/NkWbB9xxMqowAeWvPgHtpzyD3PLGVOmRO4ka0WcsEZqyg6
# efk3JiV/TEX39uNVGjgbODZhzspHvKFNU2K5MYfmHh4H1qObU4JKEjKGsqqA6Rzi
# ybPqhvE74fEp4n1tiY9/ootdU0vPxRp4BGjQFq28nzawuvaCqUUF2PWxh+o5/TRC
# b/cHhcYU8Mr8fTiS15kRmwFFzdVPZ3+JV3s5MulIf3II5FXeghlAH9CvicPhhP+V
# aSFW3Da/azROdEm5sv+EUwhBrzqtxoYyE2wmuHKws00x4GGIx7NTWznOm6x/niqV
# i7a/mxnnMvQq8EMse0vwX2CfqM7Le/smbRtsEeOtbnJBbtLfoAsC3TdAOnBbUkbU
# fG78VRclsE7YDDBUbgWt75lDk53yi7C3n0WkHFU4EZ83i83abd9nHWCqfnYa9qIH
# PqjOiuAgSOf4+FRcguEBXlD9mAInS7b6V0UaNwIDAQABo4ICNTCCAjEwDgYDVR0P
# AQH/BAQDAgGGMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTZQSmwDw9jbO9p
# 1/XNKZ6kSGow5jBUBgNVHSAETTBLMEkGBFUdIAAwQTA/BggrBgEFBQcCARYzaHR0
# cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRt
# MBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMA8GA1UdEwEB/wQFMAMBAf8wHwYD
# VR0jBBgwFoAUyH7SaoUqG8oZmAQHJ89QEE9oqKIwgYQGA1UdHwR9MHsweaB3oHWG
# c2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUy
# MElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIwUm9vdCUyMENlcnRpZmljYXRlJTIw
# QXV0aG9yaXR5JTIwMjAyMC5jcmwwgcMGCCsGAQUFBwEBBIG2MIGzMIGBBggrBgEF
# BQcwAoZ1aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNy
# b3NvZnQlMjBJZGVudGl0eSUyMFZlcmlmaWNhdGlvbiUyMFJvb3QlMjBDZXJ0aWZp
# Y2F0ZSUyMEF1dGhvcml0eSUyMDIwMjAuY3J0MC0GCCsGAQUFBzABhiFodHRwOi8v
# b25lb2NzcC5taWNyb3NvZnQuY29tL29jc3AwDQYJKoZIhvcNAQEMBQADggIBAH8l
# Kp7+1Kvq3WYK21cjTLpebJDjW4ZbOX3HD5ZiG84vjsFXT0OB+eb+1TiJ55ns0BHl
# uC6itMI2vnwc5wDW1ywdCq3TAmx0KWy7xulAP179qX6VSBNQkRXzReFyjvF2BGt6
# FvKFR/imR4CEESMAG8hSkPYso+GjlngM8JPn/ROUrTaeU/BRu/1RFESFVgK2wMz7
# fU4VTd8NXwGZBe/mFPZG6tWwkdmA/jLbp0kNUX7elxu2+HtHo0QO5gdiKF+YTYd1
# BGrmNG8sTURvn09jAhIUJfYNotn7OlThtfQjXqe0qrimgY4Vpoq2MgDW9ESUi1o4
# pzC1zTgIGtdJ/IvY6nqa80jFOTg5qzAiRNdsUvzVkoYP7bi4wLCj+ks2GftUct+f
# GUxXMdBUv5sdr0qFPLPB0b8vq516slCfRwaktAxK1S40MCvFbbAXXpAZnU20FaAo
# Dwqq/jwzwd8Wo2J83r7O3onQbDO9TyDStgaBNlHzMMQgl95nHBYMelLEHkUnVVVT
# UsgC0Huj09duNfMaJ9ogxhPNThgq3i8w3DAGZ61AMeF0C1M+mU5eucj1Ijod5O2M
# MPeJQ3/vKBtqGZg4eTtUHt/BPjN74SsJsyHqAdXVS5c+ItyKWg3Eforhox9k3Wgt
# WTpgV4gkSiS4+A09roSdOI4vrRw+p+fL4WrxSK5nMYIauDCCGrQCAQEwcTBaMQsw
# CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSswKQYD
# VQQDEyJNaWNyb3NvZnQgSUQgVmVyaWZpZWQgQ1MgRU9DIENBIDAzAhMzAAiWokxQ
# x66HAhz8AAAACJaiMA0GCWCGSAFlAwQCAQUAoIGEMBgGCisGAQQBgjcCAQwxCjAI
# oAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIB
# CzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIAY1r2BfhnbKSqiQNLQa
# DmxtV7ruzIhsVuhhU9w7XwMEMA0GCSqGSIb3DQEBAQUABIIBgExiAHiPaeQOCdP5
# QESQJ9eVBsMVMgw1NwuuZBAAWBSB7MpndT2ZemJMY9it9mu6wTiYv2Pl+EN5UTtn
# BAwhMX98JqiKdH+fP19Zm+eV3WX1fJCvRRBGGoge3tEznLu1Oe2wYcKmVoXX8lP4
# QTBxPQC4aS9w0eIYSfRNErE7xAVilfvrntjfv94U4joaqeVwYT/wDoSQLUoeereI
# 7FkcbJayeSObqtG3FkqNmEugej5Mx7PEPKXh+CGbYhjtzIWYnlkgRs/CGgwX93lr
# 769aXlV0sDXEN4Q/7/16Mh1JoPMC1dcTWRjEV6N8b8/Fr6vuXG3pOa/w0LoeMeiu
# 7eq/6uKqX7ECBKADBcoR8N8RAcordW969xbyoJ5aX/vIWBdcHuu/WF5i9GnyaUvK
# LHeFkoJwuwkm5q6Gia9hxEH6V3cPm+HXzjNV2sXkARGgb+xmh0NEfsNgKESGbyJw
# lP3qJbWtMyKSyrkNairiNIdpTxDNnmHx4uphb74dT+qa5GXl2KGCGBEwghgNBgor
# BgEEAYI3AwMBMYIX/TCCF/kGCSqGSIb3DQEHAqCCF+owghfmAgEDMQ8wDQYJYIZI
# AWUDBAIBBQAwggFiBgsqhkiG9w0BCRABBKCCAVEEggFNMIIBSQIBAQYKKwYBBAGE
# WQoDATAxMA0GCWCGSAFlAwQCAQUABCD/1Kzdyr22f2unQGRN0cRyurp840owBvYI
# Fjht9oxlUQIGasj0Ku3aGBMyMDI2MTAxOTEzMjgyMS44MDNaMASAAgH0oIHhpIHe
# MIHbMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQL
# ExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxk
# IFRTUyBFU046N0EwMC0wNUUwLUQ5NDcxNTAzBgNVBAMTLE1pY3Jvc29mdCBQdWJs
# aWMgUlNBIFRpbWUgU3RhbXBpbmcgQXV0aG9yaXR5oIIPITCCB4IwggVqoAMCAQIC
# EzMAAAAF5c8P/2YuyYcAAAAAAAUwDQYJKoZIhvcNAQEMBQAwdzELMAkGA1UEBhMC
# VVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjFIMEYGA1UEAxM/TWlj
# cm9zb2Z0IElkZW50aXR5IFZlcmlmaWNhdGlvbiBSb290IENlcnRpZmljYXRlIEF1
# dGhvcml0eSAyMDIwMB4XDTIwMTExOTIwMzIzMVoXDTM1MTExOTIwNDIzMVowYTEL
# MAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAG
# A1UEAxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5nIENBIDIwMjAw
# ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCefOdSY/3gxZ8FfWO1BiKj
# HB7X55cz0RMFvWVGR3eRwV1wb3+yq0OXDEqhUhxqoNv6iYWKjkMcLhEFxvJAeNcL
# AyT+XdM5i2CgGPGcb95WJLiw7HzLiBKrxmDj1EQB/mG5eEiRBEp7dDGzxKCnTYoc
# DOcRr9KxqHydajmEkzXHOeRGwU+7qt8Md5l4bVZrXAhK+WSk5CihNQsWbzT1nRli
# VDwunuLkX1hyIWXIArCfrKM3+RHh+Sq5RZ8aYyik2r8HxT+l2hmRllBvE2Wok6IE
# aAJanHr24qoqFM9WLeBUSudz+qL51HwDYyIDPSQ3SeHtKog0ZubDk4hELQSxnfVY
# XdTGncaBnB60QrEuazvcob9n4yR65pUNBCF5qeA4QwYnilBkfnmeAjRN3LVuLr0g
# 0FXkqfYdUmj1fFFhH8k8YBozrEaXnsSL3kdTD01X+4LfIWOuFzTzuoslBrBILfHN
# j8RfOxPgjuwNvE6YzauXi4orp4Sm6tF245DaFOSYbWFK5ZgG6cUY2/bUq3g3bQAq
# Zt65KcaewEJ3ZyNEobv35Nf6xN6FrA6jF9447+NHvCjeWLCQZ3M8lgeCcnnhTFty
# QX3XgCoc6IRXvFOcPVrr3D9RPHCMS6Ckg8wggTrtIVnY8yjbvGOUsAdZbeXUIQAW
# Ms0d3cRDv09SvwVRd61evQIDAQABo4ICGzCCAhcwDgYDVR0PAQH/BAQDAgGGMBAG
# CSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRraSg6NS9IY0DPe9ivSek+2T3bITBU
# BgNVHSAETTBLMEkGBFUdIAAwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNy
# b3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoG
# CCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMA8GA1UdEwEB/wQF
# MAMBAf8wHwYDVR0jBBgwFoAUyH7SaoUqG8oZmAQHJ89QEE9oqKIwgYQGA1UdHwR9
# MHsweaB3oHWGc2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01p
# Y3Jvc29mdCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIwUm9vdCUyMENlcnRp
# ZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAyMC5jcmwwgZQGCCsGAQUFBwEBBIGHMIGE
# MIGBBggrBgEFBQcwAoZ1aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j
# ZXJ0cy9NaWNyb3NvZnQlMjBJZGVudGl0eSUyMFZlcmlmaWNhdGlvbiUyMFJvb3Ql
# MjBDZXJ0aWZpY2F0ZSUyMEF1dGhvcml0eSUyMDIwMjAuY3J0MA0GCSqGSIb3DQEB
# DAUAA4ICAQBfiHbHfm21WhV150x4aPpO4dhEmSUVpbixNDmv6TvuIHv1xIs174bN
# GO/ilWMm+Jx5boAXrJxagRhHQtiFprSjMktTliL4sKZyt2i+SXncM23gRezzsoOi
# Bhv14YSd1Klnlkzvgs29XNjT+c8hIfPRe9rvVCMPiH7zPZcw5nNjthDQ+zD563I1
# nUJ6y59TbXWsuyUsqw7wXZoGzZwijWT5oc6GvD3HDokJY401uhnj3ubBhbkR83Rb
# fMvmzdp3he2bvIUztSOuFzRqrLfEvsPkVHYnvH1wtYyrt5vShiKheGpXa2AWpsod
# 4OJyT4/y0dggWi8g/tgbhmQlZqDUf3UqUQsZaLdIu/XSjgoZqDjamzCPJtOLi2hB
# wL+KsCh0Nbwc21f5xvPSwym0Ukr4o5sCcMUcSy6TEP7uMV8RX0eH/4JLEpGyae6K
# i8JYg5v4fsNGif1OXHJ2IWG+7zyjTDfkmQ1snFOTgyEX8qBpefQbF0fx6URrYiar
# jmBprwP6ZObwtZXJ23jK3Fg/9uqM3j0P01nzVygTppBabzxPAh/hHhhls6kwo3QL
# J6No803jUsZcd4JQxiYHHc+Q/wAMcPUnYKv/q2O444LO1+n6j01z5mggCSlRwD9f
# aBIySAcA9S8h22hIAcRQqIGEjolCK9F6nK9ZyX4lhthsGHumaABdWzCCB5cwggV/
# oAMCAQICEzMAAABdxjl4T0B9M/0AAAAAAF0wDQYJKoZIhvcNAQEMBQAwYTELMAkG
# A1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UE
# AxMpTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5nIENBIDIwMjAwHhcN
# MjYwOTE3MTg1NzIxWhcNMjcwOTE0MTg1NzIxWjCB2zELMAkGA1UEBhMCVVMxEzAR
# BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p
# Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2Eg
# T3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjdBMDAtMDVFMC1E
# OTQ3MTUwMwYDVQQDEyxNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lIFN0YW1waW5n
# IEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJ33qNzx
# FA+JrOqDscZ6+dPsV7GCAvPbhBo9jDI14cLJpN9SETe7u3YkVsVK9T31amVEEsKS
# dDZQeDaeSJqUNsIqOzGwBLuxk/X8NlZRiQXWpxvO4DSika/dYqVOkfh0tr7JhkgJ
# F9bioPywLlLbWfRzJOCGT7do8j/1LFMTQfDBLA2/tY1Tg0pLAxmcrTdiJhfOVG2f
# OLABs5CMGqR41YyyDnCNO537p6f/KbGA/peBuk01fkCPSsgSqRxoPeOcReQY7vI6
# O2rjz5x7zEo9ocxn52SsPBZT6pgHqblwpWUb6b7ahzy83um4DC0SMvUf0hsm/0++
# 9t4vQmrxeVcTNdURAbwXDULV9UL2d81qjD6ZPbuLCoJ2nFVaweldvs9YJeT4mhG0
# OpP+7IovdJu27sqdZ4T8bVWrqd7qdub7NJADmjiTzp8xuLmQrAdDR/PhBDQFggz+
# j88S51ZmyicHcnQkVtEPKi/ksiHSVzKysfOXODEza9IZp45mrUVj/JTIo+nnSGFj
# y8SFseXSTmJ+GlRJheRnhQKGUSscz0MNY31EJxAO8SdPqJaR2z30G8YvJNgTi0pU
# Mx0ebwGtquF/l+yj4F1fz0SDmCZ1LikqppNEstixJHwa32fb9+aqb+UGBR/A1hr0
# oRoJWbAbiTCF1SyMk9bIhCfPX2JgLDDN/YzNAgMBAAGjggHLMIIBxzAdBgNVHQ4E
# FgQUQ9sKXZlO8H4eVu395ahoyH9a57kwHwYDVR0jBBgwFoAUa2koOjUvSGNAz3vY
# r0npPtk92yEwbAYDVR0fBGUwYzBhoF+gXYZbaHR0cDovL3d3dy5taWNyb3NvZnQu
# Y29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwUHVibGljJTIwUlNBJTIwVGltZXN0
# YW1waW5nJTIwQ0ElMjAyMDIwLmNybDB5BggrBgEFBQcBAQRtMGswaQYIKwYBBQUH
# MAKGXWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9z
# b2Z0JTIwUHVibGljJTIwUlNBJTIwVGltZXN0YW1waW5nJTIwQ0ElMjAyMDIwLmNy
# dDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB
# /wQEAwIHgDBmBgNVHSAEXzBdMFEGDCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIB
# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9y
# eS5odG0wCAYGZ4EMAQQCMA0GCSqGSIb3DQEBDAUAA4ICAQBCyETwKcMu124k4eFo
# bUOoCnyXigtf6RyVDV/gjL73YFfBXoO6OKWgOJv6QrNPrzcQfy0kC60s42YCa4aU
# WgE04toodo2lHJ9dimsX2vgY1RzMrHyGIxmPRoSJWmUdZvrD2pLYnqaX/KyM/5V/
# Plse6M4GhRGJ1NO+kerQmxd1cTufwcm1K1xzCDKHDbUGe3kLR3MBNsIKLaBs5s9L
# lNoCYi+51r5eH2rQlHLTlgQmDh/dK073VDjdPlbQAaWrP5oV7q0MqQVVmyEz4q3X
# B4hKgHtinFBzAnmswbFL4R3yLENCsR3iDwA6WCZFUTTMQQooIQ6IrbBy0F++P+HC
# JPMSj6OgkOXmNQFCLlmOg4l0OBZo1ToPoCBDIng8jkIrpJjE3THOmCt5GB/128sZ
# ElCs7Ohq/B5JAWYlN7Mi5HtwmnXrynaP4RV0j2bi1lr1eYY6N2nfMeD4N6FqLh/b
# z/sJq6w81Smv6Zx0WEZAonPpSSgjHPuCBXPMPYOUgpKFPp+JwsYMAjuvKj8mnLNT
# hsZVat+MH8MHQiCzEe3LTOb6Anz+q+xuu1+D1H11uQycKOmR3ndc66EY+IyGsWeS
# /SDZ7kvXFWpXcK/jWCJuZ5ObEACcwae7ulG78hm7Vl2Dzbcdib7/ETWE08z6mhWi
# dmM5mmDrbOQGw78kR9rzYcmTSjGCB0Mwggc/AgEBMHgwYTELMAkGA1UEBhMCVVMx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9z
# b2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5nIENBIDIwMjACEzMAAABdxjl4T0B9
# M/0AAAAAAF0wDQYJYIZIAWUDBAIBBQCgggScMBEGCyqGSIb3DQEJEAIPMQIFADAa
# BgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI2MTAx
# OTEzMjgyMVowLwYJKoZIhvcNAQkEMSIEIEiWUP6pJ0KREPD0b5DXcoR5hWGsVScY
# gh/H6hT6bJTyMIG5BgsqhkiG9w0BCRACLzGBqTCBpjCBozCBoAQgLTVkS2/p8+5C
# YqFlp0aiuYaFAENeb9zL6xe93MQCSl0wfDBlpGMwYTELMAkGA1UEBhMCVVMxHjAc
# BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0
# IFB1YmxpYyBSU0EgVGltZXN0YW1waW5nIENBIDIwMjACEzMAAABdxjl4T0B9M/0A
# AAAAAF0wggNeBgsqhkiG9w0BCRACEjGCA00wggNJoYIDRTCCA0EwggIpAgEBMIIB
# CaGB4aSB3jCB2zELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO
# BgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEl
# MCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UECxMe
# blNoaWVsZCBUU1MgRVNOOjdBMDAtMDVFMC1EOTQ3MTUwMwYDVQQDEyxNaWNyb3Nv
# ZnQgUHVibGljIFJTQSBUaW1lIFN0YW1waW5nIEF1dGhvcml0eaIjCgEBMAcGBSsO
# AwIaAxUAvae6tbWxgM8HaMBsDxHEmsyWkPWgZzBlpGMwYTELMAkGA1UEBhMCVVMx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9z
# b2Z0IFB1YmxpYyBSU0EgVGltZXN0YW1waW5nIENBIDIwMjAwDQYJKoZIhvcNAQEL
# BQACBQDuf/jZMCIYDzIwMjYxMDE5MDIwMzA1WhgPMjAyNjEwMjAwMjAzMDVaMHQw
# OgYKKwYBBAGEWQoEATEsMCowCgIFAO5/+NkCAQAwBwIBAAICEREwBwIBAAICEgcw
# CgIFAO6BSlkCAQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoDAqAKMAgC
# AQACAwehIKEKMAgCAQACAwGGoDANBgkqhkiG9w0BAQsFAAOCAQEAihZ1tLYjQuwX
# ieVHwN2TT6HzEDFiHmEYUrwL93mSEC1ttFCndhyK2oZm1D1++19XkbnkinJVT1vr
# PQ3ooxhQbd7qO14VAe1T5GyboPE7cSICpdr30HS2JO9phqBW7QAfpTVGT0WSidQm
# nXNY8R5XAz7gP4MZuHhj6mPYa7m5pDhppBEwSsGOhcvP2KpsDCm2KDqRFH/+HY2l
# ZPg1vcTpZR7SiL6Xp9FTHmJIYjYB9X/CYHRarMw8Lgc9rkB+i+Ft5vQThTgy3Ul4
# v3G6vTbKVYpFkkEdVGmWmmcHbRf+CogAXP1qx1LjPIAukDZIxWZezQusnmHuzAJ2
# hSdpdXKp2TANBgkqhkiG9w0BAQEFAASCAgCMcyFIBnawCxzX6D6v24SzCk9ItCUu
# U8g6/RZPcNj3AfMEiDqEjJ/KhnFUkJ9wjt7A94hAnekqUtWAB2wf7plSvN+eaKe/
# 1zzeR1PyvbMOGPijXiwRKd7wkY4qKYNdsgKHNDc7BHwt/2LDCh06Vdcu/nCSwyA0
# 7G7HUC5SscNN4sbMc4R1DZMm8qZ5fefQ774rV9ynP+ud0QYQksqOUXxJsA4OAckH
# LyQAi94d0v+RRTaQW7+s8GSavnmA8jINBC6sZftGS4W1tiH9Gb+jbUFat3WC9v/H
# OJQeDhYYWJHwQkYH6FyhBUeuLp54gwtiJc1I0F2iXJvw3CF3bOBULOVlHMjK2vF+
# mpDQ6GjAWlIo70XHC6srP7YmXDH5SJrWnqsaz2KBd4CV83A3/ho9hmG9ovTw7qFl
# B8SFB9MmYrZn4gVTSkj+q9gVIfcgyyj8r0NCW/Qubnparb/2oWrs7+gIi9aIy24H
# 0rQQucf4u0ZAde9l45oqBoy+0lX5RhLQBvXtSLxda9JLgxGTklV10kf1ZuO1wry7
# 3vBi+XSMA1v8UIkb+hJmIQ+Ac3j3phV70UKc/nE9ycAqd6XsNRm3eEBtlTBODw8c
# 5nvYVA+8XtOCIIWZkiVXwxXSxdZOPNg7fx077z2kNpP+NFEaarHYWn0CsApZpAcA
# F49CiPEubTAdiA==
# SIG # End signature block