Idabus.Automation.Core.psm1

##############################################
###
### IDABUS Ressource PowerShell
### (c) 2024 Oxford Computer Group GmbH
###
##############################################

Import-Module -PassThru -Name (Join-Path $PSScriptRoot 'IDABUS.Automation.Core51.dll')

##########################################################
###
### Get the user account this session ist connected with
###
##########################################################
function Get-IdabusLogonAccount
{
    <#
    .DESCRIPTION
    Get the user account this session ist connected with.
    #>

    $user = Send-IdabusGetRequest -ResourcePath "/user/person"

    return $user|convertfrom-json

}


##########################################################
###
### Get IDABUS Resource
###
##########################################################
function Get-IdabusResource
{

    <#
    .DESCRIPTION
    Get an IDABUS resource
    #>


    [CmdletBinding(DefaultParameterSetName = 'AttributeValue')]
    param(

        [Parameter(Mandatory = $true, ParameterSetName = 'AttributeValue', Position = 0)]
        [string] $ObjectType,

        [Parameter(Mandatory = $true, ParameterSetName = 'AttributeValue', Position = 1)]
        [string] $AttributeName,

        [Parameter(Mandatory = $true, ParameterSetName = 'AttributeValue', Position = 2)]
        [string] $AttributeValue,

        [Parameter(Mandatory = $true, ParameterSetName = 'ByID', Position = 0)]
        [Guid] $ID,

        [Parameter(ParameterSetName = 'ByID')]
        [Parameter(ParameterSetName = 'AttributeValue')]
        [switch]$IncludeNull,

        [Parameter(ParameterSetName = 'ByID')]
        [Parameter(ParameterSetName = 'AttributeValue')]
        [string[]] $AttributesToGet = @("*")
    )

    $f_qry_body = [PSCustomObject]@{
        attributes   = $AttributesToGet
        queryFormat  = if ($IncludeNull) { "IncludeNull" } else { "Standard" } #"Standard"/"IncludeNull"/"Verbose"
    }

    $f_qry_atts = [System.Collections.Generic.List[String]]::new()
    $AttributesToGet.ForEach({ $f_qry_atts.Add($psitem) })

    $f_qry_body.attributes = $f_qry_atts.ToArray()

    $f_qry_json  = ($f_qry_body | ConvertTo-Json)

    switch ($PsCmdlet.ParameterSetName) {
        "AttributeValue" {

            [String]$f_xpath = "/$ObjectType[$AttributeName='$AttributeValue']"
            $f_xpath_esc = [Uri]::EscapeDataString($f_xpath)

            $f_qry_results = (Send-IdabusPostRequest -ResourcePath "/Resources/Search" -Queries @("xPathQuery=$f_xpath_esc") -JsonContent $f_qry_json | ConvertFrom-Json)

            [PSCustomObject[]]$resultsEntries = $f_qry_results.results

            switch ($resultsEntries.count) {
                0 { return $null }

                1 {
                    Write-Output ($resultsEntries[0]|ConvertTo-DeltaEntry) -NoEnumerate:$false
                }

                default {
                    throw "More than one result found."
                }
            }
            

        }
        "ByID" {
            [PSCustomObject]$f_qry_result = (Send-IdabusPostRequest -ResourcePath "/Resources/$ID" -JsonContent $f_qry_json | ConvertFrom-Json)
            Write-Output ($f_qry_result|ConvertTo-DeltaEntry) -NoEnumerate:$false
        }
    }
}

##########################################################
###
### Save IDABUS Resource
###
##########################################################
function Save-IdabusResource
{

    <#
    .DESCRIPTION
    Save an IDABUS resource
    -FullObject saves the complete entry instead of modified attributes only
    #>


    [CmdletBinding(SupportsShouldProcess)]
    param(

        [parameter(Mandatory=$true, ValueFromPipeline=$true, Position = 0)]
        [PSCustomObject] $InputObject,

        [switch]$FullObject
    )


    PROCESS
    {
        $content=$null
        $id=$null
        if($null -eq ($InputObject |get-member -Name "__GetDeltaEntry"))
        {
            $content = $InputObject|ConvertTo-Json -Depth 100
            $id = $InputObject.objectid
        }
        else
        {
            if($FullObject){

                $entry = $InputObject.__SourceEntry
                $content = $entry|ConvertTo-Json -Depth 100
                $id=$entry.objectid

            }else{

                $entry = $InputObject.__GetDeltaEntry()
                $content = $entry|ConvertTo-Json -Depth 100
                $id=$entry.objectid
            }
        }



        if([string]::IsNullOrEmpty($id))
        {
            if($PSCmdlet.ShouldProcess($content))
            {
                $result = Send-IdabusPostRequest -ResourcePath "/Resources/" -JsonContent $content
                return convertfrom-json -InputObject $result
            }
        }
        else
        {
            if($PSCmdlet.ShouldProcess($content))
            {
                $result = Send-IdabusPatchRequest -ResourcePath "/Resources/$id" -JsonContent $content
                return convertfrom-json -InputObject $result
            }
        }



    }

}

##########################################################
###
### New IDABUS Resource
###
##########################################################
function New-IdabusResource
{
    <#
    .DESCRIPTION
    Create a new IDABUS resource.
    #>


    [CmdletBinding(SupportsShouldProcess)]
    param(

        [parameter(Mandatory=$true, Position = 0)]
        [string] $ObjectType
    )

    PROCESS
    {
        if($PSCmdlet.ShouldProcess($ObjectType))
        {
            return Get-IdabusSchemaBindings $ObjectType -WriteableOnly
        }
    }
}

