Git.psm1

function Add-GitTag {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string] $Version
    )

    $tagName = "v$Version"
    $sha = Start-NativeExecution git rev-parse HEAD
    $shortSha = $shortSha = $sha.Substring(0, 8)
    $commitMessage = "Added tag $tagName for changeset $shortSha"

    Log info $commitMessage
    Start-NativeExecution git tag -a $tagName -m $commitMessage
}

function Clear-GitBranches {
    [CmdletBinding()]
    param(
        [switch] $IncludeGoneRemoteBranches
    )

    $currentBranch = Start-NativeExecution git rev-parse --abbrev-ref HEAD
    if ($LASTEXITCODE -ne 0) {
        Log warning 'Error on getting the current branch. Are you outside of a Git repository?'
        Log trace "$currentBranch"
        return
    }

    Log info "Searching for branches which already merged into '$currentBranch'..."

    $branches = @{ }

    # 1. Try the default way (no remote rebased branches can be detected)
    $mergedBranches = Get-GitMergedBranches
    $mergedBranches | ForEach-Object { Log trace "Branch found with Git default logic: '$_'" }
    if ($mergedBranches) {
        $branches.Add('default logic', $mergedBranches) > $null
    }

    # 2. Try the custom way (check each hash, also remote rebased branches can be detected)
    $mergedOrRebasedBranches = Get-GitMergedOrRebasedBranches
    $mergedOrRebasedBranches | ForEach-Object { Log trace "Branch found with Git deeper logic: '$_'" }
    if ($mergedOrRebasedBranches) {
        $branches.Add('deep logic', $mergedOrRebasedBranches) > $null
    }

    # 3. Try also the rebased and squashed logic (check for branches which are already contained in the current branch, even if they were rebased or squashed)
    $rebasedAndSquashedBranches = Get-RebasedAndSquashedBranches
    $rebasedAndSquashedBranches | ForEach-Object { Log trace "Branch found with Git rebased and squashed logic: '$_'" }
    if ($rebasedAndSquashedBranches) {
        $branches.Add('rebased and squashed logic', $rebasedAndSquashedBranches) > $null
    }

    # 4. Try also the remote gone logic (check for branches which are removed on remote, but still exist locally)
    if ($IncludeGoneRemoteBranches) {
        # 3. Get also remote gone branches
        $remoteGoneBranches = Get-GitRemoteGoneBranches
        $remoteGoneBranches | ForEach-Object { Log trace "Branch found with Git remote gone logic: '$_'" }
        if ($remoteGoneBranches) {
            $branches.Add('gone logic', $remoteGoneBranches) > $null
        }
    }

    # Filter out duplicates
    $uniqueMergedBranches = Get-Distincted @($mergedBranches, $mergedOrRebasedBranches, $rebasedAndSquashedBranches, $remoteGoneBranches) | Sort-Object
    if (-not $uniqueMergedBranches) {
        Log info 'No merged branches were found'
        return
    }

    $sb = [System.Text.StringBuilder]::new()
    $prefix = 'Merged branch:'
    $logicColumn = ($uniqueMergedBranches | Sort-Object Length -Descending | Select-Object -First 1).Length + 2
    foreach ($branch in $uniqueMergedBranches) {
        $logics = Get-Logics -groupedBranches $branches -branchName $branch

        $sb.Clear() > $null
        $sb.Append(("$prefix {0,-$logicColumn} {1}" -f "'$($branch)'", "[detected by: $($logics -join ', ')]")) > $null

        Log info $sb.ToString()
    }

    $title = 'Delete merged branches'
    $message = 'Do you want to delete the already-merged local branches displayed above?'
    $yes = New-Object System.Management.Automation.Host.ChoiceDescription '&Yes', 'Delete the remote branches listed.'
    $no = New-Object System.Management.Automation.Host.ChoiceDescription '&No', 'Leave the branches alone.'
    $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)

    $result = $Host.UI.PromptForChoice($title, $message, $options, 1)
    if ($result -eq 1) {
        return
    }

    $uniqueMergedBranches | ForEach-Object { Start-NativeExecution git branch -D $_ | Log info }
}

function Get-GitMergedBranches() {
    $mergedBranches = [System.Collections.ArrayList]@()
    $branches = Start-NativeExecution git branch --merged
    if ($LASTEXITCODE -ne 0) {
        Log trace "Error on getting merged branches: $branches"
        return
    }

    $filteredBranches = $branches | ForEach-Object { $_.Trim() } | Where-Object { $_ -notmatch '^\* (master|main)$' } | Where-Object { $_ -notmatch '^(master|main)$' } | Where-Object { $_ -notmatch '^\* .*$' }

    foreach ($branch in $filteredBranches) {
        Log trace "Branch already merged '$branch'"
        $mergedBranches.Add($branch) > $null
    }

    return $mergedBranches
}

