Public/Remove-GitHubAccelerator.ps1

function Remove-GitHubAccelerator {
    <#
    .SYNOPSIS
        Removes GitHub resources created by the Azure Landing Zone accelerator bootstrap modules.
 
    .DESCRIPTION
        The Remove-GitHubAccelerator function performs cleanup of GitHub resources that were created by the
        Azure Landing Zone accelerator bootstrap process (https://github.com/Azure/accelerator-bootstrap-modules).
        This includes repositories, teams, and optionally runner groups.
 
        The function operates in the following sequence:
        1. Validates GitHub CLI authentication
        2. Prompts for confirmation (unless bypassed or in plan mode)
        3. Discovers and deletes repositories matching the specified patterns
        4. Discovers and deletes teams matching the specified patterns
        5. Optionally discovers and deletes runner groups matching the specified patterns
 
        CRITICAL WARNING: This is a highly destructive operation that will permanently delete GitHub resources.
        Use with extreme caution and ensure you have appropriate backups and authorization before executing.
 
    .PARAMETER Organization
        The GitHub organization name where the resources to be deleted are located.
        This parameter is required.
 
    .PARAMETER RepositoryNamePatterns
        An array of regex patterns to match against repository names. Repositories matching any of these
        patterns will be deleted. If empty, no repositories will be deleted.
        Default: Empty array (no repositories deleted)
 
    .PARAMETER TeamNamePatterns
        An array of regex patterns to match against team names. Teams matching any of these patterns
        will be deleted. If empty, no teams will be deleted.
        Default: Empty array (no teams deleted)
 
    .PARAMETER RunnerGroupNamePatterns
        An array of regex patterns to match against runner group names. Runner groups matching any of
        these patterns will be deleted. If empty, no runner groups will be deleted.
        Default: Empty array (no runner groups deleted)
 
    .PARAMETER BypassConfirmation
        A switch parameter that bypasses the interactive confirmation prompts. When specified, the function
        waits for the duration specified in -BypassConfirmationTimeoutSeconds before proceeding, allowing
        time to cancel. During this timeout, pressing any key will cancel the operation.
        WARNING: Use this parameter with extreme caution as it reduces safety checks.
        Default: $false (confirmation required)
 
    .PARAMETER BypassConfirmationTimeoutSeconds
        The number of seconds to wait before proceeding when -BypassConfirmation is used. During this
        timeout, pressing any key will cancel the operation. This provides a safety window to prevent
        accidental deletions.
        Default: 30 seconds
 
    .PARAMETER ThrottleLimit
        The maximum number of parallel operations to execute simultaneously. This controls the degree
        of parallelism when processing resources. Higher values may improve performance but increase
        API throttling risk.
        Default: 11
 
    .PARAMETER PlanMode
        A switch parameter that enables "dry run" mode. When specified, the function displays what
        actions would be taken without actually making any changes. This is useful for validating
        the scope of operations before executing the actual cleanup.
        Default: $false (execute actual deletions)
 
    .EXAMPLE
        Remove-GitHubAccelerator -Organization "my-org" -RepositoryNamePatterns @("^alz-.*") -PlanMode
 
        Shows what repositories matching the pattern "^alz-.*" would be deleted from the "my-org"
        organization without making any changes.
 
    .EXAMPLE
        Remove-GitHubAccelerator -Organization "my-org" -RepositoryNamePatterns @("^alz-.*") -TeamNamePatterns @("^alz-.*")
 
        Deletes all repositories and teams matching the pattern "^alz-.*" from the "my-org" organization.
 
    .EXAMPLE
        Remove-GitHubAccelerator -Organization "my-org" -RepositoryNamePatterns @("^alz-.*", "^landing-zone-.*") -RunnerGroupNamePatterns @("^alz-.*")
 
        Deletes repositories matching either pattern and runner groups matching "^alz-.*" from the
        "my-org" organization.
 
    .EXAMPLE
        Remove-GitHubAccelerator -Organization "my-org" -RepositoryNamePatterns @("^test-alz$") -BypassConfirmation -BypassConfirmationTimeoutSeconds 10
 
        Deletes the repository named exactly "test-alz" with a 10-second confirmation bypass timeout.
 
    .NOTES
        This function requires the GitHub CLI (gh) to be installed and authenticated.
        Install GitHub CLI: https://cli.github.com/
        Authenticate: gh auth login
 
        Required permissions:
        - delete:repo (to delete repositories)
        - admin:org (to delete teams and runner groups)
    #>

    [CmdletBinding(SupportsShouldProcess = $true)]
    param (
        [Parameter(Mandatory = $true, HelpMessage = "[REQUIRED] The GitHub organization name.")]
        [Alias("org", "GitHubOrganization")]
        [string]$Organization,

        [Parameter(Mandatory = $false, HelpMessage = "[OPTIONAL] Regex patterns to match repository names for deletion.")]
        [Alias("repos")]
        [string[]]$RepositoryNamePatterns = @(),

        [Parameter(Mandatory = $false, HelpMessage = "[OPTIONAL] Regex patterns to match team names for deletion.")]
        [Alias("teams")]
        [string[]]$TeamNamePatterns = @(),

        [Parameter(Mandatory = $false, HelpMessage = "[OPTIONAL] Regex patterns to match runner group names for deletion.")]
        [Alias("runners")]
        [string[]]$RunnerGroupNamePatterns = @(),

        [Parameter(Mandatory = $false, HelpMessage = "[OPTIONAL] Bypass interactive confirmation prompts.")]
        [switch]$BypassConfirmation,

        [Parameter(Mandatory = $false, HelpMessage = "[OPTIONAL] Seconds to wait when bypassing confirmation.")]
        [int]$BypassConfirmationTimeoutSeconds = 30,

        [Parameter(Mandatory = $false, HelpMessage = "[OPTIONAL] Maximum parallel operations.")]
        [int]$ThrottleLimit = 11,

        [Parameter(Mandatory = $false, HelpMessage = "[OPTIONAL] Enable dry run mode - no changes will be made.")]
        [switch]$PlanMode
    )

    # Main execution starts here
    if ($PSCmdlet.ShouldProcess("Delete GitHub Resources", "delete")) {

        Test-Tooling -Checks @("GitHubCli")

        $TempLogFileForPlan = ""
        if($PlanMode) {
            Write-ToConsoleLog "Plan Mode enabled, no changes will be made. All actions will be logged as what would be performed." -IsWarning
            $TempLogFileForPlan = (New-TemporaryFile).FullName
        }

        $funcWriteToConsoleLog = ${function:Write-ToConsoleLog}.ToString()

        if($BypassConfirmation) {
            Write-ToConsoleLog "Bypass confirmation enabled, proceeding without prompts..." -IsWarning
            Write-ToConsoleLog "This is a highly destructive operation that will permanently delete GitHub resources!" -IsWarning
            Write-ToConsoleLog "We are waiting $BypassConfirmationTimeoutSeconds seconds to allow for cancellation. Press any key to cancel..." -IsWarning

            $keyPressed = $false
            $secondsRunning = 0

            while((-not $keyPressed) -and ($secondsRunning -lt $BypassConfirmationTimeoutSeconds)){
                $keyPressed = [Console]::KeyAvailable
                Write-ToConsoleLog ("Waiting for: $($BypassConfirmationTimeoutSeconds-$secondsRunning) seconds. Press any key to cancel...") -IsWarning -Overwrite
                Start-Sleep -Seconds 1
                $secondsRunning++
            }

            if($keyPressed) {
                Write-ToConsoleLog "Cancellation key pressed, exiting without making any changes..." -IsError
                return
            }
        }

        Write-ToConsoleLog "Thanks for providing the inputs, getting started..." -IsSuccess

        $hasRepositoryPatterns = $RepositoryNamePatterns.Count -gt 0
        $hasTeamPatterns = $TeamNamePatterns.Count -gt 0
        $hasRunnerGroupPatterns = $RunnerGroupNamePatterns.Count -gt 0

        if(-not $hasRepositoryPatterns -and -not $hasTeamPatterns -and -not $hasRunnerGroupPatterns) {
            Write-ToConsoleLog "No patterns provided for repositories, teams, or runner groups. Nothing to do. Exiting..." -IsError
            return
        }

        # Discover resources to delete
        $repositoriesToDelete = @()
        $teamsToDelete = @()
        $runnerGroupsToDelete = @()

        # Discover repositories
        if($hasRepositoryPatterns) {
            Write-ToConsoleLog "Discovering repositories in organization: $Organization"

            $repositoriesResponse = (gh repo list $Organization --json name,url --limit 1000 2>&1)
            if($LASTEXITCODE -ne 0) {
                Write-ToConsoleLog "Failed to list repositories in organization: $Organization" -IsError
                return
            }
            $allRepositories = @($repositoriesResponse | ConvertFrom-Json)
            Write-ToConsoleLog "Found $($allRepositories.Count) total repositories in organization: $Organization"

            foreach($repo in $allRepositories) {
                foreach($pattern in $RepositoryNamePatterns) {
                    if($repo.name -match $pattern) {
                        Write-ToConsoleLog "Repository matches pattern '$pattern': $($repo.name)"
                        $repositoriesToDelete += @{
                            Name = $repo.name
                            Url  = $repo.url
                        }
                        break
                    }
                }
            }

            Write-ToConsoleLog "Found $($repositoriesToDelete.Count) repositories matching patterns for deletion"
        }

        # Discover teams
        if($hasTeamPatterns) {
            Write-ToConsoleLog "Discovering teams in organization: $Organization"

            $teamsResponse = (gh api "orgs/$Organization/teams" --paginate 2>&1)
            if($LASTEXITCODE -ne 0) {
                Write-ToConsoleLog "Failed to list teams in organization: $Organization" -IsError
                return
            }
            $allTeams = @($teamsResponse | ConvertFrom-Json)
            Write-ToConsoleLog "Found $($allTeams.Count) total teams in organization: $Organization"

            foreach($team in $allTeams) {
                foreach($pattern in $TeamNamePatterns) {
                    if($team.name -match $pattern -or $team.slug -match $pattern) {
                        Write-ToConsoleLog "Team matches pattern '$pattern': $($team.name) (slug: $($team.slug))"
                        $teamsToDelete += @{
                            Name = $team.name
                            Slug = $team.slug
                            Id   = $team.id
                        }
                        break
                    }
                }
            }

            Write-ToConsoleLog "Found $($teamsToDelete.Count) teams matching patterns for deletion"
        }

        # Discover runner groups
        if($hasRunnerGroupPatterns) {
            Write-ToConsoleLog "Discovering runner groups in organization: $Organization"

            $runnerGroupsResponse = (gh api "orgs/$Organization/actions/runner-groups" --paginate 2>&1)
            if($LASTEXITCODE -ne 0) {
                Write-ToConsoleLog "Failed to list runner groups in organization: $Organization (may require GitHub Enterprise)" -IsWarning
                $allRunnerGroups = @()
            } else {
                $allRunnerGroups = ($runnerGroupsResponse | ConvertFrom-Json).runner_groups
            }

            if($null -ne $allRunnerGroups) {
                Write-ToConsoleLog "Found $($allRunnerGroups.Count) total runner groups in organization: $Organization"

                foreach($runnerGroup in $allRunnerGroups) {
                    # Skip the default runner group as it cannot be deleted
                    if($runnerGroup.name -eq "Default" -or $runnerGroup.default) {
                        Write-ToConsoleLog "Skipping default runner group: $($runnerGroup.name)"
                        continue
                    }

                    foreach($pattern in $RunnerGroupNamePatterns) {
                        if($runnerGroup.name -match $pattern) {
                            Write-ToConsoleLog "Runner group matches pattern '$pattern': $($runnerGroup.name)"
                            $runnerGroupsToDelete += @{
                                Name = $runnerGroup.name
                                Id   = $runnerGroup.id
                            }
                            break
                        }
                    }
                }

                Write-ToConsoleLog "Found $($runnerGroupsToDelete.Count) runner groups matching patterns for deletion"
            }
        }

        # Confirm deletion
        $totalResourcesToDelete = $repositoriesToDelete.Count + $teamsToDelete.Count + $runnerGroupsToDelete.Count
        if($totalResourcesToDelete -eq 0) {
            Write-ToConsoleLog "No resources found matching the provided patterns. Nothing to delete." -IsWarning
            return
        }

        if(-not $BypassConfirmation) {
            Write-ToConsoleLog "The following GitHub resources will be deleted:"

            if($repositoriesToDelete.Count -gt 0) {
                Write-ToConsoleLog "Repositories ($($repositoriesToDelete.Count)):"
                $repositoriesToDelete | ForEach-Object { Write-ToConsoleLog " - $($_.Name)"  }
            }

            if($teamsToDelete.Count -gt 0) {
                Write-ToConsoleLog "Teams ($($teamsToDelete.Count)):"
                $teamsToDelete | ForEach-Object { Write-ToConsoleLog " - $($_.Name) (slug: $($_.Slug))"  }
            }

            if($runnerGroupsToDelete.Count -gt 0) {
                Write-ToConsoleLog "Runner Groups ($($runnerGroupsToDelete.Count)):"
                $runnerGroupsToDelete | ForEach-Object { Write-ToConsoleLog " - $($_.Name)"  }
            }

            if($PlanMode) {
                Write-ToConsoleLog "Skipping confirmation for plan mode"
            } else {
                $continue = Invoke-PromptForConfirmation -message "ALL LISTED GITHUB RESOURCES WILL BE PERMANENTLY DELETED"
                if(-not $continue) {
                    Write-ToConsoleLog "Exiting..."
                    return
                }
            }
        }

        # Delete repositories
        if($repositoriesToDelete.Count -gt 0) {
            Write-ToConsoleLog "Deleting repositories..."

            $repositoriesToDelete | ForEach-Object -Parallel {
                $funcWriteToConsoleLog = $using:funcWriteToConsoleLog
                ${function:Write-ToConsoleLog} = $funcWriteToConsoleLog
                $TempLogFileForPlan = $using:TempLogFileForPlan
                $org = $using:Organization

                $repo = $_
                $repoFullName = "$org/$($repo.Name)"

                if($using:PlanMode) {
                    Write-ToConsoleLog `
                        "Would delete repository: $repoFullName", `
                        "Would run: gh repo delete $repoFullName --yes" `
                        -IsPlan -LogFilePath $TempLogFileForPlan
                } else {
                    Write-ToConsoleLog "Deleting repository: $repoFullName"
                    $result = gh repo delete $repoFullName --yes 2>&1
                    if($LASTEXITCODE -ne 0) {
                        Write-ToConsoleLog "Failed to delete repository: $repoFullName", "Full error: $result" -IsWarning
                    } else {
                        Write-ToConsoleLog "Deleted repository: $repoFullName"
                    }
                }
            } -ThrottleLimit $ThrottleLimit
        }

        # Delete teams
        if($teamsToDelete.Count -gt 0) {
            Write-ToConsoleLog "Deleting teams..."

            $teamsToDelete | ForEach-Object -Parallel {
                $funcWriteToConsoleLog = $using:funcWriteToConsoleLog
                ${function:Write-ToConsoleLog} = $funcWriteToConsoleLog
                $TempLogFileForPlan = $using:TempLogFileForPlan
                $org = $using:Organization

                $team = $_

                if($using:PlanMode) {
                    Write-ToConsoleLog `
                        "Would delete team: $($team.Name) (slug: $($team.Slug))", `
                        "Would run: gh api -X DELETE orgs/$org/teams/$($team.Slug)" `
                        -IsPlan -LogFilePath $TempLogFileForPlan
                } else {
                    Write-ToConsoleLog "Deleting team: $($team.Name) (slug: $($team.Slug))"
                    $result = gh api -X DELETE "orgs/$org/teams/$($team.Slug)" 2>&1
                    if($LASTEXITCODE -ne 0) {
                        Write-ToConsoleLog "Failed to delete team: $($team.Name)", "Full error: $result" -IsWarning
                    } else {
                        Write-ToConsoleLog "Deleted team: $($team.Name)"
                    }
                }
            } -ThrottleLimit $ThrottleLimit
        }

        # Delete runner groups
        if($runnerGroupsToDelete.Count -gt 0) {
            Write-ToConsoleLog "Deleting runner groups..."

            $runnerGroupsToDelete | ForEach-Object -Parallel {
                $funcWriteToConsoleLog = $using:funcWriteToConsoleLog
                ${function:Write-ToConsoleLog} = $funcWriteToConsoleLog
                $TempLogFileForPlan = $using:TempLogFileForPlan
                $org = $using:Organization

                $runnerGroup = $_

                if($using:PlanMode) {
                    Write-ToConsoleLog `
                        "Would delete runner group: $($runnerGroup.Name)", `
                        "Would run: gh api -X DELETE orgs/$org/actions/runner-groups/$($runnerGroup.Id)" `
                        -IsPlan -LogFilePath $TempLogFileForPlan
                } else {
                    Write-ToConsoleLog "Deleting runner group: $($runnerGroup.Name)"
                    $result = gh api -X DELETE "orgs/$org/actions/runner-groups/$($runnerGroup.Id)" 2>&1
                    if($LASTEXITCODE -ne 0) {
                        Write-ToConsoleLog "Failed to delete runner group: $($runnerGroup.Name)", "Full error: $result" -IsWarning
                    } else {
                        Write-ToConsoleLog "Deleted runner group: $($runnerGroup.Name)"
                    }
                }
            } -ThrottleLimit $ThrottleLimit
        }

        Write-ToConsoleLog "Cleanup completed." -IsSuccess

        if($PlanMode) {
            Write-ToConsoleLog "Plan mode enabled, no changes were made." -IsWarning
            $planLogContents = Get-Content -Path $TempLogFileForPlan -Raw
            Write-ToConsoleLog @("Plan mode log contents:", $planLogContents) -Color Gray
            Remove-Item -Path $TempLogFileForPlan -Force
        }
    }
}

# SIG # Begin signature block
# MIIoLwYJKoZIhvcNAQcCoIIoIDCCKBwCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCChEZ9s8gPWr85+
# 7aq41cCcTV++XYtf54ocEXaF16q/KqCCDXYwggX0MIID3KADAgECAhMzAAAEhV6Z
# 7A5ZL83XAAAAAASFMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjUwNjE5MTgyMTM3WhcNMjYwNjE3MTgyMTM3WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDASkh1cpvuUqfbqxele7LCSHEamVNBfFE4uY1FkGsAdUF/vnjpE1dnAD9vMOqy
# 5ZO49ILhP4jiP/P2Pn9ao+5TDtKmcQ+pZdzbG7t43yRXJC3nXvTGQroodPi9USQi
# 9rI+0gwuXRKBII7L+k3kMkKLmFrsWUjzgXVCLYa6ZH7BCALAcJWZTwWPoiT4HpqQ
# hJcYLB7pfetAVCeBEVZD8itKQ6QA5/LQR+9X6dlSj4Vxta4JnpxvgSrkjXCz+tlJ
# 67ABZ551lw23RWU1uyfgCfEFhBfiyPR2WSjskPl9ap6qrf8fNQ1sGYun2p4JdXxe
# UAKf1hVa/3TQXjvPTiRXCnJPAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUuCZyGiCuLYE0aU7j5TFqY05kko0w
# RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW
# MBQGA1UEBRMNMjMwMDEyKzUwNTM1OTAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci
# tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j
# b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG
# CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu
# Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0
# MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBACjmqAp2Ci4sTHZci+qk
# tEAKsFk5HNVGKyWR2rFGXsd7cggZ04H5U4SV0fAL6fOE9dLvt4I7HBHLhpGdE5Uj
# Ly4NxLTG2bDAkeAVmxmd2uKWVGKym1aarDxXfv3GCN4mRX+Pn4c+py3S/6Kkt5eS
# DAIIsrzKw3Kh2SW1hCwXX/k1v4b+NH1Fjl+i/xPJspXCFuZB4aC5FLT5fgbRKqns
# WeAdn8DsrYQhT3QXLt6Nv3/dMzv7G/Cdpbdcoul8FYl+t3dmXM+SIClC3l2ae0wO
# lNrQ42yQEycuPU5OoqLT85jsZ7+4CaScfFINlO7l7Y7r/xauqHbSPQ1r3oIC+e71
# 5s2G3ClZa3y99aYx2lnXYe1srcrIx8NAXTViiypXVn9ZGmEkfNcfDiqGQwkml5z9
# nm3pWiBZ69adaBBbAFEjyJG4y0a76bel/4sDCVvaZzLM3TFbxVO9BQrjZRtbJZbk
# C3XArpLqZSfx53SuYdddxPX8pvcqFuEu8wcUeD05t9xNbJ4TtdAECJlEi0vvBxlm
# M5tzFXy2qZeqPMXHSQYqPgZ9jvScZ6NwznFD0+33kbzyhOSz/WuGbAu4cHZG8gKn
# lQVT4uA2Diex9DMs2WHiokNknYlLoUeWXW1QrJLpqO82TLyKTbBM/oZHAdIc0kzo
# STro9b3+vjn2809D0+SOOCVZMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq
# hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
# bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
# IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg
# Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
# CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03
# a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr
# rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg
# OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy
# 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9
# sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh
# dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k
# A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB
# w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn
# Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90
# lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w
# ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o
# ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD
# VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa
# BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny
# bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG
# AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t
# L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV
# HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3
# dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG
# AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl
# AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb
# C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l
# hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6
# I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0
# wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560
# STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam
# ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa
# J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah
# XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA
# 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt
# Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr
# /Xmfwb1tbWrJUnMTDXpQzTGCGg8wghoLAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
# aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp
# Z25pbmcgUENBIDIwMTECEzMAAASFXpnsDlkvzdcAAAAABIUwDQYJYIZIAWUDBAIB
# BQCggbAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO
# MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIM0OE5l2VVai4mmR3ei3KIXn
# 0Vx23atsytSTsUUIYDskMEQGCisGAQQBgjcCAQwxNjA0oBSAEgBNAGkAYwByAG8A
# cwBvAGYAdKEcgBpodHRwczovL3d3dy5taWNyb3NvZnQuY29tIDANBgkqhkiG9w0B
# AQEFAASCAQCnxcsqGZGezAHPleah1pv3gHVe5H3G3EaFvtvnr6dv4N+1N/eAD5Yo
# gSLij9Dip2AbZ0QUVGVFhPJCH8B09O3iFWMpsnadffoiCepFqSUR9cfTnnLPXHF4
# 2t+G8i2JE8TIYky5f1mFGrkP96ClZU/EascgnXqO8TmPJn8QGF/XpP5i+CRNHKS4
# 7m07iuvm38uCenDladCN7ww2wEBdR3isLnlM2swPAT4wNMfF1jD5sXp0Q1Fak6sh
# ehExmJToFUhp2ogqV0I7MHg/y2sIy4leH3AH8CKzp6sM4ErjZOw/BU26dU0mwi7a
# vXhGGpcH9bTz/aizPrYXAtQ38EgSU+PWoYIXlzCCF5MGCisGAQQBgjcDAwExgheD
# MIIXfwYJKoZIhvcNAQcCoIIXcDCCF2wCAQMxDzANBglghkgBZQMEAgEFADCCAVIG
# CyqGSIb3DQEJEAEEoIIBQQSCAT0wggE5AgEBBgorBgEEAYRZCgMBMDEwDQYJYIZI
# AWUDBAIBBQAEIAHMdA9yZdmnc7BM5eI0ETCMFneREAlf4j4w+6ke7FlUAgZpaRT4
# XB0YEzIwMjYwMTMwMjAwNjE1LjkzM1owBIACAfSggdGkgc4wgcsxCzAJBgNVBAYT
# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBB
# bWVyaWNhIE9wZXJhdGlvbnMxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjpBMDAw
# LTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj
# ZaCCEe0wggcgMIIFCKADAgECAhMzAAACCHidWF2Sx9lSAAEAAAIIMA0GCSqGSIb3
# DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD
# VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAk
# BgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTI1MDEzMDE5
# NDI1M1oXDTI2MDQyMjE5NDI1M1owgcsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX
# YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg
# Q29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlv
# bnMxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjpBMDAwLTA1RTAtRDk0NzElMCMG
# A1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCCAiIwDQYJKoZIhvcN
# AQEBBQADggIPADCCAgoCggIBALXLcAjmUjPcinWcrkExRRsZGyNKcLP9UazffO9j
# Q16yGw+B+V3f9nf/d1LxYoEuUOWiyZck5mUVKI1dR3oNMnED2KT9lsJ1YnvwsqNs
# 3e0WRfZzpFGlEykDyyr+gFtGvI/dzxD+DGkkAocfPxy5Kft7B8IvOc2bGqWJOTdD
# kserPY+N5goP91sowFPZMABYC+6bjP8dcgnq0V0ag1XhZRFmzAJK3pE7BqpDWgBg
# a8Sd0f4NdmrX5seyC9w80J1NIilahtCIlL9QouJHTYo0KoHgj3JqMVNKWcwgQzP8
# 2LnfygYjrimFy82lR7b6popYdnx3hPUqCG9GZJIXhgXkM0QlvFoJTCzLudQuawWd
# No6NU6hMVZZ9Ze8G44qQFxApYYq+uSL3vqPjH7l7MA/fp+re7p0dElMtkC7h0S46
# ihTf6Qxmv5EFhaNMdAIpX7JnVJPR4aRsdegDaXLJEOU2MFByh5kjFYJm2z93f6d/
# WOJIs3p/rB0dpTPQAPA5ND9oSjUgLzl4V4+/IgprEUmQZTYyprpfOreoKrm2iQge
# 2OGiCysSB8MpN4VdO12GXUg+0twJ8xxY4YYBeixVRTsb3jwXpb3rjbh/ZUcPwvcW
# jIAj36vjPIhBSaqIRLO5BZ5alNOMVjAKaBdoY65INXxw05VAHog/M+d5mFVOPDFs
# BmVpAgMBAAGjggFJMIIBRTAdBgNVHQ4EFgQUozHi986pxROBg5UH1/Xz+aF6AU0w
# HwYDVR0jBBgwFoAUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXwYDVR0fBFgwVjBUoFKg
# UIZOaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0
# JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3JsMGwGCCsGAQUFBwEBBGAw
# XjBcBggrBgEFBQcwAoZQaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j
# ZXJ0cy9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcnQw
# DAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8E
# BAMCB4AwDQYJKoZIhvcNAQELBQADggIBAFGzMokrAB+zCp1pA8WJpgH9k0BhYNrT
# jRdNxCwJoK5rmewbUiyVhpKkfuaJMuvp5ASpdzNmip45r/G8OcwaJ8Y11rQIdtDC
# 2mciGy62so7aOGMRobCUmA4yqXbWvsiTpecHNrR7eEE67hQGQyX8sRf4BRG3uLv5
# FM2wY3Rxc/A9JtMUT73PtZqAZtj2nBSj83GQYmx6oYJD/0rZUxTvhvDl7v7wgZSE
# zbGykk+qdJ4c+FiZwHRZyU7FxUh+P9m5C/Cis9tMQRgNULNI3ftzTIKE8xjsUn4c
# YUE0nHB3mUoivsZh+rxrSA6ILaWMZiVziu3hwJ53VcqDzd/SX1pRWKZYFhe1815u
# Gl+votzeMPw2CysOHO3RaCch2dNkKLuPGOwgGKUf32ljn+HptBwsor8TooI/0TVg
# 3vx8to5eRczI7rEuu9Bn64JKLWF1O58ULuhIH8JTlFt8hUdcbSPWjafW2d7h4Js1
# 8qpQ9MTfW01tYFHbdiLLSveRCYd5gTUYtsvinCSepqKnUFGfpYhQwm2CdxrAQ3fd
# /wBgZnhrc2ceinMZVXqd598ZVqDhN27L6jLVgX6yEKGhd0yp+E9YWkd7e4kZPgYk
# SI2zj7bxr/AdS4X5pFpHRw3k/teU7BTXfrSJQIm1B28pBo0DAYjb0o7BLdAauJH0
# XaM4Y9QCWl4TMIIHcTCCBVmgAwIBAgITMwAAABXF52ueAptJmQAAAAAAFTANBgkq
# hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
# bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
# IDIwMTAwHhcNMjEwOTMwMTgyMjI1WhcNMzAwOTMwMTgzMjI1WjB8MQswCQYDVQQG
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg
# VGltZS1TdGFtcCBQQ0EgMjAxMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAOThpkzntHIhC3miy9ckeb0O1YLT/e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+
# F2Az/1xPx2b3lVNxWuJ+Slr+uDZnhUYjDLWNE893MsAQGOhgfWpSg0S3po5GawcU
# 88V29YZQ3MFEyHFcUTE3oAo4bo3t1w/YJlN8OWECesSq/XJprx2rrPY2vjUmZNqY
# O7oaezOtgFt+jBAcnVL+tuhiJdxqD89d9P6OU8/W7IVWTe/dvI2k45GPsjksUZzp
# cGkNyjYtcI4xyDUoveO0hyTD4MmPfrVUj9z6BVWYbWg7mka97aSueik3rMvrg0Xn
# Rm7KMtXAhjBcTyziYrLNueKNiOSWrAFKu75xqRdbZ2De+JKRHh09/SDPc31BmkZ1
# zcRfNN0Sidb9pSB9fvzZnkXftnIv231fgLrbqn427DZM9ituqBJR6L8FA6PRc6ZN
# N3SUHDSCD/AQ8rdHGO2n6Jl8P0zbr17C89XYcz1DTsEzOUyOArxCaC4Q6oRRRuLR
# vWoYWmEBc8pnol7XKHYC4jMYctenIPDC+hIK12NvDMk2ZItboKaDIV1fMHSRlJTY
# uVD5C4lh8zYGNRiER9vcG9H9stQcxWv2XFJRXRLbJbqvUAV6bMURHXLvjflSxIUX
# k8A8FdsaN8cIFRg/eKtFtvUeh17aj54WcmnGrnu3tz5q4i6tAgMBAAGjggHdMIIB
# 2TASBgkrBgEEAYI3FQEEBQIDAQABMCMGCSsGAQQBgjcVAgQWBBQqp1L+ZMSavoKR
# PEY1Kc8Q/y8E7jAdBgNVHQ4EFgQUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXAYDVR0g
# BFUwUzBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5t
# aWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQM
# MAoGCCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQE
# AwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQ
# W9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNv
# bS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBa
# BggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0
# LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqG
# SIb3DQEBCwUAA4ICAQCdVX38Kq3hLB9nATEkW+Geckv8qW/qXBS2Pk5HZHixBpOX
# PTEztTnXwnE2P9pkbHzQdTltuw8x5MKP+2zRoZQYIu7pZmc6U03dmLq2HnjYNi6c
# qYJWAAOwBb6J6Gngugnue99qb74py27YP0h1AdkY3m2CDPVtI1TkeFN1JFe53Z/z
# jj3G82jfZfakVqr3lbYoVSfQJL1AoL8ZthISEV09J+BAljis9/kpicO8F7BUhUKz
# /AyeixmJ5/ALaoHCgRlCGVJ1ijbCHcNhcy4sa3tuPywJeBTpkbKpW99Jo3QMvOyR
# gNI95ko+ZjtPu4b6MhrZlvSP9pEB9s7GdP32THJvEKt1MMU0sHrYUP4KWN1APMdU
# bZ1jdEgssU5HLcEUBHG/ZPkkvnNtyo4JvbMBV0lUZNlz138eW0QBjloZkWsNn6Qo
# 3GcZKCS6OEuabvshVGtqRRFHqfG3rsjoiV5PndLQTHa1V1QJsWkBRH58oWFsc/4K
# u+xBZj1p/cvBQUl+fpO+y/g75LcVv7TOPqUxUYS8vwLBgqJ7Fx0ViY1w/ue10Cga
# iQuPNtq6TPmb/wrpNPgkNWcr4A245oyZ1uEi6vAnQj0llOZ0dFtq0Z4+7X6gMTN9
# vMvpe784cETRkPHIqzqKOghif9lwY1NNje6CbaUFEMFxBmoQtB1VM1izoXBm8qGC
# A1AwggI4AgEBMIH5oYHRpIHOMIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz
# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv
# cnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25z
# MScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046QTAwMC0wNUUwLUQ5NDcxJTAjBgNV
# BAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WiIwoBATAHBgUrDgMCGgMV
# AI2S+7Q0pxKN1grKuEllyzJc5RM0oIGDMIGApH4wfDELMAkGA1UEBhMCVVMxEzAR
# BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p
# Y3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3Rh
# bXAgUENBIDIwMTAwDQYJKoZIhvcNAQELBQACBQDtJ1gPMCIYDzIwMjYwMTMwMTYx
# NzE5WhgPMjAyNjAxMzExNjE3MTlaMHcwPQYKKwYBBAGEWQoEATEvMC0wCgIFAO0n
# WA8CAQAwCgIBAAICE18CAf8wBwIBAAICEz4wCgIFAO0oqY8CAQAwNgYKKwYBBAGE
# WQoEAjEoMCYwDAYKKwYBBAGEWQoDAqAKMAgCAQACAwehIKEKMAgCAQACAwGGoDAN
# BgkqhkiG9w0BAQsFAAOCAQEAuprll6Fu9W1p31D624laoGkJAD3RCygnSJXTv6TZ
# DIg9TNq1s2/P7gUBJFGVsiwKghOCHdavRAByAjbve1YGkOaV76idY89VtWYWlEmS
# t6bYoI0Ww+Oh1/YRe2M2LNR2nhevxhyyP2XvFrNO4yWVCgara6l3ItF2o2LpYQNf
# 8CBWBQf68WyGJi/vOAxycf8RDXtMFxaxtUD+RDPgHaVq3BfVIknm71kGF/CZF9CK
# w55P0c9QySq0ifJPwJ3h2RCeXD3GuzyYGErIYNx4uNhNiG2V3VbKbtyPwkTzgW0K
# nYE26Qy+XkOhk/jJewnZB7MonsUj259cpooZzdzwOkdoyjGCBA0wggQJAgEBMIGT
# MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMT
# HU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAACCHidWF2Sx9lSAAEA
# AAIIMA0GCWCGSAFlAwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQ
# AQQwLwYJKoZIhvcNAQkEMSIEIFgHC4SBh/ChW0DbaKN9OmARDH3fyEkX+WpgnQGU
# JwmnMIH6BgsqhkiG9w0BCRACLzGB6jCB5zCB5DCBvQQgj/+ObwkdrZbU73vvy334
# W3Znk2Yqq20+TpD71FGmZ6kwgZgwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UE
# CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z
# b2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQ
# Q0EgMjAxMAITMwAAAgh4nVhdksfZUgABAAACCDAiBCBatbdbk/9Pzw/y63IMo6Gx
# 2p0kR8/hWMZVNgSCbyWD9zANBgkqhkiG9w0BAQsFAASCAgAk5RoAgR36sjPnv1di
# xQOMJKwYnc28zFye/ORMZoSGmJLXJO286A9g4TJf+2wl7hG1zBWXL0GikWUMp+Ry
# jd0VAsWo+89GktPOBMPODgI0iZXBYDLarnjmLTZvTqBAjfSnwkftyVyKVHCIzqVr
# ekjRx5h6oG1/XDVTt/3ydytiZgK+rmnoKES6GYrSBI0JM4/a/FAblSJLznDn+CLe
# hApZm0XuXxaK7sHyaic5/eJM68Xi2tgcu+hU9flzv3/qajbBBdohmzCRM1iGI58U
# CJ8S9lTGZi4f8fw4ZXLekBb2utFfIwfh9M19/ZPAfHYYkpKp62e0PVNO9dKDCd/A
# RD70wfPsULc/bBxQ6W7fMSm2VPgkdN7kZHj1kwc01SNIrwNAdK3eXWAPOSbvq4/P
# Uczr07bohKmOZY85lpIck1MFPH4eeX33lMEn5oheuA5L6oA+F5rdUkY9YKAezBo1
# hMqZhzAyn3JKkQ/CG8BIKAtU6sbWQSVUtTB5W8XDNN6ZMvGPr/woIbhTEhYToLaa
# Ziw9zBrOc2GrZ/EVbZ/+vej+HKZwt4Za0IdhyVy6oRbbnOarl7n4YHKsSbCZII0C
# X8P0sCFKH21h212ThExDDfztHGbfzfeuqBlLD7vRRH8P4vpGARtLVZx9C+4tC4S9
# k6SPPNhdCRe7+9WZTTxaxRXMwg==
# SIG # End signature block