Public/Get-FabricCapacityOverageCost.ps1

function Get-FabricCapacityOverageCost {
    <#
    .SYNOPSIS
    Estimates additional Fabric capacity overage costs from the Capacity Metrics App.
 
    .DESCRIPTION
    Discovers the app semantic model and all visible F-SKU capacities using only
    the app's workspace ID. Returns a structured object with totals, per-capacity
    estimates and daily detail. All costs use decimal arithmetic and the currency
    of the supplied base PAYG CU-hour price, multiplied internally by three.
 
    This is a same-observed-workload planning estimate, not an invoice prediction.
    Replays carry-forward additions and full idle billable burndown, preserving
    incoming debt and historical SKU sizes. Adjusts the interactive-delay ratio
    by simulated minus recorded debt divided by the ten-minute CU allowance.
    Pays all simulated current debt when the adjusted ratio exceeds 1.0, then
    resets that debt without clearing future-smoothed demand. Recorded processed
    overages are reported separately, never added to the estimate. Pause, resume,
    creation and deletion reset debt; ordinary pause charges are not 3x overage.
    Assumes unlimited overage spending/quota headroom and no additional workload
    admitted by enabling overage. The service's exact billing timing is unknowable.
 
    Uses the commercial Power BI Execute Queries REST API, not XMLA. Az.Accounts
    5.5.3 or newer is mandatory, even if optional Azure CLI authentication is used.
    Install only Az.Accounts, not the entire Az bundle. Authenticate separately
    with Connect-AzAccount -Tenant <tenant-id> or az login --allow-no-subscriptions.
    Azure CLI is tried first, falling back to an authenticated Az.Accounts context.
    Importing the module does not authenticate, query a model or refresh anything.
    Requires model Read/Build permission, the tenant Execute Queries setting, and
    configured Metrics App data-source credentials with capacity-admin access.
 
    Requires the current Metrics App Capacities, CU Detail, Timepoint Overage
    Detail and System Events schema, plus the CapacitiesList and UTC_offset
    parameters. Queries daily chunks in the app's clock and excludes the latest
    incomplete timepoint. Accepts model ISO strings and typed DateTime and
    DateTimeOffset wall-clock values without local timezone conversion.
    Incomplete retention/debt-free gaps produce Partial status. Missing joined
    metrics, debt-bearing gaps, inconsistent debt ledgers and truncated responses
    fail rather than inventing a cost. MissingDataCapacities have unknown costs:
    overall totals are null and known-data subtotals remain available.
 
    Refresh is off by default. Successful model refreshes or metrics strictly
    older than 12 hours warn. A refresh-history 403 explicitly reports Unknown
    freshness; unrelated API failures terminate. Refresh history needs model
    Write permission; triggering refresh also needs Dataset.ReadWrite.All.
    -Refresh submits one request and waits for that exact request, polling every
    ten seconds for up to two hours. Failure/timeout prevents calculation; timeout
    does not cancel the service operation. Ambiguous refresh submissions are not
    retried. Check history before resubmitting. Refresh consumes service quota
    and does not create missing DirectQuery usage.
    -Refresh -WhatIf or a declined -Confirm returns no costs and submits nothing.
 
    Supports Windows PowerShell 5.1 and PowerShell 7 on Windows. Other operating
    systems are not tested. Reported currency rounds to two decimal places;
    aggregates round independently of daily amounts.
 
    .PARAMETER WorkspaceId
    Required GUID of the installed Capacity Metrics App workspace, not a capacity ID.
    Alias: CapacityMetricsWorkspaceId.
    .PARAMETER Days
    Rolling days to analyze. Default 14; allowed range 1 through 14.
    Alias: NumberOfDays.
    .PARAMETER PricePerCU
    BASE PAYG CU-hour price, not CU-second or pre-multiplied overage price.
    Default decimal 0.18; overage price 0.54. Allowed range 0 through 1000000.
    Alias: PaygPricePerCUHour.
    .PARAMETER SemanticModelId
    Optional model GUID in WorkspaceId, for ambiguous or renamed models.
    .PARAMETER Refresh
    Explicitly request and await model refresh. Default false. Supports WhatIf/Confirm.
 
    .EXAMPLE
    Get-FabricCapacityOverageCost -WorkspaceId '00000000-0000-0000-0000-000000000001'
    Discover the Metrics App and estimate all visible F-SKU capacities for 14 days.
    .EXAMPLE
    $result = Get-FabricCapacityOverageCost -WorkspaceId '00000000-0000-0000-0000-000000000001' -Days 7 -PricePerCU 0.15
    $result.Capacities | Format-Table CapacityName, EstimatedOverageCUHours, EstimatedCost, DataStatus
    $result.Daily | Export-Csv -LiteralPath '.\overage-by-day.csv' -NoTypeInformation
    Examine structured results and export daily detail.
    .EXAMPLE
    Get-FabricCapacityOverageCost -WorkspaceId '00000000-0000-0000-0000-000000000001' -SemanticModelId '00000000-0000-0000-0000-000000000002'
    Select an explicit semantic model when discovery is ambiguous.
    .EXAMPLE
    Get-FabricCapacityOverageCost -WorkspaceId '00000000-0000-0000-0000-000000000001' -Refresh -Confirm
    Confirm refresh and calculate only after that request succeeds.
    .EXAMPLE
    Get-FabricCapacityOverageCost -WorkspaceId '00000000-0000-0000-0000-000000000001' -Refresh -WhatIf
    Preview refresh after read-only model discovery; do not submit or return costs.
 
    .OUTPUTS
    System.Management.Automation.PSCustomObject
    .LINK
    https://github.com/cbattlegear/fabric-capacity-overage-estimator/blob/main/docs/calculation.md
    .LINK
    https://learn.microsoft.com/fabric/enterprise/capacity-overage-overview
    .LINK
    https://learn.microsoft.com/rest/api/power-bi/datasets/execute-queries
    #>

    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
    [OutputType([pscustomobject])]
    param(
        [Parameter(Mandatory = $true, Position = 0)]
        [Alias('CapacityMetricsWorkspaceId')]
        [ValidateScript({ $_ -ne [guid]::Empty })]
        [guid] $WorkspaceId,

        [Alias('NumberOfDays')]
        [ValidateRange(1, 14)]
        [int] $Days = 14,

        [Alias('PaygPricePerCUHour')]
        [ValidateRange(0, 1000000)]
        [decimal] $PricePerCU = 0.18,

        [ValidateScript({ $_ -ne [guid]::Empty })]
        [guid] $SemanticModelId,

        [switch] $Refresh
    )

    $ErrorActionPreference = 'Stop'
    $context = @{
        WorkspaceId = $WorkspaceId
        Token = $null
        TokenAcquiredAt = [datetime]::MinValue
    }
    $overageMultiplier = [decimal] 3
    try {
        $datasetResponse = Invoke-OverageApi -Context $context -Method Get -Path "groups/$WorkspaceId/datasets"
        $models = @(Get-OptionalProperty $datasetResponse 'value')
        if ($models.Count -eq 0) { throw "No semantic models are accessible in workspace $WorkspaceId." }
        $requestedId = if ($PSBoundParameters.ContainsKey('SemanticModelId')) { $SemanticModelId } else { [guid]::Empty }
        $model = Get-OverageModel -Models $models -RequestedId $requestedId -WorkspaceId $WorkspaceId
        $modelId = [guid] $model.id
        Write-Verbose "Using semantic model '$($model.name)' [$modelId]."

        $refreshResult = $null
        if ($Refresh) {
            if (-not $PSCmdlet.ShouldProcess("semantic model $modelId in workspace $WorkspaceId", 'Refresh semantic model')) {
                Write-Verbose 'Model refresh was skipped; no costs were calculated.'
                return
            }
            $refreshResult = Start-OverageModelRefresh -Context $context -ModelId $modelId -Confirm:$false
            if ($null -eq $refreshResult) {
                throw 'The approved model refresh did not complete. No costs were calculated.'
            }
        }
        $nowUtc = Get-OverageUtcNow
        $modelFreshness = Get-OverageModelFreshness -Context $context -ModelId $modelId -NowUtc $nowUtc

        $parameters = Invoke-OverageApi -Context $context -Method Get -Path "groups/$WorkspaceId/datasets/$modelId/parameters"
        $offsetParameters = @((Get-OptionalProperty $parameters 'value') | Where-Object { $_.name -eq 'UTC_offset' })
        if ($offsetParameters.Count -ne 1) {
            throw "Could not discover the model's UTC_offset. Use a current, configured Capacity Metrics App model; timezone was not guessed."
        }
        $offset = [double] 0
        $offsetText = [System.Convert]::ToString($offsetParameters[0].currentValue, [System.Globalization.CultureInfo]::InvariantCulture)
        if (-not [double]::TryParse(
            $offsetText, [System.Globalization.NumberStyles]::Float,
            [System.Globalization.CultureInfo]::InvariantCulture, [ref] $offset
        ) -or [double]::IsNaN($offset) -or $offset -lt -12 -or $offset -gt 14) {
            throw "Invalid Metrics App UTC_offset '$offsetText'."
        }
        $modelClockNow = [datetime]::SpecifyKind($nowUtc.AddHours($offset), [System.DateTimeKind]::Unspecified)
        $modelWindowNow = $modelClockNow.AddTicks(-($modelClockNow.Ticks % [timespan]::FromSeconds(30).Ticks))
        $capacityQuery = @'
EVALUATE
    SELECTCOLUMNS('Capacities',
        "CapacityId", 'Capacities'[Capacity Id],
        "CapacityName", 'Capacities'[Capacity name],
        "SKU", 'Capacities'[SKU])
'@

        $capacityRows = @(Invoke-OverageDax -Context $context -ModelId $modelId -Query $capacityQuery)
        $capacities = @(foreach ($row in $capacityRows) {
            $id = [guid] (Get-QueryField $row 'CapacityId')
            if ($id -eq [guid]::Empty) { throw 'The Metrics App returned an empty capacity ID.' }
            [pscustomobject] @{
                Id = $id
                Name = [string] (Get-QueryField $row 'CapacityName')
                SKU = [string] (Get-QueryField $row 'SKU')
            }
        })
        foreach ($group in ($capacities | Group-Object Id)) {
            if (@($group.Group | Select-Object Name, SKU -Unique).Count -gt 1) {
                throw "Conflicting current capacity metadata for $($group.Name). No SKU or cost was guessed."
            }
        }
        $eligible = @($capacities | Where-Object { $_.SKU -match '^F[1-9][0-9]*$' } | Sort-Object Id -Unique)
        $skipped = @($capacities | Where-Object { $_.SKU -notmatch '^F[1-9][0-9]*$' } | Sort-Object Id -Unique)
        if ($skipped.Count -gt 0) {
            Write-Warning "Excluded non-F SKUs (overage applies only to F SKUs): $(($skipped | ForEach-Object { "$($_.Name) [$($_.SKU)]" }) -join '; ')."
        }
        if ($eligible.Count -eq 0) { throw 'No eligible F-SKU capacities are visible in this Metrics App model.' }

        $latestTimes = [System.Collections.Generic.List[datetime]]::new()
        $withData = [System.Collections.Generic.List[object]]::new()
        $missingData = [System.Collections.Generic.List[object]]::new()
        foreach ($capacity in $eligible) {
            $prefix = Get-CapacityDaxPrefix $capacity.Id
            $query = @"
$prefix
EVALUATE
    ROW(
        "LastUsage", FORMAT(MAX('CU Detail'[Window start time]), "yyyy-MM-ddTHH:mm:ss"),
        "LastDebt", FORMAT(MAX('Timepoint Overage Detail'[Window start time]), "yyyy-MM-ddTHH:mm:ss"))
"@

            $bounds = @(Invoke-OverageDax -Context $context -ModelId $modelId -Query $query)
            if ($bounds.Count -ne 1) { throw "Could not determine data bounds for '$($capacity.Name)'." }
            $usageText = Get-QueryField $bounds[0] 'LastUsage'
            $debtText = Get-QueryField $bounds[0] 'LastDebt'
            if ($null -eq $usageText -or $null -eq $debtText -or
                ($usageText -is [string] -and [string]::IsNullOrWhiteSpace($usageText)) -or
                ($debtText -is [string] -and [string]::IsNullOrWhiteSpace($debtText))) {
                $missingData.Add($capacity)
                Write-Warning "No usage/carry-forward data for '$($capacity.Name)'. Its cost is unknown, not zero; overall totals will be null. Verify the app's capacity-admin credentials and refresh."
                continue
            }
            $usageTime = ConvertTo-ModelTime $usageText
            $debtTime = ConvertTo-ModelTime $debtText
            $latestTimes.Add([datetime]::new([math]::Min($usageTime.Ticks, $debtTime.Ticks)))
            $withData.Add($capacity)
        }
        if ($withData.Count -eq 0) { throw 'No eligible capacity has observable usage and carry-forward data. No cost can be calculated.' }
        $end = $latestTimes | Sort-Object -Descending | Select-Object -First 1
        if ($end -gt $modelWindowNow) { $end = $modelWindowNow }
        $start = $end.AddDays(-$Days)
        # Freshness uses the unrounded clock, not the aligned query boundary.
        $metricsAgeHours = [math]::Max([double] 0, ($modelClockNow - $end).TotalHours)
        if ($metricsAgeHours -gt 12) {
            Write-Warning "Latest available usage/debt data is $([math]::Round($metricsAgeHours, 2)) hours old (over 12 hours). The estimate ends at $($end.ToString('s')) in the app's clock, NOT now. Model refresh does not create new activity for idle or paused capacities."
        }
        $rate = $PricePerCU * $overageMultiplier
        Write-Warning 'What-if estimate: same recorded workload, linear debt/10-minute-delay approximation, unlimited rolling overage headroom. Rejected/deferred work and exact service billing timing are not reproducible from this model.'
        Write-Verbose "Window [$($start.ToString('s')), $($end.ToString('s'))) in model time (UTC offset $offset); rate $rate per CU-hour."

        $results = [System.Collections.Generic.List[object]]::new()
        $dailyResults = [System.Collections.Generic.List[object]]::new()
        $totalEstimated = [decimal] 0
        $totalRecorded = [decimal] 0
        foreach ($capacity in $withData) {
            Write-Verbose "Reading '$($capacity.Name)' [$($capacity.Id)]."
            $prefix = Get-CapacityDaxPrefix $capacity.Id
            $resetQuery = @"
$prefix
EVALUATE
    SELECTCOLUMNS(
        FILTER('System Events',
            'System Events'[Capacity Id] = "$($capacity.Id)" &&
            'System Events'[Capacity state change reason] IN { "Created", "ManuallyPaused", "ManuallyResumed", "Deleted" }),
        "ResetTime", FORMAT('System Events'[Binned capacity state transition time], "yyyy-MM-ddTHH:mm:ss"),
        "ResetReason", 'System Events'[Capacity state change reason])
ORDER BY [ResetTime]
"@

            $resetRows = @(Invoke-OverageDax -Context $context -ModelId $modelId -Query $resetQuery)
            $resetTimes = @(foreach ($row in $resetRows) { ConvertTo-ModelTime (Get-QueryField $row 'ResetTime') })
            $inactiveTimes = @(foreach ($row in $resetRows) {
                if ((Get-QueryField $row 'ResetReason') -in @('ManuallyPaused', 'Deleted')) {
                    ConvertTo-ModelTime (Get-QueryField $row 'ResetTime')
                }
            })
            $samples = [System.Collections.Generic.List[object]]::new()
            for ($cursor = $start.AddSeconds(-30); $cursor -lt $end; $cursor = $chunkEnd) {
                $chunkEnd = $cursor.Date.AddDays(1)
                if ($chunkEnd -gt $end) { $chunkEnd = $end }
                $query = Get-OverageSeriesQuery -CapacityId $capacity.Id -Start $cursor -End $chunkEnd
                $rows = @(Invoke-OverageDax -Context $context -ModelId $modelId -Query $query)
                foreach ($sample in (ConvertTo-OverageSeries -Rows $rows)) { $samples.Add($sample) }
            }
            $replay = Get-OverageReplay -Samples $samples.ToArray() -ResetTimes $resetTimes -InactiveTimes $inactiveTimes -Start $start -End $end -Rate $rate
            if ($replay.DataStatus -eq 'Partial') {
                Write-Warning "'$($capacity.Name)': $($replay.MissingTimepoints) requested 30-second timepoints are unavailable (retention, idle/paused periods, or reporting gaps). Costs cover the observed data only; this is NOT a complete $Days-day estimate."
            }
            if ($replay.IneligibleTimepoints -gt 0) {
                Write-Warning "'$($capacity.Name)': excluded $($replay.IneligibleTimepoints) historical non-F-SKU timepoints."
            }
            $totalEstimated += $replay.EstimatedCUSeconds
            $totalRecorded += $replay.RecordedCUSeconds
            $results.Add([pscustomobject] @{
                CapacityId = $capacity.Id
                CapacityName = $capacity.Name
                CurrentSKU = $capacity.SKU
                DataStatus = $replay.DataStatus
                FirstTimepoint = $replay.FirstTimepoint
                LastTimepoint = $replay.LastTimepoint
                Timepoints = $replay.Timepoints
                MissingTimepoints = $replay.MissingTimepoints
                IneligibleTimepoints = $replay.IneligibleTimepoints
                InitialCarryCUSeconds = $replay.InitialCarryCUSeconds
                RemainingCarryCUSeconds = $replay.RemainingCarryCUSeconds
                EstimatedOverageCUHours = [math]::Round($replay.EstimatedCUSeconds / [decimal] 3600, 6)
                EstimatedCost = [math]::Round($replay.EstimatedCUSeconds / [decimal] 3600 * $rate, 2)
                RecordedOverageCUHours = [math]::Round($replay.RecordedCUSeconds / [decimal] 3600, 6)
                RecordedCostAtSuppliedPrice = [math]::Round($replay.RecordedCUSeconds / [decimal] 3600 * $rate, 2)
                PaymentEvents = $replay.PaymentEvents
            })
            foreach ($day in $replay.Daily) {
                $day | Add-Member -NotePropertyName CapacityId -NotePropertyValue $capacity.Id
                $day | Add-Member -NotePropertyName CapacityName -NotePropertyValue $capacity.Name
                $dailyResults.Add($day)
            }
        }
        [pscustomobject] @{
            WorkspaceId = $WorkspaceId
            SemanticModelId = $modelId
            SemanticModelName = $model.name
            RefreshRequested = [bool] $Refresh
            RefreshRequestId = if ($null -ne $refreshResult) { $refreshResult.RequestId } else { $null }
            LastSuccessfulModelRefreshUtc = $modelFreshness.LastSuccessfulRefreshUtc
            ModelRefreshAgeHours = if ($null -ne $modelFreshness.AgeHours) { [math]::Round($modelFreshness.AgeHours, 2) } else { $null }
            ModelRefreshFreshness = $modelFreshness.Status
            LatestMetricsAgeHours = [math]::Round($metricsAgeHours, 2)
            MetricsFreshness = if ($metricsAgeHours -gt 12) { 'Stale' } else { 'Recent' }
            WindowStartModelTime = $start
            WindowEndModelTimeExclusive = $end
            ModelUTCOffsetHours = $offset
            RequestedDays = $Days
            DataStatus = if ($missingData.Count -gt 0 -or @($results | Where-Object DataStatus -eq 'Partial').Count -gt 0) { 'Partial' } else { 'Complete' }
            Scenario = 'Same observed workload; linear debt replay; no overage spending/quota limit'
            BasePricePerCUHour = $PricePerCU
            OverageMultiplier = $overageMultiplier
            OveragePricePerCUHour = $rate
            EstimatedOverageCUHours = if ($missingData.Count -eq 0) { [math]::Round($totalEstimated / [decimal] 3600, 6) } else { $null }
            EstimatedCost = if ($missingData.Count -eq 0) { [math]::Round($totalEstimated / [decimal] 3600 * $rate, 2) } else { $null }
            RecordedOverageCUHours = if ($missingData.Count -eq 0) { [math]::Round($totalRecorded / [decimal] 3600, 6) } else { $null }
            RecordedCostAtSuppliedPrice = if ($missingData.Count -eq 0) { [math]::Round($totalRecorded / [decimal] 3600 * $rate, 2) } else { $null }
            EstimatedCostForCapacitiesWithData = [math]::Round($totalEstimated / [decimal] 3600 * $rate, 2)
            RecordedCostForCapacitiesWithDataAtSuppliedPrice = [math]::Round($totalRecorded / [decimal] 3600 * $rate, 2)
            Capacities = $results.ToArray()
            Daily = $dailyResults.ToArray()
            MissingDataCapacities = $missingData.ToArray()
            SkippedNonFCapacities = $skipped
        }
    }
    finally {
        $context.Token = $null
        $context.TokenAcquiredAt = [datetime]::MinValue
    }
}