function Get-GitMergedOrRebasedBranches() {
    $currentBranch = Start-NativeExecution git rev-parse --abbrev-ref HEAD
    if ($LASTEXITCODE -ne 0) {
        Log trace "Error on getting merged or rebased branches: $currentBranch"
        return
    }

    Log trace "currentBranch: '$currentBranch'"

    $currentLocalBranch = Start-NativeExecution git symbolic-ref -q HEAD
    if ($LASTEXITCODE -ne 0) {
        Log trace "Error on getting merged or rebased branches: $currentLocalBranch"
        return
    }

    Log trace "currentLocalBranch: '$currentLocalBranch'"

    $currentRemoteBranch = Start-NativeExecution git for-each-ref '--format="%(upstream:short)"' $currentLocalBranch
    if ($LASTEXITCODE -ne 0) {
        Log trace "Error on getting merged or rebased branches: $currentRemoteBranch"
        return
    }

    Log trace "currentRemoteBranch: '$currentRemoteBranch'"

    $mergedbranches = [System.Collections.ArrayList]@()

    if (-not $currentRemoteBranch) {
        return $mergedbranches
    }

    $localBranches = Start-NativeExecution git for-each-ref refs/heads '--format="%(refname:short)"' | Where-Object { $_ -notmatch '(master|main)' } | Where-Object { $_ -notmatch $currentBranch }
    if ($LASTEXITCODE -ne 0) {
        Log trace "Error on getting merged or rebased branches: $localBranches"
        return
    }

    foreach ($localBranch in $localBranches) {
        $notMergedHashFound = $false
        Log trace "Check local branch '$localBranch'..."
        $results = Start-NativeExecution git cherry $currentRemoteBranch $localBranch
        if ($LASTEXITCODE -ne 0) {
            Log trace "Get merged hashes failed: '$results'"
            break
        }

        foreach ($result in $results) {
            if ($result -match '^\-') {
                Log trace "Hash merged '$result'"
                continue
            }

            if ($result -match '^\+') {
                Log trace "Hash was not merged '$result'"
            } else {
                Log trace "No hash '$result'"
            }

            $notMergedHashFound = $true
            break
        }

        if (-not $notMergedHashFound) {
            Log trace "Branch already merged '$localBranch'"
            $mergedbranches.Add($localBranch) > $null
        }
    }

    return $mergedbranches
}

function Get-RebasedAndSquashedBranches {
    <#
    .SYNOPSIS
        Finds local branches whose changes are already contained in the current branch.
 
    .DESCRIPTION
        Iterates over all local branches (except the current one) and uses a test merge
        to check whether the branch's content is already present in the current branch.
        Detects squash and rebase merges where commit SHAs no longer match.
 
    .PARAMETER ExcludeBranches
        Branch names to skip (e.g. 'develop', 'release/*').
        The current branch is skipped automatically.
 
    .EXAMPLE
        Get-RebasedAndSquashedBranches
 
    .EXAMPLE
        Get-RebasedAndSquashedBranches -ExcludeBranches 'develop','staging'
    #>

    [CmdletBinding()]
    param(
        [string[]]$ExcludeBranches = @()
    )

    # Make sure we are inside a Git repository
    git rev-parse --is-inside-work-tree 2>$null | Out-Null
    if ($LASTEXITCODE -ne 0) {
        Write-Error 'Not a Git repository in the current directory.'
        return
    }

    # Make sure the working directory is clean - otherwise the test merge could go wrong
    $status = git status --porcelain
    if ($status) {
        Write-Error 'Working directory is not clean. Please commit or stash first.'
        return
    }

    # Determine the current branch (this is the target branch for comparison)
    $currentBranch = git rev-parse --abbrev-ref HEAD
    if ($currentBranch -eq 'HEAD') {
        Write-Error 'Detached HEAD - please check out a branch first.'
        return
    }

    Write-Verbose "Checking branches against '$currentBranch'..."

    # Get all local branches, filter out the current one and excluded ones
    $allBranches = git branch --format='%(refname:short)' |
    Where-Object { $_ -ne $currentBranch -and $_ -notin $ExcludeBranches }

    if (-not $allBranches) {
        Write-Verbose 'No branches to check.'
        return
    }

    $mergedBranches = @()

    foreach ($branch in $allBranches) {
        Write-Verbose "Checking '$branch'..."

        # Run a test merge without committing, suppress stderr
        git merge --no-commit --no-ff $branch 2>&1 | Out-Null
        $mergeExitCode = $LASTEXITCODE

        if ($mergeExitCode -ne 0) {
            # Merge conflict - branch definitely contains its own changes
            Write-Verbose " '$branch' has conflicts - skipping."
            git merge --abort 2>&1 | Out-Null
            continue
        }

        # Check whether the merge produced any actual content changes
        $diff = git diff --cached --stat

        # Always abort the merge afterwards
        # On "Already up to date" there is no active merge -> --abort would fail
        $mergeHead = git rev-parse --verify --quiet MERGE_HEAD 2>$null
        if ($mergeHead) {
            git merge --abort 2>&1 | Out-Null
        }

        if (-not $diff) {
            # No changes -> branch content is already included
            Write-Verbose " '$branch' is already included."
            $mergedBranches += $branch
        } else {
            Write-Verbose " '$branch' still has open changes."
        }
    }

    return $mergedBranches
}

function Get-GitRemoteGoneBranches() {
    $goneBranches = [System.Collections.ArrayList]@()
    $branches = Start-NativeExecution git branch -v
    if ($LASTEXITCODE -ne 0) {
        Log trace "Error on getting remote gone branches: $branches"
        return
    }

    $filteredBranches = $branches | ForEach-Object { $_.Trim() } | Where-Object { $_ -notmatch '^\* (master|main)' } | Where-Object { $_ -notmatch '^(master|main)' } | Where-Object { $_ -notmatch '^\* .*' } | Where-Object { $_ -match '^.*\[gone\].*' }
    if (-not $filteredBranches) {
        Log trace 'No remote gone branches found'
        return
    }

    $filteredBranchNames = $filteredBranches | ForEach-Object { $_.Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[0] }
    foreach ($branchName in $filteredBranchNames) {
        Log trace "Branch is removed on remote '$branchName'"
        $goneBranches.Add($branchName) > $null
    }

    return $goneBranches
}

function Get-Distincted {
    param(
        [Parameter()]
        [object[][]] $Items
    )

    $hashSet = [System.Collections.Generic.HashSet[System.Object]]::new()
    foreach ($item in $Items) {
        foreach ($entry in $item) {
            $hashSet.Add($entry) > $null
        }
    }

    $distinctedList = [System.Collections.ArrayList]@()
    foreach ($value in $hashSet) {
        $distinctedList.Add($value) > $null
    }

    return $distinctedList
}

function Get-Logics([hashtable] $groupedBranches, [string] $branchName) {
    $logics = [System.Collections.ArrayList]@()

    foreach ($logic in $groupedBranches.GetEnumerator()) {
        [object[]] $values = $logic.Value
        if ($values.Contains($branchName)) {
            $logics.Add($logic.Name) > $null
        }
    }

    return $logics
}