##########################################################
###
### Delete IDABUS Resources
###
##########################################################
function Remove-IdabusResource
{

    <#
    .DESCRIPTION
    Delete an IDABUS resource.
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(

        [parameter(Mandatory=$true,ParameterSetName = 'xpath', Position = 0)]
        [string] $XPath,

        [parameter(Mandatory=$true,ParameterSetName = 'id', Position = 0)]
        [string] $ID,

        [parameter(Mandatory=$true,ParameterSetName = 'entry', Position = 0,  ValueFromPipeline=$true)]
        [PSCustomObject] $InputObject,

        [parameter(ParameterSetName = 'xpath')]
        [switch]$DisableReferenceCleanup,

        [parameter(ParameterSetName = 'xpath')]
        [switch]$EnablePreUpdateTriggers,

        [parameter(ParameterSetName = 'xpath')]
        [switch]$EnablePostUpdateTriggers,

        [parameter(ParameterSetName = 'xpath')]
        [parameter(ParameterSetName = 'id')]
        [parameter(ParameterSetName = 'entry')]
        [string]$Comment
    )


    PROCESS
    {


        $queries = @()

        $queries+= "xpath=$([Uri]::EscapeDataString($XPath))"

        if($DisableReferenceCleanup)
        {
            $queries += "disableReferenceCleanup=true"
        }

        if($EnablePreUpdateTriggers)
        {
            $queries += "disablePreUpdateTriggers=false"
        }

        if($EnablePostUpdateTriggers)
        {
            $queries += "disablePostUpdateTriggers=false"
        }

        if(![string]::IsNullOrEmpty($Comment))
        {
            $queries += "comment=" + [Uri]::EscapeDataString($Comment)
        }



        switch ($PsCmdlet.ParameterSetName)
        {
            "id"
            {
                if($PSCmdlet.ShouldProcess($ID))
                {
                    Send-IdabusDeleteRequest -ResourcePath "/Resources/$ID" -Queries $queries
                }
            }
            "entry"
            {

                $entryID = $InputObject.objectid
                if($PSCmdlet.ShouldProcess($entryID))
                {


                    if(![String]::IsNullOrEmpty($entryID))
                    {

                        Send-IdabusDeleteRequest -ResourcePath "/Resources/$entryID" -Queries $queries
                    }
                    else
                    {
                        throw "ObjectID on 'InputObject' is empty!"
                    }
                }
            }
            "xpath"
            {
                if($PSCmdlet.ShouldProcess($XPath))
                {
                    Send-IdabusDeleteRequest -ResourcePath "/Resources/xpath" -Queries $queries
                }
            }
        }

    }


}

##########################################################
###
### Search IDABUS Resources
###
##########################################################
Function Search-IdabusResource {

    <#
    .DESCRIPTION
    Search for IDABUS resources by XPATH queries.
    #>

    [CmdletBinding(DefaultParameterSetName='Undefined')]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'ExpectedObjectType',Justification='For backward compatibility')]
    param(
        [parameter(Mandatory=$true, Position = 0)]
        [string] $XPath,
        [parameter(Mandatory=$false, ParameterSetName = 'ExpectedObjectType', Position = 1)]
        [string] $ExpectedObjectType,
        [parameter(Mandatory=$false, ParameterSetName = 'AttributesToGet', Position = 1)]
        [string[]] $AttributesToGet,
        [parameter(Mandatory=$false, ParameterSetName = 'Unconstrained', Position = 1)]
        [switch] $Unconstrained,
        [parameter(Mandatory=$false)]
        [ValidateRange(1,[int32]::MaxValue)]
        [int32] $PageSize = 200,
        [parameter(Mandatory=$false)]
        [ValidateRange(1,[int32]::MaxValue)]
        [int32] $MaxResults = [int32]::MaxValue,
        [parameter(Mandatory=$false)]
        [string] $SortByAttribute,
        [parameter(Mandatory=$false)]
        [switch] $Descending
    )

    begin {
        if ($MaxResults -lt $PageSize) {
            $PageSize = $MaxResults
        }

        $f_qry_body = [PSCustomObject]@{
            attributes   = $AttributesToGet
            queryFormat  = "IncludeNull" #"Standard"/"IncludeNull"/"Verbose"
            pageSize     = $PageSize #$PageSize
            includeCount = "fastonly" #"None"/"fastonly"/"Forced"
        }

        if ($SortByAttribute) {

            $f_sort_order = 'Ascending'
            if ($Descending) { $f_sort_order = 'Descending' }

            $f_qry_order = @{attribute = $SortByAttribute; order = $f_sort_order}

            Add-Member -InputObject $f_qry_body -MemberType NoteProperty -Name 'orderBy' -Value $f_qry_order
        }

        $f_qry_atts = [System.Collections.Generic.List[String]]::new()

        switch ($PSCmdlet.ParameterSetName) {

            'AttributesToGet' {

                $f_qry_atts.Add("ObjectID")    # Default attribute to always query
                $f_qry_atts.Add("ObjectType")  # Default attribute to always query
                $AttributesToGet.ForEach({ $f_qry_atts.Add($psitem) })
                break
            }

            'ExpectedObjectType' { #For backward compatibility only!
                $f_qry_atts.Add('*')
                break
            }

            'Unconstrained' {
                $f_qry_atts.Add('*')
                break
            }

            default {
                $f_qry_atts.Add("ObjectID")    # Default attribute to always query
                $f_qry_atts.Add("ObjectType")  # Default attribute to always query
            }
        }

        $f_qry_body.attributes = $f_qry_atts.ToArray()

        $f_xpath_esc = [Uri]::EscapeDataString($XPath)
        $f_qry_json  = ($f_qry_body | ConvertTo-Json -Depth 100)
    }

    process {

        [int]$f_total_results = 0

        $f_qry_results = (Send-IdabusPostRequest -ResourcePath "/Resources/Search" -Queries @("xPathQuery=$f_xpath_esc") -JsonContent $f_qry_json | ConvertFrom-Json)

        [PSCustomObject[]]$resultsEntries = $f_qry_results.results
        $f_total_results = $f_total_results + $resultsEntries.count

        switch ($f_total_results) {

            1 {
                Write-Output ($resultsEntries[0]|ConvertTo-DeltaEntry) -NoEnumerate:$false
                break
            }

            default {
                Write-Output ($resultsEntries|ConvertTo-DeltaEntry) -NoEnumerate:($resultsEntries.Count -ge 2)
            }
        }

        if ($MaxResults -le $PageSize) {
            $f_qry_results.hasMoreItems = $false
        }

        while ([boolean]::Parse($f_qry_results.hasMoreItems)) {

            # Retrieve next page
            $f_qry_results = (Send-IdabusGetRequest -ResourcePath "Resources/search/continue" -Queries @("continuationToken=$($f_qry_results.continuationToken)","pageSize=$PageSize") | ConvertFrom-Json)
            [PSCustomObject[]]$resultsEntries = $f_qry_results.results

            $f_total_results = $f_total_results + $resultsEntries.count

            if ($f_total_results -gt $MaxResults) {
                Write-Output ($resultsEntries|ConvertTo-DeltaEntry) | Select-Object -first ($f_qry_results.totalCount % $MaxResults) -NoEnumerate:$false
                break
            } else {
                Write-Output ($resultsEntries|ConvertTo-DeltaEntry) -NoEnumerate:$false
            }

            # Refresh Continuation Token
            if ($f_qry_results.continuationToken) {
                Send-IdabusGetRequest -ResourcePath "Resources/search/refreshtoken" -Queries @("continuationToken=$($f_qry_results.continuationToken)") | Out-Null
            }
        }
    }

    end {
    }
}



