[CmdletBinding()]
param
(
    [Parameter(Mandatory=$false)]
    [string]$LogDir,

    [parameter(Mandatory=$false)]
    [boolean] $useServiceFabric=$false,

    [Parameter(Mandatory = $false)]
    [string]$ActivityId,

    [Parameter(Mandatory = $false)]
    [string]$RunbookId,

    [Parameter(Mandatory=$false)]
	[hashtable]$AxDRConnectionString,

    [Parameter(Mandatory=$false)]
	[string[]]$EnabledServicingFeatures,

    [Parameter(Mandatory=$false)]
	[Switch]$PreDowntime,

    [Parameter(Mandatory=$false)]
    [hashtable]$Credentials
)

# Pre-defined list of error messages for known customer induced issues
$knownErrorHash = @{
    "The CREATE UNIQUE INDEX statement terminated because a duplicate key" = 131079
    "Please drop the original field, sync the table" = 131089
    "extension cannot be applied to the base element" = 131090
    "is missing the following dependencies" = 131091
    "Method not found" = 131092
}

# Check pre check status
function IsPreCheckSucceeded ([string]$ActivityId)
{
  if(!$ActivityId)
  {
    return $false
  }

  $axDBUser = Get-DataAccessSqlUsr

  if($Credentials -and $Credentials[$($axDBUser)])  {
     $axDBPwd = $Credentials[$($axDBUser)]
     EventWrite-RunbookScriptTrace -Message "Using axdbadmin password from DSU parameters." -Component "servicing" -RunbookId $RunbookId| Out-Null
  }
  else{
     $axDBPwd = Get-DataAccessSqlPwd
     EventWrite-RunbookScriptTrace -Message "Using axdbadmin password from Web config." -Component "servicing" -RunbookId $RunbookId| Out-Null
  }
  
  $axDBDatabaseName = Get-DataAccessDatabase
  $axDBServer = Get-DataAccessDbServer

    $target_sqlParams = @{
		'Database' = $axDBDatabaseName
		'UserName' = $axDBUser
		'Password' = $axDBPwd
		'ServerInstance' = $axDBServer
		'EncryptConnection' = !(IsLocalServer($axDBServer))
		'QueryTimeout' = 0
	    }

    $target_sqlParams.Query = "Select top 1 Success from DBSyncExecStats where SyncStep = 'PreCheck' and RelatedActivityId = '$ActivityId' order by StartDateTime desc"

    try{
        # during first precheck on this environment table will not be exists so catch exception and consider running precheck.
        $result = Invoke-SqlCmd @target_sqlParams
    }
    catch
    {
        $warningMessage = "[$(Get-Date)]:Get pre check status failed, activity id: $ActivityId, Exception: [$($_.Exception)]"
        Write-Host $warningMessage
        EventWrite-RunbookScriptTrace -Message $warningMessage -Component "servicing" -RunbookId $RunbookId| Out-Null
    }

    if ($result -ne $null)
    {
        return $result.Success
    }

    return $false
}