function Invoke-GitkAll() {
    Invoke-Gitk -All @args
}

function Invoke-Gitk() {
    param(
        [switch] $All
    )

    $command = 'gitk'
    $arguments = [System.Collections.ArrayList]@()

    if ($All) {
        $arguments.Add('--all') > $null
    }

    $arguments += $args
    Start-NativeExecution $command @arguments
}

function Merge-GitAllRemoteBranches($RemoteRefs = $null, $Strategie = 'recursive', [switch] $UseTheirs = $false, [switch] $UseOurs = $false) {
    if ($null -eq $RemoteRefs) {
        $RemoteRefs = 'origin/'
    }

    $currentBranch = (git rev-parse --abbrev-ref HEAD).Trim()

    git fetch --all
    git branch -r | ForEach-Object {
        $localBranch = $_
        $localBranch = $localBranch.Trim().Replace($RemoteRefs, '').Trim()
        $localBranch = $localBranch.Trim().Replace('*', '').Trim()
        $remoteBranch = $_.Trim().Replace('*', '').Trim()
        if ($remoteBranch.StartsWith($RemoteRefs) -and -not $remoteBranch.StartsWith($RemoteRefs + 'HEAD')) {
            Log info "Processing branch '${localBranch}'..."
            git checkout $localBranch

            if ($UseTheirs) {
                git merge $remoteBranch -s $Strategie -X theirs
            } elseif ($UseOurs) {
                git merge $remoteBranch -s $Strategie -X ours
            } else {
                git merge $remoteBranch
            }
        }
    }

    git checkout $currentBranch
}

function Merge-GitBranchUseTheirs($SourceBranchName, $DestinationBranchName) {
    if (($null -eq $SourceBranchName) -or ($null -eq $DestinationBranchName)) {
        return
    }

    $currentBranch = (git rev-parse --abbrev-ref HEAD).Trim()
    $tempHash = Get-Checksum -Value ([System.Guid]::NewGuid()) -Algorithm SHA1
    $tempBranchName = "merge-use-theirs-${tempHash}"
    $commitMessage = "Merge branch '${SourceBranchName}' into '${DestinationBranchName}'"

    git checkout -b $tempBranchName $SourceBranchName
    git merge --strategy=ours $DestinationBranchName
    git checkout $DestinationBranchName
    git merge --no-ff $tempBranchName -m $commitMessage
    git branch -D $tempBranchName

    git checkout $currentBranch
}

function Push-GitAllTrackedBranches($RemoteRefs) {
    if ($null -eq $RemoteRefs) {
        $RemoteRefs = 'origin/'
    }

    $currentBranch = (git rev-parse --abbrev-ref HEAD).Trim()

    git branch | ForEach-Object {
        $localBranch = $_
        $localBranch = $localBranch.Trim().Replace('*', '').Trim()

        $trackingRefs = git config branch.$localBranch.merge
        if ($trackingRefs -and ($trackingRefs.Trim().StartsWith('refs/heads/' + $RemoteRefs))) {
            Log info "Processing branch '${localBranch}'..."
            git checkout $localBranch
            git push
        }
    }

    git checkout $currentBranch
}

function Remove-GitAllBranches($RemoteRefs, [switch] $ForceAll = $false) {
    if ($null -eq $RemoteRefs) {
        $RemoteRefs = 'origin/'
    }

    $currentBranch = (git rev-parse --abbrev-ref HEAD).Trim()
    $tempHash = Get-Checksum -Value ([System.Guid]::NewGuid()) -Algorithm SHA1
    $tempBranchName = "remove-all-${tempHash}"

    git checkout -f -b $tempBranchName

    git branch | ForEach-Object {
        $localBranch = $_
        $localBranch = $localBranch.Trim().Replace('*', '').Trim()

        $trackingRefs = git config branch.$localBranch.merge
        if ($trackingRefs -and ($localBranch -ne $tempBranchName) -and (($ForceAll) -or ($null -ne $trackingRefs))) {
            if (($ForceAll) -or
                ($trackingRefs.Trim().StartsWith('refs/remotes/' + $RemoteRefs)) -or
                ($trackingRefs.Trim().StartsWith('refs/heads/' + $RemoteRefs))) {
                Log info "Delete local branch '${localBranch}'..."
                git branch -D $localBranch
            }
        }
    }

    if ($ForceAll) {
        git checkout master
    } else {
        git checkout $currentBranch
    }

    git branch -D $tempBranchName
}

function Reset-GitAllBranches($RemoteRefs) {
    Remove-GitAllBranches $RemoteRefs
    Set-GitTrackAllRemoteBranches $RemoteRefs
    Merge-GitAllRemoteBranches $RemoteRefs
}

function Set-GitTrackAllRemoteBranches($RemoteRefs) {
    if ($null -eq $RemoteRefs) {
        $RemoteRefs = 'origin/'
    }

    $localBranches = git branch | ForEach-Object { $_.Trim().Replace('*', '').Trim() }

    $notTrackedLocalBranches = @()
    git for-each-ref --format='%(refname:short) <- %(upstream:short)' 'refs/heads' | ForEach-Object {
        $row = $_ -split '<-'
        $localBranch = $row[0].Trim()
        $remoteBranch = $row[1].Trim()

        $query = "branch.${localBranch}.remote"
        $configRemote = git config --get $query
        if (-not $remoteBranch -and -not $configRemote) {
            $notTrackedLocalBranches += $localBranch
        }
    }

    git branch -r | ForEach-Object {
        $localBranch = $_
        $localBranch = $localBranch.Trim().Replace($remoteRefs, '').Trim()
        $localBranch = $localBranch.Trim().Replace('*', '').Trim()
        $remoteBranch = $_.Trim().Replace('*', '').Trim()

        if ($remoteBranch.StartsWith($remoteRefs + 'HEAD') -or -not ($remoteBranch.StartsWith($remoteRefs))) {
            return
        }

        if (-not ($notTrackedLocalBranches -contains $localBranch) -and -not ($localBranches -contains $localBranch)) {
            git branch -t $localBranch $remoteBranch
        } elseif ($notTrackedLocalBranches -contains $localBranch) {
            git branch -u $remoteBranch $localBranch
        }
    }
}