##########################################################
###
### Add References
###
##########################################################
function Add-IdabusReference
{
    <#
    .DESCRIPTION
    Add reference(s) to a multivalue reference attribute.
    #>


    param(

        [parameter(Mandatory=$true, Position = 0)]
        [Guid] $ResourceID,

        [parameter(Mandatory=$true, Position = 1)]
        [string] $AttributeName,

        [parameter(Mandatory=$true, Position = 2)]
        [Guid[]] $MemberIDs,

        [parameter(Mandatory=$false, Position = 3)]
        [string] $Comment,

        [parameter(Mandatory=$false)]
        [switch] $SkipInvalidReferences=$false


    )

    PROCESS
    {
        $queries = @()
        $queries += "skipInvalidReferences=$SkipInvalidReferences"
        if(![string]::IsNullOrEmpty($Comment))
        {
            $queries +="comment=$([Uri]::EscapeDataString($Comment))"
        }

        $attrib = [Uri]::EscapeDataString($AttributeName)

        $resource = "Resources/multivalued/multiple/$ResourceID/$attrib"

        $body = ConvertTo-Json $MemberIDs -Depth 100

        $body|Send-IdabusPutRequest -ResourcePath $resource -Queries $queries
    }
}

##########################################################
###
### Remove Reference(s)
###
##########################################################
function Remove-IdabusReference
{
    <#
    .DESCRIPTION
    Remove reference(s) from a multivalue reference attribute.
    #>

    [CmdletBinding(SupportsShouldProcess = $true)]
    param(

        [parameter(Mandatory=$true, Position = 0)]
        [Guid] $ResourceID,

        [parameter(Mandatory=$true, Position = 1)]
        [string] $AttributeName,

        [parameter(Mandatory=$true, Position = 2)]
        [Guid[]] $MemberIDs,

        [parameter(Mandatory=$false, Position = 3)]
        [string] $Comment,

        [parameter(Mandatory=$false)]
        [switch] $SkipInvalidReferences=$false
    )

    PROCESS
    {
        $queries = @()
        $queries += "skipInvalidReferences=$SkipInvalidReferences"
        if(![string]::IsNullOrEmpty($Comment))
        {
            $queries +="comment=$([Uri]::EscapeDataString($Comment))"
        }

        $attrib = [Uri]::EscapeDataString($AttributeName)

        $resource = "Resources/multivalued/multiple/$ResourceID/$attrib"

        $body = ConvertTo-Json $MemberIDs -Depth 100

        if($PSCmdlet.ShouldProcess($param))
        {
            $body|Send-IdabusDeleteRequest -ResourcePath $resource -Queries $queries -Confirm: $false
        }
        else
        {
            Write-Output "Removing member(s): $MemberIDs"
        }
    }
}

##########################################################
###
### Add Vaue(s)
###
##########################################################
function Add-IdabusValue
{
    <#
    .DESCRIPTION
    Add Value(s) to a multivalue attribute.
    #>


    param(

        [parameter(Mandatory=$true, Position = 0)]
        [Guid] $ResourceID,

        [parameter(Mandatory=$true, Position = 1)]
        [string] $AttributeName,

        [parameter(Mandatory=$true, Position = 2)]
        [string[]] $Values,

        [parameter(Mandatory=$false, Position = 3)]
        [string] $Comment
    )

    PROCESS
    {
        $queries = @()
        if(![string]::IsNullOrEmpty($Comment))
        {
            $queries +="comment=$([Uri]::EscapeDataString($Comment))"
        }

        $attrib = [Uri]::EscapeDataString($AttributeName)

        $resource = "Resources/multivalued/multiple/$ResourceID/$attrib"

        $body = ConvertTo-Json $Values -Depth 100

        $body|Send-IdabusPutRequest -ResourcePath $resource -Queries $queries
    }
}

##########################################################
###
### Remove Value(s)
###
##########################################################
function Remove-IdabusValue
{
    <#
    .DESCRIPTION
    Remove values(s) from a multivalue attribute.
    #>

    [CmdletBinding(SupportsShouldProcess = $true)]
    param(

        [parameter(Mandatory=$true, Position = 0)]
        [Guid] $ResourceID,

        [parameter(Mandatory=$true, Position = 1)]
        [string] $AttributeName,

        [parameter(Mandatory=$true, Position = 2)]
        [string[]] $Values,

        [parameter(Mandatory=$false, Position = 3)]
        [string] $Comment
    )

    PROCESS
    {
        $queries = @()
        if(![string]::IsNullOrEmpty($Comment))
        {
            $queries +="comment=$([Uri]::EscapeDataString($Comment))"
        }

        $attrib = [Uri]::EscapeDataString($AttributeName)

        $resource = "Resources/multivalued/multiple/$ResourceID/$attrib"

        $body = ConvertTo-Json $Values -Depth 100

        if($PSCmdlet.ShouldProcess($param))
        {
            $body|Send-IdabusDeleteRequest -ResourcePath $resource -Queries $queries -Confirm: $false
        }
        else
        {
            Write-Output "Removing values(s): $Values"
        }
    }
}

##################################################################################################################
##
## Internal Functions
##
###################################################################################################################

class DeltaEntry { #Base Class for DeltaEntries
    hidden [System.Collections.Generic.List[string]] $__ModifiedAttributes;
    hidden [PSObject] $__SourceEntry
}

##################################
##
## Delta calculation
##
##################################
function ConvertTo-DeltaEntry
{
    [CmdletBinding()]
    param(
        [parameter(Mandatory=$true, Position = 0,  ValueFromPipeline=$true)]
        [PSObject] $SourceEntry
    )

    PROCESS
    {

        $entry = [PSCustomObject]([DeltaEntry]::new())

        $entry.__ModifiedAttributes = [System.Collections.Generic.List[string]]::new()
        $entry.__SourceEntry = $SourceEntry

        #Deta function
        $getDeltaEntryFunc = {

            $deltaEntry = [PSCustomObject]@{
                objecttype = $this.__SourceEntry.objecttype
                objectid = $this.__SourceEntry.objectid
            }
            foreach($attrName in $this.__ModifiedAttributes)
            {
                $deltaEntry|Add-Member -MemberType NoteProperty -Name $attrName -Value $this.$attrName
            }
            return $deltaEntry
        }

        #Add properties
        foreach($propName in $entry.__SourceEntry.psobject.properties.name)
        {
            #Getter Method
            $getter = {
                $this.__SourceEntry.$propName
            }
            #Setter Method
            $setter = {
                $this.__SourceEntry.$propName = $args[0]
                $this.__ModifiedAttributes +=  $propName
            }
            $entry | Add-Member -MemberType 'ScriptProperty' -Name $propName -Value $getter.GetNewClosure() -SecondValue $setter.GetNewClosure()
        }

        $entry|Add-Member -MemberType ScriptMethod -Name "__GetDeltaEntry" -Value $getDeltaEntryFunc

        return $entry
    }

}