# Run db sync precheck to evaluate DB Sync would fail or succeed.
function RunDBSyncPreCheck([string]$ActivityId, [hashtable]$AxDRConnectionString, [string[]]$EnabledServicingFeatures)
{
    if (!$EnabledServicingFeatures -or $EnabledServicingFeatures -notcontains "DBSyncPreCheck")
    { 
       EventWrite-RunbookScriptTrace -Message "DBSyncPreCheck feature is disabled. Skipping db sync pre check, activity id: $ActivityId" -Component "servicing"  -RunbookId $RunbookId| Out-Null
       return $false
    }

    # Check if previous precheck status for activity id
    if($ActivityId)
    {
        $PreCheckResult = IsPreCheckSucceeded -ActivityId $ActivityId
        if($PreCheckResult -eq $true) 
        {
           # For prod scenario precheck will run during preparation, so we do not need to run it again.
           EventWrite-RunbookScriptTrace -Message "[$(Get-Date)]: Pre service check already succeeded for activity id: $ActivityId, Skipping precheck..." -Component "servicing" -RunbookId $RunbookId| Out-Null
           return $false
        }
     }

    # Run Precheck
    $currentDateTime = [DateTime]::UtcNow.ToString("yyyyMMddHHmmss")
    $logfile = Join-Path $LogDir "dbsyncprecheck_$currentDateTime.log"
    $errorfile = Join-Path $LogDir "dbsyncprecheck.error_$currentDateTime.log"
    Write-Host "Precheck Started..."
   
    if($PreDowntime -eq $true)
    {
      $aosWebServiceStagingPath = Get-AosServiceStagingPath
      $webroot = Join-Path -Path $aosWebServiceStagingPath -ChildPath "WebRoot"
      $PUVersion = Get-ProductPlatformBuildVersion -webroot:$webroot

      $metadatadir = Join-Path -Path $aosWebServiceStagingPath -ChildPath "PackagesLocalDirectory"
    }
    else
    {
      $PUVersion = (Get-ProductPlatformBuildVersion)
      $metadatadir = $(Get-AOSPackageDirectory)
    }

    Write-Host "AOS platform version is: $PUVersion"

    # If PU version >= PU34 then run precheck on secondary DB if exists.
    $runPrecheckOnSecondaryDB = $false
    if($PUVersion -ge 5629 -and $AxDRConnectionString -and $AxDRConnectionString['AxDRServerName'] -and $AxDRConnectionString['AxDRDatabaseName'])
    {
        $runPrecheckOnSecondaryDB =  $true
        $sqlServer =  $AxDRConnectionString['AxDRServerName']
        $sqlDB =  $AxDRConnectionString['AxDRDatabaseName']
        EventWrite-RunbookScriptTrace -Message "[$(Get-Date)]: Running precheck on secondary DB" -Component "servicing" -RunbookId $RunbookId| Out-Null
    }

    # If platform version > PU35 then run precheck with deployment setup exe
    if ($PUVersion -gt 5644)
    {
        EventWrite-RunbookScriptTrace -Message "Running precheck with deployment setup exe, activity id $ActivityId" -Component "servicing" -RunbookId $RunbookId| Out-Null
        $deploymentSetupParameter = "-setupmode preservicecheck -syncmode precheck"
        
        if($ActivityId) 
        {
            $deploymentSetupParameter += " -activityid $ActivityId"
        }

        $deploySetupPs1 = Resolve-Path -Path $deploySetupPs1
        & $deploySetupPs1 -deploymentSetupParameter $deploymentSetupParameter -logfile $logfile -errorfile $errorfile -axDRServerName $sqlServer -axDRDatabaseName $sqlDB -isPreDowntime $PreDowntime | Out-Null
        
        EventWrite-RunbookScriptTrace -Message "[$(Get-Date)]: Pre service check completed using deployment setup for activity id $ActivityId" -Component "servicing" -RunbookId $RunbookId| Out-Null
        return $true
    }
    
    EventWrite-RunbookScriptTrace -Message "Running precheck on Metadata dir: $metadatadir" -Component "servicing" -RunbookId $RunbookId| Out-Null

    # If platform version <= PU35 Run precheck with sync engine exe
    EventWrite-RunbookScriptTrace -Message "Running precheck with sync engine exe, activity id $ActivityId" -Component "servicing" -RunbookId $RunbookId| Out-Null

    $sqlUser = Get-DataAccessSqlUsr
    if($Credentials -and $Credentials[$($sqlUser)]) {
      $sqlPwd = $Credentials[$($sqlUser)]
    }
    else {
      $sqlPwd = Get-DataAccessSqlPwd
    }

    if($runPrecheckOnSecondaryDB -eq $false){
        $sqlServer = Get-DataAccessDbServer
        $sqlDB = Get-DataAccessDatabase
    }

    $connectionString = "Data Source=$($sqlServer); " +
        "Integrated Security=False; " +
        "User Id=$($sqlUser); " +
        "Password='$($sqlPwd)'; " +
        "Initial Catalog=$($sqlDB)"
    
    $command = "$metadatadir\bin\syncengine.exe"
    $commandParameter = "-syncmode=precheck"
    $commandParameter += " -metadatabinaries=$metadatadir"
    $commandParameter +=  " -connect=`"$connectionString`""
    $commandParameter +=  " -enableParallelSync"
                
    if($ActivityId)
    {
        $commandParameter += " -relatedactivityid=$ActivityId"
    }

    $process = Start-Process $command $commandParameter -PassThru -Wait -RedirectStandardOutput "$logfile" -RedirectStandardError "$errorfile"
    Write-Host "Log file location: $logfile"
        
    if ($process.ExitCode -ne 0) {
        $deploymentSetupError = Get-Content "$errorfile"
        throw $deploymentSetupError
    }

    EventWrite-RunbookScriptTrace -Message "[$(Get-Date)]: Pre service check completed using sync engine for activity id $ActivityId" -Component "servicing" -RunbookId $RunbookId| Out-Null
    return $true
}

$ErrorActionPreference = "stop"
Import-Module "$PSScriptRoot\AosEnvironmentUtilities.psm1" -Force -DisableNameChecking
Import-Module "$PSScriptRoot\CommonRollbackUtilities.psm1" -ArgumentList $useServiceFabric -DisableNameChecking

if(!$LogDir)
{
    $LogDir = $PSScriptRoot
}

$deploySetupPs1 = "$PSScriptRoot\TriggerDeploymentSetupEngine.ps1"

# PreCheck
try
{
    # This returns false if pre check skipped.
    $result = RunDBSyncPreCheck -ActivityId $ActivityId -AxDRConnectionString $AxDRConnectionString -EnabledServicingFeatures $EnabledServicingFeatures
   
    if($result -eq $true)
    {   
        $message = "[$(Get-Date)]: Pre service check succeeded for activity id: $ActivityId."
    }
    else
    {
      $message = "[$(Get-Date)]: Pre service check did not run, activity id: $ActivityId."
    }

    Write-Host $message
    EventWrite-RunbookScriptTrace -Message $message -Component "servicing" -RunbookId $RunbookId| Out-Null
}
catch
{
    $errorMessage = "[$(Get-Date)]: Pre service check failed for activity id: $ActivityId, Exception: [$($_.Exception)]"    
    EventWrite-RunbookScriptTrace -Message $errorMessage -Component "servicing" -RunbookId $RunbookId | Out-Null

    if ($EnabledServicingFeatures -and $EnabledServicingFeatures -contains "FailDBSyncOnPrecheckFailure")
    { 
       EventWrite-RunbookScriptTrace -Message "FailDBSyncOnPrecheckFailure feature is enabled and db sync pre-check is failed, activity id: $ActivityId" -Component "servicing" -RunbookId $RunbookId| Out-Null

       # Only fail in dbsync pre-check if the error message contains one of the known error strings
       foreach ($knownError in $knownErrorHash.GetEnumerator())
       {
          if($errorMessage.Contains($knownError.Name))
          {
            # In case precheck failure due to a known customer-induced error scenario we do not require PITR during rollback. In precheck success scenario full sync will run and that will calculate PITR required or not.
            Write-IsPITRRequiredDuringRollback -PitrRequired 'false'

            EventWrite-RunbookScriptTrace -Message "DBSync pre-check failed due to a known customer induced error, error code: $($knownError.Value), activity id: $ActivityId" -Component "servicing" -RunbookId $RunbookId| Out-Null
            throw $errorMessage
          }
       }
    }
}
# SIG # Begin signature block
# MIIr5AYJKoZIhvcNAQcCoIIr1TCCK9ECAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDf8pNtqZY7VDtd
# JiquVayV4+X8rN+4YqEWHTNh3X0wYqCCEW4wggh+MIIHZqADAgECAhM2AAAB33OB
# lxa+Mv0NAAIAAAHfMA0GCSqGSIb3DQEBCwUAMEExEzARBgoJkiaJk/IsZAEZFgNH
# QkwxEzARBgoJkiaJk/IsZAEZFgNBTUUxFTATBgNVBAMTDEFNRSBDUyBDQSAwMTAe
# Fw0yNDAxMjAwMTMzNDRaFw0yNTAxMTkwMTMzNDRaMCQxIjAgBgNVBAMTGU1pY3Jv
# c29mdCBBenVyZSBDb2RlIFNpZ24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
# AoIBAQDVucAmkbIWpspYysyydQyyRh2L8q5igYFcy2vDk8xGvVMRBhxwbOsJIEd0
# wY8N7WU/xgkYMnSsM4vmc2B49DGdrAjSJqbsx0zf+DLFjrBITUecdRhlq0VKGX8U
# bVOkg0aIfFNLRs4DSrCZYh26zyB8qkL/jUmB7DhcBEhhgOlXRQ4LHnUv7qf+iXqD
# uwFz9tUTAh8JGsgLRBK0oSsRfUB+FJF2KyUxzmeFXJKiEynsWz4kqoM91ag1Yw0U
# 8d0e+RgAKi3Ft1cXA+3qKM6I1H11e/NdIjh7oThvrBtfEngwlwbTF3KZOHdhLBFZ
# 18U4v8VeTlb4r94346CY2+SKnQa7AgMBAAGjggWKMIIFhjApBgkrBgEEAYI3FQoE
# HDAaMAwGCisGAQQBgjdbAQEwCgYIKwYBBQUHAwMwPQYJKwYBBAGCNxUHBDAwLgYm
# KwYBBAGCNxUIhpDjDYTVtHiE8Ys+hZvdFs6dEoFgg93NZoaUjDICAWQCAQ4wggJ2
# BggrBgEFBQcBAQSCAmgwggJkMGIGCCsGAQUFBzAChlZodHRwOi8vY3JsLm1pY3Jv
# c29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1F
# JTIwQ1MlMjBDQSUyMDAxKDIpLmNydDBSBggrBgEFBQcwAoZGaHR0cDovL2NybDEu
# YW1lLmdibC9haWEvQlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1FJTIwQ1MlMjBDQSUy
# MDAxKDIpLmNydDBSBggrBgEFBQcwAoZGaHR0cDovL2NybDIuYW1lLmdibC9haWEv
# QlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1FJTIwQ1MlMjBDQSUyMDAxKDIpLmNydDBS
# BggrBgEFBQcwAoZGaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJQ1NDQTAx
# LkFNRS5HQkxfQU1FJTIwQ1MlMjBDQSUyMDAxKDIpLmNydDBSBggrBgEFBQcwAoZG
# aHR0cDovL2NybDQuYW1lLmdibC9haWEvQlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1F
# JTIwQ1MlMjBDQSUyMDAxKDIpLmNydDCBrQYIKwYBBQUHMAKGgaBsZGFwOi8vL0NO
# PUFNRSUyMENTJTIwQ0ElMjAwMSxDTj1BSUEsQ049UHVibGljJTIwS2V5JTIwU2Vy
# dmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1BTUUsREM9R0JM
# P2NBQ2VydGlmaWNhdGU/YmFzZT9vYmplY3RDbGFzcz1jZXJ0aWZpY2F0aW9uQXV0
# aG9yaXR5MB0GA1UdDgQWBBSO7i0qme7tjtjFjyuIjlmGM6cbCTAOBgNVHQ8BAf8E
# BAMCB4AwRQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3Jh
# dGlvbjEWMBQGA1UEBRMNMjM2MTY3KzUwMTk3MDCCAeYGA1UdHwSCAd0wggHZMIIB
# 1aCCAdGgggHNhj9odHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ1JM
# L0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGMWh0dHA6Ly9jcmwxLmFtZS5nYmwv
# Y3JsL0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGMWh0dHA6Ly9jcmwyLmFtZS5n
# YmwvY3JsL0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGMWh0dHA6Ly9jcmwzLmFt
# ZS5nYmwvY3JsL0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGMWh0dHA6Ly9jcmw0
# LmFtZS5nYmwvY3JsL0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGgb1sZGFwOi8v
# L0NOPUFNRSUyMENTJTIwQ0ElMjAwMSgyKSxDTj1CWTJQS0lDU0NBMDEsQ049Q0RQ
# LENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZp
# Z3VyYXRpb24sREM9QU1FLERDPUdCTD9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0
# P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnQwHwYDVR0jBBgw
# FoAUllGE4Gtve/7YBqvD8oXmKa5q+dQwHwYDVR0lBBgwFgYKKwYBBAGCN1sBAQYI
# KwYBBQUHAwMwDQYJKoZIhvcNAQELBQADggEBAJe/YXNSCoXitLf/X5pfJZpep3cs
# jdqmBgg+8Kr++8XMjWwdm4tiLasJMUPCgmp5NYn3wC4GefGYwfF7Xm2FMSR2i6QU
# HjigGu6BjdWQh4EwGaNqXLkXlUM7Ww2Z0KrRtpCL16DCOTNZuCFPAytSHFskPWrr
# 6q3EBuiM6P5VLgFSKiAxcunldJorbrBrvZSZib1OINzFGAQszUR0ytovW6FOp+uo
# VhiQCqnOheC1ppnZPss7vnXoogyO0xgSW40bRlltGfwnlOd3IZ/43ZOj5XeeShg5
# 2SzVEiyYrZjD17MSNzQM1JKI07+mtAC7D+eZ/+g2pM/91oHcrDq9Nq4QrS0wggjo
# MIIG0KADAgECAhMfAAAAUeqP9pxzDKg7AAAAAABRMA0GCSqGSIb3DQEBCwUAMDwx
# EzARBgoJkiaJk/IsZAEZFgNHQkwxEzARBgoJkiaJk/IsZAEZFgNBTUUxEDAOBgNV
# BAMTB2FtZXJvb3QwHhcNMjEwNTIxMTg0NDE0WhcNMjYwNTIxMTg1NDE0WjBBMRMw
# EQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRUwEwYDVQQD
# EwxBTUUgQ1MgQ0EgMDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJ
# mlIJfQGejVbXKpcyFPoFSUllalrinfEV6JMc7i+bZDoL9rNHnHDGfJgeuRIYO1LY
# /1f4oMTrhXbSaYRCS5vGc8145WcTZG908bGDCWr4GFLc411WxA+Pv2rteAcz0eHM
# H36qTQ8L0o3XOb2n+x7KJFLokXV1s6pF/WlSXsUBXGaCIIWBXyEchv+sM9eKDsUO
# LdLTITHYJQNWkiryMSEbxqdQUTVZjEz6eLRLkofDAo8pXirIYOgM770CYOiZrcKH
# K7lYOVblx22pdNawY8Te6a2dfoCaWV1QUuazg5VHiC4p/6fksgEILptOKhx9c+ia
# piNhMrHsAYx9pUtppeaFAgMBAAGjggTcMIIE2DASBgkrBgEEAYI3FQEEBQIDAgAC
# MCMGCSsGAQQBgjcVAgQWBBQSaCRCIUfL1Gu+Mc8gpMALI38/RzAdBgNVHQ4EFgQU
# llGE4Gtve/7YBqvD8oXmKa5q+dQwggEEBgNVHSUEgfwwgfkGBysGAQUCAwUGCCsG
# AQUFBwMBBggrBgEFBQcDAgYKKwYBBAGCNxQCAQYJKwYBBAGCNxUGBgorBgEEAYI3
# CgMMBgkrBgEEAYI3FQYGCCsGAQUFBwMJBggrBgEFBQgCAgYKKwYBBAGCN0ABAQYL
# KwYBBAGCNwoDBAEGCisGAQQBgjcKAwQGCSsGAQQBgjcVBQYKKwYBBAGCNxQCAgYK
# KwYBBAGCNxQCAwYIKwYBBQUHAwMGCisGAQQBgjdbAQEGCisGAQQBgjdbAgEGCisG
# AQQBgjdbAwEGCisGAQQBgjdbBQEGCisGAQQBgjdbBAEGCisGAQQBgjdbBAIwGQYJ
# KwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMBIGA1UdEwEB/wQI
# MAYBAf8CAQAwHwYDVR0jBBgwFoAUKV5RXmSuNLnrrJwNp4x1AdEJCygwggFoBgNV
# HR8EggFfMIIBWzCCAVegggFToIIBT4YxaHR0cDovL2NybC5taWNyb3NvZnQuY29t
# L3BraWluZnJhL2NybC9hbWVyb290LmNybIYjaHR0cDovL2NybDIuYW1lLmdibC9j
# cmwvYW1lcm9vdC5jcmyGI2h0dHA6Ly9jcmwzLmFtZS5nYmwvY3JsL2FtZXJvb3Qu
# Y3JshiNodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9hbWVyb290LmNybIaBqmxkYXA6
# Ly8vQ049YW1lcm9vdCxDTj1BTUVSb290LENOPUNEUCxDTj1QdWJsaWMlMjBLZXkl
# MjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPUFNRSxE
# Qz1HQkw/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdD9iYXNlP29iamVjdENsYXNz
# PWNSTERpc3RyaWJ1dGlvblBvaW50MIIBqwYIKwYBBQUHAQEEggGdMIIBmTBHBggr
# BgEFBQcwAoY7aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL2NlcnRz
# L0FNRVJvb3RfYW1lcm9vdC5jcnQwNwYIKwYBBQUHMAKGK2h0dHA6Ly9jcmwyLmFt
# ZS5nYmwvYWlhL0FNRVJvb3RfYW1lcm9vdC5jcnQwNwYIKwYBBQUHMAKGK2h0dHA6
# Ly9jcmwzLmFtZS5nYmwvYWlhL0FNRVJvb3RfYW1lcm9vdC5jcnQwNwYIKwYBBQUH
# MAKGK2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0FNRVJvb3RfYW1lcm9vdC5jcnQw
# gaIGCCsGAQUFBzAChoGVbGRhcDovLy9DTj1hbWVyb290LENOPUFJQSxDTj1QdWJs
# aWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9u
# LERDPUFNRSxEQz1HQkw/Y0FDZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENsYXNzPWNl
# cnRpZmljYXRpb25BdXRob3JpdHkwDQYJKoZIhvcNAQELBQADggIBAFAQI7dPD+jf
# XtGt3vJp2pyzA/HUu8hjKaRpM3opya5G3ocprRd7vdTHb8BDfRN+AD0YEmeDB5HK
# QoG6xHPI5TXuIi5sm/LeADbV3C2q0HQOygS/VT+m1W7a/752hMIn+L4ZuyxVeSBp
# fwf7oQ4YSZPh6+ngZvBHgfBaVz4O9/wcfw91QDZnTgK9zAh9yRKKls2bziPEnxeO
# ZMVNaxyV0v152PY2xjqIafIkUjK6vY9LtVFjJXenVUAmn3WCPWNFC1YTIIHw/mD2
# cTfPy7QA1pT+GPARAKt0bKtq9aCd/Ym0b5tPbpgCiRtzyb7fbNS1dE740re0COE6
# 7YV2wbeo2sXixzvLftH8L7s9xv9wV+G22qyKt6lmKLjFK1yMw4Ni5fMabcgmzRvS
# jAcbqgp3tk4a8emaaH0rz8MuuIP+yrxtREPXSqL/C5bzMzsikuDW9xH10graZzSm
# PjilzpRfRdu20/9UQmC7eVPZ4j1WNa1oqPHfzET3ChIzJ6Q9G3NPCB+7KwX0OQmK
# yv7IDimj8U/GlsHD1z+EF/fYMf8YXG15LamaOAohsw/ywO6SYSreVW+5Y0mzJutn
# BC9Cm9ozj1+/4kqksrlhZgR/CSxhFH3BTweH8gP2FEISRtShDZbuYymynY1un+Ry
# fiK9+iVTLdD1h/SxyxDpZMtimb4CgJQlMYIZzDCCGcgCAQEwWDBBMRMwEQYKCZIm
# iZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRUwEwYDVQQDEwxBTUUg
# Q1MgQ0EgMDECEzYAAAHfc4GXFr4y/Q0AAgAAAd8wDQYJYIZIAWUDBAIBBQCgga4w
# GQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisG
# AQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEICz1spHJIHssz2VFUST5UpvuJLQBouWF
# hVjyMlXXq/LeMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBvAGYA
# dKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEBBQAEggEA
# bUHPM36MKTq8BM5skGW71hV6sbgrz4DJktPvhRIHAeRwcMYw/wG4pvV4IODWBiE2
# tAs9a1JP0bG005jqMcYehXiTbximqcZO6Y1RVP5Vbqdu3LVQx+g1n0K5HSuTHMFw
# daXPPOQqPdBfB1FQD3XbkINxUDLbB7IZ5C9EpLtAvHg3XRQmy3IMpcwMXQ5DFOEx
# 7xnx6fKotzA4ouSEIfvYD+qwKdRbDEVMmMN62aMjhQUC9tio/ojoUVXaJPpu0a1D
# 8pdVO/l2lM0JVEt09jrqMCMB1w20YAq5yGBPlpXy6EzoYpS+9oTWVU4HcRZXCx4n
# PslpuZp/Y6U0QzpzAFyb3aGCF5QwgheQBgorBgEEAYI3AwMBMYIXgDCCF3wGCSqG
# SIb3DQEHAqCCF20wghdpAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFSBgsqhkiG9w0B
# CRABBKCCAUEEggE9MIIBOQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQCAQUA
# BCAByFmrIZPBqVA+U+A6OR0nz4OAKuOTGRdWeO3t+csIEQIGZuMY8pfMGBMyMDI0
# MTAwNDE1MDAxMy4zMThaMASAAgH0oIHRpIHOMIHLMQswCQYDVQQGEwJVUzETMBEG
# A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj
# cm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBP
# cGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046OTYwMC0wNUUwLUQ5
# NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WgghHqMIIH
# IDCCBQigAwIBAgITMwAAAe+JP1ahWMyo2gABAAAB7zANBgkqhkiG9w0BAQsFADB8
# MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk
# bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1N
# aWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAeFw0yMzEyMDYxODQ1NDhaFw0y
# NTAzMDUxODQ1NDhaMIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYD
# VQQLEx5uU2hpZWxkIFRTUyBFU046OTYwMC0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1p
# Y3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIiMA0GCSqGSIb3DQEBAQUAA4IC
# DwAwggIKAoICAQCjC1jinwzgHwhOakZqy17oE4BIBKsm5kX4DUmCBWI0lFVpEiK5
# mZ2Kh59soL4ns52phFMQYGG5kypCipungwP9Nob4VGVE6aoMo5hZ9NytXR5ZRgb9
# Z8NR6EmLKICRhD4sojPMg/RnGRTcdf7/TYvyM10jLjmLyKEegMHfvIwPmM+AP7hz
# QLfExDdqCJ2u64Gd5XlnrFOku5U9jLOKk1y70c+Twt04/RLqruv1fGP8LmYmtHvr
# B4TcBsADXSmcFjh0VgQkX4zXFwqnIG8rgY+zDqJYQNZP8O1Yo4kSckHT43XC0oM4
# 0ye2+9l/rTYiDFM3nlZe2jhtOkGCO6GqiTp50xI9ITpJXi0vEek8AejT4PKMEO2b
# PxU63p63uZbjdN5L+lgIcCNMCNI0SIopS4gaVR4Sy/IoDv1vDWpe+I28/Ky8jWTe
# ed0O3HxPJMZqX4QB3I6DnwZrHiKn6oE38tgBTCCAKvEoYOTg7r2lF0Iubt/3+VPv
# KtTCUbZPFOG8jZt9q6AFodlvQntiolYIYtqSrLyXAQIlXGhZ4gNcv4dv1YAilnbW
# A9CsnYh+OKEFr/4w4M69lI+yaoZ3L/t/UfXpT/+yc7hS/FolcmrGFJTBYlS4nE1c
# uKblwZ/UOG26SLhDONWXGZDKMJKN53oOLSSk4ldR0HlsbT4heLlWlOElJQIDAQAB
# o4IBSTCCAUUwHQYDVR0OBBYEFO1MWqKFwrCbtrw9P8A63bAVSJzLMB8GA1UdIwQY
# MBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1UdHwRYMFYwVKBSoFCGTmh0dHA6
# Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMFRpbWUt
# U3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggrBgEFBQcBAQRgMF4wXAYIKwYB
# BQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWlj
# cm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3J0MAwGA1UdEwEB
# /wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwDgYDVR0PAQH/BAQDAgeAMA0G
# CSqGSIb3DQEBCwUAA4ICAQAYGZa3aCDudbk9EVdkP8xcQGZuIAIPRx9K1CA7uRzB
# t80fC0aWkuYYhQMvHHJRHUobSM4Uw3zN7fHEN8hhaBDb9NRaGnFWdtHxmJ9eMz6J
# pn6KiIyi9U5Og7QCTZMl17n2w4eddq5vtk4rRWOVvpiDBGJARKiXWB9u2ix0WH2E
# MFGHqjIhjWUXhPgR4C6NKFNXHvWvXecJ2WXrJnvvQGXAfNJGETJZGpR41nUN3ijf
# iCSjFDxamGPsy5iYu904Hv9uuSXYd5m0Jxf2WNJSXkPGlNhrO27pPxgT111myAR6
# 1S3S2hc572zN9yoJEObE98Vy5KEM3ZX53cLefN81F1C9p/cAKkE6u9V6ryyl/qSg
# xu1UqeOZCtG/iaHSKMoxM7Mq4SMFsPT/8ieOdwClYpcw0CjZe5KBx2xLa4B1neFi
# b8J8/gSosjMdF3nHiyHx1YedZDtxSSgegeJsi0fbUgdzsVMJYvqVw52WqQNu0GRC
# 79ZuVreUVKdCJmUMBHBpTp6VFopL0Jf4Srgg+zRD9iwbc9uZrn+89odpInbznYrn
# PKHiO26qe1ekNwl/d7ro2ItP/lghz0DoD7kEGeikKJWHdto7eVJoJhkrUcanTuUH
# 08g+NYwG6S+PjBSB/NyNF6bHa/xR+ceAYhcjx0iBiv90Mn0JiGfnA2/hLj5evhTc
# AjCCB3EwggVZoAMCAQICEzMAAAAVxedrngKbSZkAAAAAABUwDQYJKoZIhvcNAQEL
# BQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH
# EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNV
# BAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEwMB4X
# DTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIyNVowfDELMAkGA1UEBhMCVVMxEzAR
# BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p
# Y3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3Rh
# bXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDk4aZM
# 57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXIyjVX9gF/bErg4r25PhdgM/9cT8dm
# 95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjoYH1qUoNEt6aORmsHFPPFdvWGUNzB
# RMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1yaa8dq6z2Nr41JmTamDu6GnszrYBb
# fowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v3byNpOORj7I5LFGc6XBpDco2LXCO
# Mcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pGve2krnopN6zL64NF50ZuyjLVwIYw
# XE8s4mKyzbnijYjklqwBSru+cakXW2dg3viSkR4dPf0gz3N9QZpGdc3EXzTdEonW
# /aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYrbqgSUei/BQOj0XOmTTd0lBw0gg/w
# EPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlMjgK8QmguEOqEUUbi0b1qGFphAXPK
# Z6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSLW6CmgyFdXzB0kZSU2LlQ+QuJYfM2
# BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AFemzFER1y7435UsSFF5PAPBXbGjfH
# CBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIurQIDAQABo4IB3TCCAdkwEgYJKwYB
# BAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIEFgQUKqdS/mTEmr6CkTxGNSnPEP8v
# BO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMFwGA1UdIARVMFMwUQYM
# KwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0
# LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAKBggrBgEF
# BQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD
# VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBW
# BgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny
# bC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUH
# AQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp
# L2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG9w0BAQsF
# AAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv6lwUtj5OR2R4sQaTlz0xM7U518Jx
# Nj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZnOlNN3Zi6th542DYunKmCVgADsAW+
# iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1bSNU5HhTdSRXud2f8449xvNo32X2
# pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4rPf5KYnDvBewVIVCs/wMnosZiefw
# C2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU6ZGyqVvfSaN0DLzskYDSPeZKPmY7
# T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDFNLB62FD+CljdQDzHVG2dY3RILLFO
# Ry3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/HltEAY5aGZFrDZ+kKNxnGSgkujhL
# mm77IVRrakURR6nxt67I6IleT53S0Ex2tVdUCbFpAUR+fKFhbHP+CrvsQWY9af3L
# wUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKiexcdFYmNcP7ntdAoGokLjzbaukz5
# m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTmdHRbatGePu1+oDEzfbzL6Xu/OHBE
# 0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZqELQdVTNYs6FwZvKhggNNMIICNQIB
# ATCB+aGB0aSBzjCByzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x
# EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
# bjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UE
# CxMeblNoaWVsZCBUU1MgRVNOOjk2MDAtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNy
# b3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQBLcI81gxbe
# a1Ex2mFbXx7ck+0g/6CBgzCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX
# YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg
# Q29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAy
# MDEwMA0GCSqGSIb3DQEBCwUAAgUA6qntkTAiGA8yMDI0MTAwNDA0MjkwNVoYDzIw
# MjQxMDA1MDQyOTA1WjB0MDoGCisGAQQBhFkKBAExLDAqMAoCBQDqqe2RAgEAMAcC
# AQACAiPuMAcCAQACAhO7MAoCBQDqqz8RAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwG
# CisGAQQBhFkKAwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQEL
# BQADggEBAMcbcp7itj3u43RnQem9Ps1+mwjlQVLBBTqUpKhu21DdxLL8Q3bJ6vAM
# RNl0SGZv7SfAXL9Sch8d3c3jbws2YJrHN7nmRTyyPoo8Q6PozHpAPNZDFDWu8Qds
# 7/rUF2BH4AHPGi3lNgoEwPyXV95XL3gLT3yyHsMvyS8H6e3QeVx8Ow2s1GrM2IWV
# P9bOCoIxEHTV9uIarLDYe0Z6fo2x8sYaq/rvLXoHtMMvc7WyKazZMeu46NL6cTYt
# lRTn7JO9qW2N2Wa/3E8uH11+X/y0vbBr1xKJnw+WtXv1kr2BZ21shcydIfbBEtq8
# xXldyRmuhUlJhAVPzIhdoCueCPrhATYxggQNMIIECQIBATCBkzB8MQswCQYDVQQG
# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG
# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg
# VGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAe+JP1ahWMyo2gABAAAB7zANBglghkgB
# ZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3
# DQEJBDEiBCCgV8Q4IUCHoytS82T+7I1xg/W1MJrxGzpTgfB4CJo86DCB+gYLKoZI
# hvcNAQkQAi8xgeowgecwgeQwgb0EIPBhKEW4Fo3wUz09NQx2a0DbcdsX8jovM5Li
# zHmnyX+jMIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0
# b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh
# dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMA
# AAHviT9WoVjMqNoAAQAAAe8wIgQg/YbH/XpWq8US1cb38ppVA95ePdl+LgAwPqEV
# Uw/wJ2gwDQYJKoZIhvcNAQELBQAEggIAEFHvfb7QLIjS0ks8Wkf/ocgbEURaZEgW
# qykhfsfDSsYJLpzmG5jNFfKStiQofFoWk0A1ki6/k0KpPf/ahYYhds5Z02tuYvVg
# qYreqAiP0C9z2AH7ximFpjSabNqlZSkeD3Cafr64Nfr8Q9wnriqwFwZl7x7JDZ18
# mZ6s/6WiU/Bk2FHETuSp0HCLVRbCjfa3zp1FxzKicL3GP26QevaQw2YHtSWfpgBi
# QE4lPayeXtxIEp5fXSJa0+MruArgmSq2elDf0LWtK3vfvX322MJ94TN5yOnuAuos
# VFjI/haOwgVieyZ/bgFIvT8iVrRSp47wIYzVdE4Ql2+v93OTaGYoFp7UDjdXIzgI
# 0UKb3rMBj+ieIa/tTY7sXoVNgg1a+tVP78HRPHNxUa9ZoNl+Te53zQWh67Kn3SU2
# gLoZZs4WyvvBGoOlU8+stXV0/OKntgMTMEuAIqng4uNGZhXIXbNG1YzrpO92yBUo
# km80vlGOa9wYnbVVeSYrIRkXJfyCghwuZz3DPy6wjxb5HtY9s88IzO362Iy3IsuT
# dNSOuJDxjcOua5ggmT7juix8C8YrWBARRKMXmdZUUxJDGLMLd64cyQ76TzLPkNql
# k4qrBw/p5KLT/GxhCvd+JXrnOrez0y0T64teqHeS8KghaTBXnOxk8CLjkYnIAMuO
# 1+kc/L/eQC8=
# SIG # End signature block