function Set-GitTrackMatchedRemoteBranches($RemoteRefs) {
    if ($null -eq $RemoteRefs) {
        $RemoteRefs = 'origin/'
    }

    $notTrackedLocalBranches = @()

    git for-each-ref --format='%(refname:short) <- %(upstream:short)' 'refs/heads' | ForEach-Object {
        $row = $_ -split '<-'
        $localBranch = $row[0].Trim()
        $remoteBranch = $row[1].Trim()

        $query = "branch.${localBranch}.remote"
        $configRemote = git config --get $query
        if (-not $remoteBranch -and -not $configRemote) {
            $notTrackedLocalBranches += $localBranch
        }
    }

    $remotes = git branch -r | ForEach-Object { $_.Trim().Replace('*', '').Trim() }

    $notTrackedLocalBranches | ForEach-Object {
        $localBranch = $_
        $remotes | ForEach-Object {
            $remoteBranch = $_
            if ($remoteBranch -eq ($RemoteRefs + $localBranch)) {
                git branch -u $remoteBranch $localBranch
                return
            }
        }
    }
}

function Update-GitAllBranches() {
    $currentBranch = git rev-parse --abbrev-ref HEAD

    git fetch --all

    $branchPairs = git for-each-ref --format='%(refname:short) <- %(upstream:short)' 'refs/heads'
    $branchPairs | ForEach-Object {
        $pair = $_ -split ' <- '
        $localBranch = $pair[0]
        $remoteBranch = $pair[1]
        if ($localBranch -and $remoteBranch) {
            Log info "Processing branch '${localBranch}'..."
            git checkout $localBranch
            git rebase $remoteBranch
        }
    }

    git checkout $currentBranch
}

function Update-GitBranch() {
    git fetch --all

    $localBranch = git rev-parse --abbrev-ref HEAD
    $remoteBranch = git rev-parse --abbrev-ref --symbolic-full-name '@{upstream}'
    if (-not $remoteBranch) {
        Print-Warning "No upstream configured for branch '${localBranch}'"
        return
    }

    $remoteBranches = git for-each-ref --format='%(upstream:short)' 'refs/heads'
    foreach ($branch in $remoteBranches) {
        if ( $branch -eq $remoteBranch) {
            Log info "Rebase branch '${remoteBranch}' into '${localBranch}'..."
            git rebase $remoteBranch
            break
        }
    }
}

function Add-AssumedUnchanged {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string] $Path
    )

    $files = Get-Item $Path | Select-Object -ExpandProperty FullName
    $files | Log info

    $title = 'Add assume-unchanged flag'
    $message = 'Do you want to add the assume-unchanged flag for the files displayed above?'
    $yes = New-Object System.Management.Automation.Host.ChoiceDescription '&Yes', 'Add the assume-unchanged flag for each file at the Git index.'
    $no = New-Object System.Management.Automation.Host.ChoiceDescription '&No', 'Does not make any changes.'
    $options = [System.Management.Automation.Host.ChoiceDescription[]] @($yes, $no)

    $choice = $Host.UI.PromptForChoice($title, $message, $options, 1)
    switch ($choice) {
        0 {
            foreach ($file in $files) {
                git update-index --assume-unchanged -- $file
            }
            Log info 'Add assumed-unchanged.'
        }
        1 { Log info 'Nothing changed.' }
    }
}

function Remove-AssumedUnchanged {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string] $Path
    )

    $files = Get-Item $Path | Select-Object -ExpandProperty FullName
    $files | Log info

    $title = 'Remove assume-unchanged flag'
    $message = 'Do you want to remove the assume-unchanged flag for the files displayed above?'
    $yes = New-Object System.Management.Automation.Host.ChoiceDescription '&Yes', 'Remove the assume-unchanged flag for each file at the Git index.'
    $no = New-Object System.Management.Automation.Host.ChoiceDescription '&No', 'Does not make any changes.'
    $options = [System.Management.Automation.Host.ChoiceDescription[]] @($yes, $no)

    $choice = $Host.UI.PromptForChoice($title, $message, $options, 1)
    switch ($choice) {
        0 {
            foreach ($file in $files) {
                git update-index --no-assume-unchanged -- $file
            }
            Log info 'Removed assumed-unchanged.'
        }
        1 { Log info 'Nothing changed.' }
    }
}