# SIG # Begin signature block
# MII9LgYJKoZIhvcNAQcCoII9HzCCPRsCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCA1w/5eXVkiQro8
# mtLNnLIaK6UtmkfjweGpWFPFMbN7SqCCIfAwggXMMIIDtKADAgECAhBUmNLR1FsZ
# lUgTecgRwIeZMA0GCSqGSIb3DQEBDAUAMHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jvc29mdCBJZGVu
# dGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAy
# MDAeFw0yMDA0MTYxODM2MTZaFw00NTA0MTYxODQ0NDBaMHcxCzAJBgNVBAYTAlVT
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jv
# c29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRo
# b3JpdHkgMjAyMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALORKgeD
# Bmf9np3gx8C3pOZCBH8Ppttf+9Va10Wg+3cL8IDzpm1aTXlT2KCGhFdFIMeiVPvH
# or+Kx24186IVxC9O40qFlkkN/76Z2BT2vCcH7kKbK/ULkgbk/WkTZaiRcvKYhOuD
# PQ7k13ESSCHLDe32R0m3m/nJxxe2hE//uKya13NnSYXjhr03QNAlhtTetcJtYmrV
# qXi8LW9J+eVsFBT9FMfTZRY33stuvF4pjf1imxUs1gXmuYkyM6Nix9fWUmcIxC70
# ViueC4fM7Ke0pqrrBc0ZV6U6CwQnHJFnni1iLS8evtrAIMsEGcoz+4m+mOJyoHI1
# vnnhnINv5G0Xb5DzPQCGdTiO0OBJmrvb0/gwytVXiGhNctO/bX9x2P29Da6SZEi3
# W295JrXNm5UhhNHvDzI9e1eM80UHTHzgXhgONXaLbZ7LNnSrBfjgc10yVpRnlyUK
# xjU9lJfnwUSLgP3B+PR0GeUw9gb7IVc+BhyLaxWGJ0l7gpPKWeh1R+g/OPTHU3mg
# trTiXFHvvV84wRPmeAyVWi7FQFkozA8kwOy6CXcjmTimthzax7ogttc32H83rwjj
# O3HbbnMbfZlysOSGM1l0tRYAe1BtxoYT2v3EOYI9JACaYNq6lMAFUSw0rFCZE4e7
# swWAsk0wAly4JoNdtGNz764jlU9gKL431VulAgMBAAGjVDBSMA4GA1UdDwEB/wQE
# AwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIftJqhSobyhmYBAcnz1AQ
# T2ioojAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0BAQwFAAOCAgEAr2rd5hnn
# LZRDGU7L6VCVZKUDkQKL4jaAOxWiUsIWGbZqWl10QzD0m/9gdAmxIR6QFm3FJI9c
# Zohj9E/MffISTEAQiwGf2qnIrvKVG8+dBetJPnSgaFvlVixlHIJ+U9pW2UYXeZJF
# xBA2CFIpF8svpvJ+1Gkkih6PsHMNzBxKq7Kq7aeRYwFkIqgyuH4yKLNncy2RtNwx
# AQv3Rwqm8ddK7VZgxCwIo3tAsLx0J1KH1r6I3TeKiW5niB31yV2g/rarOoDXGpc8
# FzYiQR6sTdWD5jw4vU8w6VSp07YEwzJ2YbuwGMUrGLPAgNW3lbBeUU0i/OxYqujY
# lLSlLu2S3ucYfCFX3VVj979tzR/SpncocMfiWzpbCNJbTsgAlrPhgzavhgplXHT2
# 6ux6anSg8Evu75SjrFDyh+3XOjCDyft9V77l4/hByuVkrrOj7FjshZrM77nq81YY
# uVxzmq/FdxeDWds3GhhyVKVB0rYjdaNDmuV3fJZ5t0GNv+zcgKCf0Xd1WF81E+Al
# GmcLfc4l+gcK5GEh2NQc5QfGNpn0ltDGFf5Ozdeui53bFv0ExpK91IjmqaOqu/dk
# ODtfzAzQNb50GQOmxapMomE2gj4d8yu8l13bS3g7LfU772Aj6PXsCyM2la+YZr9T
# 03u4aUoqlmZpxJTG9F9urJh4iIAGXKKy7aIwggalMIIEjaADAgECAhMzAAdbGEDf
# TgkXlXTxAAAAB1sYMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ
# RCBWZXJpZmllZCBDUyBFT0MgQ0EgMDQwHhcNMjYxMDAxMDI1MDE5WhcNMjYxMDA0
# MDI1MDE5WjBnMQswCQYDVQQGEwJVUzELMAkGA1UECBMCbmQxEzARBgNVBAcTCldl
# c3QgRmFyZ28xGjAYBgNVBAoTEUNhbWVyb24gQmF0dGFnbGVyMRowGAYDVQQDExFD
# YW1lcm9uIEJhdHRhZ2xlcjCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGB
# ALVoOcv+l3IwxEApp8l09TPrsNALwfZgh9Fq2DPFwPAODX3D4adBG9TwaG+9WhUz
# sKgj3ICTmmW5RMqkERpPqxbWgWpyH11k5wv1MtLM4DN28sq+GgdFOHiifMzEaZBe
# szBknSx9GoX8KqsmLlr/ihXJ8EePbgGPTzpzc7Y/zUtwJxgo4J7FCPvKwp1hwm+b
# 55pz/3EjdVOW8xH+L3yj0cRfEmXiVMPlz/v/3cObU1H/v3tHNDOFQTYb7oUYdvAD
# vuwQv8uO75S+T9B9ZLKq6KCTGOBJL8RIm8lMgus2osbraofB10Ta60UZXGIuph3S
# 5v/3YrXMLL4pZYTRzOg1QBwVxm0vIuOANpoTrSOz+cu46JbllR7ztp4MRokIDc1u
# /1fT/fZ88Qby0gH9qZats619otwnZ1cCZVXqlNPjunYblf0NxpguejrRGfoL8hOE
# g3g9QRZ4qPAl6ge4ektG5p1QhrrfwPzXG1FVXSpK3wz0GT9rU3b1DSCyX3LU8Aeh
# 7wIDAQABo4IB1TCCAdEwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwPAYD
# VR0lBDUwMwYKKwYBBAGCN2EBAAYIKwYBBQUHAwMGGysGAQQBgjdhgpCMjhjwj9wE
# gfC73D+ByYzTEzAdBgNVHQ4EFgQUEB2TH85lgaBpjWqWpUWcJncgK08wHwYDVR0j
# BBgwFoAUmvFUd3UMhxY3RqCs3nn59H/BeOkwZwYDVR0fBGAwXjBcoFqgWIZWaHR0
# cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwSUQl
# MjBWZXJpZmllZCUyMENTJTIwRU9DJTIwQ0ElMjAwNC5jcmwwdAYIKwYBBQUHAQEE
# aDBmMGQGCCsGAQUFBzAChlhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz
# L2NlcnRzL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDUyUyMEVPQyUyMENB
# JTIwMDQuY3J0MFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNodHRw
# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0w
# DQYJKoZIhvcNAQEMBQADggIBACw5WA5GTU/3h+1vi/q8rC97QBcMfueg0oqMiEg1
# E123nAksZOfJQTe6gWUqa/sWuHvno+hpV8OPTC2FhLlD6nc9OMNmt6IE/eYIDtFv
# pzLIg5t11T8NRLpYMINhhezLFmy8ExtA0F4d0qMPzXqIZRnfON3skT6iwm1oZIbV
# y0We+ScjAgVFjcCrCeUeZbmQCBG9qIhzmWazMQTt0KDDsCDF14bDmTLLhRsbkNKh
# HOYToMRfndhof+Rn0ZrYMXt5eCqhkmaXrMK7NBwqXO2jT6n1/3I7tva+xME8Na6B
# Vuu+PcdaQa35GpigYQvJJvqyuV+3Xq9rIXR+TPQyK1249VJL/npb7Pk8yYncLY5t
# qTODKIQqCi7V8tuFr3uTmD3TYdsOlAAFodmLzcoYEc4HG7cHy36n3milM6pz8U3K
# ZQ8f8Uk1CdSubDxd65JDLWeEcYdWU3agZJaUmIzJgljj0uO6TWThMPXnZ0pcwHwP
# QcuQs6Xty4trf0dSaMGRRZS7pvL1mHYlBapOIitmDHiph4SuFnIigpX0EX69zDny
# 4jS7H13t1aFvPBYx6+9aRnlmSAMUpZCKqiFopMrIQa8Rn0AyL6RPuJ1RRem7kkgU
# v6YmvCYJAs46yoWVAlop/2f+lhG9Zd71QjuVI+sed6Hoe100E8QKwF6JW0KDX+fu
# oxsrMIIGpTCCBI2gAwIBAgITMwAHWxhA304JF5V08QAAAAdbGDANBgkqhkiG9w0B
# AQwFADBaMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMSswKQYDVQQDEyJNaWNyb3NvZnQgSUQgVmVyaWZpZWQgQ1MgRU9DIENBIDA0
# MB4XDTI2MTAwMTAyNTAxOVoXDTI2MTAwNDAyNTAxOVowZzELMAkGA1UEBhMCVVMx
# CzAJBgNVBAgTAm5kMRMwEQYDVQQHEwpXZXN0IEZhcmdvMRowGAYDVQQKExFDYW1l
# cm9uIEJhdHRhZ2xlcjEaMBgGA1UEAxMRQ2FtZXJvbiBCYXR0YWdsZXIwggGiMA0G
# CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC1aDnL/pdyMMRAKafJdPUz67DQC8H2
# YIfRatgzxcDwDg19w+GnQRvU8GhvvVoVM7CoI9yAk5pluUTKpBEaT6sW1oFqch9d
# ZOcL9TLSzOAzdvLKvhoHRTh4onzMxGmQXrMwZJ0sfRqF/CqrJi5a/4oVyfBHj24B
# j086c3O2P81LcCcYKOCexQj7ysKdYcJvm+eac/9xI3VTlvMR/i98o9HEXxJl4lTD
# 5c/7/93Dm1NR/797RzQzhUE2G+6FGHbwA77sEL/Lju+Uvk/QfWSyquigkxjgSS/E
# SJvJTILrNqLG62qHwddE2utFGVxiLqYd0ub/92K1zCy+KWWE0czoNUAcFcZtLyLj
# gDaaE60js/nLuOiW5ZUe87aeDEaJCA3Nbv9X0/32fPEG8tIB/amWrbOtfaLcJ2dX
# AmVV6pTT47p2G5X9DcaYLno60Rn6C/IThIN4PUEWeKjwJeoHuHpLRuadUIa638D8
# 1xtRVV0qSt8M9Bk/a1N29Q0gsl9y1PAHoe8CAwEAAaOCAdUwggHRMAwGA1UdEwEB
# /wQCMAAwDgYDVR0PAQH/BAQDAgeAMDwGA1UdJQQ1MDMGCisGAQQBgjdhAQAGCCsG
# AQUFBwMDBhsrBgEEAYI3YYKQjI4Y8I/cBIHwu9w/gcmM0xMwHQYDVR0OBBYEFBAd
# kx/OZYGgaY1qlqVFnCZ3ICtPMB8GA1UdIwQYMBaAFJrxVHd1DIcWN0agrN55+fR/
# wXjpMGcGA1UdHwRgMF4wXKBaoFiGVmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w
# a2lvcHMvY3JsL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDUyUyMEVPQyUy
# MENBJTIwMDQuY3JsMHQGCCsGAQUFBwEBBGgwZjBkBggrBgEFBQcwAoZYaHR0cDov
# L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBJRCUy
# MFZlcmlmaWVkJTIwQ1MlMjBFT0MlMjBDQSUyMDA0LmNydDBUBgNVHSAETTBLMEkG
# BFUdIAAwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3Br
# aW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMA0GCSqGSIb3DQEBDAUAA4ICAQAsOVgO
# Rk1P94ftb4v6vKwve0AXDH7noNKKjIhINRNdt5wJLGTnyUE3uoFlKmv7Frh756Po
# aVfDj0wthYS5Q+p3PTjDZreiBP3mCA7Rb6cyyIObddU/DUS6WDCDYYXsyxZsvBMb
# QNBeHdKjD816iGUZ3zjd7JE+osJtaGSG1ctFnvknIwIFRY3AqwnlHmW5kAgRvaiI
# c5lmszEE7dCgw7AgxdeGw5kyy4UbG5DSoRzmE6DEX53YaH/kZ9Ga2DF7eXgqoZJm
# l6zCuzQcKlzto0+p9f9yO7b2vsTBPDWugVbrvj3HWkGt+RqYoGELySb6srlft16v
# ayF0fkz0MitduPVSS/56W+z5PMmJ3C2ObakzgyiEKgou1fLbha97k5g902HbDpQA
# BaHZi83KGBHOBxu3B8t+p95opTOqc/FNymUPH/FJNQnUrmw8XeuSQy1nhHGHVlN2
# oGSWlJiMyYJY49Ljuk1k4TD152dKXMB8D0HLkLOl7cuLa39HUmjBkUWUu6by9Zh2
# JQWqTiIrZgx4qYeErhZyIoKV9BF+vcw58uI0ux9d7dWhbzwWMevvWkZ5ZkgDFKWQ
# iqohaKTKyEGvEZ9AMi+kT7idUUXpu5JIFL+mJrwmCQLOOsqFlQJaKf9n/pYRvWXe
# 9UI7lSPrHneh6HtdNBPECsBeiVtCg1/n7qMbKzCCBygwggUQoAMCAQICEzMAAAAX
# J0UJC4uHr8YAAAAAABcwDQYJKoZIhvcNAQEMBQAwYzELMAkGA1UEBhMCVVMxHjAc
# BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE0MDIGA1UEAxMrTWljcm9zb2Z0
# IElEIFZlcmlmaWVkIENvZGUgU2lnbmluZyBQQ0EgMjAyMTAeFw0yNjAzMjYxODEx
# MzFaFw0zMTAzMjYxODExMzFaMFoxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJRCBWZXJpZmll
# ZCBDUyBFT0MgQ0EgMDQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCC
# x2T+Aw9mKgGVzJ+Tq0PMn49G3itIsYpbx7ClLSRHFe1RELdPcZ1sIqWOhsSfy6yy
# qEapClGH9Je9FXA1cQgZvvpQbkg+QInVLr/0EPrVBCwrM96lbRI2PxNeCwXG9Lsy
# W2hG6KQgintDmNCBo4zpDIr377plVdSliZm6UB7rHwmvBnR02QT6tnrqWq2ihzB6
# lRJVTEzuh0OafzIMeMnYM0+x+ve5EOLHdfiq+HXiMf9Jb7YLHtYgyHIiJA7bTWLq
# FSLGaTh7ZlbxbsLXA91OOroEpv7OjzFuu3tkpC9FflA4Dp2Euq4+qPmxUqfGp+TX
# 0gLRJp9NJOzzILjcTD3rkFFFbxUv1xyg6avivFDLtoKBhM2Td138umE1pNOacanu
# SYtPHIeQHmB6haFi64avLBLwTTAm/Rbit860cFXR72wq+5Qh4hSmezHqKXERWPpV
# Be+APrJ4Iqc+aPeMmIkoCWZQO22HnLNFUFSXjiwyIbgvlH/LIAJEqTafTzxDZgKh
# lLU7zr6gwsq3WNpcYQI6NuxWnwh3VVDDyF7onQqKs5Ll7bleVN0Y8VvqgE45ppyB
# bvwqN/Run5fMCCRz3aYMY0kZhKO92eP7t4zHqZ5bQMAgZ0tE2Pz/jb0wiykUF/Pc
# oOqqk3vVLiRDYst6vd3GEMNzMpUUvQcvBG46+COIbwIDAQABo4IB3DCCAdgwDgYD
# VR0PAQH/BAQDAgGGMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBSa8VR3dQyH
# FjdGoKzeefn0f8F46TBUBgNVHSAETTBLMEkGBFUdIAAwQTA/BggrBgEFBQcCARYz
# aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnku
# aHRtMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMBIGA1UdEwEB/wQIMAYBAf8C
# AQAwHwYDVR0jBBgwFoAU2UEpsA8PY2zvadf1zSmepEhqMOYwcAYDVR0fBGkwZzBl
# oGOgYYZfaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9z
# b2Z0JTIwSUQlMjBWZXJpZmllZCUyMENvZGUlMjBTaWduaW5nJTIwUENBJTIwMjAy
# MS5jcmwwfQYIKwYBBQUHAQEEcTBvMG0GCCsGAQUFBzAChmFodHRwOi8vd3d3Lm1p
# Y3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMElEJTIwVmVyaWZp
# ZWQlMjBDb2RlJTIwU2lnbmluZyUyMFBDQSUyMDIwMjEuY3J0MA0GCSqGSIb3DQEB
# DAUAA4ICAQCQdVoZ/U0m38l2iKaZFlsxavptpoOLyaR1a9ZK2TSF1kOnFJhMDse6
# KkCgsveoiEjXTVc6Xt86IKHn76Nk5qZB0BXv2iMRQ2giAJmYvZcmstoZqfB2M3Kd
# 5wnJhUJOtF/b6HsqSelY6nhrF06zor1lDmDQixBZcLB9zR1+RKQso1jekNxYuUk+
# HaN3k1S57qk0O//YbkwU0mELCW04N5vICMZx5T5c7Nq/7uLvbVhCdD7f2bZpA4U7
# vOkB1ooB4AaER3pjoJ0Mad5LFyi6Na9p9Zu/hrLeOjU5FItS5YxsqvlfXxAThJ17
# 6CmkYstKRmytSHZ7JhKRfV6e9Zftk/ODb/CK4pGVAVqsOf4337bQGrOHHCQ3IvN9
# gmnUuDh8JdvbheoWPHxIN1GB5sUiY584tXN7xdD8LCSsRqJvQ8e7a3gZWTgViugR
# s1QWq+N0G9Nje6JHlN1CjJehge+H5PGktJja+juGEr0P+ukSkcL6qaZxFQTh3SDI
# 71lvW++3bl/Ezd6SO8N9Udw+reoyvRHCyTiSsplZQSBTVJdPmo3qCpGuyHFtPo5C
# Bn3/FPTiqJd3M9BHoqKd0G9Kmg6fGcAvFwnLNXA2kov727wRljL3ypfqL7iAT/Yn
# pxul6RwHRlcOf9dDGg1RRvr92NP/CWVXIb68geR2rvU/NsfmtjF1wDCCB54wggWG
# oAMCAQICEzMAAAAHh6M0o3uljhwAAAAAAAcwDQYJKoZIhvcNAQEMBQAwdzELMAkG
# A1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjFIMEYGA1UE
# AxM/TWljcm9zb2Z0IElkZW50aXR5IFZlcmlmaWNhdGlvbiBSb290IENlcnRpZmlj
# YXRlIEF1dGhvcml0eSAyMDIwMB4XDTIxMDQwMTIwMDUyMFoXDTM2MDQwMTIwMTUy
# MFowYzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
# bjE0MDIGA1UEAxMrTWljcm9zb2Z0IElEIFZlcmlmaWVkIENvZGUgU2lnbmluZyBQ
# Q0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALLwwK8ZiCji
# 3VR6TElsaQhVCbRS/3pK+MHrJSj3Zxd3KU3rlfL3qrZilYKJNqztA9OQacr1AwoN
# cHbKBLbsQAhBnIB34zxf52bDpIO3NJlfIaTE/xrweLoQ71lzCHkD7A4As1Bs076I
# u+mA6cQzsYYH/Cbl1icwQ6C65rU4V9NQhNUwgrx9rGQ//h890Q8JdjLLw0nV+ayQ
# 2Fbkd242o9kH82RZsH3HEyqjAB5a8+Ae2nPIPc8sZU6ZE7iRrRZywRmrKDp5+Tcm
# JX9MRff241UaOBs4NmHOyke8oU1TYrkxh+YeHgfWo5tTgkoSMoayqoDpHOLJs+qG
# 8Tvh8SnifW2Jj3+ii11TS8/FGngEaNAWrbyfNrC69oKpRQXY9bGH6jn9NEJv9weF
# xhTwyvx9OJLXmRGbAUXN1U9nf4lXezky6Uh/cgjkVd6CGUAf0K+Jw+GE/5VpIVbc
# Nr9rNE50Sbmy/4RTCEGvOq3GhjITbCa4crCzTTHgYYjHs1NbOc6brH+eKpWLtr+b
# Gecy9CrwQyx7S/BfYJ+ozst7+yZtG2wR461uckFu0t+gCwLdN0A6cFtSRtR8bvxV
# FyWwTtgMMFRuBa3vmUOTnfKLsLefRaQcVTgRnzeLzdpt32cdYKp+dhr2ogc+qM6K
# 4CBI5/j4VFyC4QFeUP2YAidLtvpXRRo3AgMBAAGjggI1MIICMTAOBgNVHQ8BAf8E
# BAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFNlBKbAPD2Ns72nX9c0p
# nqRIajDmMFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNodHRwOi8v
# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wGQYJ
# KwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME
# GDAWgBTIftJqhSobyhmYBAcnz1AQT2ioojCBhAYDVR0fBH0wezB5oHegdYZzaHR0
# cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwSWRl
# bnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIwQ2VydGlmaWNhdGUlMjBBdXRo
# b3JpdHklMjAyMDIwLmNybDCBwwYIKwYBBQUHAQEEgbYwgbMwgYEGCCsGAQUFBzAC
# hnVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29m
# dCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIwUm9vdCUyMENlcnRpZmljYXRl
# JTIwQXV0aG9yaXR5JTIwMjAyMC5jcnQwLQYIKwYBBQUHMAGGIWh0dHA6Ly9vbmVv
# Y3NwLm1pY3Jvc29mdC5jb20vb2NzcDANBgkqhkiG9w0BAQwFAAOCAgEAfyUqnv7U
# q+rdZgrbVyNMul5skONbhls5fccPlmIbzi+OwVdPQ4H55v7VOInnmezQEeW4LqK0
# wja+fBznANbXLB0KrdMCbHQpbLvG6UA/Xv2pfpVIE1CRFfNF4XKO8XYEa3oW8oVH
# +KZHgIQRIwAbyFKQ9iyj4aOWeAzwk+f9E5StNp5T8FG7/VEURIVWArbAzPt9ThVN
# 3w1fAZkF7+YU9kbq1bCR2YD+MtunSQ1Rft6XG7b4e0ejRA7mB2IoX5hNh3UEauY0
# byxNRG+fT2MCEhQl9g2i2fs6VOG19CNep7SquKaBjhWmirYyANb0RJSLWjinMLXN
# OAga10n8i9jqeprzSMU5ODmrMCJE12xS/NWShg/tuLjAsKP6SzYZ+1Ry358ZTFcx
# 0FS/mx2vSoU8s8HRvy+rnXqyUJ9HBqS0DErVLjQwK8VtsBdekBmdTbQVoCgPCqr+
# PDPB3xajYnzevs7eidBsM71PINK2BoE2UfMwxCCX3mccFgx6UsQeRSdVVVNSyALQ
# e6PT12418xon2iDGE81OGCreLzDcMAZnrUAx4XQLUz6ZTl65yPUiOh3k7Yww94lD
# f+8oG2oZmDh5O1Qe38E+M3vhKwmzIeoB1dVLlz4i3IpaDcR+iuGjH2TdaC1ZOmBX
# iCRKJLj4DT2uhJ04ji+tHD6n58vhavFIrmcxghqUMIIakAIBATBxMFoxCzAJBgNV
# BAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMT
# Ik1pY3Jvc29mdCBJRCBWZXJpZmllZCBDUyBFT0MgQ0EgMDQCEzMAB1sYQN9OCReV
# dPEAAAAHWxgwDQYJYIZIAWUDBAIBBQCgXjAQBgorBgEEAYI3AgEMMQIwADAZBgkq
# hkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAvBgkqhkiG9w0BCQQxIgQgtHH64p3UeQGI
# 1ZNaPEjULGphyC1as9l2G4Ukm0hbR4cwDQYJKoZIhvcNAQEBBQAEggGAJ/MGLrg5
# fqekph3+uEdNS5Ahd1rHhUh2iRi+qRpEufYx+/qOH3rS0hWyInuqqW0BnaVIFaor
# i+YFIrv9H/yOwybwSI/TsePC4oOhN0MbgHJ3L3rXYtqO5zaCjw6iKhQQRuypS8WH
# 7/a3jd+yRIjZkNmEOcolna5goE1+5JF1R+rsOaT3CQaeuaP9HardEPJUEJw7s9lZ
# 2j0E45oXqQN4WCeGw3vdnQdjIcfHB4KJVxKpSQ7ajSqQusnJtdHqsRTllPNBgDxZ
# JUQVxVNNQj5E2jgAqY7SlR9PiURzkcbZjyh61UXF+aNNOIE0wvKENmhoVQn7FY9L
# Z+m+tWtV96VBGBxXJMmP6hzWD3uAyjN1VskA+JrtNybxJxrURoRg1Omk3o5TlwnT
# OaLq+goX+rixen7bek6VYRlwY92i487oJyEM0S0mprI1+7uiZmIfSCBe3oHRKEwf
# WqPS5maMcmijzFzCdVP0NXK75RRWzLtKk9lJOcVOjPP5A5BnHHbY/HLioYIYFDCC
# GBAGCisGAQQBgjcDAwExghgAMIIX/AYJKoZIhvcNAQcCoIIX7TCCF+kCAQMxDzAN
# BglghkgBZQMEAgEFADCCAWIGCyqGSIb3DQEJEAEEoIIBUQSCAU0wggFJAgEBBgor
# BgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIBBQAEINyPoboT6B4Lv7Nz1ceV1PDSIQgl
# cGD+XMZKpfjmG3zVAgZqqTOqjUQYEzIwMjYxMDAyMTcwMzMxLjU3OFowBIACAfSg
# geGkgd4wgdsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD
# VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAj
# BgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJzAlBgNVBAsTHm5T
# aGllbGQgVFNTIEVTTjpBNTAwLTA1RTAtRDk0NzE1MDMGA1UEAxMsTWljcm9zb2Z0
# IFB1YmxpYyBSU0EgVGltZSBTdGFtcGluZyBBdXRob3JpdHmggg8hMIIHgjCCBWqg
# AwIBAgITMwAAAAXlzw//Zi7JhwAAAAAABTANBgkqhkiG9w0BAQwFADB3MQswCQYD
# VQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMUgwRgYDVQQD
# Ez9NaWNyb3NvZnQgSWRlbnRpdHkgVmVyaWZpY2F0aW9uIFJvb3QgQ2VydGlmaWNh
# dGUgQXV0aG9yaXR5IDIwMjAwHhcNMjAxMTE5MjAzMjMxWhcNMzUxMTE5MjA0MjMx
# WjBhMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
# MTIwMAYDVQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0Eg
# MjAyMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJ5851Jj/eDFnwV9
# Y7UGIqMcHtfnlzPREwW9ZUZHd5HBXXBvf7KrQ5cMSqFSHGqg2/qJhYqOQxwuEQXG
# 8kB41wsDJP5d0zmLYKAY8Zxv3lYkuLDsfMuIEqvGYOPURAH+Ybl4SJEESnt0MbPE
# oKdNihwM5xGv0rGofJ1qOYSTNcc55EbBT7uq3wx3mXhtVmtcCEr5ZKTkKKE1CxZv
# NPWdGWJUPC6e4uRfWHIhZcgCsJ+sozf5EeH5KrlFnxpjKKTavwfFP6XaGZGWUG8T
# ZaiTogRoAlqcevbiqioUz1Yt4FRK53P6ovnUfANjIgM9JDdJ4e0qiDRm5sOTiEQt
# BLGd9Vhd1MadxoGcHrRCsS5rO9yhv2fjJHrmlQ0EIXmp4DhDBieKUGR+eZ4CNE3c
# tW4uvSDQVeSp9h1SaPV8UWEfyTxgGjOsRpeexIveR1MPTVf7gt8hY64XNPO6iyUG
# sEgt8c2PxF87E+CO7A28TpjNq5eLiiunhKbq0XbjkNoU5JhtYUrlmAbpxRjb9tSr
# eDdtACpm3rkpxp7AQndnI0Shu/fk1/rE3oWsDqMX3jjv40e8KN5YsJBnczyWB4Jy
# eeFMW3JBfdeAKhzohFe8U5w9WuvcP1E8cIxLoKSDzCCBOu0hWdjzKNu8Y5SwB1lt
# 5dQhABYyzR3dxEO/T1K/BVF3rV69AgMBAAGjggIbMIICFzAOBgNVHQ8BAf8EBAMC
# AYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFGtpKDo1L0hjQM972K9J6T7Z
# PdshMFQGA1UdIARNMEswSQYEVR0gADBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wEwYDVR0l
# BAwwCgYIKwYBBQUHAwgwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDwYDVR0T
# AQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTIftJqhSobyhmYBAcnz1AQT2ioojCBhAYD
# VR0fBH0wezB5oHegdYZzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j
# cmwvTWljcm9zb2Z0JTIwSWRlbnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIw
# Q2VydGlmaWNhdGUlMjBBdXRob3JpdHklMjAyMDIwLmNybDCBlAYIKwYBBQUHAQEE
# gYcwgYQwgYEGCCsGAQUFBzAChnVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp
# b3BzL2NlcnRzL01pY3Jvc29mdCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIw
# Um9vdCUyMENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAyMC5jcnQwDQYJKoZI
# hvcNAQEMBQADggIBAF+Idsd+bbVaFXXnTHho+k7h2ESZJRWluLE0Oa/pO+4ge/XE
# izXvhs0Y7+KVYyb4nHlugBesnFqBGEdC2IWmtKMyS1OWIviwpnK3aL5JedwzbeBF
# 7POyg6IGG/XhhJ3UqWeWTO+Czb1c2NP5zyEh89F72u9UIw+IfvM9lzDmc2O2END7
# MPnrcjWdQnrLn1Ntday7JSyrDvBdmgbNnCKNZPmhzoa8PccOiQljjTW6GePe5sGF
# uRHzdFt8y+bN2neF7Zu8hTO1I64XNGqst8S+w+RUdie8fXC1jKu3m9KGIqF4aldr
# YBamyh3g4nJPj/LR2CBaLyD+2BuGZCVmoNR/dSpRCxlot0i79dKOChmoONqbMI8m
# 04uLaEHAv4qwKHQ1vBzbV/nG89LDKbRSSvijmwJwxRxLLpMQ/u4xXxFfR4f/gksS
# kbJp7oqLwliDm/h+w0aJ/U5ccnYhYb7vPKNMN+SZDWycU5ODIRfyoGl59BsXR/Hp
# RGtiJquOYGmvA/pk5vC1lcnbeMrcWD/26ozePQ/TWfNXKBOmkFpvPE8CH+EeGGWz
# qTCjdAsno2jzTeNSxlx3glDGJgcdz5D/AAxw9Sdgq/+rY7jjgs7X6fqPTXPmaCAJ
# KVHAP19oEjJIBwD1LyHbaEgBxFCogYSOiUIr0Xqcr1nJfiWG2GwYe6ZoAF1bMIIH
# lzCCBX+gAwIBAgITMwAAAFZ+j51YCI7pYAAAAAAAVjANBgkqhkiG9w0BAQwFADBh
# MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIw
# MAYDVQQDEylNaWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAy
# MDAeFw0yNTEwMjMyMDQ2NTFaFw0yNjEwMjIyMDQ2NTFaMIHbMQswCQYDVQQGEwJV
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1l
# cmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046QTUwMC0w
# NUUwLUQ5NDcxNTAzBgNVBAMTLE1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWUgU3Rh
# bXBpbmcgQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
# tKWfm/ul027/d8Rlb8Mn/g0QUvvLqY2Vsy3tI8U2tFSspTZomZOD3BHT8LkR+Rrh
# MJgb1VjAKFNysaK9cLSXifPGSIBrPCgs9P4y24lrJEmrV6Q5z4BmqMhIPrZhEvZn
# WpCS4HO7jYSei/nxmC7/1Er+l5Lg3PmSxb8d2IVcARxSw1B4mxB6XI0nkel9wa1d
# Yb2wfGpofraFmxZOxT9eNht4LH0RBSVueba6ZNpjS/0gtfm7qiIiyP6p6PRzTTbM
# nVqsHnV/d/rW0zHx+Q+QNZ5wUqKmTZJB9hU853+2pX5rDfK32uNY9/WBOAmzbqgp
# EdQkbiMavUMyUDShmycIvgHdQnS207sTj8M+kJL3tOdahPuPqMwsaCCgdfwwQx0O
# 9TKe7FSvbAEYs1AnldCl/KHGZCOVvUNqjyL10JLe0/+GD9/ynqXGWFpXOjaunvZ/
# cKROhjN4M5e6xx0b2miqcPii4/ii2ZheKallJET7CKlpFShs3wyg6F/fojQxQvPn
# bWD4Nyx6lhjWjwmoLcx6w1FSCtavLCly33BLRSlTU4qKUxaa8d7YN7Eqpn9XO0SY
# 0umOvKFXrWH7rxl+9iaicitdnTTksAnRjvekdKT3lg7lRMfmfZU8vXNiN0UYJzT9
# EjqjRm0uN/h0oXxPhNfPYqeFbyPXGGxzaYUz6zx3qTcCAwEAAaOCAcswggHHMB0G
# A1UdDgQWBBS+tjPyu6tZ/h5GsyLvyz1H+FNIWjAfBgNVHSMEGDAWgBRraSg6NS9I
# Y0DPe9ivSek+2T3bITBsBgNVHR8EZTBjMGGgX6BdhltodHRwOi8vd3d3Lm1pY3Jv
# c29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBQdWJsaWMlMjBSU0ElMjBU
# aW1lc3RhbXBpbmclMjBDQSUyMDIwMjAuY3JsMHkGCCsGAQUFBwEBBG0wazBpBggr
# BgEFBQcwAoZdaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9N
# aWNyb3NvZnQlMjBQdWJsaWMlMjBSU0ElMjBUaW1lc3RhbXBpbmclMjBDQSUyMDIw
# MjAuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwDgYD
# VR0PAQH/BAQDAgeAMGYGA1UdIARfMF0wUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYB
# BQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBv
# c2l0b3J5Lmh0bTAIBgZngQwBBAIwDQYJKoZIhvcNAQEMBQADggIBAA4DqAXEsO26
# j/La7Fgn/Qifit8xuZekqZ57+Ye+sH/hRTbEEjGYrZgsqwR/lUUfKCFpbZF8msaZ
# PQJOR4YYUEU8XyjLrn8Y1jCSmoxh9l7tWiSoc/JFBw356JAmzGGxeBA2EWSxRuTr
# 1AuZe6nYaN8/wtFkiHcs8gMadxXBs6DxVhyu5YnhLPQkfumKm3lFftwE7pieV7f1
# lskmlgsC6AeSGCzGPZUgCvcH5Tv/Qe9z7bIImSD3SuzhOIwaP+eKQTYf67TifyJK
# kWQSdGfTA6Kcu41k8LB6oPK+MLk1jbxxK5wPqLSL62xjK04SBXHEJSEnsFt0zxWk
# xP/lgej1DxqUnmrYEdkxvzKSHIAqFWSZul/5hI+vJxvFPhsNQBEk4cSulDkJQpcd
# Vi/gmf/mHFOYhDBjsa15s4L+2sBil3XV/T8RiR66Q8xYvTLRWxd2dVsrOoCwnsU4
# WIeiC0JinCv1WLHEh7Qyzr9RSr4kKJLWdpNYLhgjkojTmEkAjFO774t3xB7enbvI
# F0GOsV19xnCUzq9EGKyt0gMuaphKlNjJ+aTpjWMZDGo+GOKsnp93Hmftml0Syp3F
# 9+M3y+y6WJGUZoIZJq227jDjjEndtpUrh9BdPdVIfVJD/Au81Rzh05UHAivorQ3O
# s8PELHIgiOd9TWzbdgmGzcILt/ddVQERMYIHRjCCB0ICAQEweDBhMQswCQYDVQQG
# EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylN
# aWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMAITMwAAAFZ+
# j51YCI7pYAAAAAAAVjANBglghkgBZQMEAgEFAKCCBJ8wEQYLKoZIhvcNAQkQAg8x
# AgUAMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcN
# MjYxMDAyMTcwMzMxWjAvBgkqhkiG9w0BCQQxIgQg1+NUuXhAhNwmii7ZFlSJhKMP
# K3EQlXT5uTMHshjG3WIwgbkGCyqGSIb3DQEJEAIvMYGpMIGmMIGjMIGgBCC2DDMl
# TaTj8JV3iTg5Xnpe4CSH60143Z+X9o5NBgMMqDB8MGWkYzBhMQswCQYDVQQGEwJV
# UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNy
# b3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMAITMwAAAFZ+j51Y
# CI7pYAAAAAAAVjCCA2EGCyqGSIb3DQEJEAISMYIDUDCCA0yhggNIMIIDRDCCAiwC
# AQEwggEJoYHhpIHeMIHbMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYD
# VQQLEx5uU2hpZWxkIFRTUyBFU046QTUwMC0wNUUwLUQ5NDcxNTAzBgNVBAMTLE1p
# Y3Jvc29mdCBQdWJsaWMgUlNBIFRpbWUgU3RhbXBpbmcgQXV0aG9yaXR5oiMKAQEw
# BwYFKw4DAhoDFQD/c/cpFSqQWYBeXggyRJ2ZbvYEEaBnMGWkYzBhMQswCQYDVQQG
# EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylN
# aWNyb3NvZnQgUHVibGljIFJTQSBUaW1lc3RhbXBpbmcgQ0EgMjAyMDANBgkqhkiG
# 9w0BAQsFAAIFAO5qG4QwIhgPMjAyNjEwMDIxMjAxMDhaGA8yMDI2MTAwMzEyMDEw
# OFowdzA9BgorBgEEAYRZCgQBMS8wLTAKAgUA7mobhAIBADAKAgEAAgIFVAIB/zAH
# AgEAAgISCDAKAgUA7mttBAIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZ
# CgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBCwUAA4IBAQB2
# hiuiPOa479EleQxZZj+Kldw/H0O7gH6B/ToYi2B7Cy6s/Fq+V+6UoDZubJ7oU8Ra
# kjXJVP/hlRGmqffLuAztCbLjqG5nz3XE8mIuv7mUg4OZFuOOdOzi4F0+xSDbAdo5
# aXZphsWebri2KewoqqeAlpcKoIP/mnXKAioxwxDoTlpaW2CqMfFRYNyYUREBu/Zz
# xeVEjeQTxRzDVTxzpxcxvrFPtvuFno+2u7wm1eDm7CKJKZ3coDeRe6Xv9uaPIHa/
# xcDiS0nfkEw211kulcU43qtN3TTcvez1UZgQpAGFdQ88I0hV/oa8y3VNMQccvLAB
# 7rSXnfbXO80vQZ0bMmMRMA0GCSqGSIb3DQEBAQUABIICAFJ9XqkDjRUovaxqJBJh
# J+GHtuj7KorQSlvk6UlDsBHu1E0uOGX6unCIQ9H/LxHbPgZ8weHWA6c6iuI96i8v
# FMnwYNob4IV1xqOLGJnnCnGfX42v6azL5JkPkG/d8zaQ7tayIC+yPPKh/t8LD3fe
# U1/T7xz1HBLr8kqSLUwBhpJ3IQy/D7l913kVHIbd2OM+/bK4SzBJHU9n85pnf9UJ
# Xb29TjnemcZ4DOdmgB0DDvDT0Bo9gGKRoZLvi562bBL65DKXMdSl0C9XvWpG8EuV
# S0oTpt/pTfrurCbn6DDqLS9rEdz/C0Y5g5W0j/i9eMv1Z1JGRA9297qlfnjpVNFu
# Tnen8yBfoX78fnYDMFn7tETrSaP/kovYTBj8MnU9rFx1ki+Io/CTZGTGxG+OYjkd
# CD7jS7No0ofBOKzfQ+n8N35fs7pzSer3iAR6RncvaZEWaeQZ+QxYrRQ0Rnp2I1YF
# MmvpufGyfhNhdRYeEplp8zMGnw+9Z8RMA8ldK7ftYPzFTNvEH9E+5+QyAG77RD3k
# Cn1s6CfFAvldzjKs8EptHUMKEL2tCU44R7asudknWtvZkYrOcR9v3HTGbcmzJqWe
# HavdT1/EzpP6Y7vWL/gUELs2rmFnqQYEiYsKKnalFYf2wquFrY/1uXYxHHnb8e4M
# zgnNBbXtHwME50q10xW5iZao
# SIG # End signature block