Container/New-BCDevContainer.ps1

Function New-BCDevContainer {
    param (
        [Parameter(Mandatory = $false)] [ValidateSet('bricklead', 'primus-by-bricklead', 'primus-soft')][string]$DevOpsSignature = 'bricklead',
        [Parameter(Mandatory = $false)] [ValidateSet("Sandbox", "OnPrem")][string]$SubVersion = 'Sandbox',
        [Parameter(Mandatory = $false)] [ValidateSet("AppSource", "Master", "Release-Candidate")] [string]$SourceApp = 'Release-Candidate',
        [Parameter(Mandatory = $false)] [System.Management.Automation.PSCredential]$AdminCredential = (New-Object System.Management.Automation.PSCredential -argumentList "ADMIN", (ConvertTo-SecureString -String "P@ssword1" -AsPlainText -Force)),
        [Parameter(Mandatory = $false)] [boolean]$launchBrowser = $true,
        [switch]$Insider,
        [switch]$CopyCRONUS,
        [switch]$NoTestLibrary,
        [Switch]$NoCleanArtifact
    )

    Clear-Host
    $DevOpsSignature = $DevOpsSignature.ToLower()
    $Profil = "Consultant"
    if (Test-Path "$($env:USERPROFILE)\.vscode\extensions\ms-dynamics-smb.al-*") {
        $Profil = "Developer"
    }
    if ($NoTestLibrary) {
        $Profil = "Consultant"
    }
    #Checking container permissions
    Write-Host "Checking container permissions" -foregroun Yellow
    Check-BcContainerHelperPermissions -Fix
    # Country
    if ($insider) {
        $SourceCountries = "https://bcinsider.blob.core.windows.net/$SubVersion/indexes/countries.json".ToLowerInvariant()
    }
    else {
        $SourceCountries = "https://bcartifacts.blob.core.windows.net/$SubVersion/indexes/countries.json".ToLowerInvariant()
    }
    $TempJson = "$env:TEMP\$([Guid]::newguid().ToString()).json"
    Get-ToolFile -SourceURl $SourceCountries.ToLowerInvariant() -destination $TempJson
    $Countries = Get-Content $TempJson | ConvertFrom-Json
    Remove-Item $TempJson -Force -ErrorAction SilentlyContinue
    $Countries = $Countries | Where-Object { $_ -ne "platform" } | Where-Object { $_ -ne "base" } | Where-Object { $_ -notlike "core*" }
    if ($Countries.Length -gt 2) {
        $Countries = @("base") + $Countries
    }
    if ($Countries.length -gt 1) {
        $Default = ($Countries.IndexOf("fr"))
        if (($Profil -eq "Developer") -and ($Countries.IndexOf("base") -gt -1 )) {
            $Default = ($Countries.IndexOf("base"))
        }
        $Country = Get-ToolChoice -Caption "Please select a country version" -ChoiceList $Countries -DefaultChoice $Default
    }
    # Version
    Write-Host
    Write-Host "Getting D365BC $SubVersion $Country Artifacts..." -foregroun Yellow
    $TempJson = "$env:TEMP\$([Guid]::newguid().ToString()).json"
    $SourceVersion = "https://bcartifacts.blob.core.windows.net/$SubVersion/indexes/$Country.json".ToLowerInvariant()
    Get-ToolFile -SourceURl $SourceVersion.ToLowerInvariant() -destination $TempJson
    $BCVersions = Get-Content $TempJson | ConvertFrom-Json
    Remove-Item $TempJson -Force -ErrorAction SilentlyContinue
    # Master
    $VersionMajor = $BCVersions.Version | ForEach-Object { $_.Split('.')[0] } | Sort-Object | Get-Unique
    if ($VersionMajor.length -gt 1) {
        $VersionMajor = Get-ToolChoice -ChoiceList $VersionMajor -DefaultChoice ($VersionMajor.Length - 1)
    }
    # Minor
    $VersionMinor = ($BCVersions | Where-Object Version -like "$VersionMajor.*").Version | ForEach-Object { $_.Split('.')[1] } | Sort-Object | Get-Unique
    if ($VersionMinor.length -gt 1) {
        $VersionMinor = Get-ToolChoice -Caption "Please select a cumulative update" -ChoiceList $VersionMinor -DefaultChoice ($VersionMinor.Length - 1)
    }
    # Country
    $Countries = ($BCVersions | Where-Object Major -eq $VersionMajor | Where-Object Minor -EQ $VersionMinor).country
    if ($Countries.Length -gt 2) {
        $Countries = @("base") + $Countries
    }
    if ($Countries.length -gt 1) {
        $Default = ($Countries.IndexOf("fr"))
        if (($Profil -eq "Developer") -and ($Countries.IndexOf("base") -gt -1 )) {
            $Default = ($Countries.IndexOf("base"))
        }
        $Country = Get-ToolChoice -Caption "Please select a country version" -ChoiceList $Countries -DefaultChoice $Default
    }
    # Select Extension to Insert
    $TempJson = "$env:TEMP\$([Guid]::NewGuid().ToString()).json"
    # -------------
    $SourceURl = Get-BCDevRef -Type "availability" -DevOpsSignature $DevOpsSignature -SourceApp $SourceApp
    Get-ToolFile -SourceURl $SourceURl -destination $TempJson
    $ExtensionList = (Get-Content $TempJson | ConvertFrom-Json).extension
    $AppList = $(foreach ($Ext in $ExtensionList) { $Ext.Name }) | Sort-Object
    Remove-Item $TempJson -Force -ErrorAction SilentlyContinue
    $AddExtensions = Get-ToolFromList -Values $AppList
    # Container Name
    $ContainerName = ($SubVersion + $VersionMajor + '-' + $VersionMinor + '-' + $Country).ToLower()
    $ContainerName = $ContainerName.Replace('-0', '').Replace('-base', '')
    Write-Host
    $ContainerName = Get-ToolFromUser -Message "Container Name" -DefaultValue $ContainerName
    $ContainerName = $ContainerName.ToLower()
    # Get Artifact
    Write-Host
    Write-Host "Getting latest D365BC $SubVersion $VersionMajor.$VersionMinor $Country Artifacts..." -foregroun Yellow
    if ($Insider) {
        $ArtifactURL = Get-BCArtifactUrl -type $SubVersion -Version "$VersionMajor.$VersionMinor" -country $Country -storageAccount bcinsider -accept_insiderEula
    }
    else {
        $ArtifactURL = Get-BCArtifactUrl -type $SubVersion -Version "$VersionMajor.$VersionMinor" -country $Country
    }
    Write-Host
    Write-Host "Container version : $($ArtifactURL.split('/')[3]) $($ArtifactURL.split('/')[4]) $($ArtifactURL.split('/')[5])" -ForegroundColor Green
    # License File
    $LicenseTemp = "$env:TEMP\$([Guid]::newguid().ToString())"
    if ($ArtifactURL.Split('/')[4].Split('.')[0] -ge 19) { $LicenseSignature = 'bclicense' } else { $LicenseSignature = 'flf' };
    $LicenseCountry = $Country;
    if ($LicenseCountry -eq 'base') { $LicenseCountry = 'w1' };
    $SourceURl = Get-BCDevRef -Type "license" -DevOpsSignature $DevOpsSignature
    Try {
        $LicenseUrl = "$SourceURl/$VersionMajor/$LicenseCountry.$LicenseSignature".ToLowerInvariant()
        Get-ToolFile -SourceURL $LicenseUrl -destination $LicenseTemp
        Write-Host "License : $DevOpsSignature - $VersionMajor $LicenseCountry" -ForegroundColor Green
    }
    catch {
        Try {
            $LicenseUrl = "$SourceURl/$VersionMajor/w1.$LicenseSignature".ToLowerInvariant()
            Get-ToolFile -SourceURL $LicenseUrl -destination $LicenseTemp
            Write-Host "License : $DevOpsSignature - $VersionMajor w1" -ForegroundColor Green
        }
        catch {
            Try {
                $LicenseUrl = "$SourceURl/latest/$LicenseCountry.$LicenseSignature".ToLowerInvariant()
                Get-ToolFile -SourceURL $LicenseUrl -destination $LicenseTemp
                Write-Host "License : $DevOpsSignature - latest $LicenseCountry" -ForegroundColor Green
            }
            catch {
                $LicenseUrl = "$SourceURl/latest/w1.$LicenseSignature".ToLowerInvariant()
                Get-ToolFile -SourceURL $LicenseUrl -destination $LicenseTemp
                Write-Host "License : $DevOpsSignature - latest w1" -ForegroundColor Green
            }
        }
    }
    # Not a Developpement License
    if ($null -eq (Select-String -Path $LicenseTemp -Pattern "Solution Developer")) {
        $Profil = "Consultant"
    }
    Remove-Item -Path $LicenseTemp -ErrorAction SilentlyContinue
    # Shortcuts Folder
    $NewShortcutsFolder = "$($bcContainerHelperConfig.hostHelperFolder)\Extensions\$ContainerName\Shortcuts"
    $AppsFolder = "$($bcContainerHelperConfig.hostHelperFolder)\Extensions\$ContainerName\Apps"
    Remove-Item -Path $NewShortcutsFolder -Recurse -ErrorAction SilentlyContinue -Force | Out-Null
    # Build Container arguments
    $arguments = @{}
    $arguments.containerName = $ContainerName
    $arguments.accept_eula = $true
    $arguments.accept_insiderEula = $true
    $arguments.accept_outdated = $true
    $arguments.alwaysPull = $true
    $arguments.auth = "NavUserPassword"
    $arguments.Credential = $AdminCredential
    $arguments.artifactUrl = $ArtifactURL
    $arguments.memoryLimit = "8G"
    $arguments.licenseFile = $LicenseURL
    $arguments.shortcuts = "Desktop"
    $arguments.assignPremiumPlan = $true
    $arguments.updateHosts = $true
    $arguments.UseBestContainerOS = $true
    $arguments.enableTaskScheduler = $true
    $arguments.timeout = -1
    # $arguments.isolation = "hyperv" ### In case of fail
    if ($Profil -eq "Developer") {
        $arguments.includeTestToolkit = $true
        $arguments.includeTestLibrariesOnly = $true
        if ($VersionMajor -eq 14) {
            $arguments.includeCSide = $true
            $arguments.doNotExportObjectsToText = $true
            $arguments.enableSymbolLoading = $true
        }
    }

    Start-Sleep -Seconds 3
    
    # Create Container
    Write-Host 
    Write-Host 
    Write-Host "Creating Container $ContainerName - $($ArtifactURL.split('/')[3]) $($ArtifactURL.split('/')[4]) $($ArtifactURL.split('/')[5])" -ForegroundColor Yellow
    New-BcContainer @arguments
    # New Shortcut Folder
    New-Item -Path $NewShortcutsFolder -ItemType Directory -ErrorAction SilentlyContinue -Force | Out-Null
    # Save Log
    Write-Host
    Write-Host "Saving Container log" -ForegroundColor Yellow
    docker logs $ContainerName | Out-File "$NewShortcutsFolder\$ContainerName Container Log.txt" -Force
    # Move shortcuts
    Write-Host
    Write-Host "Moving shortcuts" -ForegroundColor Yellow
    Move-Item -Path "$([Environment]::GetFolderPath("Desktop"))\$ContainerName *" `
        -Destination "$NewShortcutsFolder\" `
        -Force
    # Adding fonts
    <#
    if (Test-Path "C:\Windows\Fonts\arial*.ttf") {
        Write-Host
        Write-Host "Adding Arial family fonts" -ForegroundColor Yellow
        Add-FontsToBcContainer -containerName $ContainerName -path @("C:\Windows\Fonts\arial*.ttf")
    }
    if (Test-Path "C:\Windows\Fonts\IDAutomation*.ttf") {
        Write-Host "Adding IDAutomation Codabar fonts" -ForegroundColor Yellow
        Add-FontsToBcContainer -containerName $ContainerName -path @("C:\Windows\Fonts\IDAutomation*.ttf")
    }
    #>

    # Insert Test Users
    if ($Profil -eq "Developer") {
        Write-Host
        Write-Host "Adding Test Users" -ForegroundColor Yellow
        Setup-BcContainerTestUsers  -containerName $ContainerName -credential $AdminCredential -Password (ConvertTo-SecureString -String "P@ssword1" -AsPlainText -Force)
    }
    # Insert Extensions
    if (($AddExtensions.Length) -gt 0) {
        Write-Host
        Write-Host "Searching $SourceApp Extensions" -ForegroundColor Yellow
        New-ToolDirectory -Path $AppsFolder
        $bcContainerHelperConfig.TrustedNuGetFeeds = @(
            [PSCustomObject]@{ "url" = "$(Get-BCDevRef -Type "nuget" -DevOpsSignature $DevOpsSignature -SourceApp $SourceApp)";
                               "token" = "$(Get-BCDevRef -Type "nugetToken" -DevOpsSignature $DevOpsSignature -SourceApp $SourceApp)";
                               "patterns" = @("*")
            }
        )
        foreach ($Extension in $AddExtensions) {
            $PackageId = ($ExtensionList | Where-Object { $_.name -eq $Extension } ).AppID
            Download-BcNuGetPackageToFolder -packageName $PackageId -downloadDependencies allButMicrosoft -folder $AppsFolder
        }
        $AppFiles = @()
        foreach ($Files in (Get-Item "$AppsFolder\*.app")) {
            $AppFiles += $Files.FullName
        }
        Write-Host "Sorting $($AppFiles.Length) extensions..." -ForegroundColor Yellow
        $AppFiles = Sort-AppFilesByDependencies -appFiles $AppFiles
        $AppFiles | ForEach-Object { Write-Host $_.split('\')[-1] }
        Write-Host
        Write-Host "Publishing extensions..." -ForegroundColor Yellow
        foreach ($Files in $AppFiles) {
            try {
                Publish-BcContainerApp -containerName $ContainerName -appfile $Files -useDevEndpoint -syncMode ForceSync -install -credential $AdminCredential
            }
            catch {
                Write-Host "$Files not installed." -ForegroundColor Red
            }
        }
    }
    # Create a Cronus Copy
    if ($CopyCRONUS) {
        Write-Host
        Write-Host "Copying CRONUS to zCompany" -ForegroundColor Yellow
        $CompanyInDocker = (Get-CompanyInNavContainer -containerName $ContainerName | Where-Object { $_.CompanyName -like "*CRONUS*" } | Select-Object -First 1).CompanyName
        try {
            Copy-CompanyInBcContainer -containerName $ContainerName `
                -sourceCompanyName $CompanyInDocker `
                -destinationCompanyName "z$CompanyInDocker"
        }
        catch {
            Write-Host "zCompany creation failed." -ForegroundColor Red
        }
    }
    # Launch Browser
    if ($launchBrowser) {
        $URL = Get-Content "$NewShortcutsFolder\$ContainerName Container Log.txt"
        $URL = $URL | Where-Object { $_ -like "Web Client*" }
        $URL = $URL.split(":")[2]
        Write-Host
        Write-Host "Launching Browser http:$URL" -ForegroundColor Yellow
        Start-Process "http:$URL"
    }
    if (!($NoCleanArtifact)) {
        Write-Host
        Write-Host "Cleaning BC Artifacts" -ForegroundColor Yellow
        Docker image prune -f
        Flush-ContainerHelperCache -cache bcartifacts -keepDays 2
    }
}
Export-ModuleMember -Function New-BCDevContainer
# SIG # Begin signature block
# MIIn2wYJKoZIhvcNAQcCoIInzDCCJ8gCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCB53dL/nrHN6oNn
# UBpVZ00UsXSLiTfj27+Wu1zoJPAkcqCCIOwwggWNMIIEdaADAgECAhAOmxiO+dAt
# 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV
# BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa
# Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy
# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD
# ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E
# MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy
# unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF
# xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1
# 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB
# MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR
# WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6
# nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB
# YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S
# UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x
# q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB
# NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP
# TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC
# AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
# Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv
# bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0
# aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB
# LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc
# Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov
# Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy
# oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW
# juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF
# mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z
# twGpn1eqXijiuZQwgga0MIIEnKADAgECAhANx6xXBf8hmS5AQyIMOkmGMA0GCSqG
# SIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx
# GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRy
# dXN0ZWQgUm9vdCBHNDAeFw0yNTA1MDcwMDAwMDBaFw0zODAxMTQyMzU5NTlaMGkx
# CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4
# RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBTSEEyNTYg
# MjAyNSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC0eDHTCphB
# cr48RsAcrHXbo0ZodLRRF51NrY0NlLWZloMsVO1DahGPNRcybEKq+RuwOnPhof6p
# vF4uGjwjqNjfEvUi6wuim5bap+0lgloM2zX4kftn5B1IpYzTqpyFQ/4Bt0mAxAHe
# HYNnQxqXmRinvuNgxVBdJkf77S2uPoCj7GH8BLuxBG5AvftBdsOECS1UkxBvMgEd
# gkFiDNYiOTx4OtiFcMSkqTtF2hfQz3zQSku2Ws3IfDReb6e3mmdglTcaarps0wjU
# jsZvkgFkriK9tUKJm/s80FiocSk1VYLZlDwFt+cVFBURJg6zMUjZa/zbCclF83bR
# VFLeGkuAhHiGPMvSGmhgaTzVyhYn4p0+8y9oHRaQT/aofEnS5xLrfxnGpTXiUOeS
# LsJygoLPp66bkDX1ZlAeSpQl92QOMeRxykvq6gbylsXQskBBBnGy3tW/AMOMCZIV
# NSaz7BX8VtYGqLt9MmeOreGPRdtBx3yGOP+rx3rKWDEJlIqLXvJWnY0v5ydPpOjL
# 6s36czwzsucuoKs7Yk/ehb//Wx+5kMqIMRvUBDx6z1ev+7psNOdgJMoiwOrUG2Zd
# SoQbU2rMkpLiQ6bGRinZbI4OLu9BMIFm1UUl9VnePs6BaaeEWvjJSjNm2qA+sdFU
# eEY0qVjPKOWug/G6X5uAiynM7Bu2ayBjUwIDAQABo4IBXTCCAVkwEgYDVR0TAQH/
# BAgwBgEB/wIBADAdBgNVHQ4EFgQU729TSunkBnx6yuKQVvYv1Ensy04wHwYDVR0j
# BBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1Ud
# JQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0
# cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0
# cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8E
# PDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVz
# dGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEw
# DQYJKoZIhvcNAQELBQADggIBABfO+xaAHP4HPRF2cTC9vgvItTSmf83Qh8WIGjB/
# T8ObXAZz8OjuhUxjaaFdleMM0lBryPTQM2qEJPe36zwbSI/mS83afsl3YTj+IQhQ
# E7jU/kXjjytJgnn0hvrV6hqWGd3rLAUt6vJy9lMDPjTLxLgXf9r5nWMQwr8Myb9r
# EVKChHyfpzee5kH0F8HABBgr0UdqirZ7bowe9Vj2AIMD8liyrukZ2iA/wdG2th9y
# 1IsA0QF8dTXqvcnTmpfeQh35k5zOCPmSNq1UH410ANVko43+Cdmu4y81hjajV/gx
# dEkMx1NKU4uHQcKfZxAvBAKqMVuqte69M9J6A47OvgRaPs+2ykgcGV00TYr2Lr3t
# y9qIijanrUR3anzEwlvzZiiyfTPjLbnFRsjsYg39OlV8cipDoq7+qNNjqFzeGxcy
# tL5TTLL4ZaoBdqbhOhZ3ZRDUphPvSRmMThi0vw9vODRzW6AxnJll38F0cuJG7uEB
# YTptMSbhdhGQDpOXgpIUsWTjd6xpR6oaQf/DJbg3s6KCLPAlZ66RzIg9sC+NJpud
# /v4+7RWsWCiKi9EOLLHfMR2ZyJ/+xhCx9yHbxtl5TPau1j/1MIDpMPx0LckTetiS
# uEtQvLsNz3Qbp7wGWqbIiOWCnb5WqxL3/BAPvIXKUjPSxyZsq8WhbaM2tszWkPZP
# ubdcMIIGvzCCBKegAwIBAgIRAIFOQhehKX/tWszUF/iRrXUwDQYJKoZIhvcNAQEL
# BQAwUzELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExKTAn
# BgNVBAMTIEdsb2JhbFNpZ24gQ29kZSBTaWduaW5nIFJvb3QgUjQ1MB4XDTI0MDYx
# OTAzMjUxMVoXDTM4MDcyODAwMDAwMFowWTELMAkGA1UEBhMCQkUxGTAXBgNVBAoT
# EEdsb2JhbFNpZ24gbnYtc2ExLzAtBgNVBAMTJkdsb2JhbFNpZ24gR0NDIFI0NSBD
# b2RlU2lnbmluZyBDQSAyMDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
# AgEA1kJN+eNPxiP0bB2BpjD3SD3P0OWN5SAilgdENV0Gzw8dcGDmJlT6UyNgAqhf
# AgL3jsluPal4Bb2O9U8ZJJl8zxEWmx97a9Kje2hld6vYsSw/03IGMlxbrFBnLCVN
# VgY2/MFiTH19hhaVml1UulDQsH+iRBnp1m5sPhPCnxHUXzRbUWgxYwr4W9Deullf
# Ma+JaDhAPgjoU2dOY7Yhju/djYVBVZ4cvDfclaDEcacfG6VJbgogWX6Jo1gVlwAl
# ad/ewmpQZU5T+2uhnxgeig5fVF694FvP8gwE0t4IoRAm97Lzei7CjpbBP86l2vRZ
# KIw3ZaExlguOpHZ3FUmEZoIl50MKd1KxmVFC/6Gy3ZzS3BjZwYapQB1Bl2KGvKj/
# osdjFwb9Zno2lAEgiXgfkPR7qVJOak9UBiqAr57HUEL6ZQrjAfSxbqwOqOOBGag4
# yJ4DKIakdKdHlX5yWip7FWocxGnmsL5AGZnL0n1VTiKcEOChW8OzLnqLxN7xSx+M
# KHkwRX9sE7Y9LP8tSooq7CgPLcrUnJiKSm1aNiwv37rL4kFKCHcYiK01YZQS86Ry
# 6+42nqdRJ5E896IazPyH5ZfhUYdp6SLMg8C3D0VsB+FDT9SMSs7PY7G1pBB6+Q0M
# KLBrNP4haCdv7Pj6JoRbdULNiSZ5WZ1rq2NxYpAlDQgg8f8CAwEAAaOCAYYwggGC
# MA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDAzASBgNVHRMBAf8E
# CDAGAQH/AgEAMB0GA1UdDgQWBBTas43AJJCja3fTDKBZ3SFnZHYLeDAfBgNVHSME
# GDAWgBQfAL9GgAr8eDm3pbRD2VZQu86WOzCBkwYIKwYBBQUHAQEEgYYwgYMwOQYI
# KwYBBQUHMAGGLWh0dHA6Ly9vY3NwLmdsb2JhbHNpZ24uY29tL2NvZGVzaWduaW5n
# cm9vdHI0NTBGBggrBgEFBQcwAoY6aHR0cDovL3NlY3VyZS5nbG9iYWxzaWduLmNv
# bS9jYWNlcnQvY29kZXNpZ25pbmdyb290cjQ1LmNydDBBBgNVHR8EOjA4MDagNKAy
# hjBodHRwOi8vY3JsLmdsb2JhbHNpZ24uY29tL2NvZGVzaWduaW5ncm9vdHI0NS5j
# cmwwLgYDVR0gBCcwJTAIBgZngQwBBAEwCwYJKwYBBAGgMgEyMAwGCisGAQQBoDIK
# BAIwDQYJKoZIhvcNAQELBQADggIBADIQ5LwXpYMQQJ3Tqf0nz0VyqcUfSzNZbywy
# MXlxhNY2Z9WrdPzU8gY6brXWy/FCg5a9fd6VLBrtauNBHKbIiTHCWWyJvCojA1lQ
# R0n9b1MOKijMSFTv8yMYW5I2TryjY9TD+wAPgNEgwsrllrrwmluqpCV6Gdv623tT
# T/m2o9lj1XVfAaUo27YYKRRleZzbtOuImBRTUGAxDGazUeNuySkmZPAU0XN4xISN
# PhSlklmreUFG6jTPgXZGOpF4GXO+/gb118GEOaBwTAo1AF7YKjAkHzJ3tuF837NG
# QeH6bY3j4wufL0DZpToNZMm+jNEayWUgOuIA+k56ITdBcJmdUB+Ze3WQdHNNRaVO
# WH/ddmqQWIlmk2Sj/lT3Tarr5SDuddeIsh0MPLyhkqBW5Ef8Zw/qeCnfj6PH2eMx
# eKcLKZRrHCddISeH4qPvyECQLlwXKCXTAUQXq4DafJSoWyP8IJ6bkaGQ/7MN5XJE
# LEcV89SRcib58gXjAWf3abXeBbb+KJCMf6EpO7cs2mQiaZbE9NNXDSqFxrtoaKyL
# 8VJLZG6quLfsTRQc+qgUOM7sJevkYt01+bh7B10bQ2cCCGs9vyUjg4GWcwfu/lha
# PDfaoNtf0pw6RpKcxCYcCTDaJeQOHZBz1B6HTmmEgZHNZX7nNfqDgGrTNB1Gp3gI
# pngyJWZ6MIIG6zCCBNOgAwIBAgIMfDeOzfSMBpXQEWmrMA0GCSqGSIb3DQEBCwUA
# MFkxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS8wLQYD
# VQQDEyZHbG9iYWxTaWduIEdDQyBSNDUgQ29kZVNpZ25pbmcgQ0EgMjAyMDAeFw0y
# NDA5MTkxMjE3MjJaFw0yNTEwMjcwODE1NTlaMFkxCzAJBgNVBAYTAkZSMREwDwYD
# VQQIEwhNb3JiaWhhbjEPMA0GA1UEBxMGVmFubmVzMRIwEAYDVQQKEwlCUklDS0xF
# QUQxEjAQBgNVBAMTCUJSSUNLTEVBRDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
# AgoCggIBANysgL1dmPiIH07tM4uKTz5r2+xZ0EHWijxeWhGiJAb0DvOSfJX08pqk
# b3Q8MMcmSgTIggnzr68GzO8oU9JqM8+uHFJUVsAWMptAa8FxaUI0q9/8MdVKOoTk
# RmyDGBMKbgDdYf+YVbLeYmsE267LQeOF1koiSmK7WRkytnjwbOZMFr/qObysIL6D
# nMiM802AC4dFP1Z6hDKJuAu1mOmSZpqgBQZ4atM2TiOBw2qApZHbbur+bM2fEah2
# j46TIjTiQZ/YD7Sznuv2feHDB9h3on8MMWff8POZURkZRFbJRn8EUk/S4+3xRLE2
# ylNuYIg6gFW1QJaaUEU90ay1hLdfFJLF5WMnRyFaTaJwX3cYjP8khR/vbA966bQ4
# l0lHMbf2tLUpeMShi0vr5f1vOqSZ10qR3hzYyYMLSmj/dIHFR3ngprG5QTcjfIwF
# Sdro8Aij0HYmN1tQ6HC8rV4yUJ8pDzKayQy5JDIKVYfq9jwaD45KGLUUtrot1lCP
# I9Zm0Hf6lMjGBLpM16MKK8U9E8ZXz5gseqUaMJg4g34vl+gbEObOPdGtbEVicEqi
# p1mSHseRHrDIOzTNA8IzI9F10csChBOlVfGZZYLZTN2DJQyhYdm6gEFzrNmBE48r
# H+Fzdcf4J1VvRgDrxSAdtpVLqbe5iR996zpfb/50JtGrc3e59YmxAgMBAAGjggGx
# MIIBrTAOBgNVHQ8BAf8EBAMCB4AwgZsGCCsGAQUFBwEBBIGOMIGLMEoGCCsGAQUF
# BzAChj5odHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2NhY2VydC9nc2djY3I0
# NWNvZGVzaWduY2EyMDIwLmNydDA9BggrBgEFBQcwAYYxaHR0cDovL29jc3AuZ2xv
# YmFsc2lnbi5jb20vZ3NnY2NyNDVjb2Rlc2lnbmNhMjAyMDBWBgNVHSAETzBNMEEG
# CSsGAQQBoDIBMjA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5nbG9iYWxzaWdu
# LmNvbS9yZXBvc2l0b3J5LzAIBgZngQwBBAEwCQYDVR0TBAIwADBFBgNVHR8EPjA8
# MDqgOKA2hjRodHRwOi8vY3JsLmdsb2JhbHNpZ24uY29tL2dzZ2NjcjQ1Y29kZXNp
# Z25jYTIwMjAuY3JsMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB8GA1UdIwQYMBaAFNqz
# jcAkkKNrd9MMoFndIWdkdgt4MB0GA1UdDgQWBBT6laBcJjcU8FGox8y/wQdZCLUf
# 2zANBgkqhkiG9w0BAQsFAAOCAgEAaJ+rcBMAnoJ+aDWDFOBe363c6HTqXcC5Rf4R
# IJt/mbzGNBYDf6S2y+oA1q4mHJ/8TByYTKIvHKCQHFTvN1tl2zsulY7FtaeXC6PI
# CPxXI5YujeYTAO6b9GMjCbxQ/IdJex6KJXuwHViTXP86G6ZwKAfczYXAmqRoC5cm
# lt+XQy9bZNC5+GpKc6qvbVON1h7lWl1Y5Mm9rTvEzWNC06CRwZbhPeeFMRXs2/z9
# VtunN+S9k+uXLR/vaC2ptuZkZjacAK9GjX9Pbw+TJ1dxR8/0wq5eIXQfgEe/Q8ZR
# 3LWUudZBsRWRIswUBsNjyfTI02B0vuG4tv8kuS+i45mtOPGZ5KZRquIGLjrhsOop
# mbAFNOh+iBLCq1ouWoNqkqOMZq81PN3fYb4rTdKX9OogYQn0AQ4UXFsAChqEC4B1
# XhXy/TW7fRWWxZRA8HXbyvid8n/9XX7p56PFipX/HJDG85PVLg+h8CJmsjrNw6qq
# 0M3949guYO79tylNhDEdI6eC5roGS4qReRsjvwYd+xUNM98oSCA8rXjMkLEZufRm
# JVfJt+OiqEst933qbVeUyfN/tqbd1vpxwm1Owm5Dl0ap0GuAo01DEzlm8602Rw+Y
# 7h53dsMMnQRrK4YLB6L1My2rUikqdtvzx7uUogzLDLAVR5hkpjF5DA6AeXNfpTJF
# tbyN51kwggbtMIIE1aADAgECAhAKgO8YS43xBYLRxHanlXRoMA0GCSqGSIb3DQEB
# CwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8G
# A1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBT
# SEEyNTYgMjAyNSBDQTEwHhcNMjUwNjA0MDAwMDAwWhcNMzYwOTAzMjM1OTU5WjBj
# MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMT
# MkRpZ2lDZXJ0IFNIQTI1NiBSU0E0MDk2IFRpbWVzdGFtcCBSZXNwb25kZXIgMjAy
# NSAxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0EasLRLGntDqrmBW
# sytXum9R/4ZwCgHfyjfMGUIwYzKomd8U1nH7C8Dr0cVMF3BsfAFI54um8+dnxk36
# +jx0Tb+k+87H9WPxNyFPJIDZHhAqlUPt281mHrBbZHqRK71Em3/hCGC5KyyneqiZ
# 7syvFXJ9A72wzHpkBaMUNg7MOLxI6E9RaUueHTQKWXymOtRwJXcrcTTPPT2V1D/+
# cFllESviH8YjoPFvZSjKs3SKO1QNUdFd2adw44wDcKgH+JRJE5Qg0NP3yiSyi5Mx
# gU6cehGHr7zou1znOM8odbkqoK+lJ25LCHBSai25CFyD23DZgPfDrJJJK77epTwM
# P6eKA0kWa3osAe8fcpK40uhktzUd/Yk0xUvhDU6lvJukx7jphx40DQt82yepyekl
# 4i0r8OEps/FNO4ahfvAk12hE5FVs9HVVWcO5J4dVmVzix4A77p3awLbr89A90/nW
# GjXMGn7FQhmSlIUDy9Z2hSgctaepZTd0ILIUbWuhKuAeNIeWrzHKYueMJtItnj2Q
# +aTyLLKLM0MheP/9w6CtjuuVHJOVoIJ/DtpJRE7Ce7vMRHoRon4CWIvuiNN1Lk9Y
# +xZ66lazs2kKFSTnnkrT3pXWETTJkhd76CIDBbTRofOsNyEhzZtCGmnQigpFHti5
# 8CSmvEyJcAlDVcKacJ+A9/z7eacCAwEAAaOCAZUwggGRMAwGA1UdEwEB/wQCMAAw
# HQYDVR0OBBYEFOQ7/PIx7f391/ORcWMZUEPPYYzoMB8GA1UdIwQYMBaAFO9vU0rp
# 5AZ8esrikFb2L9RJ7MtOMA4GA1UdDwEB/wQEAwIHgDAWBgNVHSUBAf8EDDAKBggr
# BgEFBQcDCDCBlQYIKwYBBQUHAQEEgYgwgYUwJAYIKwYBBQUHMAGGGGh0dHA6Ly9v
# Y3NwLmRpZ2ljZXJ0LmNvbTBdBggrBgEFBQcwAoZRaHR0cDovL2NhY2VydHMuZGln
# aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0VGltZVN0YW1waW5nUlNBNDA5NlNI
# QTI1NjIwMjVDQTEuY3J0MF8GA1UdHwRYMFYwVKBSoFCGTmh0dHA6Ly9jcmwzLmRp
# Z2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFRpbWVTdGFtcGluZ1JTQTQwOTZT
# SEEyNTYyMDI1Q0ExLmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1s
# BwEwDQYJKoZIhvcNAQELBQADggIBAGUqrfEcJwS5rmBB7NEIRJ5jQHIh+OT2Ik/b
# NYulCrVvhREafBYF0RkP2AGr181o2YWPoSHz9iZEN/FPsLSTwVQWo2H62yGBvg7o
# uCODwrx6ULj6hYKqdT8wv2UV+Kbz/3ImZlJ7YXwBD9R0oU62PtgxOao872bOySCI
# LdBghQ/ZLcdC8cbUUO75ZSpbh1oipOhcUT8lD8QAGB9lctZTTOJM3pHfKBAEcxQF
# oHlt2s9sXoxFizTeHihsQyfFg5fxUFEp7W42fNBVN4ueLaceRf9Cq9ec1v5iQMWT
# FQa0xNqItH3CPFTG7aEQJmmrJTV3Qhtfparz+BW60OiMEgV5GWoBy4RVPRwqxv7M
# k0Sy4QHs7v9y69NBqycz0BZwhB9WOfOu/CIJnzkQTwtSSpGGhLdjnQ4eBpjtP+XB
# 3pQCtv4E5UCSDag6+iX8MmB10nfldPF9SVD7weCC3yXZi/uuhqdwkgVxuiMFzGVF
# wYbQsiGnoa9F5AaAyBjFBtXVLcKtapnMG3VH3EmAp/jsJ3FVF3+d1SVDTmjFjLbN
# FZUWMXuZyvgLfgyPehwJVxwC+UpX2MSey2ueIu9THFVkT+um1vshETaWyQo8gmBt
# o/m3acaP9QsuLj3FNwFlTxq25+T4QwX9xa6ILs84ZPvmpovq90K8eWyG2N01c4Ih
# SOxqt81nMYIGRTCCBkECAQEwaTBZMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xv
# YmFsU2lnbiBudi1zYTEvMC0GA1UEAxMmR2xvYmFsU2lnbiBHQ0MgUjQ1IENvZGVT
# aWduaW5nIENBIDIwMjACDHw3js30jAaV0BFpqzANBglghkgBZQMEAgEFAKCBhDAY
# BgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3
# AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEi
# BCCNX9MmSARFv6aEQYTHi1GxjpiFF/NKECUHeOl9l8N/IDANBgkqhkiG9w0BAQEF
# AASCAgAAmY/OHQNqLy10+Zie0zCbDTzgAzQz0VGKotom7QFDEMsUGL3FkOhy7DHI
# 84KMxzyklNE7ypnQ7OdEev7/tBLXzx3sq3IBfyTdHyjDd/mtVPWNI3hf9n9lTR3l
# veB8Os9rOxl/i7nh6HgqP/b9+oToslmYVxim9UILN5c0JOPpp05VPvb5MWjsycd5
# AqKHDNGOh2kiOtQKwsMaiavfAVx4kzVv+YLtHD+o5pJLsB6TMFwvvIjl3hZ3Zp+L
# yz2l9uLIa7t6lahCI9h36jHqvPMsqcBuEpROHlF1YwBDmDmsetwPZhbZ97uLX1V/
# UWzblS5PUMVvbgH6rZJMlOEn/bfvBiMKvr8+WwZ25FCjbLG0sHPxrt5iNLsB7xs2
# j6/DGV/bhqcFj86R2V6lGnER33gOKCEkzuAx7k0PH3t+0br4TWAnea5cLVPYkA9p
# cpLyS3uck48ITv5kkG9gC65lq0J66g88kD5zA4Ty7QTxI5Wkn6/nSl3H0i1dNs9k
# RDiFzrKJ8sXbVE9lMwOw5YHDdmUVZORL/fyD0nnfD9ATJnRBZaZ1gR5aSoakS1L2
# JluDtXZeI9NyeORxNA10iE8y6xZjcBQ5d+OXf5JVjKFEnvS3hElOmu7DFR/d4xbH
# TRiUlobSK411Ku9YBi7JmsnZHG9cgePFLavXPvhzSc3e6baiHKGCAyYwggMiBgkq
# hkiG9w0BCQYxggMTMIIDDwIBATB9MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5E
# aWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1l
# U3RhbXBpbmcgUlNBNDA5NiBTSEEyNTYgMjAyNSBDQTECEAqA7xhLjfEFgtHEdqeV
# dGgwDQYJYIZIAWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwG
# CSqGSIb3DQEJBTEPFw0yNTA2MTYwNzA2MTNaMC8GCSqGSIb3DQEJBDEiBCAoCWqI
# gVpwgz0P6B3bIM0GaUw+LttBHwwwPddJfhujkDANBgkqhkiG9w0BAQEFAASCAgBd
# HENv7545z5rReCGSEivCrL5nTns+IJdIZXPeOuwfvPUbN7amHQmrhq5xhyLT2mQh
# 8FR+TaebLx6bWz6UwgKnST6VCXeapdrWSvrGY/bAFW7xKb6w0c0buEkZ+M3I2UQb
# EOKNWsl6nzwdYxq/+7bFouBf321Dhvbe1yhX6ZgqzqcL20fYzzIrSyB4URc2qC+4
# JAvrzZrUOeH3HMN1ymESLttUu4xtuMdQwMpHd/fRnV597PQwMaU+k5s8HDy4uwCz
# LUCAuerVZmQnaWtc2gRmYyELgK+v4pfRcF4aMglEK9Z+/T2LEILaHKG4WiOZXJs3
# Igd0WvRZQHnVGuTNHWaa6X6aluq3U6dxz9B4zdfMLpAwexA/Yv4meD+IkESl8Mk3
# 4RT7m0/jk9bkjyH9nQaA+oH1CeXdsTBgDsnlc97+y4JqaNZPF4gxOKlF2qToI2XJ
# q1TgEB+WBsSMri9h7IrbRnhd1u6MSkbHskiJwmmKR0v3bey1An29Aa15YnieWloO
# lPzUVakMcyT72tQYkMes53+Tof+d7npD2iQudtOicUrSG0hURYkAyldhlmbn4nSI
# T1SMxzUPUhj6lZJWMdDOmFeis7aYP9IBxd6abrhn9FzMpXHC+kEfXOcJDtqg2U3H
# pJqFyWb0oTfCHKLS6a8Ckf7dtadYG389uIwQVu9P5Q==
# SIG # End signature block