New-Alias agt Add-GitTag
New-Alias cgb Clear-GitBranches
New-Alias gk Invoke-Gitk
New-Alias gka Invoke-GitkAll
New-Alias pgst Push-GitAllTrackedBranches
New-Alias ugab Update-GitAllBranches
New-Alias ugb Update-GitBranch
# SIG # Begin signature block
# MIIn8gYJKoZIhvcNAQcCoIIn4zCCJ98CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCxUP2Z8Drb5RZk
# iYh2eSyGO5M0v4DIRn8o2KiAI7a0AaCCIP4wggWNMIIEdaADAgECAhAOmxiO+dAt
# 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV
# BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa
# Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy
# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD
# ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E
# MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy
# unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF
# xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1
# 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB
# MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR
# WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6
# nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB
# YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S
# UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x
# q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB
# NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP
# TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC
# AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
# Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv
# bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0
# aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB
# LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc
# Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov
# Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy
# oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW
# juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF
# mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z
# twGpn1eqXijiuZQwggahMIIEiaADAgECAhAHhD2tAcEVwnTuQacoIkZ5MA0GCSqG
# SIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx
# GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRy
# dXN0ZWQgUm9vdCBHNDAeFw0yMjA2MjMwMDAwMDBaFw0zMjA2MjIyMzU5NTlaMFox
# CzAJBgNVBAYTAkxWMRkwFwYDVQQKExBFblZlcnMgR3JvdXAgU0lBMTAwLgYDVQQD
# EydHb0dldFNTTCBHNCBDUyBSU0E0MDk2IFNIQTI1NiAyMDIyIENBLTEwggIiMA0G
# CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCtHvQHskNmiqJndyWVCqX4FtYp5FfJ
# LO9Sh0BuwXuvBeNYt21xf8h/pLJ/7YzeKcNq9z4zEhecqtD0xhbvSB8ksBAfWBMZ
# O0NLfOT0j7WyNuD7rv+ZFza+mxIQ79s1dCiwUMwGonaoDK7mqZfDpKEExR6UyKBh
# 3aatT73U2Imx/x+fYTmQFq+N8FrLs6Fh6YEGWJTgsxyw1fAChCfgtEcZkdtcgK7q
# uqskHtW6PJ9l5VNJ7T3WXpznsOOxrz3qx0CzWjwK8+3Kv2X6piWvd8YRfAOycSrT
# 4/PM0cHLFc5xs/4m/ek4FCnYSem43doFftBxZBQkHKoPW3Bt6VIrhVIwvO7hrUjh
# chJJZYdSld3bANDviJ5/ToP7ENv97U9MtKFvmC5dzd1p4HxFR0p5wWmYQbW+y3RF
# m0np6H9m57MUMNp0ysmdJjb0f7+dVLX3OEBUb6H+r1LRLZT/xEOTuwOxGg2S4w25
# KGL9SCBUW4nkBljPHeJToU+THt0P8ZQf4B9IFlGxtLK0g3uOAnwSFgKtmNjhkTl8
# caLAQwbgEINCqrhc0b6k2Z8+QwgVAL0nIuzM9ckKP8xtIcWg85L3/l0cTkHQde+j
# KGDG2CdxBHtflLIUtwqD7JA2uCxWlIzRNgwT0kH2en0+QV8KziSGaqO2r06kwboq
# 2/xy4e98CEfSYwIDAQABo4IBWTCCAVUwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNV
# HQ4EFgQUyfwQ71DIy2t/vQhE7zpik+1bXpowHwYDVR0jBBgwFoAU7NfjgtJxXWRM
# 3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMD
# MHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNl
# cnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20v
# RGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRw
# Oi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAc
# BgNVHSAEFTATMAcGBWeBDAEDMAgGBmeBDAEEATANBgkqhkiG9w0BAQsFAAOCAgEA
# C9sK17IdmKTCUatEs7+yewhJnJ4tyrLwNEnfl6HrG8Pm7HZ0b+5Jc+GGqJT8kRc7
# mihuVrdsYNHdicueDL9imhtCusI/rUmjwhtflp+XgLkmgLGrmsEho1b+lGiRp7LC
# /10di8SAOilDkHj5Zx142xRvBrrWj9eOdSGHwYubAsEd6CDojwcaVz9pfXMzYO3k
# c0O6PXg1TkcgkYlCUAuDHuk/sZx68W0FVj1P2iMh+VUq9lL1puroAydoeWVUh/+c
# MXeqfgpBqlAW+r8ma5F6yKL0stVQH8vYb1ES0mJSIPyIfkIjC1V0pbZS3p0QWsKa
# afEor8fLfLNfSxntVI/ugut0+6ekluPWRpEXH+JAiNdRjbLbZchCREe3/Xl0Ylwk
# A+eQVJfM0A7XiuFtY/mOpK2AN+E25t5mQYFhpdxZX5LTDKWgDnb+A6QnEt4iNyuk
# cLaJuS8IPgPz0E2ALZLt3Rqs+lXifK/GwnNIWQNbf7FmLDB9ph8i8dvsR1hsjc2K
# PEW4bAsbvLcz8hN1zE1/QbOV92vDGoFjwZOi2koQ+UyEh0e8jDFHAKJeTI+p8EPE
# /mqvojLFAnt31yXIA2tjt0ERtsjkhBNmZY6SEOfnIoOwvyqavLPya1Ut3/2cOFLu
# NQ8Ql6HaZsNQErnnzn+ZEAaUTkPZaeVyoHIkODECLzkwgga0MIIEnKADAgECAhAN
# x6xXBf8hmS5AQyIMOkmGMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUw
# EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x
# ITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yNTA1MDcwMDAw
# MDBaFw0zODAxMTQyMzU5NTlaMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdp
# Q2VydCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3Rh
# bXBpbmcgUlNBNDA5NiBTSEEyNTYgMjAyNSBDQTEwggIiMA0GCSqGSIb3DQEBAQUA
# A4ICDwAwggIKAoICAQC0eDHTCphBcr48RsAcrHXbo0ZodLRRF51NrY0NlLWZloMs
# VO1DahGPNRcybEKq+RuwOnPhof6pvF4uGjwjqNjfEvUi6wuim5bap+0lgloM2zX4
# kftn5B1IpYzTqpyFQ/4Bt0mAxAHeHYNnQxqXmRinvuNgxVBdJkf77S2uPoCj7GH8
# BLuxBG5AvftBdsOECS1UkxBvMgEdgkFiDNYiOTx4OtiFcMSkqTtF2hfQz3zQSku2
# Ws3IfDReb6e3mmdglTcaarps0wjUjsZvkgFkriK9tUKJm/s80FiocSk1VYLZlDwF
# t+cVFBURJg6zMUjZa/zbCclF83bRVFLeGkuAhHiGPMvSGmhgaTzVyhYn4p0+8y9o
# HRaQT/aofEnS5xLrfxnGpTXiUOeSLsJygoLPp66bkDX1ZlAeSpQl92QOMeRxykvq
# 6gbylsXQskBBBnGy3tW/AMOMCZIVNSaz7BX8VtYGqLt9MmeOreGPRdtBx3yGOP+r
# x3rKWDEJlIqLXvJWnY0v5ydPpOjL6s36czwzsucuoKs7Yk/ehb//Wx+5kMqIMRvU
# BDx6z1ev+7psNOdgJMoiwOrUG2ZdSoQbU2rMkpLiQ6bGRinZbI4OLu9BMIFm1UUl
# 9VnePs6BaaeEWvjJSjNm2qA+sdFUeEY0qVjPKOWug/G6X5uAiynM7Bu2ayBjUwID
# AQABo4IBXTCCAVkwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU729TSunk
# Bnx6yuKQVvYv1Ensy04wHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08w
# DgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEB
# BGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsG
# AQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVz
# dGVkUm9vdEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdp
# Y2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgG
# BmeBDAEEAjALBglghkgBhv1sBwEwDQYJKoZIhvcNAQELBQADggIBABfO+xaAHP4H
# PRF2cTC9vgvItTSmf83Qh8WIGjB/T8ObXAZz8OjuhUxjaaFdleMM0lBryPTQM2qE
# JPe36zwbSI/mS83afsl3YTj+IQhQE7jU/kXjjytJgnn0hvrV6hqWGd3rLAUt6vJy
# 9lMDPjTLxLgXf9r5nWMQwr8Myb9rEVKChHyfpzee5kH0F8HABBgr0UdqirZ7bowe
# 9Vj2AIMD8liyrukZ2iA/wdG2th9y1IsA0QF8dTXqvcnTmpfeQh35k5zOCPmSNq1U
# H410ANVko43+Cdmu4y81hjajV/gxdEkMx1NKU4uHQcKfZxAvBAKqMVuqte69M9J6
# A47OvgRaPs+2ykgcGV00TYr2Lr3ty9qIijanrUR3anzEwlvzZiiyfTPjLbnFRsjs
# Yg39OlV8cipDoq7+qNNjqFzeGxcytL5TTLL4ZaoBdqbhOhZ3ZRDUphPvSRmMThi0
# vw9vODRzW6AxnJll38F0cuJG7uEBYTptMSbhdhGQDpOXgpIUsWTjd6xpR6oaQf/D
# Jbg3s6KCLPAlZ66RzIg9sC+NJpud/v4+7RWsWCiKi9EOLLHfMR2ZyJ/+xhCx9yHb
# xtl5TPau1j/1MIDpMPx0LckTetiSuEtQvLsNz3Qbp7wGWqbIiOWCnb5WqxL3/BAP
# vIXKUjPSxyZsq8WhbaM2tszWkPZPubdcMIIG7TCCBNWgAwIBAgIQCoDvGEuN8QWC
# 0cR2p5V0aDANBgkqhkiG9w0BAQsFADBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMO
# RGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgVGlt
# ZVN0YW1waW5nIFJTQTQwOTYgU0hBMjU2IDIwMjUgQ0ExMB4XDTI1MDYwNDAwMDAw
# MFoXDTM2MDkwMzIzNTk1OVowYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lD
# ZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBTSEEyNTYgUlNBNDA5NiBUaW1l
# c3RhbXAgUmVzcG9uZGVyIDIwMjUgMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
# AgoCggIBANBGrC0Sxp7Q6q5gVrMrV7pvUf+GcAoB38o3zBlCMGMyqJnfFNZx+wvA
# 69HFTBdwbHwBSOeLpvPnZ8ZN+vo8dE2/pPvOx/Vj8TchTySA2R4QKpVD7dvNZh6w
# W2R6kSu9RJt/4QhguSssp3qome7MrxVyfQO9sMx6ZAWjFDYOzDi8SOhPUWlLnh00
# Cll8pjrUcCV3K3E0zz09ldQ//nBZZREr4h/GI6Dxb2UoyrN0ijtUDVHRXdmncOOM
# A3CoB/iUSROUINDT98oksouTMYFOnHoRh6+86Ltc5zjPKHW5KqCvpSduSwhwUmot
# uQhcg9tw2YD3w6ySSSu+3qU8DD+nigNJFmt6LAHvH3KSuNLoZLc1Hf2JNMVL4Q1O
# pbybpMe46YceNA0LfNsnqcnpJeItK/DhKbPxTTuGoX7wJNdoRORVbPR1VVnDuSeH
# VZlc4seAO+6d2sC26/PQPdP51ho1zBp+xUIZkpSFA8vWdoUoHLWnqWU3dCCyFG1r
# oSrgHjSHlq8xymLnjCbSLZ49kPmk8iyyizNDIXj//cOgrY7rlRyTlaCCfw7aSURO
# wnu7zER6EaJ+AliL7ojTdS5PWPsWeupWs7NpChUk555K096V1hE0yZIXe+giAwW0
# 0aHzrDchIc2bQhpp0IoKRR7YufAkprxMiXAJQ1XCmnCfgPf8+3mnAgMBAAGjggGV
# MIIBkTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTkO/zyMe39/dfzkXFjGVBDz2GM
# 6DAfBgNVHSMEGDAWgBTvb1NK6eQGfHrK4pBW9i/USezLTjAOBgNVHQ8BAf8EBAMC
# B4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwgZUGCCsGAQUFBwEBBIGIMIGFMCQG
# CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wXQYIKwYBBQUHMAKG
# UWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFRp
# bWVTdGFtcGluZ1JTQTQwOTZTSEEyNTYyMDI1Q0ExLmNydDBfBgNVHR8EWDBWMFSg
# UqBQhk5odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRU
# aW1lU3RhbXBpbmdSU0E0MDk2U0hBMjU2MjAyNUNBMS5jcmwwIAYDVR0gBBkwFzAI
# BgZngQwBBAIwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEBCwUAA4ICAQBlKq3xHCcE
# ua5gQezRCESeY0ByIfjk9iJP2zWLpQq1b4URGnwWBdEZD9gBq9fNaNmFj6Eh8/Ym
# RDfxT7C0k8FUFqNh+tshgb4O6Lgjg8K8elC4+oWCqnU/ML9lFfim8/9yJmZSe2F8
# AQ/UdKFOtj7YMTmqPO9mzskgiC3QYIUP2S3HQvHG1FDu+WUqW4daIqToXFE/JQ/E
# ABgfZXLWU0ziTN6R3ygQBHMUBaB5bdrPbF6MRYs03h4obEMnxYOX8VBRKe1uNnzQ
# VTeLni2nHkX/QqvXnNb+YkDFkxUGtMTaiLR9wjxUxu2hECZpqyU1d0IbX6Wq8/gV
# utDojBIFeRlqAcuEVT0cKsb+zJNEsuEB7O7/cuvTQasnM9AWcIQfVjnzrvwiCZ85
# EE8LUkqRhoS3Y50OHgaY7T/lwd6UArb+BOVAkg2oOvol/DJgddJ35XTxfUlQ+8Hg
# gt8l2Yv7roancJIFcbojBcxlRcGG0LIhp6GvReQGgMgYxQbV1S3CrWqZzBt1R9xJ
# gKf47CdxVRd/ndUlQ05oxYy2zRWVFjF7mcr4C34Mj3ocCVccAvlKV9jEnstrniLv
# UxxVZE/rptb7IRE2lskKPIJgbaP5t2nGj/ULLi49xTcBZU8atufk+EMF/cWuiC7P
# OGT75qaL6vdCvHlshtjdNXOCIUjsarfNZzCCBxswggUDoAMCAQICEAYFIuuX3jJX
# cLz8AeYyZmYwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCTFYxGTAXBgNVBAoT
# EEVuVmVycyBHcm91cCBTSUExMDAuBgNVBAMTJ0dvR2V0U1NMIEc0IENTIFJTQTQw
# OTYgU0hBMjU2IDIwMjIgQ0EtMTAeFw0yNTEyMjkwMDAwMDBaFw0yNjEyMjgyMzU5
# NTlaMGExCzAJBgNVBAYTAkRFMQ8wDQYDVQQIEwZCYXllcm4xETAPBgNVBAcTCEZh
# cmNoYW50MRYwFAYDVQQKEw1NYW51ZWwgVGFuemVyMRYwFAYDVQQDEw1NYW51ZWwg
# VGFuemVyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuxv/b0+nhaEE
# 94ewtCEHJFhCdgrwn6iF1lZ41Y40alX0LnSGBniZxw480yw+F9o6qhhprIpKvEoW
# WW1q+KNMxjdbLgKPlMcudU8DTfUVxKRxlVuqSMdizawGlQgwtwrj5RDsWEE2k0nq
# guNejIRWrWDn6JblBaj/WIx8DZ9YuYl6egi/KtJF5lYC6StOgymjFdZQ6WKs5v9Q
# IZMCvMw0BqpthVkFUXEQ07J49/h50bkl1dfNAnT2K8V2QeVGuJ5YOSs3GFMXiAxZ
# g6LJTHT0poTL5I5XD62X9xQ56LMRa9IDmFx6x4sMDrkn5oNVSGw7Vmx7cnI/5u1C
# 1pEymuN8vTa3DeMcVOngt7k9wRLyA+OTzdlobO+o+Hfr2S9zFVh+7PVDC0wUzrTd
# W7u1c63IK89HPHnTc37lnGFQUGPXYKXIooN6UhIbHRDTUFVO/sH2LysKLRyFWEs8
# qdOsszmx2zL+WNKmjrBmQBvPzrV7IimT6rpmpCYxEnoY/bFvXsmK5avv/Osj+efn
# GkCc9hm7oLxy494MFy3u5S1XqkB0jweBCJo750sGG3N8QapKAicVYobSXBdeLxsm
# H82yzsczRNPRAdyAGbFIe5vVpl43OSwclH9gRpREbdE63Bb8Uvyn+8FqECSb1f7N
# uLXsMwue6nHTf7Lc/u48srSd6yRnY70CAwEAAaOCAdQwggHQMB8GA1UdIwQYMBaA
# FMn8EO9QyMtrf70IRO86YpPtW16aMB0GA1UdDgQWBBREAaQBaa2AQTUPKUUkMbf9
# S5f5sDA+BgNVHSAENzA1MDMGBmeBDAEEATApMCcGCCsGAQUFBwIBFhtodHRwOi8v
# d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG
# CCsGAQUFBwMDMIGXBgNVHR8EgY8wgYwwRKBCoECGPmh0dHA6Ly9jcmwzLmRpZ2lj
# ZXJ0LmNvbS9Hb0dldFNTTEc0Q1NSU0E0MDk2U0hBMjU2MjAyMkNBLTEuY3JsMESg
# QqBAhj5odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vR29HZXRTU0xHNENTUlNBNDA5
# NlNIQTI1NjIwMjJDQS0xLmNybDCBgwYIKwYBBQUHAQEEdzB1MCQGCCsGAQUFBzAB
# hhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTQYIKwYBBQUHMAKGQWh0dHA6Ly9j
# YWNlcnRzLmRpZ2ljZXJ0LmNvbS9Hb0dldFNTTEc0Q1NSU0E0MDk2U0hBMjU2MjAy
# MkNBLTEuY3J0MAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggIBABqpRiImY/Bk
# WSYmqNEZsmjcqPNRBEp9bYFMylajgTFR7dOLqF9sCStkO+cs/X64RKHkZtlaCrQa
# ecZp6j/Dpq1fnkp2NfwuAaX2Osp/h6tMKnjaun3gvTdmI/j2iyJv6YJRxZ7daee7
# q9bkPzCTINwNc7AqWHbZ3Whlg+MmhLXaFHpoasR5JO9Vh+A8z8Y593G1bc7/Wjp2
# JWBNrCLjSUuz83YcDtf7yaURHuoJ96NDrHpbggaYU1s75sMhfBwAMTuYN2HmQe6/
# ShmDwGPtNzja0OtUdL0siHUp3Gouuqiux+ii7sjK0BDqvW3cbIQhCY41HkrJt4YF
# e+KAUzZXeger2mTb9StmWLTLuqTKvUnCpzsVlqEO1I6NwsXgV2u46/0EYqk42vBT
# e1vwXXj2Eawp5g4sSHQqbcxTAr/H5wZDIMp32tSyDMqV7zXhT6UWvxy5xua9Zkvf
# j7bn7CzUWgX/+GMyP8KlgXEDG5rCY1uSxleFBvn0ACZjWRp+kWl17WbdrIL22Kkl
# 2s1px/g9dfRbhHwNVAX1Mx2S7uCreeRs5qAA1cEjct2ulpNIbuPAEDDKenUHDTfN
# k0osUL9uaOjSx6HiVkcwPHgFzyMyu+SCVOUTpBhwBXIH+/r77s6XVnQWmjUHcZUY
# Y6KuwZiQ+E7joeAaZ0JGyW+LWx8WPfg7MYIGSjCCBkYCAQEwbjBaMQswCQYDVQQG
# EwJMVjEZMBcGA1UEChMQRW5WZXJzIEdyb3VwIFNJQTEwMC4GA1UEAxMnR29HZXRT
# U0wgRzQgQ1MgUlNBNDA5NiBTSEEyNTYgMjAyMiBDQS0xAhAGBSLrl94yV3C8/AHm
# MmZmMA0GCWCGSAFlAwQCAQUAoIGEMBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAw
# GQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisG
# AQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIJrDkVh1NqHsnBE2PZjFy7nR8apv+X6u
# v/jV0GbOdYLAMA0GCSqGSIb3DQEBAQUABIICAGY2Rs6oFTtDQ5GO+iFiX+G5k1jH
# 2bak5DdSM4BKOGWAAsyYaoxoPhZXyE1MWMUKtunhExYfUbKM+efvbYx0qLj/eY/r
# bYNk7YyJyz1PKo71BTMipDp3Ozsf9GWHkJxSq4RRG6PkVhB0qtLd4VT+kcfqAr5a
# Ikrp9AYrLYx6HNiIRcmgeQJwmBf2fkwUyjUZW6knUrMMKD3A2nw8wox9ULXBgGYz
# NPrnZ8ibCEBneWxPLjNIiVEQTUiKJSNcNPO17LVAdTiykWEgm/W0j9wKJqcOxsG0
# k1XQmN5XdZPJDzxBe3HEnkC+6rRwFuALG1BhhKuK0p8sTWLxd1K1gm4Hc9dGE7j6
# P15nVlii6sBrx1/RW+m2LZNABkxUHoxh6jCocFcPH73RKic8wl1rwU7nIRmktUwG
# 7V4QvqMvOu2teHl6G4UZ7MjvHOnX5bNGWGHCqmBD1XrJ0CJm5yw6ozPrhmgXuLIs
# kd3VI8pyWROu37lvV3Ab3jFn7yF7xohD2YJXDUTFdh773s5/Z6Fkomf8I0iSPsVJ
# TC3yzkN7kzzc/JeHMQ+2D9NiLBg/xPlAtFy/vk1/VIBYM0HPRWV3DMjDGomBtOmd
# MRHqlpRukpkLHe0ourLOVo9b2TpL1shEpqOiHTZHZ8aGPyw2it9Qyg1ovyyZZ4m1
# VYLeLRsSuELrXPSVoYIDJjCCAyIGCSqGSIb3DQEJBjGCAxMwggMPAgEBMH0waTEL
# MAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEwPwYDVQQDEzhE
# aWdpQ2VydCBUcnVzdGVkIEc0IFRpbWVTdGFtcGluZyBSU0E0MDk2IFNIQTI1NiAy
# MDI1IENBMQIQCoDvGEuN8QWC0cR2p5V0aDANBglghkgBZQMEAgEFAKBpMBgGCSqG
# SIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTI2MDQyNTE2NTgy
# OVowLwYJKoZIhvcNAQkEMSIEINBSMnJIhFKHsCWx0r8lgCllFO9KlBIheWZ62bPD
# M+e4MA0GCSqGSIb3DQEBAQUABIICAIJfLKjiDu9OHJQ9Yk0EzFNtEQEVnojsoaaR
# c3OuINweewc/mhREmcOyHBSGiPXBsZUWzhqzc4joCNlL8sueUFmh+ODSgOW4R+ub
# H/AIy60ifTN9Tns/kiIdOyoMbidhqqKLTo7qXVrY9HI9PcWyP2yTCgpmq8KyUKGf
# 1aJjTpNgovX5khbFb6G0LeZTm5rtjqRC6i62PIAJlMBf/msFthHH7fp8J+oz2O0D
# GaDV68MxRoUVvLn4MwgIphvyx+W7x7gpKC+lCcJDq3W+ALR5ot3QdCwJePOTrGRn
# 1CzCVZKCsQ9v+CsYzM1QJcYLvJHxdLfMmtx79o3eWjNLWTERQ7jhHI0pvDNH20sQ
# CaNnKUwij1ED2ImLGiZK8UckzRhG1Uqglvwsw8khuRmX1aCN6M+rzOGzEUsKHiYO
# gdRDPsLLd/ichZnfZUdoMR6m/9xooN4jowjMg4k8NoSRuOjSy812yQ0t4RHV+fQE
# vXwvixWo+dsfFBZGLAl8AZ71JS66bwJ91h+w/Hm5k/bRmDMxBhSFhHz3pJZh10GZ
# FUJSKNiNbXsHBEXV8l1X5Gld/hEgLJWV09+ZwZQNvXXNZNUHRBZ9Kf1yasy3vUzs
# GkE5lbq8lq4D3wGVTAFqPe/2oujrVWRwGgtQu0gEFaSwhd0zYEX4PP0/8XtSiOxj
# DQ2ZB8J/
# SIG # End signature block