Export-ModuleMember -Function "Get-IdabusLogonAccount"
Export-ModuleMember -Function "Get-IdabusResource"
Export-ModuleMember -Function "Save-IdabusResource"
Export-ModuleMember -Function "Remove-IdabusResource"
Export-ModuleMember -Function "New-IdabusResource"
Export-ModuleMember -Function "Search-IdabusResource"
Export-ModuleMember -Function "Add-IdabusReference"
Export-ModuleMember -Function "Remove-IdabusReference"
Export-ModuleMember -Function "Add-IdabusValue"
Export-ModuleMember -Function "Remove-IdabusValue"

Export-ModuleMember -Cmdlet "Connect-IdabusService","Disconnect-IdabusService", "Reset-IdabusSchemaCache","Send-IdabusGetRequest","Send-IdabusPostRequest","Send-IdabusPutRequest","Send-IdabusPatchRequest","Send-IdabusDeleteRequest","Get-IdabusSchemaBindings","Get-IdabusApiVersion"

# SIG # Begin signature block
# MIIuXwYJKoZIhvcNAQcCoIIuUDCCLkwCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUseGGNUmUvCVMgscqZTlx+vm+
# TrWggieSMIIFcjCCA1qgAwIBAgIQdlP+rHVGSJP15ddKSDpO+DANBgkqhkiG9w0B
# AQwFADBTMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEp
# MCcGA1UEAxMgR2xvYmFsU2lnbiBDb2RlIFNpZ25pbmcgUm9vdCBSNDUwHhcNMjAw
# MzE4MDAwMDAwWhcNNDUwMzE4MDAwMDAwWjBTMQswCQYDVQQGEwJCRTEZMBcGA1UE
# ChMQR2xvYmFsU2lnbiBudi1zYTEpMCcGA1UEAxMgR2xvYmFsU2lnbiBDb2RlIFNp
# Z25pbmcgUm9vdCBSNDUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2
# LcUw3Xroq5A9A3KwOkuZFmGy5f+lZx03HOV+7JODqoT1o0ObmEWKuGNXXZsAiAQl
# 6fhokkuC2EvJSgPzqH9qj4phJ72hRND99T8iwqNPkY2zBbIogpFd+1mIBQuXBsKY
# +CynMyTuUDpBzPCgsHsdTdKoWDiW6d/5G5G7ixAs0sdDHaIJdKGAr3vmMwoMWWuO
# vPSrWpd7f65V+4TwgP6ETNfiur3EdaFvvWEQdESymAfidKv/aNxsJj7pH+XgBIet
# MNMMjQN8VbgWcFwkeCAl62dniKu6TjSYa3AR3jjK1L6hwJzh3x4CAdg74WdDhLbP
# /HS3L4Sjv7oJNz1nbLFFXBlhq0GD9awd63cNRkdzzr+9lZXtnSuIEP76WOinV+Gz
# z6ha6QclmxLEnoByPZPcjJTfO0TmJoD80sMD8IwM0kXWLuePmJ7mBO5Cbmd+QhZx
# YucE+WDGZKG2nIEhTivGbWiUhsaZdHNnMXqR8tSMeW58prt+Rm9NxYUSK8+aIkQI
# qIU3zgdhVwYXEiTAxDFzoZg1V0d+EDpF2S2kUZCYqaAHN8RlGqocaxZ396eX7D8Z
# MJlvMfvqQLLn0sT6ydDwUHZ0WfqNbRcyvvjpfgP054d1mtRKkSyFAxMCK0KA8olq
# Ns/ITKDOnvjLja0Wp9Pe1ZsYp8aSOvGCY/EuDiRk3wIDAQABo0IwQDAOBgNVHQ8B
# Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUHwC/RoAK/Hg5t6W0
# Q9lWULvOljswDQYJKoZIhvcNAQEMBQADggIBAF4runSXNERfdkgoQIST7gFu6aGz
# 1oAl5nvkvAmRPQ/8dq3X1DAgu49g0JHWHPKc73gaK5QyAsEkllJSAtDz0fzymzlu
# meEfjkNBfZoeW8ldmoT8JuaH83RyJq2kG9k9O2pSoDwJHi8ee7MztEXH96yxr5Ng
# rXauuLIVeOuDauv/20arJOXuAvqQH1nAL13Wt12kXBC3clP4QU7M+ngaJUrK/oVi
# Q2HDtDeqgdL01joPvY1ZfjBH3itr5yFQM1/UZ5vUuGefPCeZA/+FQ45zEsogzehh
# 1bFm3BfWOW0P288jN6GCiU4caz/WoM2qB50+Qiaq1wzu+ke/GlJ+0XWB08mKYhdt
# T4igIaAmPq9t2WIwH+mYKK5ujdWOTHJmk4CNKuNVx2BnkEJWXCJRD7PcTjnuTd3Z
# HXgQVDtu0JdvA7UesiNzxhKymmTQ/JWFJKj/36Gw3JFArt8JM6u53ZK38cyRdDtp
# 62eXG5C/58egb3G7V7+3j1rtekBqFs2AhC0v4QLUJJRDsxX8DCsb/XFv/Mu8dRc6
# XoPSybMvG9WcjX9U/n5+5Fajh6ed4VlSlEGPbVu+hpWa/xp23UDSUUpwtB8zYyN3
# P+wnHlnkCIftNIJKDz/+oB3B9WdzRYZ49Kop6SeHxhnbxhMUwzlJh02gl+BlE/Wd
# d1bp2rNYxzrywM2CMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkq
# hkiG9w0BAQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j
# MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBB
# c3N1cmVkIElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5
# WjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
# ExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJv
# b3QgRzQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1K
# PDAiMGkz7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2r
# snnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C
# 8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBf
# sXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY
# QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8
# rhsDdV14Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaY
# dj1ZXUJ2h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+
# wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw
# ++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+N
# P8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7F
# wI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUw
# AwEB/zAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAU
# Reuir/SSy4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEB
# BG0wazAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsG
# AQUFBzAChjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1
# cmVkSURSb290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRp
# Z2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAow
# CDAGBgRVHSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/
# Vwe9mqyhhyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLe
# JLxSA8hO0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE
# 1Od/6Fmo8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9Hda
# XFSMb++hUD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbO
# byMt9H5xaiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMIIG
# tDCCBJygAwIBAgIQDcesVwX/IZkuQEMiDDpJhjANBgkqhkiG9w0BAQsFADBiMQsw
# CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
# ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw
# HhcNMjUwNTA3MDAwMDAwWhcNMzgwMTE0MjM1OTU5WjBpMQswCQYDVQQGEwJVUzEX
# MBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0
# ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQwOTYgU0hBMjU2IDIwMjUgQ0ExMIICIjAN
# BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtHgx0wqYQXK+PEbAHKx126NGaHS0
# URedTa2NDZS1mZaDLFTtQ2oRjzUXMmxCqvkbsDpz4aH+qbxeLho8I6jY3xL1IusL
# opuW2qftJYJaDNs1+JH7Z+QdSKWM06qchUP+AbdJgMQB3h2DZ0Mal5kYp77jYMVQ
# XSZH++0trj6Ao+xh/AS7sQRuQL37QXbDhAktVJMQbzIBHYJBYgzWIjk8eDrYhXDE
# pKk7RdoX0M980EpLtlrNyHw0Xm+nt5pnYJU3Gmq6bNMI1I7Gb5IBZK4ivbVCiZv7
# PNBYqHEpNVWC2ZQ8BbfnFRQVESYOszFI2Wv82wnJRfN20VRS3hpLgIR4hjzL0hpo
# YGk81coWJ+KdPvMvaB0WkE/2qHxJ0ucS638ZxqU14lDnki7CcoKCz6eum5A19WZQ
# HkqUJfdkDjHkccpL6uoG8pbF0LJAQQZxst7VvwDDjAmSFTUms+wV/FbWBqi7fTJn
# jq3hj0XbQcd8hjj/q8d6ylgxCZSKi17yVp2NL+cnT6Toy+rN+nM8M7LnLqCrO2JP
# 3oW//1sfuZDKiDEb1AQ8es9Xr/u6bDTnYCTKIsDq1BtmXUqEG1NqzJKS4kOmxkYp
# 2WyODi7vQTCBZtVFJfVZ3j7OgWmnhFr4yUozZtqgPrHRVHhGNKlYzyjlroPxul+b
# gIspzOwbtmsgY1MCAwEAAaOCAV0wggFZMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYD
# VR0OBBYEFO9vU0rp5AZ8esrikFb2L9RJ7MtOMB8GA1UdIwQYMBaAFOzX44LScV1k
# TN8uZz/nupiuHA9PMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcD
# CDB3BggrBgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2lj
# ZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29t
# L0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0
# cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmww
# IAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEBCwUA
# A4ICAQAXzvsWgBz+Bz0RdnEwvb4LyLU0pn/N0IfFiBowf0/Dm1wGc/Do7oVMY2mh
# XZXjDNJQa8j00DNqhCT3t+s8G0iP5kvN2n7Jd2E4/iEIUBO41P5F448rSYJ59Ib6
# 1eoalhnd6ywFLerycvZTAz40y8S4F3/a+Z1jEMK/DMm/axFSgoR8n6c3nuZB9BfB
# wAQYK9FHaoq2e26MHvVY9gCDA/JYsq7pGdogP8HRtrYfctSLANEBfHU16r3J05qX
# 3kId+ZOczgj5kjatVB+NdADVZKON/gnZruMvNYY2o1f4MXRJDMdTSlOLh0HCn2cQ
# LwQCqjFbqrXuvTPSegOOzr4EWj7PtspIHBldNE2K9i697cvaiIo2p61Ed2p8xMJb
# 82Yosn0z4y25xUbI7GIN/TpVfHIqQ6Ku/qjTY6hc3hsXMrS+U0yy+GWqAXam4ToW
# d2UQ1KYT70kZjE4YtL8Pbzg0c1ugMZyZZd/BdHLiRu7hAWE6bTEm4XYRkA6Tl4KS
# FLFk43esaUeqGkH/wyW4N7OigizwJWeukcyIPbAvjSabnf7+Pu0VrFgoiovRDiyx
# 3zEdmcif/sYQsfch28bZeUz2rtY/9TCA6TD8dC3JE3rYkrhLULy7Dc90G6e8Blqm
# yIjlgp2+VqsS9/wQD7yFylIz0scmbKvFoW2jNrbM1pD2T7m3XDCCBugwggTQoAMC
# AQICEHe9DgW3WQu2HUdhUx4/de0wDQYJKoZIhvcNAQELBQAwUzELMAkGA1UEBhMC
# QkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExKTAnBgNVBAMTIEdsb2JhbFNp
# Z24gQ29kZSBTaWduaW5nIFJvb3QgUjQ1MB4XDTIwMDcyODAwMDAwMFoXDTMwMDcy
# ODAwMDAwMFowXDELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt
# c2ExMjAwBgNVBAMTKUdsb2JhbFNpZ24gR0NDIFI0NSBFViBDb2RlU2lnbmluZyBD
# QSAyMDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyyDvlx65ATJD
# oFupiiP9IF6uOBKLyizU/0HYGlXUGVO3/aMX53o5XMD3zhGj+aXtAfq1upPvr5Pc
# +OKzGUyDsEpEUAR4hBBqpNaWkI6B+HyrL7WjVzPSWHuUDm0PpZEmKrODT3Kxintk
# ktDwtFVflgsR5Zq1LLIRzyUbfVErmB9Jo1/4E541uAMC2qQTL4VK78QvcA7B1Mwz
# Euy9QJXTEcrmzbMFnMhT61LXeExRAZKC3hPzB450uoSAn9KkFQ7or+v3ifbfcfDR
# vqeyQTMgdcyx1e0dBxnE6yZ38qttF5NJqbfmw5CcxrjszMl7ml7FxSSTY29+EIth
# z5hVoySiiDby+Z++ky6yBp8mwAwBVhLhsoqfDh7cmIsuz9riiTSmHyagqK54beyh
# iBU8wurut9itYaWvcDaieY7cDXPA8eQsq5TsWAY5NkjWO1roIs50Dq8s8RXa0bSV
# 6KzVSW3lr92ba2MgXY5+O7JD2GI6lOXNtJizNxkkEnJzqwSwCdyF5tQiBO9AKh0u
# bcdp0263AWwN4JenFuYmi4j3A0SGX2JnTLWnN6hV3AM2jG7PbTYm8Q6PsD1xwOEy
# p4LktjICMjB8tZPIIf08iOZpY/judcmLwqvvujr96V6/thHxvvA9yjI+bn3eD36b
# lcQSh+cauE7uLMHfoWXoJIPJKsL9uVMCAwEAAaOCAa0wggGpMA4GA1UdDwEB/wQE
# AwIBhjATBgNVHSUEDDAKBggrBgEFBQcDAzASBgNVHRMBAf8ECDAGAQH/AgEAMB0G
# A1UdDgQWBBQlndD8WQmGY8Xs87ETO1ccA5I2ETAfBgNVHSMEGDAWgBQfAL9GgAr8
# eDm3pbRD2VZQu86WOzCBkwYIKwYBBQUHAQEEgYYwgYMwOQYIKwYBBQUHMAGGLWh0
# dHA6Ly9vY3NwLmdsb2JhbHNpZ24uY29tL2NvZGVzaWduaW5ncm9vdHI0NTBGBggr
# BgEFBQcwAoY6aHR0cDovL3NlY3VyZS5nbG9iYWxzaWduLmNvbS9jYWNlcnQvY29k
# ZXNpZ25pbmdyb290cjQ1LmNydDBBBgNVHR8EOjA4MDagNKAyhjBodHRwOi8vY3Js
# Lmdsb2JhbHNpZ24uY29tL2NvZGVzaWduaW5ncm9vdHI0NS5jcmwwVQYDVR0gBE4w
# TDBBBgkrBgEEAaAyAQIwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFs
# c2lnbi5jb20vcmVwb3NpdG9yeS8wBwYFZ4EMAQMwDQYJKoZIhvcNAQELBQADggIB
# ACV1oAnJObq3oTmJLxifq9brHUvolHwNB2ibHJ3vcbYXamsCT7M/hkWHzGWbTONY
# BgIiZtVhAsVjj9Si8bZeJQt3lunNcUAziCns7vOibbxNtT4GS8lzM8oIFC09TOiw
# unWmdC2kWDpsE0n4pRUKFJaFsWpoNCVCr5ZW9BD6JH3xK3LBFuFr6+apmMc+WvTQ
# GJ39dJeGd0YqPSN9KHOKru8rG5q/bFOnFJ48h3HAXo7I+9MqkjPqV01eB17KwRis
# gS0aIfpuz5dhe99xejrKY/fVMEQ3Mv67Q4XcuvymyjMZK3dt28sF8H5fdS6itr81
# qjZjyc5k2b38vCzzSVYAyBIrxie7N69X78TPHinE9OItziphz1ft9QpA4vUY1h7p
# kC/K04dfk4pIGhEd5TeFny5mYppegU6VrFVXQ9xTiyV+PGEPigu69T+m1473BFZe
# Ibuf12pxgL+W3nID2NgiK/MnFk846FFADK6S7749ffeAxkw2V4SVp4QVSDAOUicI
# jY6ivSLHGcmmyg6oejbbarphXxEklaTijmjuGalJmV7QtDS91vlAxxCXMVI5NSkR
# hyTTxPupY8t3SNX6Yvwk4AR6TtDkbt7OnjhQJvQhcWXXCSXUyQcAerjH83foxdTi
# VdDTHvZ/UuJJjbkRcgyIRCYzZgFE3+QzDiHeYolIB9r1MIIG7TCCBNWgAwIBAgIQ
# CoDvGEuN8QWC0cR2p5V0aDANBgkqhkiG9w0BAQsFADBpMQswCQYDVQQGEwJVUzEX
# MBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0
# ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQwOTYgU0hBMjU2IDIwMjUgQ0ExMB4XDTI1
# MDYwNDAwMDAwMFoXDTM2MDkwMzIzNTk1OVowYzELMAkGA1UEBhMCVVMxFzAVBgNV
# BAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBTSEEyNTYgUlNB
# NDA5NiBUaW1lc3RhbXAgUmVzcG9uZGVyIDIwMjUgMTCCAiIwDQYJKoZIhvcNAQEB
# BQADggIPADCCAgoCggIBANBGrC0Sxp7Q6q5gVrMrV7pvUf+GcAoB38o3zBlCMGMy
# qJnfFNZx+wvA69HFTBdwbHwBSOeLpvPnZ8ZN+vo8dE2/pPvOx/Vj8TchTySA2R4Q
# KpVD7dvNZh6wW2R6kSu9RJt/4QhguSssp3qome7MrxVyfQO9sMx6ZAWjFDYOzDi8
# SOhPUWlLnh00Cll8pjrUcCV3K3E0zz09ldQ//nBZZREr4h/GI6Dxb2UoyrN0ijtU
# DVHRXdmncOOMA3CoB/iUSROUINDT98oksouTMYFOnHoRh6+86Ltc5zjPKHW5KqCv
# pSduSwhwUmotuQhcg9tw2YD3w6ySSSu+3qU8DD+nigNJFmt6LAHvH3KSuNLoZLc1
# Hf2JNMVL4Q1OpbybpMe46YceNA0LfNsnqcnpJeItK/DhKbPxTTuGoX7wJNdoRORV
# bPR1VVnDuSeHVZlc4seAO+6d2sC26/PQPdP51ho1zBp+xUIZkpSFA8vWdoUoHLWn
# qWU3dCCyFG1roSrgHjSHlq8xymLnjCbSLZ49kPmk8iyyizNDIXj//cOgrY7rlRyT
# laCCfw7aSUROwnu7zER6EaJ+AliL7ojTdS5PWPsWeupWs7NpChUk555K096V1hE0
# yZIXe+giAwW00aHzrDchIc2bQhpp0IoKRR7YufAkprxMiXAJQ1XCmnCfgPf8+3mn
# AgMBAAGjggGVMIIBkTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTkO/zyMe39/dfz
# kXFjGVBDz2GM6DAfBgNVHSMEGDAWgBTvb1NK6eQGfHrK4pBW9i/USezLTjAOBgNV
# HQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwgZUGCCsGAQUFBwEB
# BIGIMIGFMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wXQYI
# KwYBBQUHMAKGUWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRy
# dXN0ZWRHNFRpbWVTdGFtcGluZ1JTQTQwOTZTSEEyNTYyMDI1Q0ExLmNydDBfBgNV
# HR8EWDBWMFSgUqBQhk5odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRU
# cnVzdGVkRzRUaW1lU3RhbXBpbmdSU0E0MDk2U0hBMjU2MjAyNUNBMS5jcmwwIAYD
# VR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEBCwUAA4IC
# AQBlKq3xHCcEua5gQezRCESeY0ByIfjk9iJP2zWLpQq1b4URGnwWBdEZD9gBq9fN
# aNmFj6Eh8/YmRDfxT7C0k8FUFqNh+tshgb4O6Lgjg8K8elC4+oWCqnU/ML9lFfim
# 8/9yJmZSe2F8AQ/UdKFOtj7YMTmqPO9mzskgiC3QYIUP2S3HQvHG1FDu+WUqW4da
# IqToXFE/JQ/EABgfZXLWU0ziTN6R3ygQBHMUBaB5bdrPbF6MRYs03h4obEMnxYOX
# 8VBRKe1uNnzQVTeLni2nHkX/QqvXnNb+YkDFkxUGtMTaiLR9wjxUxu2hECZpqyU1
# d0IbX6Wq8/gVutDojBIFeRlqAcuEVT0cKsb+zJNEsuEB7O7/cuvTQasnM9AWcIQf
# VjnzrvwiCZ85EE8LUkqRhoS3Y50OHgaY7T/lwd6UArb+BOVAkg2oOvol/DJgddJ3
# 5XTxfUlQ+8Hggt8l2Yv7roancJIFcbojBcxlRcGG0LIhp6GvReQGgMgYxQbV1S3C
# rWqZzBt1R9xJgKf47CdxVRd/ndUlQ05oxYy2zRWVFjF7mcr4C34Mj3ocCVccAvlK
# V9jEnstrniLvUxxVZE/rptb7IRE2lskKPIJgbaP5t2nGj/ULLi49xTcBZU8atufk
# +EMF/cWuiC7POGT75qaL6vdCvHlshtjdNXOCIUjsarfNZzCCB/IwggXaoAMCAQIC
# DAMjZjMGqMxTW05AQjANBgkqhkiG9w0BAQsFADBcMQswCQYDVQQGEwJCRTEZMBcG
# A1UEChMQR2xvYmFsU2lnbiBudi1zYTEyMDAGA1UEAxMpR2xvYmFsU2lnbiBHQ0Mg
# UjQ1IEVWIENvZGVTaWduaW5nIENBIDIwMjAwHhcNMjMwMTE2MTU0MTExWhcNMjYw
# MzMwMTQzODMxWjCCAUAxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMw
# EQYDVQQFEwpIUkIgMTcwNzMzMRMwEQYLKwYBBAGCNzwCAQMTAkRFMRcwFQYLKwYB
# BAGCNzwCAQITBkJheWVybjEZMBcGCysGAQQBgjc8AgEBEwhNdWVuY2hlbjELMAkG
# A1UEBhMCREUxDzANBgNVBAgTBkJheWVybjEPMA0GA1UEBxMGRXJkaW5nMRkwFwYD
# VQQJExBHaWVzc2VyZWlzdHIuIDE2MSMwIQYDVQQKExpPeGZvcmQgQ29tcHV0ZXIg
# R3JvdXAgR21iSDETMBEGA1UECxMKQ29uc3VsdGluZzEjMCEGA1UEAxMaT3hmb3Jk
# IENvbXB1dGVyIEdyb3VwIEdtYkgxGDAWBgkqhkiG9w0BCQEWCXJiQG9jZy5kZTCC
# AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMEcgNzpx9sXDswyVwCbMLam
# jcIBIB731SqqmFXu9irF2ufrLLqmraN0M6LLNwwHLMqReKZBTFlmnotkb2BL35Jk
# 8/vOTsGAmXDogatO4X+tmX6rqxGdfCtMLY1tGjzLhRlJkfRds/lrO98jstsxlT6+
# yIoBFEhET3+ERHE5SwQHiSGLdKMMZDdf4tmf9ZuK1nikk+a3eYd7kBnlXgwxBK4Z
# 2Y6jLFW2iNQcL7syhI7QNcl7AVFIUIjN8eHIFH0MX8BkIlMz466GgBJzvhKTGMq/
# 3LhGHxJwpcyZSlCaUuZQLqyDm2oJDThXoJ59TWweCopPrJUR+pbR6YODv4+tXyll
# jsfGKLYb4Ym5CE3uez4C2KrY7kXxKfuYnuH0WfuE/JfxC6i3WyZmwu7Zn9rX3Xf6
# YMMTiSs7oV1/qKzQdlw9y41ZUzfiiJ5yNG+PwCFdXKJ8JrEbKSzt8rNWUU+22Al/
# JXz/+2fS77Z0R4OwC+aG41auLs8DrIvkAbGYEZM6Uac4q2Evop+f8u/MifiIXFSB
# f2wUOxKVT/uvXNVpeSoWZD+uI5ZmclsF/IgLJTzqeMOmelArth07cAGEcAW7Pz2a
# g1Pqt1WLjN9OYaX+zhO2AjIVENQfSR7X+RVTkzszp29apz5hyBBq+UhU8HK29AT7
# SzAx6rfmPENFCsvX62mhAgMBAAGjggHMMIIByDAOBgNVHQ8BAf8EBAMCB4AwgZ8G
# CCsGAQUFBwEBBIGSMIGPMEwGCCsGAQUFBzAChkBodHRwOi8vc2VjdXJlLmdsb2Jh
# bHNpZ24uY29tL2NhY2VydC9nc2djY3I0NWV2Y29kZXNpZ25jYTIwMjAuY3J0MD8G
# CCsGAQUFBzABhjNodHRwOi8vb2NzcC5nbG9iYWxzaWduLmNvbS9nc2djY3I0NWV2
# Y29kZXNpZ25jYTIwMjAwVQYDVR0gBE4wTDBBBgkrBgEEAaAyAQIwNDAyBggrBgEF
# BQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wBwYF
# Z4EMAQMwCQYDVR0TBAIwADBHBgNVHR8EQDA+MDygOqA4hjZodHRwOi8vY3JsLmds
# b2JhbHNpZ24uY29tL2dzZ2NjcjQ1ZXZjb2Rlc2lnbmNhMjAyMC5jcmwwFAYDVR0R
# BA0wC4EJcmJAb2NnLmRlMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB8GA1UdIwQYMBaA
# FCWd0PxZCYZjxezzsRM7VxwDkjYRMB0GA1UdDgQWBBTYOgAxf8YT9oktBxWk4pO1
# v3v8vDANBgkqhkiG9w0BAQsFAAOCAgEAKA8sD0fqdgzIeq4wkJLeqxeofgMHLt1h
# 0UqubUeXNdYo4VchEGeJ4QF2e7NdP+Nf1TD1qvfWoYPZBUiHkR2HlWd9udiI7aO2
# rpm4PzQ9PitbPdKu3lz+49OcgPIPGVJZ0vXi2qIT5NXtSv2Pvtix1oDxQhnKkQAh
# hqC0Qe/YKkX6EDucIfDyG1zUMigevUD8WTn4u7B9v/nedxRs4wyxoHa0kp2EeQW6
# EFh0MP8UCxROyu1hVbZBaZE5tCBZ9zM5Rt2X5dwtxC8RE0EXeGQBX64arWTz5LoN
# EvxP4m3Gar/qnyEy502l09NrdZUxXTfPx+MDssW9clylYcbWfbedRHaga/nBOiPp
# eFI/2RDdoKNnPwiZsWKpXIhhsBK5i9Mg9xKnauVAfy0fGm/+hkdF4idxiO9z+oGa
# p9OVmgDCbAZiJDHofkGOnMN1FLeweqzXSXnlpEtmIXvZ7zR0TbqBS9vyiFaJoz6Y
# ET7krbfv7pLgRCWXc58PCl5ldXdMb87bz2CaIP1XZLwKFgY3IPQO7KgTO8Dy2KJg
# LYFAEJYsHnfE3fu2Lt029L2RGAjZth4OIaeXTyFVnx7q2Wr/xuPqHXvhKD6wqdpJ
# kp7H+GYvY9RpnErF+0uVu0NLhmfNQRPTBmwIQL//XhQ9QWsxh1d8jCGexJQEeT2F
# KVyjWpOBPXQxggY3MIIGMwIBATBsMFwxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBH
# bG9iYWxTaWduIG52LXNhMTIwMAYDVQQDEylHbG9iYWxTaWduIEdDQyBSNDUgRVYg
# Q29kZVNpZ25pbmcgQ0EgMjAyMAIMAyNmMwaozFNbTkBCMAkGBSsOAwIaBQCgeDAY
# BgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3
# AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEW
# BBRUxGqCOez4yUQgg8xw/aVNEJlULzANBgkqhkiG9w0BAQEFAASCAgAGYSnwwDmz
# srsQzo2UEfzvf9IiTB1lTXx8j6FBo5Sf5n13Dr9JyeTgWoXdSrNj/QwfBhnvem7D
# 0UG29FEr9N6Xm3aFkroJFmc0s1h45BTexC0doYo2oHkZgKE+DPrGXtbnlFU8d8Hx
# xqJPABHlVp8xk5pN934O9KzI3hMBBl3VJRFNR1CBFoHEQCdHInPwvMTovoQDiap8
# fVEm8XuudQoWUc/rQ8pfsgGA86c/Q+mbv9nnxLAN9wU61wosVWXG+09Z9Ds8b01C
# 4ELAfKTjqLfwwzT4gT5l66YHLflWI8vBFNjnr17goJyd2qSPuZjXxqyMbkuZK1aG
# hqJLyNBME5I/EMoVuRVCAHEmR7I7gdtDnB0/BZIS5vcgdQFnHAse1kV9lvHs7stL
# cQBLtoMHcX3f2mHsmD7CrAdLa/RPELCC916JrMps2g7vAwtCOa0rXbcWmGJbzRsn
# mK5NeamOvI6j0u7QtBRKTQM1UWzjRVlaY0w1/GFXClvkuCZQVV9H+fpXc2Ts6KkB
# OWDnLBmvsWti+VWKGxW+YmOx31KpUDeNhD+wIPFZsfKKnf5Blpmaq7ZmlG6oeW2s
# /fM3n4MCPzd3oPmAn8TbUs5+KtN49QzX6BS5qmX0O70CzR+Nct/5Y84S7yFitO1a
# D4qr7UySK0MqvBr9Rt6sIStELIQfoFAkYaGCAyYwggMiBgkqhkiG9w0BCQYxggMT
# MIIDDwIBATB9MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5j
# LjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNB
# NDA5NiBTSEEyNTYgMjAyNSBDQTECEAqA7xhLjfEFgtHEdqeVdGgwDQYJYIZIAWUD
# BAIBBQCgaTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEP
# Fw0yNTEwMDYxNDMwNDJaMC8GCSqGSIb3DQEJBDEiBCD8zQ3BYmPeZbwjrjg0+oph
# LvYb6TTLE94Ro9i3ia0I+zANBgkqhkiG9w0BAQEFAASCAgAc4sIDTZybAwTnw0Hy
# Fe8J7OIKXgPju3LrNryDqczVNRJ0u2ZlbXwlA/zep1uZ7gWdNbo1cDSjSmRpSyY1
# ids1EPNOKImZqQQI32VaB55LKgsrwsBd/5sKyLHzazczj/Lr8T6UCFLYJIOhOnFH
# EYftjsvcCgicEndJ8k2XPhLxRvhRAXVt5UNiO8qykPsSuxkCYHXTKM+QydRbuRLA
# pnGDX6MIj9S8ipGcRdXVAAlNfzGvy2t5I+BA4RNajVilHTHnVi/pSiS0jUnXto3o
# 6OqqR143sV2e8Adi/IKU+esFJ0VoUPMBrX5AXm9Wgn2EpiGJNMTmafLUDK4zvbx/
# WPJySK2gqzE0XDoDVg7GL4hQR9xcRFpS8fWW3ZErxCTry9op8bAPN3JPVZGRg3AT
# LzSWBULmeoKTNeLN/Wc0AqT/2638AXEPcOo/F8KpA4zBz+/niZouxrPsuEQ6LOXT
# UvTeYXJydCiNXoEMRtbybxb2s/IsUVA3fubO1LJbHRJrSM/4sfdxQfIzKSw8RTFn
# sQp9+dZaY2m7YeMVFjdaWSrSSz7RyYmyzkkWFQmLk0L5OcnmC6+ETD+FWTn20/lB
# hS2nFuIdeIy75t3AQF9lf/su0yt6xoTK33WDJcg69215l3XUuQYeelnKwZorUbbq
# Qf4ucpqhZrh6EZDVswD8gdE9xg==
# SIG # End signature block