From deec1231047c7b84965a60ee0c71da917f172849 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sat, 11 Sep 2021 22:42:53 -0500 Subject: [PATCH 01/22] base scaffold --- .github/CHANGELOG.md | 16 + .github/CODE_OF_CONDUCT.md | 75 +++ .github/CONTRIBUTING.md | 23 + .github/ISSUE_TEMPLATE/bug-report.md | 39 ++ .github/ISSUE_TEMPLATE/feature_request.md | 20 + .github/PULL_REQUEST_TEMPLATE.md | 13 + .gitignore | 362 +----------- .vscode/extensions.json | 9 + .vscode/settings.json | 9 + .vscode/tasks.json | 135 +++++ actions_bootstrap.ps1 | 56 ++ azure-pipelines.yml | 120 ++++ docs/Get-HelloWorld.md | 48 ++ docs/pwshPlaces.md | 17 + src/PSScriptAnalyzerSettings.psd1 | 60 ++ .../Infrastructure/SampleInfraTest.Tests.ps1 | 18 + src/Tests/Unit/ExportedFunctions.Tests.ps1 | 66 +++ src/Tests/Unit/Private/Get-Day.Tests.ps1 | 63 ++ .../Unit/Public/Get-HelloWorld.Tests.ps1 | 41 ++ src/Tests/Unit/pwshPlaces-Module.Tests.ps1 | 49 ++ src/pwshPlaces.Settings.ps1 | 2 + src/pwshPlaces.build.ps1 | 548 ++++++++++++++++++ src/pwshPlaces/Imports.ps1 | 6 + src/pwshPlaces/Private/Get-Day.ps1 | 38 ++ src/pwshPlaces/Public/Get-HelloWorld.ps1 | 33 ++ src/pwshPlaces/pwshPlaces.psd1 | 135 +++++ src/pwshPlaces/pwshPlaces.psm1 | 34 ++ 27 files changed, 1685 insertions(+), 350 deletions(-) create mode 100644 .github/CHANGELOG.md create mode 100644 .github/CODE_OF_CONDUCT.md create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/ISSUE_TEMPLATE/bug-report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json create mode 100644 actions_bootstrap.ps1 create mode 100644 azure-pipelines.yml create mode 100644 docs/Get-HelloWorld.md create mode 100644 docs/pwshPlaces.md create mode 100644 src/PSScriptAnalyzerSettings.psd1 create mode 100644 src/Tests/Infrastructure/SampleInfraTest.Tests.ps1 create mode 100644 src/Tests/Unit/ExportedFunctions.Tests.ps1 create mode 100644 src/Tests/Unit/Private/Get-Day.Tests.ps1 create mode 100644 src/Tests/Unit/Public/Get-HelloWorld.Tests.ps1 create mode 100644 src/Tests/Unit/pwshPlaces-Module.Tests.ps1 create mode 100644 src/pwshPlaces.Settings.ps1 create mode 100644 src/pwshPlaces.build.ps1 create mode 100644 src/pwshPlaces/Imports.ps1 create mode 100644 src/pwshPlaces/Private/Get-Day.ps1 create mode 100644 src/pwshPlaces/Public/Get-HelloWorld.ps1 create mode 100644 src/pwshPlaces/pwshPlaces.psd1 create mode 100644 src/pwshPlaces/pwshPlaces.psm1 diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md new file mode 100644 index 0000000..93bbb4f --- /dev/null +++ b/.github/CHANGELOG.md @@ -0,0 +1,16 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +- TBD + +## [0.0.1] + +### Added + +- Initial release. diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..86af45e --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,75 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at **[EMAIL REQUIRED]**. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html) + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see [https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq) \ No newline at end of file diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..7b6e40c --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,23 @@ +# Contributing + +Thanks for your interest in contributing to the **pwshPlaces Project**. + +Whether it's a bug report, new feature, correction, or additional documentation, your feedback and contributions are appreciated. + +Please read through this document before submitting any issues or pull requests to ensure all the necessary information is provided to effectively respond to your bug report or contribution. + +Please note there is a code of conduct, please follow it in all your interactions with the project. + +## Reporting Bugs/Feature Requests + +## Contributing via Pull Requests + +## Finding contributions to work on + +## Code of Conduct + +This project has a [Code of Conduct](CODE_OF_CONDUCT.md). + +## Licensing + +See the [LICENSE](LICENSE.txt) file for our project's licensing. diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 0000000..40812c7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,39 @@ +--- +name: Bug report +about: Submit a new bug +title: Bug report +labels: 'bug' +assignees: '' + +--- + + + +### Expected Behavior + + +### Current Behavior + + +### Possible Solution + + +### Steps to Reproduce + + + +1. +2. +3. +4. + +### Context (Environment) + + +* Operating System and version as reported by `$PSVersionTable.OS`: +* PowerShell versions as reported by `$PSVersionTable.PSEdition`: + + + +### Detailed Description + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..a3a401e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: 'Feature request' +labels: 'enhancement' +assignees: '' + +--- + +### Description + + +### Describe the solution you'd like + + +### Describe any alternatives you've considered + + +### Additional context + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..4b6ea22 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,13 @@ +# Pull Request + +## Issue + +Issue #, if available: + +## Description + +Description of changes: + +## License + +By submitting this pull request, I confirm that my contribution is made under the terms of the projects associated license. diff --git a/.gitignore b/.gitignore index dfcfd56..f72a608 100644 --- a/.gitignore +++ b/.gitignore @@ -1,350 +1,12 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore - -# User-specific files -*.rsuser -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Mono auto generated files -mono_crash.* - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ -[Ll]ogs/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUnit -*.VisualState.xml -TestResult.xml -nunit-*.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*_wpftmp.csproj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# NuGet Symbol Packages -*.snupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx -*.appxbundle -*.appxupload - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ - -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ +Archive +Artifacts +cov.xml +# OS generated files # +###################### +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..52609dd --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "ms-vscode.PowerShell", + "ryanluker.vscode-coverage-gutters", + "DavidAnson.vscode-markdownlint" + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..745db6d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + // When enabled, will trim trailing whitespace when you save a file. + "files.trimTrailingWhitespace": true, + // specifies the location of the explicity ScriptAnalyzer settings file + "powershell.scriptAnalysis.settingsPath": "PSScriptAnalyzerSettings.psd1", + // specifies the PowerShell coding style used in this project (https://github.com/PoshCode/PowerShellPracticeAndStyle/issues/81) + "powershell.codeFormatting.preset":"Stroustrup" +} + diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..9302d28 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,135 @@ +// Available variables which can be used inside of strings. +// ${workspaceRoot}: the root folder of the team +// ${file}: the current opened file +// ${relativeFile}: the current opened file relative to workspaceRoot +// ${fileBasename}: the current opened file's basename +// ${fileDirname}: the current opened file's dirname +// ${fileExtname}: the current opened file's extension +// ${cwd}: the current working directory of the spawned process +// If you are using InvokeBuild you can enhance this tasks.json using the New-VSCodeTask command: +// Install-Script New-VSCodeTask +// New-VSCodeTask.ps1 -BuildFile .\src\YourModuleName.build.ps1 +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + + // Start PowerShell + "windows": { + "options": { + "shell": { + //"executable": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + // "executable": "C:\\Program Files\\PowerShell\\6\\pwsh.exe", + "executable": "C:\\Program Files\\PowerShell\\7\\pwsh.exe", + "args": [ "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command" ] + } + } + }, + "linux": { + "options": { + "shell": { + "executable": "/usr/bin/pwsh", + "args": [ "-NoProfile", "-Command" ] + } + } + }, + "osx": { + "options": { + "shell": { + "executable": "/usr/local/bin/pwsh", + "args": [ "-NoProfile", "-Command" ] + } + } + }, + + // Associate with test task runner + "tasks": [ + { + "label": "PesterTest", + "type": "shell", + "group": { + "kind": "test", + "isDefault": true + }, + "problemMatcher": [ "$pester" ], + "command": "Invoke-Pester '${workspaceFolder}/src/Tests/Unit' -PesterOption @{IncludeVSCodeMarker=$true}", + }, + { + "label": ".", + "type": "shell", + "problemMatcher": "$msCompile", + "command": "$PSVersionTable;Invoke-Build -Task . -File '${workspaceFolder}/src/pwshPlaces.build.ps1'", + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "TestLocal", + "type": "shell", + "problemMatcher": "$msCompile", + "command": "Invoke-Build -Task TestLocal -File '${workspaceFolder}/src/pwshPlaces.build.ps1'" + }, + { + "label": "HelpLocal", + "type": "shell", + "problemMatcher": "$msCompile", + "command": "Invoke-Build -Task HelpLocal -File '${workspaceFolder}/src/pwshPlaces.build.ps1'" + }, + { + "label": "Clean", + "type": "shell", + "problemMatcher": "$msCompile", + "command": "Invoke-Build -Task Clean -File '${workspaceFolder}/src/pwshPlaces.build.ps1'" + }, + { + "label": "ValidateRequirements", + "type": "shell", + "problemMatcher": "$msCompile", + "command": "Invoke-Build -Task ValidateRequirements -File '${workspaceFolder}/src/pwshPlaces.build.ps1'" + }, + { + "label": "Analyze", + "type": "shell", + "problemMatcher": "$msCompile", + "command": "Invoke-Build -Task Analyze -File '${workspaceFolder}/src/pwshPlaces.build.ps1'" + }, + { + "label": "AnalyzeTests", + "type": "shell", + "problemMatcher": "$msCompile", + "command": "Invoke-Build -Task AnalyzeTests -File '${workspaceFolder}/src/pwshPlaces.build.ps1'" + }, + { + "label": "FormattingCheck", + "type": "shell", + "problemMatcher": "$msCompile", + "command": "Invoke-Build -Task FormattingCheck -File '${workspaceFolder}/src/pwshPlaces.build.ps1'" + }, + { + "label": "Test", + "type": "shell", + "problemMatcher": "$msCompile", + "command": "Invoke-Build -Task Test -File '${workspaceFolder}/src/pwshPlaces.build.ps1'" + }, + { + "label": "DevCC", + "type": "shell", + "problemMatcher": "$msCompile", + "command": "Invoke-Build -Task DevCC -File '${workspaceFolder}/src/pwshPlaces.build.ps1'" + }, + { + "label": "Build", + "type": "shell", + "problemMatcher": "$msCompile", + "command": "Invoke-Build -Task Build -File '${workspaceFolder}/src/pwshPlaces.build.ps1'" + }, + { + "label": "InfraTest", + "type": "shell", + "problemMatcher": "$msCompile", + "command": "Invoke-Build -Task InfraTest -File '${workspaceFolder}/src/pwshPlaces.build.ps1'" + } + ] +} + diff --git a/actions_bootstrap.ps1 b/actions_bootstrap.ps1 new file mode 100644 index 0000000..31f4b78 --- /dev/null +++ b/actions_bootstrap.ps1 @@ -0,0 +1,56 @@ +# Bootstrap dependencies + +# https://docs.microsoft.com/powershell/module/packagemanagement/get-packageprovider +Get-PackageProvider -Name Nuget -ForceBootstrap | Out-Null + +# https://docs.microsoft.com/powershell/module/powershellget/set-psrepository +Set-PSRepository -Name PSGallery -InstallationPolicy Trusted + +# List of PowerShell Modules required for the build +$modulesToInstall = [System.Collections.ArrayList]::new() + +# https://github.com/pester/Pester +$null = $modulesToInstall.Add(([PSCustomObject]@{ + ModuleName = 'Pester' + ModuleVersion = '5.2.2' + })) +# https://github.com/nightroman/Invoke-Build +$null = $modulesToInstall.Add(([PSCustomObject]@{ + ModuleName = 'InvokeBuild' + ModuleVersion = '5.8.0' + })) +# https://github.com/PowerShell/PSScriptAnalyzer +$null = $modulesToInstall.Add(([PSCustomObject]@{ + ModuleName = 'PSScriptAnalyzer' + ModuleVersion = '1.19.1' + })) +# https://github.com/PowerShell/platyPS +# older version used due to: https://github.com/PowerShell/platyPS/issues/457 +$null = $modulesToInstall.Add(([PSCustomObject]@{ + ModuleName = 'platyPS' + ModuleVersion = '0.12.0' + })) + + + +'Installing PowerShell Modules' +foreach ($module in $modulesToInstall) { + $installSplat = @{ + Name = $module.ModuleName + RequiredVersion = $module.ModuleVersion + Repository = 'PSGallery' + SkipPublisherCheck = $true + Force = $true + ErrorAction = 'Stop' + } + try { + Install-Module @installSplat + Import-Module -Name $module.ModuleName -ErrorAction Stop + ' - Successfully installed {0}' -f $module.ModuleName + } + catch { + $message = 'Failed to install {0}' -f $module.ModuleName + " - $message" + throw + } +} diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000..9ea0aba --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,120 @@ + +jobs: + # https://docs.microsoft.com/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema + # https://docs.microsoft.com/azure/devops/pipelines/agents/hosted?view=azure-devops#use-a-microsoft-hosted-agent + # https://docs.microsoft.com/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml + # https://docs.microsoft.com/azure/devops/pipelines/tasks/test/publish-code-coverage-results?view=azure-devops + # https://docs.microsoft.com/azure/devops/pipelines/artifacts/build-artifacts?view=azure-devops&tabs=yaml + - job: build_ps_WinLatest + pool: + vmImage: windows-latest + steps: + - powershell: | + $PSVersionTable + Install-PackageProvider -Name "NuGet" -Confirm:$false -Force -Verbose + Install-Module -Name PowerShellGet -Repository PSGallery -Force + .\actions_bootstrap.ps1 + Invoke-Build -File $(Build.SourcesDirectory)\src\pwshPlaces.build.ps1 + displayName: 'Build and Test - Windows PowerShell' + - task: PublishTestResults@2 + inputs: + testRunner: 'NUnit' + testResultsFiles: '**\Artifacts\testOutput\PesterTests.xml' + testRunTitle: 'ps_winLatest' + failTaskOnFailedTests: true + displayName: "Publish Unit Test Results - Windows PowerShell" + - task: PublishCodeCoverageResults@1 + inputs: + summaryFileLocation: '**\Artifacts\ccReport\CodeCoverage.xml' + pathToSources: '$(System.DefaultWorkingDirectory)\src\Artifacts\ccReport' + failIfCoverageEmpty: false + displayName: "Publish Unit Test Code Coverage - Windows PowerShell" + condition: and(in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues', 'Failed'), eq(variables['System.PullRequest.IsFork'], false)) + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: '$(System.DefaultWorkingDirectory)\src\Archive' + artifactName: pwshPlaces-Archive + + - job: build_pwsh_WinLatest + pool: + vmImage: windows-latest + steps: + - pwsh: | + $PSVersionTable + .\actions_bootstrap.ps1 + Invoke-Build -File $(Build.SourcesDirectory)\src\pwshPlaces.build.ps1 + displayName: 'Build and Test - Windows pwsh' + - task: PublishTestResults@2 + inputs: + testRunner: 'NUnit' + testResultsFiles: '**\Artifacts\testOutput\PesterTests.xml' + testRunTitle: 'pwsh_winLatest' + failTaskOnFailedTests: true + displayName: "Publish Unit Test Results - Windows pwsh" + - task: PublishCodeCoverageResults@1 + inputs: + summaryFileLocation: '**\Artifacts\ccReport\CodeCoverage.xml' + pathToSources: '$(System.DefaultWorkingDirectory)\src\Artifacts\ccReport' + failIfCoverageEmpty: false + displayName: "Publish Unit Test Code Coverage - Windows pwsh" + condition: and(in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues', 'Failed'), eq(variables['System.PullRequest.IsFork'], false)) + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: '$(System.DefaultWorkingDirectory)\src\Archive' + artifactName: pwshPlaces-Archive + + - job: build_pwsh_ubuntuLatest + pool: + vmImage: ubuntu-latest + steps: + - script: | + sudo dpkg -i powershell_6.2.0-1.ubuntu.16.04_amd64.deb + sudo apt-get install -f + displayName: 'Install PowerShell Core' + - script: | + pwsh -c '$PSVersionTable;.\actions_bootstrap.ps1;Invoke-Build -File $(Build.SourcesDirectory)/src/pwshPlaces.build.ps1' + displayName: 'Build and Test - Linux' + - task: PublishTestResults@2 + inputs: + testRunner: 'NUnit' + testResultsFiles: '**/Artifacts/testOutput/PesterTests.xml' + testRunTitle: 'pwsh_ubuntuLatest' + failTaskOnFailedTests: true + displayName: "Publish Unit Test Results - Linux" + - task: PublishCodeCoverageResults@1 + inputs: + summaryFileLocation: '**/Artifacts/ccReport/CodeCoverage.xml' + pathToSources: '$(System.DefaultWorkingDirectory)/src/Artifacts/ccReport' + failIfCoverageEmpty: false + displayName: "Publish Unit Test Code Coverage - Linux" + condition: and(in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues', 'Failed'), eq(variables['System.PullRequest.IsFork'], false)) + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: '$(System.DefaultWorkingDirectory)/src/Archive' + artifactName: pwshPlaces-Archive + + - job: build_pwsh_macOSLatest + pool: + vmImage: macOS-latest + steps: + - script: | + pwsh -c '$PSVersionTable;.\actions_bootstrap.ps1;Invoke-Build -File $(Build.SourcesDirectory)/src/pwshPlaces.build.ps1' + displayName: 'Build and Test - macOS' + - task: PublishTestResults@2 + inputs: + testRunner: 'NUnit' + testResultsFiles: '**/Artifacts/testOutput/PesterTests.xml' + testRunTitle: 'pwsh_macOSLatest' + failTaskOnFailedTests: true + displayName: "Publish Unit Test Results - macOS" + - task: PublishCodeCoverageResults@1 + inputs: + summaryFileLocation: '**/Artifacts/ccReport/CodeCoverage.xml' + pathToSources: '$(System.DefaultWorkingDirectory)/src/Artifacts/ccReport' + failIfCoverageEmpty: false + displayName: "Publish Unit Test Code Coverage - macOS" + condition: and(in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues', 'Failed'), eq(variables['System.PullRequest.IsFork'], false)) + - task: PublishBuildArtifacts@1 + inputs: + pathToPublish: '$(System.DefaultWorkingDirectory)/src/Archive' + artifactName: pwshPlaces-Archive diff --git a/docs/Get-HelloWorld.md b/docs/Get-HelloWorld.md new file mode 100644 index 0000000..ced92af --- /dev/null +++ b/docs/Get-HelloWorld.md @@ -0,0 +1,48 @@ +--- +external help file: pwshPlaces-help.xml +Module Name: pwshPlaces +online version: +schema: 2.0.0 +--- + +# Get-HelloWorld + +## SYNOPSIS +Short description + +## SYNTAX + +``` +Get-HelloWorld [] +``` + +## DESCRIPTION +Long description + +## EXAMPLES + +### EXAMPLE 1 +``` +Example of how to use this cmdlet +``` + +### EXAMPLE 2 +``` +Another example of how to use this cmdlet +``` + +## PARAMETERS + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### Output from this cmdlet (if any) +## NOTES +General notes + +## RELATED LINKS diff --git a/docs/pwshPlaces.md b/docs/pwshPlaces.md new file mode 100644 index 0000000..575e8b0 --- /dev/null +++ b/docs/pwshPlaces.md @@ -0,0 +1,17 @@ +--- +Module Name: pwshPlaces +Module Guid: 9a9914bd-d115-4f42-bb5d-19c5e5561a3f +Download Help Link: NA +Help Version: 0.0.2 +Locale: en-US +--- + +# pwshPlaces Module +## Description +tbd + +## pwshPlaces Cmdlets +### [Get-HelloWorld](Get-HelloWorld.md) +Short description + + diff --git a/src/PSScriptAnalyzerSettings.psd1 b/src/PSScriptAnalyzerSettings.psd1 new file mode 100644 index 0000000..deafb24 --- /dev/null +++ b/src/PSScriptAnalyzerSettings.psd1 @@ -0,0 +1,60 @@ +@{ + #________________________________________ + #IncludeDefaultRules + IncludeDefaultRules = $true + #________________________________________ + #Severity + #Specify Severity when you want to limit generated diagnostic records to a sepecific subset: [ Error | Warning | Information ] + Severity = @('Error', 'Warning') + #________________________________________ + #CustomRulePath + #Specify CustomRulePath when you have a large set of custom rules you'd like to reference + #CustomRulePath = "Module\InjectionHunter\1.0.0\InjectionHunter.psd1" + #________________________________________ + #IncludeRules + #Specify IncludeRules when you only want to run specific subset of rules instead of the default rule set. + #IncludeRules = @('PSShouldProcess', + # 'PSUseApprovedVerbs') + #________________________________________ + #ExcludeRules + #Specify ExcludeRules when you want to exclude a certain rule from the the default set of rules. + #ExcludeRules = @( + # 'PSUseDeclaredVarsMoreThanAssignments' + #) + #________________________________________ + #Rules + #Here you can specify customizations for particular rules. Several examples are included below: + #Rules = @{ + # PSUseCompatibleCmdlets = @{ + # compatibility = @('core-6.1.0-windows', 'desktop-4.0-windows') + # } + # PSUseCompatibleSyntax = @{ + # Enable = $true + # TargetVersions = @( + # '3.0', + # '5.1', + # '6.2' + # ) + # } + # PSUseCompatibleCommands = @{ + # Enable = $true + # TargetProfiles = @( + # 'win-8_x64_10.0.14393.0_6.1.3_x64_4.0.30319.42000_core', # PS 6.1 on WinServer-2019 + # 'win-8_x64_10.0.17763.0_5.1.17763.316_x64_4.0.30319.42000_framework', # PS 5.1 on WinServer-2019 + # 'win-8_x64_6.2.9200.0_3.0_x64_4.0.30319.42000_framework' # PS 3 on WinServer-2012 + # ) + # } + # PSUseCompatibleTypes = @{ + # Enable = $true + # TargetProfiles = @( + # 'ubuntu_x64_18.04_6.1.3_x64_4.0.30319.42000_core', + # 'win-48_x64_10.0.17763.0_5.1.17763.316_x64_4.0.30319.42000_framework' + # ) + # # You can specify types to not check like this, which will also ignore methods and members on it: + # IgnoreTypes = @( + # 'System.IO.Compression.ZipFile' + # ) + # } + #} + #________________________________________ +} diff --git a/src/Tests/Infrastructure/SampleInfraTest.Tests.ps1 b/src/Tests/Infrastructure/SampleInfraTest.Tests.ps1 new file mode 100644 index 0000000..c44c360 --- /dev/null +++ b/src/Tests/Infrastructure/SampleInfraTest.Tests.ps1 @@ -0,0 +1,18 @@ +# #------------------------------------------------------------------------- +# Set-Location -Path $PSScriptRoot +# #------------------------------------------------------------------------- +# $ModuleName = 'pwshPlaces' +# #------------------------------------------------------------------------- +# #if the module is already in memory, remove it +# Get-Module $ModuleName | Remove-Module -Force +# $PathToManifest = [System.IO.Path]::Combine('..', '..', 'Artifacts', "$ModuleName.psd1") +# #------------------------------------------------------------------------- +# Import-Module $PathToManifest -Force +# #------------------------------------------------------------------------- +# Describe 'Infrastructure Tests' -Tag Infrastructure { +# Context 'First Infra Tests' { +# It 'should pass the first infra test' { +# # test logic +# } #it +# } +# } diff --git a/src/Tests/Unit/ExportedFunctions.Tests.ps1 b/src/Tests/Unit/ExportedFunctions.Tests.ps1 new file mode 100644 index 0000000..343f761 --- /dev/null +++ b/src/Tests/Unit/ExportedFunctions.Tests.ps1 @@ -0,0 +1,66 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', $ModuleName, "$ModuleName.psd1") +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +BeforeAll { + Set-Location -Path $PSScriptRoot + $ModuleName = 'pwshPlaces' + $PathToManifest = [System.IO.Path]::Combine('..', '..', $ModuleName, "$ModuleName.psd1") + $manifestContent = Test-ModuleManifest -Path $PathToManifest + $moduleExported = Get-Command -Module $ModuleName | Select-Object -ExpandProperty Name + $manifestExported = ($manifestContent.ExportedFunctions).Keys +} +Describe $ModuleName { + + Context 'Exported Commands' -Fixture { + + Context 'Number of commands' -Fixture { + It -Name 'Exports the same number of public functions as what is listed in the Module Manifest' -Test { + $manifestExported.Count | Should -BeExactly $moduleExported.Count + } + } + + Context 'Explicitly exported commands' -ForEach $moduleExported { + foreach ($command in $moduleExported) { + BeforeAll { + $command = $_ + } + It -Name "Includes the $command in the Module Manifest ExportedFunctions" -Test { + $manifestExported -contains $command | Should -BeTrue + } + } + } + } + + Context 'Command Help' -ForEach $moduleExported { + foreach ($command in $moduleExported) { + BeforeAll { + $help = Get-Help -Name $_ -Full + } + Context $command -Fixture { + $help = Get-Help -Name $command -Full + + It -Name 'Includes a Synopsis' -Test { + $help.Synopsis | Should -Not -BeNullOrEmpty + } + + It -Name 'Includes a Description' -Test { + $help.description.Text | Should -Not -BeNullOrEmpty + } + + It -Name 'Includes an Example' -Test { + $help.examples.example | Should -Not -BeNullOrEmpty + } + } + } + } +} diff --git a/src/Tests/Unit/Private/Get-Day.Tests.ps1 b/src/Tests/Unit/Private/Get-Day.Tests.ps1 new file mode 100644 index 0000000..284fed1 --- /dev/null +++ b/src/Tests/Unit/Private/Get-Day.Tests.ps1 @@ -0,0 +1,63 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + #------------------------------------------------------------------------- + $WarningPreference = "SilentlyContinue" + #------------------------------------------------------------------------- + Describe 'Get-Day Private Function Tests' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + } #beforeAll + Context 'Error' { + + It 'should return unknown if an error is encountered getting the date' { + Mock -CommandName Get-Date -MockWith { + throw 'Fake Error' + } #endMock + Get-Day | Should -BeExactly 'Unknown' + } #it + + } #context_Error + Context 'Success' { + + BeforeEach { + Mock -CommandName Get-Date -MockWith { + [PSCustomObject]@{ + DisplayHint = 'DateTime' + DateTime = 'Thursday, June 11, 2021 21:08:41' + Date = '06/11/21 00:00:00' + Day = '10' + DayOfWeek = 'Friday' + DayOfYear = '162' + Hour = '21' + Kind = 'Local' + Millisecond = '989' + Minute = '8' + Month = '6' + Second = '41' + Ticks = '637589561219896868' + TimeOfDay = '21:08:41.9896868' + Year = '2021' + } + } #endMock + } #beforeEach + + It 'should return the expected results' { + Get-Day | Should -BeExactly 'Friday' + } #it + + } #context_Success + } #describe_Get-HellowWorld +} #inModule diff --git a/src/Tests/Unit/Public/Get-HelloWorld.Tests.ps1 b/src/Tests/Unit/Public/Get-HelloWorld.Tests.ps1 new file mode 100644 index 0000000..5830905 --- /dev/null +++ b/src/Tests/Unit/Public/Get-HelloWorld.Tests.ps1 @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + Describe 'Get-HellowWorld Public Function Tests' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + } #beforeAll + Context 'Error' { + + # It 'should ...' { + + # } #it + + } #context_Error + Context 'Success' { + + BeforeEach { + Mock -CommandName Get-Day -MockWith { + 'Friday' + } #endMock + } #beforeEach + + It 'should return the expected results' { + Get-HelloWorld | Should -BeExactly 'Hello, happy Friday World!' + } #it + + } #context_Success + } #describe_Get-HellowWorld +} #inModule diff --git a/src/Tests/Unit/pwshPlaces-Module.Tests.ps1 b/src/Tests/Unit/pwshPlaces-Module.Tests.ps1 new file mode 100644 index 0000000..7ebbcd5 --- /dev/null +++ b/src/Tests/Unit/pwshPlaces-Module.Tests.ps1 @@ -0,0 +1,49 @@ +BeforeAll { + #------------------------------------------------------------------------- + Set-Location -Path $PSScriptRoot + #------------------------------------------------------------------------- + $ModuleName = 'pwshPlaces' + $PathToManifest = [System.IO.Path]::Combine('..', '..', $ModuleName, "$ModuleName.psd1") + $PathToModule = [System.IO.Path]::Combine('..', '..', $ModuleName, "$ModuleName.psm1") + #------------------------------------------------------------------------- +} +Describe 'Module Tests' -Tag Unit { + Context "Module Tests" { + $script:manifestEval = $null + It 'Passes Test-ModuleManifest' { + { $script:manifestEval = Test-ModuleManifest -Path $PathToManifest } | Should -Not -Throw + $? | Should -BeTrue + } #manifestTest + It 'root module pwshPlaces.psm1 should exist' { + $PathToModule | Should -Exist + $? | Should -BeTrue + } #psm1Exists + It 'manifest should contain pwshPlaces.psm1' { + $PathToManifest | + Should -FileContentMatchExactly "pwshPlaces.psm1" + } #validPSM1 + It 'should have a matching module name in the manifest' { + $script:manifestEval.Name | Should -BeExactly $ModuleName + } #name + It 'should have a valid description in the manifest' { + $script:manifestEval.Description | Should -Not -BeNullOrEmpty + } #description + It 'should have a valid author in the manifest' { + $script:manifestEval.Author | Should -Not -BeNullOrEmpty + } #author + It 'should have a valid version in the manifest' { + $script:manifestEval.Version -as [Version] | Should -Not -BeNullOrEmpty + } #version + It 'should have a valid guid in the manifest' { + { [guid]::Parse($script:manifestEval.Guid) } | Should -Not -Throw + } #guid + It 'should not have any spaces in the tags' { + foreach ($tag in $script:manifestEval.Tags) { + $tag | Should -Not -Match '\s' + } + } #tagSpaces + It 'should have a valid project Uri' { + $script:manifestEval.ProjectUri | Should -Not -BeNullOrEmpty + } #uri + } #context_ModuleTests +} #describe_ModuleTests diff --git a/src/pwshPlaces.Settings.ps1 b/src/pwshPlaces.Settings.ps1 new file mode 100644 index 0000000..164d83b --- /dev/null +++ b/src/pwshPlaces.Settings.ps1 @@ -0,0 +1,2 @@ +# specify the minumum required major PowerShell version that the build script should validate +[int]$script:requiredPSVersion = '5' \ No newline at end of file diff --git a/src/pwshPlaces.build.ps1 b/src/pwshPlaces.build.ps1 new file mode 100644 index 0000000..05102bb --- /dev/null +++ b/src/pwshPlaces.build.ps1 @@ -0,0 +1,548 @@ +<# +.SYNOPSIS + An Invoke-Build Build file. +.DESCRIPTION + Build steps can include: + - ValidateRequirements + - ImportModuleManifest + - Clean + - Analyze + - FormattingCheck + - Test + - DevCC + - CreateHelpStart + - Build + - InfraTest + - Archive +.EXAMPLE + Invoke-Build + + This will perform the default build Add-BuildTasks: see below for the default Add-BuildTask execution +.EXAMPLE + Invoke-Build -Add-BuildTask Analyze,Test + + This will perform only the Analyze and Test Add-BuildTasks. +.NOTES + This build will pull in configurations from the ".Settings.ps1" file as well, where users can more easily customize the build process if required. + https://github.com/nightroman/Invoke-Build + https://github.com/nightroman/Invoke-Build/wiki/Build-Scripts-Guidelines + If using VSCode you can use the generated tasks.json to execute the various tasks in this build file. + Ctrl + P | then type task (add space) - you will then be presented with a list of available tasks to run + The 'InstallDependencies' Add-BuildTask isn't present here. + Module dependencies are installed at a previous step in the pipeline. + If your manifest has module dependencies include all required modules in your CI/CD bootstrap file: + AWS - install_modules.ps1 + Azure - actions_bootstrap.ps1 + GitHub Actions - actions_bootstrap.ps1 + AppVeyor - actions_bootstrap.ps1 +#> + +#Include: Settings +$ModuleName = (Split-Path -Path $BuildFile -Leaf).Split('.')[0] +. "./$ModuleName.Settings.ps1" + +function Test-ManifestBool ($Path) { + Get-ChildItem $Path | Test-ModuleManifest -ErrorAction SilentlyContinue | Out-Null; $? +} + +#Default Build +$str = @() +$str = 'Clean', 'ValidateRequirements', 'ImportModuleManifest' +$str += 'FormattingCheck' +$str += 'Analyze', 'Test' +$str += 'CreateHelpStart' +$str += 'Build', 'InfraTest', 'Archive' +Add-BuildTask -Name . -Jobs $str + +#Local testing build process +Add-BuildTask TestLocal Clean, ImportModuleManifest, Analyze, Test + +#Local help file creation process +Add-BuildTask HelpLocal Clean, ImportModuleManifest, CreateHelpStart + +# Pre-build variables to be used by other portions of the script +Enter-Build { + $script:ModuleName = (Split-Path -Path $BuildFile -Leaf).Split('.')[0] + + # Identify other required paths + $script:ModuleSourcePath = Join-Path -Path $BuildRoot -ChildPath $script:ModuleName + $script:ModuleFiles = Join-Path -Path $script:ModuleSourcePath -ChildPath '*' + + $script:ModuleManifestFile = Join-Path -Path $script:ModuleSourcePath -ChildPath "$($script:ModuleName).psd1" + + $manifestInfo = Import-PowerShellDataFile -Path $script:ModuleManifestFile + $script:ModuleVersion = $manifestInfo.ModuleVersion + $script:ModuleDescription = $manifestInfo.Description + $script:FunctionsToExport = $manifestInfo.FunctionsToExport + + $script:TestsPath = Join-Path -Path $BuildRoot -ChildPath 'Tests' + $script:UnitTestsPath = Join-Path -Path $script:TestsPath -ChildPath 'Unit' + $script:InfraTestsPath = Join-Path -Path $script:TestsPath -ChildPath 'Infrastructure' + + $script:ArtifactsPath = Join-Path -Path $BuildRoot -ChildPath 'Artifacts' + $script:ArchivePath = Join-Path -Path $BuildRoot -ChildPath 'Archive' + + $script:BuildModuleRootFile = Join-Path -Path $script:ArtifactsPath -ChildPath "$($script:ModuleName).psm1" + + # Ensure our builds fail until if below a minimum defined code test coverage threshold + $script:coverageThreshold = 30 + + + [version]$script:MinPesterVersion = '5.2.2' + [version]$script:MaxPesterVersion = '5.99.99' +} #Enter-Build + +# Define headers as separator, task path, synopsis, and location, e.g. for Ctrl+Click in VSCode. +# Also change the default color to Green. If you need task start times, use `$Task.Started`. +Set-BuildHeader { + param($Path) + # separator line + Write-Build DarkMagenta ('=' * 79) + # default header + synopsis + Write-Build DarkGray "Task $Path : $(Get-BuildSynopsis $Task)" + # task location in a script + Write-Build DarkGray "At $($Task.InvocationInfo.ScriptName):$($Task.InvocationInfo.ScriptLineNumber)" + Write-Build Yellow "Manifest File: $script:ModuleManifestFile" + Write-Build Yellow "Manifest Version: $($manifestInfo.ModuleVersion)" +} #Set-BuildHeader + +# Define footers similar to default but change the color to DarkGray. +Set-BuildFooter { + param($Path) + Write-Build DarkGray "Done $Path, $($Task.Elapsed)" + # # separator line + # Write-Build Gray ('=' * 79) +} #Set-BuildFooter + +#Synopsis: Validate system requirements are met +Add-BuildTask ValidateRequirements { + # this setting comes from the *.Settings.ps1 + Write-Build White " Verifying at least PowerShell $script:requiredPSVersion..." + Assert-Build ($PSVersionTable.PSVersion.Major.ToString() -ge $script:requiredPSVersion) "At least Powershell $script:requiredPSVersion is required for this build to function properly" + Write-Build Green ' ...Verification Complete!' +} #ValidateRequirements + +# Synopsis: Import the current module manifest file for processing +Add-BuildTask TestModuleManifest -Before ImportModuleManifest { + Write-Build White ' Running module manifest tests...' + Assert-Build (Test-Path $script:ModuleManifestFile) 'Unable to locate the module manifest file.' + Assert-Build (Test-ManifestBool -Path $script:ModuleManifestFile) 'Module Manifest test did not pass verification.' + Write-Build Green ' ...Module Manifest Verification Complete!' +} + +# Synopsis: Load the module project +Add-BuildTask ImportModuleManifest { + Write-Build White ' Attempting to load the project module.' + try { + Import-Module $script:ModuleManifestFile -Force -PassThru -ErrorAction Stop + } + catch { + throw 'Unable to load the project module' + } + Write-Build Green " ...$script:ModuleName imported successfully" +} + +#Synopsis: Clean and reset Artifacts/Archive Directory +Add-BuildTask Clean { + Write-Build White ' Clean up our Artifacts/Archive directory...' + + $null = Remove-Item $script:ArtifactsPath -Force -Recurse -ErrorAction 0 + $null = New-Item $script:ArtifactsPath -ItemType:Directory + $null = Remove-Item $script:ArchivePath -Force -Recurse -ErrorAction 0 + $null = New-Item $script:ArchivePath -ItemType:Directory + + Write-Build Green ' ...Clean Complete!' +} #Clean + +#Synopsis: Invokes PSScriptAnalyzer against the Module source path +Add-BuildTask Analyze { + + $scriptAnalyzerParams = @{ + Path = $script:ModuleSourcePath + Setting = 'PSScriptAnalyzerSettings.psd1' + Recurse = $true + Verbose = $false + } + + Write-Build White ' Performing Module ScriptAnalyzer checks...' + $scriptAnalyzerResults = Invoke-ScriptAnalyzer @scriptAnalyzerParams + + if ($scriptAnalyzerResults) { + $scriptAnalyzerResults | Format-Table + throw ' One or more PSScriptAnalyzer errors/warnings where found.' + } + else { + Write-Build Green ' ...Module Analyze Complete!' + } +} #Analyze + +#Synopsis: Invokes Script Analyzer against the Tests path if it exists +Add-BuildTask AnalyzeTests -After Analyze { + if (Test-Path -Path $script:TestsPath) { + + + $scriptAnalyzerParams = @{ + Path = $script:TestsPath + Setting = 'PSScriptAnalyzerSettings.psd1' + ExcludeRule = 'PSUseDeclaredVarsMoreThanAssignments' + Recurse = $true + Verbose = $false + } + + Write-Build White ' Performing Test ScriptAnalyzer checks...' + $scriptAnalyzerResults = Invoke-ScriptAnalyzer @scriptAnalyzerParams + + if ($scriptAnalyzerResults) { + $scriptAnalyzerResults | Format-Table + throw ' One or more PSScriptAnalyzer errors/warnings where found.' + } + else { + Write-Build Green ' ...Test Analyze Complete!' + } + } +} #AnalyzeTests + +#Synopsis: Analyze scripts to verify if they adhere to desired coding format (Stroustrup / OTBS / Allman) +Add-BuildTask FormattingCheck { + + $scriptAnalyzerParams = @{ + Setting = 'CodeFormattingStroustrup' + ExcludeRule = 'PSUseConsistentWhitespace' + Recurse = $true + Verbose = $false + } + + + + Write-Build White ' Performing script formatting checks...' + $scriptAnalyzerResults = Get-ChildItem -Path $script:ModuleSourcePath -Exclude "*.psd1" | Invoke-ScriptAnalyzer @scriptAnalyzerParams + + if ($scriptAnalyzerResults) { + $scriptAnalyzerResults | Format-Table + throw ' PSScriptAnalyzer code formatting check did not adhere to {0} standards' -f $scriptAnalyzerParams.Setting + } + else { + Write-Build Green ' ...Formatting Analyze Complete!' + } +} #FormattingCheck + +#Synopsis: Invokes all Pester Unit Tests in the Tests\Unit folder (if it exists) +Add-BuildTask Test { + + Write-Build White " Importing desired Pester version. Min: $script:MinPesterVersion Max: $script:MaxPesterVersion" + Remove-Module -Name Pester -Force -ErrorAction SilentlyContinue # there are instances where some containers have Pester already in the session + Import-Module -Name Pester -MinimumVersion $script:MinPesterVersion -MaximumVersion $script:MaxPesterVersion -ErrorAction 'Stop' + + $codeCovPath = "$script:ArtifactsPath\ccReport\" + $testOutPutPath = "$script:ArtifactsPath\testOutput\" + if (-not(Test-Path $codeCovPath)) { + New-Item -Path $codeCovPath -ItemType Directory | Out-Null + } + if (-not(Test-Path $testOutPutPath)) { + New-Item -Path $testOutPutPath -ItemType Directory | Out-Null + } + if (Test-Path -Path $script:UnitTestsPath) { + + $pesterConfiguration = [PesterConfiguration]::new() + $pesterConfiguration.run.Path = $script:TestsPath + $pesterConfiguration.Run.PassThru = $true + $pesterConfiguration.Run.Exit = $false + $pesterConfiguration.CodeCoverage.Enabled = $true + $pesterConfiguration.CodeCoverage.Path = "..\..\..\$ModuleName\*\*.ps1" + $pesterConfiguration.CodeCoverage.CoveragePercentTarget = $script:coverageThreshold + $pesterConfiguration.CodeCoverage.OutputPath = "$codeCovPath\CodeCoverage.xml" + $pesterConfiguration.CodeCoverage.OutputFormat = 'JaCoCo' + $pesterConfiguration.TestResult.Enabled = $true + $pesterConfiguration.TestResult.OutputPath = "$testOutPutPath\PesterTests.xml" + $pesterConfiguration.TestResult.OutputFormat = 'NUnitXml' + $pesterConfiguration.Output.Verbosity = 'Detailed' + + Write-Build White ' Performing Pester Unit Tests...' + # Publish Test Results as NUnitXml + $testResults = Invoke-Pester -Configuration $pesterConfiguration + + # This will output a nice json for each failed test (if running in CodeBuild) + if ($env:CODEBUILD_BUILD_ARN) { + $testResults.TestResult | ForEach-Object { + if ($_.Result -ne 'Passed') { + ConvertTo-Json -InputObject $_ -Compress + } + } + } + + $numberFails = $testResults.FailedCount + Assert-Build($numberFails -eq 0) ('Failed "{0}" unit tests.' -f $numberFails) + + + Write-Build Gray (' ...CODE COVERAGE - CommandsExecutedCount: {0}' -f $testResults.CodeCoverage.CommandsExecutedCount) + Write-Build Gray (' ...CODE COVERAGE - CommandsAnalyzedCount: {0}' -f $testResults.CodeCoverage.CommandsAnalyzedCount) + + if ($testResults.CodeCoverage.NumberOfCommandsExecuted -ne 0) { + $coveragePercent = '{0:N2}' -f ($testResults.CodeCoverage.CommandsExecutedCount / $testResults.CodeCoverage.CommandsAnalyzedCount * 100) + + <# + if ($testResults.CodeCoverage.NumberOfCommandsMissed -gt 0) { + 'Failed to analyze "{0}" commands' -f $testResults.CodeCoverage.NumberOfCommandsMissed + } + Write-Host "PowerShell Commands not tested:`n$(ConvertTo-Json -InputObject $testResults.CodeCoverage.MissedCommands)" + #> + if ([Int]$coveragePercent -lt $coverageThreshold) { + throw ('Failed to meet code coverage threshold of {0}% with only {1}% coverage' -f $coverageThreshold, $coveragePercent) + } + else { + Write-Build Cyan " $('Covered {0}% of {1} analyzed commands in {2} files.' -f $coveragePercent,$testResults.CodeCoverage.CommandsAnalyzedCount,$testResults.CodeCoverage.FilesAnalyzedCount)" + Write-Build Green ' ...Pester Unit Tests Complete!' + } + } + else { + # account for new module build condition + Write-Build Yellow ' Code coverage check skipped. No commands to execute...' + } + + } +} #Test + +#Synopsis: Used primarily during active development to generate xml file to graphically display code coverage in VSCode using Coverage Gutters +Add-BuildTask DevCC { + Write-Build White ' Generating code coverage report at root...' + Write-Build White " Importing desired Pester version. Min: $script:MinPesterVersion Max: $script:MaxPesterVersion" + Remove-Module -Name Pester -Force -ErrorAction SilentlyContinue # there are instances where some containers have Pester already in the session + Import-Module -Name Pester -MinimumVersion $script:MinPesterVersion -MaximumVersion $script:MaxPesterVersion -ErrorAction 'Stop' + + $pesterConfiguration = [PesterConfiguration]::new() + $pesterConfiguration.run.Path = 'Tests\Unit' + $pesterConfiguration.CodeCoverage.Enabled = $true + $pesterConfiguration.CodeCoverage.Path = "$PSScriptRoot\$ModuleName\*\*.ps1" + $pesterConfiguration.CodeCoverage.CoveragePercentTarget = $script:coverageThreshold + $pesterConfiguration.CodeCoverage.OutputPath = '..\..\..\cov.xml' + $pesterConfiguration.CodeCoverage.OutputFormat = 'CoverageGutters' + + Invoke-Pester -Configuration $pesterConfiguration + Write-Build Green ' ...Code Coverage report generated!' +} #DevCC + +# Synopsis: Build help for module +Add-BuildTask CreateHelpStart { + Write-Build White ' Performing all help related actions.' + + Write-Build Gray ' Importing platyPS v0.12.0 ...' + Import-Module platyPS -RequiredVersion 0.12.0 -ErrorAction Stop + Write-Build Gray ' ...platyPS imported successfully.' +} #CreateHelpStart + +# Synopsis: Build markdown help files for module and fail if help information is missing +Add-BuildTask CreateMarkdownHelp -After CreateHelpStart { + $ModulePage = "$script:ArtifactsPath\docs\$($ModuleName).md" + + $markdownParams = @{ + Module = $ModuleName + OutputFolder = "$script:ArtifactsPath\docs\" + Force = $true + WithModulePage = $true + Locale = 'en-US' + FwLink = "NA" + HelpVersion = $script:ModuleVersion + } + + Write-Build Gray ' Generating markdown files...' + $null = New-MarkdownHelp @markdownParams + Write-Build Gray ' ...Markdown generation completed.' + + Write-Build Gray ' Replacing markdown elements...' + # Replace multi-line EXAMPLES + $OutputDir = "$script:ArtifactsPath\docs\" + $OutputDir | Get-ChildItem -File | ForEach-Object { + # fix formatting in multiline examples + $content = Get-Content $_.FullName -Raw + $newContent = $content -replace '(## EXAMPLE [^`]+?```\r\n[^`\r\n]+?\r\n)(```\r\n\r\n)([^#]+?\r\n)(\r\n)([^#]+)(#)', '$1$3$2$4$5$6' + if ($newContent -ne $content) { + Set-Content -Path $_.FullName -Value $newContent -Force + } + } + # Replace each missing element we need for a proper generic module page .md file + $ModulePageFileContent = Get-Content -Raw $ModulePage + $ModulePageFileContent = $ModulePageFileContent -replace '{{Manually Enter Description Here}}', $script:ModuleDescription + $script:FunctionsToExport | ForEach-Object { + Write-Build DarkGray " Updating definition for the following function: $($_)" + $TextToReplace = "{{Manually Enter $($_) Description Here}}" + $ReplacementText = (Get-Help -Detailed $_).Synopsis + $ModulePageFileContent = $ModulePageFileContent -replace $TextToReplace, $ReplacementText + } + + $ModulePageFileContent | Out-File $ModulePage -Force -Encoding:utf8 + Write-Build Gray ' ...Markdown replacements complete.' + + Write-Build Gray ' Verifying GUID...' + $MissingGUID = Select-String -Path "$script:ArtifactsPath\docs\*.md" -Pattern "(00000000-0000-0000-0000-000000000000)" + if ($MissingGUID.Count -gt 0) { + Write-Build Yellow ' The documentation that got generated resulted in a generic GUID. Check the GUID entry of your module manifest.' + throw 'Missing GUID. Please review and rebuild.' + } + + Write-Build Gray ' Checking for missing documentation in md files...' + $MissingDocumentation = Select-String -Path "$script:ArtifactsPath\docs\*.md" -Pattern "({{.*}})" + if ($MissingDocumentation.Count -gt 0) { + Write-Build Yellow ' The documentation that got generated resulted in missing sections which should be filled out.' + Write-Build Yellow ' Please review the following sections in your comment based help, fill out missing information and rerun this build:' + Write-Build Yellow ' (Note: This can happen if the .EXTERNALHELP CBH is defined for a function before running this build.)' + Write-Build Yellow " Path of files with issues: $script:ArtifactsPath\docs\" + $MissingDocumentation | Select-Object FileName, LineNumber, Line | Format-Table -AutoSize + throw 'Missing documentation. Please review and rebuild.' + } + + Write-Build Gray ' Checking for missing SYNOPSIS in md files...' + $fSynopsisOutput = @() + $synopsisEval = Select-String -Path "$script:ArtifactsPath\docs\*.md" -Pattern "^## SYNOPSIS$" -Context 0, 1 + $synopsisEval | ForEach-Object { + $chAC = $_.Context.DisplayPostContext.ToCharArray() + if ($null -eq $chAC) { + $fSynopsisOutput += $_.FileName + } + } + if ($fSynopsisOutput) { + Write-Build Yellow " The following files are missing SYNOPSIS:" + $fSynopsisOutput + throw 'SYNOPSIS information missing. Please review.' + } + + Write-Build Gray ' ...Markdown generation complete.' +} #CreateMarkdownHelp + +# Synopsis: Build the external xml help file from markdown help files with PlatyPS +Add-BuildTask CreateExternalHelp -After CreateMarkdownHelp { + Write-Build Gray ' Creating external xml help file...' + $null = New-ExternalHelp "$script:ArtifactsPath\docs" -OutputPath "$script:ArtifactsPath\en-US\" -Force + Write-Build Gray ' ...External xml help file created!' +} #CreateExternalHelp + +Add-BuildTask CreateHelpComplete -After CreateExternalHelp { + Write-Build Green ' ...CreateHelp Complete!' +} #CreateHelpStart + +# Synopsis: Replace comment based help (CBH) with external help in all public functions for this project +Add-BuildTask UpdateCBH -After AssetCopy { + $ExternalHelp = @" +<# +.EXTERNALHELP $($ModuleName)-help.xml +#> +"@ + + $CBHPattern = "(?ms)(\<#.*\.SYNOPSIS.*?#>)" + Get-ChildItem -Path "$script:ArtifactsPath\Public\*.ps1" -File | ForEach-Object { + $FormattedOutFile = $_.FullName + Write-Output " Replacing CBH in file: $($FormattedOutFile)" + $UpdatedFile = (Get-Content $FormattedOutFile -raw) -replace $CBHPattern, $ExternalHelp + $UpdatedFile | Out-File -FilePath $FormattedOutFile -force -Encoding:utf8 + } +} #UpdateCBH + +# Synopsis: Copies module assets to Artifacts folder +Add-BuildTask AssetCopy -Before Build { + Write-Build Gray ' Copying assets to Artifacts...' + Copy-Item -Path "$script:ModuleSourcePath\*" -Destination $script:ArtifactsPath -Exclude *.psd1, *.psm1 -Recurse -ErrorAction Stop + Write-Build Gray ' ...Assets copy complete.' +} #AssetCopy + +# Synopsis: Builds the Module to the Artifacts folder +Add-BuildTask Build { + Write-Build White ' Performing Module Build' + + Write-Build Gray ' Copying manifest file to Artifacts...' + Copy-Item -Path $script:ModuleManifestFile -Destination $script:ArtifactsPath -Recurse -ErrorAction Stop + #Copy-Item -Path $script:ModuleSourcePath\bin -Destination $script:ArtifactsPath -Recurse -ErrorAction Stop + Write-Build Gray ' ...manifest copy complete.' + + Write-Build Gray ' Merging Public and Private functions to one module file...' + #$private = "$script:ModuleSourcePath\Private" + $scriptContent = [System.Text.StringBuilder]::new() + #$powerShellScripts = Get-ChildItem -Path $script:ModuleSourcePath -Filter '*.ps1' -Recurse + $powerShellScripts = Get-ChildItem -Path $script:ArtifactsPath -Recurse | Where-Object { $_.Name -match '^*.ps1$' } + foreach ($script in $powerShellScripts) { + $null = $scriptContent.Append((Get-Content -Path $script.FullName -Raw)) + $null = $scriptContent.AppendLine('') + $null = $scriptContent.AppendLine('') + } + $scriptContent.ToString() | Out-File -FilePath $script:BuildModuleRootFile -Encoding utf8 -Force + Write-Build Gray ' ...Module creation complete.' + + Write-Build Gray ' Cleaning up leftover artifacts...' + #cleanup artifacts that are no longer required + if (Test-Path "$script:ArtifactsPath\Public") { + Remove-Item "$script:ArtifactsPath\Public" -Recurse -Force -ErrorAction Stop + } + if (Test-Path "$script:ArtifactsPath\Private") { + Remove-Item "$script:ArtifactsPath\Private" -Recurse -Force -ErrorAction Stop + } + if (Test-Path "$script:ArtifactsPath\Imports.ps1") { + Remove-Item "$script:ArtifactsPath\Imports.ps1" -Force -ErrorAction SilentlyContinue + } + + if (Test-Path "$script:ArtifactsPath\docs") { + #here we update the parent level docs. If you would prefer not to update them, comment out this section. + Write-Build Gray ' Overwriting docs output...' + if (-not (Test-Path '..\docs\')) { + New-Item -Path '..\docs\' -ItemType Directory -Force | Out-Null + } + Move-Item "$script:ArtifactsPath\docs\*.md" -Destination '..\docs\' -Force + Remove-Item "$script:ArtifactsPath\docs" -Recurse -Force -ErrorAction Stop + Write-Build Gray ' ...Docs output completed.' + } + + Write-Build Green ' ...Build Complete!' +} #Build + +#Synopsis: Invokes all Pester Infrastructure Tests in the Tests\Infrastructure folder (if it exists) +Add-BuildTask InfraTest { + if (Test-Path -Path $script:InfraTestsPath) { + Write-Build White " Importing desired Pester version. Min: $script:MinPesterVersion Max: $script:MaxPesterVersion" + Remove-Module -Name Pester -Force -ErrorAction SilentlyContinue # there are instances where some containers have Pester already in the session + Import-Module -Name Pester -MinimumVersion $script:MinPesterVersion -MaximumVersion $script:MaxPesterVersion -ErrorAction 'Stop' + + Write-Build White " Performing Pester Infrastructure Tests in $($invokePesterParams.path)" + + + $pesterConfiguration = [PesterConfiguration]::new() + $pesterConfiguration.run.Path = 'Tests\Infrastructure' + $pesterConfiguration.Run.PassThru = $true + $pesterConfiguration.Run.Exit = $false + $pesterConfiguration.CodeCoverage.Enabled = $false + $pesterConfiguration.TestResult.Enabled = $false + $pesterConfiguration.Output.Verbosity = 'Detailed' + + $testResults = Invoke-Pester -Configuration $pesterConfiguration + # This will output a nice json for each failed test (if running in CodeBuild) + if ($env:CODEBUILD_BUILD_ARN) { + $testResults.TestResult | ForEach-Object { + if ($_.Result -ne 'Passed') { + ConvertTo-Json -InputObject $_ -Compress + } + } + } + + $numberFails = $testResults.FailedCount + Assert-Build($numberFails -eq 0) ('Failed "{0}" unit tests.' -f $numberFails) + Write-Build Green ' ...Pester Infrastructure Tests Complete!' + } +} #InfraTest + +#Synopsis: Creates an archive of the built Module +Add-BuildTask Archive { + Write-Build White ' Performing Archive...' + + $archivePath = Join-Path -Path $BuildRoot -ChildPath 'Archive' + if (Test-Path -Path $archivePath) { + $null = Remove-Item -Path $archivePath -Recurse -Force + } + + $null = New-Item -Path $archivePath -ItemType Directory -Force + + $zipFileName = '{0}_{1}_{2}.{3}.zip' -f $script:ModuleName, $script:ModuleVersion, ([DateTime]::UtcNow.ToString("yyyyMMdd")), ([DateTime]::UtcNow.ToString("hhmmss")) + $zipFile = Join-Path -Path $archivePath -ChildPath $zipFileName + + if ($PSEdition -eq 'Desktop') { + Add-Type -AssemblyName 'System.IO.Compression.FileSystem' + } + [System.IO.Compression.ZipFile]::CreateFromDirectory($script:ArtifactsPath, $zipFile) + + Write-Build Green ' ...Archive Complete!' +} #Archive diff --git a/src/pwshPlaces/Imports.ps1 b/src/pwshPlaces/Imports.ps1 new file mode 100644 index 0000000..ad7b7d9 --- /dev/null +++ b/src/pwshPlaces/Imports.ps1 @@ -0,0 +1,6 @@ +# This is a locally sourced Imports file for local development. +# It can be imported by the psm1 in local development to add script level variables. +# It will merged in the build process. This is for local development only. + +# region script variables +# $script:resourcePath = "$PSScriptRoot\Resources" diff --git a/src/pwshPlaces/Private/Get-Day.ps1 b/src/pwshPlaces/Private/Get-Day.ps1 new file mode 100644 index 0000000..ca74750 --- /dev/null +++ b/src/pwshPlaces/Private/Get-Day.ps1 @@ -0,0 +1,38 @@ +<# +.SYNOPSIS + Short description +.DESCRIPTION + Long description +.EXAMPLE + C:\PS> + Example of how to use this cmdlet +.EXAMPLE + C:\PS> + Another example of how to use this cmdlet +.PARAMETER InputObject + Specifies the object to be processed. You can also pipe the objects to this command. +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + General notes +.COMPONENT + pwshPlaces +#> +function Get-Day { + [CmdletBinding()] + param ( + # [Parameter(Mandatory = $true, + # HelpMessage = 'Helpful Message')] + # [ValidateNotNull()] + # [ValidateNotNullOrEmpty()] + # [string]$YourParameter + ) + try { + $day = (Get-Date -ErrorAction 'Stop').DayOfWeek + } + catch { + $day = 'Unknown' + } + + return $day +} #Get-Day diff --git a/src/pwshPlaces/Public/Get-HelloWorld.ps1 b/src/pwshPlaces/Public/Get-HelloWorld.ps1 new file mode 100644 index 0000000..98cfa06 --- /dev/null +++ b/src/pwshPlaces/Public/Get-HelloWorld.ps1 @@ -0,0 +1,33 @@ +<# +.SYNOPSIS + Short description +.DESCRIPTION + Long description +.EXAMPLE + C:\PS> + Example of how to use this cmdlet +.EXAMPLE + C:\PS> + Another example of how to use this cmdlet +.PARAMETER InputObject + Specifies the object to be processed. You can also pipe the objects to this command. +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + General notes +.COMPONENT + pwshPlaces +#> +function Get-HelloWorld { + [CmdletBinding()] + param ( + # [Parameter(Mandatory = $true, + # HelpMessage = 'Helpful Message')] + # [ValidateNotNull()] + # [ValidateNotNullOrEmpty()] + # [string]$YourParameter + ) + $dayOfWeek = Get-Day # Get-Day is a private function + $message = "Hello, happy $dayOfWeek World!" + return $message +} #Get-HelloWorld diff --git a/src/pwshPlaces/pwshPlaces.psd1 b/src/pwshPlaces/pwshPlaces.psd1 new file mode 100644 index 0000000..9b8b8cc --- /dev/null +++ b/src/pwshPlaces/pwshPlaces.psd1 @@ -0,0 +1,135 @@ +# +# Module manifest for module 'pwshPlaces' +# +# Generated by: Jake Morrison +# +# Generated on: 09/11/21 +# + +@{ + + # Script module or binary module file associated with this manifest. + RootModule = 'pwshPlaces.psm1' + + # Version number of this module. + ModuleVersion = '0.0.2' + + # Supported PSEditions + # CompatiblePSEditions = @() + + # ID used to uniquely identify this module + GUID = '9a9914bd-d115-4f42-bb5d-19c5e5561a3f' + + # Author of this module + Author = 'Jake Morrison' + + # Company or vendor of this module + CompanyName = 'Unknown' + + # Copyright statement for this module + Copyright = '(c) Jake Morrison. All rights reserved.' + + # Description of the functionality provided by this module + Description = 'tbd' + + # Minimum version of the PowerShell engine required by this module + # PowerShellVersion = '' + + # Name of the PowerShell host required by this module + # PowerShellHostName = '' + + # Minimum version of the PowerShell host required by this module + # PowerShellHostVersion = '' + + # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. + # DotNetFrameworkVersion = '' + + # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. + # ClrVersion = '' + + # Processor architecture (None, X86, Amd64) required by this module + # ProcessorArchitecture = '' + + # Modules that must be imported into the global environment prior to importing this module + # RequiredModules = @() + + # Assemblies that must be loaded prior to importing this module + # RequiredAssemblies = @() + + # Script files (.ps1) that are run in the caller's environment prior to importing this module. + # ScriptsToProcess = @() + + # Type files (.ps1xml) to be loaded when importing this module + # TypesToProcess = @() + + # Format files (.ps1xml) to be loaded when importing this module + # FormatsToProcess = @() + + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + # NestedModules = @() + + # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. + FunctionsToExport = @( + 'Get-HelloWorld' + ) + + # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. + # CmdletsToExport = '*' + + # Variables to export from this module + # VariablesToExport = '*' + + # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. + # AliasesToExport = '*' + + # DSC resources to export from this module + # DscResourcesToExport = @() + + # List of all modules packaged with this module + # ModuleList = @() + + # List of all files packaged with this module + # FileList = @() + + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + ProjectUri = 'https://github.com/techthoughts2/pwshPlaces' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + # Prerelease string of this module + # Prerelease = '' + + # Flag to indicate whether the module requires explicit user acceptance for install/update/save + # RequireLicenseAcceptance = $false + + # External dependent modules of this module + # ExternalModuleDependencies = @() + + } # End of PSData hashtable + + } # End of PrivateData hashtable + + # HelpInfo URI of this module + # HelpInfoURI = '' + + # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. + # DefaultCommandPrefix = '' + +} + + diff --git a/src/pwshPlaces/pwshPlaces.psm1 b/src/pwshPlaces/pwshPlaces.psm1 new file mode 100644 index 0000000..81f168f --- /dev/null +++ b/src/pwshPlaces/pwshPlaces.psm1 @@ -0,0 +1,34 @@ +# this psm1 is for local testing and development use only + +# dot source the parent import for local development variables +. $PSScriptRoot\Imports.ps1 + +# discover all ps1 file(s) in Public and Private paths + +$itemSplat = @{ + Filter = '*.ps1' + Recurse = $true + ErrorAction = 'Stop' +} +try { + $public = @(Get-ChildItem -Path "$PSScriptRoot\Public" @itemSplat) + $private = @(Get-ChildItem -Path "$PSScriptRoot\Private" @itemSplat) +} +catch { + Write-Error $_ + throw "Unable to get get file information from Public & Private src." +} + +# dot source all .ps1 file(s) found +foreach ($file in @($public + $private)) { + try { + . $file.FullName + } + catch { + throw "Unable to dot source [$($file.FullName)]" + + } +} + +# export all public functions +Export-ModuleMember -Function $public.Basename \ No newline at end of file From fd6038a873cd97f0a66112086c55ae6b6d41b4bb Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sun, 3 Oct 2021 23:11:59 -0500 Subject: [PATCH 02/22] initial gmap commit --- .github/workflows/wf_Linux.yml | 48 + .github/workflows/wf_MacOS.yml | 48 + .github/workflows/wf_Windows.yml | 54 + .github/workflows/wf_Windows_Core.yml | 48 + README.md | 84 ++ actions_bootstrap.ps1 | 6 +- azure-pipelines.yml | 120 --- docs/Find-GMapPlace.md | 409 ++++++++ docs/Get-GMapPlaceDetail.md | 187 ++++ docs/Get-GMapPlaceDetails.md | 187 ++++ docs/Get-HelloWorld.md | 48 - docs/GoogleMapsAPI.md | 133 +++ docs/Invoke-GMapGeoCode.md | 221 ++++ docs/Search-GMapNearbyPlace.md | 364 +++++++ docs/Search-GMapText.md | 465 +++++++++ docs/pwshPlaces-FAQ.md | 11 + docs/pwshPlaces.md | 18 +- media/gcp_api_services_restrict_api_key.PNG | Bin 0 -> 102959 bytes media/gcp_enable_geocoding_api.PNG | Bin 0 -> 26377 bytes media/gcp_enable_places_api.PNG | Bin 0 -> 19253 bytes .../gcp_google_maps_create_credential_api.PNG | Bin 0 -> 76373 bytes media/gcp_google_maps_platform.PNG | Bin 0 -> 41598 bytes media/gcp_new_project.PNG | Bin 0 -> 147785 bytes .../google_cloud_top_left_navigation_menu.PNG | Bin 0 -> 6569 bytes ...le_maps_platform_maps_api_and_services.PNG | Bin 0 -> 197888 bytes src/PSScriptAnalyzerSettings.psd1 | 6 +- .../Infrastructure/SampleInfraTest.Tests.ps1 | 18 - .../Infrastructure/pwshPlaces-Infra.Tests.ps1 | 118 +++ .../Unit/Private/Format-GMapGeoCode.Tests.ps1 | 47 + .../Private/Format-GMapNearbyPlace.Tests.ps1 | 47 + .../Unit/Private/Format-GMapPlace.Tests.ps1 | 47 + .../Private/Format-GMapPlaceDetail.Tests.ps1 | 50 + .../Private/Format-GMapPlaceText.Tests.ps1 | 47 + src/Tests/Unit/Private/Get-Day.Tests.ps1 | 63 -- .../Unit/Public/Find-GMapPlace.Tests.ps1 | 91 ++ .../Unit/Public/Get-GMapPlaceDetail.Tests.ps1 | 85 ++ .../Unit/Public/Get-HelloWorld.Tests.ps1 | 41 - .../Unit/Public/Invoke-GMapGeoCode.Tests.ps1 | 88 ++ .../Public/Search-GMapNearbyPlace.Tests.ps1 | 150 +++ .../Unit/Public/Search-GMapText.Tests.ps1 | 150 +++ src/Tests/Unit/TestObjects.psm1 | 973 ++++++++++++++++++ src/pwshPlaces.build.ps1 | 10 +- src/pwshPlaces/Imports.ps1 | 447 +++++++- src/pwshPlaces/Private/Format-GMapGeoCode.ps1 | 117 +++ .../Private/Format-GMapNearbyPlace.ps1 | 89 ++ src/pwshPlaces/Private/Format-GMapPlace.ps1 | 91 ++ .../Private/Format-GMapPlaceDetail.ps1 | 116 +++ .../Private/Format-GMapPlaceText.ps1 | 89 ++ src/pwshPlaces/Private/Get-Day.ps1 | 38 - src/pwshPlaces/Public/Find-GMapPlace.ps1 | 308 ++++++ src/pwshPlaces/Public/Get-GMapPlaceDetail.ps1 | 168 +++ src/pwshPlaces/Public/Get-HelloWorld.ps1 | 33 - src/pwshPlaces/Public/Invoke-GMapGeoCode.ps1 | 186 ++++ .../Public/Search-GMapNearbyPlace.ps1 | 327 ++++++ src/pwshPlaces/Public/Search-GMapText.ps1 | 353 +++++++ src/pwshPlaces/pwshPlaces.psd1 | 42 +- 56 files changed, 6505 insertions(+), 381 deletions(-) create mode 100644 .github/workflows/wf_Linux.yml create mode 100644 .github/workflows/wf_MacOS.yml create mode 100644 .github/workflows/wf_Windows.yml create mode 100644 .github/workflows/wf_Windows_Core.yml delete mode 100644 azure-pipelines.yml create mode 100644 docs/Find-GMapPlace.md create mode 100644 docs/Get-GMapPlaceDetail.md create mode 100644 docs/Get-GMapPlaceDetails.md delete mode 100644 docs/Get-HelloWorld.md create mode 100644 docs/GoogleMapsAPI.md create mode 100644 docs/Invoke-GMapGeoCode.md create mode 100644 docs/Search-GMapNearbyPlace.md create mode 100644 docs/Search-GMapText.md create mode 100644 docs/pwshPlaces-FAQ.md create mode 100644 media/gcp_api_services_restrict_api_key.PNG create mode 100644 media/gcp_enable_geocoding_api.PNG create mode 100644 media/gcp_enable_places_api.PNG create mode 100644 media/gcp_google_maps_create_credential_api.PNG create mode 100644 media/gcp_google_maps_platform.PNG create mode 100644 media/gcp_new_project.PNG create mode 100644 media/google_cloud_top_left_navigation_menu.PNG create mode 100644 media/google_maps_platform_maps_api_and_services.PNG delete mode 100644 src/Tests/Infrastructure/SampleInfraTest.Tests.ps1 create mode 100644 src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 create mode 100644 src/Tests/Unit/Private/Format-GMapGeoCode.Tests.ps1 create mode 100644 src/Tests/Unit/Private/Format-GMapNearbyPlace.Tests.ps1 create mode 100644 src/Tests/Unit/Private/Format-GMapPlace.Tests.ps1 create mode 100644 src/Tests/Unit/Private/Format-GMapPlaceDetail.Tests.ps1 create mode 100644 src/Tests/Unit/Private/Format-GMapPlaceText.Tests.ps1 delete mode 100644 src/Tests/Unit/Private/Get-Day.Tests.ps1 create mode 100644 src/Tests/Unit/Public/Find-GMapPlace.Tests.ps1 create mode 100644 src/Tests/Unit/Public/Get-GMapPlaceDetail.Tests.ps1 delete mode 100644 src/Tests/Unit/Public/Get-HelloWorld.Tests.ps1 create mode 100644 src/Tests/Unit/Public/Invoke-GMapGeoCode.Tests.ps1 create mode 100644 src/Tests/Unit/Public/Search-GMapNearbyPlace.Tests.ps1 create mode 100644 src/Tests/Unit/Public/Search-GMapText.Tests.ps1 create mode 100644 src/Tests/Unit/TestObjects.psm1 create mode 100644 src/pwshPlaces/Private/Format-GMapGeoCode.ps1 create mode 100644 src/pwshPlaces/Private/Format-GMapNearbyPlace.ps1 create mode 100644 src/pwshPlaces/Private/Format-GMapPlace.ps1 create mode 100644 src/pwshPlaces/Private/Format-GMapPlaceDetail.ps1 create mode 100644 src/pwshPlaces/Private/Format-GMapPlaceText.ps1 delete mode 100644 src/pwshPlaces/Private/Get-Day.ps1 create mode 100644 src/pwshPlaces/Public/Find-GMapPlace.ps1 create mode 100644 src/pwshPlaces/Public/Get-GMapPlaceDetail.ps1 delete mode 100644 src/pwshPlaces/Public/Get-HelloWorld.ps1 create mode 100644 src/pwshPlaces/Public/Invoke-GMapGeoCode.ps1 create mode 100644 src/pwshPlaces/Public/Search-GMapNearbyPlace.ps1 create mode 100644 src/pwshPlaces/Public/Search-GMapText.ps1 diff --git a/.github/workflows/wf_Linux.yml b/.github/workflows/wf_Linux.yml new file mode 100644 index 0000000..68b2071 --- /dev/null +++ b/.github/workflows/wf_Linux.yml @@ -0,0 +1,48 @@ +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/software-installed-on-github-hosted-runners +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#using-a-specific-shell +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions +# https://github.com/actions/upload-artifact#where-does-the-upload-go +name: pwshPlaces-Linux-Build +on: [push, pull_request] + paths: + - 'src/**' + - '!docs/**' + - '!media/**' + - '!README.md' + - '!LICENSE' + - '!.github' +jobs: + test: + name: Run Tests + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: Check out repository + uses: actions/checkout@v2 + - name: Display the path + shell: pwsh + run: echo ${env:PATH} + - name: Version Display + shell: pwsh + run: $PSVersionTable + - name: Bootstrap + shell: pwsh + run: ./actions_bootstrap.ps1 + - name: Test and Build + shell: pwsh + run: Invoke-Build -File .\src\tbd.build.ps1 + - name: Upload pester results + uses: actions/upload-artifact@v2 + with: + name: pester-results + path: ./src/Artifacts/testOutput + if-no-files-found: warn + - name: Upload zip module archive build + uses: actions/upload-artifact@v2 + with: + name: zip-archive + path: ./src/Archive + if-no-files-found: warn diff --git a/.github/workflows/wf_MacOS.yml b/.github/workflows/wf_MacOS.yml new file mode 100644 index 0000000..b369187 --- /dev/null +++ b/.github/workflows/wf_MacOS.yml @@ -0,0 +1,48 @@ +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/software-installed-on-github-hosted-runners +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#using-a-specific-shell +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions +# https://github.com/actions/upload-artifact#where-does-the-upload-go +name: pwshPlaces-MacOS-Build +on: [push, pull_request] + paths: + - 'src/**' + - '!docs/**' + - '!media/**' + - '!README.md' + - '!LICENSE' + - '!.github' +jobs: + test: + name: Run Tests + runs-on: macOS-latest + strategy: + fail-fast: false + steps: + - name: Check out repository + uses: actions/checkout@v2 + - name: Display the path + shell: pwsh + run: echo ${env:PATH} + - name: Version Display + shell: pwsh + run: $PSVersionTable + - name: Bootstrap + shell: pwsh + run: ./actions_bootstrap.ps1 + - name: Test and Build + shell: pwsh + run: Invoke-Build -File .\src\tbd.build.ps1 + - name: Upload pester results + uses: actions/upload-artifact@v2 + with: + name: pester-results + path: ./src/Artifacts/testOutput + if-no-files-found: warn + - name: Upload zip module archive build + uses: actions/upload-artifact@v2 + with: + name: zip-archive + path: ./src/Archive + if-no-files-found: warn diff --git a/.github/workflows/wf_Windows.yml b/.github/workflows/wf_Windows.yml new file mode 100644 index 0000000..0bb3480 --- /dev/null +++ b/.github/workflows/wf_Windows.yml @@ -0,0 +1,54 @@ +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/software-installed-on-github-hosted-runners +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#using-a-specific-shell +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions +# https://github.com/actions/upload-artifact#where-does-the-upload-go +name: pwshPlaces-Windows-Build +on: [push, pull_request] + paths: + - 'src/**' + - '!docs/**' + - '!media/**' + - '!README.md' + - '!LICENSE' + - '!.github' +jobs: + test: + name: Run Tests + runs-on: windows-latest + strategy: + fail-fast: false + steps: + - name: Check out repository + uses: actions/checkout@v2 + - name: Display the path + shell: powershell + run: echo ${env:PATH} + - name: Version Display + shell: powershell + run: $PSVersionTable + - name: NuGet Latest + shell: powershell + run: Install-PackageProvider -Name "NuGet" -Confirm:$false -Force -Verbose + - name: PowerShellGet Latest + shell: powershell + run: Install-Module -Name PowerShellGet -Repository PSGallery -Force + - name: Bootstrap + shell: powershell + run: ./actions_bootstrap.ps1 + - name: Test and Build + shell: powershell + run: Invoke-Build -File .\src\tbd.build.ps1 + - name: Upload pester results + uses: actions/upload-artifact@v2 + with: + name: pester-results + path: .\src\Artifacts\testOutput + if-no-files-found: warn + - name: Upload zip module archive build + uses: actions/upload-artifact@v2 + with: + name: zip-archive + path: .\src\Archive + if-no-files-found: warn diff --git a/.github/workflows/wf_Windows_Core.yml b/.github/workflows/wf_Windows_Core.yml new file mode 100644 index 0000000..530d175 --- /dev/null +++ b/.github/workflows/wf_Windows_Core.yml @@ -0,0 +1,48 @@ +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/software-installed-on-github-hosted-runners +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#using-a-specific-shell +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions +# https://github.com/actions/upload-artifact#where-does-the-upload-go +name: pwshPlaces-Windows-pwsh-Build +on: [push, pull_request] + paths: + - 'src/**' + - '!docs/**' + - '!media/**' + - '!README.md' + - '!LICENSE' + - '!.github' +jobs: + test: + name: Run Tests + runs-on: windows-latest + strategy: + fail-fast: false + steps: + - name: Check out repository + uses: actions/checkout@v2 + - name: Display the path + shell: pwsh + run: echo ${env:PATH} + - name: Version Display + shell: pwsh + run: $PSVersionTable + - name: Bootstrap + shell: pwsh + run: ./actions_bootstrap.ps1 + - name: Test and Build + shell: pwsh + run: Invoke-Build -File .\src\tbd.build.ps1 + - name: Upload pester results + uses: actions/upload-artifact@v2 + with: + name: pester-results + path: .\src\Artifacts\testOutput + if-no-files-found: warn + - name: Upload zip module archive build + uses: actions/upload-artifact@v2 + with: + name: zip-archive + path: .\src\Archive + if-no-files-found: warn diff --git a/README.md b/README.md index cfcfb48..a6ba0a7 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,86 @@ # pwshPlaces + +[![Minimum Supported PowerShell Version](https://img.shields.io/badge/PowerShell-5.1+-purple.svg)](https://github.com/PowerShell/PowerShell) [![PowerShell Gallery][psgallery-img]][psgallery-site] ![Cross Platform](https://img.shields.io/badge/platform-windows%20%7C%20macos%20%7C%20linux-lightgrey) [![License][license-badge]](LICENSE) + +[psgallery-img]: https://img.shields.io/powershellgallery/dt/pwshPlaces?label=Powershell%20Gallery&logo=powershell +[psgallery-site]: https://www.powershellgallery.com/packages/pwshPlaces +[psgallery-v1]: https://www.powershellgallery.com/packages/pwshPlaces/0.8.1 +[license-badge]: https://img.shields.io/github/license/techthoughts2/pwshPlaces + +Branch | Windows - PowerShell | Windows - pwsh | Linux | MacOS +--- | --- | --- | --- | --- | +main | ![Build Status Windows PowerShell main](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-Windows-PowerShell/badge.svg?branch=main) | ![Build Status Windows pwsh main](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-Windows-pwsh/badge.svg?branch=main) | ![Build Status Linux main](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-Linux/badge.svg?branch=main) | ![Build Status MacOS main](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-MacOS/badge.svg?branch=main) +dev | ![Build Status Windows PowerShell dev](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-Windows-PowerShell/badge.svg?branch=dev) | ![Build Status Windows pwsh dev](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-Windows-pwsh/badge.svg?branch=dev) | ![Build Status Linux dev](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-Linux/badge.svg?branch=dev) | ![Build Status MacOS dev](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-MacOS/badge.svg?branch=dev) + +## Synopsis + +pwshPlaces is a PowerShell module + tbd + + + +## Description + +pwshPlaces enables you to + +* TBD +* TBD +* TBD +* TBD + +[pwshPlaces](docs/pwshPlaces.md) provides the following functions: + +* [Find-GMapPlace](docs/Find-GMapPlace.md) +* [Invoke-GMapGeoCode](docs/Invoke-GMapGeoCode.md) +* [Search-GMapNearbyPlace](docs/Search-GMapNearbyPlace.md) +* [Search-GMapText](docs/Search-GMapText.md) + +## Why + +TBD + +## Installation + +### Prerequisites + +Set those API Keys in the PoshGMaps.psm1 file to the appropriate variables. + +### Install pwshPlaces + +```powershell +# Install pwshPlaces from the PowerShell Gallery +Install-Module -Name pwshPlaces -Repository PSGallery -Scope CurrentUser +``` + +## Quick start + +```powershell +# TBD +TBD + +``` + +### Potential uses + +I am going to this address and want to know local businesses around it + +search for place and get lat/long + +search for businesses close by + +## FAQ + +**[pwshPlaces - FAQ](docs/pwshPlaces-FAQ.md)** + +## Author + +[Jake Morrison](https://twitter.com/JakeMorrison) - [https://www.techthoughts.info/](https://www.techthoughts.info/) + +## Notes + +This PowerShell project was created with [Catesta](https://github.com/techthoughts2/Catesta). + +## Changelog + +Reference the [Changelog](.github/CHANGELOG.md) diff --git a/actions_bootstrap.ps1 b/actions_bootstrap.ps1 index 31f4b78..2d66092 100644 --- a/actions_bootstrap.ps1 +++ b/actions_bootstrap.ps1 @@ -12,17 +12,17 @@ $modulesToInstall = [System.Collections.ArrayList]::new() # https://github.com/pester/Pester $null = $modulesToInstall.Add(([PSCustomObject]@{ ModuleName = 'Pester' - ModuleVersion = '5.2.2' + ModuleVersion = '5.3.1' })) # https://github.com/nightroman/Invoke-Build $null = $modulesToInstall.Add(([PSCustomObject]@{ ModuleName = 'InvokeBuild' - ModuleVersion = '5.8.0' + ModuleVersion = '5.8.4' })) # https://github.com/PowerShell/PSScriptAnalyzer $null = $modulesToInstall.Add(([PSCustomObject]@{ ModuleName = 'PSScriptAnalyzer' - ModuleVersion = '1.19.1' + ModuleVersion = '1.20.0' })) # https://github.com/PowerShell/platyPS # older version used due to: https://github.com/PowerShell/platyPS/issues/457 diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 9ea0aba..0000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,120 +0,0 @@ - -jobs: - # https://docs.microsoft.com/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema - # https://docs.microsoft.com/azure/devops/pipelines/agents/hosted?view=azure-devops#use-a-microsoft-hosted-agent - # https://docs.microsoft.com/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml - # https://docs.microsoft.com/azure/devops/pipelines/tasks/test/publish-code-coverage-results?view=azure-devops - # https://docs.microsoft.com/azure/devops/pipelines/artifacts/build-artifacts?view=azure-devops&tabs=yaml - - job: build_ps_WinLatest - pool: - vmImage: windows-latest - steps: - - powershell: | - $PSVersionTable - Install-PackageProvider -Name "NuGet" -Confirm:$false -Force -Verbose - Install-Module -Name PowerShellGet -Repository PSGallery -Force - .\actions_bootstrap.ps1 - Invoke-Build -File $(Build.SourcesDirectory)\src\pwshPlaces.build.ps1 - displayName: 'Build and Test - Windows PowerShell' - - task: PublishTestResults@2 - inputs: - testRunner: 'NUnit' - testResultsFiles: '**\Artifacts\testOutput\PesterTests.xml' - testRunTitle: 'ps_winLatest' - failTaskOnFailedTests: true - displayName: "Publish Unit Test Results - Windows PowerShell" - - task: PublishCodeCoverageResults@1 - inputs: - summaryFileLocation: '**\Artifacts\ccReport\CodeCoverage.xml' - pathToSources: '$(System.DefaultWorkingDirectory)\src\Artifacts\ccReport' - failIfCoverageEmpty: false - displayName: "Publish Unit Test Code Coverage - Windows PowerShell" - condition: and(in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues', 'Failed'), eq(variables['System.PullRequest.IsFork'], false)) - - task: PublishBuildArtifacts@1 - inputs: - pathToPublish: '$(System.DefaultWorkingDirectory)\src\Archive' - artifactName: pwshPlaces-Archive - - - job: build_pwsh_WinLatest - pool: - vmImage: windows-latest - steps: - - pwsh: | - $PSVersionTable - .\actions_bootstrap.ps1 - Invoke-Build -File $(Build.SourcesDirectory)\src\pwshPlaces.build.ps1 - displayName: 'Build and Test - Windows pwsh' - - task: PublishTestResults@2 - inputs: - testRunner: 'NUnit' - testResultsFiles: '**\Artifacts\testOutput\PesterTests.xml' - testRunTitle: 'pwsh_winLatest' - failTaskOnFailedTests: true - displayName: "Publish Unit Test Results - Windows pwsh" - - task: PublishCodeCoverageResults@1 - inputs: - summaryFileLocation: '**\Artifacts\ccReport\CodeCoverage.xml' - pathToSources: '$(System.DefaultWorkingDirectory)\src\Artifacts\ccReport' - failIfCoverageEmpty: false - displayName: "Publish Unit Test Code Coverage - Windows pwsh" - condition: and(in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues', 'Failed'), eq(variables['System.PullRequest.IsFork'], false)) - - task: PublishBuildArtifacts@1 - inputs: - pathToPublish: '$(System.DefaultWorkingDirectory)\src\Archive' - artifactName: pwshPlaces-Archive - - - job: build_pwsh_ubuntuLatest - pool: - vmImage: ubuntu-latest - steps: - - script: | - sudo dpkg -i powershell_6.2.0-1.ubuntu.16.04_amd64.deb - sudo apt-get install -f - displayName: 'Install PowerShell Core' - - script: | - pwsh -c '$PSVersionTable;.\actions_bootstrap.ps1;Invoke-Build -File $(Build.SourcesDirectory)/src/pwshPlaces.build.ps1' - displayName: 'Build and Test - Linux' - - task: PublishTestResults@2 - inputs: - testRunner: 'NUnit' - testResultsFiles: '**/Artifacts/testOutput/PesterTests.xml' - testRunTitle: 'pwsh_ubuntuLatest' - failTaskOnFailedTests: true - displayName: "Publish Unit Test Results - Linux" - - task: PublishCodeCoverageResults@1 - inputs: - summaryFileLocation: '**/Artifacts/ccReport/CodeCoverage.xml' - pathToSources: '$(System.DefaultWorkingDirectory)/src/Artifacts/ccReport' - failIfCoverageEmpty: false - displayName: "Publish Unit Test Code Coverage - Linux" - condition: and(in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues', 'Failed'), eq(variables['System.PullRequest.IsFork'], false)) - - task: PublishBuildArtifacts@1 - inputs: - pathToPublish: '$(System.DefaultWorkingDirectory)/src/Archive' - artifactName: pwshPlaces-Archive - - - job: build_pwsh_macOSLatest - pool: - vmImage: macOS-latest - steps: - - script: | - pwsh -c '$PSVersionTable;.\actions_bootstrap.ps1;Invoke-Build -File $(Build.SourcesDirectory)/src/pwshPlaces.build.ps1' - displayName: 'Build and Test - macOS' - - task: PublishTestResults@2 - inputs: - testRunner: 'NUnit' - testResultsFiles: '**/Artifacts/testOutput/PesterTests.xml' - testRunTitle: 'pwsh_macOSLatest' - failTaskOnFailedTests: true - displayName: "Publish Unit Test Results - macOS" - - task: PublishCodeCoverageResults@1 - inputs: - summaryFileLocation: '**/Artifacts/ccReport/CodeCoverage.xml' - pathToSources: '$(System.DefaultWorkingDirectory)/src/Artifacts/ccReport' - failIfCoverageEmpty: false - displayName: "Publish Unit Test Code Coverage - macOS" - condition: and(in(variables['Agent.JobStatus'], 'Succeeded', 'SucceededWithIssues', 'Failed'), eq(variables['System.PullRequest.IsFork'], false)) - - task: PublishBuildArtifacts@1 - inputs: - pathToPublish: '$(System.DefaultWorkingDirectory)/src/Archive' - artifactName: pwshPlaces-Archive diff --git a/docs/Find-GMapPlace.md b/docs/Find-GMapPlace.md new file mode 100644 index 0000000..3a4e478 --- /dev/null +++ b/docs/Find-GMapPlace.md @@ -0,0 +1,409 @@ +--- +external help file: pwshPlaces-help.xml +Module Name: pwshPlaces +online version: https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Find-GMapPlace.md +schema: 2.0.0 +--- + +# Find-GMapPlace + +## SYNOPSIS +Find Place request takes a text input and returns a place. +The input can be any kind of Places text data, such as a name, address, or phone number. + +## SYNTAX + +### textquery (Default) +``` +Find-GMapPlace -Query [-Contact] [-Atmosphere] [-Language ] [] +``` + +### Rectangle +``` +Find-GMapPlace [-Query ] -SouthLatitude -WestLongitude -NorthLatitude + -EastLongitude [-Contact] [-Atmosphere] [-Language ] [] +``` + +### Circle +``` +Find-GMapPlace [-Query ] [-CircleLatitude ] [-CircleLongitude ] + [-CircleRadius ] [-Contact] [-Atmosphere] [-Language ] [] +``` + +### Point +``` +Find-GMapPlace [-Query ] [-PointLatitude ] [-PointLongitude ] [-Contact] [-Atmosphere] + [-Language ] [] +``` + +## DESCRIPTION +Performs a find place request with provided parameters. +A text search is performed unless a properly formatted phone number is provided in which case +a phonenumber search is completed. +By default the location bias and language is IP based. +Location bias and language can be controlled via parameters. +The information returned in a normal +call contains all basic field types. +Additional field types including contact and atmosphere information +can be called for but these carry an additional cost. +The Find Place return does not return +all fields of these more expensive calls and has a limited return. +See notes for details. + +## EXAMPLES + +### EXAMPLE 1 +``` +Find-GMapPlace -Query "Krause's cafe" +``` + +Returns place information for the query location biased by IP. + +### EXAMPLE 2 +``` +Find-GMapPlace -Query "Krause's cafe" -Language es +``` + +Returns place information for the query location biased by IP and returns results in Spanish. + +### EXAMPLE 3 +``` +Find-GMapPlace -Query '+18306252807' +``` + +Returns place information for the query location biased by IP. + +### EXAMPLE 4 +``` +Find-GMapPlace -Query 'cafe' -PointLatitude '29.7049806' -PointLongitude '-98.068343' +``` + +Returns place information for the query location biased by provided lat/long point. + +### EXAMPLE 5 +``` +Find-GMapPlace -Query 'cafe' -PointLatitude '29.7049806' -PointLongitude '-98.068343' -Language en +``` + +Returns place information for the query location biased by provided lat/long point and returns results in English. + +### EXAMPLE 6 +``` +Find-GMapPlace -Query 'cafe' -CircleLatitude '29.7049806' -CircleLongitude '-98.068343' -CircleRadius '8046' +``` + +Returns place information for the query location biased by circle lat/long/radius. + +### EXAMPLE 7 +``` +Find-GMapPlace -Query 'cafe' -SouthLatitude '39.8592387' -WestLongitude '-75.295486' -NorthLatitude '40.0381942' -EastLongitude '-75.0064087' +``` + +Returns place information for the query location biased by rectangular two lat/lng pairs in decimal degrees, representing the south/west and north/east points of a rectangle. + +### EXAMPLE 8 +``` +Find-GMapPlace -Query '+18306252807' -PointLatitude '29.7049806' -PointLongitude '-98.068343' -Contact -Atmosphere -Language en +``` + +Returns place information for the query location biased by provided lat/long point with additional Contact and Atmosphere fields with results in Enlgish. + +### EXAMPLE 9 +``` +$findGMapPlaceSplat = @{ + Query = '+18306252807' + PointLatitude = '29.7049806' + PointLongitude = '-98.068343' + Contact = $true + Atmosphere = $true + Language = 'en' +} +Find-GMapPlace @findGMapPlaceSplat +``` + +Returns place information for the query location biased by provided lat/long point with additional Contact and Atmosphere fields with results in Enlgish. + +## PARAMETERS + +### -Query +Text input that identifies the search target, such as a name, address, or phone number. +Phone numbers must be in international format (prefixed by a plus sign ("+"), followed by the country code, then the phone number itself) + +```yaml +Type: String +Parameter Sets: textquery +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +```yaml +Type: String +Parameter Sets: Rectangle, Circle, Point +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PointLatitude +Prefer results in a specified area by specifying a single coordinate for the north-south position of a point on the Earth's surface. + +```yaml +Type: String +Parameter Sets: Point +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PointLongitude +Prefer results in a specified area by specifying a single coordinate for the east-west position of a point on the Earths surface. + +```yaml +Type: String +Parameter Sets: Point +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -CircleLatitude +Prefer results in a specified area by specifying a radius plus lat/long - north-south position of a point on the Earth's surface. + +```yaml +Type: String +Parameter Sets: Circle +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -CircleLongitude +Prefer results in a specified area by specifying a radius plus lat/long - east-west position of a point on the Earths surface. + +```yaml +Type: String +Parameter Sets: Circle +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -CircleRadius +Prefer results in a specified area by specifying a radius plus lat/long - radius in meters + +```yaml +Type: String +Parameter Sets: Circle +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SouthLatitude +Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - south latitude + +```yaml +Type: String +Parameter Sets: Rectangle +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WestLongitude +Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - west longitude + +```yaml +Type: String +Parameter Sets: Rectangle +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NorthLatitude +Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - north latitude + +```yaml +Type: String +Parameter Sets: Rectangle +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -EastLongitude +Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - east longitude + +```yaml +Type: String +Parameter Sets: Rectangle +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Contact +Returns contact related information about the result - contact fields are billed at a higher rate. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Atmosphere +Returns atmosphere related information including reviews and pricing about the result - atmosphere fields are billed at a higher rate. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Language +The language in which to return results. + +```yaml +Type: languages +Parameter Sets: (All) +Aliases: +Accepted values: af, sq, am, ar, hy, az, eu, be, bn, bs, bg, my, ca, zh, hr, cs, da, nl, en, et, fa, fi, fil, fr, ka, de, el, iw, hi, hu, is, id, it, ja, kn, kk, km, ko, ky, lo, lv, lt, mk, ms, ml, mr, mn, ne, no, pl, pt, pa, ro, ru, sr, sk, es, sw, ta, te, th, uk, ur, uz, vi, zu + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### Output from this cmdlet (if any) +## NOTES +Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + +Latitude and Longitude information can be easily retrieved using Invoke-GMapGeoCode + +If you provide faulty lat/long info the API call will default back to IP based locationbias. + +Required parameters + input + Text input that identifies the search target, such as a name, address, or phone number. +The input must be a string. + inputtype + The type of input. +This can be one of either textquery or phonenumber. + Phone numbers must be in international format (prefixed by a plus sign ("+"), followed by the country code, then the phone number itself) +Optional parameters + fields + Billing Categories + Basic - no charge + Contact + Atmosphere + language + locationbias + Prefer results in a specified area, by specifying either a radius plus lat/lng, or two lat/lng pairs representing the points of a rectangle. +If this parameter is not specified, the API uses IP address biasing by default. + +IP bias: Instructs the API to use IP address biasing. +Pass the string ipbias (this option has no additional parameters). +Point: A single lat/lng coordinate. +Use the following format: point:lat,lng. +Circular: A string specifying radius in meters, plus lat/lng in decimal degrees. +Use the following format: circle:radius@lat,lng. +Rectangular: A string specifying two lat/lng pairs in decimal degrees + +Example: + https://maps.googleapis.com/maps/api/place/findplacefromtext/json?fields=formatted_address%2Cname%2Crating%2Copening_hours%2Cgeometry&input=Museum%20of%20Contemporary%20Art%20Australia&inputtype=textquery&key=YOUR_API_KEY + +Caution: Place Search requests and Place Details requests do not return the same fields. +Place Search requests return a subset of the fields that are returned by Place Details requests. +If the field you want is not returned by Place Search, you can use Place Search to get a place_id, +then use that Place ID to make a Place Details request. +^ this essentially means you are better served with the find by using basic fields only. +If you need additional information make a subsequent Place Details API call. + +Don't use the Contact or Atmosphere parameters of this function. +They aren't worth it. +If you need more detail use Get-GMapPlaceDetail + +This function includes Google Maps features and content; use of Google Maps features and content is subject to the terms of service and Google privacy (linked below). + +## RELATED LINKS + +[https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Find-GMapPlace.md](https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Find-GMapPlace.md) + +[https://developers.google.com/maps/documentation/places/web-service/search-find-place](https://developers.google.com/maps/documentation/places/web-service/search-find-place) + +[https://maps.googleapis.com/maps/api/place/findplacefromtext/output?parameters](https://maps.googleapis.com/maps/api/place/findplacefromtext/output?parameters) + +[https://developers.google.com/maps/faq#languagesupport](https://developers.google.com/maps/faq#languagesupport) + +[https://cloud.google.com/maps-platform/terms/](https://cloud.google.com/maps-platform/terms/) + +[https://www.google.com/policies/privacy/](https://www.google.com/policies/privacy/) + diff --git a/docs/Get-GMapPlaceDetail.md b/docs/Get-GMapPlaceDetail.md new file mode 100644 index 0000000..a5363d1 --- /dev/null +++ b/docs/Get-GMapPlaceDetail.md @@ -0,0 +1,187 @@ +--- +external help file: pwshPlaces-help.xml +Module Name: pwshPlaces +online version: https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Get-GMapPlaceDetail.md +schema: 2.0.0 +--- + +# Get-GMapPlaceDetail + +## SYNOPSIS +Request more details about a particular establishment or point of interest + +## SYNTAX + +``` +Get-GMapPlaceDetail -PlaceID [-Contact] [-Atmosphere] [-Language ] [-RegionBias ] + [] +``` + +## DESCRIPTION +Place Details request returns more comprehensive information about the indicated place such as its complete address, phone number, website, user rating and reviews. + +## EXAMPLES + +### EXAMPLE 1 +``` +Get-GMapPlaceDetail -PlaceID 'ChIJE43gTHK9XIYRleSxiXqF6GU' +``` + +Returns detailed place information about provided place ID. + +### EXAMPLE 2 +``` +Get-GMapPlaceDetail -PlaceID 'ChIJE43gTHK9XIYRleSxiXqF6GU' -Contact +``` + +Returns detailed place information about provided place ID including detailed contact information. + +### EXAMPLE 3 +``` +Get-GMapPlaceDetail -PlaceID 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' -Contact -Atmosphere -Language en +``` + +Returns detailed place information about provided place ID including detailed contact, review, rating, and pricing information. +Results are returned in English. + +### EXAMPLE 4 +``` +$getGMapPlaceDetailsSplat = @{ + PlaceID = 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + Contact = $true + Atmosphere = $true + Language = 'en' +} +Get-GMapPlaceDetail @getGMapPlaceDetailsSplat +``` + +Returns detailed place information about provided place ID including detailed contact, review, rating, and pricing information. +Results are returned in English. + +## PARAMETERS + +### -PlaceID +A textual identifier that uniquely identifies a place + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Contact +Returns contact related information about the result - contact fields are billed at a higher rate. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Atmosphere +Returns atmosphere related information including reviews and pricing about the result - atmosphere fields are billed at a higher rate. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Language +The language in which to return results. + +```yaml +Type: languages +Parameter Sets: (All) +Aliases: +Accepted values: af, sq, am, ar, hy, az, eu, be, bn, bs, bg, my, ca, zh, hr, cs, da, nl, en, et, fa, fi, fil, fr, ka, de, el, iw, hi, hu, is, id, it, ja, kn, kk, km, ko, ky, lo, lv, lt, mk, ms, ml, mr, mn, ne, no, pl, pt, pa, ro, ru, sr, sk, es, sw, ta, te, th, uk, ur, uz, vi, zu + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RegionBias +The region code, specified as a ccTLD ("top-level domain") two-character value. + +```yaml +Type: ccTLD +Parameter Sets: (All) +Aliases: +Accepted values: ac, ad, ae, af, ag, ai, al, am, ao, aq, ar, as, at, au, aw, ax, az, ba, bb, bd, be, bf, bg, bh, bi, bj, bm, bn, bo, br, bs, bt, bv, bw, by, bz, ca, cc, cd, cf, cg, ch, ci, ck, cl, cm, cn, co, cr, cu, cv, cw, cx, cy, cz, de, dj, dk, dm, do, dz, ec, ee, eg, er, es, et, eu, fi, fj, fk, fm, fo, fr, ga, gb, gd, ge, gf, gg, gh, gi, gl, gm, gn, gp, gq, gr, gs, gt, gu, gw, gy, hk, hm, hn, hr, ht, hu, id, ie, il, im, in, io, iq, ir, is, it, je, jm, jo, jp, ke, kg, kh, ki, km, kn, kp, kr, kw, ky, kz, la, lb, lc, li, lk, lr, ls, lt, lu, lv, ly, ma, mc, md, me, mg, mh, mk, ml, mm, mn, mo, mp, mq, mr, ms, mt, mu, mv, mw, mx, my, mz, na, nc, ne, nf, ng, ni, nl, no, np, nr, nu, nz, om, pa, pe, pf, pg, ph, pk, pl, pm, pn, pr, ps, pt, pw, py, qa, re, ro, rs, ru, rw, sa, sb, sc, sd, se, sg, sh, si, sj, sk, sl, sm, sn, so, sr, ss, st, su, sv, sx, sy, sz, tc, td, tf, tg, th, tj, tk, tl, tm, tn, to, tr, tt, tv, tw, tz, ua, ug, uk, us, uy, uz, va, vc, ve, vg, vi, vn, vu, wf, ws, ye, yt, za, zm, zw + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### Output from this cmdlet (if any) +## NOTES +Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + +Latitude and Longitude information can be easily retrieved using Invoke-GMapGeoCode + +If you provide faulty lat/long info the API call will default back to IP based locationbias. + +Required parameters + place_id + A textual identifier that uniquely identifies a place +Optional parameters + fields + Billing Categories + Basic - no charge + address_component, adr_address, business_status, formatted_address, geometry, icon, icon_mask_base_uri, icon_background_color, name, permanently_closed (deprecated), photo, place_id, plus_code, type, url, utc_offset, vicinity + Contact + formatted_phone_number, international_phone_number, opening_hours, website + Atmosphere + price_level, rating, review, user_ratings_total. + language + region + +Example: + https://maps.googleapis.com/maps/api/place/details/json?fields=name%2Crating%2Cformatted_phone_number&place_id=ChIJN1t_tDeuEmsRUsoyG83frY4&key=YOUR_API_KEY + +This function includes Google Maps features and content; use of Google Maps features and content is subject to the terms of service and Google privacy (linked below). + +## RELATED LINKS + +[https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Get-GMapPlaceDetail.md](https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Get-GMapPlaceDetail.md) + +[https://developers.google.com/maps/documentation/places/web-service/details](https://developers.google.com/maps/documentation/places/web-service/details) + +[https://developers.google.com/maps/faq#languagesupport](https://developers.google.com/maps/faq#languagesupport) + +[https://cloud.google.com/maps-platform/terms/](https://cloud.google.com/maps-platform/terms/) + +[https://www.google.com/policies/privacy/](https://www.google.com/policies/privacy/) + diff --git a/docs/Get-GMapPlaceDetails.md b/docs/Get-GMapPlaceDetails.md new file mode 100644 index 0000000..a5363d1 --- /dev/null +++ b/docs/Get-GMapPlaceDetails.md @@ -0,0 +1,187 @@ +--- +external help file: pwshPlaces-help.xml +Module Name: pwshPlaces +online version: https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Get-GMapPlaceDetail.md +schema: 2.0.0 +--- + +# Get-GMapPlaceDetail + +## SYNOPSIS +Request more details about a particular establishment or point of interest + +## SYNTAX + +``` +Get-GMapPlaceDetail -PlaceID [-Contact] [-Atmosphere] [-Language ] [-RegionBias ] + [] +``` + +## DESCRIPTION +Place Details request returns more comprehensive information about the indicated place such as its complete address, phone number, website, user rating and reviews. + +## EXAMPLES + +### EXAMPLE 1 +``` +Get-GMapPlaceDetail -PlaceID 'ChIJE43gTHK9XIYRleSxiXqF6GU' +``` + +Returns detailed place information about provided place ID. + +### EXAMPLE 2 +``` +Get-GMapPlaceDetail -PlaceID 'ChIJE43gTHK9XIYRleSxiXqF6GU' -Contact +``` + +Returns detailed place information about provided place ID including detailed contact information. + +### EXAMPLE 3 +``` +Get-GMapPlaceDetail -PlaceID 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' -Contact -Atmosphere -Language en +``` + +Returns detailed place information about provided place ID including detailed contact, review, rating, and pricing information. +Results are returned in English. + +### EXAMPLE 4 +``` +$getGMapPlaceDetailsSplat = @{ + PlaceID = 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + Contact = $true + Atmosphere = $true + Language = 'en' +} +Get-GMapPlaceDetail @getGMapPlaceDetailsSplat +``` + +Returns detailed place information about provided place ID including detailed contact, review, rating, and pricing information. +Results are returned in English. + +## PARAMETERS + +### -PlaceID +A textual identifier that uniquely identifies a place + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Contact +Returns contact related information about the result - contact fields are billed at a higher rate. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Atmosphere +Returns atmosphere related information including reviews and pricing about the result - atmosphere fields are billed at a higher rate. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Language +The language in which to return results. + +```yaml +Type: languages +Parameter Sets: (All) +Aliases: +Accepted values: af, sq, am, ar, hy, az, eu, be, bn, bs, bg, my, ca, zh, hr, cs, da, nl, en, et, fa, fi, fil, fr, ka, de, el, iw, hi, hu, is, id, it, ja, kn, kk, km, ko, ky, lo, lv, lt, mk, ms, ml, mr, mn, ne, no, pl, pt, pa, ro, ru, sr, sk, es, sw, ta, te, th, uk, ur, uz, vi, zu + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RegionBias +The region code, specified as a ccTLD ("top-level domain") two-character value. + +```yaml +Type: ccTLD +Parameter Sets: (All) +Aliases: +Accepted values: ac, ad, ae, af, ag, ai, al, am, ao, aq, ar, as, at, au, aw, ax, az, ba, bb, bd, be, bf, bg, bh, bi, bj, bm, bn, bo, br, bs, bt, bv, bw, by, bz, ca, cc, cd, cf, cg, ch, ci, ck, cl, cm, cn, co, cr, cu, cv, cw, cx, cy, cz, de, dj, dk, dm, do, dz, ec, ee, eg, er, es, et, eu, fi, fj, fk, fm, fo, fr, ga, gb, gd, ge, gf, gg, gh, gi, gl, gm, gn, gp, gq, gr, gs, gt, gu, gw, gy, hk, hm, hn, hr, ht, hu, id, ie, il, im, in, io, iq, ir, is, it, je, jm, jo, jp, ke, kg, kh, ki, km, kn, kp, kr, kw, ky, kz, la, lb, lc, li, lk, lr, ls, lt, lu, lv, ly, ma, mc, md, me, mg, mh, mk, ml, mm, mn, mo, mp, mq, mr, ms, mt, mu, mv, mw, mx, my, mz, na, nc, ne, nf, ng, ni, nl, no, np, nr, nu, nz, om, pa, pe, pf, pg, ph, pk, pl, pm, pn, pr, ps, pt, pw, py, qa, re, ro, rs, ru, rw, sa, sb, sc, sd, se, sg, sh, si, sj, sk, sl, sm, sn, so, sr, ss, st, su, sv, sx, sy, sz, tc, td, tf, tg, th, tj, tk, tl, tm, tn, to, tr, tt, tv, tw, tz, ua, ug, uk, us, uy, uz, va, vc, ve, vg, vi, vn, vu, wf, ws, ye, yt, za, zm, zw + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### Output from this cmdlet (if any) +## NOTES +Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + +Latitude and Longitude information can be easily retrieved using Invoke-GMapGeoCode + +If you provide faulty lat/long info the API call will default back to IP based locationbias. + +Required parameters + place_id + A textual identifier that uniquely identifies a place +Optional parameters + fields + Billing Categories + Basic - no charge + address_component, adr_address, business_status, formatted_address, geometry, icon, icon_mask_base_uri, icon_background_color, name, permanently_closed (deprecated), photo, place_id, plus_code, type, url, utc_offset, vicinity + Contact + formatted_phone_number, international_phone_number, opening_hours, website + Atmosphere + price_level, rating, review, user_ratings_total. + language + region + +Example: + https://maps.googleapis.com/maps/api/place/details/json?fields=name%2Crating%2Cformatted_phone_number&place_id=ChIJN1t_tDeuEmsRUsoyG83frY4&key=YOUR_API_KEY + +This function includes Google Maps features and content; use of Google Maps features and content is subject to the terms of service and Google privacy (linked below). + +## RELATED LINKS + +[https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Get-GMapPlaceDetail.md](https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Get-GMapPlaceDetail.md) + +[https://developers.google.com/maps/documentation/places/web-service/details](https://developers.google.com/maps/documentation/places/web-service/details) + +[https://developers.google.com/maps/faq#languagesupport](https://developers.google.com/maps/faq#languagesupport) + +[https://cloud.google.com/maps-platform/terms/](https://cloud.google.com/maps-platform/terms/) + +[https://www.google.com/policies/privacy/](https://www.google.com/policies/privacy/) + diff --git a/docs/Get-HelloWorld.md b/docs/Get-HelloWorld.md deleted file mode 100644 index ced92af..0000000 --- a/docs/Get-HelloWorld.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -external help file: pwshPlaces-help.xml -Module Name: pwshPlaces -online version: -schema: 2.0.0 ---- - -# Get-HelloWorld - -## SYNOPSIS -Short description - -## SYNTAX - -``` -Get-HelloWorld [] -``` - -## DESCRIPTION -Long description - -## EXAMPLES - -### EXAMPLE 1 -``` -Example of how to use this cmdlet -``` - -### EXAMPLE 2 -``` -Another example of how to use this cmdlet -``` - -## PARAMETERS - -### CommonParameters -This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. -For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). - -## INPUTS - -## OUTPUTS - -### Output from this cmdlet (if any) -## NOTES -General notes - -## RELATED LINKS diff --git a/docs/GoogleMapsAPI.md b/docs/GoogleMapsAPI.md new file mode 100644 index 0000000..fed35b7 --- /dev/null +++ b/docs/GoogleMapsAPI.md @@ -0,0 +1,133 @@ +# Google Maps API + +***[pwshPlaces](https://github.com/techthoughts2/pwshPlaces)** includes Google Maps features and content; use of Google Maps features and content is subject to the [terms of service](https://cloud.google.com/maps-platform/terms/) and [Google privacy policy](https://www.google.com/policies/privacy/).* + +- [Google Maps API](#google-maps-api) + - [Google Maps API Key](#google-maps-api-key) + - [How to get a Google Maps API Key](#how-to-get-a-google-maps-api-key) + - [1. Create a new GCP project](#1-create-a-new-gcp-project) + - [2. Enable the Places API and the Geocoding API](#2-enable-the-places-api-and-the-geocoding-api) + - [3. Create API Key](#3-create-api-key) + - [4. Restrict to places API](#4-restrict-to-places-api) + - [5. Enable Billing on the Google Cloud project](#5-enable-billing-on-the-google-cloud-project) + - [Monitoring Google Maps API usage](#monitoring-google-maps-api-usage) + - [Understanding Google Maps API pricing](#understanding-google-maps-api-pricing) + - [API Caching](#api-caching) + +## Google Maps API Key + +**[pwshPlaces](https://github.com/techthoughts2/pwshPlaces)** requires a Google API key to run Google maps functions. + +To utilize all of the functions of pwshPlaces you must: + +- Create a Google Maps API with both the Places and Geocoding APIs enabled and enable billing on the project. + +You can read more about the Google Maps API in the links below: + +- [Google Maps Platform Documentation](https://developers.google.com/maps/documentation#places) +- [Places API](https://developers.google.com/maps/documentation/places/web-service/overview) +- [Places API Support](https://developers.google.com/maps/documentation/places/web-service/support) + +### How to get a Google Maps API Key + +Official documentation link for creating a Google Maps API Key: + +- [Google Maps Creating API Keys](https://developers.google.com/maps/documentation/places/web-service/get-api-key#creating-api-keys) + +Google Maps API Keys are created and managed through Google Cloud Platform (GCP). The GCP console is constantly changing so some of the steps below may look slightly different. Here is what you need to accomplish at a high level: + +#### 1. Create a new GCP project + +Log into your [GCP console](https://console.cloud.google.com/home/) and create a new project: +![alt text](../media/gcp_new_project.PNG 'Title') + +#### 2. Enable the Places API and the Geocoding API + +- Top left Navigation Menu + - Other Google Solutions + - Google Maps Platform + - Maps APIs and Services + - Places API - --Enable-- +- Google Maps Platform + - APIs + - Additional APIs + - Geocoding API - --Enable-- + +![Google Cloud (GCP) Top Left Navigation Menu](../media/google_cloud_top_left_navigation_menu.PNG 'GCP Navigation Menu') +![Google Cloud (GCP) Google Maps Platform](../media/gcp_google_maps_platform.PNG 'GCP Google Maps Platform') +![Google Cloud (GCP) Google Maps Platform Maps APIs and Services](../media/google_maps_platform_maps_api_and_services.PNG 'Google Maps Platform Maps APIs and Services') +![Google Maps Places API](../media/gcp_enable_places_api.PNG 'Google Maps Places API') +![Google Maps Geocoding API](../media/gcp_enable_geocoding_api.PNG 'Google Maps Geocoding API') + +#### 3. Create API Key + +- Google Maps Platform + - Credentials + - Create Credentials + - API key + +![GCP Google Maps Platform Credentials](../media/gcp_google_maps_create_credential_api.PNG 'Google Maps Platform Credentials') + +#### 4. Restrict to places API + +Restrict API access to just the two enabled + +- Google Maps Platform + - Credentials + - Restrict API to secure account + +![GCP API Restrict Access](../media/gcp_api_services_restrict_api_key.PNG 'API Restrict Access') + +#### 5. Enable Billing on the Google Cloud project + +You must [enable billing](https://console.cloud.google.com/project/_/billing/enable) on the Google Cloud Project. + +-Note: Even though you need to enable billing keep in mind the following:- + +> For most of our users, the $200 monthly credit is enough to support their needs. You can also set daily quotas to protect against unexpected increases. + +### Monitoring Google Maps API usage + +Visit the [GCP API dashboard](https://console.developers.google.com/apis/dashboard). From the ‘Select a Project’ drop-down menu, select or create the project. + +Additional reading: + +- [Monitoring API usage](https://cloud.google.com/apis/docs/monitoring) +- [Monitor Google API usage programmatically?](https://stackoverflow.com/questions/62511759/monitor-google-api-usage-programmatically) + +### Understanding Google Maps API pricing + +- [Google Maps Platform pricing](https://cloud.google.com/maps-platform/pricing) +- [Places product API pricing](https://developers.google.com/maps/billing/gmp-billing#places-product) +- [Places API Usage and Billing](https://developers.google.com/maps/documentation/places/web-service/usage-and-billing) + - [Places SKU breakdown cost data](https://developers.google.com/maps/billing/gmp-billing#basic-data) + +## API Caching + +IAW with the [terms of service](https://cloud.google.com/maps-platform/terms/): + +> Pre-Fetching, Caching, or Storage of Content +Applications using the Places API are bound by the Google Maps Platform Terms of Service. Section 3.2.3(a) and (b) of the terms states that you must not pre-fetch, index, store, or cache any Content except under the limited conditions stated in the terms. +Note that the place ID, used to uniquely identify a place, is exempt from the caching restriction. You can therefore store place ID values indefinitely. The place ID is returned in the place_id field in Places API responses. + +This means that doing something like the following is not permitted: + +```powershell +#-------------------------------------------------------------- +# scrape and locally cache up to 60 local restaurants +Import-Module Convert +Import-Module pwshPlaces + +$scrapePath = $env:Temp + +$locale = Invoke-GMapGeoCode -Address 'New Braunfels' + +$areaRestaraunts = Search-GMapNearbyPlace -Latitude $locale.Latitude -Longitude $locale.Longitude -Radius 10000 -RankByProminence -Type restaurant -AllSearchResults + +ConvertTo-Clixml -InputObject $areaRestaraunts -Depth 100 | Out-File "$scrapePath\localRestaraunts.xml" +#-------------------------------------------------------------- +# where should we eat today? +$myLocalRestaurants = Get-Content -Path "$scrapePath\localRestaraunts.xml" -Raw | ConvertFrom-Clixml + +Get-Random $myLocalRestaurants +``` diff --git a/docs/Invoke-GMapGeoCode.md b/docs/Invoke-GMapGeoCode.md new file mode 100644 index 0000000..dc26f6a --- /dev/null +++ b/docs/Invoke-GMapGeoCode.md @@ -0,0 +1,221 @@ +--- +external help file: pwshPlaces-help.xml +Module Name: pwshPlaces +online version: https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Invoke-GMapGeoCode.md +schema: 2.0.0 +--- + +# Invoke-GMapGeoCode + +## SYNOPSIS +Engages Geocoding API to return address and geographic coordinates based on provided query parameters. + +## SYNTAX + +### Address +``` +Invoke-GMapGeoCode -Address [-Language ] [-RegionBias ] [] +``` + +### Location +``` +Invoke-GMapGeoCode -Latitude -Longitude [-Language ] [-RegionBias ] + [] +``` + +### PlaceID +``` +Invoke-GMapGeoCode -PlaceID [-Language ] [-RegionBias ] [] +``` + +## DESCRIPTION +Geocoding is the process of converting addresses addresses (like "1600 Amphitheatre Parkway, Mountain View, CA") into geographic coordinates. +This function can take in an address and return coordinate information. +You can also provide coordinates to return multiple nearby address results. +If you know the exact google placeID this can also be provided to return Geocoding information about that location. + +## EXAMPLES + +### EXAMPLE 1 +``` +Invoke-GMapGeoCode -Address '148 S Castell Ave, New Braunfels, TX 78130, United States' +``` + +Performs Geocoding (latitude/longitude lookup) on provided address. + +### EXAMPLE 2 +``` +Invoke-GMapGeoCode -Latitude '29.7012853' -Longitude '-98.1250235' +``` + +Performs Reverse geocoding (address lookup) on provided coordinates and can return multiple address results. + +### EXAMPLE 3 +``` +Invoke-GMapGeoCode -Latitude '37.621313' -Longitude '-122.378955' -Language es +``` + +Performs Reverse geocoding (address lookup) on provided coordinates and can return multiple address results in Spanish. + +### EXAMPLE 4 +``` +Invoke-GMapGeoCode -PlaceID 'ChIJK34phme9XIYRqstHW_gHr2w' +``` + +Returns Geocoding information about the provided place. + +## PARAMETERS + +### -Address +The street address or plus code that you want to geocode. +Specify addresses in accordance with the format used by the national postal service of the country concerned. +Additional address elements such as business names and unit, suite or floor numbers should be avoided. + +```yaml +Type: String +Parameter Sets: Address +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Latitude +Geographic coordinate that specifies the north-south position of a point on the Earth's surface. + +```yaml +Type: String +Parameter Sets: Location +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Longitude +Geographic coordinate that specifies the east-west position of a point on the Earths surface. + +```yaml +Type: String +Parameter Sets: Location +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PlaceID +The place ID of the place for which you wish to obtain the human-readable address. +The place ID is a unique identifier that can be used with other Google APIs. + +```yaml +Type: String +Parameter Sets: PlaceID +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Language +The language in which to return results. + +```yaml +Type: languages +Parameter Sets: (All) +Aliases: +Accepted values: af, sq, am, ar, hy, az, eu, be, bn, bs, bg, my, ca, zh, hr, cs, da, nl, en, et, fa, fi, fil, fr, ka, de, el, iw, hi, hu, is, id, it, ja, kn, kk, km, ko, ky, lo, lv, lt, mk, ms, ml, mr, mn, ne, no, pl, pt, pa, ro, ru, sr, sk, es, sw, ta, te, th, uk, ur, uz, vi, zu + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RegionBias +The region code, specified as a ccTLD ("top-level domain") two-character value. +This parameter will only influence, not fully restrict, results from the geocoder. + +```yaml +Type: ccTLD +Parameter Sets: (All) +Aliases: +Accepted values: ac, ad, ae, af, ag, ai, al, am, ao, aq, ar, as, at, au, aw, ax, az, ba, bb, bd, be, bf, bg, bh, bi, bj, bm, bn, bo, br, bs, bt, bv, bw, by, bz, ca, cc, cd, cf, cg, ch, ci, ck, cl, cm, cn, co, cr, cu, cv, cw, cx, cy, cz, de, dj, dk, dm, do, dz, ec, ee, eg, er, es, et, eu, fi, fj, fk, fm, fo, fr, ga, gb, gd, ge, gf, gg, gh, gi, gl, gm, gn, gp, gq, gr, gs, gt, gu, gw, gy, hk, hm, hn, hr, ht, hu, id, ie, il, im, in, io, iq, ir, is, it, je, jm, jo, jp, ke, kg, kh, ki, km, kn, kp, kr, kw, ky, kz, la, lb, lc, li, lk, lr, ls, lt, lu, lv, ly, ma, mc, md, me, mg, mh, mk, ml, mm, mn, mo, mp, mq, mr, ms, mt, mu, mv, mw, mx, my, mz, na, nc, ne, nf, ng, ni, nl, no, np, nr, nu, nz, om, pa, pe, pf, pg, ph, pk, pl, pm, pn, pr, ps, pt, pw, py, qa, re, ro, rs, ru, rw, sa, sb, sc, sd, se, sg, sh, si, sj, sk, sl, sm, sn, so, sr, ss, st, su, sv, sx, sy, sz, tc, td, tf, tg, th, tj, tk, tl, tm, tn, to, tr, tt, tv, tw, tz, ua, ug, uk, us, uy, uz, va, vc, ve, vg, vi, vn, vu, wf, ws, ye, yt, za, zm, zw + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### Output from this cmdlet (if any) +## NOTES +Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + +This function does not support pipeline input because of this issue: + https://github.com/PowerShell/PowerShell/issues/10188 + +LAT LONG LOOKUP + Required parameters + address + key + Optional parameters + bounds + language + region + components + Example: + https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=YOUR_API_KEY +Reverse geocoding (address lookup) + Required parameters + latlng + key + Optional parameters + language + result_type + location_type + Example: + https://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&key=YOUR_API_KEY + +This function includes Google Maps features and content; use of Google Maps features and content is subject to the terms of service and Google privacy (linked below). + +## RELATED LINKS + +[https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Invoke-GMapGeoCode.md](https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Invoke-GMapGeoCode.md) + +[https://developers.google.com/maps/documentation/geocoding/overview](https://developers.google.com/maps/documentation/geocoding/overview) + +[https://maps.googleapis.com/maps/api/geocode/outputFormat?parameters](https://maps.googleapis.com/maps/api/geocode/outputFormat?parameters) + +[https://developers.google.com/maps/documentation/geocoding/overview#geocoding-lookup](https://developers.google.com/maps/documentation/geocoding/overview#geocoding-lookup) + +[https://developers.google.com/maps/documentation/geocoding/overview#ReverseGeocoding](https://developers.google.com/maps/documentation/geocoding/overview#ReverseGeocoding) + +[https://developers.google.com/maps/faq#languagesupport](https://developers.google.com/maps/faq#languagesupport) + +[https://cloud.google.com/maps-platform/terms/](https://cloud.google.com/maps-platform/terms/) + +[https://www.google.com/policies/privacy/](https://www.google.com/policies/privacy/) + diff --git a/docs/Search-GMapNearbyPlace.md b/docs/Search-GMapNearbyPlace.md new file mode 100644 index 0000000..b6ae95d --- /dev/null +++ b/docs/Search-GMapNearbyPlace.md @@ -0,0 +1,364 @@ +--- +external help file: pwshPlaces-help.xml +Module Name: pwshPlaces +online version: https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Search-GMapNearbyPlace.md +schema: 2.0.0 +--- + +# Search-GMapNearbyPlace + +## SYNOPSIS +Nearby Search lets you search for places within a specified area. +You can refine your search request by supplying keywords, type of place you are searching for and other parameters. + +## SYNTAX + +### Location (Default) +``` +Search-GMapNearbyPlace -Latitude -Longitude -Radius [-Keyword ] + [-Type ] [-Language ] [-OpenNow] [-MaxPrice ] [-MinPrice ] + [-AllSearchResults] [] +``` + +### Distance +``` +Search-GMapNearbyPlace -Latitude -Longitude [-RankByDistance] [-Keyword ] + [-Type ] [-Language ] [-OpenNow] [-MaxPrice ] [-MinPrice ] + [-AllSearchResults] [] +``` + +### Area +``` +Search-GMapNearbyPlace -Latitude -Longitude -Radius [-RankByProminence] + [-Keyword ] [-Type ] [-Language ] [-OpenNow] [-MaxPrice ] + [-MinPrice ] [-AllSearchResults] [] +``` + +## DESCRIPTION +Performs a nearby search request with provided parameters. +Nearby search is useful for finding places near a specific geographic location. +By default 20 results are returned from a standard search. +You can increase this to a maximum of 60 places results by providing the AllSearchResults switch. + +## EXAMPLES + +### EXAMPLE 1 +``` +Search-GMapNearbyPlace -Latitude '29.7049806' -Longitude '-98.068343' -Radius 5000 +``` + +Performs a nearby search and returns all places types near provided coordinates within a range of 5000 meters. + +### EXAMPLE 2 +``` +Search-GMapNearbyPlace -Latitude '29.7049806' -Longitude '-98.068343' -Radius 10000 -RankByProminence -Keyword 'butcher' -Type store +``` + +Performs a nearby search and returns all store place types that match the keyword of butcher within the specified geographic range. + +### EXAMPLE 3 +``` +Search-GMapNearbyPlace -Latitude '38.9072' -Longitude '-77.0369' -Radius 10000 -RankByProminence -Type embassy -AllSearchResults +``` + +Performs a nearby search and returns all embassy place types near provided coordinates within a range of 10000 meters. +The maximum of 60 places results is returned. + +### EXAMPLE 4 +``` +Search-GMapNearbyPlace -Latitude '29.7013856' -Longitude '-98.1249258' -Radius 1000 -Type restaurant -MinPrice 1 -MaxPrice 3 +``` + +Performs a nearby search and returns only restaurants places near provided coordinates within a range of 1000 meters. +Restaurant will be in the cheap to moderately expensive price range. + +### EXAMPLE 5 +``` +Search-GMapNearbyPlace -Latitude '29.7049806' -Longitude '-98.068343' -RankByDistance +``` + +Performs a nearby search and returns all places types near provided coordinates ranked by distance from the coordinates. + +### EXAMPLE 6 +``` +Search-GMapNearbyPlace -Latitude '26.1202' -Longitude '127.7025' -Radius 10000 -RankByProminence -Type amusement_park -Language en +``` + +Performs a nearby search and returns only amusement parks places near provided coordinates within a range of 10000 meters. +Results are ranked by prominence and returned in Engish. + +### EXAMPLE 7 +``` +Search-GMapNearbyPlace -Latitude '29.7049806' -Longitude '-98.068343' -Radius 5000 -RankByProminence -Keyword 'pasta' -Type restaurant -Language en -OpenNow -MaxPrice 4 -MinPrice 2 -AllSearchResults +``` + +Performs a nearby search and returns only restaurants places near provided coordinates that match the keyword of pasta within a range of 5000 meters. +Restaurant will be in the moderately expensive to expensive price range. +Only places that are currently opened are returned. +Results will be returned in English. + +### EXAMPLE 8 +``` +$searchGMapNearbyPlaceSplat = @{ + Latitude = '29.7049806' + Longitude = '-98.068343' + Radius = 5000 + RankByProminence = $true + Keyword = 'pasta' + Type = 'restaurant' + Language = 'en' + OpenNow = $true + MaxPrice = 4 + MinPrice = 2 + AllSearchResults = $true +} +Search-GMapNearbyPlace @searchGMapNearbyPlaceSplat +``` + +Performs a nearby search and returns only restaurants places near provided coordinates that match the keyword of pasta within a range of 5000 meters. +Restaurant will be in the moderately expensive to expensive price range. +Only places that are currently opened are returned. +Results will be returned in English. + +## PARAMETERS + +### -Latitude +Geographic coordinate that specifies the north-south position of a point on the Earth's surface. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Longitude +Geographic coordinate that specifies the east-west position of a point on the Earths surface. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Radius +Distance (in meters) within which to return place results. +Instructs the Places service to prefer showing results within that circle; results outside of the defined area may still be displayed. + +```yaml +Type: String +Parameter Sets: Location, Area +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RankByProminence +This option sorts results based on their importance. + +```yaml +Type: SwitchParameter +Parameter Sets: Area +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RankByDistance +This option biases search results in ascending order by their distance from the specified location. + +```yaml +Type: SwitchParameter +Parameter Sets: Distance +Aliases: + +Required: True +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Keyword +A term to be matched against all content that Google has indexed for this place, including but not limited to name and type, as well as customer reviews and other third-party content. +Note that explicitly including location information using this parameter may conflict with the location, radius, and rankby parameters, causing unexpected results. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Type +Restricts the results to places matching the specified type. + +```yaml +Type: placeTypes +Parameter Sets: (All) +Aliases: +Accepted values: accounting, airport, amusement_park, aquarium, art_gallery, atm, bakery, bank, bar, beauty_salon, bicycle_store, book_store, bowling_alley, bus_station, cafe, campground, car_dealer, car_rental, car_repair, car_wash, casino, cemetery, church, city_hall, clothing_store, convenience_store, courthouse, dentist, department_store, doctor, drugstore, electrician, electronics_store, embassy, fire_station, florist, funeral_home, furniture_store, gas_station, gym, hair_care, hardware_store, hindu_temple, home_goods_store, hospital, insurance_agency, jewelry_store, laundry, lawyer, library, light_rail_station, liquor_store, local_government_office, locksmith, lodging, meal_delivery, meal_takeaway, mosque, movie_rental, movie_theater, moving_company, museum, night_club, painter, park, parking, pet_store, pharmacy, physiotherapist, plumber, police, post_office, primary_school, real_estate_agency, restaurant, roofing_contractor, rv_park, school, secondary_school, shoe_store, shopping_mall, spa, stadium, storage, store, subway_station, supermarket, synagogue, taxi_stand, tourist_attraction, train_station, transit_station, travel_agency, university, veterinary_care, zoo + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Language +The language in which to return results. + +```yaml +Type: languages +Parameter Sets: (All) +Aliases: +Accepted values: af, sq, am, ar, hy, az, eu, be, bn, bs, bg, my, ca, zh, hr, cs, da, nl, en, et, fa, fi, fil, fr, ka, de, el, iw, hi, hu, is, id, it, ja, kn, kk, km, ko, ky, lo, lv, lt, mk, ms, ml, mr, mn, ne, no, pl, pt, pa, ro, ru, sr, sk, es, sw, ta, te, th, uk, ur, uz, vi, zu + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -OpenNow +Returns only those places that are open for business at the time the query is sent. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -MaxPrice +Restricts results to only those places within the specified range. +Valid values range between 0 (most affordable) to 4 (most expensive), inclusive. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -MinPrice +Restricts results to only those places within the specified range. +Valid values range between 0 (most affordable) to 4 (most expensive), inclusive. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -AllSearchResults +By default 20 results are returned from a standard search. +Using this switch increases the search results from 20 to the maximum of 60. +This does increase the number of API calls. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### Output from this cmdlet (if any) +## NOTES +Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + +Latitude and Longitude information can be easily retrieved using Invoke-GMapGeoCode + +Required parameters + location + This must be specified as latitude,longitude. +Optional parameters + keyword + language + maxprice + minprice + name + opennow + radius + rankby + type + sessiontoken + +Example: 'https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522%2C151.1957362&radius=1500&type=restaurant&keyword=cruise&key=YOUR_API_KEY' + +Nearby Search and Text Search return all of the available data fields for the selected place (a subset of the supported fields), and you will be billed accordingly There is no way to constrain Nearby Search or Text Search to only return specific fields. +To keep from requesting (and paying for) data that you don't need, use a Find Place request instead. + +Use of the AllSearchResults parameter does increase the number of API calls. + +This function includes Google Maps features and content; use of Google Maps features and content is subject to the terms of service and Google privacy (linked below). + +## RELATED LINKS + +[https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Search-GMapNearbyPlace.md](https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Search-GMapNearbyPlace.md) + +[https://developers.google.com/maps/documentation/places/web-service/search-nearby](https://developers.google.com/maps/documentation/places/web-service/search-nearby) + +[https://maps.googleapis.com/maps/api/place/nearbysearch/output?parameters](https://maps.googleapis.com/maps/api/place/nearbysearch/output?parameters) + +[https://developers.google.com/maps/faq#languagesupport](https://developers.google.com/maps/faq#languagesupport) + +[https://cloud.google.com/maps-platform/terms/](https://cloud.google.com/maps-platform/terms/) + +[https://www.google.com/policies/privacy/](https://www.google.com/policies/privacy/) + diff --git a/docs/Search-GMapText.md b/docs/Search-GMapText.md new file mode 100644 index 0000000..2eb32a2 --- /dev/null +++ b/docs/Search-GMapText.md @@ -0,0 +1,465 @@ +--- +external help file: pwshPlaces-help.xml +Module Name: pwshPlaces +online version: https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Search-GMapText.md +schema: 2.0.0 +--- + +# Search-GMapText + +## SYNOPSIS +A text search that returns information about a set of places based on provided string. + +## SYNTAX + +### textquery (Default) +``` +Search-GMapText -Query [-Type ] [-Language ] [-RegionBias ] [-OpenNow] + [-MaxPrice ] [-MinPrice ] [-AllSearchResults] [] +``` + +### Distance +``` +Search-GMapText [-Query ] [-Latitude ] [-Longitude ] [-RankByDistance] + [-Type ] [-Language ] [-RegionBias ] [-OpenNow] [-MaxPrice ] + [-MinPrice ] [-AllSearchResults] [] +``` + +### Area +``` +Search-GMapText [-Query ] [-Latitude ] [-Longitude ] -Radius + [-RankByProminence] [-Type ] [-Language ] [-RegionBias ] [-OpenNow] + [-MaxPrice ] [-MinPrice ] [-AllSearchResults] [] +``` + +### Location +``` +Search-GMapText [-Query ] -Latitude -Longitude [-Type ] + [-Language ] [-RegionBias ] [-OpenNow] [-MaxPrice ] [-MinPrice ] + [-AllSearchResults] [] +``` + +## DESCRIPTION +Text based search for finding places based on a provided string and optional parameters. +Text search is especially useful for making ambiguous queries when searching for places. +Returned results can be heavily biased based on factors such as including a location in +the query iteself, or by providing direct location information in optional parameters. +By default 20 results are returned from a standard search. +You can increase this to a maximum of 60 places results by providing the AllSearchResults switch. + +## EXAMPLES + +### EXAMPLE 1 +``` +Search-GMapText -Query "Krause's Cafe" +``` + +Performs a text search with the provided query. +Since no address or location information is provided places results are biased by your IP location. + +### EXAMPLE 2 +``` +Search-GMapText -Query "Cupcakes" -Type bakery -AllSearchResults +``` + +Performs a text search with the provided query and returns places that are classified as type: bakery. +Since no address or location information is provided places results are biased by your IP location. + +### EXAMPLE 3 +``` +Search-GMapText -Query "pizza restaurants in New York" +``` + +Performs a text search with the provided query. +Since a location is provided in the query, places results will be biased by that location. + +### EXAMPLE 4 +``` +Search-GMapText -Query "Airport" -RegionBias es +``` + +Performs a text search with the provided query. +Places results are biased to the region of Spain. + +### EXAMPLE 5 +``` +Search-GMapText -Query "italian restaurants in New York" -MinPrice 4 +``` + +Performs a text search with the provided query and returns expensive restaraunt options. +Since a location is provided in the query, places results will be biased by that location. + +### EXAMPLE 6 +``` +Search-GMapText -Query "main plaza New Braunfels" -Type restaurant +``` + +Performs a text search with the provided query and returns only restaurants. +Since a location is provided in the query, places results will be biased by that location. + +### EXAMPLE 7 +``` +Search-GMapText -Query 'Cafe' -Latitude '26.1202' -Longitude '127.7025' -Radius 5000 -Language en +``` + +Performs a text search with the provided query. +Results are returned based on the provided coordiantes within a 5000 meter range. +Places results are returned in English. + +### EXAMPLE 8 +``` +Search-GMapText -Query 'Coco' -Latitude '26.1202' -Longitude '127.7025' -Radius 5000 -Language en -Type restaurant +``` + +Performs a text search with the provided query. +Only restaurant places are returned. +Results are returned based on the provided coordiantes within a 5000 meter range. +Places results are returned in English. + +### EXAMPLE 9 +``` +Search-GMapText -Query 'Coco' -Latitude '26.1202' -Longitude '127.7025' -Radius 500 -RankByProminence +``` + +Performs a text search with the provided query. +Results are returned based on the provided coordiantes within a 500 meter range. +Places results are ranked by their prominence. + +### EXAMPLE 10 +``` +Search-GMapText -Query 'Coco' -Latitude '26.1202' -Longitude '127.7025' -RankByDistance -Type restaurant +``` + +Performs a text search with the provided query. +Only restaurant places are returned. +Results are returned based on the provided coordiantes and are ranked by their distance from the coordinates. + +### EXAMPLE 11 +``` +Search-GMapText -Query 'Coco' -Latitude '26.1202' -Longitude '127.7025' -RankByDistance -Type restaurant -Language en -OpenNow -MinPrice 1 -MaxPrice 2 -AllSearchResults +``` + +Performs a text search with the provided query. +Only restaurant places are returned. +Results are returned based on the provided coordiantes and are ranked by their distance from the coordinates. +Places data is returned in English. +Results with a cheap to moderate price are returned. +Only restaraunts that are currently open are returned. +The maximum of 60 places results is returned. + +### EXAMPLE 12 +``` +$searchGMapTextSplat = @{ + Query = 'Coco' + Latitude = '26.1202' + Longitude = '127.7025' + RankByDistance = $true + Type = 'restaurant' + Language = 'en' + OpenNow = $true + MinPrice = 1 + MaxPrice = 2 + AllSearchResults = $true +} +Search-GMapText @searchGMapTextSplat +``` + +Performs a text search with the provided query. +Only restaurant places are returned. +Results are returned based on the provided coordiantes and are ranked by their distance from the coordinates. +Places data is returned in English. +Results with a cheap to moderate price are returned. +Only restaraunts that are currently open are returned. +The maximum of 60 places results is returned. + +## PARAMETERS + +### -Query +Text string on which to search + +```yaml +Type: String +Parameter Sets: textquery +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +```yaml +Type: String +Parameter Sets: Distance, Area, Location +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Latitude +Geographic coordinate that specifies the north-south position of a point on the Earth's surface. + +```yaml +Type: String +Parameter Sets: Distance, Area +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +```yaml +Type: String +Parameter Sets: Location +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Longitude +Geographic coordinate that specifies the east-west position of a point on the Earths surface. + +```yaml +Type: String +Parameter Sets: Distance, Area +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +```yaml +Type: String +Parameter Sets: Location +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Radius +Distance (in meters) within which to return place results. +Instructs the Places service to prefer showing results within that circle; results outside of the defined area may still be displayed. + +```yaml +Type: String +Parameter Sets: Area +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RankByProminence +This option sorts results based on their importance. + +```yaml +Type: SwitchParameter +Parameter Sets: Area +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RankByDistance +This option biases search results in ascending order by their distance from the specified location. + +```yaml +Type: SwitchParameter +Parameter Sets: Distance +Aliases: + +Required: True +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Type +Restricts the results to places matching the specified type. + +```yaml +Type: placeTypes +Parameter Sets: (All) +Aliases: +Accepted values: accounting, airport, amusement_park, aquarium, art_gallery, atm, bakery, bank, bar, beauty_salon, bicycle_store, book_store, bowling_alley, bus_station, cafe, campground, car_dealer, car_rental, car_repair, car_wash, casino, cemetery, church, city_hall, clothing_store, convenience_store, courthouse, dentist, department_store, doctor, drugstore, electrician, electronics_store, embassy, fire_station, florist, funeral_home, furniture_store, gas_station, gym, hair_care, hardware_store, hindu_temple, home_goods_store, hospital, insurance_agency, jewelry_store, laundry, lawyer, library, light_rail_station, liquor_store, local_government_office, locksmith, lodging, meal_delivery, meal_takeaway, mosque, movie_rental, movie_theater, moving_company, museum, night_club, painter, park, parking, pet_store, pharmacy, physiotherapist, plumber, police, post_office, primary_school, real_estate_agency, restaurant, roofing_contractor, rv_park, school, secondary_school, shoe_store, shopping_mall, spa, stadium, storage, store, subway_station, supermarket, synagogue, taxi_stand, tourist_attraction, train_station, transit_station, travel_agency, university, veterinary_care, zoo + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Language +The language in which to return results. + +```yaml +Type: languages +Parameter Sets: (All) +Aliases: +Accepted values: af, sq, am, ar, hy, az, eu, be, bn, bs, bg, my, ca, zh, hr, cs, da, nl, en, et, fa, fi, fil, fr, ka, de, el, iw, hi, hu, is, id, it, ja, kn, kk, km, ko, ky, lo, lv, lt, mk, ms, ml, mr, mn, ne, no, pl, pt, pa, ro, ru, sr, sk, es, sw, ta, te, th, uk, ur, uz, vi, zu + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RegionBias +The region code, specified as a ccTLD ("top-level domain") two-character value. +This parameter will only influence, not fully restrict, results from the geocoder. + +```yaml +Type: ccTLD +Parameter Sets: (All) +Aliases: +Accepted values: ac, ad, ae, af, ag, ai, al, am, ao, aq, ar, as, at, au, aw, ax, az, ba, bb, bd, be, bf, bg, bh, bi, bj, bm, bn, bo, br, bs, bt, bv, bw, by, bz, ca, cc, cd, cf, cg, ch, ci, ck, cl, cm, cn, co, cr, cu, cv, cw, cx, cy, cz, de, dj, dk, dm, do, dz, ec, ee, eg, er, es, et, eu, fi, fj, fk, fm, fo, fr, ga, gb, gd, ge, gf, gg, gh, gi, gl, gm, gn, gp, gq, gr, gs, gt, gu, gw, gy, hk, hm, hn, hr, ht, hu, id, ie, il, im, in, io, iq, ir, is, it, je, jm, jo, jp, ke, kg, kh, ki, km, kn, kp, kr, kw, ky, kz, la, lb, lc, li, lk, lr, ls, lt, lu, lv, ly, ma, mc, md, me, mg, mh, mk, ml, mm, mn, mo, mp, mq, mr, ms, mt, mu, mv, mw, mx, my, mz, na, nc, ne, nf, ng, ni, nl, no, np, nr, nu, nz, om, pa, pe, pf, pg, ph, pk, pl, pm, pn, pr, ps, pt, pw, py, qa, re, ro, rs, ru, rw, sa, sb, sc, sd, se, sg, sh, si, sj, sk, sl, sm, sn, so, sr, ss, st, su, sv, sx, sy, sz, tc, td, tf, tg, th, tj, tk, tl, tm, tn, to, tr, tt, tv, tw, tz, ua, ug, uk, us, uy, uz, va, vc, ve, vg, vi, vn, vu, wf, ws, ye, yt, za, zm, zw + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -OpenNow +Returns only those places that are open for business at the time the query is sent. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -MaxPrice +Restricts results to only those places within the specified range. +Valid values range between 0 (most affordable) to 4 (most expensive), inclusive. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -MinPrice +Restricts results to only those places within the specified range. +Valid values range between 0 (most affordable) to 4 (most expensive), inclusive. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -AllSearchResults +By default 20 results are returned from a standard search. +Using this switch increases the search results from 20 to the maximum of 60. +This does increase the number of API calls. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### Output from this cmdlet (if any) +## NOTES +Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + +Latitude and Longitude information can be easily retrieved using Invoke-GMapGeoCode + +Required parameters + query +Optional parameters + language + location + maxprice + minprice + opennow + radius + region + type + +Example: 'https://maps.googleapis.com/maps/api/place/textsearch/json?query=restaurants%20in%20Sydney&key=YOUR_API_KEY' + +Nearby Search and Text Search return all of the available data fields for the selected place (a subset of the supported fields), and you will be billed accordingly There is no way to constrain Nearby Search or Text Search to only return specific fields. +To keep from requesting (and paying for) data that you don't need, use a Find Place request instead. + +Use of the AllSearchResults parameter does increase the number of API calls. + +This function includes Google Maps features and content; use of Google Maps features and content is subject to the terms of service and Google privacy (linked below). + +## RELATED LINKS + +[https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Search-GMapText.md](https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Search-GMapText.md) + +[https://developers.google.com/maps/documentation/places/web-service/search-text](https://developers.google.com/maps/documentation/places/web-service/search-text) + +[https://maps.googleapis.com/maps/api/place/textsearch/output?parameters](https://maps.googleapis.com/maps/api/place/textsearch/output?parameters) + +[https://developers.google.com/maps/faq#languagesupport](https://developers.google.com/maps/faq#languagesupport) + +[https://cloud.google.com/maps-platform/terms/](https://cloud.google.com/maps-platform/terms/) + +[https://www.google.com/policies/privacy/](https://www.google.com/policies/privacy/) + diff --git a/docs/pwshPlaces-FAQ.md b/docs/pwshPlaces-FAQ.md new file mode 100644 index 0000000..0291826 --- /dev/null +++ b/docs/pwshPlaces-FAQ.md @@ -0,0 +1,11 @@ +# pwshPlaces - FAQ + +- [pwshPlaces - FAQ](#pwshplaces---faq) + - [FAQs](#faqs) + - [Do I need an API key us to use pwshPlaces](#do-i-need-an-api-key-us-to-use-pwshplaces) + +## FAQs + +### Do I need an API key us to use pwshPlaces + +Yes diff --git a/docs/pwshPlaces.md b/docs/pwshPlaces.md index 575e8b0..a51e941 100644 --- a/docs/pwshPlaces.md +++ b/docs/pwshPlaces.md @@ -2,7 +2,7 @@ Module Name: pwshPlaces Module Guid: 9a9914bd-d115-4f42-bb5d-19c5e5561a3f Download Help Link: NA -Help Version: 0.0.2 +Help Version: 0.0.9 Locale: en-US --- @@ -11,7 +11,19 @@ Locale: en-US tbd ## pwshPlaces Cmdlets -### [Get-HelloWorld](Get-HelloWorld.md) -Short description +### [Find-GMapPlace](Find-GMapPlace.md) +Find Place request takes a text input and returns a place. The input can be any kind of Places text data, such as a name, address, or phone number. + +### [Get-GMapPlaceDetail](Get-GMapPlaceDetail.md) +Request more details about a particular establishment or point of interest + +### [Invoke-GMapGeoCode](Invoke-GMapGeoCode.md) +Engages Geocoding API to return address and geographic coordinates based on provided query parameters. + +### [Search-GMapNearbyPlace](Search-GMapNearbyPlace.md) +Nearby Search lets you search for places within a specified area. You can refine your search request by supplying keywords, type of place you are searching for and other parameters. + +### [Search-GMapText](Search-GMapText.md) +A text search that returns information about a set of places based on provided string. diff --git a/media/gcp_api_services_restrict_api_key.PNG b/media/gcp_api_services_restrict_api_key.PNG new file mode 100644 index 0000000000000000000000000000000000000000..87762ecf109266cb9f957e43dc6c467595e3da8b GIT binary patch literal 102959 zcmd?RcT`hP_wb9NAksucdQk+$LT{mpC_x|;L6F{i2@+Z;K}3oQp|^ylbP!OgLLefD zl!O*~3pF$WAwcNd@GZ~td+$GY-MilRuX|PqIp@sG*)y|e&z|}0b>8Y~1L-ewT&AF) zpnt0V_!$KSC6I#RV&Ekz@|Csz0WkUBImk2MBZ~5Fu4VGc1xFQ-3I)ZNSlT1&i{x_} zPjzDm1;thGv%hmw4!r&p6sP%5AFCMnTl_wz_huPvJdMq+={7M&D;rx@Hf=?U2z`1# z&xkeGJ9_%1ct=`r*btR=;Hp8KGjstt2evd840)M$*Ch`j{PRudh6=)O7U-y79M@Da zsoqCunqI)EJuv$CBJ4y90j>_^ToAfHyrSVWAf;IAxOmd%5Q7$U%EqI#-onmb*JEN_s->XG7DaGMPG zyn1T75Gv@^>>aX1Mb$HmCp~y{W&rZUXHp1nKU+Xx#eeXd3XX)GzBxU*V{&ANV0gE; zz%7jNo60w0VC*f!@93EJ9?Y<>0D#^n$r9V_x93zp6U#%R@jZ$sC?O9NBRN? zNImIYR#pZprW6c69&Lo|x{vJ_N^G~z_(eTfO6RBa4zoOXlp+fJ=)ZL23hqliBB<)} za2Pb{X6=f6*9b{BElle90E;yD`Kybe$!qyx<&$$nM66EvcHGYE zJC~Fek5kx#vfvBL_AW^;<|n zS?hHS?UsJ%)}1FC&x|6od|&fGpJ>U2z+ux*X;o~WiUN&WLmMK%sBc<~JtS9#=k5LH zWKK6^LPYJPff$w%2t`L4=+~?p{565N-@cHG1Q+aE@GOL#* zz_{JplflIZk{2k}+2O^p_b=Wa+`Yw53rmxJ%Lb=_fO%ydHs_%iQ7JCSe!} z*Qf~Ya`5?OIgdZ-`pV)vetT)?RQy2tW&NDm9cfVeh zO>aX9aab@@*^k3WqEHd1L(blE`Y3MgmawOuXNF>}YFlnw;RH!6?Mf&lN(Ps2f)(ZR z@N$4mizyLs%LC$9=uBnb^4^osZkg38WeyO(1;G{G-M11AJ+|QiDsSj63ZBqIBsmsX z4d@Cm4iFfz222q&mJWTPS8-VfP4Q?{t_V^xZZGp!Kqf2~ zxaDO*DK#-`ONeapkUh2VNB>wfWq&(7^|1jK0*4plw$_Lny%K2UCr0g(70*^J&rBk` z$yK-k075NkHfYP@nt~Ew-Fk1`wJdT)etQmSg3+44;P2dnEerjkG3KT{{Zr>kuSZQ? z5B_Bh%x-9GB@dz!lRy#unHbE&{=^;>CnQ_Z5nPU&Ma zhRD++!Abwr__ivYj5g%(#34QOZxwMI`ZabCjQb2DCHVAODDA*Ej%J314t{oR^sj<5 zb9s^c=wK4)>dQKX9&~x35M+ByQ|+^G^>hcM)$g4j9Bm)ll;RAhS^`)cVI?Qa`agSI zAzc)Xhkemj#9ETatMI*P$6e*XyRo5ck30?+9hZx~vgBI==ETiqyk8vp1)wzwF-(o| z1%XEL%P%wo{n6May&pkJU4EH<&ZLbRp-lw;OH27~=BW>OPO8LMEPurx$P>1&z&#Sp zK{L}yW_ou?dH@o3qIwdHfCVQE`(^Qn#TJjCQ=ye3=s)(tW$ z{km>_$6*S^0iP5L-NJRvhEH?BKR3QbwJH6 zHIWY@8FC1itvcLks;bT+-q_u|lAYpgz1NgGoa>r1m9Hw26~AwOIy>$KDD0Rj-DdfM z2fvpDl1vZn3ITf&<_zCR@~FL;`rrx(_6>_jOV>eJ)fIaxX4M-!A5B|^<19JWQ}Z_H z-4c%aufZ(}*DCX;p#d*+^a)EnI>_Z0C2g(hNN4!KK{pzN9t-HF=|%@8H1VxBXu__# z-La49CK^iA6TwZYLHkX_dQmyKKc~x_+qRq0!P9yWcKw;!;~iE&kB6=8GU#fmWM4wfT_Qw(doB_&M6e6@>R3~aUH_Su&Qb0f)W=saX zZ=FwcN{RVa0aFp+ylJi$fXCQle9~vVhWraR542jkX2r!^FUytz@H!4kl{1qf<_rYs zJ#cp_LlbCuu3fEFUMKMZngd-qOEltSn+mDeU%=O!X-T;M*e41*rqE}*5`s>~TTPV$ zLZE?!?MDepsjvTJS)TM0<`op3hFm6gs1&hSW4FneKk0?SOE?X>yRj8{deE>8pzLiDbR|d4oGMr$RBgps_F$_L#vM(^u*%T8@pg%+BS6`J|kD#1}Ra zg?C8Vg=-B{IY>xQ=~4tfE3s_}vst&~db7+!+*d7)*0_bAm>(00{^53L{f*JspC5$H zkVXRf9n@vY4rffgA0`!>uijb^1BM1CEA&el8h?((>QFDS2h)a-%mav$jG-rj!K3=P zi!rcfu8Zw-HkB9ekM^nnknAy*qMfV5ORq#a#pPt}{Gl7-1a*@D1jAP!3oOL|ozmz9 zPvQgaD-vT#7oVoigj1Eu#S#EHq@SD*ky|{f#3MSnY_e8KHuk{mJH=ze@n5#?4*UFY z_ytyk5$+)O_MA{e$_ItrWg__n zBu-&zBK)tDjk`YXu#6tfbB`T-j$cof@K)?ebyzk(So2*C>7pwhyET44Gl%yjCzCab z$DG$2Pdj$vd_a$Wy6zKQj|K$9C=uV(UBBa>ZRRy7{g(Jgph>!>S!_EKx1GsNIdG(E zZc0d0Lp=I;I@OJC`R#Xd*)>irSImaIq6>RawHq~~!pgJX!hWzeRegM3OJ5x?m%!`B z0+rj>KuDkN(wqFKq2-*)D_r1r_=AZb@YCr(JyCXaI-DU6+{-c&A2iNYj*Z<`_tDwg zrk{mL;}xCEO_6qqmG?WptVIqgDWH*u=KD^+I1OV!hLAk!*v~FG9#`z!LN>gE>4x!K z3vMPw{rQ%fhl@Jx=7B>xrgc(!2YF@Q~<()`g8--(oFcs>#$2d!*Pzm z48qNfUV9SX&0nFTgNqO_rB87-*<(ZOiw)a%27dan9#$^U;UHbTEeB;k88?XQvs(80 z;}I51NeUE4mTcl3EN^WDNR4il&ICahogtmgZ~d}_xKT@Ud7GunHk-AQu<=3r@AiwC zsjj0l2}(Q#-up=C_EkGJiR7Q^Zi{tG@XdIF%8qQV0Ipi)1>b1C&^@px|qMl#%E+%!;hecWyEbr1EB+)IYE5~6p8md;Bu}8 zbdI^{2$}M*b#aA{Za8(?$ElV6)vc;Gq!qy#^unr%KSb3_l)HDox1JrjxbH3hX9P;f?xPP z6Lc1l6A9R;Z|gAR!LING;7d-i3?uslLM0t&e?v z6aOs(MqD$pol7=eZ9!ulJg2HnrtBrhmi!lt5_7^pjnV9=^qR+XV3F(`+{9G)g|o3H zC;1H%6@g1Xyq?6XT{wdeNY4=;?EiJs2=>BycscoOiZ^SUnwyXG3pwiy@;J*(H9MRJ z71E5A3v&wM*9a!QU+uC~Ify(qQ;b@#T?8dqrnr^`A?QiB!RUuq*7T$M><=#i>>O-3bC7kACI$FFW`iDU-xz z5dtTCpPaMQrud4#PcVPS|B+yd(iBN@hNCFOm(I~vGPLKoDk_9=8=P!EkozGN>yjHM zx{CIjxN~D4BZ-ED=-6UcsA73{gwh*1FzAxcFfJ2Q-;Y5$5 zk*?-mgI6y;U3}Zs4~DTVDREjhEL5cUi&o*@8|D^=@qFwH5I{_ZrN)7$PyO=PkVHB?~vDsXI5! zE=dE|9ef`7(f5YDe=4#8)jT=Hj}HQF9ev6y0q;3u?pIgcFyU5i{@gP8rSvPVC4 z7ccj<*dbdqNxv1GMUWqOvpy^WCL1>T@o>5Ef=M;%*vVGYL!EenrsO}H{BDNp}e54%m{^aia`}4X}F#8*wR$&~2-J^_BNu=!l zYNK$v88rRH7^-G2`*@kCnZCZGe&=+2gcvqyl=X+m9mz1cMl+=@r#Wk?mTw2H{)Oqy z=~Iqq4hiX}sO+g_mDwPtA5H9z`nCwMOrXTHR2Y$Ou5F=U#s^`4J&Co^A|eFYEPT2K z>X}`0WsbwTIV}gxvtBtw@;92JQR(*J6mHGLvW}v*hWqbRaeG+D^o6pzT$;PLA?)a# zgUkw(Zzmq|1nVDb1K?8o%|5f1j-fMDmohXs>)DkRrk|f1wD{*z>JoalgU;GxZL= zK(fQb--)HQE9JQDX*h1ETK6z`rk_fPp)HEMyo%1d+{qVA@(Gy#Grlbc#GOCZ>jN5C z@{Uj6fo%7O0FN*I7CP{V-MnEKdL+6W63&)_R1Uhk<*#ul0Vw(b82kDSFZHmcEHq61 z&Ezi4!5DA%XmEm^oV12c<9Z&gHC$ZnE2QHW7ma<;g|lrUc5_a)yb znw)&kXYho|JH(Yzst7u`|| z#f?uZEQ+h6=(QcoEk$~W7;g?`TqktMK93YLTquSuy`Gxhy& zo6-bTK>*mC_2Qbp6RNAy|MX{!5PX}vLui!VD zo-bS5L~tvky3(YyEigXI+bYctwKCIMwH(wHUlp_5%3HIvbzV%VFZ4$%M0VDbG=N{Y0$ zs6Oa!`Fm3O;>&O8L}QMPN)rd{HE?X*YF#jqYp`{YD_zRP;%JKt1drcqT5Kuk23pY< z7dWvWzx&-chN^)ddk;g}e(CPJZ@D_p&6T!T!{4mSJz?a5MRu1MRc}##UM&NQe{)F+ zQaazo>+chCVW>)Hg|Y%~V!Iw#ejI@!o21JsV|;6Y3#i|v^Qi?^7s#04Vxfu@kju)e zSK``M6FV=>OQqLZS9M4nEETdNBnfUV$@FtUBlfS)KeR|4RfwMPNo#vrh`sK%b&^&P z(NR0;c6p3Z`Kuw2lRu?97w?NLcw@1b=HHb(ygGTCSt6F;RlxM;$0}}r8q#Xkts@sj zx<_>DU$FAvN3u&3e?O2%FQDx6JA6@4P8F)G!oUg|kS<`k()y^jwCj7tZ?6aPW|!sA zugf=&SnRal6G;>?KxLw zp;qy$fopM+E(i*p60V3%U9hioH+oMB!)?L#v5X1A)EmI}2 zcF^_g9>S4Z7h?8!k%L)!J|pXN5w9?bG^~&)%J3e&;BJ%}YB{<3T|^tnq~s?{!sbi#R59&o+;>+3o+Np6%4=eUoxU*1Ie3dx>e6h zgMK2TJYV9+GNA2wrFcV4xI}S9-U@zpa^+$gKgGk}uK?%C zCl9ZkUHn2xzE3{%&MvkxknfX^$LIcEXS(FzR}y{o?F9js;bI{Q3XmOSps!Dbgbz`E zU|v6vKUiv{ucH&Iu~2|UXTy%>cyTgKoAmev1}@p0XC{BZ;CeR>p8jfQl`p8`Ya%1J zVD{GLWj@5s=S(r#1}a2EogTPNV@R(|OJA*c(xpEqv7m8{Ued8sR%5F+Va};DgUSVu z^oc#sK2jCo@vZ)~Fh{EQ?#3)&`z-bZEJ6VTy97@M9tVd;x`;Sy3= zsQ?xu?ps)dX>x?#T4!f{ZU(CRG^!fz{dUpDs^_{%gT40xRJXT>|3V9YOQ-`vpd!NmFuixD1m|%-bosMy z`-E7vWeJz4C_DH_`(8S;K6)PuHgKVpR)ZC^-^0CN$pdJBKVJN~qL%zA-)Gdu?O1e{ z&!+zt!fxfJy~dja<`pONY!fx{ZGsc2(yJy|+F1>juuy%!!o8q45Gs&d6#VpBjM1TN z*1Lh~`8Te`4?Zq)xcN#ao9y4WR1+z3=7U{(2bhgag2|SR?7c(Cy(90k*Xyu(S-iPb zwA61upvW;Lvt3buxU~p)>ccru{pCESFUl(iniAZYWFP!lo>1h3Iz-sUh*T0brJ&1| z9>cU`8ukUdtK6u~+Zc>K#?V|XoT=uJR#V`Xop*=BP7m>i9L&mJZuB250hPBvb1a;9 zKsOM%CxcS8#WU1ySQkfLiC)Is%A~K8_6h5gYB39jui`TrGcr=2s=C45!i*l()ZSwj zylu~3FdJ?BZYk*EglQP`wUV;R z1mwMNzP!l%6bJN>{}QI}Qe`4SqipqYN%d1Lnjd1olSr3WyVXNQtO)|uo~1;qZ~#Zc zpDvkWR9{aMFE!bH7XOL~N3oSz> zB#r;A`Jjb{wwqWhL0x&|wsgO*)YGdoq393Y;(pAmK3}J-M)T_QbA#^O`WXY0M43>% zw93Qk-H&EU9ON?Iu6b@O5{)7yez42K(qNd{BQrq;o%YIy*X!+T_msurIVeR^%m`60 z5v1F$hT~%7+K;qKsvV(b7Im(yW-G*7CshB~yc^u-I2y7?I?)xbsO;!ph2l&Gu6{=ozutfSw$GMWbC+% zwX60Wo}uDu--+hDyovu_S$hzuMCOL|{N+IeWodiZdVoI(o{)5dp&7c!mtu&6Kq+TavWK~n?OV$EI*Qn(oNf}2ZPS{*mJSi zNCUZ49$1WpbpL0i@s~p;x=e0xaiZ)Brtg>X$xD+;yQf3ms^K0I3VMxOqf@eaCs{1> z@JH$V%EY*zT={{{rbLC3&xiK~oF|^BP|9EUP`a0BFzAqu2sIZfg=%F5!@aS3n-jj5 zYk?=8RX+$&7GF-6bte-&yoOGo;rvAFxHC9V@p-gJ0=nyo+RnH{$lRcg`|}~#3L(~* z_Y!5G6R3r&{zVyn#ZxI3QMYrT)cS*9Icr|W@%f{5l8*!LgXko{yJRsN;a;xIhY#o> z1--JPJ&}jHW?F-w*aR?Z>y_cC;A4mOZ$@$?9K(wGbKJF284Z$H=kDxVB#kr<_3pjd zekSg7gg2ffI^LtfLps;U8&tZoIvunO%b3klwr7~E6q|0UuA9^+90e`qH1!hN@8rT6 zG@h6G2&}gME@0UmQ5%oN*xuNvAR?TRBo#-F!6pW%PVHd}OAIT?F8GMbsfT0p=yP`F z$KTYeCt36j?13ybo3=&hm=gcPtkgt?8`$_BpVZhH8m;lVx7W36%F}6lRwsIVxI?~X z#qSKbuxcRWt{cD9d-h2NLdr;O4t>eo{(h{&I5>I_N<4VgP#|!rN+`3~(+P4b`aR-D zhP-!@$MmwL!XtE|e)Z-E5Z||PEa4vst7{W?hK%cQ)M#(?(#F0}D>%4O=x$i>t)o>E z2x;<8gAof5H^{ph=}@lc1gEZ)2Os+B=?^084I;tdythGNm&BE!LtM{0S=&SCoD_#p4nmZvA(OkWSdJUiBXMKDuAkp!PL56FI*E4mpvKO8ONBI~ zwBoc)_so`HM2}#0I8@1NNY&4;|D}%ene>rdv~lF^(q9jZo{H_)6iHqv>iWrkDfcm( z(rr(x{z;*`Mm>~=>>t)`1wJawZ)b#73Fq2;iJrQynN7LRJ$^*Wjg@|o;lfQTb#pcd za?4=j_<4422aRNC*KieHT&F5k7gAPp8W2aBX$eMi3sxKkGW5?H-y>SfH2YbM?aN5@ zR1w;px&xXCPFAcB^p0~hTfK)p#tJ$B5!&pW$EiNdkI?5zy;qT~Zk3#!uiDdkGTcDR zTCby-?s1(EqLzGIj_>N=b@1|?=$5ox=It60FNErLl(o&RiY7G@htwl2CBl-bsXTOb)ybeaqAy6i z=V+B_>)m4c%d$YL;j1<4uZYx-9lnyMm>8zSGQ%Z*)-rIvN~Qew8cW2jF6Xz zbOZHR2Wf=Rz`M(*{NqhE@^;u)bgiNBs-M(xZI2$q(l})|uc6QbQP<-0>%;p~_^RAP zA*6_Mreor1z>hTk#eMgoUb8rWhM#_?wA#AY{8~+MrC*PxKDZ&E5Ao^7y(3SP0{=Ot zM!fN%OIWW{Zc9&wsGWq`C(jG%{1tsP)^IpaZY;6BDL`^yshJ#1!O63nd-`H!>f|#b z_iTEvb|05MXyHA1DDV5*6H6-&#GmZeEr^fTfeXW^8T;E}IL(Q)eO$|tbsoEKEJg55il)vv_f1h4ubQWpYKs{>efc7lb772~MoQgK?^w&(f zO&K_(ufJorbKO9bEq}#8P2!ULl`U6D=Ji8iVm^ZJ(r@Hma#<5}U=<=$h669Ya}MqE zZ6?ipz<*D^Jco?G;ds2z^{Gn+f3!NySH-S^ke+aAOhz3{9lLO_(M906(%YhTs=ArC zF`AU|2A*u8jyVa;OJlW-Z8g&u-ZX(6x8-73K~PKn8<_Z0J~0@{&^&NMQo{E`8<#mi$_DEmAzep9ox8sqr}jNI8JIEG+qUKO zRrX$+z?KGS3~i*lWamPP6>TXG09QQGL*p`A$cDBBnJyBIHK=eE^je-a54nF zOg7Z@R*+W8TV{c4HNMJx`YMDdYW?X2kEVTxVec{tM+4vkMt(?{0`87H`*Oa$$Pxsok&6BLbV)eQ# zT)xxGlG&Ac$S~}Oz<}o_NP2_Yls|F`Bo1IJn4UupvXUPi-Z+>v-KoxbRhON$|LyC^ z@JU8iACV{x9Buc22a#HogtcR)XuCS?5A1rWGq#C$9H+Vd9L3LvxDh8~KiNqEPgdK( zhx>SZ)l0j5w{L40#MNKb_6V)Tp!SmJ)T=0YJ&a!I9scM11o!ol-bKS+D^P&)+WtYh z+pr+b?^L=rNl%rfMJmQY#ULk0QZecD(At*bqPs#6m0d4rAqb-vac(O;6~Lz|qPSTi zA7lTjyPuzA0{yz+=UA1NdxI@56x6+_dI7){B(| zmz$wOUNOP9I~I#}#%K(C6R$C9LceaeNY!m0E0X9>DWrO4?K8IeL01~_7GylWYt^ZF zvcD)u!wo92Oubq+TAr5rai`~r#8*CfQDE3(D{@Cvb?i0u(RLM0$PS0uPvN&vYTiv$ zEnEwnITFUT+4MZE(;d zI*nD>!Id7O7!dxg;}$>mo(L}HRB(ux&p%L31#OoEs`h?@17jsZkev?jBRZA}`J$mH zc6P|T0sG>!wkI2;lzZ1krzU8q7&^w%krfg^#aWIbk-l9nzswvNV{P|mfc$#ufjgdI zo9;Ik&sj@p;tmPk-t-CO)t4bH!;BoO=ZcUpyWNFvo{*%F6Dharb=4EI>t^?dBxc42 zTYa8c{bB2H@HygsyPisQvv|7ws=r*YPD%S92iBs^bbNl0df7uqmDoERHPu!m26SGr zD4=d)2TDA7C4ZW7y;Ln=O=ekc|F!$IwA@R-q`{DZI{3=KG}n{FeSukQl1azHt!+T* zx1rwj+$9o;?zhik0tt}ZXlyQhGoAl~-Tw2Ew;_b@e9^+HfqW5s?BTQPM)`Ahf;K!w zI|_{_r{hOIt#9jx#H+O(yMMSsh|=y02};Lta3W zejI!NN8wVuONBT#|7aKYAv6SE)aZXJK?kdKZRXncohFS}BLbH=LuzBEztQ-#4F7uD zHFji*9oj3?)S-1VT)cUDbeLF>*i%!&wAD)$_?f-$9D9?bG?m>nEAJ2=nUq3&D~-~tBiaTmp$&=bBa`5bZeLUUZp z;;}*ZeJXz3p*|<2TkqSYC?Xq6j==6?eEljO zO6N_nCaxFe0`H$a$&&{OzocJqXAtAq8`8DqL|iR#^JNr5l6QTIHGXj|@HBU$(hZ+= z9*Q+?KRqz7;#e78huj)z#H`QF^Nc04?sH4MS4c7tu0mdlXq;K428nmb*qt)8oUC5v z=^SUjJS2M^x`2l^WQi%1h;2Uz0dUjt@LR*vM%d3<779Z)=P641R%UQ0lEOn(8F4>~ zpGektWV+mCo#E))-`Y<(!}aapHr=VV#^)0fZW}4~hfO03FVx;+wx(l$jPb{s=Kv}< zY(H|jj+yb=)+ldbyXL>fQYFU=qHU2IFj?%#`_gr>2>!*`A9A@34Ecag(*C?AJf70s zZO$E06fX{pCcc&g1b$=g`r7?~B)Yi^v1p~}QV6#}Di{A&V|v_ja_N)*6jvZ9r0=%O zk=v}jzp(|-{|FoZ^`N-%XTWZ7?cArmvKZhi9$o%BqKni;wv#tX8nFk`OvvO?wC}5? z%{?I__XKIBlgce-vxYos$3GIl^w)sS2%eV$TFmDIowVlyWy2;vm50bn6>}y5+QW{; z8sc~hS51u^8CRwa_E-A~TdRvx`vgjay4=S5F7yGB90l@SW2+K!{aa2x1k%k5C(z!m zTh1##K(%7D!7X*Xl8?^e^)8vDlGR{MoJq~=+amvG=zKQAWz`bi6(!ycdX5{H9y{h? zn3(T{CGr2U`%TgQJkW0Y3zL^z3bmO&*;&-l4ObygU+OUQ3h7Mx067*R+ z3xEvGX?! z4f7`m_LDQa8{}3yd9|-%vNK9QOa~&dKwO@y^>fi2$mnJ&@G2h1MmJeG95DsOT*5e3 zI?lfkmGz8?g-uQP4>#*lbx5jx`ctE38~Iuq_zTXR=v#$GOD3u4O|Ftb>kCVeXCAF^BHj40{cai=k?Tj!mQH3XvQpe(f@Kgz;vB zsCM&;9Srw( zLbV-zxvmEm`cMo0<@E&vMdSPj^$HUd6r<~98F+WBWW^6L`zLcmJWTY*tIfvo#ghbf zJ|OK1`{?rO`0#G!%X=Bu@_l(DsUahxJIBENHqK_~H` z-{2eJM_=nsBH|{0`Mtr$f9GoUZ5EvKf9L8Q+$kHWs_@HO;%7#g$wNCsx1gUps8NpI zR&A1)cnp&Wt+Qb@Z!gmtW+|wxZt?Tx40Z3 zbKk$%My@V~sfCILyhK4^`(A0~g`LzS5j=Z2;_@-353kZ65mmUU5QjuznJ6f($%WgI zafsFLKeYAG1c2_qqcKEH;&qB}Y77$vpYM0Ba}?jz|In7CwiQJQ8Wk4t`@c}8xP1Np z7*F~C1Y!P9XHxgPLZ*#>b34hQaKsr*nnrS-A)|*)XH8^t)>`D_BL(CFMHDx=x5!7- z`TsN_1qI*bzq;@o`91~3t2_UH&cyEkhjYuTO-@d(uu@Ra@%+thq*49~>S& z@BCqH?*95Jjp~!RVjBwy_f=5owXpW}Ysqij2g>!)!N$NE051AMI6_49dgwo7Fk+A^ z699==N1wu+-$;8*$lg8Rc?ywq7gH2|{eaZp zut8}^q?hPBa0r3|$5)GOP&H-qUxk#MqYmVr87SIw2@KZW<&aLm*?5u#ylPNel#CEw zl(bKJb}@cxTzf~NY$0LJ;aTt@x1`Y#J>jmKYZuhEV%aKJ|sz9JHOsAxu7^fqcy-$ zL^-Gb3ik^o)B8q`l7(u@q`G+{LV_p_vfq&$Bws4;b zUdBK45wHo^2UTa0YFz0DK`e(1z)JJG!f!DiOPg_FGOa`_phYk z26x)@f*|%~ISJa+pmU;E{~c7SL!Y``<3{GwsNT9p9~Ib}I^4R1{{(lk>fvxnlL&7U z_$h9amEz2HAct_yTECaX1(aBv1p3zH(TW0Z=GvH+=)~>U(e_j>TZ|1U^sJ}a-HQfv zVkj_7ci8?N$~U;r!5OAzZjF`L&Iy#U;K(kr^-(&C82?TPBFdbn#{ z;!n{$o&Kio>m@Ty^2ztiuqzYG#9{zKbIpuXz!fg|Y|hs;3wySQ@WR(ozxX%*VE?zC z@}CKy(;sQMqg`bRpwwqKmP~8D>zZWD(0++}=!~L)Bv}2iUhpv2i zDvo88$(M-SC!Es$WE1P>8s!aL`_N6TFWE!hVWCDir-)JuNLl7TFwZD|TaK9KX)dcM z>y&zJ7F!M|F?MG!P#_N~C!gmLrZgO7>l=t_YYkk%#h*5c3*NXe8%1-|qI_8W;Dksd zU<+cEXmypPPhJJNEEE6YH{`}YXMQ4T(qC}N9 z4Q7)XIre)eXr%9AdT&sWSBdV@=9<0kRF#+3U$Y>`X=q>M_H zo=uz)8YbWQx3ae`@a}& z8DMlBlslS-;Cd=Od6pj=dt?pkDR%pP7nh%`=byq=?BU=4)$re zWHyxrWSM(EzfGPh3^G@)=(F5CuHM%yf)Qjj-l3VFBrYG+DpnUZW;wt$JNKU?mO4Z0 z^qve3s}!#YNeXxD-}$)7vNO;$jBC}2SNaw!$GgV{n(@)uXH)F`7OQ=5`|QmMH_tlv z%ww|dB^0HM)yX^)LS~gncm46l^o1@|h0i?gAE+nCqxe1ut|@qo(RsG;j^C?EJDWTc z#O4|HcMbrZ?s8_?B_s%>>Z*2`xD;n=Kgn>|^-9ppZxDJetd(fu;I63%S{%zs2%ld& zFQB*Fbv?hR_SVydVvkV_16hKcEBzyx?){Q*v|Lo?{U)FTR{{KfcQTybS! zpvb}F?U>IH*c?)wH-7M7gv_P2?iE}_Za};(T_Y(Y8=ZKXVvRAJd(v&NU8KR)4D^e!=N3T>a z{1vs-Ru2eRNH$vf$!eMBm<3e>ZMN9LF9f?kuaqwQgb^1`8GVWy3O6i!2GYE}6IH2r zv}c28QzN{__MJZA4UTiopOAxvwndUS&jRU=s{J-B_A?ax)-wWJzMc)!R`?eecz2fK zJy72V)ySn7nJHcUF!C0sf;&5j(q_&U$(`*zsVO|dwNp_ZulA|>Wka7|QFcI}o&ee7 zwOW$(S-Ez+AQJLHF>qHmBm|9E`P)^t9pw5VHd|*sLteNmtT$gRRgQP}{VO19uZ+s> z#pq)rkS^8Ac}%<_pX$e`f*#Gj&YA}Uo}(8u1VsuPNL^<-^h#xM(hr|pqjp<6Bd$i> zB8(hkN7gCZKCUl9vmCj9_K^IA?3vcS^Ks*eWqpKqg8Dus@g@F}a>tn;$m?&WRrf3z zefovWGtY|bN3iCS7g!W*UQ@6`cjvgTR2^mLE_r~3@%HtmI0D|#AnnDvX+k+<>@IX zwl4l{*R0unA=Tc?&xE9v5T9}60xkcUC;wV>efq~_zOaICS(%q@K47%;#g!lzas8m+ z6_Q*D=$3j2CliI}(LW~mz9;bslozyZS#? z_A?z4AO|7PaVz-uN-J{8cqE})w8#W6&7`Y6VVuj@q3C|T{tNWtR8>63-8TLBJ$XGz zvS-Pi$2m3XyzZ2{dYe`6rrx~*(cppjk^-T*1RImr@7j!XTiPr%x}ecLUT5=Pn&IG3 zMZYL{gr?-!VO_)v&x;!VWB6Z0V7WHqCdU5Emy(0$N^7F;>tXe70+LruV%>4-~@)twAGDY4DK6g#~=eAd)`iID9%WD`^;sm_&U*i zos1){j+eSXqT?jBo|YKXyIyD$6b0@lPF25pN4dc{M9T_uw!I7RxQumnDs1fLH_#e+g$D{NR^=;Yd; zs6J?I#D1C)R)DlZb^5=i6N{ikbMKhdth0CHM85*ep1b~H0;A3BJEku2g3x~XQfIpc zAzN^=AqKJdoV@;6T`Mr`_E|*;d6?XedG;(XRO-AfD><5I$SyMCG-}m^xk_% zlpcC-QGr0HLg@9~c;C-+X3os{aOVHcnKNe&-!ePdd$IOfzj|HQnv35Rg2I2dXh)@+ zc?37?+ZUGlsgG+|CG*;S0fKV%dBw(C?*j^cA*W<#&0mI8z0PeUtdNt~Kj`(pxo`>s zhQxavBYVjFb}^Gs)IN)P4w+d$#?5%)W9_D{Vf{(oMlTPBmeX1{z4@db6-hQ%<*jgL z3}B(!X+QE2_p3o(SEICBrOhGyTORG0?zKWqAequ@#qmS2fa7KL=hMsR59hPDp)baY zCJs{b~%v=4s42$-g{KIpo}jGQRxk zk92q#t;mx9zMVxdAK#QFAye#mMY2W6Y466ewhD8f_j_BDGZg9JvNgF3i&{lQO+k|K zd)OH31t)1=aBIp}F>H6Ryu2s!K-Xggw5`24@oJV{w^iZ1Fih%@Q9-d*^er`ahW%v z_%QNRd{pIkxTz4kqgkt!Q$ImwKPh@vj00(;vf260)dZ!6+nxS)BX;;fBUg%l(@Gpq zCgqspmo=UIZTKuLtBBHijqu2;+2_mOyjrgmlK|865|S78qAjxVGGemL%zGuzgA%LF zED|=kM7&{>v&O#os_l^?u)H)|F=~41+;M5MB{rYV;zx;#>H{8FsS^Mz*=j5o&wzO> z`v;tdee3BRx#}1)HrNtPvGQsiOlS17091~np(@IPGAZr(8>1YGSa08bonwCUL^mO| ze4DGqH!%Yz`x|&Cw$c4~P>3}ucQ_(xqq>D*dop5nL`&+<Q+iXccb+SaF+gLE&LZvS(;|4RdSr&}4R%&?ikWnBC< zs%;pFN2T9J=Whz+8N3`iBZlHe%)3%2&xLUm7Tp!hfCk6j8N{aW_ciL|$Tc&8*5CDG z4tr9+PYt%e8pTrHsZYszJ>kB(^XRX2H{%C-vw=$!0j$QwM$LM~H_cXV>UAn@2eXU< za8AQ^d^}T%giKz$+|DoG@WzW+TDPSY7R`JWJ@fh_(@Vn&qP~@JVr#aH&uQ}z(A?3? zajZ{LPak&c+?g;0A0-%KTW0~%uyVX|jCgHeKI9&{9Xm3v_|!xDF(-Nz_kdH|6UUsQ;SNPF&9w=Hf>hrhoM7c7MlG%E;%(K_~tTd1P>Yt$Ee~2PQPm$1zWc~9UTF2INp_J!N zpAI&rnU$h${S%92fZx^~bbFs(g(rBzb1?|ieOhJ*Qo^@O!_4Aj^V1Lr#Db$c3&11qHc6A7Fl7CuI6Q(H=zkxS1JHK> zrWHWrkG>ZEr`mYy??-^-aP`QmLZqbX#^3k-x7-MT?nT@GEvH?P9DXSOGs{;+O5iU4 zum71ERmzzFd|LyS=VB0bg|`px97X${5$x?1LaYg-C9>DQyOr1;CJA@1oj~BbrV7|! z9T430y|E~MwR_c7ot6wYC_eogNco%aL0h*(l-x^w{UN8D9lMuk$YqXW!>6$xi4l7N ze|8#Uxy#*V*8KHBuhsHx&~Wk&q5Od2@If@B&!8*-@S{cU3ix3vF+*Ycq1Iqvk|_Y4 zw5w?cs(>IU)YvPjpS$Xt>c*mvHoJh&{tQ= za;|LpWZvi*afiVPx_EN*lH)<&*{F(EL*-a=L+ZtaFL@7(hxBFUCx3Nw^A~N+Q|u?61WDs+`^Z!wU;l_Ma}$7{7{#UvhDmXZnMSE(_*&pxR1(KNK#O z1O}O{`J*)VT1zr~>sKUCwn|C5v8O*=9BPCtdw9&Fo6_Jl1_|lvC;emvENfHDn$MC} z=U>_So>I=>W*JpC$@|QnV^%rsjhW&Ul(T1Qa;*o`(sCLL>i@Xl zDAYh@vc}>h;!9tng#&~ivg*W`zPe0ef{@jZcMuW(Sg3iVm=p+LM^JfB3z_ioqtQJqxKXmYya zrQd695V}v0?IpEGuRY>y2_yw@@O&@xPglz=HN(hngr)y?KLBYRQ;N{@%~>NDY7yKgQRHDf&y#yKD*%wXC-UcK>m7{>gb&+@tcK~K%7}APLVTRgNvU6U==jgX zOkpgx=2pX*xHco3rT$ecr(@2kA(+VRIQN3*UXQHL{TTg!?b)}8d);lfph@%$-%i~x z&vVYuf-fvQ#Z!Lx2`AuWWF|fkHxMSf8(}^WGr*qMA{M05d}2a}_XO#O{CM9_L|Y?>n`fXZ7ppADp7S`!{(Fq~ zZ5n`${MTs^0sFV^V0DdW%QcaKD|G-K-oJ-A`^F0$P+c(I5ftsC>YW{=!}>_pUJTop z++)nT1OWG%X_?~g>e3krCAymo^V>%)er}sr09oXCXW0@1Y^gT&9NoYl0zScqACJiG z9U6P~Di7|WNN(JX{_jkKpqxT4Fsm*zN1;fPb|mA+^GKR76i{*W!N{)WlZPwkLJJp% z(Oc1(!-iFF1n3t9Q-{~~yd8QmV}Fv<85i0zN3p|e7cW&Vf^ZR8y6#)i*548{yH+nL zEbQk3XYsX{I1WM+saG&t(q z39^6RmG<0e_i`XIc59|o6#an667jiQx1=AjhFbzbbCoY*efHR!OQrW(3)J^;j^n{i zN}2j@d9G%Hg*c2-49N+dBs1H84A0b+iyL}J_)mTfFunjiNVorNhAYv>;FNzy3Up*{ ze|pRM?+<}8@u&2u|8M^6@z)Ciprw3Og!v!$BiU}>LX7@e#9!+giiUW^AW{_zje)!V z+YB|Gpxabd(`Aw*)V}J0^*EeZ8QOn|4T$B;)fB$ICTV%d&!OT>&1(I!Lz`yp!4_H- z`gAwpq1tjVz6}R3Ht)aHCxD^%*ccX*v!w}s>WX|tI9{@@foprS`>n!Rt5dS;?Yn8! zc$XTTMr9=+YY?3jpswmNp*PzbMc%Fn`xXMiS z*+dSJ*%yEJB{->TqU$W{ay>+_S+@TfQgNTR32^Atz*@Ls4nEjLGB+m1XFni)!~FT) zRn_cGbjQ_(r=q)BJ3#qR7AS^Y<&~nSlBi|&m%^DFS8-n3)IZg^H;B)6uqEmbU$f$z zs~czlx*iS2Kyk4?@gYw%9h6e5KNDl$EQ2eXkKxe3kpU%&`O+LwI;&K3M`8BsCw4w| z?gjnI`i%}B+~$SDEfAH&hQ}3@njAmc81zPY1GyQDv*P4N>OwfIjBrA0`}49$&sxwG z)x;{fL|o%EMz1w6d1t8~-m97DCdZJ;U$zcG3d54e;|sm1d*(_CUE}sa0{B&y@ZOZ% zj2)L9fLAzg5>r{9O8mt%KPqwAa%J=f9{tP)JAQq$%6mki1^xKi=AZhQ1%+@SEm3ps zUdQ0>b)@)3=1#U(ts1V0s6m!q>Xa&bLZgid4^Q>}-;kG}Ka$8wx_h1G!{e217pC)F z`Ap*|9XVvfyXbj3p2lPF%RbBXWuV!YV>jzcaQKvrh00H+&hOmi(7Axq3F8r)+z=sD z-=D@C=(@G18nYS=T71k$-HU-bUhrDOK+|E)i|nQ-tNpMR$&7 zi%e~kU2C)t4YoRIA}=OC)^FsO#^tQ*W!<2-BapFPexfrumGcPvi^E0_{d6FlVa>a& zhgVk)*_<5Msyy108Mu60xl1GNNWgKf6mlpIHc|zlB%?(@PE0O`%3L01> z1V7NL)3OV1jeSxBKic^rsKf(9$=lBST68PcDFe%o9(1aE8T~nE!gry<$o8^39v(mH z_4=h<9h&Y78eer~VI9&^TF+Nls?Nnp+7!6h@J3h0lii{tz$5>g$N`(@iKfBJrzN$A z_5H)jHXK^kaGL~xjgjmc(smG(JOh-QY>>B0Z11{{p|!Jfygseq8DM1XT8DG^j-6kNSCQpmHrx~psALm`x97ikN#b6Y9A{0g=ZFI$+Sc+FC;CZE9d(0 z1_YJJ@|_x!6DS1g(rU8wl|a+VVPxYX&DEMjF#4I>_KwL`D$nw*vsYX;Rqg=-D%J|! zJhdM&-Ml0h%V#&vXMaRnjXe2EvS7b&{FVus$=qi-JIZ>(5LDG&VEU-guInw5IrlhK zs?B>*Og?5zbsfeEKLC<5BFcYPo3p0+?5oQn+s~haS8BXY;$A0!#Ouwe0;+CDxhe%Y zKrEG?*=M9^_ZHol@U}Xc&67uwFniI%3-ddzu6KgO#dzDsagJZ(xC~vy-n{z&G<}Oe ze1yDE@S#9Z5byzv(^Y&+!)7@hgpo})EVNB#K@?rJ0DrF?yD0QMTqELmhlj^@|6l9X ztuANZXt%X&Bl5IgQcFKaoZoMKj{mL{QizL9do<*W{!q3*-%vGkwvtJa+U?Pwre_sB z2G9m~=6Pq`whuR?qw^a);`!dDNE`G=Rx$z+nnbA@D)Q010<9z8sX!t}M$b5^>J9@T zo@zSKq10<|$=8HJ1CbAW^duiS?9Hl=3rgRWL(&QRV+5;47ussBbG&|6jb^wp*1`AZ z8UbEJ8y%sN!7KU$aSo+<1!7!uvXb-JH9yL@*je1=3M*rzIaN`nS&g#5X&O1toLRzC zMpM!k%AMB12 z$-|U$D_u)}HkHpDHZr90LW$BUuC;yeTjZ0gNf%#~D(joW)pEOtObyx$2)qNG;8Vn_ z=Wn^Bb$L1`1r%2eZS_lpAf<}me?ZuFxQxvnK2>VAO>QUI*d}8K63yi;*cenrqCy+N zQhTs6Xz=F)amW0M)z3PiJO_MKme=Hv!6{W-^dU|QSoF7niG5qyA@Z)x1L>b4G(vZu zBrfaybM77bdUl*Wvnhx@KVxR*_if1lphgDNaUy`e_2aa3@%fYt=f?bK%kRRIvTq@o z?Sv!En`1+7K;yXIp-)zM2U)?!W`M?G zk2aY<;Gm>60v!o#llF{AdHcWiRA@Lybt>iOXa-uoo@n0GH2#Vd{}Vr0sA0x3?BTE} ztF~`e2$ml{dY0EyohrER(BzNFJ5H_*_H@K`2yWV!<`Ru(Wm|dQ1lhR+Y@q5>(kpf( z4+Ii2d%v_ws;jANrq)Ej=}`mmn*zJG;%6%h!!nb7O{=DHaKpZS}R9s}D=6)!Dwh!tG~;1`{~~xaE3FpJ#=s1SUU` zS*gmNWj#l2@8t0773cud<@ZSddVZcLWVTf1a3M)zV;r5i@Txb5a80Sm-2=T0G%_Vl z4xe+S#-&?_FuEgI^9YE51jdm!x)C0`|EmAt{TxL!j;;o(VBwCdNx?{b*!F>uoD?QZV@4x zlo!KT7M3Kva8G0MBxy;1Ey`bilb~cjvgbj8q7#x~X0H2~C%bb~J2-ikkRyq>$g$>0 zAMH3Ke?Nxv$wdj1X|uEn&|3ygK#7ENm!OXo)`Zvu?C5>Dw+oTa6W&MN3(l`UkSuyF zWGt^-oCz{)+SD!}T~{LNC@Rhpgub0!UVm}ey+nOidkRQ%28D44P$WVw+1ihWF z+ECyB#`2QmH`&1as z_5)#X8WKuDnXhO37;LZyL|%uepLmP^^pnzNoNl+Kxou4G1*0N8VK!9+wV&({q4&=fKkt{_ zwM5JfPH)JxpSXR&wRb8uSoa9p$0%w>zpO4-_0R@EH6)m>$8e|7&?iE!lqeki&tx-+ zc$wmrZWUmHk~)gEcd6@p*IsO0mdk~?p3UESb_kJOT(oz{w;|teD6()(O_#r=ktlhq zJB`m4Awxc%m4N@NogtqLNW`dEh~B=qB_uV&xxcrUNACY371OOT%cRCAC5Y+*WZ2R6 z^|u$G)NLyOUZ8>`eAwL@({!5LBBUZ{CZsVeKS6pL)-C}3)N;=zRY!8s)wnPbw+ayz zm<})Y4+r%Hpnb zJ))MrV#Du=Xx#i9fLHcW-IF4il_;rwd4Fv+Kpm z4|Cy4@-PwD8>DaNC%I*U_&Z+oB6nG0|^4yi!+ zzOcYI9>+(zaOD!@-9KI8K($D@$ZD-FnIbBvlZ1VC36X+W)4d2$0h!~Qd*GQ9kB0Xn zu6yV4$MNA{qH+=d2uLWvNt|Ek4num9fHzM}5CIPpGJkz*km;wCeER#7llun2)!0dx zCswQkshGboVA&?2Z)$~!U}R&2y8FKQ0AP&3Tny-iF0)x1t|u+AS#O!-Yo(=C@C-!< z9;)&1Q2n4g4%KFb)(Hgux%(GTX4gU9S@pUDZ(VIJnRII7{Nd}4+ey}X%QY->b<$IX z?`C(nXnAb9jlI%5T~LvuluV{oBC*D-bpX-rlfmhWt0vQ-ez7MAFOge7ZCWVB~m2$)t=CU(>@PS>_e4;=CWXuVVxg&>d>kJgLK7 zie}NGqP(>-k`*nE(dj^x7-M6&#D~Y!xp3k!t|<+d6N>^r_~VXPn}<6hnSEB+8m)Ii zx4xtA@}JVlHCeMX_VUlUdG~e_OhS6L0kjN)^W?}&USrQ4G3PXp@F zt+cG(L**{G#qGZ+FGRUD!YIqD;8@anty$1^i%IWvgF4ot?tPe>*q^(4`+MyBqP|A6 zJ9u!@@lkU4UCK@#iD$jrm6Z3L+vvh*xQ|{F@K&w-;lWn^reXYKM@cN@Y9NE8+|JLz zjvoez9^Cx1LBIDA8$TRIa{dLuATAlX^+)C0AH%r-MT0YZ@M-^MK2)QaRgKNxCLUuW zErxsZv^<$u0f>CzE$lU_t@aDilV0;tY(?pr^7(+YMfzc5X^^+^0Y!OE2GmO@n+-}pYqSIy@x}o9lX$vcK?;fxaW5Rz%%aXKm9`f|ZMo-nS0(whoVLtQ#&s|woYQgeTUy?KqFn|Nli!KgA3F-o zMklGaV@3#CUh3fZCtfAS+b~~;+joiY^^j-}5gQ#e$L{rbx!o_-f()Vd3j)15{ZeuJ zVYHgGUINAswND&J1{sDn|41WeM7w2QTBgF=x;r?LUVWJ^LkmvA{A>*#)odZYSwtq> zxr2G>B-|%oo}DLJPL5>wR!s76#lFdX%c?-`Xt;8XZGm!)ebx!Cw2`xO4fANgrR*ZDT@w3cfl?R_iaO2r7? zBjaYht@!bk20bzcvK=oJ=~!KT2J-Ti0>mC2*ihvSbI z6B-BZ;Pf7JonAVj3%?UWZ7Hc&GRyC7dl?=OM;f zhv<_BaGymvk*^riW~I~1bzb=I8i|noCRrGA4re@57mk^`(9y#UK^oNiFMn&i{T*rQ z;x~n9zT6i+Ia9Z-KSXzjJzk zfLCDWTTr#b1eOLYpDdm!dK@4~hW7d#vH~x@E8!0EmmRYLwYmreen#g#dfRylQ9>`2 zeH7YQVl5WEFM4<;zGqS%*5D;##pqbM=(gh(z-#BpmH08#OElMN{jEdB5^6FKo4Qi$ zt^cu`*b|-0m?7a5{Y|1c=jJ!^8KqNYaYf->A;;R?cY7)%!(s7Cxg>KtMIf{v#fJnB zBaQ>ut@*q=zq>h3@}^h|QLV4h0|a?n71Vob^FG5}bl~GlvU9r~0_ljOYeZ8`&G6<6 ziF3R1=gP`HDd*=x_V<^$L&R-Um4{UxD&{H>ySuEh-myA)T1$A!*tRRW(3wvuM%wChb7#<<|OlBBgXY-xz7${ z-FrV-H2%w7-JJrFmhEOlTuq4Wn^}hG!EUj@!4#h#96H&C?h`@jI%%yddAOQBtIj~j zTm)Rqm(jjODVZ_;iz&0p_T=|+GL}b+XI~r;%HrOcO+I_@pDHBtvhma_rX{DJ@8D)c z9wYjUMOF_;2Ggm9Aw?(p;AL2#L0X+pd~ijg8kB?~ns625#69o_jP@JIg{h#G8Si&> zdnxYnL33-kAD(X5jkfU2KNtFUfT1V_bujP9ZOTcw(g&WLC&)&v7N>E&Ii~5 zsl5x|S(VG3jifP&cL;>otODa@EhW}?49tXzqGyhHro7btF9`=LFOZWl>-Gxms7!kOAAjtv?*bh{!`m?Ac( z6ecnk!ia+(o_)Xlz6d^od08?GN?Sc{ge=(&mSR@b1TMAHw;>PjIiCtk*brEU3YOR~ z;vWhtq?)}bLPf~#{|OV=*j&*QvOFf@$9ER4zwU;H$=$%lD^g;N9F~Yv?zjIYtURn& z0XGVhj?gWOOkD1LpikgmapTMeA9xmRavy!s^=x7vtj;Jidf0y-J5KR<&~eZw%`3*? z;kBwJ&gJ@b@k=;hzjSo<;o5OgFfiTMly7G48_R`{58>Z_)Q|4<4(qH|MT#G`oW_LD zSyuc0CT`g7$Y^T)Lpyn#y6L?u%HlIi452K7?>XSA12K0-Sq4}^e9R=^!*K-*$XUtL zdU_L|ES;E@v+K?&%7bWW#)?w>OM8pKKoW5O@b<**QD;ZS6z$eTN(Rz^722-V^rO?c zHvPTY3z*Dtvn0CyT)M$zk#;v;5Nf=YZMnqbF9_us_Dx9i-ntF9+VMGAP}^_B`^PL1 zcfV1>y$J7N%AElA@^eoG$Tu%;yk7s#_f@l zB6`FIU%oY8q-=Y?KT@To$a(^uxKdirb-B2%W8qQ~?Eo7WA*|u9K_ZW3OEehVRm$kf zl#~W4d^Y2&5|Z$o$=ZD{_~&um+|JyAbBBaHV*F^P#{5LUE%|t$I3-H!i6Ln*iO$ue z`*F2{LWW%n$Za2!$A6L;eLT8bN{#q&zub+wH}kAV>X7R-%S+Gt_YBHqHrgvQIp`|Vf6zfgMao|Tyj+prUX!fRw%|VT zs|NH>?yM+}8oP zE_97Sa7E-ZVFJ(PZ_~u(qh9NErM0r8%=;b>E-!W~1)xx;knb>sc2w~`MD!|b9w2;qAr_h#SJAI|fXCN8gl zINDdD%@Ix2CE!}D$ic6 z>*HrXL4|TD>{|MJlf?w9=f+|$iU(7_)`ps2)v43*K7vPHE9EBFtgVF=$}W0By_AK+ zj>xLfC#6*{MIU3T0}bd~1sK{O?KuM>_r9A|il{^vn}*NJU3#vVY70aeTzfTT;i~(| ze{uH0?_$4?gcdhAjL3#v_xrMOt#XESyTT1j;x_gdQrESZdJ8{$-ljgOD*;w8%?6jn>N4Ns_Uobq33*XQ&-HWbN zLt!AN3ht;Lu-e4~G!E^XgxoNPC)b>JwT{Fy3K9L9yQe1t9UOE``}0#|lFKYw(F=XP zYoiR%b>lX@iDrwqj|_sQiny(JPfCI>2jqIEZyXJ zTS9a66F)6Gtp|Zlq^}MyKFPby@Nj4izE)hLQkIX)@H6sy5kTP9>$B6=heLn1Fe*-#bKL2DjZS|{4YdA;i zl%%8cbw-%rqF;zseZjS-{Jkhi2j5Nt>z%>=f#1rBC!3A~Vtgw;QpWeqH|f>5Co6zB z;1T`=31{{_l{Dfo*R56Mi#4iXXF_{~nZ^syBR@_uNcekWAals-tGRCE^#;?Sd5d|-Pt~kd<$VNbO!;`qkA3QV z_N=!{-2M;nRXDd9a9+WdLgxo!>J^s(_=n5bQeY9YP<~f3#S$i5UQ|3z< zcKfV%*9nKzllUI@wKFbiV^+5=55|a_PaZb=7?~{&@qydEHEq-9t}O43RyiyyxNMRr zcl#h4C!1fv#y${>ZA-KsM$wILN!b?dto_{*A3lKj%Vi+WHsSAY&y`MfOzuWB2zxK; z>{TFc4bW#n9fzenRB{is7ha%`#{1mLUgU~k3w3Z61p=U5xZdxydwMbw zP-F1$FdY(Osta3h+C@>I$|he0)|J2?v*XuI#wB=@iVRJX9s3JT)+Iu zsxxdTykdg5u}ih~EBo0G@SpqPoGZi@@3xM$I(dKo7Sng7oZrw}VP88d0G-t{7(D7P zzb6n=dpIJ{2faY`d1m*8mo}EJ;$~MGL~%vWDf_=RZRh%?kl7&sLsfV3e$`GqMmQ}z zWCEfvkRP=O`SnepNQk7=M`Cgn>!V(eA{E~8nxL9N26nYv8m}D94GJbod7#}Y8*i~5 z)<>ALIVyF6Q*4a|dORG->iS7>Gxt1SkSuf6Rt8PbP*$Kt__t8GLL<3oQNOjlhz~|t zVCNGeuybhd7jfUpz}-}wqi;?FpjUQT44sEayhzg7%=Nv0OMXD#HCelu+_zBjFK8hB z162~{HaYi2J4}cl-wp4DkoR4DJktN92C7#;QQk3tu-Jb6U+TyU6M*K|rV3CsZvDeM zx%%$^Nz(XFm+zy1NS&|$@N51>Mg8BUqWgEWmY&$Y$(>~sbDIO5cQ)P|S;ybbs|Oy| z_UAv8Er0x^)P0rIbU7sWZ`iM_3 z7R5Z+FmvPSgMi>pjUP=GGZRVL>_q-PGoGj34aXlHII5CKH*>Uv2XnKNPR1N_!bO0B zk-33-oUQX5ITDA;9cy}Qamdl&aiQ*PPVk*5A@keEyW!SBO&jOy`kLq2&6@C8qk{7p zA0T$c!(;9(OJJ5Di%|lIHa0zxP-Lcc2-bEJBrFdmL~zsz`kXkAG9f-`j`ihP0Mpc$~7!Wh}&LHZ5DNezykSWiYkUh8jb^ zw!W6F!c~oFy_|?&#nGya5Q5?nbeXgdw=*3bE}p@wu+m6eTj9iBWiB=sJ*{&2$MNk< z>v`e@cD8F3J37G`ZHMUw6l)J#=iI5Tz)fvI0F2yfu`_IBZ)s$Axo`Q>|C1opoPDO) zM_~j&mZ(@L6MUUc;ULR_5xN$lr2^8x*UK$AlQO}^BCpo(C4X&g_C!t;Pdy6_;eB;^ z%6py*-c<0-PO-@!H4M!6+%Ymr~K`K8Ys=>p!L&jO}Ps--G zU!%k^v$=)B$a?LyVB~{rCAXm`(u>SpUfVIFrKGxJn=$(aS*MC*46yIkb zmtD7{X|#mqNNXa|;~%u3kp}4a!dHDq#UlG`kvabd1}u`Zq_Q2FGFwX38t@K52kyN z>I!t||3VTFPmr=4NRIRkrvcdax%EshxQ!1!r9L`S|8l!1SA8DIO`5zvgwf2lYtd>{ zCK%#)qoSN{t1prd&BEH{lUhH}ROkPgGf}N>IcTyr-SpXll9f%j5_vKnh20F(YW@5G!f+N$Xy{`usc6SlQF?v;CH*oOo-aS z+xe%lF*9?_wbeNe1ygQdE)BVg_%GEd9nVThWiT{)){fAhAm~-Iu-rh-JXk1XS7NR@ zU@ZsO!KqC1&LjK)cLeFpRqYad=2D!SRCiGJ{@Qd4DLJv}G#z|+qan9n4O0c*qo2N* z=u+jgpwaOR@oSypQBuj7!&0R>AepJItcQPpP!h9)Lzf>fov54Q1p^4vP210Cm7~k_ zzGQ@3@-K($F3f~F;Y*0fcRCcQ9z@^H^ewZ!jz+>}7+KhIkceZ7WOPa0XgBnV+3$f9 zhW@xCWbV+Xyl5^8QWm@$9NY3*C!AhaGWOf6x_&KBGOqhF$~>lt?4>4uXc%J$v`SJ1 zsX^MI)!`x%^?k2?P8JQABgXhRD3%=^_==YHRv(r>Z(iXXtriDHsR?r>T2Q^9t&Q9hXBcT~r=tL{MZs51 zA0RLfQ=K&NY;~t;mRb?(4B|tP`gR1JQrsM;`Z@?itsf#Srck6wX+TR2JxRrvS*>fB zp6GOQ2;f5liuT1G3|gVJCyi4T@w9ZXS3oaVGf~W1HFTyhUPrT`*1o`-+DVQ$4ot+U z5}j<$)NPG8>-)mj*DDNEdT-w8k7UXPSpE^esNg3G3)iT{WLD4C_fj02WVdSxJfBMq zO85ko=z4yx(cf;dYeKD6{N>gI=E@EBy;{Z&aTZD{p!ZjvVDba8HcE}68ms&gdDk_D z?gp%?GC$_QQ_$E5z;G^@A+K$xdIF3uKR+fZdNXGnB_Q=OQq2%1X$_%qZP_nHQQ#k-#i{8%FNN=IG89`EyTBFEeoWVc&Vj zJ6eO$CW9?GUE1@an;v>IVi*9 zk}n(zQ7*^xr{=+u0#Hcicya3&Xz#P!7|ugpb0$@(lEHH$l6^Y$u6A<-aQyoCxnZ<@ z!W)DPB`?$;f0D+@UX=SSE(RpMg{`{cN z4&GuaNSIWdO(r3x{(LqNnP$>sgSdg;D2A5NlM3f%r?hq{?tX-19>2_j`=l0g4HhiM);0KeWh}+#{k~X^Z5HU{7wJrU1tT z4+H2AU^I9cyufH|!|H_CLZ_&(!y8wsHvfiZ-+&+m=+P>7W`KWxBq5T%8obpN7x=!Y z>i-UO?%&7%kAlIgJN*A*M*kyKr*9F7nfL_vRH0BPo2$EfVKyG#&u{L?;}*HoKi(Uvgf9 z=$aFqSv~1#vbSe>xs>}4@7O@yP6CX`(G-rZKb~h_=;9edS{Oo@!UgKjZsoa~`gzSK ziP>{imguKQDKJo+N{q_E;Iz7dog#<|_T0GU4*aV177sxU`qF;|F`%Tp|JlSr2jI5? zSte3hxsG#nYD)AT*HOb)=carbneGekPHSMvZ*mgY4{9s2Jy+7?{xm<5li~~^z|JeY zib!Gmii}f^%n20A<;eexZv;DsGri%KQ@sjp4(W1IQDGCFG_|L+p{f`wR#0p(UPF^w z3GUsbXG6XLpbUP;y3oKHStA@5+}4y#BYYUtRuM9R*5nSAWuKlVNxW=vt$wRVsFhPk z_X;UvD<1Z7ljJn7I2d;&$;9L+o-(Gc!L+L`<(6$=EQ;d7oS|Q>gOw&}3X*IRua|=5 zA1dV(BDF_ms#QiL`9PLFKpyeHJTh4iYP-~+pC6E*6hP{z-6gY{ zXqg&$X$!l`FI9nac9Jb<@*>*?>9SQI&|>}%X-XmwH=A5#!Va_hwx&$c~JjAn6RYSO%dz_b@XbmXjrr2 z9Vw=`@<~#TOF+Nz_C*M#9sdYjI!5;!UQpPnd79A$#8BA!!F*kN!ff;B9O~m(%#$kt zr)pV1zzI9U+Gq7T=Vi301b~1dislRH|1pyEP_>-2sb^CK0Jh3J4ChSay598Vn^`_# zC~r3zK;M2>xG!+nP%PGnbN?JS_;4l6qs$vQZk`%{UbTO4EO@z)JGNbZw?DE|1kEMI zw52oAm`vJ%rrRIR2_Ql~*}~W1Tt8@43B`ja(d4~cvL2!6%WG8S2kFVVkM6F8{NQUz zSev}7c7E{A4j+$~g-Q+f{gx~(lYQ`&{MlrcBYa(-W54^SSpU4da$T@GIG_-Avuq^& zNxp+$vbiZ}dPK6s+$L(_760nJ_oGM^)bLoistufyUYr^u=Xi6=!7rBi@|tyxaKqg< z%3`Na`pUhjo8O#kzCOkwnRURQyTi8|PG|FaU&o(Pv1gg=&_(keyA{uBbQ0Ak*E2&f zvXgX%BSZ2j;$1!Sw@KUR*vG*6+xlDa1RddGwdO{lwkyjNn$|1jswWf8iqAM)Q^gJ` zA|zAVr@#Cz#NjIl)VLW{Ol)V40}ajH4bG7 z!abKGTN567x3GDRGj)114z>DJ$NH3YY&75-_Lit~f{f^*PqN>h?=WR9uChFc8>G*+ zq);P9JRt;VKc)i8S|9JKLvlDU^K1?#_)e9W zgj`L*>C67e_BN-+aDBNBGMnF10ew_g-1grF4_02Q8<@rs@}833lh~b$JMI=_W|sWA zoSUw8C~R!XZ$SQ%0ifGhzDgQ*3X2eu1e8fsHRNcR9Nw;^Kpu1lS}McLs0j~IGqa4A z&$u`T#w}Tuk{*(WpcTaI0RX_zV`Ezr;n4yc0VDeyQLD(?!7fARohlH?Xcl-V13%ga z`LT&LFaG@mu*rmx?mNo=li-e`mxV^sx*-RhUoDfY3IP zhlKYyQY7C7FeYTGT}f!Y3FXbebc^1`7p`2SdBT9vSFsFxU)hj+EtenE9MS8nC~m1!2{{hhc8U%3CBi}Ib?A;<_U6Z2HJ|x z=udju6mUk8kch5sk=^R8RGtia*Zb;^)jJZm1J%j6hXwH{vbm3531{nq6RYpUD)bBK zbRE8h>32(b$qpZuwI%oatfB-48X~yl zHj+&xdUHCre7xM(U_D4{4&M?`P35k*~Lq_}9ZxdL+Rv%+8< zWs25cC?D2OuCcUI=9{b+tC03*j%9j{E8L2{7I~<@YIDwhI%CE#gwg85-n8h|9CEAo^RNxda=bad3CZxuN{-2 zU@CWsLk83^&0*+9tWNO6x>#bs_h;~?ez@Isc33S?268@KexiTh5(K(BXG;;s!R?IH z#<6m~V%QK1?2($VU&YK)Hugy;PZoaM5l=e1m8=)3Ufy#fB*XACfgfAxY6epB~mfR7~Q|dl8 zw#qHZR)|N8sAol#*68hZm@ib-5S3`Jh z7s<{W!Bz^vdZhZS-g5W*E0J_TCauF=RW!KQng z|GcntM=~x=9?P?s{nSPv3#D&N`*L z%Ym(O5--#6EX=~{riEMd>=j!KiD7^k{Un0; zWAkjkay78%QNzHcRbO1@v-;k|XsVMh%(sq(Q;o774r88HYT;g*7}#hx-txXJ_~QDd2Yd{o zGv3|f{Ck+Gc;-lZUhhM#Moa%RNyqbdk08xPT&82YmCh3%tWeH@1D+lxPg<4-qJ;iCfEs>9dJQLf3g zgTphNASkx@j{WF2(8g|((=J^>X1*IksF-D+)R0g^{PR)6<=<86KXG{j46XoB@1+=j zadjxGF-CZEmrDWfg`~i5O!q62i8ep*_i*7=%6&4cZ(2$dfr^_J))=Mw2Q0m28TZ_$3m}=!Ey7cWZy7S9^xQXNUKh@Xj;v(P zB6OA2i%;GxtQXp7o?OZ?>2s$x#E0Eg@V%oFfl8n{P2f~9_o3`{*WGsx%RL@T-v6@b zxIF!yFpi7l+U&a$e}1P_PksxUUR{)#dAlG~N4+rj8`OvBWwA;crAPczAoF8qgOPg~ zbXeW$tpQ!d?1fd?!BX2L?kBg+9~A50`oBV@ z+_FY|(KQ;H?sRm6n8Dp|5B*y2D?|=(hqVQ}?&8_BA#I8i*IYx~(OpAhh>y)~J$@Pb z=h=hKT0>D)>3Y=(xEs4USg*AXQfV7U>M!Ylkv+Sl^CxfW1;yusOx+II!U2?f6Mla? zS*FvVqA`Xx(c}sXB=Mv|r4X-A~|e7kS4`l85V9kOM-KGe^cX$o7+`91}_*LufK$(|`UUBaYLX zpx4tcGVk^%ArZfhd-%)kjvmGu5!T^wf}60+BA3Wx4lc3H2>BtgrpvcP&%ObEZCh1W zClhU&CCPQN@w1c!Hte>lYhRbQ!R%l_E1@gV4D{pfF*t1dN`GdbpfbD^Y4UJuMdYOz zA>?V+|GMSM`-EOwx%n#3COyD85Myp_25P>5S|Y81mHcU?7bNtTk8FfS?k$rZ7~#67 z&e|ohoy_f-=Vjssp5F{gR@(# zB7R=%W@t{(5sP^oY@}s4pQU2rB86PnrJg46nL(pCnrTt?vZ2HVZMo6$41q>F=ac-- ztscLvjejZZ%*ll#ZOHXeQBj&lV|(eSW1SwJXucm}TRgE1C=h$_K0H1+(>_shfpDOu zpyp%wFkh^DV{*>L;A0G>zJEMoPVlSIhiB;#FAfBxs!tP$v}j_|uO54Pj)ILOJX;ha zbYEOO(yAek((D@Lv~M`6QN-N1B0u9iKv`#7PGVYb`cI2g1mK+B+agG&#Ov{ztMSIv zxOO6iv(9Zg=(rV~@zz(!6uLCcDE5?oR37($S;2Tm7K;4wSF72D^-`$uXX+mvQC1qK zOd<7wSa|y{7Sj3HJ0PpxgEWy>Q))SZ8$a&WN+%M~R_cj)AtnXV20S({_;3L!&NhV! zLB^T-aFwYSEkUOl)AK9VZqLnlt4Th%?sA{re;?Yj$@6PnY;kFa$DDm(D)kTuOXL8XrkRLf*edMAY1+o2=_?_A_*n!vxH8l&c zbz8s~v5rd%Vzmuk{U-OTq6BOYIm4BG3>tQRrGu5vK}hZE_u+4`w8w0C>>~mD zFYbOD03l%bE8nO(0Sfj=Kqv|LkC!*Q4IZG;_P6c^&|+>h0%B=zYB>J?&FSx7{{zqv z_%}lQw|x8mn)+#;^+bS)43(`Fv?H0bSPNYD88a@=O;^OdB0B}ek|*zj7|F`@LvM5b zS;sCED5LqBB>H-qP2D2uyL?ggjSKQp_m^vtb%69ib0B<`j&}K4x$m6yO`8t2-K^v6 z5S#Z^J6lUr_I{P0!!w|7>oGachRGx9Q68&&+|AExF06CIe}J(8qlhV1qE$yqX>Avu zl6jMVVHzuPDoJO5AWpCJ#Up0FSM*F5!dsmk9o;XZ!$uq`UnQWvj#nS>Nu`{PsYVWq zgOE`P5__^20W>iL9l<>qzkw0%+TVNK``SG}H@zd1U(3=(T?p9B3imnSt<(LbyAq<; z>6pmM`^BG4A)c$6XmF4!O@Q&cpME&SJac|o%NO!iZjdpi^C1?_BnUaos-M6|RQ$%r z?4due=`;u>CeU7KbHUq_@t(AW))`ki}Ch6 z0`^p0k@>M7ZK2i0v&q<;eo0Tj+E6pB;8m1x6bP(ZoML?~^xhYIrq`Tvt+V^YWBEv- zJU_N+k=43YG*Pkgi-&b0$4sAW$o$N14or%2%te7!#Vh4V2_=l;mgB`)xICg0(`b28QQZN*CuieH$duOnA7z6%um#6rs_UhErT`>_I5pxOc>2M=IcXx3)O9_TLurM%!29b z9J63a(DJEHVWBcVL6RboEReTqyJU@AIJ%fM7wBcCt z7+svr4NI-#v)Rs6s{@WnV9GZ}`MHOo=FeumeY(2ol2%AEdQR$@K2|kj=!qEIi9XA8-r%6mWz%kpT(T$6;#NOU`3`7HACIn-AGxYFy{miy6d!Mi;vIcH3c;3_mS=$WTaYoS zss8W?r6>RSME+0@kjZsVg`P|Eh;*K1feJVfpQB$d{_5@H9uGW{H z{sj4z9A_dB91$8FhjT_&Q-*U&xM_+IOHqxhZqnK2_j&6D3|hXwHW%>5J#D8m2?kEJhGxt}@ev%=C#MAiT$dA&8;EH|Ze??XF>T$d`jB34BWc$s$} zyQBI!;;VUi#T^>=zoDh*t}2t7&|d_tm0YaQDLYSRbwAs%=m4T@5f~m^*M3zd++)x+ zpW_}{9dE5us2Xn{^7?e1r(wDSz^P69Df1^*%G?H!uc&Etd4_L7Na-IXS&D0EBR=S} zC)00ppiB0X^0(Xp`AfQ#eMzWKc}M?11n+N+5Q1q*_yOe-n&Daw6ObYvT;KR~5AVtS zJ%UI@MJ`q`>nD5^v3L&zxn!#2`*+{l?d_jbUCv#B-%*ybTGKt6H=y( zZ`Ux^9|Z(h;84_12hXSY&P=?@|EYkdNjD7gWH9H@P1~*+8ez#PoN`5%B>lN=b0G4T z*1+_NwsYy`u+mH!WxVn?6Q)iaOQ4ep#2jkk!Yf0iL)}-;x^%e}5KDa~NVm_d*?BKs z8-7t#?Giu*XjImGtv}?-8W^o1LpQUX4Dw?S50EXH(ws0ztHWwu6tY*^$^pt|5MPc< z-Oc0EgMQvHX0t1r5car^(xbSzq~4igpQ`Dip{Ti9yS$IYSihbvGy=RO$@ zt&=~kmW+HpC#S%eQ~e{CPS=*Hx`%;&z@Y5#GuER%&wYxBthAniV6P>$H+Bi&9d@^j z2Dx>%gv)5bUcol&_h>;}h`a?QV49ebi_)n{DQ7*|D8u2X7SzKVMhQgqMQU|q--&Fmf?oU}_ouV3W+rsh717Q2rJBN$YPd{R)Avi@F zyq%DvEa1BqsWshA4KNWZ-+yGbl>lx3UO=^4v%7iRWRh&!YNsd3Qna=LF*nU^Mu#_t`Ppd@Rjg%BY%~fZ6nEI+g4i6>3@2sYL`^KxC2j@HImNQhhoa?w-Lh(1RlEJEEdL7?pQDR-6LKUrL1_+)1gmtF~WFJL5on#T(lN z|0U*J;Pi%r$5Ub79%>xm%O%~Kt;v7CE>|_1C4g^lDkR)VNl9MMRk8s^gLgQ8cB09@ zdfbus8*iH{^f0&^j%ufn^gZAJr+X9jT@(w7zgEn!?`X|dSs&AMtL(Br3tv^@Oj@7+ z;o!(}5Yxc-K(m}u(}H3jHB0`){Uz-Io78%ry9nWQ`|mZO8})YH%UGI`EL}Yxj#e!$ zF}*vK^8R+Wt;!Mri6D#P?WnnvHN(6JU;R^Z-Gjz6iUS7Qws+*E7Csudj}>c%Y9S-l zHstJZKYCJN?3kp->jDz%yk2!seqyepyqSP6i#*m1o1Zr0W`~2D$altm;*lS7JT`Dy z$Pwx_Ty5I9h$v{V^M<_#U5?I|XPJ>&3rtLp$sL6GDg(|OsGS#aM~xr(L@+%J4IOU8 zUrbArbAZM}dhkbz9HO^Z?~6PIk{Jt95bjZzuizw%o_?~|WE7M0GkRj0aL-?7*v`g_ zPP+ien=1ERl8%GZvi|B1ZLur;GQ36SumX3C-9Kc)=G(SucJCm1N>4geQyKb8j z;>2d?zMl_c6R1hCpM`|B`HV{2e6zpfM6mDtw^zBW1T(}8nU@-GPw)qwuehHlPtSFk zY->DZ>VVt>S{czExc9VA$TCbRD{WxwDlH>;zvG#j_3J2X zyzlPQ^cP*UOT&a1#UdN`nPjT3p z&HO3Nv4K$7YcMoQ+{u)%$apAOK20juG)R+i#c>)}P-j2F?$Y*+vtePuiDtn|s_o+y z<$~`FRkK;qOkkKMQka`vWFr1vO7I6soQD8IGq5qYwAGLplncoHP2RcDZw zmnV6^Hy9Qd7n(V>Bm1qen&AnmA_*Vxoe19gWVlXgn~_6cp6Y>TK?d>Ic^Z1K0F}-! zI*Ba*c+VZ!B`M2LjUT=_rYw3L8lCXDESakR>7#}((?++8nUOa0Y|v&TipK~aNAhDc z>h)5foN=6e#ar8NtevV%<&r69*7>EmjtP`#;+@BHo=e=9E5oSyVAJ0GvDuS7;BD#+IoLzFN8etp}lutG;I6EGgCNz0N_SF^Z zZ6@cbF+>l?0FBjJU59P;oiIA2^>&OUk+UoJI_cJY@lMB@0|;B}v0~`>fmOIIv(W-vA&5{$>Edp<#)-Q;%oxxqEPam|g7S^< z^u*J?6!ebJ9<_o>{Lq=Ct?dPE?oMqy8r_OoJG2V9RoJe&lT}sbZE@%oVgz$Zs6aKV z0m3h@>0S&b%lnocOjgi{g%{=@Q0(xO0SYO6E0VMOShSV;Yo>4R@1jH%jt>9MCnb5^IPBqM$HCYR_KZ@^b5Kn0>RM@e1kec|OQ=51U z`0O)MI{R@19|%{>Y<<{H6QQp06Z@la*2*5J(eWvAT`ICf4_rHh*>v#YSODBK6x9cR z@J#RL)nkeX?Lt5XUI6quNbK`D8Bg3)PA`S< z`p*pH-W^F3Z?=znol3oLgv=9KHZ@@E#{$?KFuqm&5rE*e#lKl?7~>+axN6F(wN5uF zq{EsBbV&racF>B)9X6~TrfX>;>91RTU~lzEW=8NuVbC>xOXF)*KvOvc=-KV}ojIb3 zoPd}hPU*TYQTImRqpvp7D-Q9Se~UK&f$c_l-0Ay?P_t)q<5H6iPp8!WSxl()dY+`J z@!uzKXWi<<4F`yI;9nu*nxu*$el1}@AaMPVfIo2UD0VGm_kS1)zyMS)0S^yAMe+aS zi-_g7^3}8h9@n9_mP#Db6=ivjik8IsZuk>B3IUfN1afYZ&fbe1y5Dcx0B{*1k z4H&~56gG7WMj@2T5;fxie!5rH`dq=KlZz4GumVk?*@}iti8MFRfz9Lqw<1KY4Ecz+)MzKd|I_+ZN?7>rz_TWjK5t>XYlvZxB}rDv>;xLsDb{ zte}6zpE0X0TUgLN5eTL~4q7i&OINlA;AI%8O16dYM-0$)ALKTunpy`$bCnbsD$to- z`?%y3n+3>_GzipzixGudW&^X>%lJde^Z%3Yjn_7`rN8cZ(ciGt@2pzLKeb{*RwJM; z`MFwRa@LhE{7I*>(XaSL+3h2M+x{s97a$qN+Sn{|Wm>Rn__LnC+=?^!V9`Hz#mCG> zj=OUAk|{GXqYuVegK0=Sq??jiKWkM`N=&I9a`&i8bW8q>Q_j#4QJfy1+rRHR;U!_f z(DPTcnf`{IKB#!ZPB$w_4ec=$l`p^eYbggFPB<-cENBz1suv@Na*pIAtw!6VJyTn1 zpPt&H=WrZ0BZ~%DMV>Q{J=Ie0AUqpO%M0omN$TUJKdZ3!u|@+01z}o8UsN0~Mr?8V zs}cH+)}&k>rpzB-#UDF2iRpmc@etduag@o5Y?2>qkqM(dzuAfKVb<<#w^L@|(ubph zB8u2%fbJ8!A=v8F&iL_jJD0c)sy@*DdGpN-5p3J`Cq^fqkxkqMsVWPeB|GS(!AxV* zia6S-i;CjmS~kQLKNb^-_3Wb7&tjo!oAB0iZo=Nq2po~6Zv9Y$x2c2WK5k3rrS>5g z-v^GnsLf`WJk;iGE%~S6NA~Gn67dHZ4*?-PAlle802UXrMgl|Y?G0!h$h4Iwm6xX} z5}dLZkwSLs%aQQ3rRyNd^D;zMUq~J)>&CsyOqf)%oi^s5pO9wa0yR#J+6Xiq87V&1 zm&wpxq8?}sMNG;+n^O$&mk%a39tY+_Ut2L2rU6u1xiLq#wzF7H5b&=4t!svwoZ&zTh+^**)){rI^!R!lVld-)#~jWTu$B1 zDwn|L8$pJ(LX}HePqb;+efA3z>!ZsboqG?G z?j21U`2z>Xf?mm>bt{1B$ezrrJ@^!-rqgwiKafV>xj=_JCLaJJJDVfOCaj&GI0%SYb@Zq>x~w3RKCIOLx;2xs56#4kpCefWu2 z1Z^Y1S7daK+%*Kp&@4#ph_MgXkrG9E!nPk7C)Ttr;F-eMCl3F^-q9Vf(!!^m$t`k> zHLI4d80(pznwN!rx@@WaoXevk+HRUj1ohr(f0KS7zG4aUw)JQKE`u`zDulcqwQ7VD zNt{s$P5;ELzC1t~4WmkbE>GW2CMwxY6WEQXkO}$tE*WYkFb%cZ9hILPK>M)YDCj3KqqO>+%b_X+Ewn{g)oGY3GExb@2)_NMZah z%m2D@;~?n+6*>O;nroO!g6~44^e%9PRVpUh8rFI%K!6ZGhNgw@Cr~i7MyYtEE5DH> zh@AjIC!(z-o$OZeG%ms-)VU?!O1LSjTmCBw)^T@5&dN2bp}md=bXm0WR1G6HVs}onllQe z7X6dEaOr_|OI}36Yg05*Or%a-;$Gspgs}MX$oX>F45)Q=**Fq@qBNZytcR+GdJkGB zotwp*quaoD)8_(28CqCTw+LPTW@12oteNTf!#6UR3k+~nl)6Dv!QzY+NKDLIw*rR1 zxMiODSNEcTCECaJZ_V|x);$nxk#A>$h#2uE#NII zmH03La?yvQ>0G#+;FFSS_D!gUsA2>pbW9wVJp;DZx zFV{aaxFAoClnO~g(#MrjGHC1+0Amq@U!-$lpHAx-Af!yD`t+pBEU1Hxe!&8RMfsPy z4MH8N(*}Ro87N!Z4N{)p^{*QdZRvfeGxL!j|BKPTsA*X5o9IvTFeZu%#V+zi3SEtD9@l#}JO-e z4zpBDGY6r10K=_eI3OoSyLfobIpw?5(vLskzRCz)_kyOx;UNA;qw9~fiXjZ&GwIZp zNR}|v`lh}PK;dTHB7S%_!qbFDbrbU@?n`gbsh)uHnXE-p@}*vBa^!29)A-*anvfZc zfZL~?0(fLto8BYmI)^_X%(`=p$vX?XsykrC;#Jda$mkARpoSa8$Q{ZISaTJJnbF(b$B z)(pvEjG|n&G`Uyb6o`Qi1K{p-em^@6wH}8q6(oFP5qUBJKv~-~U+Yqzhu_P;fIhrg zHQ4=+@^(b$@_fC1jZcGd0HJ;mnZGE;Cpj67jDIRxX}KhJG+mkeqiNWVyw1Qn9S88| zF=wS2FYw#J70$@7*w4f!LMbOM&x!nkR<5HIgBFI3eKC}rOX|XW{X*fm%`J` z*omqg)oI?N)-y@5@dI7kQI0T|j6sC(iwV7xe!0y>F}Lk#VK+!kTUCD!pfd`2dMt<$ z__re%CJjty+~}Zzx}Oe!=*5&&4%BDIr>?2z z0;KtW6LP7mNbkEedv(NpCFlB)+@RX_J^zoCp@dqEP6iL$*>UaQZLD+&=)Q94h;Twz zBIQ(uI6l@&C%ZxqSUI>4wCCZ_#;NrqEUYoC;@N?qO&n_V8vo&xDqWL zQPw4Y?xS9PZ^TD9|6=Dwc>%*oUz-@=!MMbgYd7&+=;tOM6)ct9 zcmVzfGh=X2v-dG5gR`RfDDMqiXxo7x{yM$V;f9iodJ3k2T9c6kp) zc|KY$|HjH1++qQYUEGi5W6__?D#zdT0E&T}X1*-8M#EgOY%&xPFE>binEj0)Umx~3 z|61)DIRRY1p8U{*OL4@kb9wFLFvMyP&hFA`&YWgY8vKpLzY=3%`Vh|4-0E7_!s^ML!5yAb2j^%-ln2hJF=uDcMty{5r=sR-S&auu`mli z41b*epkxrx$0UfuRZCb~mq}1n{gm(i1)nR#WX!C&eRyIB7sE;P-|zf?L|+@1>&605 ze4GEMC8K^(IK#m=GiBUnAhOEq*@B=Sz5P$s4%1#1MkdEA&HmZi%Jh@-Z(=9mmhWhhk8^H9CEbjMK0*ms%6hF5) z{RI2p5pSY}kMY;zSw?jKuyIaS4}kVUDrrn=*<#O;mare!%z=L&!>VjyXN8pN@~S=5 z^b`TR0EC^ateUopHouF6>{=C^C9TrYUnxA5&%f@Ws^kQqCCUKsBPWqc!w0iKG)x!( z=nJxD882>-j2e@pWI5XQ(jV>~_mU8P-7`0rcw>fF>cRdCxmj-`v2zz~^KHp|E#&f? zU)-Qzw2`WS;l@pM$1Gk`(%gi!t}InyTXpPRb9Vo{BTIAX^{k5o{P=FUcj%ECr(Ldr zDP(go+;tFCN2=&sy*mx`kGDOO^{Da(tA}dzko-eXv`h8zH~U2Pk!L4+%7cs^v9oAP z9rMB7jWh05!C#Np=Z*hCRY=oWYC*es)aU7IMwA-!zV@qe^eVA;>2<2kR#qH-W-f!% z1UJJiuWS* z9j!K%-!1(tl9qO~jwx*t(s(lqBhIKf+o*rHvS~;;xmnd@uK$`v+>kS^{1!^0HaRmb zsSfHx)T$)#8VIEUT~okhaM*^ZG+&YI*#a5K4Y1;xzt$iOCvWf7EfMYw?x#pNiKiJGJXvp&&{Gz!NTgXIyH-QB>7)i8lT(gOMR=S-^1KqT$&@XHZdV)+N}2t`UWT*Mexa} z0-3)493iirJ{_Rf`1|6a?5OYT@3^=+xoU^Nv$DwZl7rl9VDUi(-Lg@r4qc_N>KO8| z%#JNt@@*OkyaozoGqr*>qhY3729h=9+zosKo;!V}QMp5}03^Y3{oUEYvQ~W40oRiQ z6X=ip8kdtA)W=}1GPGj}yBr9^sPx7Kj}&mm{pY1YJaWk?Zd8KAEb+b7@dhi0tM(`K z>Jh>6KxTccgNMwO6E<)!%y*uA1q6>L-azsT+ZF2p!sntlZ)36^ZZcoBjnGgv)C}{& zhqT98>e}^lLwF%c=5ehd-;i>l%h4PQ(DmiadZ4Y~dAVcG88sB;vC}t(1x@mZEv3}{ zaQ*7fN0>#^sA+^8C5*mxXs~*+qXpRfK0=Z6l+}bq>wDeBAgsALS9-s5f;GY=q~&p- zI|4{eX;L+g9}$8MXjq-9dwo?dg~nf?u7)( zeSilS^XrivIHn?^rH>axC>Qs!Vj;>l#n znu_o)XxPG_)vF{*NZY>F-$u>F{AI=4WJ+yQz%hpUhht5K_IJ~%>j{D2`S{GmP;Z1Kg?wgI0~ zMzxGGz}GtcN*cqz>iQsh=>}x3xdCvqQ~5(9OMIxkb=KJ?LaE;X5=&Q2=w23F0wG^J1sLCPrgDbcRS_m~hZ!4M3 zP8w0WJT?jaY7|DHB;aCKXln}I+iCYZxokS&IB3dfq6{w&5@|m0PCXE|+L`~uG45^P zEqtP|=U}yx)!O^ zUd{g3&p9pwb`$vg$Q=z$TBeUN@xq|+i^Vb3!d*VE2L3ixp zF(1Rx=X2?QF4mf^xWK@j);a-QuZs5^K0N)%^;Yiwvu=KB`VF<;LSXu?vA$i>XMfTu zeejvBAniEx=Dg!aL0OJju3!?-b{#w1KF;=Xt~tdv=K`IGF?qY|k^fN9loMz3KJHca z*xNfw@UPyxiRh&V-S=-z@?U>S0g4mj?KfIULGboPJr&j_)E~OK2R5sdrAd5 zVZMX_A7H%1{r`UOdU@0iMewd-=Jz!V%=+!Y=AED97LJZIAFNmo8@5vU9i-LlPh_oZXtRl+Iep;pff)xibx3&OF|3h+Cg$&;qRZ4+cUzB-(br>^bGS6?Y{cGme6 zt+~jWdmR#B_{$PqKkP{x-s)+>Qz6L+pA+2EwFTO>CFsT1*sIbBy?SivX*LZS5Yi<& zqeB@cG4TNS!~XX_+z9lvh_a2V0gI$zTFNVUo;6m@0Y7?MXdD{;@jf`*)@Vdg5Z@)Zog^BUMh3*h`Z^2STFr2Y2nh z(+1L><+-cJtU->dy%U7mjfplM<|8eo(TJ;MuHA&4cq5_Hk3ZZEZeb|V-@J_9oXomm zvK1`V6N7Q^)#{1fYywz7MudGT`G-U-?U@%J30Xj-=wwY|qagSG{j=1`iY**+@QRf| zg4bPDg5m%VVu73%;naDmVNrt6;U{GUtoXnvs5tNKNWKp_qu=g}K2aupamF>g`f~n)fI84sGdSp z7zPIY%}xyjk$EtpsSPaS73}&u)xa<}Pozaia^RRa94eJ2^AP+#EB%{_V^H(6ZsnPl zsj0fY=erJ2${%}3l zt%!R40(R*2iJK+t1Vj|)J2LiZMXG5D@)WaN8e%4$@JC+?149k=@9LtK_A42Rjo(62 z(smJ1@ys|FZK2z2WgI-l zf(`(|+W#KxD_mhuTL&Jx%@O`^C188_w>1OWaKzV7OpF(330q&kS$M!ZhLJ0J6AnN# zI1=mc9{zvj556WQB#gu+_f~5E{f%XSsbStk#t&hA1{liFUGGDnE@i@y`8R6iu4Hc? zV_;C+yah*2wO%JXZ+|zPEP5d~3o_!T4ZN55exZ2r>*Yn}a|NVYP;srmcv`2< z>$H(l_LbA-es*{1ge_9`8Z~VKD!2On`F?2CWnv$E%PKC&JH|D=0mDg(pJb%FiQhG& zwEgP&4Aj5?m7TSG`F)h2HF)H}4MUIkCR{bTqwpeXL{WWFlw*@)o2_n5oMKzA@xUkp zu8Qz7uX5b@lr{}ANPe0y3Fjz78jDdqsh5M&@xl_tFfLzzM}^q2W=or&MQH6BWPG$* z^cXiiGN%A8t|+I}?NeP%!Ggn+F%tjB;{iCLL0YU_be1fF412daPt-`?X3=hnlhKEP zgsQ`-CNjc*>pHAJ_Egiayuy{Kg(QXN0&~%XB_Z8Wmbpkh%3;l&rj^TWcFKf=cqVl` zmSFz8y;jaIEHG3311g>zG5D^3^TAV?OlpPGQ(gr1LBPxU>WCHS8^nJv*qm+d^rJlU z3Q=O)-LX7En4MUYUf}$e<|^^#PNNJBGVL_zSO%4yWTC?>B5lF^Gdd8}RnTR6KmWx5 zU-_eW)&4o06X!kB6eQ&YG%;O&sZwyMrj*sS!eL*}dd}l@qD`FcPAaI?>+?`jEYBd4 zb~sid%?rG-eNSvK3}(W~ey-i2a+ck@o}BWrlZ|N}bYZrga9qTfG}|uX3EJ8_5URG@ zF)Nxl$nGYda~mk?!UL~t)ad37@_`}oM|}sB=HU=*ohP^;QBal?UhMhNeIs_ zaQQk-!+Xa|;6=Y2#GvcQwTVSR0>vbVe>CXMS8>Om@$VV>5bSBYQ`;sPe{(v0qb7n4 z{W(OLUG>C_ec-JzJk8AVK4qV&v`-N{lp8%HCyRvVxBhoxWOwN5xV|&sOttyFWzDzu zT_=gO^kmk{_1;p6C{WQQ^x%tYY@=IS15Oey(v!Y=d&R!cPBlolY`JK%fcxO`XVIC3 zMXJ;Jht@1%kK_z?hT`Lm+Oe!RckqK>I9T0B#Nfj_tDM-D`oq~pG+7uzrRn;Fw%NHJ zfO?!NnVwkaCim0JC>)be_HiTd{9>$IbddeA1&21x^v&PO%fFKR4oh z7aDdnlAaAs5R_8!*`-D?F^OtfTSYkt6$GA}iOGspk{{$b@hb4LR}6plTGRPccOM}< zN|f4h!DziujLI`?9`<}5LMpAb=^@bC-j4&rsQ#P30C@ogbVq-)M^`G6VdUq{4XqXcaPD?vzGJ_GB3AUtaH-T94+6in7AW8?M6Pi zx80%`{fhRnJ!jrdLo0|8I|IVhxn-_!w_khp%X(hD7D4D|>-W2(me4Mlrjm9-&MRy^ zo>%b0{_SZ)mXF=eUCMNNG~A^-Yc$q)Z?(4caCf7ToousEP4C5_<7BhTl?^t3x&NYs z*rv9JVc1h{mE9^fzTyA`dt9HC;Ue#SFTVG~GsiRwec+@-91GQGKgU8da5g^aQl=iH zwrA0*u4QvXWF#O+$5#8Uj*H;?_XqFV;rBhWU#NB*Jx+~vcUiqy);p~jc5)IteM^AW z)n++jIDhcx^<@+95c5Of({WNa&&+INsKcnTFN=EEHed7G+2)h}<&yhgRcT(Chn!|BPkyC7K8ll&mZ=2{!Pg968J$L?lCn--)Cp;ANY{-A(M#X zqV=$r=~MZ$0qKRqyZb~Zvn3C@#u!qP(=PXl39J|d9dou>{N-+th5gHE;-IN;c@-@- z^x3lhegH{rc69@uqRmUqYQ1kOeWiceTvpS^q0cIE=wHAiY_Z%80VL5F5&1J7H1X zb2|=#-U;!73Ddc^DK$HOrtr)?uz(M$Iq!(wdKq|q7=THH>w-ww!>+&8bpIqveEN5* zR%1Ts{AQWdJ#ZYOrZbRJcVm90Ksb@}Gxy@GwncZ1ova<>%f&D_d|rz6`g#!a4j>`y zO7fWYJhc3+$NRLbivAv5K6XEGy#63M(7rV0w|gI6|6Uhf@QRh(G{|Sy?et461C=lD zit~%N8c9yIjlJ4gO>AHvRwm)EF24biqovhD)UaKIEzH04zr1&Tz{~D&_dpWqc(Hp@ zjeDBF7)u-J@OWg0%#JrjGA#v2{dx`QoUDAli#@(hjUMix;}O~(N!2D1t=8*OIu2UL z4YuDa-OUA*H*PsQPLamAHZ*@~DyRD%EbaCPCXtdOd?o$G zW%P2Zp1DElzzB(Z$sL({OsDq<0kb0 zY!i#@c?_%V-0>ZWYQoANzEsF`8EjfYJ;4l><^Tf&20`(;zs$J-T6&Y5#DulUmVX1Tzf@!a~9szYbnN7@4-EZ2G7xsYUBDo;D= zUg5Lr#7nhgrSF)`nv~ClDw&@@ZJL<}VL&No*UJr0xCq0epJ>2D4?VZ;=jj^|&VCdL z{dbAf_F`KLf$Qr{(P|+{on}UxA*YN|yS~A<=i!A?1bA(bj>#8q-2NWH!IVfWsy3L^ zok*`20+-qaGqz#(Bp7Gz#$s)w9F}1?5$znPE<1{!6cNUEig)VOawR zhfpRsOP>LmEMnxOU&K+}RHx0|0&>_#f3w*xr8TTL^D=Pb0izvvoi zJ6U8<6uGQzJ)X54t1qOt11|~f^Y8Br!8EMHZJ#B1Ioc;vd!k6 z?0u(L)(Xep9-G?Snl#fhS?@w~(aTL6{iDCGGd4I?KlWUoVlw5R=T79etK%Wh^}by1 z%Jd7Wq?%Ijj@DLC4yzJVyJ?NLnWw&8#?To`A-;L}RByp7X|7&Xfp5ELMO6UFfs-FR zg8FH;KW{#M&^ouwPm8^4@Crh6S9El1RZe@diRVfLA?B3_85`=l8rGYn-s>(kB4snS zN*Y@cr##@F#18M=a9$o-|JZrf3f_>ZZLC$-6TberP)DO>Lkk&*MN87-<>CPr4O$NvMa-*(Og7c+Vc;$AmX3P?B5~pZLSHLGa)O9RB z;^zK1hWEiV^vk6+j*hW+gMDXgf)4NEGP2whM*b(A<@caVBrEO6YEpH>Pmk%DooUFDAP&IVx(HXc z^?CP(KhS)?M#sE_FUY}q%+w|5BCHwjI`v(`c`LdVbqvUsx$s);28D0Ncik6aM5hE` z<>)(2uHtu#GkN3mbQGWqjAMu_s0tIzFu+Be0tsC7HQvPW75336z#jy@k)dyVtpl!~h?_fi z%2Dl3lZ+ExE%lc$Zn;b%8zmE}@ za#+<$o*NyNJ?yd~z?6$|=H*?#P_woxP4ITYSSJ{>&w8;^Z%@GzSKa+NlXXys|0?z=E}ca9DT&e;&5x2O&6e;H5Y zrXlEV%o~!?^0H1=_LqR2;ox3cL2n+@J?I|9Pp*0W?)#y3kvr6#@YaaSC4H8s38t_j zX#_cp?9Tnahij|>S9cWY1JzRgChst@n5||zLN?s){G-Q?b02VrO?IRmFp|teIld*Z zWgC3>iviq{bgbmSLf{%z^S%%-?N(x1Jn_9weKF+(r3& zjA#=mQ&*#q`2YkzTn5xMCrR-f~$Or>+S+9d5#T5RjUm5!Ru|@x{`uz$VB^m zz2{svT>wIj1ckcbsc$UnZ(;M}mNd0(U zclcE;MMe2Wq;3}oD+0xtK;{^=Q;n()2kMo=Esx?aR=cV%-`wO5gfN-`Tp~%cpslq$ zYxRo57tv~OyDQB$!lp+#!wbeKEOLT#Dzh#YNlw1LO)DFB;$gIm04N&C<}nRItMet_ z(5$mvB=jklzX6={wu?L3Gdmiwg5y{lImwF`QDl7yTQ(H9U<3tl=B(=GzsUS9RlfFn z@WW@e3&*P_&GS6>I0N1Bm&Z<$BD6>`x!>($WC@j;6|9VmtmQ{K-IhozSAE5HkBPqS z`mnu2(8nyU^>+5bN+EhR{dNi*K{O+p2*x!0_-#R9lTT|4Z)w; zr$O`+DeR^}Lryy?mR)M5ssxSmK|eNn$w8&}pImYA1AME)wmIaTiSo$bD<4oxLD6F) z{ZbS(pn4wYO4l;<)6!>_1<$2eY(K|jx$}h%JcORwzA#J45EmF|ubmh8Xzln&kOL37 z$7Oh|u}c}SG$KZMguoiur1+{DhDV+0TNiFy_|ycRm>o9GUtiQ_nD6u3fUTeb1d-E& zeE6UI2Pj47Z31_}$d~rseJj8$UxJ7s?!*3{N)POGxHv z7t8@rR2>nF2o~ZzW;Sq}p=U4~N$ETgOEJ$n@xFk0c8d~@Wg6|~s<#Geu5iyC6K;`C zDjdo>f@?U}Dxw7pM~Pl*1+(lqKp#O!6`ZylB6M9zW&6`wBn7VMMK1iYyEqa+S#%QCDI?fuN{NCTY&)H}1Q}_OS&iR7~Gqdh{-K$*J^(~8*+PdFW z(1qraSGaDm$=2)@-L_5YGw2?0D19y4v(*YTP5ZoUpT%a=to)nk>H)=evC~eK0=ew< zhi&5p%YIDXU8RW5v|OIZDuO%hsTh50ujSvKU+xgG-@Ll}GB(Xe}Dr}N2Gs?p5 zZjwbtj`_7ppI@N4Y&KHX>a{UFj_dW`mM><%@bA{@mHkn7$gaoPM_2y6uDJ#7zxM1f zDf7ngC@Rm{FWg^Gy>;{cvM2t*Ag}xPI=P$x_isVr``=b*4<1!Zjq%vHB)!FtR|n{m zB0P?Lyu?}^<>w%HjnKFq;wD>KOjJ|UQqR*l4@Uh@zZegROzQ_SC3d!L_3-?R+SJmP zTC4m5fZwVn6oKzQt|Ly`)?>MdwdT_@kBDnTZ;BLLOfnx$I=^uY-QmGcyP=UWyoBJO z(2mJ=8v&9b_+Lo?Ir#b(1Tq!cHh43VI*dkYZdfN2XF0pcKU2lFp0<$_IFWtSNdV<@ zITdXT%{tLi`!*Gza*HBLr!(KtFUQ1D5x?r@)xqOAe|1HHg0oev1yy=nUtqPRy1C;9 zp6qj#8csS`;mJ6^!C8RklF&gKsA_04K6W*RHK#hOM0$}8QEm5i^gWH4qCju8< z{k%RrHp0U=jWj*ob_@Xg&jAQ4o;r1EZ7Ptajjn!M5rv62dgTMFV4glbbS%&O&%?)}oO`$)N;J<(sUQ(4XPO!HxxJFY3bnJ(7X1*EFtaS#lRN2gWXQ^%0 zILOxTbsiTXsi0d7nW{eTd`VDk6z~Phj_&4-%~o4r7b{W&fNgV;4?6EAxYa!UqhScL zfh`7{`vY4r2zob}Q$f|&yOnp0$9h*+)z2}_%^NqTX`KlW;%t~xE>DuNwa@!`j>8JK zMW(RXb5wGZZ0)lTDFSpg)?#K`0N=&pB@ZOn%=W0(ZzZD^c>BfEG`v2CD`)6J*Q2D{ zZzTy~)gIL}j$I5c1nb?KxJ6^37vh3@;-01bXWD1hVk~Aq@<{-!R?xJfuTrTB)a5rM zm(<(avn1NHu-?|vCKoweQQuvl#oZvq!*)5!dB}!f`n$SY0&EUl++!@4OPOElog&L) z{s(5wLe6T8+F1Y~&uH*{>M##w;E%n=PV0azU-6p49yK~MfmZSpQ=S%0b@CEDlXt!( z1!!v4Kl2#=K|D%#PABI)=^cgNd~f}wyo(|*kOcw4T1*lGW-(g9IrH6gz9f7-@ZJDx zXKJ;jfEUe%lS7>TPK~fT_32A&I+qdD1qnI68Vm-aEp-i71S_kxlLD83tQM-!P?BU> zl`S{aHC0E|`*Clql>M*2Zou-j{hJN(?>vT`JbwgbvR*XWS=}y~rE9ZFjv(b7rZVbF zJ$E+?DF~jHCg}HMWCH;40|g3t#A2i*q0r4dyM11=_dk?+KYORzu zl-}w%Lp_c(D6HREc-;A=>JQNO-8m~m$*!ii0Q=spvt7lJ_~U+{ObyZI^J)ET)=wEM z58qLljn)Z2ebnb80g-*TJqTfc7ARb-VTGNyv^3cml0<3EO0EAOpd;NxXKzhbHA!whS|)&+GwE7nER^?Dqghqd_ya4zIwc}jNmIkK)hf9l;Y zWSXlij4$2;H5^9jlMiJ%H#H1Ci9^0Wj`++9N&FB+Yx8@ZBbW`oonHSayQ|gJaMYrq zW2K7Al{fNJPoq|4?e%nTZr}Ix2sfAF!uY+J^vq@jShd9)SHHd#cF*QQr;}tlG^E8* zAfGR_ylI}=t;6|bfL_<;15h{5CFjMV z))${W%oE1PH6LOi2oL2iLKb`y5T^J|^#+N*n4Vc|=R>{@iitQqf67FbLQa~%O;p!= zRXi0!PW9epv*|E7$ej&2;j>J+`8Pb)2g{JG+Sv27P$CQyN(rjV=bepLuFuz12}8p7 zk}}0G4U@?neg1?ZN--bJH`q&Ln#a}5x9GW#<84wlE03rc_IVA*W~;BB<%H28RU4z= z$f^dvaZ9`|*0V6S+HibNGVJvy3znMdflY$PJ0E0~fU}5ly8|o>?wme0`7-?B`CnR> z5gP^>zm``V-L)bf^^VUoBuRY)QH3YowGsVuHn_xGwMvMY?1RtI;&-hns#Ia2cY}G@ z7@XAn>Fu&Ab|P%lJY)=G_@GQ%5zVEEBS3c0$^>kHZ+FiMaK8torDQz+=NQ~uNf02^ zp7?IBPlr)0OO3`$yogE7O}S#(s0H5R{+*92j3s6#jjd4P;F-9(!U5H$Yx9X~uP#8f-=VeFY_K;I zC2sSho`GG)sx6>`*;`gLMv}AJ!6D|15T}ald;Wyg5F0h{yH5dNqS82$jK_l$mRe@j^YcWMq8D zb$YNm{%e=g!%(YOn_sj5ODl7FZ1{TnnPj0-Z?lzWU}>~xc1p-br95<)bYeys`#w*$ zhs`Cfp>6(DSkEj_o*c|d1Xb1#LbOhMy{5a*QJJ8$_$Fj)K;7h4DlGKlb)CwC@17ei zr4l{Gbyc|1JlCR1SE}@p+v)lOM)Mmx00tqEt5loGPm&3~`coMGPw=gSO)3kb@$a4? zZ!RAQD1+ZUN3Rx$>c2kRd--&NZ%jE}mM_l4QkXU<-xL*c4Yw?JgYzt*H6%X7RED?o zd(Lf8(Yoh`Y0lQe;wHHZ%G?YoEnRQy1nnh#seUXwG0IZov}Toyh_*M@R6C*T_}+EXo-O*(HPvzw z>=r#nMaQHMs~sQo%{yfGbdT9IT(y+Uh<9cZdx6Hd{n|4<<4bFT7*A2ov0=y4{(s#? zw@hjX&vcItK3zGVGA2H$FFG%gw0Q%!xRlUmjpIA{isuMU2^q+CMTZWs_ZY&EZTTQB z(B1MDd%-117}K>i6wu~4vyNMlFk}m5ONDd{x}@*BZgbs*1h-eT_@N)(1SM>{<2}X& z3G=%`#(ESihB69fX{Ry@LP$Hrw5nsv%I_9<}1Do?7t*L`g!#df-+ZuxA1IWJ!fCeLE-*aDYagA zWwK+eHpSoqw2itztq*1a3;!XSr4bjxc5r!UQ}5T474~8U`H&vt_xfuY8hh-;FpH+r z_H4d$>fiASYmkL#Z+UTB8H2z!Qjeo-TBC&%5B3n)7Oo=`5DkR@M4^sn6ZE_c;(3p@kktV#w zaws*m+K^G$mAQ{MA>lX)wG+yr$kdTx5WJF~;CcGP7v7UOUMhUq&yjEbpWr_0lL#&vE)oShrK=Xg60KX=J-)3^#C8r!KNJ`e(f!WluiODcZOIp~ zc7;XWhLDT4eIz`JvBjHkjD~)E^Tgu@I245|g0y&_gGMQ&_RgJ7@iuDy$a(qQWducB z`ptq8UD#4kX7eZm1vaB(T~qjL72h{-mI&rJ0O4{2Oqh%ehtDNKe+gQOqiwcEnmZ&e z*lBM09WdjbxuE)oH)oP9{LB=u@IX+nU*d+gJhod8_4tY?_`7oSM$#%8VvDo9d4c(j+|96M%ym*-TfdUV9>CzD}1^`cZ~9g&1aSu(QA z|6IpU3Z~)NGkt3#|3E7B?oPc)RG$&`j@> z*tCVXE_PSTQg6Pzs@654BGXzp_JHyJ=`I;gL%DVNL@5-Xfu}J?t#u&}ZZQtqrMO=C z`WrutCv$NWFkyeMvy=O1q>YYnP)^991oj2wY;#a=zV~fiE}+;ln{l|%{s~%b(Ke}h|Gwk2Viybp*f;3yt1iFq-b0Mk7T8`7$ z9cN*HR189?rh}6)4+U^DKX%a5&uV!l<1PwtpMy5-jan)RM;JNfUy}XdENmVEQ`gBH z>ZEpXio2~fU7xk4-diF!R(iMG$RKyfEHFDRy_aEP)8QSO%XYGjJmJRhgk-kBOmP-N zlI8S0=dR|fh!BgxHhm28Zg03?j;M-upiq%E)t$Y77RzuK2>U46tHnRXBapPvGE`EE zLFIqXC?&F}e=(_Rx4j5ex&Xz_Y=hMHv5hG<+wv_H7p^HP9%r<(vgvZLDb^;sBq4ci zF_%h7K5uSrNvy~kj&H`Oj=t>&`}@aJToY~|6~AVO5mE+h?bkMErg zbhyw~w`_@~f^48l#oB&Gda1kdxhLu-T6Tj|+1_1~_^EZSo{D$8mnH3?L{+s>5=D_p zvbgn?qjeNSl2Q;-VWfi7GGoY|HY@Y@Pf4V_y?29Y){AonOW%os8)&Y{{@WuNk7q8B zcXUQ>9ju3ztfmb)^Je*Xl7{2TSH_HTz2ylUOc-R zl9`ne{H6f|64tOBb%#k7b+?-BAp6k@-n`J6#QWBx^k8O%`z|2Bd0Y2>bs~O=eU%Y^ z`(kF0{iT#fx0Zh!d6q*HGfvL0qCDXenc%yluu=kYwTQQ^b^pGe;>^>8j<;!djD=`l z2FUNj5Ffcml?$!JT^zRs42G{Ath~yv@16K7xetQkAHd`Z|(IT0iwgZrvfe?6J%3H0Fs+!mo`|;Yq*~E z#re`h(^yl@2}NpXi1C#H-t?WRXWren@Us`(_1b(qea9YLfP$IzLU?IEB=aX~dN0cm zPb8$NOmtqKpK04Xb@~=r;t@kcgb^{OgO*DU5D><-OpQI4*$KH27nDgiQ%Dnnbs4#eJZ<>yPM1l| z>r-SFN30r~b9pivrzCNXZfClT7F>j~nkoYL-#BL_Tr9YAHnghUQlB7uUAUppWXt|9 zM?;5tv6gX*hpQa1J#q5Yo1<;)g&;&? zuB!xl)pt59zuWHM%`JT7ebk{57AG3manfl#@+F+_qjTQmq*T1K zMV+*}tpXYqO>y#PJYA-K_}ZR8ujpg=dHY~=-dHDZ7^vJaqGr$Ct2ml4OTlb}z1NGL zWZ_eQuT_H1^hYiB4)Z5E(@GMa6}j=fbSl>5jG3&zH&S)jP#xzrHRf9S)!}sw+@-|K z39m~?@$lb1B0}SOzyS(^I3%7{=r^ys_+#u0s=%Ri>L7;F6Q)*1!{)?x4iVwe8jZq7 zscdZm)rxC^o2pZ*(&Heu%nfl05W`AeBx|{L6p445xs#EZ*8G1jrlV>v#B4^lBU?bS zd}}a6!?pu+i|$L!!z9$b5uY@gcs{`R_bM#WrdEvLR|#E?85o?rSsn7R`F1L<+NjXv z!1B8DqkG|MlAKMs9;%~bt&el@$)9V*D%yKZ{lZfdHl!R*hh~+%EI**Zw(^cM%V^w@ z){85c1rId4-`L-qlZ1$#Q*{3yIUxx2FHEm@#cpEX)xa9pMVG{m$+kK5C z-TEjOT}Rt^CGZr{FiNhArM=^j{CKwYD7`Ld}-el$m+&0(S9l4C)77KB9%U7E{ zvp(yxSz5}UG+XrnPI* zBNtG@*Q}5y5xdS(nPB0GoDalR1AnNh4%kjzLHx*EbGGPO@6RrE^VgV9z=v&~zD~E{ z)bNc8I{jlZxn#8|@^D-Fh)X&`4edExuZV7Ro*?S&>9>UF+}n)H*79D@7s^RqB9`1S>K2p=;;BfBG|Kr0 zq4=dIwu8)WO11rFuAZYXC~HoT)8mZ6^2MZK->Q!`ded~RZb+tbiZ{FdUe6mM4ywna z9HcO@Qtd12y?qrQDiKre^KM%*9vUAB;jm>;hzW7la7Z|?dZS7I(^?tY`n1rc$blB| z%TK{4zVj}g-L+1xRR4FVFi$suCk7R>gi5>PAoVCtbl2#ZclKM7&i&1v?uE(eg&D>M zpQb_O?k1>(t9{e*o`h|64{V(zRT%!2Vky%_gyL(5_$TI?&5fHRcKrtlT@d|WuAw~C z{>(C(kVwRJlIFog!!d;)MPkj%X-)4KIxl}1tG(q@aCt)N?yRQ{w(ROb-N=&Xf*oz` zWFP_OZDTmzQ)NImj%S_LoiSlOxBQQJk5n2vXbpIXYhoOsZINN9_oQR zd$LRm_@@@JlMW(TaHLfTU_jK<#2q+p2TaBl{+^Wbd&IvUViQj^3P02c!M1xd9W-N) zg@bP5k|b_Bi#U+3oR@vwh<0Z`Og5;Hr}aBGSVSvzGWVl%ERC!HzX=Cpg+okeT93SL zli<(cTRS8P!3awY^Fi-;@5K(JrYJPM6U3IMSz4%idkeZj4FFKmF8Z!?P3EaAr_?ai zghUji@}h?AFeOviKI_d)5&Nl`K$^bx1cyk6QRd5K5{H38FT8|>J=>P$nK;S;TMZK! z(z0tx)#S3}Ca{!d7id`+2Mcgd_Y&FH;j<-U8s%CK3{l1Tgi$3qC)V_$f`}#&}c!g0q8Rnqk@X&S@@!-6{ly2D<_Uu4JGLF%{@u z-kS2eCVX*}l6>hp5S>hoVMsDXf0=~w-jCtE!O4{2PV3Brgq1j!gbCBM20z9Q>F>sa zX2X-RZ0~bbMl#p?tGUMI(ux>Zylg zoUR>R?sSgk?3bO$hF!5iR9B6f%!)7+39CNXhY?0E;oK6x-e(OqkGcH@l|;ABz~RC} zxmGRnX34;U&{D8?NKe0o*#H~@2zlJ^@N(|Ut-i7X`y;gQ_7(a7xw|$C7@+> zS1h=Qk%US9rM6!{zg0Lgz){zHWrF1; zkr?mo^rI`-bD3K_?b|^_#Zv9*mpyQ$O8n%?*9!sh$p|pRifcLblnp`H{m#csDc%|J zaj7{Xy94D0G$jp!+-UcLnazkp<}C3o8$ToY;-Bch7ivZ)o`A{Ij(^HtKdQ3ts?~~m zb9YZfO1y6FWw0u->%D_`GgeNvn-o&!S~W!teldG+7(-__1EqR9#Pm5pb@$z)eP_2= zQ5Qwy;eLp3uWT1~hsRaHUg1tE+( zx9n0WCq~nNe~b3yWp_*B=|}DusioNQ%<@E4r^@fBV8@yF-gVExO+srgzbTUMXMHs0 z`3NU%*@b^iop>pDC8{y(N!1|$B3=*guib>0XM-rLXcx?I+^aVg34>ti-IW>ch*13R#%T-K>XA8rGu zO;T|d;a@p;Qz(dY%WOJUO891pd^FE$Q;*j1NTq2r;{V3@EJq`q*Wq3Y?5n^;Z3BwM z6IazP{OUPN%D|EYH??^Qb^C6P=|NAcntjmwb;H@fnvRnABa)yULm2Y1hBRK@wMyiv zlb3&^>n30k#@3ycx1B~N$v`WRb}#nQ6XDZMFI3}};b+h-DT9QzaF}WY_S>5oW{I+W za(pzM>MU|lQgQuOUFg!w(B@wx6)MwLyvbqhQ_!`0>2CP3C(hDVlPPIaKW)%l^TWmU zd;X}ww>mhd29(~?*ZXYakLA!1cE`zNJW1h#JtjFmPKHyrrNB-8Ss1Ju@!nY<%_E3P zwh=v=-OoRfV6;A%PV1f`>l- zXTWpCN%|Y(J#*A-iyhbdbvr_Csk!^V_=>3l`>l0WR@EeXwyZrgU zL5VG0NW6CQ+rxIb7pDYp1WT`?{KWZXCokh4Zk<|Znq%gZ*sgE{C~e^7Xb+_>_V*#r zV4EB)at;hv{?HvqC3i%4C?en$qb?d_bp%*izW|>E`S}Hn=oOgU`~u5g2h3R#TSL2z zj1MctJU-3%edZ=IF>ZQ}!uT1QN(a~>%Fn4-pDa7N z;}^J2=R{k^O4NJ6xut&5!^AkNjSiQey>_nlP8|3=cvr$R%B5+HL^X^nOLMF>9{>U~ zta@t3210ih{&(u(0G~`dPMbT4TrYw;w4vQ zSr}3bMkgTi17T&`V!}RKKu`bm1br}lt@+r&-q~z;_gQ@pZ*kgBmGwQ|;Cw5Rd`-#} zhhp6H0+fegtota&AKqjfD2Vhz1Zbmc6SkZhR{U)T>u)c6^P&RN`KyeJj*V(A6IJyt zB0dtH9I-*=#ES@?Eh5_cu93ydx6aoSGV6%1hw$=A=7e9?@Mg+}$^gPAtyTPxP5o#O zJk5rt>tN49vwqui7=teOntHUN->C&%IM^C8^_8Lf9RGs;r zFKis<>_v179aRx(ooW4k?$oj)R^Y{%KQ_H-pxne-f!zZhwW={Z-)efgz7JCuAkyD{ z5fn1LeCGo6#34+0mIoK+CkM=@`$V(@&Z-wL&4q1eeb5GMitiehJdjTmh=D7kg*$1P zS#}7(p#*e`3Dtv5prgBX$am{-&m64zd{{EI2&W+DTjZEBJd>Yts@B?w?lnXJ6T*)_ z66ODe*MIueZ-*+Eb6#4J*&i+Cey4N}h392Trm>k5$AeetEsHHe9X#ki#F{ z1+7-62_DtfDP4Y$T~COsA+pz#o6C4O`OUvaNi<#1FB99XWybh1Ff`$ZxavoDjnr51 zGb7xSPX}o`3>Wpk%#6jZ)m^dQJ!$J&kG0v3U9>OTySlGVLCldIDG;M}37Ou3_x(p2 zWYK-;g(^@x-p46g@X;fYQRJHL`v{|p$Fz_8zlQU6^CdR6BAGo)fsz3aHum1CY$yDh7CHbJx#H(^YTY%N&&U3Vn zu^X+;eL~wHxF!2`vatYL-J!e@Ek^%N9pPjP%|Doa0N7tslwV2If700+d7V|FT zS@1RvJ5U?7v=yj*IWCrEJq$^VrTLW#sx+V?k~Wwq3`ukdZn!0y;$-Xcfa26QQc0*S zzv!aXv0cP>2cBcAi2K-?sc|(6jq;)$6(LJ4?8MZ$lN_Lr{GlA07Uz~w?E;eV%iy^?(47zemP1T5(tWK>+ zy^QdZ<}g|hu%#4hzb<6mk}ouQ({St!nI_xOL%7xyHIXFcP!weei*PeC*AfM$KP|sM z$WN3Li&HPoWQTk}%cvP3x5$h7J}fTVi#Bz}J0jJ01n6f1i(N>`x!il}$&h%{w3Lno z$!ndNA(%zn6_?+j$gtvEFqWyXYaGs=98g@6o}iMzA44@-(W=mWx`3ExeMj!glZq|! z_AO5}V6QOF$~7b-QI^eqjt^8ln3nA-S-cbL?+!({7M<;5j`>>VDhOLLZ|Kg&5KACNw`)OPS($LwEg`dpyucHIt!1LiJv?7{RjN@b${!?K)Sq}R*Zl^G(k+<6e*w^ z&9zJ+(S#jFJBQLT|B+lh9^ro?3)$IYSg=3K5J`Xb`l!E@Y8 zSL<^Ao&Qj84JD9RTh4qRGu*93`FYNAlI6)CFaN4VpV2Lhy4DP9D)K+ZUN7Gd$<(vZ zb}g#Eqb25%0=e4yZmI?p*9LR&-Wn;bfMn{T zFBb?IX0eMG1~U?Qwvop1)#fW?AATI=IimY7I@tjUHOtUD0-cmu5}e5jdG|Bz5ykb{ zs^n-hn-7svn~1?|7%{LO#$`x=h|)bO$?MV=nI_UvRge!r2S=H|GGr9SZGEO07dBq9*XeDsQ zwE3SE=U+5e>QCAnmG2jxHnu(TiRduuWskVV-}RE@^cNSB$$HJc$|?-SkvH?>RMa;> zHN{J`VJv%7*n7VYQaxSu8^BA10hN_SeqHj+nxs*kN~2mFHzo9i4PfiL6j{G0n{=fG z)*Le`u*|fvRn{0J6I{3ysTs;>*qU~ ze*fDPSq~=TNm}Z!do8ouk+NiYT1P<20$LfjA`Ud@%Gv7zvB0wJ$W-hi;@^ZOfZFr& zcsBiuyZYblc$HV-i|uxbWF+oO^{~-`pD`hf#Al5{uJ?VM>f{}lF`lQ$lRa>f$Fg)sH)*N?Bv0ty64_CwmFs)70YyoEs}=ntHlt(1rniRfi{V1|HQ4tF z)}}>x;~uV{8MEH7hwI{O+Bpv;`+VdDa1Kh>%7vcmk|D>`br-~6ZRozE3pXI{ufl0Z zA+kL%*ZkLe%L@%P@a>m7PX&sus}2m@>8`sZgL@O2>52J1;a>XN{7})OhQ8o{4w{AU zmgW4Sx4l4ds%gG{-`Gs<0ixwpdX>B^3Zrjr(8Jihr8=0~WL}9jx6A%Q(7(O-tGcM2 z239@O_eJmh4O7sx#+z;}ZH=)%QOU(for>8f*IQe~8eEDhB-pL+4N4M6;xf~_8 zzunwXrCM>dwt_}_wb-qI3aekTtLy#u;(m2QPJmw}2F<$s)TwpS<4hlMJNdi&c88=> zR4Du!U;RxlDsybjGjSh+3QA~*h-IOvMt~9iZ@m#BvXJdL6$_qQu7#=EMOt0A)=4FW z%->+=<+7`)yUjnR`C0pv%VE`r)v-A5tNe*6 z(l!3!`IVcO`XUd9n~*J3Uk)Erq+Xk)m%U8@s$r=KzY@J)1y9))VB|A8#f93Z2;>oZ zEmcfC#&Rp4rs%6@lKE@+oN6~iYF0Y=^j({BzZq+oBkrDiAm(>>B!O}|4U z+PLb-e}N82yOG2SHQm$LCF0bk_jCbrCeFst=sO*kIKMn=74B`r)`oN)D@?Y&N`Q84 z9Dk6VFDlQOVl+Wzyw3V=ge>OUBAhm_W36ki0eGv_(?`GF3tXxGt?PYj+F#43~g2u18Z?}_hY=oCAmDwsTSmjRwdo&0=hlR$;pGK#&4Oc?ZqhqdvY;% zCS7;A>ki{S^boz@eC;vu)s%F6$|%$7nU&6J~xMim%(O+TY(q zrlc`C5wm{UbUC;&WA@hKSm%a!CaEfF8)>BOhGK}1CRmX}!kf#48U8?wIsQ`FVT0X5 z+*af`w&n+zQ3L;2@4dAE&a*bhE zKT~UL6YRTNhfiS9MRJ@wA?Npa`B^Q;Q|l7FhJ3;mllW6w(^XH4-a1%^DzpV);5oI* zDtkprly~rLg!)n?$L;>~_A9}x2|rzRzB&u%ITu|is- z$Y-=?OSW!ag-xp}%5x13_PT`3CLZt;d}zU7(YZp(O)et%qF)4O($%rUhY#F$>SBT> zwr5$$sVql-MhJyZ+bB9ods|=3lI4#W^>tfu)YmF~gm0^MtR8>HQg+|5cJmrO=j2PP z_oG;rh%@EsEZarB2PQNv-7$?&x9L}I=;Jg%?ThT8 z*x6^UC3aBdAFK^Ll9cfT&zbJTf4V9pb=$aIfYMsJ+@+_j$HonN>O|mq1syqlmIyO0b+-az0O`R>7I+O!Y9Jk?JzD ze^)-X|6WnPiMdnc#qre6G1ePHU7t?ij93<3i@OXnOU%syz&>tF&j)ty+1YbFRM$6r zG&zWutF5YDt}_0dy>7Qgw016K?V2BOsv7y`u2#T57ujyuZ>z$<8a@{ z%O%LQI<$G|R)o*Y)Iw|LQnYb|SisU5^!zM2B1qxegqJRJ1#<1z!h2bQb+6~Q+9>&A znL|fA%Sz<0U!zgYj-E{Rxkx*Q%I;a+p~+ZYdDa~ZH@d)*5H^vtrEqpg;zGjm?TO`m zSAz8I$x5N^;jL#+=n(;Kw~%9zE2)ZS(C$W-;QAESKVras!gu67d;?;Z|1hGtAVL{U zBvbw#)G=TZl~;eBjN^!Fegl&6*oSgKI}pxhWS4>mXV4t{rrOz|eAKEpSit3qlp}jj ze>|LnR1?h{B;PI8;lI~CI%jSX^0(i^Umh}-jTg?4T>*4y(y;n}(&O^K5p0AJn;YQK zhQ#?;9@J7E&(l5g|1Qg-BbU(q{GGQ6Gfs7`y8e>F5Scr()~Pw&!#i%*$;e(Xk?ySD zMcgGY>gCV@B z`z2VvpYVI4`BL2b*$9J6?@v?VoDbC4cC`RX8e2owz6G}(63<9k zk`U6g-00^%Xu?4TDlc3^8VVX~>ZyX7;*lh!xw4f;8~J+3C~z0?tNeh0xz$7uGqm>OJFx&tznnS(;o-{#T{p@0Xy` z&_pn%Iu&|ebcZ$QS=~cX`%w-W8CQOWg{Ib1R zy{4!g^|2&ba6koWW}0-vf{mq@fg{=HqzMibQYuQu+H89fD->TxcBM zY()XfoDcN75ZtaKn%@;tFl9|hqu~@&adjSBuR^}Ib&7t-s}ReflhPpKZD@^>%k$1+%0reA?DJH>=N^>S%r@_K;MvjpO#6&`Wnfu76mQ9Lb}^}{1~$oojiWl*lw7) z)0Jbn7Vk35pTBQfry@B%!M46n@?*Y?Sl<|KjBGr`B-HV35Mk$m6b zuU|=OOS%(i^|SMVA2P(C0#_Or9DjLF!i3$PA(AaNa-_FmeHJ5l;@1ai^z1US9KPQa zG}u9OYz_SEn=Sf2+O8EjP0-0uC+JH*4hRb_yD?m&=>%A*pOyjrm$IU)l9PxjYsy8? zh0=evd2cpRFMFQMS&I~2l8nOt_dK2{pj%dy%Nq&{o6Bxnj_#Zm&L)4H{{w7jAB1;O z)?zc$GUIu_|J{%54Jte?2Xr}9LMfr=j|4=Xajr1`T?@;LQ}cB2Cuhkc$klGGzzRt+ zG1e(sg~{u~J)b>u%YdU{_3|Ht>x>YTOHvNyeP8tCD>a}8JvL6Sg&I6!@xSvgAHX;W z;z39tYhPr0`+Zj$J0bQh87K-U?>=<;M?|fqr}MZT*dYQ6K$fq1@ngVG+VSy>QfJzq zcnJf**c!!4B$Yj=`iPe(rFN(Srzn^;*HUx;paJGSXv>C`K=3;$fvV^6<>xcfg>VUf{8%xt_y*XUHev_p0nDfP5Zknx=$WsTbH zz(nzcN)cNx+04Xu4dC0n#lRNO6YQp8%rwSHNWS3*qCBM|!DI zY23!}6Wj1(n|&DwyWhpwFIhB@F!0Gqd2t*1dWF%XI-CY?Xl9li(VyM#{jGt+{q(~a zQqz1W)!h!&&sp8~>V1!%_FFU;j;78;g#}U(E$a(j!S&*!POo)xL00#JdY+?#%~$8x z4d_Hc77YdXqC-yj5sXNURn2hYguuB=-O}Jo8F>_P^**G9RMy_xtED$U)}# zGfROby9Ha==!F=zfilv)xt|9u=;)}VJIL>(2ih%5@*QrLq_=l>?F+67#U5>tB9PSW zVg83)2AZ~9K$@VkFR-=%J$mm6&}vIjPDC)_Y}Z*fDn+SuU-gND^wov1vDK0KeGEUPh_v*x$MwMB z{D%&{W}TY!aIy=ty5pm`ab@iX_O5d4W8IB=dm%HPhug|GSZ!&drM~@%WD<=t=ip7k z^eC3o2ARP(38y%53U@wD`0qK8y7sdVyWi}sxV>SFe-0|$-T$7?L3#-0?=mOalhM>A zeRh$H*xRIOWg!DWWwgZC?gVTxpk$P`6dI_M99c_Q1c>B)C|B&|g#zRR>0a|Fbyd<8 z4T#uy#`yin8UJe|ud-y6cTt}PS#jzN|9n{gQE+AucbZL(7R4g2!lL0+x5IHX2Z=ur51 zsthciboHOX#fvzi(zTYY6BuLnUuC7gRyon??|2!Easz;wv4oXxM4(s@N|Z{w4Q6t; zNQ0Q$4zqPLoHlabIqOIfMuIF@yciLSPwnLBhY$5#N1x&U_?mO`IDwwP=d+zc*x>)kHH!bBS~_ZI5x0QiP;ijNl=B^jAu9p7GV< z0T08<@-Aej!6wUjhQKh4J|jwx3sve3Jx}UC%Z$aZDk?I{q7WQu(urjJYSco1e0;!m z*lKMKZvMiCLc@fcyqv&BfZkzX5b2&vA6s{&+)a1i%Apcv#bG}(MmBbL0{*8p>A7H=O7S-ghb*$Z~ngn-(@)AHN0F0}e2!d*x<1Ac>~n z1B0Q%DLrD_({tcBI=&VMNZk0#U~uSJj8C@b4OGk>(e*rB;i zKp3gSU%&72`%jM&S6L2AE=F$1ogH`1N)KOkragO$v|4?}I13-)0t4VgUllM{E;JDITd@}|JK?h2 z!=tf9>At_cdLJLfWPqJObx{|%f}s>o8nllKg4qsO>2H&)(06ZSuw2{CK*J+7!R6`b z&VQ#fiA^VNMV)pUr(O{Lw8sgO+bX2f^de+GXxNEstX zoo9e5n;I%7*iKqFFQfB>A*ew{TxiJNjpIK1oC%Fcx-lbJ-c_3|2F9QI=K<#|_zZS( z`_vW0MnpYa=q%7jgBJgFEhO8n8xZ#KSb6Yk-6UsPBhRd(kADo}g@a7|#JdL2U6DU& zC>t-4E*{hCoHaN&uj#^w*w{5B6HuK;Xwqh8f$Bi?Vmls6d zy)y@ulU!CcAXLr|4Q43}`e9>QyY)&084<>NuYH#gkJ>0?BE<5ezot*J@n21YKVH6& zGr5x`BnMhixyRenUD_md_^Em{uvhR_G``wi&)wTC?AKV`odOo-xf(n{>N;sSLc3RDVpq?7=qgo-Rv-F&6V4=-T7kuvDu)gHnDPS z=gW)J3HTNxF<%|xOtSTrw7xZ@{L_zI^S=j_(Q~~xcjU#ZUUU*Hh)MW1rwXRn$!7<#zEgxl<5@rZ^k=Bwqb}d6Cd2&xdf37s0tpUZ zZ(P@)m)!bF?UXl~x@J*6W+%6uG*;pfH};`VFF)Qrd8@4zndz>yFgG{B;py)ZtncZY zYzEfp3IDY&(*rn{)T67pseX$H(~+gpy{{%AdxNV_hEd+B`NkQ0$osP1&4V-K4Xz$U zlREFG%san3OXowTylaWgaM{n%=DaCINR0I)%EWPC`drRr@r#17)vqiqb`xtk0SDm) zY?3CACa&*4JD2cXKnEwPmv79OypELyb+4%6y)U#)c_f)j{9~9nk+|GHn zlg^yreJ4GVCVy9I=kIy=IawN-mM1KD8d;Y5J9>W4S!FljQjqakiHC_q-pLCK=^JK%ic7*~ZtrX%Mvwo6z4wf2di&Z% zZ5wQWZ7Y%hDkv6;Zs}FUO+ch57CI;*y@!@ibfaJ+5tQD^DNV0yb%=ye`K69=U6KV+V3pkeZYI&r? zj8s+`VecIg!ZfKr<`mI2BtY)8(b6*?$XS#j@zEcok_U%J9~QC z-Y&x4x7lH2QS%5il(Sy#OPeH1cI9D+*+$(Re_ZR!nAU_zJT(bt`jNS@rwdHOOoP=n zUw`KVmwfVDCM954Ub60>YIsGi?6vG0PVOT|2gakV8Z^$`U#yrK+;Ok|bI7DaY5may zduhPZiXp-Ix#kgMygC`Pd!DSb`mA<^MFp0-?>b{-;xcHj#1_~V_k5`Bpo`W+$Hw+( zAmFTD@mLDTY_NS%9EEY1FGqbYHa_wCsP~@)c*wMQ*+t*0@OBcqq9vNdtP}|#yn)O- zZGKs_TR3k4@ji92_7k`IUg)O_y{Ok;KbPF_>UA)C<;!(#wQDwSycDDx^?n7_v(ruz zxC+i2=CvWd54r1oWux5&x5jA6LtB4W?r4Uhu6aK9O38HftlP`l^C#iTVd%SzLRc6pU~l zx5H+OifoX^_oso9HDiKtk5A>#9Hy^W7q#23_7+vYxN(zx*ZcgXE9F202z(DI`*#$) z#rli)n^&>%`^%dksE#nR)$@{-D>3feCY7-og?(Nv-$=iU&ws#9$9RQ1lrE3Rc%D>I z|NgoZ1=1>Z>HWvTUvZ1xSP84&1vU&_@li5VuJ&LfL8nhHuuSdUmuac_a^i2?a#rED zZ59#1VI?(&+H)U~U+F537{_`7#|-ndk5Ai$TH3DmS?t!k;MMX%CG^#}(EbaROa0FR zlRfsL7}>dw)NtFw;oqY(j^v{O{tg9L;_X@0L(ph3RM=7llwNlj_d6>*UYr!Y-In{# z7#J(iMh0VbOJrGgvio&_Drf9i-%?bzmg)^6DPauX>^W9vCQOx(Eue%Q(3mc$)j>q$ z3J^ZmJiC#y{4jY@;quJThr5V28uP_Wq{J zxAWaU+~sCi!ZlSgM6OE3_S*@Uq=(kU-inu#tPt2(g-{i3EvV;pc_tqsVtxk-IOsi$ zSk?H%u0oJDPnqv0=)~Z;^R%y#EDzsaWI9-#JxcX!U;vj0lJ#4oUKD))Dn9>h=Pb(S z>`oK_2u;_)2K3$mlE?c>k4s#Gfe%khSbNjI5dsV{tWji}BR#$g-w`KbijcQv^&+r;)xIeB`4i~pjS2-g`F1kF;-!GWkjieEw`IIA@jN*T* z)HyB_nR>%t2CpDe=>9yUbE0jf6_4(**6L5}7Q-qsNZ(!%dQXmU8ury6m<^ppV)$TG z(j-~&qoxW7YUp(O!}KkO6gKW-+R>_ca1sH;n75cj21(i;K8kUR#*&E&CEaRD;}7Upawy(_z> zhPs^p?t?D{(>&PIb8Qzh*4e!KX%~g!6yNR508Ws8YQhhQ1ron6+nYuIc)V+kBoWUQ zp)T*Xm6T{-*|}tlWDAXFq}@}MzqfSoc)m(IqKSN_$G_&_Ii#230rx>%cdeKEDAgm8 zOE{_nEwIB6wN>6|jO<0|^<(9%DiVYHsZ_&;huI9vnt+0~bS*FeGv`8Eur+hPAhp^y|6FXdT_X|)C7wEl?m()`%%{a_1S3<)cGt;e^0nc>?@v&i1e zMV=_ja+z=y**f%eBxRb{+Ggf~>u}{i6gg5#18M@9l*g~1k#_)%3~B6$cg|X%3vZ{( zt4_-z`@2(pr80;d{mSXW=E$w#$N<&!`i=_;T}$vV2EW6eOIOZ^oC2##`GAhaD)>aQ z263nk*{-P!by0}Hdm?3L6f=bU10)x%YZ|{^srJ6LF;T$sUxU1qH}a~}kGV>09bO6f zTGM?srO(rpe+PgIh>{GunkzCr`$lY)H&+qNJylDhm&7#!5}V^CU0X>M16rDzUycRw z`7yJb*ciM7wG_jplSe!0%2%%7Lcs+qrSPPlo}P(IEfN?l8H0tXVZ4sA$*#I4=hfvU z66VVy443a%8Fz&cFZcMqLc`9Jb4%}X#P}{1#z#Y82=p>{qG{W+eam;55{M-4uOxpr zQPZ%aMau_1%R3wfgvOpLV#d})Ep}>KvJwHv_7A?bLksO$Wj!~Rl!MZDXhPl(l$6Od z>)7%{{dvn{9!m#FC0hRd$XoPNoVv3CR_p;k^pZ_QoFen--wSu_y1JsO3*s_=`7V`? z=+9oGR9+kJ>5Fu=4a=Sz{+MiqKQbIL^Pw$L%A+L#(xF5a+V4(`2{Xr)`Cz*|c6cWg z$2PR(I-Nq15YvgNOhtmMUL-c0^mJSGv1VL`PPV_r19tZ$RYo z=P7FSR9kHEJt>dG`qgFI>V-gF_y=lW%GSTgW0El%l8`oQ)e@~;2(wKIpog{RmpBBaijui+>1ij6tMuHn0O|6#gM-znfDwzFkSxW=_ zbFIr0y$$-DkW#$r_k+DZw(l#IH|$X|KCGmEmTuRQYN7=#s75sS+ogJEDQ=$d?bpb} z;)m`V&1U7)N%wc%q=Sw8+83l*B=#Cc-08rmZ0gh~rI#zKqamneP;p}$8zVMT(LAmz z$$8pmXJec|q28>ajP<67YRQ4U`K}eYZ8(o%P@@$pKDhySzX$1g}pgcaAa@kvrsKJ~4!n~*~Drf zV;qgCr|AB%%JPBCJ?~qdE#4O^WQBCkl)E%u+t?Tc)k1vA*QMNlOb|I0@G2wR zNoSp?f=;jVN~6xQuB@oIW>DuvO8DR%<|i|gIN7`(rxM(P?GSz(@3Jb$8zv0qf;)kp z&DT+B842F-L4V3e#{`?(J!ut+qI7k*O;r#)1TT#48i8|aZbfx3Rn7?9as3t%9nad@ zXU}AInKY+&HD`Q(FVnU#hCuUqlvnNP82mF6Bg)g51h*M&TV?19o5z&ceg2IRu{u&r z=i8I)vSxisOgY8t5ZUe7RFS&)U$k)ij&)ZaOS+dSGM(4WN5sfYTaamhIyAl8za7>% z-z6B|a!W{TDQRA^ez~j`x(%k#YG$`;ljP~yW(pE*;8N;F5oJr>X!x?o?mMyRrP)MA zhyn4(@y{EXNDCZ#8a{!u9CDbwc%7X$&%m!Ta>5qv&UZ0A{Z$T!8_0n4RxVemJrTXk^xWE1#^|u@gIAa|=Q%!s6q^n+6 zT6!7*52FW&K_D2I54F-uVall*XUa`#Dt2gY(++^c&zpUTm$$L>)%5rGFS+$`*FspC zu(Cw9D0L#DjJmv$uO}xb|DcuB*J~&5${lIZN$1Yu z?Zm{yz5)oC5sc@DKx>QMsS{~&*+&&I3T|KAeedPRZC{_+(VyjJgjz~0k)!9m!i;iP z?B=_jO82AO6(S`O%+$8TQ@WOxmM@Pb7^}{^B))iGoHSW5ERiPJ`eo- zcKvC*K-$s*jW9n(z&Jf>6-SdDr+okkvvz`DfH2qfWq56R_hmSc@H*BFg=!gP56cCv zu)|w!sfxWmIMd}%jjXn;_RZe1&#KZ>X%-S{O!I*-R{v-ffiWmpl?9L9qJtIbuJ@z{ z@dO3Db%h7@2vKw4N%d`5t_wQR(=cksq_lbQtu1-H||O?4^3%wk812ihiq z(mbPd)&M|QN8rN7oy2W(3EwmG2IhKg>!Tqm$<5%Lt{vweAhX1qY3FFr*-{%~6W%`f z^q_}oiO^zuib_gzJnLQ+g$%$ONE$3DDOSDd22MPnv6+7*URRFMVH+1}zt%?fyu z>pjecp3DWhwt0Uk=I(1KZ~oOM-^x3vM2bI8V+7z2DGp&Bl(o?&N}bMaK; z3dl(R+{Qo%IpWOt5;V%}$8QIXr&B;=h8}DR%C<16wvRba@rXc49+joqOS-9+ELg<} zK(5Y+wif6{HB?v1RXWm%tJ*cn9{pEJ@(Xfua-0hFxX_bwa$LpMM{@(A+qzZbrL(fL8=7&D&2;auk&E*hJ;MjNs}(-_-<2@L5{NbJ_Ar)zqu&d*-U9x2g@(f?J4bMNSsoLGdteQ6cR71!Wxa1d? z*AC~Unvn@{wLsRZ<#x`8`S4}eUhj^v$*M*C&z9SiN)|)`((-nh`w#Ns zuTBE?S;SBgt_!_fZyiq{bO&l10<>j)`ImY8YUc;Xh8#_J#txnI0k-RN?3cCudrwLM z8d_<#N<09yAuTb3x51iM=l1!I=Ik!9pGG%d#R=Q&TlYeF%`XX#yb?v(hWX&(Hm5Co zmri6aXwYVpF|M1Wtp0^|_~V*Mn|#^I>&M3sr-E3uLk053zCOuax32srtaDX|g3H&~ z`ODv`_l=dYwSIui?1r@s171E1A~y1NSV}-`s;bSlb*7MC&jhDONeSsW@s{?@4?Old zqMgyyQ()yd-j;NKdTyHFs~1({<;v{ z^;G{QmnJ;;DOu4awyeB7iTyIW`6Y4v8MU>;0}^dz{G`8E8YCVcqFT*%&Ucrp#b6q@ z9~-Fj%CPopSGwJg64!WH4Zti^Nkt_EXUeR*0+_ar!KP>k=CuzloMMYCSh6WCztJeL z`xPI)RD*4=NBg+|7(*54)m=}@n!fZFJLIgd_Z-AIUm(>6FI+SNH!0&f`6OKjjht;r zNY@zD2_32oUbtO4b$6p+n*)#^k6*z2=;1irOz>*YS`oy78c$*nn>2G6W-kwe8ePOR!d8Zbox*A zTV5ThYWEjqttw=@5pW3`Tbf0gb45;vt9x>v#HFe)V>jCMEVIE^y-wr>8l3Bn8IeI@YUr8O#~F7i78Nd zXzOqbeU=^oSlSz50pNPU(Pp%vnc1@~4_V7VC-J0dZSMnPSxIXV(RUEivvi2rgDN{a z6Q8|MU8mv7TV1&=A-*f8afs;z5th|>f01?xs7Z`!n?Am|r4_I_IlOVR(4LvO?`O{^ z%pv`l!5Svn45OEKO(NnQH)fQe87*l2>tz)nVI&i zsXh|sX}w@sPoWLOE!7PhNlgqiY&>7xR4W7pA|hhg8K0{q65(m_k~cxe+jPX_>qk9| z(mIP!v_>en!j%&H^A&WqK<&b~L%aE8hJx3BTO%RYt^V|pn07a^xIZ_H4ic%W#zCuTYA|P-Z`Pa*t z4_39~z_mjs#s0N=KzI=^kd;NpbOW7F8p~5!sb{6B+Ey1MgsjZOG79JuGY_4%>!T0kEqQA->j2iq?}wuvtfHU4*YWehOS3v`j^AeEVVim-*Tzi9)T6D!keC6b>TZC+PZd!+6d=U$p3B*q95m<*OsbQT7&{AmsUXWW1JLFO-*_h zIJgV*sFs$nmITrrk&4#lI5XW}SyJD;=NtX72|PwEU@9@G5`&QfoB-DyO}J)blO}6X z^1e1uuBLsOS_v~-ckAviROqSz^$!S09xGd~t*UyI%bI@XR#@G1ky`8kQ>5I#9{u*^ zjWcLWdHGcimum#B%4-+en&7I+Cmt4hC={647kGvfG2J7~%VRK{w?gjhJTQwK=C&cN zcB1aM&;O*XE_vLSqMk1PdUF*-zp-=e`y4Qs8v|??!TD z8eC#{b%ophhgF69DfAZDnV%#I07exJB+eqE{SQti4LP3V1ny(=00vY7Fa9!TxS-6L z^s@JxTsGPtr;S~pFRuo7`FYStmKE+v)#B9<)7TAI*Gx>%7t=NS@^vd;Qv(kFw!6kCL70)E9g0gT^^J=Rsh*L(+`UA%%~ zSvyDcduVc_y{QiZH$LvbHd3z@TDwS4Bl$c+y8{Dw9n^1oREj2+D1gA0tFcunssg#L z8e1V5dE^Ru=J5sfK)^^iu!u=4X}Tupw#iQITX2v1Xkoy8F>3>X`m2orRbNq7S0R3t z(=fNbin%rdKGqV9-}LT~4$M<6aR*8{{HU|O?TJC9U8pI<@*@2{ucCN{e9%tW+!_5; zn??5x&`>@D)eh+el!JJHR;!TgSUkxsYQWLjrIGaZ?H!9kES9KQp{O_kha826@do-< z%9z2^zx(ys{{eKbjK|BNo&NMW99$BvjnBE5w5x_{e_52=nWGibkIbD7T(=v&c6>g; zRkwc}jTC)C}GymccD6H3p1sprlZ4wwXLwc1c} zj8e8X(-MRQ4P%v|eRrPiv4wL$Z}{*I&*0M1rJz+0Gde zB{MN&_oB{pDSV)=%j`p;UCL*^H&*f|=lHRrUJ>`o*oHeL1nK)vV?0~zk*H;enlm=e zxN^NN4J!>@s`CJ=<#A`?scM?c>w(Ps2HdC8$Dq|H2`x*}N6kg*_FsOou6+OLuoafT zs}Et}3}RE@1@79GkdYSU_k*T4mquP$QlNb!F8ua-p0L>iG_povHFvaxx)@dd8f2?H z5+KvbQtZer@pZe?vYRz~+)zy1q0rULD2Ye+&&bu4;~QR00?eMkgnr`~OF-sQifRKSYT0kldmTMuV3Qq>_7<5X@wN{;vNFfNw)U{V$0P5EA z&Xp2ucKo!O@5bGC3{%#2&yNxNsUjAP)R;>m`r0ZMVY7I=_3jaUt)Bpd?c(NkI`Eqx zeeU`w62(kKv%ychzy}s;2zO4JKC2fV4o^PeVub-*2H9msNh5H;Cu*rrDIQb|Y26w_ zfkN@Vr}4_rW9;%zgVO?oC2>WHM|xK(V_H7`hNNa z!-)HZ4lirN)U({){q@^zyg$#sH-%fLx$X{W%`ym%v@GrFb)eq*`1NE^Dse5lvzEp% zRz*xJsV!&kO}d3};^xC4u;fKo1K~SjZA=&-OwgFEb?~%Wxow~- z7Moxf))z8Id(4L;hu^Oqxc`%(`QMhId9?_1=*&elK5X+u)ZMV76HyWA2|&@4Boggf zv!{Wy#!L9OrDi3N?m z!9fo(?u<67e7#Q0_Yr+!oIuj}`0a(&Pkt|FucwViZkeWc`>8m#?y07wBik4rv;{l6 z(0pp5PI#DNwzDkl8n5d-t$UKec$~Ah&tHqx>u?)i&J<;u!||-yVaav_)rQ`+qxmD` zjA@7gs7hxhKtFAD1Z40uvW#^^!#G_T$p`&mXo2K8_sPh1oE9zOsyv`bmm)-4N^u-C;XUs*&*iT9g%^dERr zc2GH1kzs)ktFvfQmbc;OdiWROAoh^`?4w?}H2Q+P)nTDaq4`}Njb=19wwrv?l|~}p zFhywis=Sc?ZLf!_@xKA6$8#L-w3iFIx6GyM;>I(FJq#hA)TIq6nN%jEKpihnyWo0- z(fOL*m77B6U|AdJM1VGh1XkT%q8ArCUldZigWapS+Wl^~*q1imr9!fWpn1d}DI=poEINe_s zwh`rNrt5L}PATI8qHcx#w1b8x-ii51fXUsH0?WyJ0cNOLelc1wB=# zHzrm#nkn@10_3KYL8%1ZM|qdfgZ|#0ku&Pc#!<5LPAtg2oQp8!mFqSzgVRiC6c^7? zGe{P$aA?SOA-z<0&|TMt9#)MmC%qy}_#eSNSw+`q2T&OEkY1^|N=Kv@2!4McU5~0G zX&U%T1+)8XjM-O-ANbO(>dxTSx&&dUs(m`ek*Sq*emF(l{UWVvrRya2cyRQTwySBE zKVL3#8^_9_*Y{D{)9oOdOii~@J4*IKuRj9^>fd`P#~$+fJ^D&MX!h)QiN_i+Lpab^rJ3-`>xx!c)3{h$ujwTJs6~3n405|@^qQmL`}kw~Q0~~6 zx*mPrXPw&FvXJGDM)LB<_0_KJfnzFE;a0E0unXGXxZw&5+7%{+)^i@!Un0H!1n1sk zhfDPJY)Dh$9ZvVmYk;AS5ex z*}rb){$fDgnAo$hjY#R4iYdg3#Ac0qhU`BN|Cp=hsf^Rp2ISz@`%>kAyFDj@Vr}5Z zZpHquvIIg7V`FTLbFB~_X{@YjN}|yA?TJh74#SZW?DFo6!C*4jK(V$O+#xat;(ct`HRE`1a#lxcSed9GT`9nDrR`SM^UFlX4bX=f3+HMsyP!o zO!n_xJeoGFEnoSB6;MUs#}|;T%a0l5BS48YYDHrc(}rL5fCl4R93gX3_ocFDjXcg! z5BiG557eYAQ7^~U>KPCY&oxHMW9#&^10`x^_{X8OE};Jz=(Ujd z`#bZ#Li;*t>0UL%6_rMP{!7^hi6ZCJ2Qvho{Dc9n2Y-}vMcH^Yd}|r5JG9`%xdCK@ z9;P)+trz8h>+Iz)X<3meg^kJ~j4)9y|>X_czZF{_WE+Z4T%R&l_VKPXwZ@Spxe#A5?HZvjqD5s{toQ z4rS3p46u@>sDJKKpNJS_UCioP3NMMG!_4@;fC0s4Q{IOHAHF{0)Q=9uNAPUW%vRrmGJ$Rd#quQXQuRE36PJM!RY*Uf#U_M=G=h9}~ffoPgV4 z$xDMxk zlP(#@L(|GGWfPYuJAsCD)g00FTiw|Q#GxGx>4r8(=-;naL;k2@mV=#f@VOMJ=+%OB z95MlhG;XaMl21c>-z)akHTqjq&ks!uK*iVth9n%6u7*!xS3i}4Cv?a3DyQ0nslMq^ zf&~QigUhl@sHCPML*$i#6`#IoPGkQk{mS_YLUcfTjP~sC*>+plP5LSHVzQJ697s{A zr8ltKN}@dj>x-@ZzFu&B%cbn5&#$^Mh^Kof9|eqgb)Sb{ok1Tv250!v!X;yX` zfs%1Tm-?xEMdM0nXZles<1{>!i(KI1dEEQooEQ~U&(nl{za+RPfwZ(4Cc15n*5j)< zzC=kOw|Rl$JKkFcFP7IM6MhBg7W={{%UTy9P5&`@eMyWQNO>vFm0-??+-+ z^9X!Ol;JoakjD>nfJlx;YQ~8GH&R0At$9H&!4&}Pdpa5OTua%eXQp&8-lOwGxK#zr z2=WFe2T0bHbC(FhdE}>A3(hCW!SLj4p_^$rcVU%YYzx{kig}O3A)E0>Ckl^-Y{?&b zdKQZ%IZjvij9BB+v0;mO%~25s!ecefw;8DX*utI!w7Nn$i+sv4K4#29Sov1u2Jl3NBh263UGQyC0CL8ghl z+wg{oM1>%tG?BHq3ax z6kND`lF0VBO$Bti&o`=L$$d8C5OgGDjVnW0Zh>)NHoO*w|BihcP!|W2hNx~Cy#Rb=IZFpOdom}VW&=a>_d z^dEiR?souOx~vA;MP2I4ydpMrd}-L<8j7$%vo^R86IRoT8Yc%b6V}Pgs(iY_zqkq0P(RYj$koLU9K5W4g|H$lX`KwON)f-7i?tyaU0Amd z1#x|I6~szFR0a~%8`d2VTKlv$%JtVj{GE?p16^w&)fzuY>5-B%vif@lemvm8V*^iqR*eGAS@&|)ey@LwFfz;g^bmjT)}Fv%kb2W}gYgaE}an`SEHT?CRfTwnORXtTg*rjWdT^=-dv-Iy2@~>fH zK+3@V?S8Clf#5%fU%mr`AgcU1B^~~MdL#gZ>j3#N-vse$0kCsy(nQOu6f~e_P2Wz^ zjS~LTti;LLSwCLZ;t){0jho9DB};=0@c70-a&vc((D7_4+0PC&V|D#{0-s22%j4EN zlMd}3mnq3MOh_K}F+^WNFJ8{ZLnz>`nPAB@kAG#?eq2fMJ{T8#f z_I%Vg$45FnI$t<~Ho#I#u1*iD>#4RntCAz_FTd!m4K7ui*(fNS*qi`3N4*m5S$2-| z#;p2!TOb0%9NUcsFd~G@^d~!{9Mwat$UAZ*N_eMUG<#3=7EdG{3Jo3LsTRqzX1B-w zTs^R&Wo&)k3;fb}%6#hyY@*0th3OePPYYy_osNX~-yGnm$rE4UP#Xb*sG6VS0v<_^vwGhUjaX;a{6t}*3mYTKFbU$Hj?QW?- zUHX9KYb(E$75>dGWbV&ketvXF;6@InUqp zX!ldDL#99}gUP`V;ImgjHApgLu+Xg;B|aWJ80l$P>4G+5TiDTj0mKhAp;zRShWuDd zC$P1D1lanEd#YMj`#OF(RYkKMjxv}vq~_hM%%(9w-3cgeGAG8Z=7Y#keX6>1af0!( zYhZ;mrZ_cW+TcO0NOD7IUQ(^D7@=9m~MA81!roWI~c zP({)-c7^tP^e?<#Km~ZlIuq~MI%F-lctv><@cVVkS)_VFcTrQE@t_yp>8za}vfz>J ziBSb7NN2!ceHN$z<%!+m&uu`4N6|Het-ltctu=icUeK75Hw!VO6%&ryaxhG0&67a59NPBoR{f+I@VRNjhm>t{!X z7A)IRvb^D-r$p?!c;-;UKX$1WbcrHPm;4R{FYQovDN);P19^C5a5(8Hv)2Lrv9f+q zuIps@*BIE>ktj)&(oEi;5YcYuTUiz+mm7(WkejPMZfA<4tv&Qz8b1QPrI2dIa7!1D zWLq0lyi^SxEEKoQt=k+o#ntE9F9~VYx!j??DpwTkjdZv?+UeOfW7hBIK#vyH{{Bv6 zZ{#7|*&<7>^YBJ_q^Hu`_-AnU{vh&Lt9Xh$hR7WghLmzu$VhpYj5y>}!1tGuqD;0$ zE_Jk03pO}7I1e&M$u9CWavFFrJ*OtQ%5(ui4yWoyr=9TV_yip1IzTa)TI^?j>YB6Rv!8u)c$q5a}N{Au%#R{^@-`T~GxLw)rGmCPgnsSqueL zyLm2F*ohpO8F{!)etedT z@B*7aX1^IsU&-LPPGdqvs-_e*Om>O0vKOSgLDCXa{RNI6sOfew$?xz&3S2!rTb&hp z4Hp)w^CrvT`sy5`y4!o)w&poJ^chl~SHAW0NJFocM$e70tON9@ zJHmG4g%^#!in4UU`$89oxkGHeme%9@6Tmn;>DgQ%WPpUYa=GoY_>t5cwsr!#p0dBI&u^|jB0 zO6>_X745p!c3bq9u9Xrh7T7QLojfuKBfBpk?4C2)I~|wL-su6+E@CIJ%KVWhl} zsQRD;-f%dDBhgKpE~o(~XlW751|4h>%M;V~Fd^?e{=VB07LaiFt4 z&n(lLzC**X(u+8vA3J1K_3ft-;zxnNJb}#}{%H|iqpZ#psaKv@0PQimXf70`(tHg4TS66*)jK~4Y!DYo`c5az88{H?u z3Z-!E!E||s?QHCMtOAMmkPT_U48~W*GJ>bn2mIZLFO5r^Ek0Jy^=UkEIWtFpdQRi( z8*paqAPI$LY$|AiGzfnd^1V?~S%=}rK~y*AFgeeCL1|eX>q9#F0^i0Aj*@Bq8H?pt zSk_PA?J=uPQT6y`h9_LDMxsVe2U;CiS4!DbO>2;d3U80$;biLAOlUPWuY|VvPEb;j zI|cX-D>6=wYjYXlkqxORgG&ycJg=H;{;$aavwz`` zDf^z_vYmy5iP;OWS>9R9a(FJ9m0rrtZ!V}HEjG4j`6p$C^xW_ulq zv|!37`#eDD*2ep+z4YMgI0?4(1bk3MoHag!E^JQMA%xG;0|qEp4L26A)=yAGCOFG9 z4`K`?(OT?{f4VeFsg$q_btHZb(({8+gTsJyD8d66eSb)5WfUv9fpg=91z{8gPbw7Y|eF2jQweG(a3-(~LoDyNWq_irnR{$a7L{ zua79p7qIKubyC8w{pcqR*jy)&u(k-~JrhH$)_)&9n8j2bbi2xY8Me~rq0c}x&4VIS zwh^0@t}s|X^EkZSN{R2@Vkd%q61x4X;Z`%%-J?)CuGV*?Wk~wn^ccw_4hi5F3oS>- zLD-`3P>gs)J(_>b((I?)1viUTL~K1$KbMQ;I?rm!)m&7BCXDaVN-7)h3we zUhP=8McI*q?@^_viccD!bJzdAQ*c2l5%SF5sm?Hd27SaTpmO@kY&DI+ts{ocEUIZ! zD1jZdcI4}tV-)jyyHvAE2=o=tL%G17-4rNGbE5Z9601K@@K z_m?d>-inKa%4CSjYHjtzctX?ho_9EDgB8khd+cf?k)tplHtSu=H;nxxQto}) zb3aP@7-+*3s`}=Bs?UXg{SmxmF!<}OmsA=^O>*J3X@E25{2C%=OcJ$OFMK7?ONkrK z!oOL76$dYj-~RCEcRyFaf3|~`FoK5dvXx%L_3xg0R(<|!TQb0R$ZyUSH`wAA?J7M7 zKgUSR{c|j{-h19nQ1DApBwBCh`Wqk^m`0jR_m}5c)FJ%+T94%_0v%9#xphJV z>C>lAq_?G@!tC9r{f#pk<{jSBF4eE^r}z-Or46=7Mn1b0+dw+`?t$2ckjyBDbD-=r z!KO!h=BDbQwp9Nfi}w5bY@n3b2)Y?6TMBew0sGU54n1g4Rfi89teL^(rG-;HD$CJZG`HQ*hZ5$zwqqS6 zOTePYI;qB%4SZ^7uX0q4&AKPjXh6>PX3i>KRMN;;&6rmH^Ng4hn2cAyZ9)m&xJTc4 zu61k%6l9Hy&j!J2+^fdot@<4|)G6G1BHPnAm$msEMA==mEiKFg5q#*ub1hYKd|0R- zEiF)3qT2?D;HMEAs4)=`F!kSh|G9DxM<%|qpmFP6KG~m-KD6PS#l3i_fa}?p@8@NA zR}DqIRm?D_Jyxh!P5fi}%VPyk-JLIK6F5epn{Cj@{eb@B^KTCwxZkTR#y&Y!A3=|l zG9Vbq4Lq>|zkpl7WO&IK=u|*=vs=#OsE~& z^II70sGY)lzaUS&i59%W^I6*{-_>*AS@Zz^y`0bsm4nC>;Bps zU>Pr~{GXTq>$Dh3qEyG-dh%Va<(vBq_yY@E#z-tD^Rr&WQQ%O!~?;7?(ZkC6AkU$;uJdrxPdDjYDLAMt* zb62r0N`aM1kn|$#*YdAyg#kv`O_wy;otI)$6Hq?O1MDr;#n7kZBjd8n<$D-EqE_HZ zM|tB;izaVH3DjIsxQdyX8H{%uxH#=Zb*TmtsOss*8$QBcTDASo9RSrt_6ChHoPX@x zu=^O0cF9o#wwmhj^iPwm(KjeNgL+{sAU@Uten|D>ZHe_Cy%p0hHS8p${TC;72)gt0 z>D6n&SoxZ%l6QOl>nBS!tdn_ln6-GqZmBij`~63nOKw_EeUln36|{?}2|VdEex3yc zKrY5wi=P7OR0g~oQxBS@PLvEtp*6|cSW^SX!cjWgF}iO zT_qw_BzsJXCUt~9HWE5D;{r@Eo}Fnd!;>WF^mm7nP5625`7 z!X6&hj(Ya#{ssY=^wcsxxn1E>A#Owml*pI!@w;gXpk-aV16nJf40a@AphUv>p6-5B zE9K#{c~EU#wh)ZvTl{gGS;X}P;Ks}SoAx^??z0Q=(ZEM8?pEAvGiIR5qb;hQRj52% zk>Su-q51uD#B|AajqPnt{fiX4VR=8kQ|+2xG}6p)tneJ{mtUAehu7L1Vc#qcm2Gq@ zY6FR@KKW;rGN@C{_Z-a?&<;TsZQ+2i2xRtp=l9Yo@hj6XO1nCNqSM2L%x;`j(524f z)FPLsztslfxr6QPD#HV-I+C=@P^;DG5r6ma3RBfbCn4r2kLR46HR~86Y7D?$vCkpm z!;>GP_k(&ZWw4N;PPW=3v_zkqP?;>BLxhK(de|%4E@StU*+XB?G=Q&Mzc6|}2DscwRz0dDZfus z3TVK)5CQAreq8ucRWzuXLy_YGmRHqH>)zY>^37X{FV+g~bbec|Ifm=Ip7ZA{>Ex^e zZ$33-z+rHy%FlhCtCb_D#yX|3hrthrgp5Ppow}72G8ZZ=O-lI&I(1Z{-OS@99?KfD`Xa^B zci)ZN{Vilydc?*3DA#%1TSmOhn5y*p!Tb`(Esr#+vu5?d~NrmCSYgyZxd=LxxMP%Q0SaH1bLQonJJ6^N; zFf>=?aN+R7NB(!4#|+dMEetjIgy}*IIwY&^_A#tXdLYnSl%oxUwLq=JL_Tf&kn9VV z#P;2&$l!2`_~yR3NX!JC07e;yjJO#-KR9`GC}9^toB?L=U#DcJicJv60|=mRdynWa zzGNvGU&a)-`G5a560p?&F!*x=(ilN6KIZk{>Bf%$s3chXeoUQy5kzziGTtOM#mB>VPf+NjJg%??Cw*ZVlt>vEzQa5YnIkZOKW`vE)uASHR*6?A&w;QSk+hN;A z-`544-iQb`-=|yfGAg^)4XSl$rWBIF03aD#u zoaQCLsyKYxA~5y5N!!0~(W(DePH>C*VtU@KE?fxyoM#?1`EGvD;x#Ju~vS*PtD ze;D3NkcGGJB;LSRpSErC`8>O~oNb@zt=PsTlq?j05sfL|PPLwsutQFlm!1>#2c5|~ zEHg&*)hqt!mDS@%Q6r7sv7)HGdu3km3%gLOn`Hy79X6ZSLqr2jMzfUvukNlq918XO z-=uQ8mMoQJY>gNdQkJ36VhqVL$d*!EC6gsCVPxDe7>u%)?V6FLE-GtDVn_{QtTj{I zp+UK0X&5n<-#gsW{pa`mp5OPsuRlDGnb*6VbKduy^LgKM&g7++Ii2HYc(J7Pg(`9O zj*}B!HG&$O1ypJm0*5DkulZYzv`@VJ@YxX;K@RY2M>}GLwXWG%F=Yf(=}jFXj#C*R zX*;K?wqBP?ikh{AzV`Q=E7Y(~9`__kz!E)S=MYym$_iZa} zp=w@%qfKzloSGZMV4Z@V2aZiQ4GFf!1Wun%+w!0s;t;kV^MFL!K;df1#Z#Ww+Jw}aF%=cH92 z7xU*cLfEB8Vs@87@#qH>nWGUSxiN3jB>i`vlodjDKT2!7q)7oTT^z&n6Im2g_%mJz z_A@YFvL`%M;j=WcI?F<$_o}A;*ot~r8+|uzzeDvFh4e0(D%U z=x;Hfv~TyidOUPWSa+|1|JMqi{ zO$$sNv*h27QZ7_T^1P&GzjcFYqXB4E-~)^7a7$ftyl;cwy+Rv9tvmXHI`OD=mt@WC z+?f0;u+Y!AZ|u;7to!0yvsz$3-~#{g;1b>r-l0xxHQ@05u!3UWaCTOQxYbcq&hD15 z^amY>f509Db$WqYnPn9=EZ&h~W$2V+b5q|Cw8nN3CXIW(F2#w}Cf|M)1lOUv~kt7~@!n9JCZch?Qs#{QQ#{!qo7(apj>nmiUj?aD0XEhRTEqsGR0j6s=r(*qh+G@>!l9 z(%aC$x*S4BOs@`+y5pZ%dtP-`{iGOD_gg&AGQaQ^ewk^1t)p+-Y@K ze*L$*6J3N)v`4_SE%Ezk^GD~p%jqfJmd&dxrK?9W^$+Lx*%C7%L#XVT_=c}BjoDJC zlNP(lSiMYrwZa%wb$*ynhrciqJ+*?U^L7m$*Vt-Xh>0}hxC&SI=z3$_4+c(#cO8D| z-n3H@{Y3NI>GL@^Fsl%A)r&l07&ZcW~*(-DIcVyo$ymdpK9tCg%x z6cx6nM#5tuW&k=J4PT_YuI2^R!IeFHX%*#5g*h3R;V<=YJXDB^73bFKoy?5^mAO5b(^W2Hlwf=t{ccN84>?u7 z)%s{Cl_FQfY+loD;OH;Gm=s|oPJNhkPXnr@Epj2{F5D9kdhl;L_9c2qWksUEBJs=(dSvX~~yX}p` zf^MRl^Itf=YXP`#y*$B@uKB$B$>+)&cbuwvDZny=x#}XBD^k^Vv(+vgllbM?#hOj)d^+J`WH(63a;MBj`!Ew7ee{IOziXb) zg`GbvJ8gK;NI}D*pMg4s8%~w%dc%AFLYi3)v~Jzwy-Uv&J{>D3vsPmzRQ-4P<|jhgiok)^z{> zqcJI(Oyxa`ajZ}>ONsH*($)s2vXUfW6i0$02>{qOtGC8MX`rA*!Qf{Me0cK^&&YUi zu}PE#>S)+#%<4gAj{AatnUfmm7ZxXY>H?*$oXZ#=U~OyQnJ>uJ?MOi*T>$PSKF2`~ z{|bN;H@#wv1Gg7^maKeU82SDdECy;~|IyEwdj+1XMHNJ{V@M!%nKT$&96T(9DuacG zmM1Y{??;n#hr$9Z;rcv(p(9zzLJoYr7dRAtY-cz=s25!?JM?(##e@1HkROL4d9&ZTuA293w$S^-%-_rO+3UwUr7PW;D8`J~lJv^rk znc37}4Ihq~t_={W(M7+;v`t5 z4hXC{5ZLqMCxO)k{xTe2c#-61S2qcgOAeLIsL=r&H?TAvV{~=1*w72=+b;0@dYt5K zP4tWfCd+||U+pRpc2Rq1`)`V}c9Rr9S(Q93UL79#b5X)*-C(R=b4F}sT4ffHCGm1! z28>Tke)`FLanJ{poO5dpnu;+dpV$mi6y{bxx|k^|)Cpp8=yH3di7rV7oJ<}?a~@K> zg;_fgb;jIT-g{f`a$Y)<>Sap330tTn-Y*rC=y@0_NlgcPz@h-Sw30fIncw9Z#SqZH z=d}TS=^Z}TPenHA`phb5Udm$ptOd6+T=?~D0<%z*c)7$rN|i@1=^8I@L6*o)Z!wm* z>nQa+)rT5hKi%{T68kkRAmTk*Yv`8#KZG)e6DfYi2(UL5AT!=hf~BNKv4c>8Ex%Ie zEl(HEUwLtOH3$+}*B_;2oDP;y)w`3mgC&NLL10=Eqdgl0OazNa=i<+k{7q#Uut^&S z85>}mYdu<&1p5U)0n)*1@oNcG4MO?EMjk^IsI^_Mx>Ag-iB!hj0v9clwJz<>RG+N0 zsMa8ZguE|JEjZqIZS<3P{D_IQ(GdoAm=&K=L7(L^;OF>#Lsj}C|=(Z=ytx1kkf z+It|H_?w)AuD*60X;kF{9#e~~7_oSfK)eX|kV4vkTuaV`TdZv2&-JEJN(5OUp%&e1 z62He06?q2kpZEUsjD*n&JW1oK#1D9DW6Z8b7_O(UOdEeef&rshJ-=FD0XFJgcnXAI z4YJA3$x#)$4mM9etzCiP-cmEW;!{uB@ZW<;EAn`z@3fPJsziz6c_h_LC2$fiq{j3x z(TVQKUl(RE*s(rqpP;y;DN{Sc z)Pd2I@tl1$bv)-!K@-hv^=(kv%R`bVY9UXuvdu)0Ffui)evLU%Q0Z6!(`!Ovi2?(P z2vf@Ok^?|wqhM=W?{A8?MX3QEulSoNepnhx)1%c%S|Z_;#$rLFW&!W|bkCd`1XUFw zVPNWU46hi(UvNkXL4DiqAWHP_lU7@k$7)K@z5W$rQ5>MQMCt-x0 z+$ki24tG6B1WH2L(zQwS%eGLE;C@SifSHzpXmYWnzr)tT#{z3Y5J-H`zm*w;$Lk!R zRSF=;{NSn_oDyg_ao2WJ2_b}3vcEMR|5EwH8u@bm-WO?YCz#ik54(vHyeFf)<{c|0(ejXgjY^hj^!x7#2pGOvy#}i%f%2f6fh#kxE;X>O+A)#U zVrLDTr~-jgs3-Z4c*4VUeDZ-v%z*9NMslvpq+9F*8rLG*5J%b}|D_5SK~apO2$_`~ zItaMw)bC&7T!&zC67N?<+Nnuw0dtS*8S{%;%6COe6iZ$|r=w(7+PL1WT@@#OUrZ;H g!h&i$^ekaJ_U`>d-_hmKPvFN4VQE};;=;}U0i+%nS^xk5 literal 0 HcmV?d00001 diff --git a/media/gcp_enable_geocoding_api.PNG b/media/gcp_enable_geocoding_api.PNG new file mode 100644 index 0000000000000000000000000000000000000000..65ffa299b07fb7f28e12397ea16df3ee4144e4e1 GIT binary patch literal 26377 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 N!PC{xWt~$(697d0ENcJ& literal 0 HcmV?d00001 diff --git a/media/gcp_google_maps_create_credential_api.PNG b/media/gcp_google_maps_create_credential_api.PNG new file mode 100644 index 0000000000000000000000000000000000000000..76ce813442502e1a6ec3d99e4af7b0056d68981f GIT binary patch literal 76373 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ⅈ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 literal 0 HcmV?d00001 diff --git a/media/google_maps_platform_maps_api_and_services.PNG b/media/google_maps_platform_maps_api_and_services.PNG new file mode 100644 index 0000000000000000000000000000000000000000..ec68dac532d2ff90d67d41656bd5d2b62e74a958 GIT binary patch literal 197888 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�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 literal 0 HcmV?d00001 diff --git a/src/PSScriptAnalyzerSettings.psd1 b/src/PSScriptAnalyzerSettings.psd1 index deafb24..4e1571a 100644 --- a/src/PSScriptAnalyzerSettings.psd1 +++ b/src/PSScriptAnalyzerSettings.psd1 @@ -18,9 +18,9 @@ #________________________________________ #ExcludeRules #Specify ExcludeRules when you want to exclude a certain rule from the the default set of rules. - #ExcludeRules = @( - # 'PSUseDeclaredVarsMoreThanAssignments' - #) + ExcludeRules = @( + 'PSUseBOMForUnicodeEncodedFile' + ) #________________________________________ #Rules #Here you can specify customizations for particular rules. Several examples are included below: diff --git a/src/Tests/Infrastructure/SampleInfraTest.Tests.ps1 b/src/Tests/Infrastructure/SampleInfraTest.Tests.ps1 deleted file mode 100644 index c44c360..0000000 --- a/src/Tests/Infrastructure/SampleInfraTest.Tests.ps1 +++ /dev/null @@ -1,18 +0,0 @@ -# #------------------------------------------------------------------------- -# Set-Location -Path $PSScriptRoot -# #------------------------------------------------------------------------- -# $ModuleName = 'pwshPlaces' -# #------------------------------------------------------------------------- -# #if the module is already in memory, remove it -# Get-Module $ModuleName | Remove-Module -Force -# $PathToManifest = [System.IO.Path]::Combine('..', '..', 'Artifacts', "$ModuleName.psd1") -# #------------------------------------------------------------------------- -# Import-Module $PathToManifest -Force -# #------------------------------------------------------------------------- -# Describe 'Infrastructure Tests' -Tag Infrastructure { -# Context 'First Infra Tests' { -# It 'should pass the first infra test' { -# # test logic -# } #it -# } -# } diff --git a/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 b/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 new file mode 100644 index 0000000..10c87aa --- /dev/null +++ b/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 @@ -0,0 +1,118 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +#------------------------------------------------------------------------- +#if the module is already in memory, remove it +Get-Module $ModuleName | Remove-Module -Force +$PathToManifest = [System.IO.Path]::Combine('..', '..', 'Artifacts', "$ModuleName.psd1") +#------------------------------------------------------------------------- +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- +Describe 'Infrastructure Tests' -Tag Infrastructure { + Context 'Google Maps Function Tests' { + + Context 'Find-GMapPlace' { + It 'should return the expected results' { + $findGMapPlaceSplat = @{ + Query = '+18306252807' + PointLatitude = '29.7049806' + PointLongitude = '-98.068343' + Contact = $true + Atmosphere = $true + Language = 'en' + } + $eval = Find-GMapPlace @findGMapPlaceSplat + $eval.place_id | Should -BeExactly 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + $eval.name | Should -BeExactly "Krause's Cafe" + $eval.Open | Should -Not -BeNullOrEmpty + $eval.rating | Should -Not -BeNullOrEmpty + Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) + } #it + } #context_Find-GMapPlace + + Context 'Get-GMapPlaceDetail' { + It 'should return the expected results' { + $getGMapPlaceDetailsSplat = @{ + PlaceID = 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + Contact = $true + Atmosphere = $true + Language = 'en' + } + $eval = Get-GMapPlaceDetail @getGMapPlaceDetailsSplat + $eval.place_id | Should -BeExactly 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + $eval.name | Should -BeExactly "Krause's Cafe" + $eval.website | Should -BeExactly 'https://www.krausescafe.com/' + $eval.Phone | Should -BeExactly '(830) 625-2807' + $eval.Open | Should -Not -BeNullOrEmpty + $eval.OpenHours | Should -Not -BeNullOrEmpty + $eval.GoogleMapsURL | Should -Not -BeNullOrEmpty + $eval.rating | Should -Not -BeNullOrEmpty + $eval.user_ratings_total | Should -Not -BeNullOrEmpty + $eval.price_level | Should -Not -BeNullOrEmpty + $eval.Latitude | Should -Not -BeNullOrEmpty + $eval.Longitude | Should -Not -BeNullOrEmpty + Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) + } #it + } #context_Get-GMapPlaceDetails + + Context 'Invoke-GMapGeoCode' { + It 'should return the expected results for lat long lookup' { + $eval = Invoke-GMapGeoCode -Address '148 S Castell Ave, New Braunfels, TX 78130, USA' + $eval.place_id.Count | Should -BeGreaterOrEqual 1 + Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) + } #it + It 'should return the expected results for reverse geocoding' { + $eval = Invoke-GMapGeoCode -Latitude '29.7012853' -Longitude '-98.1250235' + $eval.place_id.Count | Should -BeGreaterThan 1 + Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) + } #it + It 'should return expected results for place lookup' { + $eval = Invoke-GMapGeoCode -PlaceID 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + $eval.place_id | Should -BeExactly 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + $eval.City | Should -BeExactly 'New Braunfels' + $eval.Latitude | Should -Not -BeNullOrEmpty + $eval.Longitude | Should -Not -BeNullOrEmpty + Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) + } #it + } #context_Invoke-GMapGeoCode + + Context 'Search-GMapNearbyPlace' { + It 'should return the expected results' { + $searchGMapNearbyPlaceSplat = @{ + Latitude = '29.7049806' + Longitude = '-98.068343' + Radius = 5000 + RankByProminence = $true + Keyword = 'pasta' + Type = 'restaurant' + Language = 'en' + MaxPrice = 4 + MinPrice = 2 + AllSearchResults = $true + } + $eval = Search-GMapNearbyPlace @searchGMapNearbyPlaceSplat + $eval.place_id.Count | Should -BeGreaterOrEqual 20 + Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) + } #it + } #context_Search-GMapNearbyPlace + + Context 'Search-GMapText' { + It 'should return the expected results' { + $searchGMapTextSplat = @{ + Query = 'Coco' + Latitude = '26.1202' + Longitude = '127.7025' + RankByDistance = $true + Type = 'restaurant' + Language = 'en' + MinPrice = 1 + MaxPrice = 2 + AllSearchResults = $true + } + $eval = Search-GMapText @searchGMapTextSplat + $eval.place_id.Count | Should -BeGreaterOrEqual 20 + } #it + } #context_Search-GMapText + } #context_GoogleMaps +} #describe_infra_tests diff --git a/src/Tests/Unit/Private/Format-GMapGeoCode.Tests.ps1 b/src/Tests/Unit/Private/Format-GMapGeoCode.Tests.ps1 new file mode 100644 index 0000000..9377d0e --- /dev/null +++ b/src/Tests/Unit/Private/Format-GMapGeoCode.Tests.ps1 @@ -0,0 +1,47 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +$PathToTestObjects = [System.IO.Path]::Combine('..', 'TestObjects.psm1') +Import-Module $PathToTestObjects -DisableNameChecking -Global -Force +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + #------------------------------------------------------------------------- + $WarningPreference = "SilentlyContinue" + #------------------------------------------------------------------------- + Describe 'Format-GMapGeoCode' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + } #beforeAll + # Context 'Error' { + # } #context_Error + Context 'Success' { + + # BeforeEach { + # } #beforeEach + + It 'should return the expected results' { + $eval = ($geoAddress.results | Format-GMapGeoCode) + $eval.place_id | Should -BeExactly 'ChIJK34phme9XIYRqstHW_gHr2w' + $eval.formatted_address | Should -BeExactly '148 S Castell Ave, New Braunfels, TX 78130, USA' + $eval.StreetNumber | Should -BeExactly '148' + $eval.Street | Should -BeExactly 'South Castell Avenue' + $eval.City | Should -BeExactly 'New Braunfels' + $eval.Country | Should -BeExactly 'United States' + $eval.PostalCode | Should -BeExactly '78130' + $eval.Latitude | Should -BeExactly '29.7012853' + $eval.Longitude | Should -BeExactly '-98.1250235' + } #it + + } #context_Success + } #describe_Format-GMapGeoCode +} #inModule diff --git a/src/Tests/Unit/Private/Format-GMapNearbyPlace.Tests.ps1 b/src/Tests/Unit/Private/Format-GMapNearbyPlace.Tests.ps1 new file mode 100644 index 0000000..2e7d9c0 --- /dev/null +++ b/src/Tests/Unit/Private/Format-GMapNearbyPlace.Tests.ps1 @@ -0,0 +1,47 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +$PathToTestObjects = [System.IO.Path]::Combine('..', 'TestObjects.psm1') +Import-Module $PathToTestObjects -DisableNameChecking -Global -Force +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + #------------------------------------------------------------------------- + $WarningPreference = "SilentlyContinue" + #------------------------------------------------------------------------- + Describe 'Format-GMapNearbyPlace' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + } #beforeAll + # Context 'Error' { + # } #context_Error + Context 'Success' { + + # BeforeEach { + # } #beforeEach + + It 'should return the expected results' { + $eval = ($nearby.results[0] | Format-GMapNearbyPlace) + $eval.place_id | Should -BeExactly 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + $eval.name | Should -BeExactly 'Krause''s Cafe' + $eval.Address | Should -BeExactly '148 South Castell Avenue, New Braunfels' + $eval.Latitude | Should -BeExactly '29.7013856' + $eval.Longitude | Should -BeExactly '-98.1249258' + $eval.rating | Should -BeExactly '4.3' + $eval.user_ratings_total | Should -BeExactly '3675' + $eval.price_level | Should -BeExactly '2' + $eval.Open | Should -BeExactly 'False' + } #it + + } #context_Success + } #describe_Format-GMapNearbyPlace +} #inModule diff --git a/src/Tests/Unit/Private/Format-GMapPlace.Tests.ps1 b/src/Tests/Unit/Private/Format-GMapPlace.Tests.ps1 new file mode 100644 index 0000000..aa982b2 --- /dev/null +++ b/src/Tests/Unit/Private/Format-GMapPlace.Tests.ps1 @@ -0,0 +1,47 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +$PathToTestObjects = [System.IO.Path]::Combine('..', 'TestObjects.psm1') +Import-Module $PathToTestObjects -DisableNameChecking -Global -Force +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + #------------------------------------------------------------------------- + $WarningPreference = "SilentlyContinue" + #------------------------------------------------------------------------- + Describe 'Format-GMapPlace' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + } #beforeAll + # Context 'Error' { + # } #context_Error + Context 'Success' { + + # BeforeEach { + # } #beforeEach + + It 'should return the expected results' { + $eval = ($findplaceAll.candidates | Format-GMapPlace) + $eval.place_id | Should -BeExactly 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + $eval.name | Should -BeExactly 'Krause''s Cafe' + $eval.Address | Should -BeExactly '148 S Castell Ave, New Braunfels, TX 78130, United States' + $eval.Latitude | Should -BeExactly '29.7013856' + $eval.Longitude | Should -BeExactly '-98.1249258' + $eval.rating | Should -BeExactly '4.3' + $eval.user_ratings_total | Should -BeExactly '3675' + $eval.price_level | Should -BeExactly '2' + $eval.Open | Should -BeExactly 'False' + } #it + + } #context_Success + } #describe_Format-GMapPlace +} #inModule diff --git a/src/Tests/Unit/Private/Format-GMapPlaceDetail.Tests.ps1 b/src/Tests/Unit/Private/Format-GMapPlaceDetail.Tests.ps1 new file mode 100644 index 0000000..d8f835a --- /dev/null +++ b/src/Tests/Unit/Private/Format-GMapPlaceDetail.Tests.ps1 @@ -0,0 +1,50 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +$PathToTestObjects = [System.IO.Path]::Combine('..', 'TestObjects.psm1') +Import-Module $PathToTestObjects -DisableNameChecking -Global -Force +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + #------------------------------------------------------------------------- + $WarningPreference = "SilentlyContinue" + #------------------------------------------------------------------------- + Describe 'Format-GMapPlaceDetail' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + } #beforeAll + # Context 'Error' { + # } #context_Error + Context 'Success' { + + # BeforeEach { + # } #beforeEach + + It 'should return the expected results' { + $eval = ($placeDetails.result | Format-GMapPlaceDetail) + $eval.place_id | Should -BeExactly 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + $eval.name | Should -BeExactly 'Krause''s Cafe' + $eval.website | Should -BeExactly 'https://www.krausescafe.com/' + $eval.Address | Should -BeExactly '148 S Castell Ave, New Braunfels, TX 78130, United States' + $eval.Phone | Should -BeExactly '(830) 625-2807' + $eval.Open | Should -BeExactly 'False' + $eval.GoogleMapsURL | Should -BeExactly 'https://maps.google.com/?cid=6720415583914850961' + $eval.rating | Should -BeExactly '4.3' + $eval.user_ratings_total | Should -BeExactly '3697' + $eval.price_level | Should -BeExactly '2' + $eval.Latitude | Should -BeExactly '29.7013856' + $eval.Longitude | Should -BeExactly '-98.1249258' + } #it + + } #context_Success + } #describe_Format-GMapPlaceDetail +} #inModule diff --git a/src/Tests/Unit/Private/Format-GMapPlaceText.Tests.ps1 b/src/Tests/Unit/Private/Format-GMapPlaceText.Tests.ps1 new file mode 100644 index 0000000..5bf00d8 --- /dev/null +++ b/src/Tests/Unit/Private/Format-GMapPlaceText.Tests.ps1 @@ -0,0 +1,47 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +$PathToTestObjects = [System.IO.Path]::Combine('..', 'TestObjects.psm1') +Import-Module $PathToTestObjects -DisableNameChecking -Global -Force +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + #------------------------------------------------------------------------- + $WarningPreference = "SilentlyContinue" + #------------------------------------------------------------------------- + Describe 'Format-GMapPlaceText' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + } #beforeAll + # Context 'Error' { + # } #context_Error + Context 'Success' { + + # BeforeEach { + # } #beforeEach + + It 'should return the expected results' { + $eval = ($textSearch.results[0] | Format-GMapPlaceText ) + $eval.place_id | Should -BeExactly 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + $eval.name | Should -BeExactly 'Krause''s Cafe' + $eval.Address | Should -BeExactly '148 S Castell Ave, New Braunfels, TX 78130, United States' + $eval.Latitude | Should -BeExactly '29.7013856' + $eval.Longitude | Should -BeExactly '-98.1249258' + $eval.rating | Should -BeExactly '4.3' + $eval.user_ratings_total | Should -BeExactly '3675' + $eval.price_level | Should -BeExactly '2' + $eval.Open | Should -BeExactly 'False' + } #it + + } #context_Success + } #describe_Format-GMapPlaceFull +} #inModule diff --git a/src/Tests/Unit/Private/Get-Day.Tests.ps1 b/src/Tests/Unit/Private/Get-Day.Tests.ps1 deleted file mode 100644 index 284fed1..0000000 --- a/src/Tests/Unit/Private/Get-Day.Tests.ps1 +++ /dev/null @@ -1,63 +0,0 @@ -#------------------------------------------------------------------------- -Set-Location -Path $PSScriptRoot -#------------------------------------------------------------------------- -$ModuleName = 'pwshPlaces' -$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") -#------------------------------------------------------------------------- -if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { - #if the module is already in memory, remove it - Remove-Module -Name $ModuleName -Force -} -Import-Module $PathToManifest -Force -#------------------------------------------------------------------------- - -InModuleScope 'pwshPlaces' { - #------------------------------------------------------------------------- - $WarningPreference = "SilentlyContinue" - #------------------------------------------------------------------------- - Describe 'Get-Day Private Function Tests' -Tag Unit { - BeforeAll { - $WarningPreference = 'SilentlyContinue' - $ErrorActionPreference = 'SilentlyContinue' - } #beforeAll - Context 'Error' { - - It 'should return unknown if an error is encountered getting the date' { - Mock -CommandName Get-Date -MockWith { - throw 'Fake Error' - } #endMock - Get-Day | Should -BeExactly 'Unknown' - } #it - - } #context_Error - Context 'Success' { - - BeforeEach { - Mock -CommandName Get-Date -MockWith { - [PSCustomObject]@{ - DisplayHint = 'DateTime' - DateTime = 'Thursday, June 11, 2021 21:08:41' - Date = '06/11/21 00:00:00' - Day = '10' - DayOfWeek = 'Friday' - DayOfYear = '162' - Hour = '21' - Kind = 'Local' - Millisecond = '989' - Minute = '8' - Month = '6' - Second = '41' - Ticks = '637589561219896868' - TimeOfDay = '21:08:41.9896868' - Year = '2021' - } - } #endMock - } #beforeEach - - It 'should return the expected results' { - Get-Day | Should -BeExactly 'Friday' - } #it - - } #context_Success - } #describe_Get-HellowWorld -} #inModule diff --git a/src/Tests/Unit/Public/Find-GMapPlace.Tests.ps1 b/src/Tests/Unit/Public/Find-GMapPlace.Tests.ps1 new file mode 100644 index 0000000..42b0feb --- /dev/null +++ b/src/Tests/Unit/Public/Find-GMapPlace.Tests.ps1 @@ -0,0 +1,91 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +$PathToTestObjects = [System.IO.Path]::Combine('..', 'TestObjects.psm1') +Import-Module $PathToTestObjects -DisableNameChecking -Global -Force +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + Describe 'Find-GMapPlace' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + } #beforeAll + BeforeEach { + Mock -CommandName Invoke-RestMethod -MockWith { + $findplaceBasic + } #endMock + } + Context 'Error' { + + It 'should throw if an error is encountered with invoking the API' { + Mock -CommandName Invoke-RestMethod -MockWith { + throw 'Fake Error' + } #endMock + { Find-GMapPlace -Query 'cafe' } | Should -Throw + } #it + + It 'should warn the user if the API does not return an OK status' { + Mock Write-Warning { } + Mock -CommandName Invoke-RestMethod -MockWith { + [PSCustomObject]@{ + results = '' + status = 'ZERO_RESULTS' + } + } #endMock + Find-GMapPlace -Query 'cafe' + Assert-MockCalled -CommandName Write-Warning -Times 1 + Assert-VerifiableMock + } #it + + } #context_Error + Context 'Success' { + + It 'should return expected results if no issues are encountered' { + $eval = Find-GMapPlace -Query 'cafe' -PointLatitude '29.7049806' -PointLongitude '-98.068343' + $eval.Count | Should -BeExactly 1 + $eval[0].Latitude | Should -BeExactly '29.7013856' + $eval[0].Longitude | Should -BeExactly '-98.1249258' + } #it + + # jake- put all the things here + It 'should call the API with the expected parameters when all options are provided' { + Mock -CommandName Invoke-RestMethod { + $Uri | Should -BeLike 'https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input=*' + $Uri | Should -BeLike '*phonenumber*' + $Uri | Should -BeLike '*locationbias=point*' + $Uri | Should -BeLike '*language=en*' + $Uri | Should -BeLike '*opening_hours*' + $Uri | Should -BeLike '*price_level*' + } -Verifiable + Find-GMapPlace -Query '+18306252807' -PointLatitude '29.7049806' -PointLongitude '-98.068343' -Contact -Atmosphere -Language en + Assert-VerifiableMock + } #it + + It 'should call the API with the expected parameters with circle' { + Mock -CommandName Invoke-RestMethod { + $Uri | Should -BeLike 'https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input=*locationbias=circle*' + } -Verifiable + Find-GMapPlace -Query 'cafe' -CircleLatitude '29.7049806' -CircleLongitude '-98.068343' -CircleRadius '8046' + Assert-VerifiableMock + } #it + + It 'should call the API with the expected parameters with rectangle' { + Mock -CommandName Invoke-RestMethod { + $Uri | Should -BeLike 'https://maps.googleapis.com/maps/api/place/findplacefromtext/json?input=*locationbias=rectangle*' + } -Verifiable + Find-GMapPlace -Query 'cafe' -SouthLatitude '39.8592387' -WestLongitude '-75.295486' -NorthLatitude '40.0381942' -EastLongitude '-75.0064087' + Assert-VerifiableMock + } #it + + } #context_Success + } #describe_Find-GMapPlace +} #inModule diff --git a/src/Tests/Unit/Public/Get-GMapPlaceDetail.Tests.ps1 b/src/Tests/Unit/Public/Get-GMapPlaceDetail.Tests.ps1 new file mode 100644 index 0000000..df373a3 --- /dev/null +++ b/src/Tests/Unit/Public/Get-GMapPlaceDetail.Tests.ps1 @@ -0,0 +1,85 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +$PathToTestObjects = [System.IO.Path]::Combine('..', 'TestObjects.psm1') +Import-Module $PathToTestObjects -DisableNameChecking -Global -Force +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + Describe 'Get-GMapPlaceDetail' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + } #beforeAll + BeforeEach { + Mock -CommandName Invoke-RestMethod -MockWith { + $placeDetails + } #endMock + } + Context 'Error' { + + It 'should throw if an error is encountered with invoking the API' { + Mock -CommandName Invoke-RestMethod -MockWith { + throw 'Fake Error' + } #endMock + { Get-GMapPlaceDetail -PlaceID 'ChIJE43gTHK9XIYRleSxiXqF6GU' } | Should -Throw + } #it + + It 'should warn the user if the API does not return an OK status' { + Mock Write-Warning { } + Mock -CommandName Invoke-RestMethod -MockWith { + [PSCustomObject]@{ + results = '' + status = 'ZERO_RESULTS' + } + } #endMock + Get-GMapPlaceDetail -PlaceID 'ChIJE43gTHK9XIYRleSxiXqF6GU' -Contact + Assert-MockCalled -CommandName Write-Warning -Times 1 + Assert-VerifiableMock + } #it + + } #context_Error + Context 'Success' { + + It 'should return expected results if no issues are encountered' { + $eval = Get-GMapPlaceDetail -PlaceID 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + $eval.Count | Should -BeExactly 1 + $eval.place_id | Should -BeExactly 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + $eval.name | Should -BeExactly 'Krause''s Cafe' + $eval.website | Should -BeExactly 'https://www.krausescafe.com/' + $eval.Address | Should -BeExactly '148 S Castell Ave, New Braunfels, TX 78130, United States' + $eval.Phone | Should -BeExactly '(830) 625-2807' + $eval.Open | Should -BeExactly 'False' + $eval.GoogleMapsURL | Should -BeExactly 'https://maps.google.com/?cid=6720415583914850961' + $eval.rating | Should -BeExactly '4.3' + $eval.user_ratings_total | Should -BeExactly '3697' + $eval.price_level | Should -BeExactly '2' + $eval.Latitude | Should -BeExactly '29.7013856' + $eval.Longitude | Should -BeExactly '-98.1249258' + } #it + + It 'should call the API with the expected parameters when all options are provided' { + Mock -CommandName Invoke-RestMethod { + $Uri | Should -BeLike 'https://maps.googleapis.com/maps/api/place/details/json?place_id=*' + $Uri | Should -BeLike '*language=*' + $Uri | Should -BeLike '*fields=*' + $Uri | Should -BeLike '*address_component*' + $Uri | Should -BeLike '*formatted_phone_number*' + $Uri | Should -BeLike '*price_level*' + $Uri | Should -BeLike '*region=*' + } -Verifiable + Get-GMapPlaceDetail -PlaceID 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' -Contact -Atmosphere -Language en -RegionBias us + Assert-VerifiableMock + } #it + + } #context_Success + } #describe_Get-GMapPlaceDetails +} #inModule diff --git a/src/Tests/Unit/Public/Get-HelloWorld.Tests.ps1 b/src/Tests/Unit/Public/Get-HelloWorld.Tests.ps1 deleted file mode 100644 index 5830905..0000000 --- a/src/Tests/Unit/Public/Get-HelloWorld.Tests.ps1 +++ /dev/null @@ -1,41 +0,0 @@ -#------------------------------------------------------------------------- -Set-Location -Path $PSScriptRoot -#------------------------------------------------------------------------- -$ModuleName = 'pwshPlaces' -$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") -#------------------------------------------------------------------------- -if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { - #if the module is already in memory, remove it - Remove-Module -Name $ModuleName -Force -} -Import-Module $PathToManifest -Force -#------------------------------------------------------------------------- - -InModuleScope 'pwshPlaces' { - Describe 'Get-HellowWorld Public Function Tests' -Tag Unit { - BeforeAll { - $WarningPreference = 'SilentlyContinue' - $ErrorActionPreference = 'SilentlyContinue' - } #beforeAll - Context 'Error' { - - # It 'should ...' { - - # } #it - - } #context_Error - Context 'Success' { - - BeforeEach { - Mock -CommandName Get-Day -MockWith { - 'Friday' - } #endMock - } #beforeEach - - It 'should return the expected results' { - Get-HelloWorld | Should -BeExactly 'Hello, happy Friday World!' - } #it - - } #context_Success - } #describe_Get-HellowWorld -} #inModule diff --git a/src/Tests/Unit/Public/Invoke-GMapGeoCode.Tests.ps1 b/src/Tests/Unit/Public/Invoke-GMapGeoCode.Tests.ps1 new file mode 100644 index 0000000..74d247b --- /dev/null +++ b/src/Tests/Unit/Public/Invoke-GMapGeoCode.Tests.ps1 @@ -0,0 +1,88 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +$PathToTestObjects = [System.IO.Path]::Combine('..', 'TestObjects.psm1') +Import-Module $PathToTestObjects -DisableNameChecking -Global -Force +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + Describe 'Invoke-GMapGeoCode' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + } #beforeAll + BeforeEach { + Mock -CommandName Invoke-RestMethod -MockWith { + $geoAddress + } #endMock + } + Context 'Error' { + + It 'should throw if an error is encountered with invoking the API' { + Mock -CommandName Invoke-RestMethod -MockWith { + throw 'Fake Error' + } #endMock + { Invoke-GMapGeoCode -Address '24-593 Federation Drive, San Francisco, CA' } | Should -Throw + } #it + + It 'should warn the user if the API does not return an OK status' { + Mock Write-Warning { } + Mock -CommandName Invoke-RestMethod -MockWith { + [PSCustomObject]@{ + results = '' + status = 'ZERO_RESULTS' + } + } #endMock + Invoke-GMapGeoCode -Address '24-593 Federation Drive, San Francisco, CA' + Assert-MockCalled -CommandName Write-Warning -Times 1 + Assert-VerifiableMock + } #it + + } #context_Error + Context 'Success' { + + It 'should return expected results if no issues are encountered' { + Mock -CommandName Invoke-RestMethod -MockWith { + $geoLatLong + } #endMock + $eval = Invoke-GMapGeoCode -Latitude '29.7012853' -Longitude '-98.1250235' -Language 'en' -RegionBias 'us' + $eval.Count | Should -BeExactly 2 + $eval[0].Latitude | Should -BeExactly '29.7012853' + $eval[0].Longitude | Should -BeExactly '-98.1250235' + } #it + + It 'should call the API with the expected parameters with address' { + Mock -CommandName Invoke-RestMethod { + $Uri | Should -BeLike 'https://maps.googleapis.com/maps/api/geocode/json?address=*' + } -Verifiable + Invoke-GMapGeoCode -Address '24-593 Federation Drive, San Francisco, CA' + Assert-VerifiableMock + } #it + + It 'should call the API with the expected parameters with location' { + Mock -CommandName Invoke-RestMethod { + $Uri | Should -BeLike 'https://maps.googleapis.com/maps/api/geocode/json?latlng=*' + } -Verifiable + Invoke-GMapGeoCode -Latitude '29.7012853' -Longitude '-98.1250235' + Assert-VerifiableMock + } #it + + It 'should call the API with the expected parameters with place ID' { + Mock -CommandName Invoke-RestMethod { + $Uri | Should -BeLike 'https://maps.googleapis.com/maps/api/geocode/json?place_id=*' + } -Verifiable + Invoke-GMapGeoCode -PlaceID 'ChIJK34phme9XIYRqstHW_gHr2w' + Assert-VerifiableMock + } #it + + } #context_Success + } #describe_Invoke-GMapGeoCode +} #inModule diff --git a/src/Tests/Unit/Public/Search-GMapNearbyPlace.Tests.ps1 b/src/Tests/Unit/Public/Search-GMapNearbyPlace.Tests.ps1 new file mode 100644 index 0000000..5beeb11 --- /dev/null +++ b/src/Tests/Unit/Public/Search-GMapNearbyPlace.Tests.ps1 @@ -0,0 +1,150 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +$PathToTestObjects = [System.IO.Path]::Combine('..', 'TestObjects.psm1') +Import-Module $PathToTestObjects -DisableNameChecking -Global -Force +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + Describe 'Search-GMapNearbyPlace' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + function Start-Sleep { + } + } #beforeAll + BeforeEach { + Mock -CommandName Invoke-RestMethod -MockWith { + $nearby + } #endMock + } + Context 'Error' { + + It 'should throw if an error is encountered with invoking the API' { + Mock -CommandName Invoke-RestMethod -MockWith { + throw 'Fake Error' + } #endMock + { Search-GMapNearbyPlace -Latitude '29.7049806' -Longitude '-98.068343' -Radius 5000 } | Should -Throw + } #it + + It 'should warn the user if the API does not return an OK status' { + Mock Write-Warning { } + Mock -CommandName Invoke-RestMethod -MockWith { + [PSCustomObject]@{ + results = '' + status = 'ZERO_RESULTS' + } + } #endMock + Search-GMapNearbyPlace -Latitude '29.7013856' -Longitude '-98.1249258' -Radius 1000 -Type restaurant -MinPrice 1 -MaxPrice 3 + Assert-MockCalled -CommandName Write-Warning -Times 1 + Assert-VerifiableMock + } #it + + It 'should throw if subsequent pagetoken calls fail' { + $script:mockCalled = 0 + $mockInvoke = { + $script:mockCalled++ + if ($script:mockCalled -eq 1) { + return $nearby + } + elseif ($script:mockCalled -eq 2) { + throw 'Fake Error' + } + elseif ($script:mockCalled -eq 3) { + $mockObj = [PSCustomObject]@{ + html_attributions = '' + next_page_token = 'toooooken' + status = 'OK' + + } + return $mockObj + } + else { + $mockObj = [PSCustomObject]@{ + html_attributions = '' + status = 'OK' + + } + return $mockObj + } + } #mock_invoke + Mock -CommandName Invoke-RestMethod -MockWith $mockInvoke + { Search-GMapNearbyPlace -Latitude '29.7013856' -Longitude '-98.1249258' -Radius 1000 -Type restaurant -MinPrice 1 -MaxPrice 3 -AllSearchResults } | Should -Throw + } #it + + } #context_Error + Context 'Success' { + + It 'should return expected results if no issues are encountered' { + $eval = Search-GMapNearbyPlace -Latitude '29.7049806' -Longitude '-98.068343' -RankByDistance + $eval.Count | Should -BeExactly 2 + $eval[0].Latitude | Should -BeExactly '29.7013856' + $eval[0].Longitude | Should -BeExactly '-98.1249258' + } #it + + It 'should call the API with the expected parameters when all options are provided' { + Mock -CommandName Invoke-RestMethod { + $Uri | Should -BeLike 'https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=*' + $Uri | Should -BeLike '*radius=*' + $Uri | Should -BeLike '*keyword=*' + $Uri | Should -BeLike '*type=*' + $Uri | Should -BeLike '*language=en*' + $Uri | Should -BeLike '*openNow*' + $Uri | Should -BeLike '*rankby=prominence*' + $Uri | Should -BeLike '*maxprice=*' + $Uri | Should -BeLike '*minprice=*' + } -Verifiable + Search-GMapNearbyPlace -Latitude '29.7049806' -Longitude '-98.068343' -Radius 5000 -RankByProminence -Keyword 'pasta' -Type restaurant -Language en -OpenNow -MaxPrice 4 -MinPrice 2 + Assert-VerifiableMock + } #it + + It 'should run the expected number of times if AllResults is specified' { + $script:mockCalled = 0 + $mockInvoke = { + $script:mockCalled++ + if ($script:mockCalled -eq 1) { + return $nearby + } + elseif ($script:mockCalled -eq 2) { + $mockObj = [PSCustomObject]@{ + html_attributions = '' + next_page_token = 'toooooken' + status = 'OK' + } + return $mockObj + } + elseif ($script:mockCalled -eq 3) { + $mockObj = [PSCustomObject]@{ + html_attributions = '' + next_page_token = 'toooooken' + status = 'OK' + + } + return $mockObj + } + else { + $mockObj = [PSCustomObject]@{ + html_attributions = '' + status = 'OK' + + } + return $mockObj + } + } #mock_invoke + Mock -CommandName Invoke-RestMethod -MockWith $mockInvoke + Search-GMapNearbyPlace -Latitude '29.7013856' -Longitude '-98.1249258' -Radius 1000 -Type restaurant -MinPrice 1 -MaxPrice 3 -AllSearchResults + Assert-MockCalled -CommandName Invoke-RestMethod -Times 3 + Assert-VerifiableMock + } #it + + } #context_Success + } #describe_Search-GMapNearbyPlace +} #inModule diff --git a/src/Tests/Unit/Public/Search-GMapText.Tests.ps1 b/src/Tests/Unit/Public/Search-GMapText.Tests.ps1 new file mode 100644 index 0000000..1301138 --- /dev/null +++ b/src/Tests/Unit/Public/Search-GMapText.Tests.ps1 @@ -0,0 +1,150 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +$PathToTestObjects = [System.IO.Path]::Combine('..', 'TestObjects.psm1') +Import-Module $PathToTestObjects -DisableNameChecking -Global -Force +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + Describe 'Search-GMapText' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + function Start-Sleep { + } + } #beforeAll + BeforeEach { + Mock -CommandName Invoke-RestMethod -MockWith { + $nearby + } #endMock + } + Context 'Error' { + + It 'should throw if an error is encountered with invoking the API' { + Mock -CommandName Invoke-RestMethod -MockWith { + throw 'Fake Error' + } #endMock + { Search-GMapText -Query "Krause's Cafe" } | Should -Throw + } #it + + It 'should warn the user if the API does not return an OK status' { + Mock Write-Warning { } + Mock -CommandName Invoke-RestMethod -MockWith { + [PSCustomObject]@{ + results = '' + status = 'ZERO_RESULTS' + } + } #endMock + Search-GMapText -Query "Airport" -RegionBias es + Assert-MockCalled -CommandName Write-Warning -Times 1 + Assert-VerifiableMock + } #it + + It 'should throw if subsequent pagetoken calls fail' { + $script:mockCalled = 0 + $mockInvoke = { + $script:mockCalled++ + if ($script:mockCalled -eq 1) { + return $textSearch + } + elseif ($script:mockCalled -eq 2) { + throw 'Fake Error' + } + elseif ($script:mockCalled -eq 3) { + $mockObj = [PSCustomObject]@{ + html_attributions = '' + next_page_token = 'toooooken' + status = 'OK' + + } + return $mockObj + } + else { + $mockObj = [PSCustomObject]@{ + html_attributions = '' + status = 'OK' + + } + return $mockObj + } + } #mock_invoke + Mock -CommandName Invoke-RestMethod -MockWith $mockInvoke + { Search-GMapText -Query "Cupcakes" -Type bakery -AllSearchResults } | Should -Throw + } #it + + } #context_Error + Context 'Success' { + + It 'should return expected results if no issues are encountered' { + $eval = Search-GMapText -Query 'Coco' -Latitude '26.1202' -Longitude '127.7025' -RankByDistance -Type restaurant + $eval.Count | Should -BeExactly 2 + $eval[0].Latitude | Should -BeExactly '29.7013856' + $eval[0].Longitude | Should -BeExactly '-98.1249258' + } #it + + It 'should call the API with the expected parameters when all options are provided' { + Mock -CommandName Invoke-RestMethod { + $Uri | Should -BeLike 'https://maps.googleapis.com/maps/api/place/textsearch/json?query=*' + $Uri | Should -BeLike '*location=*' + $Uri | Should -BeLike '*radius=*' + $Uri | Should -BeLike '*type=*' + $Uri | Should -BeLike '*language=en*' + $Uri | Should -BeLike '*openNow*' + $Uri | Should -BeLike '*rankby=prominence*' + $Uri | Should -BeLike '*maxprice=*' + $Uri | Should -BeLike '*minprice=*' + } -Verifiable + Search-GMapText -Query 'Coco' -Latitude '26.1202' -Longitude '127.7025' -Radius 5 -RankByProminence -Type restaurant -Language en -OpenNow -MinPrice 1 -MaxPrice 2 -AllSearchResults + Assert-VerifiableMock + } #it + + It 'should run the expected number of times if AllResults is specified' { + $script:mockCalled = 0 + $mockInvoke = { + $script:mockCalled++ + if ($script:mockCalled -eq 1) { + return $textSearch + } + elseif ($script:mockCalled -eq 2) { + $mockObj = [PSCustomObject]@{ + html_attributions = '' + next_page_token = 'toooooken' + status = 'OK' + } + return $mockObj + } + elseif ($script:mockCalled -eq 3) { + $mockObj = [PSCustomObject]@{ + html_attributions = '' + next_page_token = 'toooooken' + status = 'OK' + + } + return $mockObj + } + else { + $mockObj = [PSCustomObject]@{ + html_attributions = '' + status = 'OK' + + } + return $mockObj + } + } #mock_invoke + Mock -CommandName Invoke-RestMethod -MockWith $mockInvoke + Search-GMapText -Query 'Coco' -Latitude '26.1202' -Longitude '127.7025' -Radius 5 -RankByProminence -Type restaurant -Language en -OpenNow -MinPrice 1 -MaxPrice 2 -AllSearchResults + Assert-MockCalled -CommandName Invoke-RestMethod -Times 3 + Assert-VerifiableMock + } #it + + } #context_Success + } #describe_Search-GMapText +} #inModule diff --git a/src/Tests/Unit/TestObjects.psm1 b/src/Tests/Unit/TestObjects.psm1 new file mode 100644 index 0000000..858cbb1 --- /dev/null +++ b/src/Tests/Unit/TestObjects.psm1 @@ -0,0 +1,973 @@ +#region findPlace + +$findplaceBasic = [PSCustomObject]@{ + candidates = [PSCustomObject]@{ + business_status = 'OPERATIONAL' + formatted_address = '148 S Castell Ave, New Braunfels, TX 78130, United States' + geometry = [PSCustomObject]@{ + location = [PSCustomObject]@{ + lat = '29.7013856' + lng = '-98.1249258' + } + viewport = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.7028062298927' + lng = '-98.1235759201073' + } + southwest = [PSCustomObject]@{ + lat = '29.7001065701073' + lng = '-98.1262755798927' + } + } + } + icon = 'https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png' + icon_background_color = '#FF9E67' + icon_mask_base_uri = 'https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet' + name = 'Krause''s Cafe' + place_id = 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + plus_code = [PSCustomObject]@{ + compound_code = 'PV2G+H2 New Braunfels, Texas' + global_code = '76X3PV2G+H2' + } + types = @( + 'bar' + 'restaurant' + 'food' + 'point_of_interest' + 'establishment' + ) + } + status = 'OK' +} + +$findplaceAtmosphere = [PSCustomObject]@{ + candidates = [PSCustomObject]@{ + business_status = 'OPERATIONAL' + formatted_address = '148 S Castell Ave, New Braunfels, TX 78130, United States' + geometry = [PSCustomObject]@{ + location = [PSCustomObject]@{ + lat = '29.7013856' + lng = '-98.1249258' + } + viewport = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.7028062298927' + lng = '-98.1235759201073' + } + southwest = [PSCustomObject]@{ + lat = '29.7001065701073' + lng = '-98.1262755798927' + } + } + } + icon = 'https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png' + icon_background_color = '#FF9E67' + icon_mask_base_uri = 'https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet' + name = 'Krause''s Cafe' + place_id = 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + plus_code = [PSCustomObject]@{ + compound_code = 'PV2G+H2 New Braunfels, Texas' + global_code = '76X3PV2G+H2' + } + price_level = '2' + rating = '4.3' + types = @( + 'bar' + 'restaurant' + 'food' + 'point_of_interest' + 'establishment' + ) + user_ratings_total = '3675' + } + status = 'OK' +} + +$findplaceContact = [PSCustomObject]@{ + candidates = [PSCustomObject]@{ + business_status = 'OPERATIONAL' + formatted_address = '148 S Castell Ave, New Braunfels, TX 78130, United States' + geometry = [PSCustomObject]@{ + location = [PSCustomObject]@{ + lat = '29.7013856' + lng = '-98.1249258' + } + viewport = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.7028062298927' + lng = '-98.1235759201073' + } + southwest = [PSCustomObject]@{ + lat = '29.7001065701073' + lng = '-98.1262755798927' + } + } + } + icon = 'https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png' + icon_background_color = '#FF9E67' + icon_mask_base_uri = 'https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet' + name = 'Krause''s Cafe' + opening_hours = [PSCustomObject]@{ + open_now = 'False' + } + place_id = 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + plus_code = [PSCustomObject]@{ + compound_code = 'PV2G+H2 New Braunfels, Texas' + global_code = '76X3PV2G+H2' + } + types = @( + 'bar' + 'restaurant' + 'food' + 'point_of_interest' + 'establishment' + ) + } + status = 'OK' +} + +$findplaceAll = [PSCustomObject]@{ + candidates = [PSCustomObject]@{ + business_status = 'OPERATIONAL' + formatted_address = '148 S Castell Ave, New Braunfels, TX 78130, United States' + geometry = [PSCustomObject]@{ + location = [PSCustomObject]@{ + lat = '29.7013856' + lng = '-98.1249258' + } + viewport = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.7028062298927' + lng = '-98.1235759201073' + } + southwest = [PSCustomObject]@{ + lat = '29.7001065701073' + lng = '-98.1262755798927' + } + } + } + icon = 'https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png' + icon_background_color = '#FF9E67' + icon_mask_base_uri = 'https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet' + name = 'Krause''s Cafe' + opening_hours = [PSCustomObject]@{ + open_now = 'False' + } + place_id = 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + plus_code = [PSCustomObject]@{ + compound_code = 'PV2G+H2 New Braunfels, Texas' + global_code = '76X3PV2G+H2' + } + price_level = '2' + rating = '4.3' + types = @( + 'bar' + 'restaurant' + 'food' + 'point_of_interest' + 'establishment' + ) + user_ratings_total = '3675' + } + status = 'OK' +} + +#endRegion + +#region GeoCode + +$geoAddress = [PSCustomObject]@{ + results = [PSCustomObject]@{ + address_components = @( + [PSCustomObject]@{ + long_name = '148' + short_name = '148' + types = @( + 'street_number' + ) + } + [PSCustomObject]@{ + long_name = 'South Castell Avenue' + short_name = 'S Castell Ave' + types = @( + 'route' + ) + } + [PSCustomObject]@{ + long_name = '' + short_name = '' + types = @( + + ) + } + [PSCustomObject]@{ + long_name = 'New Braunfels' + short_name = 'New Braunfels' + types = @( + 'locality' + 'political' + ) + } + [PSCustomObject]@{ + long_name = 'Comal County' + short_name = 'Comal County' + types = @( + 'administrative_area_level_2' + 'political' + ) + } + [PSCustomObject]@{ + long_name = 'Texas' + short_name = 'TX' + types = @( + 'administrative_area_level_1' + 'political' + ) + } + [PSCustomObject]@{ + long_name = 'United States' + short_name = 'US' + types = @( + 'country' + 'political' + ) + } + [PSCustomObject]@{ + long_name = '78130' + short_name = '78130' + types = @( + 'postal_code' + ) + } + [PSCustomObject]@{ + long_name = '5102' + short_name = '5102' + types = @( + 'postal_code_suffix' + ) + } + ) + formatted_address = '148 S Castell Ave, New Braunfels, TX 78130, USA' + geometry = [PSCustomObject]@{ + bounds = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.7014997' + lng = '-98.1247988' + } + southwest = [PSCustomObject]@{ + lat = '29.7010964' + lng = '-98.1252494' + } + } + location = [PSCustomObject]@{ + lat = '29.7012853' + lng = '-98.1250235' + } + location_type = 'ROOFTOP' + viewport = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.7026470302915' + lng = '-98.1236751197085' + } + southwest = [PSCustomObject]@{ + lat = '29.6999490697085' + lng = '-98.1263730802915' + } + } + } + place_id = 'ChIJK34phme9XIYRqstHW_gHr2w' + types = @( + 'premise' + ) + } + status = 'OK' +} + +$geoLatLong = [PSCustomObject]@{ + plus_code = [PSCustomObject]@{ + compound_code = 'PV2F+GX New Braunfels, TX, USA' + global_code = '76X3PV2F+GX' + } + results = @( + [PSCustomObject]@{ + address_components = @( + [PSCustomObject]@{ + long_name = 'PV2F+GX' + short_name = 'PV2F+GX' + types = @( + 'plus_code' + ) + } + [PSCustomObject]@{ + long_name = 'New Braunfels' + short_name = 'New Braunfels' + types = @( + 'locality' + 'political' + ) + } + [PSCustomObject]@{ + long_name = 'Comal County' + short_name = 'Comal County' + types = @( + 'administrative_area_level_2' + 'political' + ) + } + [PSCustomObject]@{ + long_name = 'Texas' + short_name = 'TX' + types = @( + 'administrative_area_level_1' + 'political' + ) + } + [PSCustomObject]@{ + long_name = 'United States' + short_name = 'US' + types = @( + 'country' + 'political' + ) + } + ) + formatted_address = 'PV2F+GX New Braunfels, TX, USA' + geometry = [PSCustomObject]@{ + bounds = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.701375' + lng = '-98.125' + } + southwest = [PSCustomObject]@{ + lat = '29.70125' + lng = '-98.125125' + } + } + location = [PSCustomObject]@{ + lat = '29.7012853' + lng = '-98.1250235' + } + location_type = 'ROOFTOP' + viewport = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.7026470302915' + lng = '-98.1236751197085' + } + southwest = [PSCustomObject]@{ + lat = '29.6999490697085' + lng = '-98.1263730802915' + } + } + } + place_id = 'GhIJYqr0boezPUAR0O6QYgCIWMA' + types = @( + 'plus_code' + ) + } + [PSCustomObject]@{ + address_components = @( + [PSCustomObject]@{ + long_name = '148' + short_name = '148' + types = @( + 'street_number' + ) + } + [PSCustomObject]@{ + long_name = 'South Castell Avenue' + short_name = 'S Castell Ave' + types = @( + 'route' + ) + } + [PSCustomObject]@{ + long_name = '' + short_name = '' + types = @( + + ) + } + [PSCustomObject]@{ + long_name = 'New Braunfels' + short_name = 'New Braunfels' + types = @( + 'locality' + 'political' + ) + } + [PSCustomObject]@{ + long_name = 'Comal County' + short_name = 'Comal County' + types = @( + 'administrative_area_level_2' + 'political' + ) + } + [PSCustomObject]@{ + long_name = 'Texas' + short_name = 'TX' + types = @( + 'administrative_area_level_1' + 'political' + ) + } + [PSCustomObject]@{ + long_name = 'United States' + short_name = 'US' + types = @( + 'country' + 'political' + ) + } + [PSCustomObject]@{ + long_name = '78130' + short_name = '78130' + types = @( + 'postal_code' + ) + } + [PSCustomObject]@{ + long_name = '5102' + short_name = '5102' + types = @( + 'postal_code_suffix' + ) + } + ) + formatted_address = '148 S Castell Ave, New Braunfels, TX 78130, USA' + geometry = [PSCustomObject]@{ + bounds = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.7014997' + lng = '-98.1247988' + } + southwest = [PSCustomObject]@{ + lat = '29.7010964' + lng = '-98.1252494' + } + } + location = [PSCustomObject]@{ + lat = '29.7012853' + lng = '-98.1250235' + } + location_type = 'ROOFTOP' + viewport = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.7026470302915' + lng = '-98.1236751197085' + } + southwest = [PSCustomObject]@{ + lat = '29.6999490697085' + lng = '-98.1263730802915' + } + } + } + place_id = 'ChIJK34phme9XIYRqstHW_gHr2w' + types = @( + 'premise' + ) + } + ) + status = 'OK' +} + +$geoPlaceID = [PSCustomObject]@{ + results = [PSCustomObject]@{ + address_components = @( + [PSCustomObject]@{ + long_name = '148' + short_name = '148' + types = @( + 'street_number' + ) + } + [PSCustomObject]@{ + long_name = 'South Castell Avenue' + short_name = 'S Castell Ave' + types = @( + 'route' + ) + } + [PSCustomObject]@{ + long_name = '' + short_name = '' + types = @( + + ) + } + [PSCustomObject]@{ + long_name = 'New Braunfels' + short_name = 'New Braunfels' + types = @( + 'locality' + 'political' + ) + } + [PSCustomObject]@{ + long_name = 'Comal County' + short_name = 'Comal County' + types = @( + 'administrative_area_level_2' + 'political' + ) + } + [PSCustomObject]@{ + long_name = 'Texas' + short_name = 'TX' + types = @( + 'administrative_area_level_1' + 'political' + ) + } + [PSCustomObject]@{ + long_name = 'United States' + short_name = 'US' + types = @( + 'country' + 'political' + ) + } + [PSCustomObject]@{ + long_name = '78130' + short_name = '78130' + types = @( + 'postal_code' + ) + } + [PSCustomObject]@{ + long_name = '5102' + short_name = '5102' + types = @( + 'postal_code_suffix' + ) + } + ) + formatted_address = '148 S Castell Ave, New Braunfels, TX 78130, USA' + geometry = [PSCustomObject]@{ + bounds = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.7014997' + lng = '-98.1247988' + } + southwest = [PSCustomObject]@{ + lat = '29.7010964' + lng = '-98.1252494' + } + } + location = [PSCustomObject]@{ + lat = '29.7012853' + lng = '-98.1250235' + } + location_type = 'ROOFTOP' + viewport = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.7026470302915' + lng = '-98.1236751197085' + } + southwest = [PSCustomObject]@{ + lat = '29.6999490697085' + lng = '-98.1263730802915' + } + } + } + place_id = 'ChIJK34phme9XIYRqstHW_gHr2w' + types = @( + 'premise' + ) + } + status = 'OK' +} + +#endregion + +$nearby = [PSCustomObject]@{ + html_attributions = '' + next_page_token = 'toooooken' + status = 'OK' + results = @( + [PSCustomObject]@{ + business_status = 'OPERATIONAL' + geometry = [PSCustomObject]@{ + location = [PSCustomObject]@{ + lat = '29.7013856' + lng = '-98.1249258' + } + viewport = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.7028062298927' + lng = '-98.1235759201073' + } + southwest = [PSCustomObject]@{ + lat = '29.7001065701073' + lng = '-98.1262755798927' + } + } + } + icon = 'https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png' + icon_background_color = '#FF9E67' + icon_mask_base_uri = 'https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet' + name = 'Krause''s Cafe' + opening_hours = [PSCustomObject]@{ + open_now = 'False' + } + place_id = 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + plus_code = [PSCustomObject]@{ + compound_code = 'PV2G+H2 New Braunfels, Texas' + global_code = '76X3PV2G+H2' + } + price_level = '2' + rating = '4.3' + reference = 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + types = @( + 'bar' + 'restaurant' + 'food' + 'point_of_interest' + 'establishment' + ) + user_ratings_total = '3675' + vicinity = '148 South Castell Avenue, New Braunfels' + } #obj + [PSCustomObject]@{ + business_status = 'OPERATIONAL' + geometry = [PSCustomObject]@{ + location = [PSCustomObject]@{ + lat = '29.6980452' + lng = '-98.1297508' + } + viewport = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.6993595802915' + lng = '-98.1281500697085' + } + southwest = [PSCustomObject]@{ + lat = '29.6966616197085' + lng = '-98.1308480302915' + } + } + } + icon = 'https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png' + icon_background_color = '#FF9E67' + icon_mask_base_uri = 'https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet' + name = 'Granzin Bar-B-Q' + opening_hours = [PSCustomObject]@{ + open_now = 'False' + } + place_id = 'ChIJ6VO3IWG9XIYRXWDr4zdiDro' + plus_code = [PSCustomObject]@{ + compound_code = 'MVXC+63 New Braunfels, TX, USA' + global_code = '76X3MVXC+63' + } + price_level = '2' + rating = '4.3' + reference = 'ChIJ6VO3IWG9XIYRXWDr4zdiDro' + types = @( + 'restaurant' + 'food' + 'point_of_interest' + 'establishment' + ) + user_ratings_total = '1260' + vicinity = '660 West San Antonio Street, New Braunfels' + } #obj + ) +} + +$textSearch = [PSCustomObject]@{ + html_attributions = '' + next_page_token = 'toooooken' + status = 'OK' + results = @( + [PSCustomObject]@{ + business_status = 'OPERATIONAL' + formatted_address = '148 S Castell Ave, New Braunfels, TX 78130, United States' + geometry = [PSCustomObject]@{ + location = [PSCustomObject]@{ + lat = '29.7013856' + lng = '-98.1249258' + } + viewport = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.7028062298927' + lng = '-98.1235759201073' + } + southwest = [PSCustomObject]@{ + lat = '29.7001065701073' + lng = '-98.1262755798927' + } + } + } + icon = 'https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png' + icon_background_color = '#FF9E67' + icon_mask_base_uri = 'https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet' + name = 'Krause''s Cafe' + opening_hours = [PSCustomObject]@{ + open_now = 'False' + } + place_id = 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + plus_code = [PSCustomObject]@{ + compound_code = 'PV2G+H2 New Braunfels, Texas' + global_code = '76X3PV2G+H2' + } + price_level = '2' + rating = '4.3' + reference = 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + types = @( + 'bar' + 'restaurant' + 'food' + 'point_of_interest' + 'establishment' + ) + user_ratings_total = '3675' + } #obj + [PSCustomObject]@{ + business_status = 'OPERATIONAL' + formatted_address = '1644 McQueeney Rd, New Braunfels, TX 78130, United States' + geometry = [PSCustomObject]@{ + location = [PSCustomObject]@{ + lat = '29.6877297' + lng = '-98.115463' + } + viewport = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.6892016298927' + lng = '-98.1141575701073' + } + southwest = [PSCustomObject]@{ + lat = '29.6865019701073' + lng = '-98.1168572298927' + } + } + } + icon = 'https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png' + icon_background_color = '#4B96F3' + icon_mask_base_uri = 'https://maps.gstatic.com/mapfiles/place_api/icons/v2/shopping_pinlet' + name = "Granzin's Meat Market" + opening_hours = [PSCustomObject]@{ + open_now = 'False' + } + place_id = 'ChIJE43gTHK9XIYRleSxiXqF6GU' + plus_code = [PSCustomObject]@{ + compound_code = 'MVQM+3R New Braunfels, Texas' + global_code = '76X3MVQM+3R' + } + rating = '4.8' + reference = 'ChIJE43gTHK9XIYRleSxiXqF6GU' + types = @( + 'grocery_or_supermarket' + 'liquor_store' + 'food' + 'point_of_interest' + 'store' + 'establishment' + ) + user_ratings_total = '793' + } #obj + ) +} + +$placeDetails = [PSCustomObject]@{ + html_attributions = '' + result = [PSCustomObject]@{ + address_components = @( + [PSCustomObject]@{ + long_name = '148' + short_name = '148' + types = @( + 'street_number' + ) + } + [PSCustomObject]@{ + long_name = 'S Castell Ave' + short_name = '148' + types = @( + 'route' + ) + } + [PSCustomObject]@{ + long_name = 'New Braunfels' + short_name = 'New Braunfels' + types = @( + 'locality' + 'political' + ) + } + [PSCustomObject]@{ + long_name = 'Comal County' + short_name = 'Comal County' + types = @( + 'administrative_area_level_2' + 'political' + ) + } + [PSCustomObject]@{ + long_name = 'Texas' + short_name = 'TX' + types = @( + 'administrative_area_level_1' + 'political' + ) + } + [PSCustomObject]@{ + long_name = 'United States' + short_name = 'US' + types = @( + 'country' + 'political' + ) + } + [PSCustomObject]@{ + long_name = '78130' + short_name = '78130' + types = @( + 'postal_code' + ) + } + [PSCustomObject]@{ + long_name = '5102' + short_name = '5102' + types = @( + 'postal_code_suffix' + ) + } + ) + business_status = 'OPERATIONAL' + formatted_address = '148 S Castell Ave, New Braunfels, TX 78130, United States' + formatted_phone_number = '(830) 625-2807' + geometry = [PSCustomObject]@{ + location = [PSCustomObject]@{ + lat = '29.7013856' + lng = '-98.1249258' + } + viewport = [PSCustomObject]@{ + northeast = [PSCustomObject]@{ + lat = '29.7028062298927' + lng = '-98.1235759201073' + } + southwest = [PSCustomObject]@{ + lat = '29.7001065701073' + lng = '-98.1262755798927' + } + } + } + icon = 'https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png' + icon_background_color = '#FF9E67' + icon_mask_base_uri = 'https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet' + name = 'Krause''s Cafe' + opening_hours = [PSCustomObject]@{ + open_now = 'False' + periods = [PSCustomObject]@{ + open = @( + [PSCustomObject]@{ + day = 0 + time = 0730 + } + [PSCustomObject]@{ + day = 1 + time = 0730 + } + [PSCustomObject]@{ + day = 2 + time = 0730 + } + [PSCustomObject]@{ + day = 3 + time = 0730 + } + [PSCustomObject]@{ + day = 4 + time = 0730 + } + [PSCustomObject]@{ + day = 5 + time = 0730 + } + [PSCustomObject]@{ + day = 6 + time = 0730 + } + ) + close = @( + [PSCustomObject]@{ + day = 0 + time = 2200 + } + [PSCustomObject]@{ + day = 1 + time = 2200 + } + [PSCustomObject]@{ + day = 2 + time = 2200 + } + [PSCustomObject]@{ + day = 3 + time = 2200 + } + [PSCustomObject]@{ + day = 4 + time = 2200 + } + [PSCustomObject]@{ + day = 5 + time = 2300 + } + [PSCustomObject]@{ + day = 6 + time = 2300 + } + ) + } + weekday_text = @( + 'Monday: 7:30 AM – 10:00 PM' + 'Tuesday: 7:30 AM – 10:00 PM' + 'Wednesday: 7:30 AM – 10:00 PM' + 'Thursday: 7:30 AM – 10:00 PM' + 'Friday: 7:30 AM – 11:00 PM' + 'Saturday: 7:30 AM – 11:00 PM' + 'Sunday: 7:30 AM – 10:00 PM' + ) + } + place_id = 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + plus_code = [PSCustomObject]@{ + compound_code = 'PV2G+H2 New Braunfels, Texas' + global_code = '76X3PV2G+H2' + } + price_level = '2' + rating = '4.3' + reviews = @( + [PSCustomObject]@{ + author_name = 'Andrea Mara' + author_url = 'https://www.google.com/maps/contrib/106805061694773377686/reviews' + language = 'en' + profile_photo_url = 'https://lh3.googleusercontent.com/a-/AOh14Gg9C60vdW30CJmsLgpaXtLNC0-OF0eSSRCkNseqK60=s128-c0x00000000-cc-rp-mo-ba3' + rating = '4' + relative_time_description = '2 weeks ago' + text = 'We went there for the first time and we were so happy we found it. + This restaurant has a huge outside beer garden and inside restaurant. + My husband had the Reuben sandwich with German potato salad and I had + their cheeseburger with homemade chips. I had not tasted such great + beef since we used to raise our own beef. The meat was so tasty and + moist. Both of us only ate half our sandwiches as we had a huge + pretzel for an appetizer. We will be going back.' + time = '1631827922' + } + ) + types = @( + 'bar' + 'restaurant' + 'food' + 'point_of_interest' + 'establishment' + ) + url = 'https://maps.google.com/?cid=6720415583914850961' + user_ratings_total = 3697 + utc_offset = '-300' + vicinity = '148 South Castell Avenue, New Braunfels' + website = 'https://www.krausescafe.com/' + } + status = 'OK' +} + +Export-ModuleMember -Variable '*' diff --git a/src/pwshPlaces.build.ps1 b/src/pwshPlaces.build.ps1 index 05102bb..4409044 100644 --- a/src/pwshPlaces.build.ps1 +++ b/src/pwshPlaces.build.ps1 @@ -184,7 +184,11 @@ Add-BuildTask AnalyzeTests -After Analyze { $scriptAnalyzerParams = @{ Path = $script:TestsPath Setting = 'PSScriptAnalyzerSettings.psd1' - ExcludeRule = 'PSUseDeclaredVarsMoreThanAssignments' + ExcludeRule = @( + 'PSUseDeclaredVarsMoreThanAssignments' + 'PSAvoidOverwritingBuiltInCmdlets' + 'PSUseShouldProcessForStateChangingFunctions' + ) Recurse = $true Verbose = $false } @@ -244,7 +248,7 @@ Add-BuildTask Test { if (Test-Path -Path $script:UnitTestsPath) { $pesterConfiguration = [PesterConfiguration]::new() - $pesterConfiguration.run.Path = $script:TestsPath + $pesterConfiguration.run.Path = $script:UnitTestsPath $pesterConfiguration.Run.PassThru = $true $pesterConfiguration.Run.Exit = $false $pesterConfiguration.CodeCoverage.Enabled = $true @@ -502,7 +506,7 @@ Add-BuildTask InfraTest { $pesterConfiguration = [PesterConfiguration]::new() - $pesterConfiguration.run.Path = 'Tests\Infrastructure' + $pesterConfiguration.run.Path = $script:InfraTestsPath $pesterConfiguration.Run.PassThru = $true $pesterConfiguration.Run.Exit = $false $pesterConfiguration.CodeCoverage.Enabled = $false diff --git a/src/pwshPlaces/Imports.ps1 b/src/pwshPlaces/Imports.ps1 index ad7b7d9..94f87c4 100644 --- a/src/pwshPlaces/Imports.ps1 +++ b/src/pwshPlaces/Imports.ps1 @@ -2,5 +2,450 @@ # It can be imported by the psm1 in local development to add script level variables. # It will merged in the build process. This is for local development only. -# region script variables +#region script variables # $script:resourcePath = "$PSScriptRoot\Resources" + +#------------------------------------------------------------ +# ! API KEYS +# $env:GoogleAPIKey = '' +#------------------------------------------------------------ + +$script:googleMapsBaseURI = 'https://maps.googleapis.com/maps/api/' + +#endregion + +#region parameter enums + +enum ccTLD { + ac #Ascension Island + ad #Andorra + ae #United Arab Emirate + af #Afghanistan + ag #Antigua and Barbuda + ai #Anguilla + al #Albania + am #Armenia + ao #Angola + aq #Antarctica + ar #Argentina + as #American Samoa + at #Austria + au #Australia + aw #Aruba + ax #Ã…land Islands + az #Azerbaijan + ba #Bosnia and Herzegov + bb #Barbados + bd #Bangladesh + be #Belgium + bf #Burkina Faso + bg #Bulgaria + bh #Bahrain + bi #Burundi + bj #Benin + bm #Bermuda + bn #Brunei + bo #Bolivia + br #Brazil + bs #Bahamas + bt #Bhutan + bv #Bouvet Island + bw #Botswana + by #Belarus + bz #Belize + ca #Canada + cc #Cocos (Keeling) Isl + cd #Democratic Republic + cf #Central African Rep + cg #Republic of the Con + ch #Switzerland + ci #Ivory Coast + ck #Cook Islands + cl #Chile + cm #Cameroon + cn #China + co #Colombia + cr #Costa Rica + cu #Cuba + cv #Cape Verde + cw #Curaçao + cx #Christmas Island + cy #Cyprus + cz #Czech Republic + de #Germany + dj #Djibouti + dk #Denmark + dm #Dominica + do #Dominican Republic + dz #Algeria + ec #Ecuador + ee #Estonia + eg #Egypt + er #Eritrea + es #Spain + et #Ethiopia + eu #European Union + fi #Finland + fj #Fiji + fk #Falkland Islands + fm #Micronesia + fo #Faroe Islands + fr #France + ga #Gabon + gb #United Kingdom + gd #Grenada + ge #Georgia + gf #French Guiana + gg #Guernsey + gh #Ghana + gi #Gibraltar + gl #Greenland + gm #Gambia + gn #Guinea + gp #Guadeloupe + gq #Equatorial Guinea + gr #Greece + gs #South Georgia + gt #Guatemala + gu #Guam + gw #Guinea-Bissau + gy #Guyana + hk #Hong Kong + hm #Heard Island and Mc + hn #Honduras + hr #Croatia + ht #Haiti + hu #Hungary + id #Indonesia + ie #Ireland + il #Israel + im #Isle of Man + in #India + io #British Indian Ocea + iq #Iraq + ir #Iran + is #Iceland + it #Italy + je #Jersey + jm #Jamaica + jo #Jordan + jp #Japan + ke #Kenya + kg #Kyrgyzstan + kh #Cambodia + ki #Kiribati + km #Comoros + kn #Saint Kitts and Nev + kp #North Korea + kr #South Korea + kw #Kuwait + ky #Cayman Islands + kz #Kazakhstan + la #Laos + lb #Lebanon + lc #Saint Lucia + li #Liechtenstein + lk #Sri Lanka + lr #Liberia + ls #Lesotho + lt #Lithuania + lu #Luxembourg + lv #Latvia + ly #Libya + ma #Morocco + mc #Monaco + md #Moldova + me #Montenegro + mg #Madagascar + mh #Marshall Islands + mk #North Macedonia + ml #Mali + mm #Myanmar + mn #Mongolia + mo #Macao + mp #Northern Mariana Is + mq #Martinique + mr #Mauritania + ms #Montserrat + mt #Malta + mu #Mauritius + mv #Maldives + mw #Malawi + mx #Mexico + my #Malaysia + mz #Mozambique + na #Namibia + nc #New Caledonia + ne #Niger + nf #Norfolk Island + ng #Nigeria + ni #Nicaragua + nl #Netherlands + no #Norway + np #Nepal + nr #Nauru + nu #Niue + nz #New Zealand + om #Oman + pa #Panama + pe #Peru + pf #French Polynesia + pg #Papua New Guinea + ph #Philippines + pk #Pakistan + pl #Poland + pm #Saint Pierre and Mi + pn #Pitcairn Islands + pr #Puerto Rico + ps #Palestine + pt #Portugal + pw #Palau + py #Paraguay + qa #Qatar + re #Réunion + ro #Romania + rs #Serbia + ru #Russia + rw #Rwanda + sa #Saudi Arabia + sb #Solomon Islands + sc #Seychelles + sd #Sudan + se #Sweden + sg #Singapore + sh #Saint Helena + si #Slovenia + sj #Svalbard and Jan Ma + sk #Slovakia + sl #Sierra Leone + sm #San Marino + sn #Senegal + so #Somalia + sr #Suriname + ss #South Sudan + st #Sao Tome and Princi + su #Soviet Union + sv #El Salvador + sx #Sint Maarten + sy #Syria + sz #Eswatini + tc #Turks and Caicos Is + td #Chad + tf #French Southern Ter + tg #Togo + th #Thailand + tj #Tajikistan + tk #Tokelau + tl #East Timor + tm #Turkmenistan + tn #Tunisia + to #Tonga + tr #Turkey + tt #Trinidad and Tobago + tv #Tuvalu + tw #Taiwan + tz #Tanzania + ua #Ukraine + ug #Uganda + uk #United Kingdom + us #United States + uy #Uruguay + uz #Uzbekistan + va #Vatican + vc #Saint Vincent and t + ve #Venezuela + vg #British Virgin Isla + vi #U.S. Virgin Islands + vn #Vietnam + vu #Vanuatu + wf #Wallis and Futuna + ws #Samoa + ye #Yemen + yt #Mayotte + za #South Africa + zm #Zambia + zw #Zimbabwe +} #enum_ccTLD + +# https://developers.google.com/maps/faq#languagesupport +enum languages { + af #Afrikaans + sq #Albanian + am #Amharic + ar #Arabic + hy #Armenian + az #Azerbaijani + eu #Basque + be #Belarusian + bn #Bengali + bs #Bosnian + bg #Bulgarian + my #Burmese + ca #Catalan + zh #Chinese + # zh-CN #Chinese (Simplified) + # zh-HK #Chinese (Hong Kong) + # zh-TW #Chinese (Traditional) + hr #Croatian + cs #Czech + da #Danish + nl #Dutch + en #English + # en-AU #English (Australian) + # en-GB #English (Great Britain) + et #Estonian + fa #Farsi + fi #Finnish + fil #Filipino + fr #French + # fr-CA #French (Canada) + ka #Georgian + de #German + el #Greek + iw #Hebrew + hi #Hindi + hu #Hungarian + is #Icelandic + id #Indonesian + it #Italian + ja #Japanese + kn #Kannada + kk #Kazakh + km #Khmer + ko #Korean + ky #Kyrgyz + lo #Lao + lv #Latvian + lt #Lithuanian + mk #Macedonian + ms #Malay + ml #Malayalam + mr #Marathi + mn #Mongolian + ne #Nepali + no #Norwegian + pl #Polish + pt #Portuguese + # pt-BR #Portuguese (Brazil) + # pt-PT #Portuguese (Portugal) + pa #Punjabi + ro #Romanian + ru #Russian + sr #Serbian + # si #Sinhalese + sk #Slovak + # sl #Slovenian + es #Spanish + # es-419 #Spanish (Latin America) + sw #Swahili + ta #Tamil + te #Telugu + th #Thai + uk #Ukrainian + ur #Urdu + uz #Uzbek + vi #Vietnamese + zu #Zulu +} #enum_languages + +# https://developers.google.com/maps/documentation/places/web-service/supported_types#table1 +enum placeTypes { + accounting + airport + amusement_park + aquarium + art_gallery + atm + bakery + bank + bar + beauty_salon + bicycle_store + book_store + bowling_alley + bus_station + cafe + campground + car_dealer + car_rental + car_repair + car_wash + casino + cemetery + church + city_hall + clothing_store + convenience_store + courthouse + dentist + department_store + doctor + drugstore + electrician + electronics_store + embassy + fire_station + florist + funeral_home + furniture_store + gas_station + gym + hair_care + hardware_store + hindu_temple + home_goods_store + hospital + insurance_agency + jewelry_store + laundry + lawyer + library + light_rail_station + liquor_store + local_government_office + locksmith + lodging + meal_delivery + meal_takeaway + mosque + movie_rental + movie_theater + moving_company + museum + night_club + painter + park + parking + pet_store + pharmacy + physiotherapist + plumber + police + post_office + primary_school + real_estate_agency + restaurant + roofing_contractor + rv_park + school + secondary_school + shoe_store + shopping_mall + spa + stadium + storage + store + subway_station + supermarket + synagogue + taxi_stand + tourist_attraction + train_station + transit_station + travel_agency + university + veterinary_care + zoo +} #enum_placeTypes + +#endregion diff --git a/src/pwshPlaces/Private/Format-GMapGeoCode.ps1 b/src/pwshPlaces/Private/Format-GMapGeoCode.ps1 new file mode 100644 index 0000000..1fc2c47 --- /dev/null +++ b/src/pwshPlaces/Private/Format-GMapGeoCode.ps1 @@ -0,0 +1,117 @@ +<# +.SYNOPSIS + Formats GeoCode object with easier to understand properties while leaving original properties intact +.DESCRIPTION + Changes GeoCode object to custom PSType and creates additional properties that contains information most likely to be viewed. +.EXAMPLE + $results.result | Format-GMapGeoCode + + Formats GeoCode object results with a set of easier to understand properties +.PARAMETER Results + GeoCode API results +.OUTPUTS + GMap.GeoCode +.NOTES + Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + + Based on code from: https://github.com/Kreloc/PoshGMaps +.COMPONENT + pwshPlaces +#> +function Format-GMapGeoCode { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, + HelpMessage = 'GeoCode API results', + ValueFromPipeline = $true)] + $Results + ) + begin { + Write-Verbose ('Starting {0}' -f $myinvocation.mycommand) + } #begin + process { + Write-Debug -Message ($Results | Out-String) + + $Results.PSTypeNames.Insert(0, 'GMap.GeoCode') + + Write-Debug -Message ($Results.PSTypeNames | Out-String) + + $updateTypeDataSplat = @{ + TypeName = 'GMap.GeoCode' + MemberType = 'ScriptProperty' + MemberName = 'StreetNumber' + Value = { $(($this.address_components | Where-Object { $_.types -contains "street_number" }).long_name) } + Force = $true + } + Write-Verbose ($updateTypeDataSplat | Out-String) + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.GeoCode' + MemberType = 'ScriptProperty' + MemberName = 'Street' + Value = { $($this.address_components | Where-Object { $_.types -contains "route" }).long_name } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.GeoCode' + MemberType = 'ScriptProperty' + MemberName = 'City' + Value = { $($this.address_components | Where-Object { $_.types -contains "locality" }).long_name } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.GeoCode' + MemberType = 'ScriptProperty' + MemberName = 'Country' + Value = { $($this.address_components | Where-Object { $_.types -contains "country" }).long_name } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.GeoCode' + MemberType = 'ScriptProperty' + MemberName = 'PostalCode' + Value = { $($this.address_components | Where-Object { $_.types -contains "postal_code" }).long_name } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.GeoCode' + MemberType = 'ScriptProperty' + MemberName = 'Latitude' + Value = { $this.geometry.location.lat } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.GeoCode' + MemberType = 'ScriptProperty' + MemberName = 'Longitude' + Value = { $this.geometry.location.lng } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + # set a default display of the above properties, all other properties are still there just not displayed + $updateTypeDataSplat = @{ + TypeName = 'GMap.GeoCode' + DefaultDisplayPropertySet = 'place_id', 'formatted_address', 'StreetNumber', 'Street', 'City', 'Country', 'PostalCode', 'Latitude', 'Longitude', 'types' + DefaultKeyPropertySet = 'place_id' + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $Results + } #process + end { + Write-Verbose ('Ending {0}' -f $myinvocation.mycommand) + } #end +} #Format-GMapGeoCode diff --git a/src/pwshPlaces/Private/Format-GMapNearbyPlace.ps1 b/src/pwshPlaces/Private/Format-GMapNearbyPlace.ps1 new file mode 100644 index 0000000..349caa1 --- /dev/null +++ b/src/pwshPlaces/Private/Format-GMapNearbyPlace.ps1 @@ -0,0 +1,89 @@ +<# +.SYNOPSIS + Formats Nearby Place object with easier to understand properties while leaving original properties intact +.DESCRIPTION + Changes Nearby Place object to custom PSType and creates additional properties that contains information most likely to be viewed. +.EXAMPLE + $results.results | Format-GMapNearbyPlace + + Formats Nearby Place object results with a set of easier to understand properties +.PARAMETER Results + Nearby Place API results +.OUTPUTS + GMap.NearbyPlace +.NOTES + Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + + Based on code from: https://github.com/Kreloc/PoshGMaps +.COMPONENT + pwshPlaces +#> +function Format-GMapNearbyPlace { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, + HelpMessage = 'Place API results', + ValueFromPipeline = $true)] + $Results + ) + begin { + Write-Verbose ('Starting {0}' -f $myinvocation.mycommand) + } #begin + process { + Write-Debug -Message ($Results | Out-String) + + $Results.PSTypeNames.Insert(0, 'GMap.NearbyPlace') + + Write-Debug -Message ($Results.PSTypeNames | Out-String) + + $updateTypeDataSplat = @{ + TypeName = 'GMap.NearbyPlace' + MemberType = 'ScriptProperty' + MemberName = 'Latitude' + Value = { $this.geometry.location.lat } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.NearbyPlace' + MemberType = 'ScriptProperty' + MemberName = 'Longitude' + Value = { $this.geometry.location.lng } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.NearbyPlace' + MemberType = 'ScriptProperty' + MemberName = 'Address' + Value = { $this.vicinity } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.NearbyPlace' + MemberType = 'ScriptProperty' + MemberName = 'Open' + Value = { $this.opening_hours.open_now } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + # set a default display of the above properties, all other properties are still there just not displayed + $updateTypeDataSplat = @{ + TypeName = 'GMap.NearbyPlace' + DefaultDisplayPropertySet = 'place_id', 'name', 'Address', 'Latitude', 'Longitude', 'types', 'rating', 'user_ratings_total', 'price_level', 'Open' + DefaultKeyPropertySet = 'place_id' + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $Results + } #process + end { + Write-Verbose ('Ending {0}' -f $myinvocation.mycommand) + } #end +} #Format-GMapNearbyPlace diff --git a/src/pwshPlaces/Private/Format-GMapPlace.ps1 b/src/pwshPlaces/Private/Format-GMapPlace.ps1 new file mode 100644 index 0000000..efd8e01 --- /dev/null +++ b/src/pwshPlaces/Private/Format-GMapPlace.ps1 @@ -0,0 +1,91 @@ +<# +.SYNOPSIS + Formats Place object with easier to understand properties while leaving original properties intact +.DESCRIPTION + Changes Place object to custom PSType and creates additional properties that contains information most likely to be viewed. +.EXAMPLE + $results.candidates | Format-GMapPlace + + Formats Place object results with a set of easier to understand properties +.PARAMETER Results + Place API results +.OUTPUTS + GMap.Place +.NOTES + Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + + Based on code from: https://github.com/Kreloc/PoshGMaps +.COMPONENT + pwshPlaces +#> +function Format-GMapPlace { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, + HelpMessage = 'Place API results', + ValueFromPipeline = $true)] + $Results + ) + begin { + Write-Verbose ('Starting {0}' -f $myinvocation.mycommand) + } #begin + process { + Write-Debug -Message ($Results | Out-String) + + $Results.PSTypeNames.Insert(0, 'GMap.Place') + + Write-Debug -Message ($Results.PSTypeNames | Out-String) + + $updateTypeDataSplat = @{ + TypeName = 'GMap.Place' + MemberType = 'ScriptProperty' + MemberName = 'Latitude' + Value = { $this.geometry.location.lat } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.Place' + MemberType = 'ScriptProperty' + MemberName = 'Longitude' + Value = { $this.geometry.location.lng } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.Place' + MemberType = 'ScriptProperty' + MemberName = 'Address' + Value = { $this.formatted_address } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + # if ($Contact) { + $updateTypeDataSplat = @{ + TypeName = 'GMap.Place' + MemberType = 'ScriptProperty' + MemberName = 'Open' + Value = { $this.opening_hours.open_now } + Force = $true + } + Update-TypeData @updateTypeDataSplat + # } + + # set a default display of the above properties, all other properties are still there just not displayed + $updateTypeDataSplat = @{ + TypeName = 'GMap.Place' + DefaultDisplayPropertySet = 'place_id', 'name', 'Address', 'Open', 'rating', 'user_ratings_total', 'price_level', 'Latitude', 'Longitude', 'types' + DefaultKeyPropertySet = 'place_id' + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $Results + } #process + end { + Write-Verbose ('Ending {0}' -f $myinvocation.mycommand) + } #end +} #Format-GMapPlace diff --git a/src/pwshPlaces/Private/Format-GMapPlaceDetail.ps1 b/src/pwshPlaces/Private/Format-GMapPlaceDetail.ps1 new file mode 100644 index 0000000..20dc7e3 --- /dev/null +++ b/src/pwshPlaces/Private/Format-GMapPlaceDetail.ps1 @@ -0,0 +1,116 @@ +<# +.SYNOPSIS + Formats Detailed Place object with easier to understand properties while leaving original properties intact +.DESCRIPTION + Changes Detailed Place object to custom PSType and creates additional properties that contains information most likely to be viewed. +.EXAMPLE + $results.results | Format-GMapPlaceDetail + + Formats Detailed Place object results with a set of easier to understand properties +.PARAMETER Results + Detailed Place API results +.OUTPUTS + GMap.PlaceDetail +.NOTES + Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + + Based on code from: https://github.com/Kreloc/PoshGMaps +.COMPONENT + pwshPlaces +#> +function Format-GMapPlaceDetail { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, + HelpMessage = 'Place API results', + ValueFromPipeline = $true)] + $Results + ) + begin { + Write-Verbose ('Starting {0}' -f $myinvocation.mycommand) + } #begin + process { + Write-Debug -Message ($Results | Out-String) + + $Results.PSTypeNames.Insert(0, 'GMap.PlaceDetail') + + Write-Debug -Message ($Results.PSTypeNames | Out-String) + + $updateTypeDataSplat = @{ + TypeName = 'GMap.PlaceDetail' + MemberType = 'ScriptProperty' + MemberName = 'Latitude' + Value = { $this.geometry.location.lat } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.PlaceDetail' + MemberType = 'ScriptProperty' + MemberName = 'Longitude' + Value = { $this.geometry.location.lng } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.PlaceDetail' + MemberType = 'ScriptProperty' + MemberName = 'Address' + Value = { $this.formatted_address } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.PlaceDetail' + MemberType = 'ScriptProperty' + MemberName = 'Phone' + Value = { $this.formatted_phone_number } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.PlaceDetail' + MemberType = 'ScriptProperty' + MemberName = 'Open' + Value = { $this.opening_hours.open_now } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.PlaceDetail' + MemberType = 'ScriptProperty' + MemberName = 'OpenHours' + Value = { $this.opening_hours.weekday_text } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.PlaceDetail' + MemberType = 'ScriptProperty' + MemberName = 'GoogleMapsURL' + Value = { $this.url } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + # set a default display of the above properties, all other properties are still there just not displayed + $updateTypeDataSplat = @{ + TypeName = 'GMap.PlaceDetail' + DefaultDisplayPropertySet = 'place_id', 'name', 'website', 'Address', 'Phone', 'Open', 'OpenHours', 'GoogleMapsURL', 'rating', 'user_ratings_total', 'price_level', 'Latitude', 'Longitude', 'types' + DefaultKeyPropertySet = 'place_id' + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $Results + } #process + end { + Write-Verbose ('Ending {0}' -f $myinvocation.mycommand) + } #end +} #Format-GMapPlaceDetail diff --git a/src/pwshPlaces/Private/Format-GMapPlaceText.ps1 b/src/pwshPlaces/Private/Format-GMapPlaceText.ps1 new file mode 100644 index 0000000..c64c18f --- /dev/null +++ b/src/pwshPlaces/Private/Format-GMapPlaceText.ps1 @@ -0,0 +1,89 @@ +<# +.SYNOPSIS + Formats Text Place object with easier to understand properties while leaving original properties intact +.DESCRIPTION + Changes Text Place object to custom PSType and creates additional properties that contains information most likely to be viewed. +.EXAMPLE + $results.results | Format-GMapPlaceText + + Formats Text Place object results with a set of easier to understand properties +.PARAMETER Results + Nearby Place API results +.OUTPUTS + GMap.PlaceText +.NOTES + Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + + Based on code from: https://github.com/Kreloc/PoshGMaps +.COMPONENT + pwshPlaces +#> +function Format-GMapPlaceText { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, + HelpMessage = 'Place API results', + ValueFromPipeline = $true)] + $Results + ) + begin { + Write-Verbose ('Starting {0}' -f $myinvocation.mycommand) + } #begin + process { + Write-Debug -Message ($Results | Out-String) + + $Results.PSTypeNames.Insert(0, 'GMap.PlaceText') + + Write-Debug -Message ($Results.PSTypeNames | Out-String) + + $updateTypeDataSplat = @{ + TypeName = 'GMap.PlaceText' + MemberType = 'ScriptProperty' + MemberName = 'Latitude' + Value = { $this.geometry.location.lat } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.PlaceText' + MemberType = 'ScriptProperty' + MemberName = 'Longitude' + Value = { $this.geometry.location.lng } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.PlaceText' + MemberType = 'ScriptProperty' + MemberName = 'Address' + Value = { $this.formatted_address } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'GMap.PlaceText' + MemberType = 'ScriptProperty' + MemberName = 'Open' + Value = { $this.opening_hours.open_now } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + # set a default display of the above properties, all other properties are still there just not displayed + $updateTypeDataSplat = @{ + TypeName = 'GMap.PlaceText' + DefaultDisplayPropertySet = 'place_id', 'name', 'Address', 'Latitude', 'Longitude', 'types', 'rating', 'user_ratings_total', 'price_level', 'Open' + DefaultKeyPropertySet = 'place_id' + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $Results + } #process + end { + Write-Verbose ('Ending {0}' -f $myinvocation.mycommand) + } #end +} #Format-GMapPlaceText diff --git a/src/pwshPlaces/Private/Get-Day.ps1 b/src/pwshPlaces/Private/Get-Day.ps1 deleted file mode 100644 index ca74750..0000000 --- a/src/pwshPlaces/Private/Get-Day.ps1 +++ /dev/null @@ -1,38 +0,0 @@ -<# -.SYNOPSIS - Short description -.DESCRIPTION - Long description -.EXAMPLE - C:\PS> - Example of how to use this cmdlet -.EXAMPLE - C:\PS> - Another example of how to use this cmdlet -.PARAMETER InputObject - Specifies the object to be processed. You can also pipe the objects to this command. -.OUTPUTS - Output from this cmdlet (if any) -.NOTES - General notes -.COMPONENT - pwshPlaces -#> -function Get-Day { - [CmdletBinding()] - param ( - # [Parameter(Mandatory = $true, - # HelpMessage = 'Helpful Message')] - # [ValidateNotNull()] - # [ValidateNotNullOrEmpty()] - # [string]$YourParameter - ) - try { - $day = (Get-Date -ErrorAction 'Stop').DayOfWeek - } - catch { - $day = 'Unknown' - } - - return $day -} #Get-Day diff --git a/src/pwshPlaces/Public/Find-GMapPlace.ps1 b/src/pwshPlaces/Public/Find-GMapPlace.ps1 new file mode 100644 index 0000000..feda7d2 --- /dev/null +++ b/src/pwshPlaces/Public/Find-GMapPlace.ps1 @@ -0,0 +1,308 @@ +<# +.SYNOPSIS + Find Place request takes a text input and returns a place. The input can be any kind of Places text data, such as a name, address, or phone number. +.DESCRIPTION + Performs a find place request with provided parameters. + A text search is performed unless a properly formatted phone number is provided in which case + a phonenumber search is completed. By default the location bias and language is IP based. + Location bias and language can be controlled via parameters. The information returned in a normal + call contains all basic field types. Additional field types including contact and atmosphere information + can be called for but these carry an additional cost. The Find Place return does not return + all fields of these more expensive calls and has a limited return. See notes for details. +.EXAMPLE + Find-GMapPlace -Query "Krause's cafe" + + Returns place information for the query location biased by IP. +.EXAMPLE + Find-GMapPlace -Query "Krause's cafe" -Language es + + Returns place information for the query location biased by IP and returns results in Spanish. +.EXAMPLE + Find-GMapPlace -Query '+18306252807' + + Returns place information for the query location biased by IP. +.EXAMPLE + Find-GMapPlace -Query 'cafe' -PointLatitude '29.7049806' -PointLongitude '-98.068343' + + Returns place information for the query location biased by provided lat/long point. +.EXAMPLE + Find-GMapPlace -Query 'cafe' -PointLatitude '29.7049806' -PointLongitude '-98.068343' -Language en + + Returns place information for the query location biased by provided lat/long point and returns results in English. +.EXAMPLE + Find-GMapPlace -Query 'cafe' -CircleLatitude '29.7049806' -CircleLongitude '-98.068343' -CircleRadius '8046' + + Returns place information for the query location biased by circle lat/long/radius. +.EXAMPLE + Find-GMapPlace -Query 'cafe' -SouthLatitude '39.8592387' -WestLongitude '-75.295486' -NorthLatitude '40.0381942' -EastLongitude '-75.0064087' + + Returns place information for the query location biased by rectangular two lat/lng pairs in decimal degrees, representing the south/west and north/east points of a rectangle. +.EXAMPLE + Find-GMapPlace -Query '+18306252807' -PointLatitude '29.7049806' -PointLongitude '-98.068343' -Contact -Atmosphere -Language en + + Returns place information for the query location biased by provided lat/long point with additional Contact and Atmosphere fields with results in Enlgish. +.EXAMPLE + $findGMapPlaceSplat = @{ + Query = '+18306252807' + PointLatitude = '29.7049806' + PointLongitude = '-98.068343' + Contact = $true + Atmosphere = $true + Language = 'en' + } + Find-GMapPlace @findGMapPlaceSplat + + Returns place information for the query location biased by provided lat/long point with additional Contact and Atmosphere fields with results in Enlgish. +.PARAMETER Query + Text input that identifies the search target, such as a name, address, or phone number. Phone numbers must be in international format (prefixed by a plus sign ("+"), followed by the country code, then the phone number itself) +.PARAMETER PointLatitude + Prefer results in a specified area by specifying a single coordinate for the north–south position of a point on the Earth's surface. +.PARAMETER PointLongitude + Prefer results in a specified area by specifying a single coordinate for the east–west position of a point on the Earths surface. +.PARAMETER CircleLatitude + Prefer results in a specified area by specifying a radius plus lat/long - north–south position of a point on the Earth's surface. +.PARAMETER CircleLongitude + Prefer results in a specified area by specifying a radius plus lat/long - east–west position of a point on the Earths surface. +.PARAMETER CircleRadius + Prefer results in a specified area by specifying a radius plus lat/long - radius in meters +.PARAMETER SouthLatitude + Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - south latitude +.PARAMETER WestLongitude + Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - west longitude +.PARAMETER NorthLatitude + Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - north latitude +.PARAMETER EastLongitude + Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - east longitude +.PARAMETER Contact + Returns contact related information about the result - contact fields are billed at a higher rate. +.PARAMETER Atmosphere + Returns atmosphere related information including reviews and pricing about the result - atmosphere fields are billed at a higher rate. +.PARAMETER Language + The language in which to return results. +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + + Latitude and Longitude information can be easily retrieved using Invoke-GMapGeoCode + + If you provide faulty lat/long info the API call will default back to IP based locationbias. + + Required parameters + input + Text input that identifies the search target, such as a name, address, or phone number. The input must be a string. + inputtype + The type of input. This can be one of either textquery or phonenumber. + Phone numbers must be in international format (prefixed by a plus sign ("+"), followed by the country code, then the phone number itself) + Optional parameters + fields + Billing Categories + Basic - no charge + Contact + Atmosphere + language + locationbias + Prefer results in a specified area, by specifying either a radius plus lat/lng, or two lat/lng pairs representing the points of a rectangle. If this parameter is not specified, the API uses IP address biasing by default. + + IP bias: Instructs the API to use IP address biasing. Pass the string ipbias (this option has no additional parameters). + Point: A single lat/lng coordinate. Use the following format: point:lat,lng. + Circular: A string specifying radius in meters, plus lat/lng in decimal degrees. Use the following format: circle:radius@lat,lng. + Rectangular: A string specifying two lat/lng pairs in decimal degrees + + Example: + https://maps.googleapis.com/maps/api/place/findplacefromtext/json?fields=formatted_address%2Cname%2Crating%2Copening_hours%2Cgeometry&input=Museum%20of%20Contemporary%20Art%20Australia&inputtype=textquery&key=YOUR_API_KEY + + Caution: Place Search requests and Place Details requests do not return the same fields. + Place Search requests return a subset of the fields that are returned by Place Details requests. + If the field you want is not returned by Place Search, you can use Place Search to get a place_id, + then use that Place ID to make a Place Details request. + ^ this essentially means you are better served with the find by using basic fields only. + If you need additional information make a subsequent Place Details API call. + + Don't use the Contact or Atmosphere parameters of this function. They aren't worth it. If you need more detail use Get-GMapPlaceDetail + + This function includes Google Maps features and content; use of Google Maps features and content is subject to the terms of service and Google privacy (linked below). +.COMPONENT + pwshPlaces +.LINK + https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Find-GMapPlace.md +.LINK + https://developers.google.com/maps/documentation/places/web-service/search-find-place +.LINK + https://maps.googleapis.com/maps/api/place/findplacefromtext/output?parameters +.LINK + https://developers.google.com/maps/faq#languagesupport +.LINK + https://cloud.google.com/maps-platform/terms/ +.LINK + https://www.google.com/policies/privacy/ +#> +function Find-GMapPlace { + [CmdletBinding( + PositionalBinding = $false, + DefaultParameterSetName = 'textquery')] + param ( + # 'Phone numbers must be in international format (prefixed by a plus sign ("+"), followed by the country code, then the phone number itself)')] + [Parameter(Mandatory = $true, + ParameterSetName = 'textquery', + HelpMessage = 'Text input that identifies the search target, such as a name, address, or phone number.')] + [Parameter(ParameterSetName = 'Point', Mandatory = $false)] + [Parameter(ParameterSetName = 'Circle', Mandatory = $false)] + [Parameter(ParameterSetName = 'Rectangle', Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [string]$Query, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Point', + HelpMessage = 'Location bias by point lat')] + [ValidateNotNullOrEmpty()] + [string]$PointLatitude, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Point', + HelpMessage = 'Location bias by point long')] + [ValidateNotNullOrEmpty()] + [string]$PointLongitude, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Circle', + HelpMessage = 'Location bias circular lat')] + [ValidateNotNullOrEmpty()] + [string]$CircleLatitude, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Circle', + HelpMessage = 'Location bias circular long')] + [ValidateNotNullOrEmpty()] + [string]$CircleLongitude, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Circle', + HelpMessage = 'Location bias circular radius')] + [ValidateNotNullOrEmpty()] + [string]$CircleRadius, + + # A string specifying two lat/lng pairs in decimal degrees, representing the south/west and north/east points of a rectangle. + [Parameter(Mandatory = $true, + ParameterSetName = 'Rectangle', + HelpMessage = 'Location bias rectangle south lat')] + [ValidateNotNullOrEmpty()] + [string]$SouthLatitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Rectangle', + HelpMessage = 'Location bias rectangle west long')] + [ValidateNotNullOrEmpty()] + [string]$WestLongitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Rectangle', + HelpMessage = 'Location bias rectangle north lat')] + [ValidateNotNullOrEmpty()] + [string]$NorthLatitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Rectangle', + HelpMessage = 'Location bias rectangle east long')] + [ValidateNotNullOrEmpty()] + [string]$EastLongitude, + + [Parameter(Mandatory = $false, + HelpMessage = 'return additional contact information')] + [switch]$Contact, + + [Parameter(Mandatory = $false, + HelpMessage = 'return additional atmosphere information')] + [switch]$Atmosphere, + + [Parameter(Mandatory = $false, + HelpMessage = 'The language in which to return results')] + [languages]$Language + ) + + Write-Debug -Message ($PSCmdlet.ParameterSetName) + + $uri = '{0}{1}' -f $googleMapsBaseURI, 'place/findplacefromtext/json?' + Write-Debug -Message ('Base function URI: {0}' -f $uri) + + $fQuery = 'input={0}' -f [uri]::EscapeDataString($Query) + $uri += $fQuery + + if ($Query -match '^\+\d+$') { + Write-Debug -Message 'Phone number input type' + $fInputType = '&inputtype=phonenumber' + } + else { + $fInputType = '&inputtype=textquery' + } + $uri += $fInputType + + switch ($PSCmdlet.ParameterSetName) { + 'Point' { + Write-Debug -Message 'Point specified' + $combinedPoint = ':{0},{1}' -f $PointLatitude, $PointLongitude + $fLocationBias = '&locationbias=point{0}' -f [uri]::EscapeDataString($combinedPoint) + $uri += $fLocationBias + } #point + 'Circle' { + Write-Debug -Message 'Circle specified' + $combinedCircle = ':{0}@{1},{2}' -f $CircleRadius, $CircleLatitude, $CircleLongitude + $fLocationBias = '&locationbias=circle{0}' -f [uri]::EscapeDataString($combinedCircle) + $uri += $fLocationBias + } #circle + 'Rectangle' { + Write-Debug -Message 'Rectangle specified' + $combinedRectangle = ':{0},{1}|{2},{3}' -f $SouthLatitude, $WestLongitude, $NorthLatitude, $EastLongitude + $fLocationBias = '&locationbias=rectangle{0}' -f [uri]::EscapeDataString($combinedRectangle) + $uri += $fLocationBias + } #rectangle + } #switch_parametersetname + + if ($Language) { + Write-Debug -Message ('Language: {0}' -f $Language) + $fLanguage = '&language={0}' -f $Language + $uri += $fLanguage + } + + $fFields = '&fields=' + $basicFields = 'business_status,formatted_address,geometry,icon,icon_mask_base_uri,icon_background_color,name,photo,place_id,plus_code,type' + $fFields += [uri]::EscapeDataString($basicFields) + if ($Contact) { + $contactFields = ',opening_hours' + $fFields += [uri]::EscapeDataString($contactFields) + } + if ($Atmosphere) { + $atmosphereFields = ',price_level,rating,user_ratings_total' + $fFields += [uri]::EscapeDataString($atmosphereFields) + } + $uri += $fFields + + Write-Verbose -Message ('Querying Google API: {0}' -f $uri) + + Write-Debug -Message 'Adding API key' + $fAPIKey = '&key={0}' -f $env:GoogleAPIKey + $uri += $fAPIKey + Write-Debug -Message ('Final URI: {0}' -f $uri) + + $invokeRestMethodSplat = @{ + Uri = $uri + ErrorAction = 'Stop' + } + try { + $results = Invoke-RestMethod @invokeRestMethodSplat + } + catch { + throw $_ + } + + if ($results.status -ne 'OK') { + Write-Warning -Message 'Did not get a succcessful return from Google Geocode API endpoint' + $finalResults = $results + } + else { + $finalResults = ($results.candidates | Format-GMapPlace) + } + + return $finalResults + +} #Find-GMapPlace diff --git a/src/pwshPlaces/Public/Get-GMapPlaceDetail.ps1 b/src/pwshPlaces/Public/Get-GMapPlaceDetail.ps1 new file mode 100644 index 0000000..99863a0 --- /dev/null +++ b/src/pwshPlaces/Public/Get-GMapPlaceDetail.ps1 @@ -0,0 +1,168 @@ +<# +.SYNOPSIS + Request more details about a particular establishment or point of interest +.DESCRIPTION + Place Details request returns more comprehensive information about the indicated place such as its complete address, phone number, website, user rating and reviews. +.EXAMPLE + Get-GMapPlaceDetail -PlaceID 'ChIJE43gTHK9XIYRleSxiXqF6GU' + + Returns detailed place information about provided place ID. +.EXAMPLE + Get-GMapPlaceDetail -PlaceID 'ChIJE43gTHK9XIYRleSxiXqF6GU' -Contact + + Returns detailed place information about provided place ID including detailed contact information. +.EXAMPLE + Get-GMapPlaceDetail -PlaceID 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' -Contact -Atmosphere -Language en + + Returns detailed place information about provided place ID including detailed contact, review, rating, and pricing information. Results are returned in English. +.EXAMPLE + $getGMapPlaceDetailsSplat = @{ + PlaceID = 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + Contact = $true + Atmosphere = $true + Language = 'en' + } + Get-GMapPlaceDetail @getGMapPlaceDetailsSplat + + Returns detailed place information about provided place ID including detailed contact, review, rating, and pricing information. Results are returned in English. +.PARAMETER PlaceID + A textual identifier that uniquely identifies a place +.PARAMETER Contact + Returns contact related information about the result - contact fields are billed at a higher rate. +.PARAMETER Atmosphere + Returns atmosphere related information including reviews and pricing about the result - atmosphere fields are billed at a higher rate. +.PARAMETER Language + The language in which to return results. +.PARAMETER RegionBias + The region code, specified as a ccTLD ("top-level domain") two-character value. +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + + Latitude and Longitude information can be easily retrieved using Invoke-GMapGeoCode + + If you provide faulty lat/long info the API call will default back to IP based locationbias. + + Required parameters + place_id + A textual identifier that uniquely identifies a place + Optional parameters + fields + Billing Categories + Basic - no charge + address_component, adr_address, business_status, formatted_address, geometry, icon, icon_mask_base_uri, icon_background_color, name, permanently_closed (deprecated), photo, place_id, plus_code, type, url, utc_offset, vicinity + Contact + formatted_phone_number, international_phone_number, opening_hours, website + Atmosphere + price_level, rating, review, user_ratings_total. + language + region + + Example: + https://maps.googleapis.com/maps/api/place/details/json?fields=name%2Crating%2Cformatted_phone_number&place_id=ChIJN1t_tDeuEmsRUsoyG83frY4&key=YOUR_API_KEY + + This function includes Google Maps features and content; use of Google Maps features and content is subject to the terms of service and Google privacy (linked below). +.COMPONENT + pwshPlaces +.LINK + https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Get-GMapPlaceDetail.md +.LINK + https://developers.google.com/maps/documentation/places/web-service/details +.LINK + https://developers.google.com/maps/faq#languagesupport +.LINK + https://cloud.google.com/maps-platform/terms/ +.LINK + https://www.google.com/policies/privacy/ +#> +function Get-GMapPlaceDetail { + [CmdletBinding( + PositionalBinding = $false, + DefaultParameterSetName = 'textquery')] + param ( + [Parameter(Mandatory = $true, + ParameterSetName = 'textquery', + HelpMessage = 'A textual identifier that uniquely identifies a place')] + [ValidateNotNullOrEmpty()] + [string]$PlaceID, + + [Parameter(Mandatory = $false, + HelpMessage = 'return additional contact information')] + [switch]$Contact, + + [Parameter(Mandatory = $false, + HelpMessage = 'return additional atmosphere information')] + [switch]$Atmosphere, + + [Parameter(Mandatory = $false, + HelpMessage = 'The language in which to return results')] + [languages]$Language, + + [Parameter(Mandatory = $false, + HelpMessage = 'The region code, specified as a ccTLD')] + [ccTLD]$RegionBias + ) + + Write-Debug -Message ($PSCmdlet.ParameterSetName) + + $uri = '{0}{1}' -f $googleMapsBaseURI, 'place/details/json?' + Write-Debug -Message ('Base function URI: {0}' -f $uri) + + $fPlaceID = 'place_id={0}' -f $PlaceID + $uri += $fPlaceID + + if ($Language) { + Write-Debug -Message ('Language: {0}' -f $Language) + $fLanguage = '&language={0}' -f $Language + $uri += $fLanguage + } + + $fFields = '&fields=' + $basicFields = 'address_component,adr_address,business_status,formatted_address,geometry,icon,icon_mask_base_uri,icon_background_color,name,photo,place_id,plus_code,type,url,utc_offset,vicinity' + $fFields += [uri]::EscapeDataString($basicFields) + if ($Contact) { + $contactFields = ',formatted_phone_number,international_phone_number,opening_hours,website' + $fFields += [uri]::EscapeDataString($contactFields) + } + if ($Atmosphere) { + $atmosphereFields = ',price_level,rating,review,user_ratings_total' + $fFields += [uri]::EscapeDataString($atmosphereFields) + } + $uri += $fFields + + if ($RegionBias) { + Write-Debug -Message ('RegionBias: {0}' -f $RegionBias) + $fRegion = '®ion={0}' -f $RegionBias + $uri += $fRegion + } + + Write-Verbose -Message ('Querying Google API: {0}' -f $uri) + + Write-Debug -Message 'Adding API key' + $fAPIKey = '&key={0}' -f $env:GoogleAPIKey + $uri += $fAPIKey + Write-Debug -Message ('Final URI: {0}' -f $uri) + + $invokeRestMethodSplat = @{ + Uri = $uri + ErrorAction = 'Stop' + } + try { + $results = Invoke-RestMethod @invokeRestMethodSplat + } + catch { + throw $_ + } + + if ($results.status -ne 'OK') { + Write-Warning -Message 'Did not get a succcessful return from Google Geocode API endpoint' + $finalResults = $results + } + else { + $finalResults = ($results.result | Format-GMapPlaceDetail) + } + + return $finalResults + +} #Get-GMapPlaceDetail diff --git a/src/pwshPlaces/Public/Get-HelloWorld.ps1 b/src/pwshPlaces/Public/Get-HelloWorld.ps1 deleted file mode 100644 index 98cfa06..0000000 --- a/src/pwshPlaces/Public/Get-HelloWorld.ps1 +++ /dev/null @@ -1,33 +0,0 @@ -<# -.SYNOPSIS - Short description -.DESCRIPTION - Long description -.EXAMPLE - C:\PS> - Example of how to use this cmdlet -.EXAMPLE - C:\PS> - Another example of how to use this cmdlet -.PARAMETER InputObject - Specifies the object to be processed. You can also pipe the objects to this command. -.OUTPUTS - Output from this cmdlet (if any) -.NOTES - General notes -.COMPONENT - pwshPlaces -#> -function Get-HelloWorld { - [CmdletBinding()] - param ( - # [Parameter(Mandatory = $true, - # HelpMessage = 'Helpful Message')] - # [ValidateNotNull()] - # [ValidateNotNullOrEmpty()] - # [string]$YourParameter - ) - $dayOfWeek = Get-Day # Get-Day is a private function - $message = "Hello, happy $dayOfWeek World!" - return $message -} #Get-HelloWorld diff --git a/src/pwshPlaces/Public/Invoke-GMapGeoCode.ps1 b/src/pwshPlaces/Public/Invoke-GMapGeoCode.ps1 new file mode 100644 index 0000000..e5092a1 --- /dev/null +++ b/src/pwshPlaces/Public/Invoke-GMapGeoCode.ps1 @@ -0,0 +1,186 @@ +<# +.SYNOPSIS + Engages Geocoding API to return address and geographic coordinates based on provided query parameters. +.DESCRIPTION + Geocoding is the process of converting addresses addresses (like "1600 Amphitheatre Parkway, Mountain View, CA") into geographic coordinates. + This function can take in an address and return coordinate information. + You can also provide coordinates to return multiple nearby address results. + If you know the exact google placeID this can also be provided to return Geocoding information about that location. +.EXAMPLE + Invoke-GMapGeoCode -Address '148 S Castell Ave, New Braunfels, TX 78130, United States' + + Performs Geocoding (latitude/longitude lookup) on provided address. +.EXAMPLE + Invoke-GMapGeoCode -Latitude '29.7012853' -Longitude '-98.1250235' + + Performs Reverse geocoding (address lookup) on provided coordinates and can return multiple address results. +.EXAMPLE + Invoke-GMapGeoCode -Latitude '37.621313' -Longitude '-122.378955' -Language es + + Performs Reverse geocoding (address lookup) on provided coordinates and can return multiple address results in Spanish. +.EXAMPLE + Invoke-GMapGeoCode -PlaceID 'ChIJK34phme9XIYRqstHW_gHr2w' + + Returns Geocoding information about the provided place. +.PARAMETER Address + The street address or plus code that you want to geocode. Specify addresses in accordance with the format used by the national postal service of the country concerned. Additional address elements such as business names and unit, suite or floor numbers should be avoided. +.PARAMETER Latitude + Geographic coordinate that specifies the north–south position of a point on the Earth's surface. +.PARAMETER Longitude + Geographic coordinate that specifies the east–west position of a point on the Earths surface. +.PARAMETER PlaceID + The place ID of the place for which you wish to obtain the human-readable address. The place ID is a unique identifier that can be used with other Google APIs. +.PARAMETER Language + The language in which to return results. +.PARAMETER RegionBias + The region code, specified as a ccTLD ("top-level domain") two-character value. This parameter will only influence, not fully restrict, results from the geocoder. +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + + This function does not support pipeline input because of this issue: + https://github.com/PowerShell/PowerShell/issues/10188 + + LAT LONG LOOKUP + Required parameters + address + key + Optional parameters + bounds + language + region + components + Example: + https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=YOUR_API_KEY + Reverse geocoding (address lookup) + Required parameters + latlng + key + Optional parameters + language + result_type + location_type + Example: + https://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&key=YOUR_API_KEY + + This function includes Google Maps features and content; use of Google Maps features and content is subject to the terms of service and Google privacy (linked below). +.COMPONENT + pwshPlaces +.LINK + https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Invoke-GMapGeoCode.md +.LINK + https://developers.google.com/maps/documentation/geocoding/overview +.LINK + https://maps.googleapis.com/maps/api/geocode/outputFormat?parameters +.LINK + https://developers.google.com/maps/documentation/geocoding/overview#geocoding-lookup +.LINK + https://developers.google.com/maps/documentation/geocoding/overview#ReverseGeocoding +.LINK + https://developers.google.com/maps/faq#languagesupport +.LINK + https://cloud.google.com/maps-platform/terms/ +.LINK + https://www.google.com/policies/privacy/ +#> +function Invoke-GMapGeoCode { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, + ParameterSetName = 'Address', + HelpMessage = 'The street address or plus code that you want to geocode')] + [ValidateNotNullOrEmpty()] + [string]$Address, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Location', + HelpMessage = 'Geographic coordinate that specifies the north–south position of a point on the Earths surface')] + [ValidateNotNullOrEmpty()] + [string]$Latitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Location', + HelpMessage = 'Geographic coordinate that specifies the east–west position of a point on the Earths surface')] + [ValidateNotNullOrEmpty()] + [string]$Longitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'PlaceID', + HelpMessage = 'The place ID of the place for which you wish to obtain the human-readable address')] + [ValidateNotNullOrEmpty()] + [string]$PlaceID, + + [Parameter(Mandatory = $false, + HelpMessage = 'The language in which to return results')] + [languages]$Language, + + [Parameter(Mandatory = $false, + HelpMessage = 'The region code, specified as a ccTLD')] + [ccTLD]$RegionBias + ) + + $uri = '{0}{1}' -f $googleMapsBaseURI, 'geocode/json?' + Write-Debug -Message ('Base function URI: {0}' -f $uri) + + switch ($PSCmdlet.ParameterSetName) { + 'Address' { + Write-Debug -Message 'Address specified' + $fAddress = 'address={0}' -f [uri]::EscapeDataString($address) + $uri += $fAddress + } #address + 'Location' { + Write-Debug -Message 'Location specified' + $combinedLatLong = '{0},{1}' -f $Latitude, $Longitude + $fLatLong = 'latlng={0}' -f [uri]::EscapeDataString($combinedLatLong) + $uri += $fLatLong + } #location + 'PlaceID' { + Write-Debug -Message 'PlaceID specified' + $fPlaceID = 'place_id={0}' -f $PlaceID + $uri += $fPlaceID + } #placeID + } #switch_parametersetname + + if ($Language) { + Write-Debug -Message ('Language: {0}' -f $Language) + $fLanguage = '&language={0}' -f $Language + $uri += $fLanguage + } + if ($RegionBias) { + Write-Debug -Message ('RegionBias: {0}' -f $RegionBias) + $fRegion = '®ion={0}' -f $RegionBias + $uri += $fRegion + } + + Write-Verbose -Message ('Querying Google API: {0}' -f $uri) + + Write-Debug -Message 'Adding API key' + $fAPIKey = '&key={0}' -f $env:GoogleAPIKey + $uri += $fAPIKey + Write-Debug -Message ('Final URI: {0}' -f $uri) + + $invokeRestMethodSplat = @{ + Uri = $uri + ErrorAction = 'Stop' + } + try { + $results = Invoke-RestMethod @invokeRestMethodSplat + } + catch { + throw $_ + } + + if ($results.status -ne 'OK') { + Write-Warning -Message 'Did not get a succcessful return from Google Geocode API endpoint' + $finalResults = $results + } + else { + $finalResults = ($results.results | Format-GMapGeoCode) + # $finalResults = $results.results + # $finalResults = (Format-GMapGeoCode -Results $Results.results) + } + + return $finalResults + +} #Invoke-GMapGeoCode diff --git a/src/pwshPlaces/Public/Search-GMapNearbyPlace.ps1 b/src/pwshPlaces/Public/Search-GMapNearbyPlace.ps1 new file mode 100644 index 0000000..abce373 --- /dev/null +++ b/src/pwshPlaces/Public/Search-GMapNearbyPlace.ps1 @@ -0,0 +1,327 @@ +<# +.SYNOPSIS + Nearby Search lets you search for places within a specified area. You can refine your search request by supplying keywords, type of place you are searching for and other parameters. +.DESCRIPTION + Performs a nearby search request with provided parameters. + Nearby search is useful for finding places near a specific geographic location. + By default 20 results are returned from a standard search. + You can increase this to a maximum of 60 places results by providing the AllSearchResults switch. +.EXAMPLE + Search-GMapNearbyPlace -Latitude '29.7049806' -Longitude '-98.068343' -Radius 5000 + + Performs a nearby search and returns all places types near provided coordinates within a range of 5000 meters. +.EXAMPLE + Search-GMapNearbyPlace -Latitude '29.7049806' -Longitude '-98.068343' -Radius 10000 -RankByProminence -Keyword 'butcher' -Type store + + Performs a nearby search and returns all store place types that match the keyword of butcher within the specified geographic range. +.EXAMPLE + Search-GMapNearbyPlace -Latitude '38.9072' -Longitude '-77.0369' -Radius 10000 -RankByProminence -Type embassy -AllSearchResults + + Performs a nearby search and returns all embassy place types near provided coordinates within a range of 10000 meters. The maximum of 60 places results is returned. +.EXAMPLE + Search-GMapNearbyPlace -Latitude '29.7013856' -Longitude '-98.1249258' -Radius 1000 -Type restaurant -MinPrice 1 -MaxPrice 3 + + Performs a nearby search and returns only restaurants places near provided coordinates within a range of 1000 meters. Restaurant will be in the cheap to moderately expensive price range. +.EXAMPLE + Search-GMapNearbyPlace -Latitude '29.7049806' -Longitude '-98.068343' -RankByDistance + + Performs a nearby search and returns all places types near provided coordinates ranked by distance from the coordinates. +.EXAMPLE + Search-GMapNearbyPlace -Latitude '26.1202' -Longitude '127.7025' -Radius 10000 -RankByProminence -Type amusement_park -Language en + + Performs a nearby search and returns only amusement parks places near provided coordinates within a range of 10000 meters. Results are ranked by prominence and returned in Engish. +.EXAMPLE + Search-GMapNearbyPlace -Latitude '29.7049806' -Longitude '-98.068343' -Radius 5000 -RankByProminence -Keyword 'pasta' -Type restaurant -Language en -OpenNow -MaxPrice 4 -MinPrice 2 -AllSearchResults + + Performs a nearby search and returns only restaurants places near provided coordinates that match the keyword of pasta within a range of 5000 meters. Restaurant will be in the moderately expensive to expensive price range. Only places that are currently opened are returned. Results will be returned in English. +.EXAMPLE + $searchGMapNearbyPlaceSplat = @{ + Latitude = '29.7049806' + Longitude = '-98.068343' + Radius = 5000 + RankByProminence = $true + Keyword = 'pasta' + Type = 'restaurant' + Language = 'en' + OpenNow = $true + MaxPrice = 4 + MinPrice = 2 + AllSearchResults = $true + } + Search-GMapNearbyPlace @searchGMapNearbyPlaceSplat + + Performs a nearby search and returns only restaurants places near provided coordinates that match the keyword of pasta within a range of 5000 meters. Restaurant will be in the moderately expensive to expensive price range. Only places that are currently opened are returned. Results will be returned in English. +.PARAMETER Latitude + Geographic coordinate that specifies the north–south position of a point on the Earth's surface. +.PARAMETER Longitude + Geographic coordinate that specifies the east–west position of a point on the Earths surface. +.PARAMETER Radius + Distance (in meters) within which to return place results. Instructs the Places service to prefer showing results within that circle; results outside of the defined area may still be displayed. +.PARAMETER RankByProminence + This option sorts results based on their importance. +.PARAMETER RankByDistance + This option biases search results in ascending order by their distance from the specified location. +.PARAMETER Keyword + A term to be matched against all content that Google has indexed for this place, including but not limited to name and type, as well as customer reviews and other third-party content. Note that explicitly including location information using this parameter may conflict with the location, radius, and rankby parameters, causing unexpected results. +.PARAMETER Type + Restricts the results to places matching the specified type. +.PARAMETER Language + The language in which to return results. +.PARAMETER OpenNow + Returns only those places that are open for business at the time the query is sent. +.PARAMETER MaxPrice + Restricts results to only those places within the specified range. Valid values range between 0 (most affordable) to 4 (most expensive), inclusive. +.PARAMETER MinPrice + Restricts results to only those places within the specified range. Valid values range between 0 (most affordable) to 4 (most expensive), inclusive. +.PARAMETER AllSearchResults + By default 20 results are returned from a standard search. Using this switch increases the search results from 20 to the maximum of 60. This does increase the number of API calls. +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + + Latitude and Longitude information can be easily retrieved using Invoke-GMapGeoCode + + Required parameters + location + This must be specified as latitude,longitude. + Optional parameters + keyword + language + maxprice + minprice + name + opennow + radius + rankby + type + sessiontoken + + Example: 'https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522%2C151.1957362&radius=1500&type=restaurant&keyword=cruise&key=YOUR_API_KEY' + + Nearby Search and Text Search return all of the available data fields for the selected place (a subset of the supported fields), and you will be billed accordingly There is no way to constrain Nearby Search or Text Search to only return specific fields. To keep from requesting (and paying for) data that you don't need, use a Find Place request instead. + + Use of the AllSearchResults parameter does increase the number of API calls. + + This function includes Google Maps features and content; use of Google Maps features and content is subject to the terms of service and Google privacy (linked below). +.COMPONENT + pwshPlaces +.LINK + https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Search-GMapNearbyPlace.md +.LINK + https://developers.google.com/maps/documentation/places/web-service/search-nearby +.LINK + https://maps.googleapis.com/maps/api/place/nearbysearch/output?parameters +.LINK + https://developers.google.com/maps/faq#languagesupport +.LINK + https://cloud.google.com/maps-platform/terms/ +.LINK + https://www.google.com/policies/privacy/ +#> +function Search-GMapNearbyPlace { + [CmdLetBinding( + DefaultParameterSetName = 'Location')] + param ( + [Parameter(Mandatory = $true, + ParameterSetName = 'Location', + HelpMessage = 'Geographic coordinate that specifies the north–south position of a point on the Earths surface')] + [Parameter(ParameterSetName = 'Area', Mandatory = $true)] + [Parameter(ParameterSetName = 'Distance', Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string]$Latitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Location', + HelpMessage = 'Geographic coordinate that specifies the east–west position of a point on the Earths surface')] + [Parameter(ParameterSetName = 'Area', Mandatory = $true)] + [Parameter(ParameterSetName = 'Distance', Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string]$Longitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Area', + HelpMessage = 'Distance (in meters) within which to return place results')] + [Parameter(ParameterSetName = 'Location', Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string]$Radius, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Area', + HelpMessage = 'This option sorts results based on their importance')] + # [Parameter(ParameterSetName = 'Location', Mandatory = $false)] + [switch]$RankByProminence, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Distance', + HelpMessage = 'This option biases search results in ascending order by their distance from the specified location')] + # [Parameter(ParameterSetName = 'Location', Mandatory = $false)] + [switch]$RankByDistance, + + [Parameter(Mandatory = $false, + HelpMessage = 'A term to be matched against all content that Google has indexed for this place')] + [ValidateNotNullOrEmpty()] + [string]$Keyword, + + [Parameter(Mandatory = $false, + HelpMessage = 'Restricts the results to places matching the specified type')] + [placeTypes]$Type, + + [Parameter(Mandatory = $false, + HelpMessage = 'The language in which to return results')] + [languages]$Language, + + [Parameter(Mandatory = $false, + HelpMessage = 'Returns only those places that are open for business at the time the query is sent')] + [switch]$OpenNow, + + [Parameter(Mandatory = $false, + HelpMessage = 'Restricts results to only those places within the specified range')] + [ValidateNotNullOrEmpty()] + [string]$MaxPrice, + + [Parameter(Mandatory = $false, + HelpMessage = 'Restricts results to only those places within the specified range')] + [ValidateNotNullOrEmpty()] + [string]$MinPrice, + + [Parameter(Mandatory = $false, + HelpMessage = 'TBD')] + [switch]$AllSearchResults + ) + + $uri = '{0}{1}' -f $googleMapsBaseURI, 'place/nearbysearch/json?' + Write-Debug -Message ('Base function URI: {0}' -f $uri) + + $combinedPoint = '{0},{1}' -f $Latitude, $Longitude + $fLocation = 'location={0}' -f [uri]::EscapeDataString($combinedPoint) + $uri += $fLocation + + if ($Radius) { + Write-Debug -Message ('Radius: {0}' -f $Radius) + $fRadius = '&radius={0}' -f $Radius + $uri += $fRadius + } + + if ($Keyword) { + Write-Debug -Message ('Keyword: {0}' -f $Keyword) + $fKeyword = '&keyword={0}' -f $Keyword + $uri += $fKeyword + } + + if ($Type) { + Write-Debug -Message ('Type: {0}' -f $Type) + $fType = '&type={0}' -f $Type + $uri += $fType + } + + if ($Language) { + Write-Debug -Message ('Language: {0}' -f $Language) + $fLanguage = '&language={0}' -f $Language + $uri += $fLanguage + } + + if ($OpenNow) { + $cOpenNow = 'openNow:true' + $fOpenNow = '&{0}' -f [uri]::EscapeDataString($cOpenNow) + $uri += $fOpenNow + } + + if ($RankByProminence) { + $fRankBy = '&rankby=prominence' + $uri += $fRankBy + } + + if ($RankByDistance) { + $fRankBy = '&rankby=distance' + $uri += $fRankBy + } + + if ($MaxPrice) { + Write-Debug -Message ('MaxPrice: {0}' -f $MaxPrice) + $fMaxPrice = '&maxprice={0}' -f $MaxPrice + $uri += $fMaxPrice + } + + if ($MinPrice) { + Write-Debug -Message ('MinPrice: {0}' -f $MinPrice) + $fMinPrice = '&minprice={0}' -f $MinPrice + $uri += $fMinPrice + } + + Write-Verbose -Message ('Querying Google API: {0}' -f $uri) + + Write-Debug -Message 'Adding API key' + $fAPIKey = '&key={0}' -f $env:GoogleAPIKey + $uri += $fAPIKey + Write-Debug -Message ('Final URI: {0}' -f $uri) + + $allresults = [System.Collections.ArrayList]::new() + + $invokeRestMethodSplat = @{ + Uri = $uri + ErrorAction = 'Stop' + } + try { + $results = Invoke-RestMethod @invokeRestMethodSplat + } + catch { + throw $_ + } + + if ($results.status -eq 'OK' -and $AllSearchResults) { + $results.results | ForEach-Object { + [void]$allresults.Add($_) + } + $i = 0 + $pageToken = $results.next_page_token + while ($null -ne $pageToken) { + Write-Debug -Message ('Run # - {0}' -f $i) + #_________________________________________________________________________ + # reconstruct URI for pagetoken use + $loopURI = 'https://maps.googleapis.com/maps/api/place/nearbysearch/json?' + $loopURI += 'pagetoken={0}' -f $pageToken + $loopURI += $fAPIKey + #_________________________________________________________________________ + <# + There is a short delay between when a next_page_token is issued, and when it will become valid. + Requesting the next page before it is available will return an INVALID_REQUEST response. + This sleep is necessary. the api backend needs time to catch up. + #> + Start-Sleep -Seconds 4 + #_________________________________________________________________________ + # resets + $results = $null + $pageToken = $null + #_________________________________________________________________________ + $invokeRestMethodSplat = @{ + Uri = $loopURI + ErrorAction = 'Stop' + } + try { + $results = Invoke-RestMethod @invokeRestMethodSplat + } + catch { + throw $_ + } + #_________________________________________________________________________ + $pageToken = $results.next_page_token + $results.results | ForEach-Object { + [void]$allresults.Add($_) + } + $i++ + #_________________________________________________________________________ + } + $finalResults = $allresults | Format-GMapNearbyPlace + } + elseif ($results.status -ne 'OK' ) { + Write-Warning -Message 'Did not get a succcessful return from Google Geocode API endpoint' + $finalResults = $results + } + else { + $finalResults = ($results.results | Format-GMapNearbyPlace) + } + + return $finalResults + +} #Search-GMapNearbyPlace diff --git a/src/pwshPlaces/Public/Search-GMapText.ps1 b/src/pwshPlaces/Public/Search-GMapText.ps1 new file mode 100644 index 0000000..8017874 --- /dev/null +++ b/src/pwshPlaces/Public/Search-GMapText.ps1 @@ -0,0 +1,353 @@ +<# +.SYNOPSIS + A text search that returns information about a set of places based on provided string. +.DESCRIPTION + Text based search for finding places based on a provided string and optional parameters. + Text search is especially useful for making ambiguous queries when searching for places. + Returned results can be heavily biased based on factors such as including a location in + the query iteself, or by providing direct location information in optional parameters. + By default 20 results are returned from a standard search. + You can increase this to a maximum of 60 places results by providing the AllSearchResults switch. +.EXAMPLE + Search-GMapText -Query "Krause's Cafe" + + Performs a text search with the provided query. Since no address or location information is provided places results are biased by your IP location. +.EXAMPLE + Search-GMapText -Query "Cupcakes" -Type bakery -AllSearchResults + + Performs a text search with the provided query and returns places that are classified as type: bakery. Since no address or location information is provided places results are biased by your IP location. +.EXAMPLE + Search-GMapText -Query "pizza restaurants in New York" + + Performs a text search with the provided query. Since a location is provided in the query, places results will be biased by that location. +.EXAMPLE + Search-GMapText -Query "Airport" -RegionBias es + + Performs a text search with the provided query. Places results are biased to the region of Spain. +.EXAMPLE + Search-GMapText -Query "italian restaurants in New York" -MinPrice 4 + + Performs a text search with the provided query and returns expensive restaraunt options. Since a location is provided in the query, places results will be biased by that location. +.EXAMPLE + Search-GMapText -Query "main plaza New Braunfels" -Type restaurant + + Performs a text search with the provided query and returns only restaurants. Since a location is provided in the query, places results will be biased by that location. +.EXAMPLE + Search-GMapText -Query 'Cafe' -Latitude '26.1202' -Longitude '127.7025' -Radius 5000 -Language en + + Performs a text search with the provided query. Results are returned based on the provided coordiantes within a 5000 meter range. Places results are returned in English. +.EXAMPLE + Search-GMapText -Query 'Coco' -Latitude '26.1202' -Longitude '127.7025' -Radius 5000 -Language en -Type restaurant + + Performs a text search with the provided query. Only restaurant places are returned. Results are returned based on the provided coordiantes within a 5000 meter range. Places results are returned in English. +.EXAMPLE + Search-GMapText -Query 'Coco' -Latitude '26.1202' -Longitude '127.7025' -Radius 500 -RankByProminence + + Performs a text search with the provided query. Results are returned based on the provided coordiantes within a 500 meter range. Places results are ranked by their prominence. +.EXAMPLE + Search-GMapText -Query 'Coco' -Latitude '26.1202' -Longitude '127.7025' -RankByDistance -Type restaurant + + Performs a text search with the provided query. Only restaurant places are returned. Results are returned based on the provided coordiantes and are ranked by their distance from the coordinates. +.EXAMPLE + Search-GMapText -Query 'Coco' -Latitude '26.1202' -Longitude '127.7025' -RankByDistance -Type restaurant -Language en -OpenNow -MinPrice 1 -MaxPrice 2 -AllSearchResults + + Performs a text search with the provided query. Only restaurant places are returned. Results are returned based on the provided coordiantes and are ranked by their distance from the coordinates. Places data is returned in English. Results with a cheap to moderate price are returned. Only restaraunts that are currently open are returned. The maximum of 60 places results is returned. +.EXAMPLE + $searchGMapTextSplat = @{ + Query = 'Coco' + Latitude = '26.1202' + Longitude = '127.7025' + RankByDistance = $true + Type = 'restaurant' + Language = 'en' + OpenNow = $true + MinPrice = 1 + MaxPrice = 2 + AllSearchResults = $true + } + Search-GMapText @searchGMapTextSplat + + Performs a text search with the provided query. Only restaurant places are returned. Results are returned based on the provided coordiantes and are ranked by their distance from the coordinates. Places data is returned in English. Results with a cheap to moderate price are returned. Only restaraunts that are currently open are returned. The maximum of 60 places results is returned. +.PARAMETER Query + Text string on which to search +.PARAMETER Latitude + Geographic coordinate that specifies the north–south position of a point on the Earth's surface. +.PARAMETER Longitude + Geographic coordinate that specifies the east–west position of a point on the Earths surface. +.PARAMETER Radius + Distance (in meters) within which to return place results. Instructs the Places service to prefer showing results within that circle; results outside of the defined area may still be displayed. +.PARAMETER RankByProminence + This option sorts results based on their importance. +.PARAMETER RankByDistance + This option biases search results in ascending order by their distance from the specified location. +.PARAMETER Type + Restricts the results to places matching the specified type. +.PARAMETER Language + The language in which to return results. +.PARAMETER RegionBias + The region code, specified as a ccTLD ("top-level domain") two-character value. This parameter will only influence, not fully restrict, results from the geocoder. +.PARAMETER OpenNow + Returns only those places that are open for business at the time the query is sent. +.PARAMETER MaxPrice + Restricts results to only those places within the specified range. Valid values range between 0 (most affordable) to 4 (most expensive), inclusive. +.PARAMETER MinPrice + Restricts results to only those places within the specified range. Valid values range between 0 (most affordable) to 4 (most expensive), inclusive. +.PARAMETER AllSearchResults + By default 20 results are returned from a standard search. Using this switch increases the search results from 20 to the maximum of 60. This does increase the number of API calls. +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + + Latitude and Longitude information can be easily retrieved using Invoke-GMapGeoCode + + Required parameters + query + Optional parameters + language + location + maxprice + minprice + opennow + radius + region + type + + Example: 'https://maps.googleapis.com/maps/api/place/textsearch/json?query=restaurants%20in%20Sydney&key=YOUR_API_KEY' + + Nearby Search and Text Search return all of the available data fields for the selected place (a subset of the supported fields), and you will be billed accordingly There is no way to constrain Nearby Search or Text Search to only return specific fields. To keep from requesting (and paying for) data that you don't need, use a Find Place request instead. + + Use of the AllSearchResults parameter does increase the number of API calls. + + This function includes Google Maps features and content; use of Google Maps features and content is subject to the terms of service and Google privacy (linked below). +.COMPONENT + pwshPlaces +.LINK + https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Search-GMapText.md +.LINK + https://developers.google.com/maps/documentation/places/web-service/search-text +.LINK + https://maps.googleapis.com/maps/api/place/textsearch/output?parameters +.LINK + https://developers.google.com/maps/faq#languagesupport +.LINK + https://cloud.google.com/maps-platform/terms/ +.LINK + https://www.google.com/policies/privacy/ +#> +function Search-GMapText { + [CmdletBinding( + DefaultParameterSetName = 'textquery')] + param ( + [Parameter(Mandatory = $true, + ParameterSetName = 'textquery', + HelpMessage = 'Text string on which to search')] + [Parameter(ParameterSetName = 'Location', Mandatory = $false)] + [Parameter(ParameterSetName = 'Area', Mandatory = $false)] + [Parameter(ParameterSetName = 'Distance', Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [string]$Query, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Location', + HelpMessage = 'Geographic coordinate that specifies the north–south position of a point on the Earths surface')] + [Parameter(ParameterSetName = 'Area', Mandatory = $false)] + [Parameter(ParameterSetName = 'Distance', Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [string]$Latitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Location', + HelpMessage = 'Geographic coordinate that specifies the east–west position of a point on the Earths surface')] + [Parameter(ParameterSetName = 'Area', Mandatory = $false)] + [Parameter(ParameterSetName = 'Distance', Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [string]$Longitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Area', + HelpMessage = 'Distance (in meters) within which to return place results')] + [ValidateNotNullOrEmpty()] + [string]$Radius, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Area', + HelpMessage = 'This option sorts results based on their importance')] + [switch]$RankByProminence, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Distance', + HelpMessage = 'This option biases search results in ascending order by their distance from the specified location')] + [switch]$RankByDistance, + + [Parameter(Mandatory = $false, + HelpMessage = 'Restricts the results to places matching the specified type')] + [placeTypes]$Type, + + [Parameter(Mandatory = $false, + HelpMessage = 'The language in which to return results')] + [languages]$Language, + + [Parameter(Mandatory = $false, + HelpMessage = 'The region code, specified as a ccTLD')] + [ccTLD]$RegionBias, + + [Parameter(Mandatory = $false, + HelpMessage = 'Returns only those places that are open for business at the time the query is sent')] + [switch]$OpenNow, + + [Parameter(Mandatory = $false, + HelpMessage = 'Restricts results to only those places within the specified range')] + [ValidateNotNullOrEmpty()] + [string]$MaxPrice, + + [Parameter(Mandatory = $false, + HelpMessage = 'Restricts results to only those places within the specified range')] + [ValidateNotNullOrEmpty()] + [string]$MinPrice, + + [Parameter(Mandatory = $false, + HelpMessage = 'By default 20 results are returned from a standard search. Using this switch increases the search results from 20 to the maximum of 60')] + [switch]$AllSearchResults + ) + + $uri = '{0}{1}' -f $googleMapsBaseURI, 'place/textsearch/json?' + Write-Debug -Message ('Base function URI: {0}' -f $uri) + + $fQuery = 'query={0}' -f [uri]::EscapeDataString($Query) + $uri += $fQuery + + if ($Latitude -and $Longitude) { + $combinedPoint = '{0},{1}' -f $Latitude, $Longitude + $fLocation = '&location={0}' -f [uri]::EscapeDataString($combinedPoint) + $uri += $fLocation + } + + if ($Radius) { + Write-Debug -Message ('Radius: {0}' -f $Radius) + $fRadius = '&radius={0}' -f $Radius + $uri += $fRadius + } + + if ($Type) { + Write-Debug -Message ('Type: {0}' -f $Type) + $fType = '&type={0}' -f $Type + $uri += $fType + } + + if ($Language) { + Write-Debug -Message ('Language: {0}' -f $Language) + $fLanguage = '&language={0}' -f $Language + $uri += $fLanguage + } + + if ($RegionBias) { + Write-Debug -Message ('RegionBias: {0}' -f $RegionBias) + $fRegion = '®ion={0}' -f $RegionBias + $uri += $fRegion + } + + if ($OpenNow) { + $cOpenNow = 'openNow:true' + $fOpenNow = '&{0}' -f [uri]::EscapeDataString($cOpenNow) + $uri += $fOpenNow + } + + if ($RankByProminence) { + $fRankBy = '&rankby=prominence' + $uri += $fRankBy + } + + if ($RankByDistance) { + $fRankBy = '&rankby=distance' + $uri += $fRankBy + } + + if ($MaxPrice) { + Write-Debug -Message ('MaxPrice: {0}' -f $MaxPrice) + $fMaxPrice = '&maxprice={0}' -f $MaxPrice + $uri += $fMaxPrice + } + + if ($MinPrice) { + Write-Debug -Message ('MinPrice: {0}' -f $MinPrice) + $fMinPrice = '&minprice={0}' -f $MinPrice + $uri += $fMinPrice + } + + Write-Verbose -Message ('Querying Google API: {0}' -f $uri) + + Write-Debug -Message 'Adding API key' + $fAPIKey = '&key={0}' -f $env:GoogleAPIKey + $uri += $fAPIKey + Write-Debug -Message ('Final URI: {0}' -f $uri) + + $allresults = [System.Collections.ArrayList]::new() + + $invokeRestMethodSplat = @{ + Uri = $uri + ErrorAction = 'Stop' + } + try { + $results = Invoke-RestMethod @invokeRestMethodSplat + } + catch { + throw $_ + } + + if ($results.status -eq 'OK' -and $AllSearchResults) { + $results.results | ForEach-Object { + [void]$allresults.Add($_) + } + $i = 0 + $pageToken = $results.next_page_token + while ($null -ne $pageToken) { + Write-Debug -Message ('Run # - {0}' -f $i) + #_________________________________________________________________________ + # reconstruct URI for pagetoken use + $loopURI = 'https://maps.googleapis.com/maps/api/place/textsearch/json?' + $loopURI += 'pagetoken={0}' -f $pageToken + $loopURI += $fAPIKey + #_________________________________________________________________________ + <# + There is a short delay between when a next_page_token is issued, and when it will become valid. + Requesting the next page before it is available will return an INVALID_REQUEST response. + This sleep is necessary. the api backend needs time to catch up. + #> + Start-Sleep -Seconds 4 + #_________________________________________________________________________ + # resets + $results = $null + $pageToken = $null + #_________________________________________________________________________ + $invokeRestMethodSplat = @{ + Uri = $loopURI + ErrorAction = 'Stop' + } + try { + $results = Invoke-RestMethod @invokeRestMethodSplat + } + catch { + throw $_ + } + #_________________________________________________________________________ + $pageToken = $results.next_page_token + $results.results | ForEach-Object { + [void]$allresults.Add($_) + } + $i++ + #_________________________________________________________________________ + } + $finalResults = $allresults | Format-GMapPlaceText + } + elseif ($results.status -ne 'OK' ) { + Write-Warning -Message 'Did not get a succcessful return from Google Geocode API endpoint' + $finalResults = $results + } + else { + $finalResults = ($results.results | Format-GMapPlaceText) + } + + return $finalResults + +} #Search-GMapText diff --git a/src/pwshPlaces/pwshPlaces.psd1 b/src/pwshPlaces/pwshPlaces.psd1 index 9b8b8cc..bfa6dd0 100644 --- a/src/pwshPlaces/pwshPlaces.psd1 +++ b/src/pwshPlaces/pwshPlaces.psd1 @@ -1,7 +1,7 @@ # # Module manifest for module 'pwshPlaces' # -# Generated by: Jake Morrison +# Generated by: Jake Morrison - @jakemorrison - https://www.techthoughts.info # # Generated on: 09/11/21 # @@ -12,7 +12,7 @@ RootModule = 'pwshPlaces.psm1' # Version number of this module. - ModuleVersion = '0.0.2' + ModuleVersion = '0.5.0' # Supported PSEditions # CompatiblePSEditions = @() @@ -24,7 +24,7 @@ Author = 'Jake Morrison' # Company or vendor of this module - CompanyName = 'Unknown' + CompanyName = 'TechThoughts' # Copyright statement for this module Copyright = '(c) Jake Morrison. All rights reserved.' @@ -70,7 +70,11 @@ # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. FunctionsToExport = @( - 'Get-HelloWorld' + 'Find-GMapPlace' + 'Get-GMapPlaceDetail' + 'Invoke-GMapGeoCode' + 'Search-GMapNearbyPlace' + 'Search-GMapText' ) # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. @@ -97,19 +101,43 @@ PSData = @{ # Tags applied to this module. These help with module discovery in online galleries. - # Tags = @() + Tags = @( + 'API', + 'Area', + 'Atmosphere', + 'Contact', + 'Find', + 'FindPlace', + 'Geo', + 'Geolocation', + 'Google', + 'GoogleMaps', + 'GMap', + 'GMaps', + 'Latitude', + 'Longitude', + 'Location', + 'Place', + 'Places', + 'Map', + 'Maps', + 'Rating', + 'Ratings', + 'Search', + 'SearchPlace' + ) # A URL to the license for this module. # LicenseUri = '' # A URL to the main website for this project. - ProjectUri = 'https://github.com/techthoughts2/pwshPlaces' + ProjectUri = 'https://github.com/techthoughts2/pwshPlaces' # A URL to an icon representing this module. # IconUri = '' # ReleaseNotes of this module - # ReleaseNotes = '' + ReleaseNotes = 'https://github.com/techthoughts2/pwshPlaces/blob/master/.github/CHANGELOG.md' # Prerelease string of this module # Prerelease = '' From e4a9116ed193957b894ea63366eace3a902cd05e Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sun, 3 Oct 2021 23:17:33 -0500 Subject: [PATCH 03/22] path adjustment --- .github/workflows/wf_Linux.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/wf_Linux.yml b/.github/workflows/wf_Linux.yml index 68b2071..d81a78d 100644 --- a/.github/workflows/wf_Linux.yml +++ b/.github/workflows/wf_Linux.yml @@ -6,8 +6,7 @@ # https://github.com/actions/upload-artifact#where-does-the-upload-go name: pwshPlaces-Linux-Build on: [push, pull_request] - paths: - - 'src/**' + paths-ignore: - '!docs/**' - '!media/**' - '!README.md' From 963382b9660ce37761450e2dd14f3d4bf5d16fde Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sun, 3 Oct 2021 23:21:43 -0500 Subject: [PATCH 04/22] adjusted workflows --- .github/workflows/wf_Linux.yml | 19 ++++++++++++------- .github/workflows/wf_MacOS.yml | 19 +++++++++++-------- .github/workflows/wf_Windows.yml | 19 +++++++++++-------- .github/workflows/wf_Windows_Core.yml | 19 +++++++++++-------- 4 files changed, 45 insertions(+), 31 deletions(-) diff --git a/.github/workflows/wf_Linux.yml b/.github/workflows/wf_Linux.yml index d81a78d..ffc954b 100644 --- a/.github/workflows/wf_Linux.yml +++ b/.github/workflows/wf_Linux.yml @@ -5,13 +5,18 @@ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions # https://github.com/actions/upload-artifact#where-does-the-upload-go name: pwshPlaces-Linux-Build -on: [push, pull_request] - paths-ignore: - - '!docs/**' - - '!media/**' - - '!README.md' - - '!LICENSE' - - '!.github' +on: + push: + paths-ignore: + - '**.md' + - 'media/**' + - 'LICENSE' + pull_request: + paths-ignore: + - '**.md' + - 'media/**' + - 'LICENSE' + jobs: test: name: Run Tests diff --git a/.github/workflows/wf_MacOS.yml b/.github/workflows/wf_MacOS.yml index b369187..03746da 100644 --- a/.github/workflows/wf_MacOS.yml +++ b/.github/workflows/wf_MacOS.yml @@ -5,14 +5,17 @@ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions # https://github.com/actions/upload-artifact#where-does-the-upload-go name: pwshPlaces-MacOS-Build -on: [push, pull_request] - paths: - - 'src/**' - - '!docs/**' - - '!media/**' - - '!README.md' - - '!LICENSE' - - '!.github' +on: + push: + paths-ignore: + - '**.md' + - 'media/**' + - 'LICENSE' + pull_request: + paths-ignore: + - '**.md' + - 'media/**' + - 'LICENSE' jobs: test: name: Run Tests diff --git a/.github/workflows/wf_Windows.yml b/.github/workflows/wf_Windows.yml index 0bb3480..3340eee 100644 --- a/.github/workflows/wf_Windows.yml +++ b/.github/workflows/wf_Windows.yml @@ -5,14 +5,17 @@ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions # https://github.com/actions/upload-artifact#where-does-the-upload-go name: pwshPlaces-Windows-Build -on: [push, pull_request] - paths: - - 'src/**' - - '!docs/**' - - '!media/**' - - '!README.md' - - '!LICENSE' - - '!.github' +on: + push: + paths-ignore: + - '**.md' + - 'media/**' + - 'LICENSE' + pull_request: + paths-ignore: + - '**.md' + - 'media/**' + - 'LICENSE' jobs: test: name: Run Tests diff --git a/.github/workflows/wf_Windows_Core.yml b/.github/workflows/wf_Windows_Core.yml index 530d175..e01f73f 100644 --- a/.github/workflows/wf_Windows_Core.yml +++ b/.github/workflows/wf_Windows_Core.yml @@ -5,14 +5,17 @@ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions # https://github.com/actions/upload-artifact#where-does-the-upload-go name: pwshPlaces-Windows-pwsh-Build -on: [push, pull_request] - paths: - - 'src/**' - - '!docs/**' - - '!media/**' - - '!README.md' - - '!LICENSE' - - '!.github' +on: + push: + paths-ignore: + - '**.md' + - 'media/**' + - 'LICENSE' + pull_request: + paths-ignore: + - '**.md' + - 'media/**' + - 'LICENSE' jobs: test: name: Run Tests From e5d070785386479382e2c965daaede67ea373262 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sun, 3 Oct 2021 23:30:22 -0500 Subject: [PATCH 05/22] adjusted invoke for actions --- .github/workflows/wf_Linux.yml | 2 +- .github/workflows/wf_MacOS.yml | 2 +- .github/workflows/wf_Windows.yml | 2 +- .github/workflows/wf_Windows_Core.yml | 2 +- README.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/wf_Linux.yml b/.github/workflows/wf_Linux.yml index ffc954b..ff26d63 100644 --- a/.github/workflows/wf_Linux.yml +++ b/.github/workflows/wf_Linux.yml @@ -37,7 +37,7 @@ jobs: run: ./actions_bootstrap.ps1 - name: Test and Build shell: pwsh - run: Invoke-Build -File .\src\tbd.build.ps1 + run: Invoke-Build -File .\src\pwshPlaces.build.ps1 - name: Upload pester results uses: actions/upload-artifact@v2 with: diff --git a/.github/workflows/wf_MacOS.yml b/.github/workflows/wf_MacOS.yml index 03746da..21b5a7e 100644 --- a/.github/workflows/wf_MacOS.yml +++ b/.github/workflows/wf_MacOS.yml @@ -36,7 +36,7 @@ jobs: run: ./actions_bootstrap.ps1 - name: Test and Build shell: pwsh - run: Invoke-Build -File .\src\tbd.build.ps1 + run: Invoke-Build -File .\src\pwshPlaces.build.ps1 - name: Upload pester results uses: actions/upload-artifact@v2 with: diff --git a/.github/workflows/wf_Windows.yml b/.github/workflows/wf_Windows.yml index 3340eee..926e45c 100644 --- a/.github/workflows/wf_Windows.yml +++ b/.github/workflows/wf_Windows.yml @@ -42,7 +42,7 @@ jobs: run: ./actions_bootstrap.ps1 - name: Test and Build shell: powershell - run: Invoke-Build -File .\src\tbd.build.ps1 + run: Invoke-Build -File .\src\pwshPlaces.build.ps1 - name: Upload pester results uses: actions/upload-artifact@v2 with: diff --git a/.github/workflows/wf_Windows_Core.yml b/.github/workflows/wf_Windows_Core.yml index e01f73f..2c7f6f0 100644 --- a/.github/workflows/wf_Windows_Core.yml +++ b/.github/workflows/wf_Windows_Core.yml @@ -36,7 +36,7 @@ jobs: run: ./actions_bootstrap.ps1 - name: Test and Build shell: pwsh - run: Invoke-Build -File .\src\tbd.build.ps1 + run: Invoke-Build -File .\src\pwshPlaces.build.ps1 - name: Upload pester results uses: actions/upload-artifact@v2 with: diff --git a/README.md b/README.md index a6ba0a7..05c858d 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Branch | Windows - PowerShell | Windows - pwsh | Linux | MacOS --- | --- | --- | --- | --- | main | ![Build Status Windows PowerShell main](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-Windows-PowerShell/badge.svg?branch=main) | ![Build Status Windows pwsh main](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-Windows-pwsh/badge.svg?branch=main) | ![Build Status Linux main](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-Linux/badge.svg?branch=main) | ![Build Status MacOS main](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-MacOS/badge.svg?branch=main) -dev | ![Build Status Windows PowerShell dev](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-Windows-PowerShell/badge.svg?branch=dev) | ![Build Status Windows pwsh dev](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-Windows-pwsh/badge.svg?branch=dev) | ![Build Status Linux dev](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-Linux/badge.svg?branch=dev) | ![Build Status MacOS dev](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-MacOS/badge.svg?branch=dev) +dev | [![Build Status Windows PowerShell dev](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Windows.yml/badge.svg?branch=dev)](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Windows.yml) | [![Build Status Windows pwsh dev](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Windows_Core.yml/badge.svg?branch=dev)](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Windows_Core.yml) | [![Build Status Linux dev](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Linux.yml/badge.svg?branch=dev)](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Linux.yml) | [![Build Status MacOS dev](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_MacOS.yml/badge.svg?branch=dev)](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_MacOS.yml) ## Synopsis From f9d403d32994e007d2dfca89a08723bb64db7f34 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sun, 3 Oct 2021 23:34:20 -0500 Subject: [PATCH 06/22] added google api secret retrieval --- .github/workflows/wf_Linux.yml | 3 +++ .github/workflows/wf_MacOS.yml | 3 +++ .github/workflows/wf_Windows.yml | 3 +++ .github/workflows/wf_Windows_Core.yml | 3 +++ 4 files changed, 12 insertions(+) diff --git a/.github/workflows/wf_Linux.yml b/.github/workflows/wf_Linux.yml index ff26d63..e518342 100644 --- a/.github/workflows/wf_Linux.yml +++ b/.github/workflows/wf_Linux.yml @@ -35,6 +35,9 @@ jobs: - name: Bootstrap shell: pwsh run: ./actions_bootstrap.ps1 + - name: Retrieve Google API Key + env: + GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Test and Build shell: pwsh run: Invoke-Build -File .\src\pwshPlaces.build.ps1 diff --git a/.github/workflows/wf_MacOS.yml b/.github/workflows/wf_MacOS.yml index 21b5a7e..0fe0a85 100644 --- a/.github/workflows/wf_MacOS.yml +++ b/.github/workflows/wf_MacOS.yml @@ -34,6 +34,9 @@ jobs: - name: Bootstrap shell: pwsh run: ./actions_bootstrap.ps1 + - name: Retrieve Google API Key + env: + GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Test and Build shell: pwsh run: Invoke-Build -File .\src\pwshPlaces.build.ps1 diff --git a/.github/workflows/wf_Windows.yml b/.github/workflows/wf_Windows.yml index 926e45c..1be40ad 100644 --- a/.github/workflows/wf_Windows.yml +++ b/.github/workflows/wf_Windows.yml @@ -40,6 +40,9 @@ jobs: - name: Bootstrap shell: powershell run: ./actions_bootstrap.ps1 + - name: Retrieve Google API Key + env: + GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Test and Build shell: powershell run: Invoke-Build -File .\src\pwshPlaces.build.ps1 diff --git a/.github/workflows/wf_Windows_Core.yml b/.github/workflows/wf_Windows_Core.yml index 2c7f6f0..e2efb62 100644 --- a/.github/workflows/wf_Windows_Core.yml +++ b/.github/workflows/wf_Windows_Core.yml @@ -34,6 +34,9 @@ jobs: - name: Bootstrap shell: pwsh run: ./actions_bootstrap.ps1 + - name: Retrieve Google API Key + env: + GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Test and Build shell: pwsh run: Invoke-Build -File .\src\pwshPlaces.build.ps1 From f6e22f9059b8927a07cb79f9ace906f0f48b6677 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sun, 3 Oct 2021 23:35:55 -0500 Subject: [PATCH 07/22] adjusted env tab --- .github/workflows/wf_Linux.yml | 4 ++-- .github/workflows/wf_MacOS.yml | 4 ++-- .github/workflows/wf_Windows.yml | 4 ++-- .github/workflows/wf_Windows_Core.yml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/wf_Linux.yml b/.github/workflows/wf_Linux.yml index e518342..0de0115 100644 --- a/.github/workflows/wf_Linux.yml +++ b/.github/workflows/wf_Linux.yml @@ -36,8 +36,8 @@ jobs: shell: pwsh run: ./actions_bootstrap.ps1 - name: Retrieve Google API Key - env: - GoogleAPIKey: ${{ secrets.GoogleAPIKey }} + env: + GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Test and Build shell: pwsh run: Invoke-Build -File .\src\pwshPlaces.build.ps1 diff --git a/.github/workflows/wf_MacOS.yml b/.github/workflows/wf_MacOS.yml index 0fe0a85..6a6a6f8 100644 --- a/.github/workflows/wf_MacOS.yml +++ b/.github/workflows/wf_MacOS.yml @@ -35,8 +35,8 @@ jobs: shell: pwsh run: ./actions_bootstrap.ps1 - name: Retrieve Google API Key - env: - GoogleAPIKey: ${{ secrets.GoogleAPIKey }} + env: + GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Test and Build shell: pwsh run: Invoke-Build -File .\src\pwshPlaces.build.ps1 diff --git a/.github/workflows/wf_Windows.yml b/.github/workflows/wf_Windows.yml index 1be40ad..f3d4aba 100644 --- a/.github/workflows/wf_Windows.yml +++ b/.github/workflows/wf_Windows.yml @@ -41,8 +41,8 @@ jobs: shell: powershell run: ./actions_bootstrap.ps1 - name: Retrieve Google API Key - env: - GoogleAPIKey: ${{ secrets.GoogleAPIKey }} + env: + GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Test and Build shell: powershell run: Invoke-Build -File .\src\pwshPlaces.build.ps1 diff --git a/.github/workflows/wf_Windows_Core.yml b/.github/workflows/wf_Windows_Core.yml index e2efb62..78ffbb5 100644 --- a/.github/workflows/wf_Windows_Core.yml +++ b/.github/workflows/wf_Windows_Core.yml @@ -35,8 +35,8 @@ jobs: shell: pwsh run: ./actions_bootstrap.ps1 - name: Retrieve Google API Key - env: - GoogleAPIKey: ${{ secrets.GoogleAPIKey }} + env: + GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Test and Build shell: pwsh run: Invoke-Build -File .\src\pwshPlaces.build.ps1 From 6abc348121023004b83930cd57acf20c102b2dbf Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sun, 3 Oct 2021 23:38:14 -0500 Subject: [PATCH 08/22] added shell reference --- .github/workflows/wf_Linux.yml | 1 + .github/workflows/wf_MacOS.yml | 1 + .github/workflows/wf_Windows.yml | 1 + .github/workflows/wf_Windows_Core.yml | 1 + 4 files changed, 4 insertions(+) diff --git a/.github/workflows/wf_Linux.yml b/.github/workflows/wf_Linux.yml index 0de0115..5619739 100644 --- a/.github/workflows/wf_Linux.yml +++ b/.github/workflows/wf_Linux.yml @@ -36,6 +36,7 @@ jobs: shell: pwsh run: ./actions_bootstrap.ps1 - name: Retrieve Google API Key + shell: pwsh env: GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Test and Build diff --git a/.github/workflows/wf_MacOS.yml b/.github/workflows/wf_MacOS.yml index 6a6a6f8..279a3e8 100644 --- a/.github/workflows/wf_MacOS.yml +++ b/.github/workflows/wf_MacOS.yml @@ -35,6 +35,7 @@ jobs: shell: pwsh run: ./actions_bootstrap.ps1 - name: Retrieve Google API Key + shell: pwsh env: GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Test and Build diff --git a/.github/workflows/wf_Windows.yml b/.github/workflows/wf_Windows.yml index f3d4aba..8bfbb28 100644 --- a/.github/workflows/wf_Windows.yml +++ b/.github/workflows/wf_Windows.yml @@ -41,6 +41,7 @@ jobs: shell: powershell run: ./actions_bootstrap.ps1 - name: Retrieve Google API Key + shell: powershell env: GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Test and Build diff --git a/.github/workflows/wf_Windows_Core.yml b/.github/workflows/wf_Windows_Core.yml index 78ffbb5..d2ae919 100644 --- a/.github/workflows/wf_Windows_Core.yml +++ b/.github/workflows/wf_Windows_Core.yml @@ -35,6 +35,7 @@ jobs: shell: pwsh run: ./actions_bootstrap.ps1 - name: Retrieve Google API Key + shell: pwsh env: GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Test and Build From 08df4026f8658782952fccbe205540e3e71e62f6 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sun, 3 Oct 2021 23:43:29 -0500 Subject: [PATCH 09/22] moved secret retrieval --- .github/workflows/wf_Linux.yml | 6 ++---- .github/workflows/wf_MacOS.yml | 6 ++---- .github/workflows/wf_Windows.yml | 6 ++---- .github/workflows/wf_Windows_Core.yml | 6 ++---- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/.github/workflows/wf_Linux.yml b/.github/workflows/wf_Linux.yml index 5619739..a2153b8 100644 --- a/.github/workflows/wf_Linux.yml +++ b/.github/workflows/wf_Linux.yml @@ -35,13 +35,11 @@ jobs: - name: Bootstrap shell: pwsh run: ./actions_bootstrap.ps1 - - name: Retrieve Google API Key - shell: pwsh - env: - GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Test and Build shell: pwsh run: Invoke-Build -File .\src\pwshPlaces.build.ps1 + env: + GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Upload pester results uses: actions/upload-artifact@v2 with: diff --git a/.github/workflows/wf_MacOS.yml b/.github/workflows/wf_MacOS.yml index 279a3e8..6455302 100644 --- a/.github/workflows/wf_MacOS.yml +++ b/.github/workflows/wf_MacOS.yml @@ -34,13 +34,11 @@ jobs: - name: Bootstrap shell: pwsh run: ./actions_bootstrap.ps1 - - name: Retrieve Google API Key - shell: pwsh - env: - GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Test and Build shell: pwsh run: Invoke-Build -File .\src\pwshPlaces.build.ps1 + env: + GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Upload pester results uses: actions/upload-artifact@v2 with: diff --git a/.github/workflows/wf_Windows.yml b/.github/workflows/wf_Windows.yml index 8bfbb28..95fe7ae 100644 --- a/.github/workflows/wf_Windows.yml +++ b/.github/workflows/wf_Windows.yml @@ -40,13 +40,11 @@ jobs: - name: Bootstrap shell: powershell run: ./actions_bootstrap.ps1 - - name: Retrieve Google API Key - shell: powershell - env: - GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Test and Build shell: powershell run: Invoke-Build -File .\src\pwshPlaces.build.ps1 + env: + GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Upload pester results uses: actions/upload-artifact@v2 with: diff --git a/.github/workflows/wf_Windows_Core.yml b/.github/workflows/wf_Windows_Core.yml index d2ae919..43aaaab 100644 --- a/.github/workflows/wf_Windows_Core.yml +++ b/.github/workflows/wf_Windows_Core.yml @@ -34,13 +34,11 @@ jobs: - name: Bootstrap shell: pwsh run: ./actions_bootstrap.ps1 - - name: Retrieve Google API Key - shell: pwsh - env: - GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Test and Build shell: pwsh run: Invoke-Build -File .\src\pwshPlaces.build.ps1 + env: + GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - name: Upload pester results uses: actions/upload-artifact@v2 with: From 7cfce8c105ad16786095474511345cdb46df2930 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Mon, 4 Oct 2021 21:05:42 -0500 Subject: [PATCH 10/22] adjusted for legacy count --- README.md | 2 +- docs/pwshPlaces.md | 2 +- .../Infrastructure/pwshPlaces-Infra.Tests.ps1 | 16 ++++++++-------- src/Tests/Unit/Public/Find-GMapPlace.Tests.ps1 | 2 +- .../Unit/Public/Get-GMapPlaceDetail.Tests.ps1 | 2 +- .../Unit/Public/Invoke-GMapGeoCode.Tests.ps1 | 2 +- .../Unit/Public/Search-GMapNearbyPlace.Tests.ps1 | 2 +- src/Tests/Unit/Public/Search-GMapText.Tests.ps1 | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 05c858d..15c0762 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Branch | Windows - PowerShell | Windows - pwsh | Linux | MacOS --- | --- | --- | --- | --- | -main | ![Build Status Windows PowerShell main](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-Windows-PowerShell/badge.svg?branch=main) | ![Build Status Windows pwsh main](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-Windows-pwsh/badge.svg?branch=main) | ![Build Status Linux main](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-Linux/badge.svg?branch=main) | ![Build Status MacOS main](https://github.com/techthoughts2/pwshPlaces/workflows/pwshPlaces-MacOS/badge.svg?branch=main) +main | [![Build Status Windows PowerShell main](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Windows.yml/badge.svg?branch=main)](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Windows.yml) | [![Build Status Windows pwsh main](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Windows_Core.yml/badge.svg?branch=main)](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Windows_Core.yml) | [![Build Status Linux main](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Linux.yml/badge.svg?branch=main)](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Linux.yml) | [![Build Status MacOS main](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_MacOS.yml/badge.svg?branch=main)](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_MacOS.yml) dev | [![Build Status Windows PowerShell dev](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Windows.yml/badge.svg?branch=dev)](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Windows.yml) | [![Build Status Windows pwsh dev](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Windows_Core.yml/badge.svg?branch=dev)](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Windows_Core.yml) | [![Build Status Linux dev](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Linux.yml/badge.svg?branch=dev)](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_Linux.yml) | [![Build Status MacOS dev](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_MacOS.yml/badge.svg?branch=dev)](https://github.com/techthoughts2/pwshPlaces/actions/workflows/wf_MacOS.yml) ## Synopsis diff --git a/docs/pwshPlaces.md b/docs/pwshPlaces.md index a51e941..28ab228 100644 --- a/docs/pwshPlaces.md +++ b/docs/pwshPlaces.md @@ -2,7 +2,7 @@ Module Name: pwshPlaces Module Guid: 9a9914bd-d115-4f42-bb5d-19c5e5561a3f Download Help Link: NA -Help Version: 0.0.9 +Help Version: 0.5.0 Locale: en-US --- diff --git a/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 b/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 index 10c87aa..b583e49 100644 --- a/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 +++ b/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 @@ -23,10 +23,10 @@ Describe 'Infrastructure Tests' -Tag Infrastructure { Language = 'en' } $eval = Find-GMapPlace @findGMapPlaceSplat - $eval.place_id | Should -BeExactly 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' - $eval.name | Should -BeExactly "Krause's Cafe" - $eval.Open | Should -Not -BeNullOrEmpty - $eval.rating | Should -Not -BeNullOrEmpty + $eval.place_id | Should -BeExactly 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' + $eval.name | Should -BeExactly "Krause's Cafe" + $eval.Open | Should -Not -BeNullOrEmpty + $eval.rating | Should -Not -BeNullOrEmpty Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) } #it } #context_Find-GMapPlace @@ -59,12 +59,12 @@ Describe 'Infrastructure Tests' -Tag Infrastructure { Context 'Invoke-GMapGeoCode' { It 'should return the expected results for lat long lookup' { $eval = Invoke-GMapGeoCode -Address '148 S Castell Ave, New Braunfels, TX 78130, USA' - $eval.place_id.Count | Should -BeGreaterOrEqual 1 + ($eval.place_id | Measure-Object).Count | Should -BeGreaterOrEqual 1 Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) } #it It 'should return the expected results for reverse geocoding' { $eval = Invoke-GMapGeoCode -Latitude '29.7012853' -Longitude '-98.1250235' - $eval.place_id.Count | Should -BeGreaterThan 1 + ($eval.place_id | Measure-Object).Count | Should -BeGreaterOrEqual 1 Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) } #it It 'should return expected results for place lookup' { @@ -92,7 +92,7 @@ Describe 'Infrastructure Tests' -Tag Infrastructure { AllSearchResults = $true } $eval = Search-GMapNearbyPlace @searchGMapNearbyPlaceSplat - $eval.place_id.Count | Should -BeGreaterOrEqual 20 + ($eval.place_id | Measure-Object).Count | Should -BeGreaterOrEqual 2 Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) } #it } #context_Search-GMapNearbyPlace @@ -111,7 +111,7 @@ Describe 'Infrastructure Tests' -Tag Infrastructure { AllSearchResults = $true } $eval = Search-GMapText @searchGMapTextSplat - $eval.place_id.Count | Should -BeGreaterOrEqual 20 + ($eval.place_id | Measure-Object).Count | Should -BeGreaterOrEqual 20 } #it } #context_Search-GMapText } #context_GoogleMaps diff --git a/src/Tests/Unit/Public/Find-GMapPlace.Tests.ps1 b/src/Tests/Unit/Public/Find-GMapPlace.Tests.ps1 index 42b0feb..4539f01 100644 --- a/src/Tests/Unit/Public/Find-GMapPlace.Tests.ps1 +++ b/src/Tests/Unit/Public/Find-GMapPlace.Tests.ps1 @@ -51,7 +51,7 @@ InModuleScope 'pwshPlaces' { It 'should return expected results if no issues are encountered' { $eval = Find-GMapPlace -Query 'cafe' -PointLatitude '29.7049806' -PointLongitude '-98.068343' - $eval.Count | Should -BeExactly 1 + ($eval | Measure-Object).Count | Should -BeExactly 1 $eval[0].Latitude | Should -BeExactly '29.7013856' $eval[0].Longitude | Should -BeExactly '-98.1249258' } #it diff --git a/src/Tests/Unit/Public/Get-GMapPlaceDetail.Tests.ps1 b/src/Tests/Unit/Public/Get-GMapPlaceDetail.Tests.ps1 index df373a3..5b50270 100644 --- a/src/Tests/Unit/Public/Get-GMapPlaceDetail.Tests.ps1 +++ b/src/Tests/Unit/Public/Get-GMapPlaceDetail.Tests.ps1 @@ -51,7 +51,7 @@ InModuleScope 'pwshPlaces' { It 'should return expected results if no issues are encountered' { $eval = Get-GMapPlaceDetail -PlaceID 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' - $eval.Count | Should -BeExactly 1 + ($eval | Measure-Object).Count | Should -BeExactly 1 $eval.place_id | Should -BeExactly 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' $eval.name | Should -BeExactly 'Krause''s Cafe' $eval.website | Should -BeExactly 'https://www.krausescafe.com/' diff --git a/src/Tests/Unit/Public/Invoke-GMapGeoCode.Tests.ps1 b/src/Tests/Unit/Public/Invoke-GMapGeoCode.Tests.ps1 index 74d247b..d8648fb 100644 --- a/src/Tests/Unit/Public/Invoke-GMapGeoCode.Tests.ps1 +++ b/src/Tests/Unit/Public/Invoke-GMapGeoCode.Tests.ps1 @@ -54,7 +54,7 @@ InModuleScope 'pwshPlaces' { $geoLatLong } #endMock $eval = Invoke-GMapGeoCode -Latitude '29.7012853' -Longitude '-98.1250235' -Language 'en' -RegionBias 'us' - $eval.Count | Should -BeExactly 2 + ($eval | Measure-Object).Count | Should -BeExactly 2 $eval[0].Latitude | Should -BeExactly '29.7012853' $eval[0].Longitude | Should -BeExactly '-98.1250235' } #it diff --git a/src/Tests/Unit/Public/Search-GMapNearbyPlace.Tests.ps1 b/src/Tests/Unit/Public/Search-GMapNearbyPlace.Tests.ps1 index 5beeb11..89c9907 100644 --- a/src/Tests/Unit/Public/Search-GMapNearbyPlace.Tests.ps1 +++ b/src/Tests/Unit/Public/Search-GMapNearbyPlace.Tests.ps1 @@ -85,7 +85,7 @@ InModuleScope 'pwshPlaces' { It 'should return expected results if no issues are encountered' { $eval = Search-GMapNearbyPlace -Latitude '29.7049806' -Longitude '-98.068343' -RankByDistance - $eval.Count | Should -BeExactly 2 + ($eval | Measure-Object).Count | Should -BeExactly 2 $eval[0].Latitude | Should -BeExactly '29.7013856' $eval[0].Longitude | Should -BeExactly '-98.1249258' } #it diff --git a/src/Tests/Unit/Public/Search-GMapText.Tests.ps1 b/src/Tests/Unit/Public/Search-GMapText.Tests.ps1 index 1301138..df1aecf 100644 --- a/src/Tests/Unit/Public/Search-GMapText.Tests.ps1 +++ b/src/Tests/Unit/Public/Search-GMapText.Tests.ps1 @@ -85,7 +85,7 @@ InModuleScope 'pwshPlaces' { It 'should return expected results if no issues are encountered' { $eval = Search-GMapText -Query 'Coco' -Latitude '26.1202' -Longitude '127.7025' -RankByDistance -Type restaurant - $eval.Count | Should -BeExactly 2 + ($eval | Measure-Object).Count | Should -BeExactly 2 $eval[0].Latitude | Should -BeExactly '29.7013856' $eval[0].Longitude | Should -BeExactly '-98.1249258' } #it From b0d4cc409ea442b1a6516730ddc1d71640679112 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Thu, 7 Oct 2021 12:31:12 -0500 Subject: [PATCH 11/22] added first bing function --- .github/workflows/wf_Linux.yml | 2 + .github/workflows/wf_MacOS.yml | 2 + .github/workflows/wf_Windows.yml | 2 + .github/workflows/wf_Windows_Core.yml | 2 + .vscode/tasks.json | 6 + bing.ps1 | 48 ++++ docs/BingMapsAPI.md | 160 ++++++++++++ docs/Invoke-BingGeoCode.md | 247 ++++++++++++++++++ docs/pwshPlaces-FAQ.md | 6 + docs/pwshPlaces.md | 5 +- media/bin_map_create_api_key.PNG | Bin 0 -> 55892 bytes .../bing_map_create_bing_maps_dev_account.PNG | Bin 0 -> 44148 bytes media/bing_maps_api_usage_report.PNG | Bin 0 -> 62877 bytes media/create_bing_maps_api_key.PNG | Bin 0 -> 16338 bytes .../Infrastructure/pwshPlaces-Infra.Tests.ps1 | 14 + .../Unit/Private/Format-BingGeoCode.Tests.ps1 | 47 ++++ .../Unit/Private/Format-GMapGeoCode.Tests.ps1 | 2 +- .../Private/Format-GMapNearbyPlace.Tests.ps1 | 2 +- .../Unit/Private/Format-GMapPlace.Tests.ps1 | 2 +- .../Private/Format-GMapPlaceDetail.Tests.ps1 | 2 +- .../Private/Format-GMapPlaceText.Tests.ps1 | 2 +- .../Unit/Public/Find-GMapPlace.Tests.ps1 | 2 +- .../Unit/Public/Get-GMapPlaceDetail.Tests.ps1 | 2 +- .../Unit/Public/Invoke-BingGeoCode.Tests.ps1 | 83 ++++++ .../Unit/Public/Invoke-GMapGeoCode.Tests.ps1 | 4 +- .../Public/Search-GMapNearbyPlace.Tests.ps1 | 6 +- .../Unit/Public/Search-GMapText.Tests.ps1 | 6 +- src/Tests/Unit/TestObjects.psm1 | 104 +++++++- src/pwshPlaces.build.ps1 | 5 + src/pwshPlaces/Imports.ps1 | 129 ++++++++- src/pwshPlaces/Private/Format-BingGeoCode.ps1 | 116 ++++++++ src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 | 192 ++++++++++++++ src/pwshPlaces/pwshPlaces.psd1 | 3 +- 33 files changed, 1174 insertions(+), 29 deletions(-) create mode 100644 bing.ps1 create mode 100644 docs/BingMapsAPI.md create mode 100644 docs/Invoke-BingGeoCode.md create mode 100644 media/bin_map_create_api_key.PNG create mode 100644 media/bing_map_create_bing_maps_dev_account.PNG create mode 100644 media/bing_maps_api_usage_report.PNG create mode 100644 media/create_bing_maps_api_key.PNG create mode 100644 src/Tests/Unit/Private/Format-BingGeoCode.Tests.ps1 create mode 100644 src/Tests/Unit/Public/Invoke-BingGeoCode.Tests.ps1 create mode 100644 src/pwshPlaces/Private/Format-BingGeoCode.ps1 create mode 100644 src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 diff --git a/.github/workflows/wf_Linux.yml b/.github/workflows/wf_Linux.yml index a2153b8..073c323 100644 --- a/.github/workflows/wf_Linux.yml +++ b/.github/workflows/wf_Linux.yml @@ -40,6 +40,8 @@ jobs: run: Invoke-Build -File .\src\pwshPlaces.build.ps1 env: GoogleAPIKey: ${{ secrets.GoogleAPIKey }} + env: + BingAPIKey: ${{ secrets.BingAPIKey }} - name: Upload pester results uses: actions/upload-artifact@v2 with: diff --git a/.github/workflows/wf_MacOS.yml b/.github/workflows/wf_MacOS.yml index 6455302..03bd406 100644 --- a/.github/workflows/wf_MacOS.yml +++ b/.github/workflows/wf_MacOS.yml @@ -39,6 +39,8 @@ jobs: run: Invoke-Build -File .\src\pwshPlaces.build.ps1 env: GoogleAPIKey: ${{ secrets.GoogleAPIKey }} + env: + BingAPIKey: ${{ secrets.BingAPIKey }} - name: Upload pester results uses: actions/upload-artifact@v2 with: diff --git a/.github/workflows/wf_Windows.yml b/.github/workflows/wf_Windows.yml index 95fe7ae..e82626f 100644 --- a/.github/workflows/wf_Windows.yml +++ b/.github/workflows/wf_Windows.yml @@ -45,6 +45,8 @@ jobs: run: Invoke-Build -File .\src\pwshPlaces.build.ps1 env: GoogleAPIKey: ${{ secrets.GoogleAPIKey }} + env: + BingAPIKey: ${{ secrets.BingAPIKey }} - name: Upload pester results uses: actions/upload-artifact@v2 with: diff --git a/.github/workflows/wf_Windows_Core.yml b/.github/workflows/wf_Windows_Core.yml index 43aaaab..e3b5640 100644 --- a/.github/workflows/wf_Windows_Core.yml +++ b/.github/workflows/wf_Windows_Core.yml @@ -39,6 +39,8 @@ jobs: run: Invoke-Build -File .\src\pwshPlaces.build.ps1 env: GoogleAPIKey: ${{ secrets.GoogleAPIKey }} + env: + BingAPIKey: ${{ secrets.BingAPIKey }} - name: Upload pester results uses: actions/upload-artifact@v2 with: diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 9302d28..24cbc8f 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -124,6 +124,12 @@ "problemMatcher": "$msCompile", "command": "Invoke-Build -Task Build -File '${workspaceFolder}/src/pwshPlaces.build.ps1'" }, + { + "label": "BuildNoInfra", + "type": "shell", + "problemMatcher": "$msCompile", + "command": "Invoke-Build -Task BuildNoInfra -File '${workspaceFolder}/src/pwshPlaces.build.ps1'" + }, { "label": "InfraTest", "type": "shell", diff --git a/bing.ps1 b/bing.ps1 new file mode 100644 index 0000000..28317e1 --- /dev/null +++ b/bing.ps1 @@ -0,0 +1,48 @@ +# Bing Maps REST Services +<# +https://docs.microsoft.com/en-us/bingmaps/rest-services/ + +https://docs.microsoft.com/en-us/bingmaps/rest-services/getting-started-with-the-bing-maps-rest-services + +Bing Maps Locations API +https://docs.microsoft.com/en-us/bingmaps/rest-services/locations/ + +Bing Maps API Best Practices +https://docs.microsoft.com/en-us/bingmaps/getting-started/bing-maps-api-best-practices + +When a request is rate limited, the response will return no results. This may be confusing at +first as it looks like Bing Maps was unable to find results. To indicate that the request was rate +limited a flag is added to the header of the response (X-MS-BM-WS-INFO) which is set to the +value of 1 as documented the Status Codes and Error Handling page. +https://msdn.microsoft.com/en-us/library/ff701703.aspx + +Supported Culture Codes +https://docs.microsoft.com/en-us/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes + +The Bing Maps geocoder will attempt to find the closest match as possible to your query. In some cases, +it will not be able to find an exact match. This is where the match code parameter of the returned results +becomes useful. The match code parameter is an array of values and can have any combination of the following +three values; Good, Ambiguous, or UpHierarchy. If you are only interested in exact matches then keep a look +out for UpHierachy as this indicates that your exact query was not found but an upper level address value was found. + +REST services take your IP address into consideration when making a request +o help reduce this issue you can set the userIp parameter of the request to 127.0.0.1. +This will trick the service into thinking you are making the call from a local application +and cause it to ignore your IP address. + +Base URL Structure +https://docs.microsoft.com/en-us/bingmaps/rest-services/common-parameters-and-types/base-url-structure +https://dev.virtualearth.net/REST/version/restApi/resourcePath?queryParameters&key=BingMapsKey +http://dev.virtualearth.net/REST/v1/Locations?q=seattle&output=xml&key=BingMapsKey + +Limit your coordinates to 6 decimal places. +don’t encode coordinate based locations. + +Output Parameters + https://docs.microsoft.com/en-us/bingmaps/rest-services/common-parameters-and-types/output-parameters +Culture Parameter + https://docs.microsoft.com/en-us/bingmaps/rest-services/common-parameters-and-types/culture-parameter + &c= +User Context Parameters + https://docs.microsoft.com/en-us/bingmaps/rest-services/common-parameters-and-types/user-context-parameters +#> \ No newline at end of file diff --git a/docs/BingMapsAPI.md b/docs/BingMapsAPI.md new file mode 100644 index 0000000..4228aa8 --- /dev/null +++ b/docs/BingMapsAPI.md @@ -0,0 +1,160 @@ +# Bing Maps API + +***[pwshPlaces](https://github.com/techthoughts2/pwshPlaces)** includes Google Maps features and content; use of Google Maps features and content is subject to the [terms of service](https://www.microsoft.com/maps/product/terms.html) and [Microsoft privacy policy](https://privacy.microsoft.com/en-us/privacystatement).* + +https://blogs.bing.com/maps + +https://docs.microsoft.com/en-us/bingmaps/ + +- [Bing Maps API](#bing-maps-api) + - [Bing Maps API Key](#bing-maps-api-key) + - [How to get a Bing Maps API Key](#how-to-get-a-bing-maps-api-key) + - [1. Create a new GCP project](#1-create-a-new-gcp-project) + - [2. Enable the Places API and the Geocoding API](#2-enable-the-places-api-and-the-geocoding-api) + - [3. Create API Key](#3-create-api-key) + - [4. Restrict to places API](#4-restrict-to-places-api) + - [5. Enable Billing on the Google Cloud project](#5-enable-billing-on-the-google-cloud-project) + - [Monitoring Google Maps API usage](#monitoring-google-maps-api-usage) + - [Understanding Bing Maps API pricing](#understanding-bing-maps-api-pricing) + - [API Caching](#api-caching) + +Bing Maps API FAQ - https://www.microsoft.com/en-us/maps/faq + +https://www.bingmapsportal.com/Application + +## Bing Maps API Key + +https://www.microsoft.com/en-us/maps/create-a-bing-maps-key +Getting a Bing Maps Key + https://docs.microsoft.com/en-us/bingmaps/getting-started/bing-maps-dev-center-help/getting-a-bing-maps-key + +**[pwshPlaces](https://github.com/techthoughts2/pwshPlaces)** requires a Google API key to run Google maps functions. + +To utilize all of the functions of pwshPlaces you must: + +- Create a Google Maps API with both the Places and Geocoding APIs enabled and enable billing on the project. + +You can read more about the Google Maps API in the links below: + +https://docs.microsoft.com/en-us/bingmaps/getting-started/ + +- [Google Maps Platform Documentation](https://developers.google.com/maps/documentation#places) +- [Places API](https://developers.google.com/maps/documentation/places/web-service/overview) +- [Places API Support](https://developers.google.com/maps/documentation/places/web-service/support) + +### How to get a Bing Maps API Key + +button create api + +Prompted to create a Bing Maps Dev Center account, + +Yes, let's create a new account + + + + + +Official documentation link for creating a Google Maps API Key: + +- [Google Maps Creating API Keys](https://developers.google.com/maps/documentation/places/web-service/get-api-key#creating-api-keys) + +Google Maps API Keys are created and managed through Google Cloud Platform (GCP). The GCP console is constantly changing so some of the steps below may look slightly different. Here is what you need to accomplish at a high level: + +#### 1. Create a new GCP project + +Log into your [GCP console](https://console.cloud.google.com/home/) and create a new project: +![alt text](../media/gcp_new_project.PNG 'Title') + +#### 2. Enable the Places API and the Geocoding API + +- Top left Navigation Menu + - Other Google Solutions + - Google Maps Platform + - Maps APIs and Services + - Places API - --Enable-- +- Google Maps Platform + - APIs + - Additional APIs + - Geocoding API - --Enable-- + +![Google Cloud (GCP) Top Left Navigation Menu](../media/google_cloud_top_left_navigation_menu.PNG 'GCP Navigation Menu') +![Google Cloud (GCP) Google Maps Platform](../media/gcp_google_maps_platform.PNG 'GCP Google Maps Platform') +![Google Cloud (GCP) Google Maps Platform Maps APIs and Services](../media/google_maps_platform_maps_api_and_services.PNG 'Google Maps Platform Maps APIs and Services') +![Google Maps Places API](../media/gcp_enable_places_api.PNG 'Google Maps Places API') +![Google Maps Geocoding API](../media/gcp_enable_geocoding_api.PNG 'Google Maps Geocoding API') + +#### 3. Create API Key + +- Google Maps Platform + - Credentials + - Create Credentials + - API key + +![GCP Google Maps Platform Credentials](../media/gcp_google_maps_create_credential_api.PNG 'Google Maps Platform Credentials') + +#### 4. Restrict to places API + +Restrict API access to just the two enabled + +- Google Maps Platform + - Credentials + - Restrict API to secure account + +![GCP API Restrict Access](../media/gcp_api_services_restrict_api_key.PNG 'API Restrict Access') + +#### 5. Enable Billing on the Google Cloud project + +You must [enable billing](https://console.cloud.google.com/project/_/billing/enable) on the Google Cloud Project. + +-Note: Even though you need to enable billing keep in mind the following:- + +> For most of our users, the $200 monthly credit is enough to support their needs. You can also set daily quotas to protect against unexpected increases. + +### Monitoring Google Maps API usage + +Visit the [GCP API dashboard](https://console.developers.google.com/apis/dashboard). From the ‘Select a Project’ drop-down menu, select or create the project. + +Additional reading: + +- [Monitoring API usage](https://cloud.google.com/apis/docs/monitoring) +- [Monitor Google API usage programmatically?](https://stackoverflow.com/questions/62511759/monitor-google-api-usage-programmatically) + +### Understanding Bing Maps API pricing + +https://www.microsoft.com/maps/licensing/licensing.aspx +https://www.microsoft.com/en-us/maps/licensing/licensing-options + +- [Google Maps Platform pricing](https://cloud.google.com/maps-platform/pricing) +- [Places product API pricing](https://developers.google.com/maps/billing/gmp-billing#places-product) +- [Places API Usage and Billing](https://developers.google.com/maps/documentation/places/web-service/usage-and-billing) + - [Places SKU breakdown cost data](https://developers.google.com/maps/billing/gmp-billing#basic-data) + +## API Caching + +IAW with the [terms of service](https://cloud.google.com/maps-platform/terms/): + +> Pre-Fetching, Caching, or Storage of Content +Applications using the Places API are bound by the Google Maps Platform Terms of Service. Section 3.2.3(a) and (b) of the terms states that you must not pre-fetch, index, store, or cache any Content except under the limited conditions stated in the terms. +Note that the place ID, used to uniquely identify a place, is exempt from the caching restriction. You can therefore store place ID values indefinitely. The place ID is returned in the place_id field in Places API responses. + +This means that doing something like the following is not permitted: + +```powershell +#-------------------------------------------------------------- +# scrape and locally cache up to 60 local restaurants +Import-Module Convert +Import-Module pwshPlaces + +$scrapePath = $env:Temp + +$locale = Invoke-GMapGeoCode -Address 'New Braunfels' + +$areaRestaraunts = Search-GMapNearbyPlace -Latitude $locale.Latitude -Longitude $locale.Longitude -Radius 10000 -RankByProminence -Type restaurant -AllSearchResults + +ConvertTo-Clixml -InputObject $areaRestaraunts -Depth 100 | Out-File "$scrapePath\localRestaraunts.xml" +#-------------------------------------------------------------- +# where should we eat today? +$myLocalRestaurants = Get-Content -Path "$scrapePath\localRestaraunts.xml" -Raw | ConvertFrom-Clixml + +Get-Random $myLocalRestaurants +``` diff --git a/docs/Invoke-BingGeoCode.md b/docs/Invoke-BingGeoCode.md new file mode 100644 index 0000000..5875478 --- /dev/null +++ b/docs/Invoke-BingGeoCode.md @@ -0,0 +1,247 @@ +--- +external help file: pwshPlaces-help.xml +Module Name: pwshPlaces +online version: https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Invoke-BingGeoCode.md +schema: 2.0.0 +--- + +# Invoke-BingGeoCode + +## SYNOPSIS +Engages Bing Maps API to return address and geographic coordinates based on provided query parameters. + +## SYNTAX + +### Address +``` +Invoke-BingGeoCode -AddressLine -City -State -PostalCode [-Country ] + [-Language ] [-MaxResults ] [] +``` + +### Location +``` +Invoke-BingGeoCode -Latitude -Longitude [-Language ] [-MaxResults ] + [] +``` + +## DESCRIPTION +Geocoding is the process of converting addresses addresses (like "1600 Amphitheatre Parkway, Mountain View, CA") into geographic coordinates. +This function can take in an address and return coordinate information. +You can also provide coordinates to return multiple nearby address results. + +## EXAMPLES + +### EXAMPLE 1 +``` +Invoke-BingGeoCode -AddressLine '148 S Castell Ave' -City 'New Braunfels' -State TX -PostalCode 78130 +``` + +Performs Geocoding (latitude/longitude lookup) on provided address. + +### EXAMPLE 2 +``` +Invoke-BingGeoCode -Latitude '29.7030' -Longitude '-98.1245' +``` + +Performs Reverse geocoding (address lookup) on provided coordinates and can return multiple address results. + +### EXAMPLE 3 +``` +Invoke-BingGeoCode -AddressLine '148 S Castell Ave' -City 'New Braunfels' -State TX -PostalCode 78130 -Country us -Language en -MaxResults 20 +``` + +Performs Geocoding (latitude/longitude lookup) on provided address. +Results are biased to the United States country. +Results are returned in English. +Up to 20 results are returned. + +### EXAMPLE 4 +``` +$invokeBingGeoCodeSplat = @{ + AddressLine = '148 S Castell Ave' + City = 'New Braunfels' + State = 'TX' + PostalCode = 78130 + Country = 'us' + Language = 'en' + MaxResults = 20 +} +Invoke-BingGeoCode @invokeBingGeoCodeSplat +``` + +Performs Geocoding (latitude/longitude lookup) on provided address. +Results are biased to the United States country. +Results are returned in English. +Up to 20 results are returned. + +## PARAMETERS + +### -AddressLine +A string specifying the street line of an address. + +```yaml +Type: String +Parameter Sets: Address +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -City +The locality, such as the city or neighborhood, that corresponds to an address. + +```yaml +Type: String +Parameter Sets: Address +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -State +The subdivision name in the country or region for an address. +This element is typically treated as the first order administrative subdivision, but in some cases it is the second, third, or fourth order subdivision in a country, dependency, or region. +A string that contains a subdivision, such as the abbreviation of a US state. + +```yaml +Type: String +Parameter Sets: Address +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PostalCode +The post code, postal code, or ZIP Code of an address. + +```yaml +Type: String +Parameter Sets: Address +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Country +The ISO country code for the country. + +```yaml +Type: ccTLD +Parameter Sets: Address +Aliases: +Accepted values: ac, ad, ae, af, ag, ai, al, am, ao, aq, ar, as, at, au, aw, ax, az, ba, bb, bd, be, bf, bg, bh, bi, bj, bm, bn, bo, br, bs, bt, bv, bw, by, bz, ca, cc, cd, cf, cg, ch, ci, ck, cl, cm, cn, co, cr, cu, cv, cw, cx, cy, cz, de, dj, dk, dm, do, dz, ec, ee, eg, er, es, et, eu, fi, fj, fk, fm, fo, fr, ga, gb, gd, ge, gf, gg, gh, gi, gl, gm, gn, gp, gq, gr, gs, gt, gu, gw, gy, hk, hm, hn, hr, ht, hu, id, ie, il, im, in, io, iq, ir, is, it, je, jm, jo, jp, ke, kg, kh, ki, km, kn, kp, kr, kw, ky, kz, la, lb, lc, li, lk, lr, ls, lt, lu, lv, ly, ma, mc, md, me, mg, mh, mk, ml, mm, mn, mo, mp, mq, mr, ms, mt, mu, mv, mw, mx, my, mz, na, nc, ne, nf, ng, ni, nl, no, np, nr, nu, nz, om, pa, pe, pf, pg, ph, pk, pl, pm, pn, pr, ps, pt, pw, py, qa, re, ro, rs, ru, rw, sa, sb, sc, sd, se, sg, sh, si, sj, sk, sl, sm, sn, so, sr, ss, st, su, sv, sx, sy, sz, tc, td, tf, tg, th, tj, tk, tl, tm, tn, to, tr, tt, tv, tw, tz, ua, ug, uk, us, uy, uz, va, vc, ve, vg, vi, vn, vu, wf, ws, ye, yt, za, zm, zw + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Latitude +Geographic coordinate that specifies the north-south position of a point on the Earth's surface. + +```yaml +Type: String +Parameter Sets: Location +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Longitude +Geographic coordinate that specifies the east-west position of a point on the Earths surface. + +```yaml +Type: String +Parameter Sets: Location +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Language +The language in which to return results. + +```yaml +Type: languages +Parameter Sets: (All) +Aliases: +Accepted values: af, sq, am, ar, hy, az, eu, be, bn, bs, bg, my, ca, zh, hr, cs, da, nl, en, et, fa, fi, fil, fr, ka, de, el, iw, hi, hu, is, id, it, ja, kn, kk, km, ko, ky, lo, lv, lt, mk, ms, ml, mr, mn, ne, no, pl, pt, pa, ro, ru, sr, sk, es, sw, ta, te, th, uk, ur, uz, vi, zu + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -MaxResults +Specifies the maximum number of locations to return in the response. +If not specified the default is 5. + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### Output from this cmdlet (if any) +## NOTES +Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + +Example: + http://dev.virtualearth.net/REST/v1/Locations?countryRegion={countryRegion}&adminDistrict={adminDistrict}&locality={locality}&postalCode={postalCode}&addressLine={addressLine}&userLocation={userLocation}&userIp={userIp}&usermapView={usermapView}&includeNeighborhood={includeNeighborhood}&maxResults={maxResults}&key={BingMapsKey} + +## RELATED LINKS + +[https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Invoke-BingGeoCode.md](https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Invoke-BingGeoCode.md) + +[https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-address](https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-address) + +[https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-point](https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-point) + +[https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes](https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes) + +[https://www.microsoft.com/maps/product/terms.html](https://www.microsoft.com/maps/product/terms.html) + +[https://privacy.microsoft.com/en-us/privacystatement](https://privacy.microsoft.com/en-us/privacystatement) + diff --git a/docs/pwshPlaces-FAQ.md b/docs/pwshPlaces-FAQ.md index 0291826..ea10721 100644 --- a/docs/pwshPlaces-FAQ.md +++ b/docs/pwshPlaces-FAQ.md @@ -6,6 +6,12 @@ ## FAQs +Bing API + +Applications using up to 125,000 billable transactions per calendar year qualify for limited website and mobile app terms within the Bing Maps API Terms of Use. + +Less than 50,000 cumulative billable transactions with any 24-hour period + ### Do I need an API key us to use pwshPlaces Yes diff --git a/docs/pwshPlaces.md b/docs/pwshPlaces.md index 28ab228..735546d 100644 --- a/docs/pwshPlaces.md +++ b/docs/pwshPlaces.md @@ -2,7 +2,7 @@ Module Name: pwshPlaces Module Guid: 9a9914bd-d115-4f42-bb5d-19c5e5561a3f Download Help Link: NA -Help Version: 0.5.0 +Help Version: 0.5.1 Locale: en-US --- @@ -17,6 +17,9 @@ Find Place request takes a text input and returns a place. The input can be any ### [Get-GMapPlaceDetail](Get-GMapPlaceDetail.md) Request more details about a particular establishment or point of interest +### [Invoke-BingGeoCode](Invoke-BingGeoCode.md) +Engages Bing Maps API to return address and geographic coordinates based on provided query parameters. + ### [Invoke-GMapGeoCode](Invoke-GMapGeoCode.md) Engages Geocoding API to return address and geographic coordinates based on provided query parameters. diff --git a/media/bin_map_create_api_key.PNG b/media/bin_map_create_api_key.PNG new file mode 100644 index 0000000000000000000000000000000000000000..753f200ea5aee47b3d8572d5895e83d538d18344 GIT binary patch literal 55892 zcmd42cT`i|*DgvE6jV?^M5G9U(iN26M4B{_-cjkj6M9fUP(-A6klsOh2}uN`OYb#O zLJJTnAtWKmiSPUSzH{#w_x^Lv7-yV6_E=->vG>|*tv%PA&z#SkAN6$AuhHJ2B_kud z_CiBNpNx!>fpn!@rY7AHo1YOUHRQhf>dIubqjz^n9V*9XI?u?+>J#WL-drN}uXt&g z`I3>{^!s~}uR3rBl94U!zEF8)7-+q}awUgpE(nPa@jS$>qI3@987|V;I=amD&;K3B+@H%#3F^50uafOa>Yd3G|*a^c>j#noFfh#5tOH4!}%|5p=0J z=LOze%o~A9lVrMljBDH+?wLTKkm{^T}>~;rVf2 zP26!h^t}CI2}%UbC8_&|&3}1HTD2jh@&?y55QsT}8j!zD40VCKVW#(__lS+fyJ_&_ zR8FEE0WJwWGCwY_rQbfkBd4x=cb>0`x}O6;db|9tk$}<@Set3M=Ybq13{QM|QhbDs zJ|3ipJRqJTfT;hx#;rtpSkBi-QmHyuRA-u~NbFIp`a@PQhXxQ&wJ^Jigy%nC7ss4% z&Ty3IW2;gEN)nowPf%{g#N-dxg`c>33M34LO7*k+UFYx2sxAc<9#6tY$y9ZFg`ADJzcTXY zm(eiUtBdx8;uC^$(3}1{W?qQGU!7+y+MR*s9jR{VX%;3!Z9KAYK_G?_vuy)%WP_ad zD5l@=r zfcJsmS4ve^yWxfxVim|Z{iTL4j-|%FyAlpbZu3pn*AGz#$kKK(Td$A`o7Q&i3~6g0 zw_(yw8NRP%=aLXk6UFb0!N-7SfWJRR6b;1*V<1?xXWnr`EhxW@{B8Gc7j~g0n+*N|cDQVJ~$}&O94~Vwx{-z>65)lJb1QG0Sl-6z_^zQ@qfY zPf#>gMiR$>DA8julxWcp3qf~|r#Iqz>%xt;5V%&7=x+ZSfD)FV(o1-R4WTF$Ri>Dx zh^d159p=6{dpS1Mg>Y5Gf4n$)NtkTE>(PnYYYE=(2N=G_4!sQD?4-soo)R)*2JPRiIUoKmn4xYQnFotfYx~ z`xjV5)ZG>txikIcSJle7>aMgy>HZn*sjckx@VvwXW=!)y#MW*~w|OkYWO#27U+lZl zaoA~ot=OzAT+9(gEnR9e_D)*tNt2t5U-sh){T51+9@R>{&Y)uyac*mrv)4!|UJK#1 zy6%x)7z2PO08d$t9f4@c(S-<`w2gh0PO<{JT>$CX>cyDO#u#`U5W_Nh3dL>P3>6`P zCL97-81|@@c$#qhCj=Jo$&sCcBy7mxY~U$P!x{nP^V=5<|G4NVuP1vku1b(JoUp2F zF*u*V4Y9W$HH!|TiCbmI>6HTzbWPpR%V{FM7ep+e3uM0ysj`L!;FfHXyVU{q8|uix z5E!9@(VB2%11wq127VpGW6*X>8}xQPk?73}PT(sDehyedi-t+P`5_lxu^4VpgX}^> zd1xSi2Ao0aV8sN&zU;B23sGlh{N0+P3rrD9$d|dN3&O2<4&6eXm{wVz94Ur!a}s;e zZ%4;>>`y~Zw@e^A)fUKYSsQ%PMa3f8kYn^H^({+j&S2Ft*^wF$ak0G@ki^Oc{#via z4A&8I7Z^NYf1oj;08mtWlEC7yr#V+4XcSu>MK)nq?zU_q{fuOx?9x8(bQjaDyK^ol z!7LsdD1hIl$+fz5beeX)y44wCreGNDS(%^_A;ox=p+gF2FjDoD$Si%-n*e`Md3i2@ zM&RKS(bfApsq`~Y)W%^egbziVHnij0Z@-DznDp2-5Ax_m9AA|39^+gvcU-rIJd7-3 zI2|DuL4yn6SK+`j(;(gEAdenp%&%kC$pWu-Az?6g^Gt&Yaa;*i=d+gKF@YX2w_^_KhN9xiO2S?w3K`dR5v7hw6u+)MKo3`$tm-2Ol{xx2 z>FqOKv!dC=p&n_7fQ*t;bMPP==(H8Pv^n4LYI1RwZ{^NeGV`c{n{i!D0a!;xFvxvF zKXblYqVD~Zpch-rJFitENSeJ~%z*(l;(77$s&xBUdshxb{ima(NK#+rz(JF5?$vpl zhf}qXl21FLQjU~2<#Wgi(gx+*bZRT!V=nSTUwk6|=E)3ROZhBiEVN|kjf>1Df-e>k z4kv$bKmpNxm_W_67?v#%--a%OrN~&AXv#MyU>xZO?-_*xk3=C4@-KSx2Qi}Zi5{v| z_E7?VVEECw+%v5AuB%Pjg)N8|Fc&OcMlr;BfdRnjf#+eE-xfBhBS6MAIr3Irxm3v6Mx zo{bUvUIK;s6^I&rl|N2eA>urWnBFn?nIv&ux~hOO`7rI22epW-cs*foDK`d&`7otR zlT~+dE(*Vd3V#VcF10kQgTEx6)sf~Z6nS{o1nHJiv&f#3zxS|L8RJ2)#Xen;rja<_~;3&bMdM9NHP}p0BA%S8gK(zsd_f&=5sx ztJ>ie2w`-edmq|zc8r*AxA12P$qSwI4+$0=`vUL9T3A3DZaJ-lu13&LacRpR> z>=jVjse1HuzSEF8cm4tX%VFAR2wm~JMeAXAL3{X0wr;&^2X^OB>)`sW7i`Q@ei`El zAta16z0jhmP;^#wPO{fmBf@t)^nkcAXo|PvbxoXnwtb^O<%sQCiTLqkUVOvenQB?= zoIC0{%Mxc8(n9Psus&1`3~{xmx@=Wm2elF4(dGO)R`va6_%FR)ycddNN1UDz!y$Wg zC`m9iXQ}a4jtts4x(Yp?fvTMK%K2p*FPRMIdWO#g5d@nRfyc?5(u&FW1VyjD$5EWY z)x9kwTag-9mUC#Kc#avf%cYgAvyt6yen=#p$4MrxJXa}0iQs6Tqv^Yz!S1_HoZIiN zN?0A6&-nM<^Sj%qcfC@gpO#PKLD_HP=pe#f$HkA72>WMaUUNl@la7aK3r~v-SSg!j z2XhV%Tj)oS_L=!gHFq;R>XkliqtlK3SJuP2hvHqrqV=ChtLN2Cs9+N~_>))vC=apq z*za^RH`pIKu_h{-8@u^FS6MqZhM-!KSuIW#dh^~n$pyCDoo`pMMyx8;SbzzTWFD)! z9Ff=T)I*yld|Gent;17)-Br|SskPpWP8vB@%m0lfVfU@U46*{wmw#=D{*fAHzXLOB zcA1?!9N5Dh!^memmI$*_c;1&kk7!Cjdr|y^C_6WX#S66uJxf~-R8O-Ev)HPl0Cs1` z6Fsu}uDef|xfDLKaY0a$im510$OAUc&Id5UQhu;OQGzPcIc1GxiL4@b4^TC4w5pZtqiG2$2M<9Bz!RDonq^5a> z^AUwgjis6S-KCMCoM+NaTqe=9fUJotre2IcN{xsdm`AfqUx(NwqX z!#pIqV;{vlV_f>(Bq_}5)!{S?T@UxQzZ=agSarxdE*;)W9>j6*a zq3(^5$Sf{huM7Wt2Zlc@s%T zchnVk%u?LGs0+edz~@==r3wU6V|+u67FlCIhy^sGZ=a^3k=AKj zvU4DE<(L>+S_UlPDmMF=de|mir}8%O3`Rg1&|D_6#Ao=S*tInGij$K7Qn(Z;2X4B`-wY%p-q9Zfbyr7I$)Sm zD_s~rzH#3p9G_5vU!~XLXRndPVDR~@(lirEqlDVn{tZ<_e;JrK+}RBI8xawV{UtD^QLGXvMM9>d-&(_i;I zV&4c(83loMDGzQTQTRLI3R?LFV{}3nHQiEBDnQ=k-ei=<`h)ARpMso3Kk2 zSuQB1v>z1u(mHJ0?zK{D_zn=SQ3KlDTR2`dfo^JxN0wVuqA{a$&~a_h6QpJngIVv3jq$?)}z;4u4uJh%2nq}Zi zlP1jPNaC&}{Hzr!A_+wqNuR{Lw40b|&3)I`bDepR1zam5^Q7sOsxgAnf+yV@jLY?u zGI_HH+=~b$#MG0&?agI7E_6|RUNa^qkz$=V3Yr~!)SQ3~r^62EEV4J(@{**kZ?8E_ zlP0z<^qxn=c_}S}t5L-K$>4L0xK@Pe@#@os+E3@u&n#TDCMpy^-!y+QF^o8;WS+cO zn!**=3C%d+-)oqTldo3^C^ZR~^2K@Pq$^$|h9t|MjIX4eiq+W!O|?h1TEoVOaGRXQ zI~};>pq&ssrb;hn2#tCn=@6ChD4ictdV6^*Rv>i%AVgH1uHBQgdIMV|>lPt8rAV)z$iH`MXeN*r4(tYgta|A0%Q{Hc0s5d4Iv8mMbj91co46dVVhuoP(POqJu zE~LfT;CV8`4{{hI6fRZ)D)~9%l)s4Qb$%?RZwF;VGy*EV|0xKjKNZ6ggFp8)ET!kL z5iV{C>F@ZfFUl4f>|eCGXq63OuTQxwh#^%DKE%xU;?xh17}{fg)<%mJSgkl& zpcbty&VJ&bkH7Q| z{2wEMJKUjon${9bi_v6YFJjVfgFCZ?;^#G^W!QLRE6HqQ;A65I)NToiL=0@WUKIb% z7ro1g>toI6fA^9@dgCf#E4`kw*`Hy^dwwGCVupY!i}JxI0b4CBsZxFXVQL^h5PN?GqMvcLG;+wj)V*3sG)CGLd`DM;u4O1UR5{moOu@sP40 z-DJ(ag;B}ytNFNO8~5>S&Cd)Rm)Ynexpa z8+^!Le!v37@|JPUTDe`|&xeC|$h$h)W*l!{_)T0S5V3;H9PbemD;|C!I>e>SQrg!m zgun6D*|#?I7qbT_>;*lzlf&f5!03W_${Eh5h$p$TjxO>tQEm`o?X;zsnI>_Q9z0u5 zFCS}JX91;NLg3-h%Am^m){!a4r>ECeFHTMoI@D`b3!im5rhsrH5NNu;PK>FMl#Q!MVVT)TPm;nRKriT*e;B<4L;8aM%j7=TC|J8|y5*k~G)F zv@1dKAip~|*n>>IRWXoaTE24*RU*m7f%ewLf`*kYt$TcoTabGoz%7;T;m6F=0d?7Y zj2%x~k*+l?c2VYPumiJJ#SYhKA+|H+9XF+~;q)6ibHh90?AZa8b2UBMziVd&R8H^m zR7r;5SUO|@o7(D1K9qGNgXQoynywgragr~cPMq%In$+RH$vq976aEUbc&e^Y)!p-b ziUz*9%{gpBIHsxmlYlRkXXH$PpxFocSMS#VYLgQnIAKqhnV<}^3G{S$&}KYk#jn45 zem?pNDQLo6H$)X{LqODR&TlKER3LM{vKZZ{K?>A>gxe{L9ko_QJO_SngxC=y(Qq&_ zRGud?5;Api;0e^xgyQ`%hcIHixSEm;YWKnf!c_+j)84E6-Gm?^KDy!g503aphzi;fq;Q84Yd;&lc?JvIZ)8i?$ft}JBkoy@{iVHxo#!Se$3((ctR^Df|Roh7l4^MSllhk)Yg$fiWO*EB*e(Qm%P(nmrx z@eAo^Z)V<n*hX&)WQFTgFAhWnoteRyW#&uRgg5@X(qM&53~ss6Yr~9 z{7W9m5VrHIH<+P0TnDOu2~!tdQ%*#L@EOAYyygfdqQ1E-ksbIcy7k{7ZMc9<>NOJI zbI#dfdyUjhO(5&y;ogkgV0UZ-z~m)B}3WY9=E z$RP0tBqM&?bG+ zP@U>B*OeAq694#3hFgj3#dmfC(r0FFkW*;9|If&m8I*3i^)r!z0{$uyWJ$08od^#F z)mN&e$0Yw#kNpN$#QphyKlp#q&~P!O*&HcBNl`&ZlOYXPwvw6q{E(d%S&&Zz_?l%+ z$MAWoZ1L}>!<_;@0<`7h*R)y(KT_TbksLhqpMs})z*iie?>_QLtInM65~Gi;6n|ZM zce3B|NSoDiY?a#RCI0$zdrX7(cWFUarV;m( zjcby7aLZ%m>$|!82YLq#TtmGqTq2x_BRuZzSz2)wmwZ;7pGRmo{k|z(wOY1bkrreW zagY&w$0K51NY><68nafRgva6zzF_q}TVGSEOq%`hR=D1NmU4uW+1~K)=xq4ULmmCX zPtDhOvdtI23HT5Km>@|{$qU2LCU!V$RMwgMSNAxZ#B}w|!5#0qf#Z0#oJZc(znOQl zN*N}chg?vt0kv0Ke}x1y<67G=8NGY>hbi)c(;>yH`Tk3WU*}s5`M^$|oQ4FlSB~eQ zD2|E)5mv#XnK1_qM}qMW)rf~IqDnb(4;@AGQUMa17K=@3&a%40DDfCLJB7;I88M~m zv`lu}?HT9P2UP$B{dB6>iWt<5>hk@9-A4=G-tQ3>itMcuWo9MflUdvk^x$?z5l)E@ zT;paC3-Tsv&6S*4Ha3g#7W+B8f@b5OyEdiw)1=7@o3+jBR?7Rik}}#8q}hxTqR3$c71-YJM&w&PxF7yB};@VkM>?+`p9;!djuHHTAY zcK4~u)?f3T7OM(%XI9Pa;e@YuSL9TKaV;x_xZ7qOuKAW7uUnd5o^`Il($F0H8BAt< z3Smi1Rq(M&{N2WehYdPl2)lT&7Tt=2%R6ylO)&jCe}#}1+dbzLX09hw;LWet-=DSX z=8V-wECfIRP}%npX9BzjEY8eslV~;S$J0UB0{0JQ4J=$!1*DpzKAk$R)yU@ElDFTg zY}PM?-ZLC#UjZ9S=w1N`j+gC~X{|}r;kqCc3m}h<&n}$8m)FDeXvzRzGoxKFB|P@$ zg(#oth1F2jxk+~f`R0V04OVCJ+Bu%j2 z!7kcC`)qGjp}iV~4s6teJ0aHi5b!SqhleBWx4cQmA?^j&4&D7TcHhPEc9#yB*GP$Oqm57F~WLc`QiJ&_Y?rPU_TA~u^e4~MM7!(zhqKA>n3 z&_qod8He_r0Mds7PnMxw3W@6-?WaNhd3Ca>7!V6KQwFHDez6jVYc;L0V5dohuC2n> z2#?qJt09Xv&A%YMVyjEUJ|32egAQm<{Xx%LN|kl=!?VCRLXGZ)BY#{X6>E+ofdliPBj#LZ;VXylNv#3 z0~d2;1HX6$H^-f=KIf;|(uJrlUNdVSyK;R_*CX-iN$J2vs>NpYb#hP7q(SLQovN;e ztqkkYYS+^01%JKT3VV@TVD5v{;EwV_qI>hN-scUTaP3SCR*qjTblME5%6xU1A<;ad z?c(fl`|^`Tll`!Wo%h~D8qGOa=^C%} zC3LV!ole-UjD3lCjop-A=KlVi+`@t13sZh^P#fn%{!6i8(LR1lcbi3;!4;9Yc-LCm zzMEjEZ2IuJ$&72De}~&r1u56XEK4`pxSYOA*~qO8x8`YkR#b03c5lXEENd`PVl<@9 zGx75)WGWEWkS;JJQ88zE(Q$Qr4E%O`yc<&B8MIQkF;1c;qhJ8wZ?8|75t91lK3RR4 z*J^ov=WUBq!|5Z0Yr*Vx=bWp3uCH8tYOl3q>P@5hwqCP`4^^T{%Q|&VLTp>i9?J58 z5H50oX^obfXxnAM28XKf_-s3r-U)~kXWc1h580ns5)6G#I~~4ny;)cpp5{Kx$mGZTYdF{zigJf`csA=*X=?~ddrMmXc@*=F~T zzh)G95DJE>t1u~I>)uC_X%eSf&eusiv95&P7@n2tt%Fu2;{dAQbnJG6HX!b}+2X18 zohk`;pA)-1ANJR2!^-$puGV<-7Rcu4?9?wGY(~D&r4G>7tQM60ikc@67BF^KG7%aA z+8!8ZIRM6ugfjCydp>9Hte!pe4Wg!e@9m9RwXvPV9{8O@z*3@|8X;j*UO=}YH37` zMPl7ea7itsmhD@~Y ziXsRkIT8Z1r8WprRX+-4g%g7UhiT$4^R_?m3t6_yY`z6~W3)`Sua%75C9-~<-?Xk-Z!*4~E4oLQg@8B!STB_)@ZPvE$_7Ft0M?>n>gtz7A_E0IRs?qul zf#07znySnS4r(xlmhCxaxS@+#Y^(~b5e_Ixe!ng699e}QRD5Wu%Xmve*=>tZ7_49( zss*-x^XeU=6ADHL$XdsTeZ08ax!rHPO+!4~&9A^(Gz6rqLjREXiOV(4s&|cBJ(?)wWJ{3z~V$j&YR;eune-q{g6#uwdS!WB=ZXi{y$`~iO}n9HSofL z9!p1evRv+t_BjldUIW&4cB%>k!y~mnFNN`Qcq$sc_Ilsznw{gNC->Bv!C53ZPWQo% zz*FOvDkUbfviw%0hpFacrTwg%GN5%G$pihX48GgH^xmim+fc9cwYUY%f2k--lv2u& zs8MdKEPpc7dvr1d;7P^RUHu3w(6j<=~r{GrPGjW+PlpembRcIz`#i)zfz%uaC$B?W2 zvfG$Iqe~foTrbrSVF33NBn`PJT#LuI|fNq9j~NuYfEz4yt0rOmLe;% zwlUk1h3qS`h|6OElB=*1)77!AyU@sOsdx6M@$n-T28A@RsQXz>YU)O?28hpIm~HZV zmA2VNp7fH{@4QPQugITbl;uxltBTJ!RP!I;Bo(FT7h*})lt4CNX&%+_xH;R3=^E7< z*+g}^ko;Y%S*HE;*3YP|^a7(Veg}%md%QhQ#=B^A5jAb%k z6JfNz!FgAk-NMhbjOJ57{trJurqej;q)v48i0$u5rWw!-+wa?lCd?^7l+C0~Td#o~ z5{S1GbkSdI%WBZb3>210`|I_iFJZ%{8Dy_O?N{@*1LVDDx2 z9nuHfoJ99{a*Vy15x?CoB_N5v-1PqSJRmAego%|y0Yu_vL=f)hej z)9T``mrCH{lktzdiB_XzH|k7JUmQegMOTc1?R|cCoDc|y9~YEWQt9b6H&^MsF=N{E zaa$R?FPKjb#ZuY0lyT0wy_!WN3hoXQ#i)Bxhq99LRy>SChXf8-0{TGTsulP)XdY!iI1)cMP zFC9eAtQd-_>nZUzfN;lFuuGrKLkFQ)^V-*7!YnM{1{L%_`LVG@a--TeIM}0-%fEo;7zb+Ch_+|#o$9<0WLH7^r2M$9`>>)2&j`8lNldI?6wSzAms^Fr znbv|iM5 z^3({QY#hbJYG0CQ}TVWqoH^EEu9^`4m=qDoZd_7`E}cQ(h8D0{Qt zDlDVEDKc{1yk2f0Imth?LZ7Qw@Vb^f|Dh6T23BRmRTEvE4qt88s=BguXAt)rr)3g6 zrYId`2T$X(H=WM&XhtIpn%zE;D^GRZ6Yq|E+wIU9qL9HY^_HMm7d-$PI1gD_&Z!5KVg7tjdBVdGH zzWgYcOEdCaSLN2Za0*zr-i%}q{EvP37eLCTR2~nFVIekE0TEszQQv@`HRyLvB4G}Q zD!fWvMyeBof7ki!Xw&p3TbqbjgX%e?{0gh%P10|?TIit=3h_;qlr)VZ+>*Q_Gz_?< z@#5UYQCMxrVMfFw;!j`O&nPNjghpT^_@5IuFefqy#W=_`u#gv8zNL)X?JK6k{|KaZ zjd+wEBwzC>$k(VyY;!c#7Hfg0qp^>HT&?uoox%HH*7@5@MJM)T8Q+R*1Rw3(F~ee+ zGNH2vSU>zccdO2(SZ)92=2p;Xhs53SbSHV?vh)yK#D=uWrpx_G5g)+|&-=SAQAfFWqT{vYc@X z-R3Gx=P>GD$r>Dm%lf0G(dS0}5MmbY1yw9L-Li;a)eJ-?-TOf5S-=i#Fn72p-NL$a zGDxT5T2q)r7Jc9fIHiK9JDmty(UYuB5!uLUlajD;bIYw+l?-DwIROmar5nYX48Fkw zjESAxiZsJ8@Z3u6%L!=w8njo(e&;57eib}qsTSN2^3fF4Dn`(GUNo#KYSuXoX8CCD z0q>Mt&PR24A14v_{gn2PviC!nmi~&(Krks%RZn$!DxP01@1AZ%tmS(nK*;gSgrbcM zUj22D^m23&n|;@xL$OzYcO7k3TRS0gQtrDqG`8-CL=6D5~!12fs?@??KH1UP$vzuJE=hDZ&1p zg{7q$>Fu%EjiBPg#+QW6pBTzeDU=IIGV9~gSUM{7PF5$fJ5@ct!kI!zFbdR(RP%Yq z#=%;^CR;IQtlvfomb$}neRTz$Pga4+4^iQ6bghGGTiIuSO3a^AL{=QA`nFR>y#*yM zAA4K9hgI*f@rj7JpX#ifjw~9km4As(p^UoKmY9P+xxRc~#LsP40t>kB#nV!DnIQ|n zsNs9kIL{W#%gJ?`Q5vs$82qc`Eds#F-1e#%hhv7U+0NL1iNkLpvrj-E!&^%p9~|2g zm;2^$79RK0+oS?SD)oNjg}ta7X^6V*EMGEs>rS0`BmKSTmPPqa(S4Yu9cV!=+|wIu zoFpk8D6SV4`T&wx0`QfE!H9+S8=V{K2mKkB8URx%Vjfq`6Umje4m}kb*vQw-oJ(k( zjD-5B=nP-{ccfm9hux87(BGGrZ#dLY_`h!(HmuP}42@d#j(g^ z_KnU2^OAVQ=w~Vnqd1#yp!(m`!aDy|r*S0?Jd!A!Ps}IM8U5JLYOYo+`}BVWwZP25 zwb+E@iqCq|=&^6sz#OesR5}tN_CE;~l^#AFcyG>^SrP+7MJ*SofWUop>TRuE-ot;*oFW<_6T|>#f&88tEV@Si3E3>GP*qU062rd=U zv-j-)5qg&<9ObAk|Ij6RWWX4eNqm*Y{ScD>!9ZeU8ZeYmYOy3T$9`~>Y)$aPRSK%t zEY}(C+#}INKa<1AxeYI~l3pFX#r5Rxi{A%p$!-WlTwG>|up-q!+~6in_%=C3`PSbe zE-vN;MlR*(m!uot1qGFyqDag6tsX&EDgBqO)KCqeiq-34+-M)W$rT|*${G(>uZGHU z{2lgDrE0|a6LN}JEuzN`?8XxE%d-g5oYc-}E*sq@&GMX^yzn!_zxRx(E?acj?sStl zq@RuyQHsKTOYMqV*+0Q`5UbjdqaiY5XEsIBqv>%3c z{t=H%DaD_@n`1d?63{Zd zm*`$S%sWd81Bj%Fv-t?03?&JwN=~17R;S7lPZ$l94=QPZ5#w%9t$!-hoTy@(Dh0)_ zrw%;;cn(JP1K`U^TWJ!kZUg50M$djvTMo-{N-Cuc)l7wK{!A=CG4U8EiV0p7mTs-i zo^BMfXyNzKbcZ&5B|CcZ@4iyS`niZ}jaE=#!jInaix^$ngTs?tUDGS{X&G2boHX`3 zgRL9~DnKrTo)dkiOq-Tt>expVQA9v5X$SsR(nX|!$-7M$oX5D8I=}B{oQ&Ys_{WAb z*iB}jb(%*`7E2wIfVF^jACO_*POUt>7JO88$^I3rV?yFu$6#TYwA`rKX>JYaVLXUGoPnB5q(VH9eql1~(czFA(c{~d4=6TSbB#PDl3AD=&4(n$L zcBI|n@GDhiPYHVGua^3kiWosmba_K|{Y!?6n|%~kL)N3ycg~6sW0`H1qbj2w4?C)+ zvt8}q(lj3abmZDY<=*S(L9_`b9G1^P+R~q#Z8;{BQjg8TNlKX{f;>vaIxGvJX3Y6$ zz@Q<1Sul{3J&R$l(!k`HZcJA7xL=Z9bK(@>yC zB2eq*hODRN;0M+QyPkmd0Ci*}%X^=g;iPz8ADd*qyi*#6M(muTaM(v)w7%(qst=bZK8CsIZoG~L8Q`WZK(qk#W!o#fX~ zpXnJ|l>65NW1BST8LVHo*~m?2Z!uS_bxm7KmObzsIm+e#L%T-Py175e0*~fZHzE%; z85KRDm#7uoh^rgw=S&%B&|Nj9Gb%=o_xcy>JkM+!18(s&lN}A>Z<;Y-X04B`4T^{L zF8RIj@&9^_#h(o+^Z}i>ydo)f9uK5sexf-O;vbO4mL+7BQF;KbeV<^SaNXLW{mzK} zt{HpyFS8^n@@{F6&kJz6Lr_VVhV&l-J7#CV(AlHZ{-Ygbl!FBaiFFpGihWY=Z#J~@ zCoSt1_EyNO!h^dxSqRaKNC(atSZCF`9nSyuw**f(^ld$9Lg+LgCX`B!_g+QHHpzmX4d_#!N8@) zBIWp)BS-XW5RbW|eJiixKWgg|IXC+q?XN{0-$aGKJ|^s1KSpwD%YXYF`hLA5hRGVm z0+R5!$1cBgLv~E~%Rix>NoKCjxt&Xtt@CqZ8`7fDl&2)ZP{qo5rlhP>&H_LqnAC{0 zJn9q62qS&er74jWw=D8@^sIAu#3Rof+^^)+0w?9Gpp+vtA_u^n>!0#6z2e{vpAcU4 zuF1RP-LjGE;J%;8k2l!3_TZw4bfc!%z$3E96Crc(J_}W!^BM%ipO2PdwZnQxa7x1M z%*x{|&r|Nj8P~u1&pqM~i;6j%y+ zg<>e9Slhz2XRo<)?1VpsNTJAXj5j3`N6JUA7L!#n zrM=5z$zWt2;Uum;ir|)AmFLt(m&T~uR~#mAIx_f=cHcBI1a);Q#CF6BO z5W>q_x3|6e8a}S%0k9xYbR1KtoGLI>K0+SopjVS$dQ_)}0-apOZ34=bi5pAVoA!?8 zQc8h177oyaU-8{>^qPj4(pA`TY3S*1;RUy|{#Pd8beSl_6OvAuC1pHR(o?8hYP_Cu z-J8Y~mW*KQDBqqKZc}Jmw{Gx5eM$DQiTPAjwM-%D!#Zc-V+#{AYjA=v zJJ+QvhTAIf7TbB`kCzrZkvi?f-<`{}p_KV{5jzl-+RE(&ky}H1QR&{zD<83GlB2)V zXzz6iYG;xZY;LlCwP=4O=;lf%qYEN8h+n?kIu7#Lm4*51Db7z_Ghqik2)=)KfCIoc zXo45+k11U><83{~0k?Ie4?ELON_Ga8j+G8xZZ@==Mg1*|)qfUIt{1r?s~aOabLWgm?v?)+z-PCSemLz2jYn>I0pJq{8~RV`<1IGJ?r`OF^=*TX$Q@q$3P~#c z4E7;@SPpb;6k?qoZ?N2vpV(mas0hoQUPWgajhg~26}+sGR?^a1I*3R5pH`nlmV()S z)ci^onF^40^jm(N&ZYD)US0U=@@HLG8!~k5_OAZy*wg2KEtHY~DTCxG2`!M3RcO47 zxcyII@>Zj!LsM&0TvfZa<+eyjDAAaA^tfQXPt=lxUC3nrg%!M)V%-~DePlx{vPp#$ z;}&1Y$cz6eEG{mbB=Pj|w#CggHL7t(T0FxfC~?ZI^cMyc%PZX#Sl!2mw0F)fPD-dX z;U??DqDjDMey47*g-J2BU93D z-!wKAp4dXk$H*1o_bbN5T1auoEbCNIp@hFR|TdCHi} zX?>V(Vv#9j*gIa-=U?qm`@$@G>P{2!56r13Pa#`_R_d>vp97r2Yf-lswwiqVwdN^* zo=on+?MXQtAhX%4uCImtmX*u1fAO0lsA74l)Tmo8{rJ!OIb>^Wx5M79Jam3zp>_nY znY7AXzZAQjm5@U5K*=rf`7pH>STC_?mwTrXY@N)$$p>*pt|@8M-Cy%0~6CXb6ZZosT}sF_kymi%GjeTFcZBEyLK%9NaP}44xzO6B$VU1;4UlYqKf?ISC3D7v7|d z61{)d^u8?{HvQuVI^x1dF-n#A#Yx~QwWQL%nGj?A!5;2NAV^Uw^ zk=@>*fQ{>V9Xmg%7Pai~yL1DPRQAz$ADU-DlKzGSj*UN&Fl>!R;Q1~PBaE2=62=m@ zsbV)7xc;6d0coZAj>iiiQRk18D%YG9o!i;CKBW%`3i~Hc8TJXocBo?I>1Z_A>$td; z?C9n7u)l~{n|I$|lQM>`|GQ6+^#QHas+l**DQ;8S|4X*BqAs#?2dfw+NFcuJrWkeLzd@k}o`vj-C3}cP4^*l|V z-6AlgvHjvD6>Kf(^VRxO{wzrCDX}70N`IqNS+m>4hc^A4mBfnGAQdI!%~PYaAsM;? zkmSN_^uJ^EieF}ccxdC&G~eVLYMJ|x7k-##dknkA0NNhjD`CqatH+@Z-@Pvvqx{*) zNP_tNi;vAF`c}8v@3iat^|%7wezFh$i%4gEU25&EBMA*_7s5}8wabeN8h2v09m$BM zH0-x$38Tn?-!L40;K}oR?>{u3fajvb-u4G7NEornAMEw7Xy(0$2&~0ZEx<ErZJel* zsfSP*FFTilh1Lh5Wu|Kk2sN!Gy=R6P^7X=$J@KoaBZ(|R?#HyELk~(!;2s?mDlu1l z&Rb~d={*MqqYuRS%7+M3+(w4fr~{)aet8h;f7j@ywIu)qj*VRqW8Zpj#pN+jpN`jd@DB zf^U((wMN28frB}r&dat0-ch$IP;B_|1zGXjDnK{C=n zOO8zrLKCK%`@Wy&`DVSd*7v?MKW5gNU&`TdPF0<%UHiJOy?2@T<&L_BCDj$YJFLpO zrFOR)wOQ$P{O4~!KH-M4plzIu@$Xw*qiwzp*qJ0*cQ0kT>w174^ms(e7%R%*=B23* zH)ZbrM%zeg=pK4Dl*0^dF?8-^g7DzWlXA>Rp6eRUdUZaI zbiSUdNV1xKz4VJ9c#+k$)nEmEYNrCMMimJaQSc(peLnCvdQ)30ni1=(EO;Q;ZQurN zd3lig*;wxm)lgGv?(ZmSYXkeIZ>P zJ@{*DVWkUGg)^j0F3VycnZ0z={1vE2Q0E~w-7_QIPiW{ zdjW@ShL7JVXVz8Oaq=L zM3P$bv-{&-3-Dcl#})|^oVK&2glk>jUGLvb&UNLAxh=f@i(gOphV&hzlz%P*WqapSaT;d6qUPjvqF_EEGc0Qb z4`tS3z$ow$@kZ z4VvcyG0@!>DwUUm=QkL$yrSQEKqOtK`;cSy^fEMWUD?R$o?V%v?>l+o?|KWw@xT^c zTUxB8|8V=b>CEJ;z-wwXWY?8LVd+WQ;@ME0=3w8j00VQmq!#jr!*aIt`(NvWKP^pm zZIoggndJVQ6x{l2vEQMSVc-O9>jrt7rnQ`l7uI62;e8!J>)C}|2si)F8%)t!_IWdC z`k}Q{CKf=9yO`IqXQ3MCJKg&DTIYt;4Zeo|wio z^NYOE3*>XpfbtZsS4~$deEs#Vr@1E;C*Jw`eGQ2u;)S+2nGQU?aW|!z5kApfKNZ7H zrL*)n>RbHlYN!;iQ9L6$s#VLWD!n$!#BHkPto4H^dzM>ZW9X`du&0#fT9jDHxHYk^z${lXm zpTs(jOpi{LyX{u(oxX$}p*_50-Iv!NPM1OR24;m?Ea93ly`oms=RN`n%nC*i?-~Bs zVoEYYK(e8vYF7p7{M-l5RmgJJZs(*oA4<=}Xu0l1oguGKl-7;k83y08o=0KAhQWyV z@AG-)*su8;_r*NZ?m-W~sTm!S`%1^2Mjt04sSvH<9z% zK!zuCWx#u%P59+pb@WP|qNrA z5!yEO$-|Sf~ySR}3GT{Po?Yj>bh!(6Brn%J@rYoB6oN(dtLWrse?BnuNkE8(ODJJ-_f8o==wsSb*Q=XFNtr{djKTQQIO!efx z%k=MCk~ZPi;u`u?pGKh4eWQJQPTbQ8*Z=hjMOPCtlL4JKWR6?n0n;Xd(S89;EC)taDb1r?ka1`pl-e^`U z@N4`AjV1hl1-F2P8NU86Q{f&+JOAPP!P?(MbJPRM!tO_e?}>jz&$8<(q?j|7QvK^* zJHKjfOQGHf)_2E%tc(Zd1C!LjQ?`PGLXPo z9u<9=dAY$|RbszZX7WCt7Lnk+Ro+#7Zp)$x2b5SN3zL!Xtwi?9t%`W&oT2&w41eZk z)YO8JyOT|LQcW64K89vNWOcQ!%?%k+GlQx`bJIrdFB%b#c=XvkM^qzti~Ax@;&c?;n!f3s z^*sGCPgv0?Z;f8BZxAlE7g}F|zXTiF%c{3MvVR+d%m>GievR?>A8)hUuRc4?Ut`!H z^cO6fn`rfPa78Ovt=XfW9_5bC&NVC~%~xW{Jq0Shu-x7^>e z3`WHNqXP)Mzz^W4opp0KtB>xn<=Ly>-=m4mUEb&nWUwf4j&>CMz4ahI2PFcXDFRgK z>PY52ji(602zGh)PDd>l;aSdJ9<8S>Xt_>6s_LKCl5ro^(8BR1a}B2f{mIppf$U6tbTbfZ@7C7+g?bh7iFE$S5kmCZZ;|A;!p{!f;jVmCAp762wor zD~nY_^>q#fCBB*DgXG;|!hsEisE2;k5T*Ie=$}r-|xQ7EZdptXQu;&x~U<86bcrx`0WV5V z4ICUEy)I+R-QL{@I%Oa|n;P?}5lbM`~(IcfNy;a5-eRR=N{PT8g@3Sw>q*w zqUJ+tB9j^qQH6k5yzNnu-ElQ2hC1_Go#Mm?tnM6+2)uOlBeE{i@XKdLI!_j11Hat3 zCYj#2TL0{1PSN4#w=#4YcHesg0m$ynJ|!I>sNg`Bgb+cQfebWF@tTMORFg#TfmK3* zC&P9F0jC82jRH&ni!K)?QNzt3M5`k4aO_lE2S9sw+s3$cX0f!c`0 zxWW*7;C0~5e%8RBKX0hq9trFoDGVW|=BLrba*Cz{uep2P9H_P<=tw7c>fOHy(DQb( zh~fv#@C21-|42~6)H)YpDYSKuT&2$J0(?zuo3s-C^%m_!$ipfhZ=GBB%GUWcjF!=) zCv_K3y}z8OSyiGRK!))_#~va<>6i5Wl9wzwPi9mI@qS z;Dwp8zR}%Y83E@bZ~WnyQ-+^SOWmG^8#XLpqj0phW3|C@@z;&Ujn8g zx{zp-;#XMbpPrYD5~r;PzCW)bD8B+<=4;0kBrSlPWifF?13IsPHEM)GwY|;X5G(tY z9CL$aibIA$Ne#cqVQ7m7P0MQ6WlsI)zl>=ktkRnwyc1t2oPJPt!hQSS_f0~jNNE*{ z#-4F>>AJbw7E|Y1w|qy||Niu=#oq$Uz-Qa!iDU2yAS|4C0T!HY*JGJG&3Qhj*W;-) zu)$3~&W?Df)XfAD|JWDJ9P?SkDNQ8jVl$WaE!jM&F3l%d?Iz{WWeZWF57hQO{*NAk z__iiTNIos@nKrm*dQlkkU)H(!053P8i|j%W#vC>qSW*Um) z!Xcrb$zchFFfx)Wnh0lUH%J8Fo*@|?L?o@8nYM&95y+k`yAz|5k`p^s)_wfy3&A-7mqq)N(5`o(R19nXX4}H_U#L)$E>9 z*5nwD|Lg{#9#Z*f&F9^i!ac8t687G+D~e@tep;R>_vi0LA`;9j@rEd4qo+z`i(WNQ=V7g%#^W8YY?ReT*SRyCsMmmSP zRalbGLAKbR-<8+n&Erkzf<8wTSYthyitM^7svfj|IW2fXa< zZ7T>1eg~-J&;GQ>1A9+;GXm@e1>_quSkru*h+TslLiL-Qoy2wK9uxdjH{O5mo))#R z{U%!Kohv%|NJGcn-Da-+%|@r`{2zXDSig7m1HX>@yiH7y2m;)E%fOR4tyGRIqY@Hy zuBv=%xfVvgJ^fzG!D5jwK5}$I$UY=#vsW$Yqk%!fdt)~H$?DtTPH{O@McsvtC^O?! zjf*4cRXwOu18(CwZYFp9ipk14^I02)%(SLL)py+6+g+;L`&pb08~FC__6!>)qPK}3 zEhrvr#$;@dbg2$fuD9aT8_yk3WqXsmq{6tqZO9(BdCp;Abw^QukaO7oc~ z1TqhH^CxB+eoJ=}xjihI7)_!WT5XYCruj*`MH5aIDE*q#G2{C46lpM;{%el<3 zf!3OOGiAct@onhyIdqWy;WBF8CBD0kF>XD^J=v@Kf)Quc9gHEdS&BXVJsY8j({80X zyFV2K(OnqtVukNt9Tc}Q-Gwa@&F=3#Izk48>XG&AS;V%eTN|hMB1V<%+;@1o*T0;) z-w==MV6`{ez;u*VLC*^jf9?1L;Z;>jTvw(#=r*)T+y=f_<8i@kGpq0y>r9IEVLdr@ z12$svc4d}gWXAOBTs!{YzPS6rH<5VB{IcEMamKn+V>9uCaP{|GNpFh6xX*qk)R&pQ zQaOm-5O&M#nJh6XYCP~UV_=G@zx2!HM?2Rrll`#WHqGt5g{F!DgGya`t96vxcX#5s z#!)%@#g)du?XD-2Y9`6nW%bm*+OZB9FP=EjcV4Siv-4bSVjzJb%}=)yBb}QpDXG+J z0JG2~KUKOBcah@A)@{(>dtzx`aRVg;?vAs53k1QtBm>1b(C>Gb~8IEX>?>DyHI7^TTNm=1nt;;g1pw%6NMs;)fH*rwv^ng+-X*e zr%Bo1oKo*4|1mh;8(YPEV?N0is0fv+vy7$Np|^L7JEr2ekX_FxVV!|*a?q0KzUh4n zx>XbI^hDd*r3&{&%H^j>e24-eZc`A3J{$A6t?KGmUBy}XZ?f9;Y%~)SIjfFRh1v4i`_L6FPc;8A2 zX&cNpIu7TzS|SGAi;{eQ7cI_GYiWs+Pov(rR;@t#)hrn6*BT^`25O7HHHbWtT|ozzWe(>hO#_}>_UFD~IGMv}EAc!ttCxOF(v2y6DyD`aBe@}f}A2k$dMU37H8F^Rg zSl#e`%VFzYF~S3r^}D;O>MN=CJFnX$-p7MJ zi&o)~NY!@BEjd}OGc58%HRZGzz7RI~>h?lAwt~DD9}*1!A#POCC&k>^C!sUn1iHPr zbjgZ6kc8&u5&z&+KowH zHEvEw=Uf$iGcv3l)MLQIYTv-cG~tb|RnZ2~x3oc;+eO#oX^eI0ys*CqbVd2j8gGfp zf1}rW_!2wn5=d&5<~~a{7bbMFw0b)X1LD&DHX6^l3a0k)zRfC^+5{A;(h(I$+AtYL zapqJiG)Jd2+Gl6zx^hg82vw`d9O8egGw@zr6MLv+_l=a2X)21U==z7K!ZNc1Vg80v zJQ+SqB`-YaOxT2|h^lcyrLx3sw)gsq2b~orMf(+Y)Gn+Z6G(FwAEX;nT+>~zd#m^l z3Lla}hWio^py^?|hQ1@@F!L)|7jK~k2EF}crtUERXLW~#n>?L0rD`_ri|yi z(3B54#=yXK!(4XVM0!ucePi)NoUfboPJfxUt1BgC1u;a7@~^!j;B@40Lb@1o@}x?I z#}QVfK0967G-R;8b?+B{ucTx=!L9! zlkW>7%;F8b{vRW3VQx^V9fA)^4{G;i5{a4B0c-n!}TM0^;1T?7udi z{66**u+blD);(XH|7i^mXpP*RnC?henpicr z?u9#X?$n-jaS#SRr3K{p4PB)T8I)N4jhqEk$mvb|fJ-FA;Ts*EIV0Vg_K8P)p9$r8 zy1qvqR?QDxN2~VWS<+~43R4?ZjxLdwS{S^oKlqwlyzyzRvW$QPJ#U+8h~g-w>W>q{ zzh0{`#$ayv)~7eEM;w#wwgSTo$gH5(!48ZT$MHlt}gE}L`q2(z0sXpS_|X# z4-ox<<~d-w(Xvo9A=#i1)FbG9xY4zIIBmZ)StQ;(-=dqPDSLFJMOvBV^`bWPAdBKH zUO-e+n=8>Y#yyRn`$~;(BXqs%!-v5EA-C(0d|uq!P4NQ?((3PfC9K_lVQAOrD$RIE zrYTM|-9YYX{=HseV50Uj$TWXZzQ#gciHYH?I!4vAFg3WU_1Yz}wW8WLP-roA%toFg z@Q$C8{CR9*yuak37qNJyyRqy_xb}nVgWfqi&wp)=upV~Mnoa3nulpg#L;0biZqL(E z)Wc%#X`YwcYUp)+aV3xMn4=iPC1|?E?1NHH%`tS0>!WWeCwaLi?~I>v_E(cZ5bo!0 zBqJPR;#b`y>ZEH8LC6A11;D(H7t-e8u5XRkPau$Gz_bFW7}1{|_ukup49~v;3c2$3 z9B0DI%IVlwtGJ@Glr5B+UsW;VeC1Vccz=m-DO;1tBng=OXeY++qM57X%J)>;K0t4Hex+`!;6J z87xB2Esj6rl{M1+$2I1AHeGKx5MF=0C=W}r8yFzkuIKas-mtOHk40H)7$fAe4=VQjIawr7Q05ay!{XVkg0KQ-SdYsw!y9S8@@g|q*j8Nrdqq;5=)j%CO zlFQNQa)CksP!I0vfn2~#!9;9e9DnQKAUq!*;?DhLn!$@gBf3*poKh6~ z8QBpaG#PLX08o*`T1S-gbX8I%=)|dCdiYc$OO`GKg+19yZNfweHOSEX8QHim{G&>Z zHH#m1TJ(t901`|pqcpcCGlGmadGztE9`{5$=F)u6U@`BI#8VAYTT~VI8xJOFOvc7b z?I-l7sRbU$R|nq+zWwZDb75-5J{9E#J~rSro|qZ>kzB@3GvEIySm{Q^-Sw!g?xZQnyBki+$^9zj;kqlW^+b;}{EP{i}Odj^b9*$t?f63`>#JS8y zIr|8}zn!_q9g2YSIB@fs?+)S{QP7i5n^lxF(IZlW}j?zsYEcJb@ zLYCRW5g!lkTz2TePTSZRn>y81{=Ot32o##Xk<}kEd4p#9Qp3}@;kM>g>wx6X+JP%QThg)Bfc(--GzOUc^lp|!tX9*j*Fx6n^#9%pA0_>*-V ze&-cCvlx#LY6vf&sYKVdSp536<2%rnvy@-Hf@$6dT=eQayddx$@J~25fmvTBj#b~w z0s+3nh=q6KXgnndub-&fcw>(OQ?rBQZ#NwA#fV6`pFvCIO$hpV**|tJz&Gqxq5MqNWg1H#xTd1B!nr5^;C)4=n~ASw`Wedm7*Q2@yWIHK==cBvy5(x2(B+_^lUYP>Q?1%U)C^(ma_ zSz#%>^>N?0ogjDwiBf!1G@12amTfz}4|iP6jU#?d-$yHbDk#h4!E;l>j99YQ+GYB- z$<(z7B&43jjMJXaOZ*pcj{qqi-by1$?j=YdJ5}#mW}Ws7r6yPQ4Q(^yRwVdSpX2~y zaH>v*B>$de4u-#?{-3_-f!zb1j2jO#91H2xg(FZem)YXl2}Udv6!n7m*@8(F0bT-u zlmfL9aSd!`kPbocvz3e=*f>!CmpAI9g1#4oUKN#Mi_WVmFXJ)@TBNV~aC#!DY}#Gl zGc4mVS8$Mle%HKsXf(JfVxu^lWXxA$^P!`>eUdmYwGF=9e{+Hc5^)(cO(5R|`fQ@4 zaiGbh_`ZmOBdXN=`6!Q3;9i+_Jak5uF4u>fr4}gJpIUIud00UX11HQdYllN3)xLmE zY(|4l4g^D6kRdWt(&qw0{zI(+P(UbeRlU~sB#Be`Jp}XM0uS;Cizja`R|`; z>mo_Wy;!@#71;$z-LlBJx&63{Q&^#=YcJ@893pn@(F)c}hrE+r6J-}F`C<1~s-o;p zh(Q%m=jBmJ1tORCXGcFgi&3(bwCcab>6mBRmyp#PMrtf*&m0-!vO&3r8r?fcJnXFn1S)Vk^Oydu-QSZr9(L~eJ3BYEh^q1Gj? z-plC8g}A55^d6WAJddRD#Vza9JrT#+eT`{(+I;-1y4&r^&)h$TGGv7u9vk=ixOVFV z)^I<16aVEph-qY~V6=?Ch@TZ+Rrr);NJ6$!M_uH?Kwrj&bk4d+Xx?5Z1ILN6Mxc9g z_CWTDa#ZmMf32_O@B*Qg=J!kRmAuh~`mh^(3TJo5U85x2SDf?b+w;Ahq-A#Z!pS!V z$HY33(}mq^+bMJ1AL|)Gddg`J8^s3W^2j5wHPU5OMWPKnoHSQ;vHdoiFiXjHs^wdh zNiMOb-;b}$QAX51wWjy4D@ZjB+r9dmTQuL2-`*rj)aBgc@)LLlt1zj4@<`UU&!W-( zlTALe4sA?hkvP!)DjbgT((kH!RFU~OVrWv?ygo9!2h2Hddz;!1>wAQ2v=xq9aGmXn zV9XVsm`vd5({73%V-0!ax1FFOB@K1;T6ezFWIBuN>tK=lJP-Yzv(>Z?JL(u#?b23w z7-YQZ3})n-s|jK-3+CuB#Y@x;kk6^ZV(e)tU=^9FsZYO1lHY64DZ228?YdjBuQpTX z+ayYjDAKSgPrf2w12o{?>Mt#2kxe1I#gd9cs{_6D;wlS`cb&7*uJz4^t?jwexl1^6+mwX14Q*V>J zXtENLb?>QKyS=k-t`SCi2h4_geczHgH7-!nSp`v4pPMS$w*7)`jQeqB!V7^$6Z*Xg z16RQI=9W?DqLkKc)jrmxW_adBOnWj)BFdwDj!@W+)m^KxU*ewApS#In`3R~;AA66v zipOryXBya_o-?XUW4%H@S|-tr1O22lFT)sC1?y+q+)X}6{_~YUO1_S*MzE0hRe1ej z?by5T*h=Af$iuR*A>@SA_(~B^jknqJMj=M#Qp}jt1c`0;Z8IcluSswN4U#=jhL)(e zWH$0YJT!~-Y;*`*ql{0EL+z8n02?`Bob-10h4B(jZWCaA9P)j&g}N6Ib4ecAkj4L2yWaWjL4`uN<1 zeWJ(V5nCQjJJ{||DGk!-?CG6NNr$Ta{$`RcUZ5e08vE zRBosC?)#P7JWGpeH$+vA8h+bnxEXz%m~R-R<3W7GvG?$2MwrFePkNetraMwUSgZS-~c><$m1{g5K^!~ zft{-*zaH8`5uk&5C|lUn@wxwV;F-|$}*u0aQ-NaD4s1#?`lekC1q0BudVRIQN8+?F6-ixk&~d}4Zae=-FwA5iVDVa zzYUo}v9@B=USXlN%&X$+NVjfORF>?t`b$@C2}`@g`Nyrzd)pE&A_9H#x<;UY5x?Iz zB9#6E&+M)U3wGv8wbJfD{*eShGbTZ5vl=Rl*KZpISpLux`2w7KC979_^Kx8>9| z{+tmqMeE@a=Z;~onPOGPQuI0=7&N7H)Hd)_w0ahJyB~E|XY(KgqKl+=`|bggd@n8w zgPB--I`Le*Xm%N2ru1KncbFSd-R9_J_bSfI@5NCYl`An(o$g)D!3O%=_{3N7iSH|l zm`;eqmmz6GR>L|$A0G^Y-Q{CiL#E@-(Ynx%>5;pUu}WGJ3v$<+!KpuQJd6Sm~lRQr4F8$~Jd>&3srwqDqK z2^k($RWu2KZ1la2p&nNnRv-iBEjINhxoXv`{m8OQOj!{pF~X}714+>{W6*PNZXoxF zAoz2fOxou*&R8hq7XZMxRiuXl!kd3NG0ZmLUkD@4-(W_V;aIe<|5NAZzw(kE$`J%7 zaZhGG{g6F^fkOP?C-HfbqR7;|`EwRi#_#z+eU{VG_++g($luNUPj?OHCF`$NVv;0- zliq@QziPg6D}72Q@mAP7-q&zmU^@Ycs&8VtdgqEyGVsb2eB~bP#uJ0SeFZKk6aq=X z_2&Qcm>(Qj$^2h47JLE-l@EjA8=dT7%B7|s3sn<(c-~GHA@u`SIYsRzJ`5neGX^=# z>t5a*+kgGRBgMhAVeU;%n+`L%*XrHkU-7OE3HBn8Po?0y;j~HSwgOHK?Hm+8DXjl% zG?-mG#o=HWbduVmn-!Tc0N1pIx2`?*fBNA_coUG-wY zskr2X;A1D^ccV}G6aS6wNob2ITZHX+F&ozNrGyZJrws1mkM$iEI> zEB*r58XoPN6P9OU5QI5yD)F%+2tqJ?GGwX-HyDlM4BT?c$hAKGKFCgdEm}H>NIMmP zrhlH1tPjhffHjU@rLI4gEFgd~-!&o)5(g_v`^sO7FZg++6_Yef6s;S~S;>cE^)hI(h%SmWp?EugRow^wLMh zR15_P)z}_blLFD7%>OS0_Y0CTx_ti-u!0^rZ7pzPTLinBDY3qW4-l33~M36Y>a=gnmN ze&(3{h$lt~0^_ZGj?hnjSz%SUc)*~rfInRyRRo9W!iA6cwR~O1CA7LhaMD*?6C=!V z_!CgM5JW6ke+oIFq_AEDZ}&cEC&_;cRR5Rz${s09wYDqx3yYalyoa(V0LN~PFGZKp zO=SX=J>7sW!iOJVP#?aO@)pXhPUMVa7si}8WXhvo@mYjgOIr9jA)k+cfz)`58;sm>LK5FJ z{fqhXehN8bkcWp|^zfNCNg^0*$Nh@l{sw)wL2w%fpdfIR!)F!fe)Rn(%1d5BshUr{y#zPoMSQBM)voN zt~3_vD}}#uSBosDN=8>D3xutKle)&!`_^2h+!C}x1q=drHU%9Uk1sK^8^F3HAbyAQDt;JDz2D(Zkq42qjYhy0YSJHR?HYvW^Ac8 z%E)n?dqU5zQJW|=N(yT=Tf3#xvv}aJUuRIn(KB2+``^OgY1wL8R)eRkow}=ZlTBsT zJFf-uOmFwD{_kOM4oYY`fZT-#IqIDDpu7fx6_{`Z7NUpPKynKm_`dA|cE2&3L%3gWmWFWd6wHbP#(m>n&&|EMtQfJA4r06DU)UOZ?V zM6ln+`C12xZf)w@bGWJgChiqxay}Vyk%C`8Im~<5C-Fr2GCVDp=9kOroKW%MRPE~^)?z>YU*Fz8_e4Z!XFTy)aiRd_XZA`G3Zh{Bs6i8P zrb%^=Wqv~Fx)3H?LG=%%i_}yjMc3BrK=8eESE*b^^Ro6IrjmBV(C#_1BPc-gUqinK zWNe*`=Ppjw&JqU8C7Zjoq>C}SN@keiPb_ZX%Wy8|^hwAV=cu>#uKyypG%_YxLJRI5 zH7uJ4_?wN7;RmEx2>I;7mv^3dqZ_|5ib5j(V*Y5^3f$U^*LI)yZ7#eC>GXS=oE2%E z=-`*DC%*z}ARza2d>pVHKfUb5WXw=s0;?~M#nRzlEHgT@**Rt4L6rY+t`sjx_C36B zJ@UchhrZ}!n8)5KJ)Qa`BiD4ubZ+id!;$xKD_??@tbY z?tAxYi@RtHP*wvt0uu*?w?Z1mmPa6wGLav>z__Z49ys!l=f9iy4=DV8)4rSQ^(=Al zzko3GJJvPx(}f1^VtVag(Dan@&SAm|eKoq`1JR}?ij`lYFWA~E(KATj z3)bbdD!I<E^sV3rkK2$n8LEW3{s>>||zkh*U z2gl{b{f zp(|XN`WcC3NPkHNHH7V>a+!!XhPbnu_mEGmnEyIFdMQiCv(0vtfW-1_+oKwkV_S8( z7vfT;P-8X#e>$7(=r|Cl6f-%FC z=Tf22BZu#Jkeh$?O5Lx+Ly@Knc>Ioptl$`(bL)#IGlFw*KvgN+dg#ERQCtY-{~22Y zxA1?gB>b07&;Jjmf!F!pNA!Bd*g z@!85A{FWJfN)T4xJwNJYoJlkdXcDKt?{{qRAN0}bfvgLrpKLEU?cLqBr_m>YV-64J@`iG0=-y(UGo3T`J3K>8C zNlGd$gw3|1W(N;5iw42f5giu z{zgi6_|6i$aC>rJRQBYnE;e^Dh8iB!>&caktckgD37m=5cL^t1_CuNTHh*(&8?lyt z<>O(4+$14BL~$RESWQINO*NVJ1<2It3Gd*oQl-d}u4SnI-s6Zt>5xM>)CS|Jw40BM zoSx4nu3yF+^++#KIy?)n=1N)gAq8;!m=ceS4Y9}Sh z`q&$h+2TO5`Rp`}X+o08Nh|fdT{mP_d9nuc$-xqQOQUvgGuGyd@loD0u>p%Aw&mJ2 z?+Rqa+Nst+zA=NwBmxv>nKMy_7Q9+Xa_vo!1KW}BtrQ5oZN zDor=tYdg?J%&N&Jic*)L&%UMcbd_+iXMUJ!U$f!6Q~v&iUv9+TeToEyq!fL()_KZL zyzmQHWGjndLW9h!d&GpwqVy=ekdE@-KC-VvNNHX{rfpVJ*O8*v9(iF}UdgEA`>CW6 zKPZqA8kg;$hZ~jXfW&5GWfww6qi!;0*UR--y4(Pe1RO8QfA)!sE1BgcNSI|~>4sj+ z-0S3d%fSEBsgf}q#{JFP=p&w-;wW=Pp$;dWrQk}Vm$ckjJ zT=eT9m&LFbd3wew@gecdm#@|%c+HM(**EH57sbyW-cdMUb8K%Rho#L3FMqkH)_nTd zcx7IKM-<@{;j-G8+0rE+h26evHI$h&=^sS`^Og%5VbEv$k2Zj_h0~tCDyDyU%q*7j zyoAKnG~|vAIh)VR*K$4EylJebrD2FaTgi%Vb3T{dglNd#OYqRW(n_0!6yKXz9=Oc4 zRI#wbSTOV0q;%NHYTIP|p0P%Wdhuj^u>gIw=6K^H=9<;1@X$9TGz&m+VaOXs7L1B3 z@f@(yH6C~`^Lxh#6fE(=rrphng2~2%8hlbi-c45jTp$qJDXa6EF_Id zf>m6ro-$bCVCv+a2(xs<&))%r;%v>5Xj%^A$Jrrs$hxeDWJd|rZ72cQ${%d(eBu&|xIin92HH&%U65q2Up)JMNu`xG+ zjbhmWfrGb4@Y|}9unP0LW$X)~vgx2;il*g73X=oYA62%$?;YlNVi_idJnKFp@ey*H zMW4&}OLuh$?bnj?CSP7+5uA*EC7-S<?ZI=;FI|u0O!yuUL-KDO3>4;fP@$aI=fV$;m zg%`10FDem!XPiaVcBi3EJzPN7G(>?7k-NATq=3rme=x|h?|bXSf+w31~G%3@A{F?OC0l~Fnoa8`sdO`5?E)r zcQEH=_)HMUX@kK1ajYL0c}N7Pc7)4lgPdz){|{V>d)NcvMF zkIDx2>5j^QhY$+btwL1ghYLn^%Kq)DbNs1=PzXe7*D~|;^H6GhW#2%~KYSWGdr2~Q zS~9v1FlrzBIk0GSKuHza6<0i$Po-5J%AxV?*Ze4 z1aAgWB7mjCCAD4QG+yFZ^23-S=C@9aPzZn(f6 z;0bF49;2`$U6pvLlb&-kgbZw9U9r>7Yu)EW<9XB#c-6(6h~k(!L~pM9D7k!F4?g6R z63h9UWhVHcrsg>bu4T_(4~3}M+;-m)?0Q?qK3AKPW9Yf+w`Rhpp#LYfaM=B|t*Dm_ zx5*Gvt$V)A(+p)}l$By-in1$sQ2L}!cqeVNPTu7Qc@ZtdFB41%KrJyFcG&EpIyw$wqlM-+%%yvM3I91kbe8X3v8^VcAtFfWtHQNy_C39AK&q383acVHt*&Y zi=#&VbRntZW+#cxto_JbXaCOclh5x(IFd_}s<^GGT{RY=c8rGm?6n3Bdjt^;MA zOuNq$8HX(ob}`r{CjdDabHVzjV`A=|BQy{V%#h7b#D(?Ab+1RES0x1Qs!NUz?s-l2 zO7gshoMW6wDTz!Ud%Z&c<~HW|;Sr$*7cKX+RS2D=Rp}jrCdCV>yY134cnD>>3cDu5 z!NGF!?{jOX^L)N;^}MhQv$``1A_zoDO)ac`Cwm>w^AQn+MykJc0-I+Ghzr(P1t)iwVmG}D<@8s{2+IDmz7S~^~+i~MYhDM zldl7jEOF&3

*?+EOaPZi_!ydgF;t&H|<%{5{7qBf_tcz!)sLc=tBC+Xgc&way*~ z`jqxwg5#}JeOQ)dAF6ff5c3vfDVYT48q{)+vy4uS-yGB@&cO#sm4oJ;B(7GaVC8_7 z0>Ub(@+P$&Epe-)r8oT<{{4P_g;H-l)cr0L?%K~?m)JREM!j|iueY4Fae2Zuwa?0q&IyFbJrGx@akdcRR5 z_gWmXcV3UZyAn$Ybe{U&ci#WgBv~eW_3}?>@4cWwiM>K3%;cUo=}u1SDd7L>&QTV!8q3Uc2I+J_0{&0K z2-Keh0sGqwwJue5z-$sM_o@7^+QmpMQgo4u*^(Jlb{@o8b4_21aS7#ATsCwhFF0BO zm};%kS`&6)MF&zNuXrys1K59;j{^Y|7)zYc41WBd1xfzD_!t@&1<>BRh6+9V%yE^d@UfYIf53KeT zaKh|g+8`YroF>VMd^DJTmDB#y8vpI_S%P3ooWeAGo{HoSZ851%2~Bw$%=OG)*7dFv z!Mn3#WL*6+z?fA&-#e`uojGnNzuI)IaQKCXP=RYQ7qgezbsv|usPs5Y3);oqvP|)L zpSEvK7_)?(cU7FK`F(=Aw8UK8A0Kzz$7bP<26sXHc5ws2#|<>plNT4SKc_dSe-qC< zX$-^uA%AAjZ}+zxT@gska`jSI0_~mJZhg!0&HV<~m)|%C03*%tuE*xW8^2Au=s90O z^L5LfzUz<(Zm?kFf(V1hzQQOjpH?KekFp7y zc&o0=q-a2`xilHRyvka`>C{|BsyLmRjDW82I+Xd+VK5#nfmq)n@ukIx<)f! z!Po=zMfP0CITwu!wz&9zwD;aYO}~AcXh0E_Y5_!)rh*_4>CzEUI!NzCrAY}$uK^Sh z6cv!(MS2mClF$(aDWUfg5~T+S2!R9$f&Iqc^X$I6^Uj<-GkbQ=nK}HyObFlP?)T^V zlvBH~nZ!tyZm{~=0+rdkK+|Ms~e+-7;45V2%P8Y4Vs?Xjc z)ojze4|rHl$1feN<68!FfB^KKEa~dB`bluc#vtFD z92ww<5&TzSB<~})ly*a(uFGk;-{r1yhva^HB2aDj)(S47~#y$ziEU>1GJCKpAVZh-;e}5wc5?`toV~z2tRA!_^ zv-|%Y&7Md7$7uHF(U;J?tyl-HJF?2J(4;9TV3_x9?b2q?fbuDf1M%zt-T2*~WJ(nK zgYeTII@|2GXP`%sK892(+gskL77z<)Entz*UQDUkg5v~-tC;UtK38%Gj}8n&&O|+5 z)joDIas=j;3G^ubU#8)2k4-4_X?@lmC5y;pUU1E{zM=%5d+ z5BF$@UFd;xnw|)bSw(pN=$YuLUo896`v|Vket{#mcd3sq*XV)%nu=H0C8A|b+Ih#( zKOKapwtYgVc%^o4ozzf)j2VDYIYXtwqiifex)MjBF0#K0{E7epN#%lC8|Dn8VEu4V zxDJph1X%2ssns5wqlvCxxC}Hk&Y99)Ax35(_Wk*PwKdMp^7llSv1#nlh8+U-Gc%dJ zMClGRCs&^mcJ2nG$$=vsJ5<*s@eHM=h@S?8vboj%$Gjonaw0?D9!Fd`Rz0`|MDY(o z01KT3#s^q8-@2ngx%xfn;!JQTH3*dQ*LXjy86~7y+EP{u@aSA+!XF@n?X~Mvc)U>y zD@+E+cK;#`ZY0Il1a=uHT!@lFrN@4WJM+cUWJ=l-fMEV_*xS6ot@1w_=6P$^x%u1@ zGg1aEGe5@g`}G#GH;jCTTSu<(uMcDCnl3=T!&5nzub?3_B%(;;76r|r{`IQ>t?(2zo?HNje2<*9KPL1N#01w zpe;nkh~iPyC(9FGbFq}-0+0oTuLLl09DpbA4(l=|9XVFFZiI}k`vzOUuPgFR`n;%Y zlDm$+P4~KXcNvisNISMG?$ND`5&Mv`EHjt*p&xm!w$4K-H2iijslqagzgS9rap%F@ za;>#ulRCU*!ekA5fDWy<`CLn`-Y8hD2C$_1KSqd&a>}0Y(YNs^lZ;cc4<3mQ;(*Q1j<=uOHY)8mn3ic5p3l&kE6wIg_B|D`?lmA~jpo761dXP*3X+6z z)&x*|A0fxJG})wmC@F?m+(CgX4U1@VC>-*=JwBRcdiVvv5Q((qhoU=t#Oj|#Tq4p|5AjPiK? zpvY?5Z(5>T%&W8HFtW9NY%t;ezij%Kyp}n)qC;x7>inC;Z~bEU78?A(V-JOE^??yP z0P5VzNgq$#RF9B|tI44F z5rXPp7$Hlab{_>i*L_+J(U@bx9~( zw}bEyNHF#cC0oDHam8gQh9p_HHbcl?&7S;5U1eus-?yGvvSQE<*YF}W#Q61e(lt5U zrwz-H{fID)O`x=%&$Ce&2cR}v>`7FYn)$zWJ^4NyU|FB1F)1z!92QZkV0B5OYpiOk zg21ub`2(r^vsxdzeOV;*M6m2vnZI<&)UP)*3n5@E zM{n&^`rh;>m9+XKj?w?rzwtl)kG;{Lc)$T9 z;Wje%pXaMm(y;&+kQIU!1bX@3-4O8r@NxyRvGBC<;uk=mDJ-QXszgZ~np2?vH)R#j z^S}ZHPXZQmm6!g4mF~BSc;I#g+_o&-K>BM9#eW36{3i_^fGB_?NbUds6JV$OpBo8# zV}KReIZk3jN%tyaYDx2l{1T#ei^n0krls=9e@M-H#CX^;x|NG-p$VrDxKZj8pAC7x zl(>3V`zk~Bo%d0F>Th>Rg%~BW;tU#+=R4~+lI!YEfwg-pF&(?XMHp4G?F`xu)UEa} zD}>zNAQB3V6gAAlbOku^?jn{O|J0GK<7LUVUVPNbl+)~Q9o(jLW?=D^L)h3>5e_zC z<8crF$a6Qi1Y#jUJSS5}U6xWYQ@En0&{k9@F@hV6Rfbik* zJXG_(t~~E{hAAJyr)(@weLCFjpXFG}L#?(10HSVIpkZgIK40ZkHl`$#|3Ck>F%l%| zuN%Jsmf>>GS8`zg`0CpdAE4; z&F^nt8nAfr=g6lAkh%hgwIr6t{aFO)IOZhe+urM-is~_>KxDU9&mvlYF3sdx)(L+rTNK9tYSkQr!Uk@%0c^m$XjM9Zg2X+u43t! z0TG+&rqVy50FgDk-;6?T?eDIMjdvdD$w(IWY{+czQsu=t~N^02sz5JTNPl=PQK-s|FCmfan)F>cchfMp^9F^FfEz{Y_cESocRk zjpsOzMIOOyt(N2|9?Ve_EwIyo7k%1S)8ydwnNI|L#4vJgn>lFuba($; zOSWWWaHjZ~(8G6XpP{Ml+RHi`_mo$~uN*cgT3xVhJ9q#0qmQMvG|>&TCc`j*1=Jgd zH~Pi;r^`Ole*#cgKul^@^u(?9zXt(P_50h!8pY? zIo_IaSLNSBc9{9%wg`qj`g!=!T5l ze7lVtwcU|~Qa$aqbOQMbI&oY37MP@D@9enEEfs4Fw0d`PFnJoheZ6{+`-%BNrsAhx z%^vI=-h6rVW@bI0@#O!|^TI!1SNd1kMP2->qO^yB7F4{$7N9v?&pWH3UGuXFpJq;{ z0TRCQ`cbuj=1@U#pD3__I;RaA!W?3nCk!EV&Tp*i7Z@G=Hd(gOz75-^@z+Av8-ua| z8jqOco78H3L6p3BZc4^@u@n_=TG`#S7ZXM)EV6?@>)RWz>v537PIm9MTt8`~uL%J} z=~Ul^RuDVetRDas8XC)jI@g!G1FwsTfKyOcZS3(5dt0O~`?;ZI!@)`S5YII#-cYte zO|PB%C5f9M7N*SwGwO{GDY6Iubs6gV^Ne&h;1rn;FO~#7-+iH~&O7P`l$m{=7$wi; z?zZhoh<96@G~KK%cef+(*oF`7%I+!%97P}`70#&WOQ(DkuH2=GUNuQ72XtbGbWJl` z3eMvJ8qH+Ra`^{(SaGHzr_Z=X&F?Y-oKk>NpsdFZe6>2?d4n;zl+h>`lj~r=Q%*AZ}h#UzxK%b&;rNz6pOj$ z9}1_wT79wdP({dmetAEDzT=y-YvxKYQ+>)S$_`P`MT{e{&{V3KWy5Oy8(CD}8xq$V zM|YHIPhql(&DdCxl0{`BHVr1v-V#Nse}B&Q14M{Y{b-j60Kwq)DcGBd%cov#iB&LF zxTW+5!Q}LUQl8l?!JUU7Zz~!}o+s8X%1xmFf9s~rnhDLBE%YVew5HI3-z_x(hROnj zNLAXryqM0&nDLgNxw4IJ@oMUDI>X-hx$I~uwAL=JOj99UZd6NIIE%uOH+cF5a zku(9B$}dW0`Fd?BhYEEqlmBvG0hMQavJ4*|o^rIHd-`Ah|KG-aScOJbD0nZ}CAgA` zd-Sh`eu2C8i~|3?POuYiuX-C`0FG|u;mDGf2$(#sC05&Uf&n-MA9&7@xlWX3 zZnA16{%U#n`Sb9nhx9K|&W{An7`Fam5PYQOo>+BJ*_e6zyV_ckV*0L2y0zIzt#kTR zVZ)c$GqBtjk*bm@DQv-|{;GhC2QxY!#hYtwE z3%oQ3o&_;e_yx;vj*va;2PWOqz z1u>u|##{nu=ETKAn)!1FZ8=A3kr$sGj8;l*8AFex1B zD%mxrZ8zWeAFH<>_wEiCEu7lnm@_*$K>opszo`-Gbjx9HVBWa~`qf2oW?B|f&ByK# z>ZGunJB_!cH`{LHtg9T9VYKEu|4b@zDrJMVeO44C`&AFz;9b}vaY-D|31y0#)-~-+ zbYJ9#pUK^@FXtBrJ0^`jg|948EgB-LPF7;~ zNEjyia&Y!ehPCpwJTD6$1X`{T zAY;A-QN)xfLn_F{@x94CHJ56o!iRw8a#mk7hRP)1TOiMBTkdzk{ zoM~6f(>k6j z+_oFZOg^ax^9q4+Rh0)Cb(&yGA*4113)Q`(R?C(5-+k9y@b)+ihR@ZJu8-WBsM&#( z4#DohjNdkomVLWRej~VsQM_X{h6$z(E3+lOX&!AD7w^~hLdv{t1KJ14u}v{E4Yp;g zfzlekIH~kdOvYpmqTzS3WFR;#I{S->na1nzz5WrE>g+JzR!GIH8Zb%)6u1T~3l+AK z-<+`H3X~i^)7uB4@1e(gT-NMw#Px#MM8X_OHcriP!`h5aPC`^H<&h(B>*Km~#~0LU zzdDvOX9(D0i2&O&npsvpLFEqDh@dR6a`E%+lAuk09G`W71ZtV>EXe#VWxF_BDka85&VTHjTHE{vbKWyIZ(1B zWuMT{oOOs2{E$_~(sCz{5Jbd`~Q;0LXAdI`$HJ`T>~m!ca9^fr%4i+@h3P~!;;*a8C)1; z$5Bc}Cn&NaE%B&4CR)_If@Cvx*vX>@*D8h8YZlo$#)?aFZ6&>D>@GHn3lj=!EZdqv z-5@INPc`h8dIS=73c^TPC~e!;U2)>aQkgT+_0XCpzsq75W8G&t?~SfLg=JH|oSKT4 zowYSUKUA&|EKF)_E&`L+YAFHIf7b3i^()TavAqoaF$t!ni1xWnI~v1@K-J?e^le^CTtYATn*)V~f7`4*A7*i|J57-_bhtoRiq2(2e3?BZM^| z6kY>eCuk#zppekJw`_hK|2BE@8Te}+Lpvx}o_yqq>BlJ=k$oLzIPyUtZA#p(ZiBkR zj?M7iDNq%Pa*CdgKA>C;rhsDNPYEnv;9jO&Bj!~9uf1aa=Po|Wt5ow1 zXBvF{bvV^z`NyABLR5BQ?i8#Twzx3`ikQu2kW>$EeV5B@^^?ZIkp_V=~2u0HWTKj$# z7axb-`5w2DB(terHj$z=`>o87eaAYzjy7LBK9026>RES){exXDX`F3h3MwIcHk+Nf zO4KswUSH;eXzBTNk1a-9{CrmCv);<-tkJ5zuor*e_U4%Wd+gu2lc4VSDJC=N`%r}6 z7kQoBDUQYk>Xap{{IG3%buTh}B_=>oC%m3d8XQcz{i~y5XtMC=4;Akh{ZKWkdGsHe zurPv8Q{;H`yKL0u}2 zDrk>c23m|f9bH8XDnj`XyLu+(=q|b71sC70A*R39jO0&XpB?bXu$^VzK8yx^rHI6s zYx|rX-679g?1Mxx-?!DTaEH>PKo@4ft|l)eOJ?LlRNh7ml9^3|!XG(`Y-oeCxm3gN zMv~`G#9WdSo^Y(-lJN^`2XfcFgoHGf1ZP{fc$J0pDVtb~j`^T^Q@Mpc;5B{U&6$Eg zh{5AV=0L0biaAaN&V=cnGO-a`9xHqwo!N0HT~tDcC0O7a|5@*SK5?eWUr$4274|$Drv;5EKEH{!cx*=5_3|9%-Q1o&#FFd?ze_}b< zJl}1p)_~)LCSD|d?IY>;!6xRE`1$${WoB0#D|b&vX_Y8?tTzdIphVaGYRKW2g?r(m zrZO-Y`(&qC<0jpmJ-qXe=IX7Opeb#FR0Da&=Fa%_2)(emoO|HC^&|YYuG|Q35!l8E zudP9B4>^(GAsHBR=;Ut3f8F<0%4>EzJMaX;KyE%4FR6TcIfa=R=pS~^2Bz}Rmt!nc zY`C#Yhhtc3RAf+AfSd%c>_1#Wsb{a4;pBNH#}5Y>rHjxB7jnXaEosLWo~*mS94$|8 z3yrm(GrIt&w}jV~Q@;{Pblhd@n+kL;tBlKgFD&L~6o$PymSUaE9FMS>dA;XzL(H?} zzTU)`)@%V)k#ZVVFk#%~D!x;Ox5mgUAMsU1PwGUabnp4A?_$_tWa`zp7mf-#?Rd*^ zMWcX4Z7e(ameWe*?8MCz`E3MW<8;yIo2DzccjR@)2!Q@CUbJ44WdPdGm zE;b)=p%$`Hwnm++(Wqx5_;mH0({yc%1nutnn({HJKZJN}?5n`9IEpq8)L zP}lwua@Q6$TRs!0E0R>=8#80pQmINwI-A%z#~etz_)+BI!>i;6zU{WyAtg+#bPp%V z{M*_LV^M(CHT-LOBem%pnagxAor-Z%M6~zrx?Yh)Igx8lNOq!RS>`sbX%9nMoZqi9 zdbR&{?E8(Kbj7R77EDFVf9NMgp&W@HU^FF@0%c<W)8%-8(O8{^cIn90qb*fs|9!lfJx2cUrujb9y}A6jmCvk{JnLc8f<9BCSWWgU zb7)#AhP9@*iKKg7bNuM%Gq>e9D}o7%+*I-;P7C{r<*VphzNl^LkzwmrbU)-_PBt+J zuw?U(`3lX%-Q_Ow4=U^#g>uEG4R{?i;8O!D3+v{(SnJ6ywrDAq?&F%mFUzn+)>8kb ze4ZV)8({`k#xUE>62JY|Vh4mgfQEC{%Uw0qYtAepM>@@(o|$H_yW)_MKc5eyx*4RO zGq+CK6Lg;)q4Nuatar`t#jkiu7a_Qtue>sK}Q!5830Xi&aXMZx>6*tSsFI`NdSG_-fIvO^D zo7QVxK|OYz5N&zXFLVzY9|WfPZ^I`-1tb?p9xFO0Cv zT4Uo-g2hjCH_j_~sWCA;Qv%lRB@Z7U?Hn^7R%_>8s81l7~jWIp7@- zR!-FP_+|F$o!922PK3g#2VY{_s(Qw_8g`8g3!hxF1TK~}*0L;8zg;e}+c!rz;GtCV zhEeAz(yOA(=qK)gSx?CcOUqv@^b;=damP=*qtm&|ScR_wu3?nsZylHkdQ$k6CTPmL z)pvK3jy+O`<67_H`oiA@BtrG{nB>CeD8oZbH^Z@LKg}p0^hbva?y)okr(t5&Y}ejw z#P8`|daQJUic4`zs2PM9JsBRjGw{z^VWr|-M1pnp*@86WRIuxX{;~^xxRlA=fJ*v0 zgq8}E$+nQ3gtA(#aDw$)W^t%__+5V9WmfL_U8FThZ5yhOhz-@DQt=M6sTzzDxdDW+ zz@d)(QT9RkRu#2b_-m2$h7W=bUodvbsBv1?_2TDyMUDLLh9&NavM2TaUw zJ#Hsd#xB6y-I2zgZg2gSNES75faf;Z^0gyrT!?>Jal^{vPUtMFyt0l>a`Ieof70iW zm6H5HX>lT3qFRf$p3XE4%P;=%X6jJ~jM)VsHuKH$zG~`7RE0Tv)ZL_jl$aYSE}?gIDI&6={_nZD+M&6Ixhjh;=o=vKr5 z)01>0T+^t^U@Z#*X+`)jqd~95Z0=Pa*O3fRQd3Zw z6p&~eZ2X^I`yK=SVM>SVa~8_RSH38kEqpldxr};;QatGk4Yf#@&VaIWo>3V2*FrWO z&>XuY?Db8Nl{xfcoz=7YcHUZ$ao@R;_Df82H?sU+J3N8}4U@mO8sdb1nra@mvN~B; z5M!jxg)-nJU{}nWw$ftMba88kx_z&0sHj?@RMd?5ogeHM5TO1GI=Fel$ zUmp%8napPwyB3YEOUEjnV^uDk8VK20`LoS1V3&4yqbRhx`pj9Y{KA)}t75>|EZ4Pz z+$QyPS6Z2*uAL+u$_+8~+*ubof(tmW#it3_R238sIU@r*Zs0$N^~*_ct_zz@K-UG3 z1SxrM=16|!+xWJ3u4_AyxKn7PrQ?ALA|=##RL`eAMR9}P+VMGFlzm(&MV~<<*8ALj zSYU@@pep2pA!K0=-?@IYThV%SIPNoWOFIEtlVbKIt`M%5HdIMx{q<&dt<1dMSWlDx zY}Kb^@v(W-6L`rDNjE+Vp_^cqHQTk32IJM}K6+x%>z>;@DIFUIqgX}1pE83*`Y&l7 zbrX;w&V9SkR6@XOYGjx2=MlZngv^Y)asfhtZ-#Y{A8H0G40HR_mK}>~*PVB7-L7Qp zh0U2YGT}(y2oWng<%NI>DRA#(%kfC>hKAOt2W1|t!rCUC%UX^+ce;=FW$N^Wha9Yb zsN7HA7@f)0X~kVDV-PIP+Aytb;>&XylVArMxST%K5dsV)Fv=ZJt4tt2G}bt*>|kH9 zYYyh&xBn{5OfM%a(yLq_l5MKX)x2g~4wFnFyE^=J$eDyc|BzfTm$+UlvC(^xvm7V{ z-(|>emd5rTMsn5*q;Tdbq74K(vw!nFAYHZZ&VCi-WWKrPhqC}LHQpnjc>Kl(?8GG8 zXX50kk|dNt zG1{00Y1eSjpS(Q%cRBq$0R=r}ad%Ef11@liXP0>~GvXJQD#Nd?0pLzxE1-4+2+4bxNgiQo8sCed6 zl#!1;F6M3;p#KIZYt`ZKk3WfqVO-Gb8+3ltxj3sPvvlxY4~PHm&O@D(tr(GSZlsw^ z+!d*JC2BKWz8qIazME!}@1cV=4R9Xo+WqUt9Z9>+DjmUK0lkympk>URQ}2Tdy2W*e zTZ7oU4{ZhG=4Yab?`m{O1vnW}`k$_qz1Hn*da(DLi-^=QH+`JhK!2q`Bt4a2tSGb5dpx>4KUy35(Uuj{vZNS}%`<;d+++(uN?* zmz)X=+2R9d3!qbduFYhJ(E;sKdb#3qDDGP?{MK62>+@&V(kiy1N6r4?we0(nHnG;m z>t3}!2|>{KYg=acHUQ1a;3uK?gcmL~nrmnf?<3+g;5T5$1MsP4^$*#y;L)|Mbtj*& z&3N6OJ)LtN5mr?g03G@Tk4g8`WdsFAjI_?Swwl}O?$6GQp%->r5a93j=a~;O2uN(Z zYss-6CleDhkGqihSb)a>+*aVSq@XUycs!3?o&Y=CC8rVvV=LYaze{5 zcoxww=AiZG4iFG~Ec_Led!EKbsNln+Wr_#E!JQ8A7(jw9P9)b;>bi3()51s6IjhEy z?^v3j*`^8}qE3x1|$AXv(=0&NgTHQ&F zywj)vi@KF`>k`75_z(*-4EC~Z<#@WvC}I3dGAD1_~zH!O(v7IqIe4BIqMSQ?7NNiFOQs(^B&$^7kdf%#c3trk~x}(Z5{x zz{FfIJY5fYCY_#b5=KkiG4L?Wcu?18?MCrow8dMQw^ziJz(wDN9(*{SB~!O~KL}bU zc27v6zjsOIEG6amzTG+QjXRK)>MpsD_;g+|#a~%Ow{!)iGP*k+E+}*~N<+Hq&SM|5 zj1_OnYP-|qqf|V3pknwf<5CYD+D~PEazu>)pm-v z4Dh?(3xNihTD~@Es>$N20-{@wpqg|woE&<7q=`GXAiZE)?L8|!s;9rv(#I5&-c%e} zM|w%Jke*p(@*a?-iO6Z%XvmDcFy()i`3^-Upl)&Cg~rJUfz<$@a|lgyTvoD>YI~Nq zA!r0yeXr})0G5=R4YjD43GBPBWoKJ9$Z+LZMVtcRTJ*J)6%*80SvHe^*GH5uokGb3 zY(SX#B~2_#6SLqy5Hqs>ABf41^7T8Ee7IfIFRh%#*oTK0!) z=CRMu9|&zLsOF*!vn4?)QL{4J!;&lL-V51arL?`Xa_Tp$DrsM;82<9axXO>xa1Elu zLXSc5>xvoRvPq>oB*yh87Q$XjrNN4-)z^=SAzlrePLHZEN6;Q27YvVbIfch@qWT;& zfXdfSHd9K4b;Lr_3N3<_Wz}2SA3x%&$WHN|Q{brt$Mu7aHLQwO)a>NYvYR_9_JX#C zC||2FkipF*oMRutmI(%Vg^hP_81WnMekGy$`{M3BYPEMSZ|eZr)<=8X2O(7oo--?q z>=r-??3JI3^x|4$O$)zHLEkiR6%iX8mYvYrK;VYM0RoNK4bZFT5Bi{4E@i)_8hd5y zRt={%AV)Ig6hSNK_>Vn!+kO?v}ERchm2*$)u2lQjQ*=BA0jwzVepyP^)nBUVi40UQT6gIn<+N$Kz93U z-;McN22!_FhgDNiFMTT_hf1pfLmFe{L_{uA54zHo-OS}gkkdWSCRj%O1A5m^Vy<$Z zUkYeD40}B<+B;7hEu@-i{DRHbUSUen>B?vpqm1dZmv7ix^KV%awpuO+=pn6c zfNR$#Z4)*lcm})NRhJ=Ocfp7o8YDp8w`|nEbpxywA(a?_3Imgy*J@E&I^6|gVV}m?7`m?ksFY{-=2|n(OV;9YRE`=H z5qnAKv)*U;k0D05Z2LWy=F3gxwM5m;tqh%)4}zP4Xh2~*r1CsLD{3>=UXE2vxdY>V zIy#9W6JqH_rE=2j4*oi&_{)~?bvl%%3Gym?e!%wpPWxE+?ke)qgtSI%i*-J}F+`y0 z6CHo>w5q}};=#k8>h^wGnxPh~S`H~`?w>1r8tn5q`Q_ycTOTK+B)zMV7q@AQ(>8>s zi>}uE;O}D#+Ywas6j``xb2csEQDx6+n&paDVwrKSgGk1-0B&>Xh8zWd!Zb~`QupHg zZXzOs&kgWPaV8i@Rt87(m+Ff{Hbtji*V6=*GL+yZ#wM_~1XC9OR?v#m`Q6=wVxxsV zg_Lq#SA7%#m+Yr-v%@=WgmaHrzJ{!#9=xOQt6sfe?P!J7WqHwcwFdd9s+#AJDXg|m};d2##GwM}46=w0Xd&%K)eLN~ra414L z{Cq<^>e2drjD#m0j}xjU_=c!Ab&+jr>sCZl=s(;5AUBTzRS^o`H zpM7kwh-^H?ASN*{!{%6SC2N;OS5yD*hg|_xArR=#4~j?ke*vI<8ZY0FYocWvY$Wws z-btZhx!BDm(5lz{$f$ISTshWS0t1g5<@CllU8?rO9}Z3SkEbWMl^vYeX!*TTI>}2W zR$qpY#isRHpnE%G-ekiWX%W}&g|r|cN;zi?=&Od#*W=*nYdfe*`d?C<(iIbLlwPT5 zAW5^ZRv?obYj*ky1ud+m@67rXrye1K$Zbo1I{gkTR^`1AiKjXe>b6SYVPKXNAIM(s z>#WY|2D8XF+Y}wA0D7SBLew3+J=eI;7gR0fj-g1VjPP2mP}@I&t}W$?haZfK;|#`U zTORW~Ejdr8M0qCUU-;GSeyhW*gFwr1*4XNAMR5o+Mp(GCenNd$DXzB(Bd1r6RrN;qUttH#1Hwc%kY8cH&f1o2z5$E$dVv@{6^(WQaXfHU*UwyYrlVMY`1gM z?#X(Bj9;UfC_RI>}GAAkcEkp$u0tiuBP>roFc9 z{7;734nqVS*ucoq>_5pZ4Cy$!J=r?FB|qB)u433jDDq`O_1vbkivqHVjHeAR0A$s_ zSw5wjk2lsmv0^07B}08Dvs4;PStg?{G8HTnqN>+laUSDay~kSpo<2OEHJSdh$;Fao zTs%h`d#9y(DT&rl@e5r`RP_(mQN8f}fwYtONv>`}qwRF)_9drO0~cGZCq;>9)6Tr~ z$>Zc#ZYA0pnwS;67j9t!x2GoW$Q`yB;7Mg02Kedft++ranmzEoF!A{;awlI-X~p`S zRlv;4lSt_T!^oE-=M{8w-S)@*4duLS&Sy>rOso+2tJS~gdu4T<+;nIRYuvlbHLHX{ z#&qfIYtS*fjyGq9?wi^+uC^}kd5kxPfR`%QUZRB4w_spNX$%nCnb6m- ze#65QU$P#@u=Z79GU6#2AyD5E`Ni%_&=dYW|B2rB|t*W1y_MJn(rzA$lcKt|&!w(jh(OV{00=ldPdKj2VuH<&^gMg%C zl7m1)Zp=KQz?{o~=yDukT#DUzl)eixC_nFQ^6a>DuJ(pLOWGwD+eiHn!`|pM%Ch@2m2SMMGLc$mf=kgydS6MNFP7wU*TYpZyt4lUy**& zbvjYq(63NCTi|@t=fr~tg?`V6Uflyr=NrS@=8qI6L0`8&qJO%`*h`Nb@&;m^Vg=x+5uMdtF~|*)=~EtnTwZwk6+5Uy=(T!ZvFJ@cQDGvmi0J~j0QdV zpw$+DqOS`y?4Oho+hhc5i6V>F#V~d158o?;Zb9D&?Z+t=sh%hxK=BS|jXLEFy@_1at`L+I zaP|I!zTTc=Zcq4-gYvUsoWo}(FyB$0@+4z=jxA3d%)?Ac*~W7uJ;vsvX1sq8kj%4| z`;(l#V#I$=?xWc$uR&z@oh0FwSmW98kdIJEF)04`O&8esXZzgD+-DzT-^hCEMn(ip z9~|B&(X>_QO`3eFl6r{}3ktm%%$VBseFCf(&l!4gPh@(eD0%&KOg$8^Cd?^B|K$L| z<>lb%QQ^vFsEEv(aG%|oX#4m|Fx{H9h$PRgl)fcf*Prg%xxx9f*9uPb80+{^$a+@f zL>Z>2;?Ta5+Lxp-U84Ve0@_IWa?O*vBgHU?@S=IqT7*zp{ljcZ1W>MQ3UMy+9{3Jy z%puicvCI9Xe`3AaCnXP4=uMir0?AOKpb?^Atf96%D=dIx1e|-dHPrFSlvy5A4KFLm~6c(E&nXL`kx4ZeThhyt?|U&a~*`&{+mnk{lkC8Waamcd;^CYE@ZS` zKs8n44)&@GvEZJJ_=39O3#|j*=b6(zY>egH8>AoNTNQUTg1X-?Rt$7M#JpdeK#KEY z_A*Jo22MH+F)aDt-RDh%cJj9--&etv8eENSGbQ+)N&2=-Zk4})5YLe-)5_Et>eJ!> z02F}yaZ~KoJ1(`XjVmNum!E}8>>g9yrH^)8`{&9M)B)0kfWCh$k%eW(lws8rI4)$u z|FXPp`+bYB<;nr@4jt+p}HT55lJJdy{)>s#^`o zR=^p$7bcVxbg#c}#rX$7{u+S#=d+o9dWXI02}{Rw`pEef*OT;1t{pt`%W_N3>Ec`i zq;%&0X1xOGj35x6;vWRQ>i=|xeBCdq&serPLn|X55)-G7q8pIuzQastVS2n|@drq_ z1c4s^&Bz3D`T-;eyyT`NjRVR1Q$Ux2pQpev0Q~%a<;}yAqcE@2>_&Gps`)AH)_kC+ KR-y9v<$nQ`=B|+d literal 0 HcmV?d00001 diff --git a/media/bing_map_create_bing_maps_dev_account.PNG b/media/bing_map_create_bing_maps_dev_account.PNG new file mode 100644 index 0000000000000000000000000000000000000000..6563036b6ec326e6235df3653cbbf3de10d671ef GIT binary patch literal 44148 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 literal 0 HcmV?d00001 diff --git a/media/create_bing_maps_api_key.PNG b/media/create_bing_maps_api_key.PNG new file mode 100644 index 0000000000000000000000000000000000000000..b3b7508d4246ac6217e64bb6d6637836bcf6e693 GIT binary patch literal 16338 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 +function Format-BingGeoCode { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, + HelpMessage = 'GeoCode API results', + ValueFromPipeline = $true)] + $Results + ) + begin { + Write-Verbose ('Starting {0}' -f $myinvocation.mycommand) + } #begin + process { + Write-Debug -Message ($Results | Out-String) + + $Results.PSTypeNames.Insert(0, 'Bing.GeoCode') + + Write-Debug -Message ($Results.PSTypeNames | Out-String) + + $updateTypeDataSplat = @{ + TypeName = 'Bing.GeoCode' + MemberType = 'ScriptProperty' + MemberName = 'formatted_address' + Value = { $this.address.formattedAddress } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'Bing.GeoCode' + MemberType = 'ScriptProperty' + MemberName = 'Street' + Value = { $this.address.addressLine } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'Bing.GeoCode' + MemberType = 'ScriptProperty' + MemberName = 'City' + Value = { $this.address.locality } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'Bing.GeoCode' + MemberType = 'ScriptProperty' + MemberName = 'Country' + Value = { $this.address.countryRegion } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'Bing.GeoCode' + MemberType = 'ScriptProperty' + MemberName = 'PostalCode' + Value = { $this.address.postalCode } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'Bing.GeoCode' + MemberType = 'ScriptProperty' + MemberName = 'Latitude' + Value = { $this.point.coordinates[0] } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'Bing.GeoCode' + MemberType = 'ScriptProperty' + MemberName = 'Longitude' + Value = { $this.point.coordinates[1] } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + # set a default display of the above properties, all other properties are still there just not displayed + $updateTypeDataSplat = @{ + TypeName = 'Bing.GeoCode' + DefaultDisplayPropertySet = 'name', 'formatted_address', 'Street', 'City', 'Country', 'PostalCode', 'Latitude', 'Longitude', 'entityType' + DefaultKeyPropertySet = 'name' + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $Results + } #process + end { + Write-Verbose ('Ending {0}' -f $myinvocation.mycommand) + } #end +} #Format-BingGeoCode diff --git a/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 b/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 new file mode 100644 index 0000000..f10a6d7 --- /dev/null +++ b/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 @@ -0,0 +1,192 @@ +<# +.SYNOPSIS + Engages Bing Maps API to return address and geographic coordinates based on provided query parameters. +.DESCRIPTION + Geocoding is the process of converting addresses addresses (like "1600 Amphitheatre Parkway, Mountain View, CA") into geographic coordinates. + This function can take in an address and return coordinate information. + You can also provide coordinates to return multiple nearby address results. +.EXAMPLE + Invoke-BingGeoCode -AddressLine '148 S Castell Ave' -City 'New Braunfels' -State TX -PostalCode 78130 + + Performs Geocoding (latitude/longitude lookup) on provided address. +.EXAMPLE + Invoke-BingGeoCode -Latitude '29.7030' -Longitude '-98.1245' + + Performs Reverse geocoding (address lookup) on provided coordinates and can return multiple address results. +.EXAMPLE + Invoke-BingGeoCode -AddressLine '148 S Castell Ave' -City 'New Braunfels' -State TX -PostalCode 78130 -Country us -Language en -MaxResults 20 + + Performs Geocoding (latitude/longitude lookup) on provided address. Results are biased to the United States country. Results are returned in English. Up to 20 results are returned. +.EXAMPLE + $invokeBingGeoCodeSplat = @{ + AddressLine = '148 S Castell Ave' + City = 'New Braunfels' + State = 'TX' + PostalCode = 78130 + Country = 'us' + Language = 'en' + MaxResults = 20 + } + Invoke-BingGeoCode @invokeBingGeoCodeSplat + + Performs Geocoding (latitude/longitude lookup) on provided address. Results are biased to the United States country. Results are returned in English. Up to 20 results are returned. +.PARAMETER AddressLine + A string specifying the street line of an address. +.PARAMETER City + The locality, such as the city or neighborhood, that corresponds to an address. +.PARAMETER State + The subdivision name in the country or region for an address. This element is typically treated as the first order administrative subdivision, but in some cases it is the second, third, or fourth order subdivision in a country, dependency, or region. A string that contains a subdivision, such as the abbreviation of a US state. +.PARAMETER PostalCode + The post code, postal code, or ZIP Code of an address. +.PARAMETER Country + The ISO country code for the country. +.PARAMETER Latitude + Geographic coordinate that specifies the north–south position of a point on the Earth's surface. +.PARAMETER Longitude + Geographic coordinate that specifies the east–west position of a point on the Earths surface. +.PARAMETER Language + The language in which to return results. +.PARAMETER MaxResults + Specifies the maximum number of locations to return in the response. If not specified the default is 5. +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + + Example: + http://dev.virtualearth.net/REST/v1/Locations?countryRegion={countryRegion}&adminDistrict={adminDistrict}&locality={locality}&postalCode={postalCode}&addressLine={addressLine}&userLocation={userLocation}&userIp={userIp}&usermapView={usermapView}&includeNeighborhood={includeNeighborhood}&maxResults={maxResults}&key={BingMapsKey} +.COMPONENT + pwshPlaces +.LINK + https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Invoke-BingGeoCode.md +.LINK + https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-address +.LINK + https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-point +.LINK + https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes +.LINK + https://www.microsoft.com/maps/product/terms.html +.LINK + https://privacy.microsoft.com/en-us/privacystatement +#> +function Invoke-BingGeoCode { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, + ParameterSetName = 'Address', + HelpMessage = 'A string specifying the street line of an address')] + [ValidateNotNullOrEmpty()] + [string]$AddressLine, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Address', + HelpMessage = 'The locality, such as the city or neighborhood, that corresponds to an address')] + [ValidateNotNullOrEmpty()] + [string]$City, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Address', + HelpMessage = 'adminDistrict - A string that contains a subdivision, such as the abbreviation of a US state')] + [ValidateNotNullOrEmpty()] + [string]$State, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Address', + HelpMessage = 'The post code, postal code, or ZIP Code of an address')] + [ValidateNotNullOrEmpty()] + [string]$PostalCode, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Address', + HelpMessage = 'ISO Country code')] + [ccTLD]$Country, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Location', + HelpMessage = 'Geographic coordinate that specifies the north–south position of a point on the Earths surface')] + [ValidateNotNullOrEmpty()] + [string]$Latitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Location', + HelpMessage = 'Geographic coordinate that specifies the east–west position of a point on the Earths surface')] + [ValidateNotNullOrEmpty()] + [string]$Longitude, + + [Parameter(Mandatory = $false, + HelpMessage = 'The language in which to return results')] + [languages]$Language, + + [Parameter(Mandatory = $false, + HelpMessage = 'Specifies the maximum number of locations to return in the response')] + [ValidateRange(1, 20)] + [int]$MaxResults + ) + + switch ($PSCmdlet.ParameterSetName) { + 'Address' { + Write-Debug -Message 'Address specified' + + $uri = '{0}{1}' -f $bingMapsBaseURI, 'v1/Locations?output=json' + Write-Debug -Message ('Base function URI: {0}' -f $uri) + + $fAddressLine = '&addressLine={0}' -f [uri]::EscapeDataString($AddressLine) + $uri += $fAddressLine + $fCity = '&locality={0}' -f [uri]::EscapeDataString($City) + $uri += $fCity + $fState = '&adminDistrict={0}' -f [uri]::EscapeDataString($State) + $uri += $fState + $fPostalCode = '&postalCode={0}' -f [uri]::EscapeDataString($PostalCode) + $uri += $fPostalCode + $fCountry = '&countryRegion={0}' -f [uri]::EscapeDataString($Country) + $uri += $fCountry + } #address + 'Location' { + Write-Debug -Message 'Location specified' + $latLong = 'v1/Locations/{0},{1}?output=json' -f $Latitude, $Longitude + $uri = '{0}{1}' -f $bingMapsBaseURI, $latLong + Write-Debug -Message ('Base function URI: {0}' -f $uri) + } #location + } #switch_parametersetname + + if ($MaxResults) { + Write-Debug -Message ('MaxResults: {0}' -f $MaxResults) + $fMaxResults = '&maxResults={0}' -f $MaxResults + $uri += $fMaxResults + } + if ($Language) { + Write-Debug -Message ('Language: {0}' -f $Language) + $fLanguage = '&language={0}' -f $Language + $uri += $fLanguage + } + + Write-Verbose -Message ('Querying Bing API: {0}' -f $uri) + + Write-Debug -Message 'Adding API key' + $fAPIKey = '&key={0}' -f $env:BingAPIKey + $uri += $fAPIKey + Write-Debug -Message ('Final URI: {0}' -f $uri) + + $invokeRestMethodSplat = @{ + Uri = $uri + ErrorAction = 'Stop' + } + try { + $results = Invoke-RestMethod @invokeRestMethodSplat + } + catch { + throw $_ + } + + if ($results.statusDescription -ne 'OK') { + Write-Warning -Message 'Did not get a succcessful return from Bing Geocode API endpoint' + $finalResults = $results + } + else { + $finalResults = ($results.resourceSets.resources | Format-BingGeoCode) + } + + return $finalResults + +} #Invoke-BingGeoCode diff --git a/src/pwshPlaces/pwshPlaces.psd1 b/src/pwshPlaces/pwshPlaces.psd1 index bfa6dd0..3eb3d13 100644 --- a/src/pwshPlaces/pwshPlaces.psd1 +++ b/src/pwshPlaces/pwshPlaces.psd1 @@ -12,7 +12,7 @@ RootModule = 'pwshPlaces.psm1' # Version number of this module. - ModuleVersion = '0.5.0' + ModuleVersion = '0.5.1' # Supported PSEditions # CompatiblePSEditions = @() @@ -72,6 +72,7 @@ FunctionsToExport = @( 'Find-GMapPlace' 'Get-GMapPlaceDetail' + 'Invoke-BingGeoCode' 'Invoke-GMapGeoCode' 'Search-GMapNearbyPlace' 'Search-GMapText' From 2604c34de0f9d0f3d2984b35737315fee58bf99e Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Thu, 7 Oct 2021 12:32:42 -0500 Subject: [PATCH 12/22] adjusted workflow syntax --- .github/workflows/wf_Linux.yml | 1 - .github/workflows/wf_MacOS.yml | 1 - .github/workflows/wf_Windows.yml | 1 - .github/workflows/wf_Windows_Core.yml | 1 - 4 files changed, 4 deletions(-) diff --git a/.github/workflows/wf_Linux.yml b/.github/workflows/wf_Linux.yml index 073c323..d27497e 100644 --- a/.github/workflows/wf_Linux.yml +++ b/.github/workflows/wf_Linux.yml @@ -40,7 +40,6 @@ jobs: run: Invoke-Build -File .\src\pwshPlaces.build.ps1 env: GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - env: BingAPIKey: ${{ secrets.BingAPIKey }} - name: Upload pester results uses: actions/upload-artifact@v2 diff --git a/.github/workflows/wf_MacOS.yml b/.github/workflows/wf_MacOS.yml index 03bd406..ac3adc7 100644 --- a/.github/workflows/wf_MacOS.yml +++ b/.github/workflows/wf_MacOS.yml @@ -39,7 +39,6 @@ jobs: run: Invoke-Build -File .\src\pwshPlaces.build.ps1 env: GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - env: BingAPIKey: ${{ secrets.BingAPIKey }} - name: Upload pester results uses: actions/upload-artifact@v2 diff --git a/.github/workflows/wf_Windows.yml b/.github/workflows/wf_Windows.yml index e82626f..e6ab9c2 100644 --- a/.github/workflows/wf_Windows.yml +++ b/.github/workflows/wf_Windows.yml @@ -45,7 +45,6 @@ jobs: run: Invoke-Build -File .\src\pwshPlaces.build.ps1 env: GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - env: BingAPIKey: ${{ secrets.BingAPIKey }} - name: Upload pester results uses: actions/upload-artifact@v2 diff --git a/.github/workflows/wf_Windows_Core.yml b/.github/workflows/wf_Windows_Core.yml index e3b5640..6ff3e9a 100644 --- a/.github/workflows/wf_Windows_Core.yml +++ b/.github/workflows/wf_Windows_Core.yml @@ -39,7 +39,6 @@ jobs: run: Invoke-Build -File .\src\pwshPlaces.build.ps1 env: GoogleAPIKey: ${{ secrets.GoogleAPIKey }} - env: BingAPIKey: ${{ secrets.BingAPIKey }} - name: Upload pester results uses: actions/upload-artifact@v2 From e570e10a4cfa7f2b0123e3b30302cbae92c5ad76 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sat, 9 Oct 2021 15:47:04 -0500 Subject: [PATCH 13/22] added Find-BingPlace --- bing.ps1 | 2 + docs/Find-BingPlace.md | 345 ++++++++++++++++++ docs/Find-GMapPlace.md | 4 +- docs/pwshPlaces.md | 5 +- .../Infrastructure/pwshPlaces-Infra.Tests.ps1 | 14 + .../Unit/Private/Format-BingGeoCode.Tests.ps1 | 2 +- .../Unit/Private/Format-BingPlace.Tests.ps1 | 45 +++ .../Unit/Public/Find-BingPlace.Tests.ps1 | 106 ++++++ .../Unit/Public/Invoke-BingGeoCode.Tests.ps1 | 18 +- src/Tests/Unit/TestObjects.psm1 | 50 +++ src/pwshPlaces/Imports.ps1 | 98 ++++- src/pwshPlaces/Private/Format-BingGeoCode.ps1 | 4 +- src/pwshPlaces/Private/Format-BingPlace.ps1 | 80 ++++ src/pwshPlaces/Public/Find-BingPlace.ps1 | 254 +++++++++++++ src/pwshPlaces/Public/Find-GMapPlace.ps1 | 4 +- src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 | 8 +- src/pwshPlaces/pwshPlaces.psd1 | 12 +- 17 files changed, 1038 insertions(+), 13 deletions(-) create mode 100644 docs/Find-BingPlace.md create mode 100644 src/Tests/Unit/Private/Format-BingPlace.Tests.ps1 create mode 100644 src/Tests/Unit/Public/Find-BingPlace.Tests.ps1 create mode 100644 src/pwshPlaces/Private/Format-BingPlace.ps1 create mode 100644 src/pwshPlaces/Public/Find-BingPlace.ps1 diff --git a/bing.ps1 b/bing.ps1 index 28317e1..97b16aa 100644 --- a/bing.ps1 +++ b/bing.ps1 @@ -45,4 +45,6 @@ Culture Parameter &c= User Context Parameters https://docs.microsoft.com/en-us/bingmaps/rest-services/common-parameters-and-types/user-context-parameters +Types + https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/type-identifiers/ #> \ No newline at end of file diff --git a/docs/Find-BingPlace.md b/docs/Find-BingPlace.md new file mode 100644 index 0000000..db331e2 --- /dev/null +++ b/docs/Find-BingPlace.md @@ -0,0 +1,345 @@ +--- +external help file: pwshPlaces-help.xml +Module Name: pwshPlaces +online version: https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Find-BingPlace.md +schema: 2.0.0 +--- + +# Find-BingPlace + +## SYNOPSIS +Returns a list of business entities centered around a location or a geographic region + +## SYNTAX + +### textquery (Default) +``` +Find-BingPlace -Query [-RegionBias ] [-Language ] [-MaxResults ] + [] +``` + +### Rectangle +``` +Find-BingPlace [-Query ] -SouthLatitude -WestLongitude -NorthLatitude + -EastLongitude [-RegionBias ] [-Language ] [-MaxResults ] + [] +``` + +### Circle +``` +Find-BingPlace [-Query ] [-CircleLatitude ] [-CircleLongitude ] + [-CircleRadius ] [-RegionBias ] [-Language ] [-MaxResults ] + [] +``` + +### Point +``` +Find-BingPlace [-Query ] [-PointLatitude ] [-PointLongitude ] [-RegionBias ] + [-Language ] [-MaxResults ] [] +``` + +## DESCRIPTION +Performs a find place request with provided parameters. +A text search is performed that returns a list of business entities. +By default the location bias is IP based. +Location bias and language can be controlled via parameters. + +## EXAMPLES + +### EXAMPLE 1 +``` +Find-BingPlace -Query "Krause's cafe" +``` + +Returns place information for the query location biased by IP. + +### EXAMPLE 2 +``` +Find-BingPlace -Query "Krause's cafe" -Language es +``` + +Returns place information for the query location biased by IP and returns a few portion of the results in Spanish. + +### EXAMPLE 3 +``` +Find-BingPlace -Query 'cafe' -PointLatitude '29.7049806' -PointLongitude '-98.068343' +``` + +Returns place information for the query location biased by provided lat/long point. + +### EXAMPLE 4 +``` +Find-BingPlace -Query 'cafe' -CircleLatitude '29.7049806' -CircleLongitude '-98.068343' -CircleRadius '5000' +``` + +Returns place information for the query location biased by circle lat/long/radius. + +### EXAMPLE 5 +``` +Find-BingPlace -Query 'cafe' -SouthLatitude '39.8592387' -WestLongitude '-75.295486' -NorthLatitude '40.0381942' -EastLongitude '-75.0064087' +``` + +Returns place information for the query location biased by rectangular two lat/lng pairs in decimal degrees, representing the south/west and north/east points of a rectangle. + +### EXAMPLE 6 +``` +Find-BingPlace -Query 'cafe' -PointLatitude '29.7049806' -PointLongitude '-98.068343' -Language en -MaxResults 20 +``` + +Returns place information for the query location biased by provided lat/long point with a maximum of 20 results in English. + +### EXAMPLE 7 +``` +$findBingPlaceSplat = @{ + Query = 'cafe' + PointLatitude = '29.7049806' + PointLongitude = '-98.068343' + Language = 'en' + MaxResults = 20 +} +Find-BingPlace @findBingPlaceSplat +``` + +Returns place information for the query location biased by provided lat/long point with a maximum of 20 results in English. + +## PARAMETERS + +### -Query +Text input that identifies the search target, such as a name, address, or phone number. +Phone numbers must be in international format (prefixed by a plus sign ("+"), followed by the country code, then the phone number itself) + +```yaml +Type: String +Parameter Sets: textquery +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +```yaml +Type: String +Parameter Sets: Rectangle, Circle, Point +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PointLatitude +Prefer results in a specified area by specifying a single coordinate for the north-south position of a point on the Earth's surface. + +```yaml +Type: String +Parameter Sets: Point +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PointLongitude +Prefer results in a specified area by specifying a single coordinate for the east-west position of a point on the Earths surface. + +```yaml +Type: String +Parameter Sets: Point +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -CircleLatitude +Prefer results in a specified area by specifying a radius plus lat/long - north-south position of a point on the Earth's surface. + +```yaml +Type: String +Parameter Sets: Circle +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -CircleLongitude +Prefer results in a specified area by specifying a radius plus lat/long - east-west position of a point on the Earths surface. + +```yaml +Type: String +Parameter Sets: Circle +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -CircleRadius +Prefer results in a specified area by specifying a radius plus lat/long - radius in meters + +```yaml +Type: String +Parameter Sets: Circle +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SouthLatitude +Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - south latitude + +```yaml +Type: String +Parameter Sets: Rectangle +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WestLongitude +Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - west longitude + +```yaml +Type: String +Parameter Sets: Rectangle +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NorthLatitude +Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - north latitude + +```yaml +Type: String +Parameter Sets: Rectangle +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -EastLongitude +Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - east longitude + +```yaml +Type: String +Parameter Sets: Rectangle +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RegionBias +The region code, specified as a ccTLD ("top-level domain") two-character value. + +```yaml +Type: ccTLD +Parameter Sets: (All) +Aliases: +Accepted values: ac, ad, ae, af, ag, ai, al, am, ao, aq, ar, as, at, au, aw, ax, az, ba, bb, bd, be, bf, bg, bh, bi, bj, bm, bn, bo, br, bs, bt, bv, bw, by, bz, ca, cc, cd, cf, cg, ch, ci, ck, cl, cm, cn, co, cr, cu, cv, cw, cx, cy, cz, de, dj, dk, dm, do, dz, ec, ee, eg, er, es, et, eu, fi, fj, fk, fm, fo, fr, ga, gb, gd, ge, gf, gg, gh, gi, gl, gm, gn, gp, gq, gr, gs, gt, gu, gw, gy, hk, hm, hn, hr, ht, hu, id, ie, il, im, in, io, iq, ir, is, it, je, jm, jo, jp, ke, kg, kh, ki, km, kn, kp, kr, kw, ky, kz, la, lb, lc, li, lk, lr, ls, lt, lu, lv, ly, ma, mc, md, me, mg, mh, mk, ml, mm, mn, mo, mp, mq, mr, ms, mt, mu, mv, mw, mx, my, mz, na, nc, ne, nf, ng, ni, nl, no, np, nr, nu, nz, om, pa, pe, pf, pg, ph, pk, pl, pm, pn, pr, ps, pt, pw, py, qa, re, ro, rs, ru, rw, sa, sb, sc, sd, se, sg, sh, si, sj, sk, sl, sm, sn, so, sr, ss, st, su, sv, sx, sy, sz, tc, td, tf, tg, th, tj, tk, tl, tm, tn, to, tr, tt, tv, tw, tz, ua, ug, uk, us, uy, uz, va, vc, ve, vg, vi, vn, vu, wf, ws, ye, yt, za, zm, zw + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Language +The language in which to return results. + +```yaml +Type: languages +Parameter Sets: (All) +Aliases: +Accepted values: af, sq, am, ar, hy, az, eu, be, bn, bs, bg, my, ca, zh, hr, cs, da, nl, en, et, fa, fi, fil, fr, ka, de, el, iw, hi, hu, is, id, it, ja, kn, kk, km, ko, ky, lo, lv, lt, mk, ms, ml, mr, mn, ne, no, pl, pt, pa, ro, ru, sr, sk, es, sw, ta, te, th, uk, ur, uz, vi, zu + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -MaxResults +Specifies the maximum number of locations to return in the response + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### Output from this cmdlet (if any) +## NOTES +Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + +Example: + http://dev.virtualearth.net/REST/v1/Locations?countryRegion={countryRegion}&adminDistrict={adminDistrict}&locality={locality}&postalCode={postalCode}&addressLine={addressLine}&userLocation={userLocation}&userIp={userIp}&usermapView={usermapView}&includeNeighborhood={includeNeighborhood}&maxResults={maxResults}&key={BingMapsKey} + +## RELATED LINKS + +[https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Find-BingPlace.md](https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Find-BingPlace.md) + +[https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-query](https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-query) + +[https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/user-context-parameters](https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/user-context-parameters) + +[https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes](https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes) + +[https://www.microsoft.com/maps/product/terms.html](https://www.microsoft.com/maps/product/terms.html) + +[https://privacy.microsoft.com/en-us/privacystatement](https://privacy.microsoft.com/en-us/privacystatement) + diff --git a/docs/Find-GMapPlace.md b/docs/Find-GMapPlace.md index 3a4e478..8c042eb 100644 --- a/docs/Find-GMapPlace.md +++ b/docs/Find-GMapPlace.md @@ -106,7 +106,7 @@ Returns place information for the query location biased by rectangular two lat/l Find-GMapPlace -Query '+18306252807' -PointLatitude '29.7049806' -PointLongitude '-98.068343' -Contact -Atmosphere -Language en ``` -Returns place information for the query location biased by provided lat/long point with additional Contact and Atmosphere fields with results in Enlgish. +Returns place information for the query location biased by provided lat/long point with additional Contact and Atmosphere fields with results in English. ### EXAMPLE 9 ``` @@ -121,7 +121,7 @@ $findGMapPlaceSplat = @{ Find-GMapPlace @findGMapPlaceSplat ``` -Returns place information for the query location biased by provided lat/long point with additional Contact and Atmosphere fields with results in Enlgish. +Returns place information for the query location biased by provided lat/long point with additional Contact and Atmosphere fields with results in English. ## PARAMETERS diff --git a/docs/pwshPlaces.md b/docs/pwshPlaces.md index 735546d..d72961c 100644 --- a/docs/pwshPlaces.md +++ b/docs/pwshPlaces.md @@ -2,7 +2,7 @@ Module Name: pwshPlaces Module Guid: 9a9914bd-d115-4f42-bb5d-19c5e5561a3f Download Help Link: NA -Help Version: 0.5.1 +Help Version: 0.5.2 Locale: en-US --- @@ -11,6 +11,9 @@ Locale: en-US tbd ## pwshPlaces Cmdlets +### [Find-BingPlace](Find-BingPlace.md) +Returns a list of business entities centered around a location or a geographic region + ### [Find-GMapPlace](Find-GMapPlace.md) Find Place request takes a text input and returns a place. The input can be any kind of Places text data, such as a name, address, or phone number. diff --git a/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 b/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 index d936967..6bf4dac 100644 --- a/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 +++ b/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 @@ -128,5 +128,19 @@ Describe 'Infrastructure Tests' -Tag Infrastructure { Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) } #it } #context_Invoke-GMapGeoCode + Context 'Find-BingPlace' { + It 'should return the expected results' { + $findBingPlaceSplat = @{ + Query = 'cafe' + PointLatitude = '29.7049806' + PointLongitude = '-98.068343' + Language = 'en' + MaxResults = 20 + } + $eval = Find-BingPlace @findBingPlaceSplat + ($eval.name | Measure-Object).Count | Should -BeGreaterOrEqual 1 + Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) + } #it + } #context_Find-BingPlace } #context_BingMaps } #describe_infra_tests diff --git a/src/Tests/Unit/Private/Format-BingGeoCode.Tests.ps1 b/src/Tests/Unit/Private/Format-BingGeoCode.Tests.ps1 index a350e37..b701b15 100644 --- a/src/Tests/Unit/Private/Format-BingGeoCode.Tests.ps1 +++ b/src/Tests/Unit/Private/Format-BingGeoCode.Tests.ps1 @@ -32,7 +32,7 @@ InModuleScope 'pwshPlaces' { It 'should return the expected results' { $eval = ($geoBingAddress.resourceSets.resources | Format-BingGeoCode) $eval.name | Should -BeExactly '148 S Castell Ave, New Braunfels, TX 78130' - $eval.formatted_address | Should -BeExactly '148 S Castell Ave, New Braunfels, TX 78130' + $eval.FormattedAddress | Should -BeExactly '148 S Castell Ave, New Braunfels, TX 78130' $eval.Street | Should -BeExactly '148 S Castell Ave' $eval.City | Should -BeExactly 'New Braunfels' $eval.Country | Should -BeExactly 'United States' diff --git a/src/Tests/Unit/Private/Format-BingPlace.Tests.ps1 b/src/Tests/Unit/Private/Format-BingPlace.Tests.ps1 new file mode 100644 index 0000000..c9aebbc --- /dev/null +++ b/src/Tests/Unit/Private/Format-BingPlace.Tests.ps1 @@ -0,0 +1,45 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +$PathToTestObjects = [System.IO.Path]::Combine('..', 'TestObjects.psm1') +Import-Module $PathToTestObjects -DisableNameChecking -Global -Force +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + #------------------------------------------------------------------------- + $WarningPreference = "SilentlyContinue" + #------------------------------------------------------------------------- + Describe 'Format-BingPlace' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + } #beforeAll + # Context 'Error' { + # } #context_Error + Context 'Success' { + + # BeforeEach { + # } #beforeEach + + It 'should return the expected results' { + $eval = ($findBingPlace.resourceSets.resources | Format-BingPlace) + $eval.name | Should -BeExactly 'Krause''s Cafe' + $eval.formattedAddress | Should -BeExactly '148 S Castell Ave, New Braunfels, TX, 78130' + $eval.PhoneNumber | Should -BeExactly '(830) 625-2807' + $eval.Website | Should -BeExactly 'https://www.krausescafe.com/' + $eval.Latitude | Should -BeExactly '29.7015113830566' + $eval.Longitude | Should -BeExactly '-98.1247940063477' + $eval.entityType | Should -BeExactly 'Restaurant' + } #it + + } #context_Success + } #describe_Format-BingPlace +} #inModule diff --git a/src/Tests/Unit/Public/Find-BingPlace.Tests.ps1 b/src/Tests/Unit/Public/Find-BingPlace.Tests.ps1 new file mode 100644 index 0000000..3cb9163 --- /dev/null +++ b/src/Tests/Unit/Public/Find-BingPlace.Tests.ps1 @@ -0,0 +1,106 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +$PathToTestObjects = [System.IO.Path]::Combine('..', 'TestObjects.psm1') +Import-Module $PathToTestObjects -DisableNameChecking -Global -Force +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + Describe 'Find-BingPlace' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + } #beforeAll + BeforeEach { + Mock -CommandName Invoke-RestMethod -MockWith { + $findBingPlace + } #endMock + } + Context 'Error' { + + It 'should throw if an error is encountered with invoking the API' { + Mock -CommandName Invoke-RestMethod -MockWith { + throw 'Fake Error' + } #endMock + { Find-BingPlace -Query 'cafe' } | Should -Throw + } #it + + It 'should warn the user if the API does not return an OK status' { + Mock Write-Warning { } + Mock -CommandName Invoke-RestMethod -MockWith { + [PSCustomObject]@{ + results = '' + status = 'ZERO_RESULTS' + } + } #endMock + Find-BingPlace -Query 'cafe' + Assert-MockCalled -CommandName Write-Warning -Times 1 + Assert-VerifiableMock + } #it + + } #context_Error + Context 'Success' { + + It 'should warn the user if the API call was successful, but no results were found' { + Mock Write-Warning { } + Mock -CommandName Invoke-RestMethod -MockWith { + [PSCustomObject]@{ + resourceSets = [PSCustomObject]@{ + estimatedTotal = 0 + } + statusCode = '200' + statusDescription = 'OK' + } + } #endMock + Find-BingPlace -Query 'cafe' + Assert-MockCalled -CommandName Write-Warning -Times 1 + Assert-VerifiableMock + } #it + + It 'should return expected results if no issues are encountered' { + $eval = Find-BingPlace -Query 'cafe' -PointLatitude '29.7049806' -PointLongitude '-98.068343' + ($eval | Measure-Object).Count | Should -BeExactly 1 + $eval.Latitude | Should -BeExactly '29.7015113830566' + $eval.Longitude | Should -BeExactly '-98.1247940063477' + } #it + + # jake- put all the things here + It 'should call the API with the expected parameters when all options are provided' { + Mock -CommandName Invoke-RestMethod { + $Uri | Should -BeLike 'https://dev.virtualearth.net/REST/v1/LocalSearch?output=json*' + $Uri | Should -BeLike '*query=*' + $Uri | Should -BeLike '*userLocation=*' + $Uri | Should -BeLike '*culture=en*' + $Uri | Should -BeLike '*maxResults=*' + } -Verifiable + Find-BingPlace -Query 'cafe' -PointLatitude '29.7049806' -PointLongitude '-98.068343' -Language en -MaxResults 20 + Assert-VerifiableMock + } #it + + It 'should call the API with the expected parameters with circle' { + Mock -CommandName Invoke-RestMethod { + $Uri | Should -BeLike 'https://dev.virtualearth.net/REST/v1/LocalSearch?output=json*userCircularMapView=*' + } -Verifiable + Find-BingPlace -Query 'cafe' -CircleLatitude '29.7049806' -CircleLongitude '-98.068343' -CircleRadius '5000' + Assert-VerifiableMock + } #it + + It 'should call the API with the expected parameters with rectangle' { + Mock -CommandName Invoke-RestMethod { + $Uri | Should -BeLike 'https://dev.virtualearth.net/REST/v1/LocalSearch?output=json*userMapView=*' + } -Verifiable + Find-BingPlace -Query 'cafe' -SouthLatitude '39.8592387' -WestLongitude '-75.295486' -NorthLatitude '40.0381942' -EastLongitude '-75.0064087' -Region us + Assert-VerifiableMock + } #it + + } #context_Success + } #describe_Find-BingPlace +} #inModule diff --git a/src/Tests/Unit/Public/Invoke-BingGeoCode.Tests.ps1 b/src/Tests/Unit/Public/Invoke-BingGeoCode.Tests.ps1 index a553316..fbcc31d 100644 --- a/src/Tests/Unit/Public/Invoke-BingGeoCode.Tests.ps1 +++ b/src/Tests/Unit/Public/Invoke-BingGeoCode.Tests.ps1 @@ -49,6 +49,22 @@ InModuleScope 'pwshPlaces' { } #context_Error Context 'Success' { + It 'should warn the user if the API call was successful, but no results were found' { + Mock Write-Warning { } + Mock -CommandName Invoke-RestMethod -MockWith { + [PSCustomObject]@{ + resourceSets = [PSCustomObject]@{ + estimatedTotal = 0 + } + statusCode = '200' + statusDescription = 'OK' + } + } #endMock + Invoke-BingGeoCode -AddressLine '148 S Castell Ave' -City 'New Braunfels' -State TX -PostalCode 78130 -Country us + Assert-MockCalled -CommandName Write-Warning -Times 1 + Assert-VerifiableMock + } #it + It 'should return expected results if no issues are encountered' { $eval = Invoke-BingGeoCode -AddressLine '148 S Castell Ave' -City 'New Braunfels' -State TX -PostalCode 78130 -Country us $eval.Latitude | Should -BeExactly '29.701293' @@ -64,7 +80,7 @@ InModuleScope 'pwshPlaces' { $Uri | Should -BeLike '*postalCode=*' $Uri | Should -BeLike '*countryRegion=*' $Uri | Should -BeLike '*maxResults=*' - $Uri | Should -BeLike '*language=*' + $Uri | Should -BeLike '*culture=*' } -Verifiable Invoke-BingGeoCode -AddressLine '148 S Castell Ave' -City 'New Braunfels' -State TX -PostalCode 78130 -Country us -Language en -MaxResults 20 Assert-VerifiableMock diff --git a/src/Tests/Unit/TestObjects.psm1 b/src/Tests/Unit/TestObjects.psm1 index cf650a3..6830a37 100644 --- a/src/Tests/Unit/TestObjects.psm1 +++ b/src/Tests/Unit/TestObjects.psm1 @@ -1050,6 +1050,56 @@ $geoBingAddress = [PSCustomObject]@{ #endregion +$findBingPlace = [PSCustomObject]@{ + authenticationResultCode = 'ValidCredentials' + brandLogoUri = 'http://dev.virtualearth.net/Branding/logo_powered_by.png' + copyright = 'Copyright © 2021 Microsoft and its suppliers. All rights reserved. This API + cannot be accessed and the content and any results may not be used, reproduced + or transmitted in any manner without express written permission from Microsoft + Corporation.' + resourceSets = [PSCustomObject]@{ + estimatedTotal = 1 + resources = [PSCustomObject]@{ + '__type' = 'Location:http://schemas.microsoft.com/search/local/ws/rest/v1' + name = "Krause's Cafe" + point = [PSCustomObject]@{ + type = 'Point' + coordinates = @( + 29.7015113830566 + -98.1247940063477 + ) + } + address = [PSCustomObject]@{ + addressLine = '148 S Castell Ave' + adminDistrict = 'TX' + countryRegion = 'US' + formattedAddress = '148 S Castell Ave, New Braunfels, TX, 78130' + locality = 'New Braunfels' + postalCode = '78130' + } + PhoneNumber = '(830) 625-2807' + Website = 'https://www.krausescafe.com/' + entityType = 'Restaurant' + geocodePoints = @( + [PSCustomObject]@{ + type = 'Point' + coordinates = @( + 29.7013301849365 + -98.1249465942383 + ) + calculationMethod = 'Rooftop' + usageTypes = @( + 'Display' + ) + } + ) + } + } + statusCode = '200' + statusDescription = 'OK' + traceId = 'xxxxxxxxxxxxxxxxx|XXXXXXX|0.0.0.1|Ref A:XXXXXXXXXXXXX Ref B: XXXXXXXXX Ref C: 2021-10-06T03:08:54Z' +} + #endregion Export-ModuleMember -Variable '*' diff --git a/src/pwshPlaces/Imports.ps1 b/src/pwshPlaces/Imports.ps1 index 546d5bf..59d15bf 100644 --- a/src/pwshPlaces/Imports.ps1 +++ b/src/pwshPlaces/Imports.ps1 @@ -571,7 +571,103 @@ enum cultureCodes { #zh-Hans #Chinese (Simplified) #zh-Hant #Chinese (Traditional) zu #isiZulu -} +} #enum_cultureCodes + +enum typeIdentifier { + AmusementParks # Amusement parks. + AntiqueStores # For retail stores that sell antiques. + Attractions # Miscellaneous attractions that don't belong to another type. + BanksAndCreditUnions + Bars # For establishments that serve primarily alcoholic drinks such as beer, wine, liquor, and cocktails for consumption by the patrons on certain premises. + BarsGrillsAndPubs # A casual restaurant that serves substantial amount of food and alcoholic beverages on the menu. + BelgianRestaurants # Restaurants that primarily serve cuisine from Belgium. + Bookstores # For retail stores that primarily sell books, and may also include newspapers, magazines, maps. + BreweriesAndBrewPubs # For businesses or entities which brew and process beer on the premises, typically also serving their products in-house to the public. + BritishRestaurants # A restaurant that primarily serves cuisine from the British cultural traditions, including English, Welsh, Cornish and Scottish. + BuffetRestaurants # A restaurant where food is presented buffet-style and patrons can serve themselves. + CDAndRecordStores # Includes music stores that primarily sell music via CDs, Records, Albums, Cassette Tapes. May also sell music accessories for those devices. + CafeRestaurants # This casual eating and drinking place offers significant food options, prepared to order, and seating at the premise. + CaribbeanRestaurants # A restaurant that primarily serves cuisine from the Caribbean traditions. + Carnivals # Carnival attractions. + Casinos # Casinos and other gambling establishments. + ChildrensClothingStores # For retail stores that primarily sell clothing for children (including infants). + ChineseRestaurants # A restaurant that primarily serves cuisine from the Chinese cultural traditions. + CigarAndTobaccoShops # For retail stores that sell tobacco and tobacco accessories. + CocktailLounges # For bars whose focus is serving and selling alcoholic mixed drinks. + CoffeeAndTea # For establishments that primarily serve coffee and/or tea. + ComicBookStores # For retail stores that focus sales on comic books, comic magazines, and other comic accessories. + Delicatessens # In the United States, a delicatessen store, or deli, is a type of business that is both a grocery store and serves food. + DeliveryService # This type includes business which offer the option to deliver prepared dishes to different locations like home or work. + DepartmentStores # For retailers that primarily sell a wide range of consumer goods such as clothing, housewares, furniture and appliances, toys, cosmetics. + Diners # Diners are characterized by offering a wide range of foods, mostly American, a casual atmosphere, a counter, and late operating hours. + DiscountStores # For retail stores that primarily sell products at lower prices than standard retail stores. Discount stores may or may not have various departments offering a wide variety of goods. + Donuts # For places that primarily serve donuts. + FastFood # For businesses characterized by their quickness, cheap food, and minimal service. + FleaMarketsAndBazaars # Where individuals are able to rent a space to display and sell their goods that are usually used/old at a lower price. + FrenchRestaurants # A restaurant that primarily serves cuisine from the French cultural traditions. + FrozenYogurt # For entities that primarily serve frozen yogurt such as FroYo and Frogurt. + FurnitureStores # For retail stores that sell objects (whether new or used) intended to support various human activities such as sitting and sleeping. + GermanRestaurants # Restaurants that primarily serve cuisine from Germany. + GreekRestaurants # Restaurants that primarily serve cuisine from the Greek cultural traditions. + Grocers # Retail entities that provide food products to consumers, including corner stores. + Grocery # Retail entities that provide food products to consumers. + HawaiianRestaurants # A restaurant that primarily serves cuisine from Hawaiian traditions. + HomeImprovementStores # For retail stores that primarily sell hardware for home improvements such as power tools, electrical supplies and other related items. + Hospitals + HotelsAndMotels + HungarianRestaurants # Restaurants that primarily serve food from Hungarian cuisine. + IceCreamAndFrozenDesserts # For businesses that primarily serve ice cream and other frozen desserts, like cheese cake. + IndianRestaurants # Restaurants that primarily serve cuisine from Indian cultural traditions. + ItalianRestaurants # Restaurants that primarily serve cuisine from Italian cultural traditions. + JapaneseRestaurants # Restaurants that primarily serve cuisine from Japanese cultural traditions. + JewelryAndWatchesStores # For retail stores which sell jewelry and watches, as well as business that purchase gold and silver from the buyer ("cash for gold"). + Juices # For businesses offering juices and smoothies. + KitchenwareStores # For retail stores that primarily sell tableware, cookware and bakeware. + KoreanRestaurants # Restaurants that primarily serve cuisine from Korean cultural traditions. + LandmarksAndHistoricalSites # Man-made landmarks and historical sites. + LiquorStores # For retail stores that primarily sell liquor, wine, beer and spirits. + MallsAndShoppingCenters # For large complexes with various retail shops and interconnecting walkways allowing shoppers to have a complete shopping experience. + MensClothingStores # For retail stores that primarily sell clothing specifically designed for men to wear + MexicanRestaurants # Restaurants that primarily serve cuisine from Mexican cultural traditions. + MiddleEasternRestaurants # Restaurants that primarily serve cuisine from Middle Eastern cultural traditions. + MiniatureGolfCourses # Miniature golf courses. + MovieTheaters # Movie theaters and houses. + Museums # Museums and art galleries. + MusicStores # For retail shops which sell music related equipment or offer music related services. + OutletStores # For retail shops which sell music related equipment or offer music related services. + Parking + Parks # Natural parks and gardens. + PetShops # for retail stores that primarily sell pets. + PetSupplyStores # For retail stores that primarily sell pet supplies. + Pizza # Restaurants that primarily serve pizza, including pizza deliveries. + PolishRestaurants # Restaurants that primarily serve cuisine from Polish cultural traditions. + PortugueseRestaurants # Restaurants that primarily serve cuisine from Portuguese cultural traditions. + Pretzels # For businesses, places, kiosks, stands, or carts that primarily sell pretzels. + Restaurants # Business entities with the primary purpose of serving prepared-to-order food to the public. + RussianAndUkrainianRestaurants # Restaurants that primarily serve cuisine from Russian and/or Ukrainian cultural traditions. + Sandwiches # Restaurants that primarily serve sandwiches. + SchoolAndOfficeSupplyStores # Includes all office-related products. Pens, pencils, whiteboard markers, binders, mailing/shipping supplies, and basic office machines (fax, media projectors, etc.). Also includes retail-specific supplies, like shopping bags, signs, and cash handling products. All forms and types of calendars, breakroom and office cleaning supplies, and in-person meeting supplies. + SeafoodRestaurants # A restaurant that primarily serves seafood, including freshwater fish. + ShoeStores # For retail stores that primarily sell footwear. + SightseeingTours # Sight-seeing tours. + SpanishRestaurants # Restaurants that primarily serve cuisine from Spanish cultural traditions. + SportingGoodsStores # For retail stores that primarily sell sport and fitness equipment. + SportsBars # Bars with a primary focus on viewing live sporting and entertainment events. + SteakHouseRestaurants # Restaurants that primarily serve beef steaks. + Supermarkets # Large, warehouse-like retail entities that provide food products to consumers. + SushiRestaurants # Restaurants that primarily service sushi, including both cooked and raw seafood. + TakeAway # A food establishment that offers the option to purchase prepared dishes for the purpose of being eaten elsewhere. + Taverns # Similar to bars, but with additional seating; typically these are businesses which were once residences. + ThaiRestaurants # Restaurants that primarily serve cuisine from Thai cultural traditions. + TouristInformation # Tourist information booths and visitor centers. + ToyAndGameStores # For retail stores that primarily sell toys and games for all ages, including electronic toys, and educational game systems. + TurkishRestaurants # Restaurants that primarily serve cuisine from Turkish cultural traditions. + VegetarianAndVeganRestaurants # Restaurant that primarily serve vegetarian and/or vegan cuisine. + VietnameseRestaurants # Restaurants that primarily serve cuisine from Vietnamese cultural traditions. + VitaminAndSupplementStores # For retail stores that primarily sell vitamins and supplements. + WomensClothingStores # For retail stores that primarily sell women's clothing. + Zoos # Zoos and aquariums. +} #enum_typeIdentifier #endregion diff --git a/src/pwshPlaces/Private/Format-BingGeoCode.ps1 b/src/pwshPlaces/Private/Format-BingGeoCode.ps1 index b955a51..f8c08b5 100644 --- a/src/pwshPlaces/Private/Format-BingGeoCode.ps1 +++ b/src/pwshPlaces/Private/Format-BingGeoCode.ps1 @@ -39,7 +39,7 @@ function Format-BingGeoCode { $updateTypeDataSplat = @{ TypeName = 'Bing.GeoCode' MemberType = 'ScriptProperty' - MemberName = 'formatted_address' + MemberName = 'FormattedAddress' Value = { $this.address.formattedAddress } Force = $true } @@ -102,7 +102,7 @@ function Format-BingGeoCode { # set a default display of the above properties, all other properties are still there just not displayed $updateTypeDataSplat = @{ TypeName = 'Bing.GeoCode' - DefaultDisplayPropertySet = 'name', 'formatted_address', 'Street', 'City', 'Country', 'PostalCode', 'Latitude', 'Longitude', 'entityType' + DefaultDisplayPropertySet = 'name', 'FormattedAddress', 'Street', 'City', 'Country', 'PostalCode', 'Latitude', 'Longitude', 'entityType' DefaultKeyPropertySet = 'name' Force = $true } diff --git a/src/pwshPlaces/Private/Format-BingPlace.ps1 b/src/pwshPlaces/Private/Format-BingPlace.ps1 new file mode 100644 index 0000000..5830448 --- /dev/null +++ b/src/pwshPlaces/Private/Format-BingPlace.ps1 @@ -0,0 +1,80 @@ +<# +.SYNOPSIS + Formats Place object with easier to understand properties while leaving original properties intact +.DESCRIPTION + Changes Place object to custom PSType and creates additional properties that contains information most likely to be viewed. +.EXAMPLE + $results.resourceSets.resources | Format-BingPlace + + Formats GeoCode object results with a set of easier to understand properties +.PARAMETER Results + Place API results +.OUTPUTS + Bing.Place +.NOTES + Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + + Based on code from: https://github.com/Kreloc/PoshGMaps +.COMPONENT + pwshPlaces +#> +function Format-BingPlace { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, + HelpMessage = 'GeoCode API results', + ValueFromPipeline = $true)] + $Results + ) + begin { + Write-Verbose ('Starting {0}' -f $myinvocation.mycommand) + } #begin + process { + Write-Debug -Message ($Results | Out-String) + + $Results.PSTypeNames.Insert(0, 'Bing.Place') + + Write-Debug -Message ($Results.PSTypeNames | Out-String) + + $updateTypeDataSplat = @{ + TypeName = 'Bing.Place' + MemberType = 'ScriptProperty' + MemberName = 'FormattedAddress' + Value = { $this.address.formattedAddress } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'Bing.Place' + MemberType = 'ScriptProperty' + MemberName = 'Latitude' + Value = { $this.point.coordinates[0] } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'Bing.Place' + MemberType = 'ScriptProperty' + MemberName = 'Longitude' + Value = { $this.point.coordinates[1] } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + # set a default display of the above properties, all other properties are still there just not displayed + $updateTypeDataSplat = @{ + TypeName = 'Bing.Place' + DefaultDisplayPropertySet = 'name', 'FormattedAddress', 'PhoneNumber', 'Website', 'Latitude', 'Longitude', 'entityType' + DefaultKeyPropertySet = 'name' + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $Results + } #process + end { + Write-Verbose ('Ending {0}' -f $myinvocation.mycommand) + } #end +} #Format-BingPlace diff --git a/src/pwshPlaces/Public/Find-BingPlace.ps1 b/src/pwshPlaces/Public/Find-BingPlace.ps1 new file mode 100644 index 0000000..e7ad597 --- /dev/null +++ b/src/pwshPlaces/Public/Find-BingPlace.ps1 @@ -0,0 +1,254 @@ +<# +.SYNOPSIS + Returns a list of business entities centered around a location or a geographic region +.DESCRIPTION + Performs a find place request with provided parameters. + A text search is performed that returns a list of business entities. + By default the location bias is IP based. + Location bias and language can be controlled via parameters. +.EXAMPLE + Find-BingPlace -Query "Krause's cafe" + + Returns place information for the query location biased by IP. +.EXAMPLE + Find-BingPlace -Query "Krause's cafe" -Language es + + Returns place information for the query location biased by IP and returns a few portion of the results in Spanish. +.EXAMPLE + Find-BingPlace -Query 'cafe' -PointLatitude '29.7049806' -PointLongitude '-98.068343' + + Returns place information for the query location biased by provided lat/long point. +.EXAMPLE + Find-BingPlace -Query 'cafe' -CircleLatitude '29.7049806' -CircleLongitude '-98.068343' -CircleRadius '5000' + + Returns place information for the query location biased by circle lat/long/radius. +.EXAMPLE + Find-BingPlace -Query 'cafe' -SouthLatitude '39.8592387' -WestLongitude '-75.295486' -NorthLatitude '40.0381942' -EastLongitude '-75.0064087' + + Returns place information for the query location biased by rectangular two lat/lng pairs in decimal degrees, representing the south/west and north/east points of a rectangle. +.EXAMPLE + Find-BingPlace -Query 'cafe' -PointLatitude '29.7049806' -PointLongitude '-98.068343' -Language en -MaxResults 20 + + Returns place information for the query location biased by provided lat/long point with a maximum of 20 results in English. +.EXAMPLE + $findBingPlaceSplat = @{ + Query = 'cafe' + PointLatitude = '29.7049806' + PointLongitude = '-98.068343' + Language = 'en' + MaxResults = 20 + } + Find-BingPlace @findBingPlaceSplat + + Returns place information for the query location biased by provided lat/long point with a maximum of 20 results in English. +.PARAMETER Query + Text input that identifies the search target, such as a name, address, or phone number. Phone numbers must be in international format (prefixed by a plus sign ("+"), followed by the country code, then the phone number itself) +.PARAMETER PointLatitude + Prefer results in a specified area by specifying a single coordinate for the north–south position of a point on the Earth's surface. +.PARAMETER PointLongitude + Prefer results in a specified area by specifying a single coordinate for the east–west position of a point on the Earths surface. +.PARAMETER CircleLatitude + Prefer results in a specified area by specifying a radius plus lat/long - north–south position of a point on the Earth's surface. +.PARAMETER CircleLongitude + Prefer results in a specified area by specifying a radius plus lat/long - east–west position of a point on the Earths surface. +.PARAMETER CircleRadius + Prefer results in a specified area by specifying a radius plus lat/long - radius in meters +.PARAMETER SouthLatitude + Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - south latitude +.PARAMETER WestLongitude + Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - west longitude +.PARAMETER NorthLatitude + Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - north latitude +.PARAMETER EastLongitude + Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - east longitude +.PARAMETER RegionBias + The region code, specified as a ccTLD ("top-level domain") two-character value. +.PARAMETER Language + The language in which to return results. +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + + Example: + http://dev.virtualearth.net/REST/v1/Locations?countryRegion={countryRegion}&adminDistrict={adminDistrict}&locality={locality}&postalCode={postalCode}&addressLine={addressLine}&userLocation={userLocation}&userIp={userIp}&usermapView={usermapView}&includeNeighborhood={includeNeighborhood}&maxResults={maxResults}&key={BingMapsKey} +.COMPONENT + pwshPlaces +.LINK + https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Find-BingPlace.md +.LINK + https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-query +.LINK + https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/user-context-parameters +.LINK + https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes +.LINK + https://www.microsoft.com/maps/product/terms.html +.LINK + https://privacy.microsoft.com/en-us/privacystatement +#> +function Find-BingPlace { + [CmdletBinding( + PositionalBinding = $false, + DefaultParameterSetName = 'textquery')] + param ( + [Parameter(Mandatory = $true, + ParameterSetName = 'textquery', + HelpMessage = 'A string that contains information about a location, such as an address or landmark name')] + [Parameter(ParameterSetName = 'Point', Mandatory = $false)] + [Parameter(ParameterSetName = 'Circle', Mandatory = $false)] + [Parameter(ParameterSetName = 'Rectangle', Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [string]$Query, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Point', + HelpMessage = 'Location bias by point lat')] + [ValidateNotNullOrEmpty()] + [string]$PointLatitude, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Point', + HelpMessage = 'Location bias by point long')] + [ValidateNotNullOrEmpty()] + [string]$PointLongitude, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Circle', + HelpMessage = 'Location bias circular lat')] + [ValidateNotNullOrEmpty()] + [string]$CircleLatitude, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Circle', + HelpMessage = 'Location bias circular long')] + [ValidateNotNullOrEmpty()] + [string]$CircleLongitude, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Circle', + HelpMessage = 'Location bias circular radius')] + [ValidateRange(0, 5000)] + [string]$CircleRadius, + + # A string specifying two lat/lng pairs in decimal degrees, representing the south/west and north/east points of a rectangle. + [Parameter(Mandatory = $true, + ParameterSetName = 'Rectangle', + HelpMessage = 'Location bias rectangle south lat')] + [ValidateNotNullOrEmpty()] + [string]$SouthLatitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Rectangle', + HelpMessage = 'Location bias rectangle west long')] + [ValidateNotNullOrEmpty()] + [string]$WestLongitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Rectangle', + HelpMessage = 'Location bias rectangle north lat')] + [ValidateNotNullOrEmpty()] + [string]$NorthLatitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Rectangle', + HelpMessage = 'Location bias rectangle east long')] + [ValidateNotNullOrEmpty()] + [string]$EastLongitude, + + [Parameter(Mandatory = $false, + HelpMessage = 'The region code, specified as a ccTLD')] + [ccTLD]$RegionBias, + + [Parameter(Mandatory = $false, + HelpMessage = 'The language in which to return results')] + [languages]$Language, + + [Parameter(Mandatory = $false, + HelpMessage = 'Specifies the maximum number of locations to return in the response')] + [ValidateRange(1, 20)] + [int]$MaxResults + ) + + Write-Debug -Message ($PSCmdlet.ParameterSetName) + + # $uri = '{0}{1}' -f $bingMapsBaseURI, 'v1/Locations?output=json' + $uri = '{0}{1}' -f $bingMapsBaseURI, 'v1/LocalSearch?output=json' + Write-Debug -Message ('Base function URI: {0}' -f $uri) + + $fQuery = '&query={0}' -f [uri]::EscapeDataString($Query) + $uri += $fQuery + + switch ($PSCmdlet.ParameterSetName) { + 'Point' { + Write-Debug -Message 'Point specified' + $combinedPoint = '{0},{1}' -f $PointLatitude, $PointLongitude + # $fLocationBias = '&userLocation={0}' -f $combinedPoint + $fLocationBias = '&userLocation={0}' -f [uri]::EscapeDataString($combinedPoint) + $uri += $fLocationBias + } #point + 'Circle' { + Write-Debug -Message 'Circle specified' + $combinedCircle = '{0},{1},{2}' -f $CircleLatitude, $CircleLongitude, $CircleRadius + $fLocationBias = '&userCircularMapView={0}' -f [uri]::EscapeDataString($combinedCircle) + $uri += $fLocationBias + } #circle + 'Rectangle' { + Write-Debug -Message 'Rectangle specified' + $combinedRectangle = '{0},{1},{2},{3}' -f $SouthLatitude, $WestLongitude, $NorthLatitude, $EastLongitude + # $fLocationBias = '&userMapView={0}' -f $combinedRectangle + $fLocationBias = '&userMapView={0}' -f [uri]::EscapeDataString($combinedRectangle) + $uri += $fLocationBias + } #rectangle + } #switch_parametersetname + + if ($RegionBias) { + Write-Debug -Message ('RegionBias: {0}' -f $RegionBias) + $fRegion = '&userRegion={0}' -f $RegionBias + $uri += $fRegion + } + if ($MaxResults) { + Write-Debug -Message ('MaxResults: {0}' -f $MaxResults) + $fMaxResults = '&maxResults={0}' -f $MaxResults + $uri += $fMaxResults + } + if ($Language) { + Write-Debug -Message ('Language: {0}' -f $Language) + $fLanguage = '&culture={0}' -f $Language + $uri += $fLanguage + } + + Write-Verbose -Message ('Querying Bing API: {0}' -f $uri) + + Write-Debug -Message 'Adding API key' + $fAPIKey = '&key={0}' -f $env:BingAPIKey + $uri += $fAPIKey + + $invokeRestMethodSplat = @{ + Uri = $uri + ErrorAction = 'Stop' + } + try { + $results = Invoke-RestMethod @invokeRestMethodSplat + } + catch { + throw $_ + } + + if ($results.statusDescription -ne 'OK') { + Write-Warning -Message 'Did not get a succcessful return from Bing Location API endpoint' + $finalResults = $results + } + elseif (-not ($results.resourceSets.estimatedTotal -ge 1)) { + Write-Warning -Message 'No results returned from query' + $finalResults = $results + } + else { + $finalResults = ($results.resourceSets.resources | Format-BingPlace) + # $finalResults = $results + } + + return $finalResults + +} #Find-BingPlace + diff --git a/src/pwshPlaces/Public/Find-GMapPlace.ps1 b/src/pwshPlaces/Public/Find-GMapPlace.ps1 index feda7d2..f293acb 100644 --- a/src/pwshPlaces/Public/Find-GMapPlace.ps1 +++ b/src/pwshPlaces/Public/Find-GMapPlace.ps1 @@ -40,7 +40,7 @@ .EXAMPLE Find-GMapPlace -Query '+18306252807' -PointLatitude '29.7049806' -PointLongitude '-98.068343' -Contact -Atmosphere -Language en - Returns place information for the query location biased by provided lat/long point with additional Contact and Atmosphere fields with results in Enlgish. + Returns place information for the query location biased by provided lat/long point with additional Contact and Atmosphere fields with results in English. .EXAMPLE $findGMapPlaceSplat = @{ Query = '+18306252807' @@ -52,7 +52,7 @@ } Find-GMapPlace @findGMapPlaceSplat - Returns place information for the query location biased by provided lat/long point with additional Contact and Atmosphere fields with results in Enlgish. + Returns place information for the query location biased by provided lat/long point with additional Contact and Atmosphere fields with results in English. .PARAMETER Query Text input that identifies the search target, such as a name, address, or phone number. Phone numbers must be in international format (prefixed by a plus sign ("+"), followed by the country code, then the phone number itself) .PARAMETER PointLatitude diff --git a/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 b/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 index f10a6d7..681532c 100644 --- a/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 +++ b/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 @@ -157,7 +157,7 @@ function Invoke-BingGeoCode { } if ($Language) { Write-Debug -Message ('Language: {0}' -f $Language) - $fLanguage = '&language={0}' -f $Language + $fLanguage = '&culture={0}' -f $Language $uri += $fLanguage } @@ -180,7 +180,11 @@ function Invoke-BingGeoCode { } if ($results.statusDescription -ne 'OK') { - Write-Warning -Message 'Did not get a succcessful return from Bing Geocode API endpoint' + Write-Warning -Message 'Did not get a succcessful return from Bing Location API endpoint' + $finalResults = $results + } + elseif (-not ($results.resourceSets.estimatedTotal -ge 1)) { + Write-Warning -Message 'No results returned from query' $finalResults = $results } else { diff --git a/src/pwshPlaces/pwshPlaces.psd1 b/src/pwshPlaces/pwshPlaces.psd1 index 3eb3d13..e2c26c0 100644 --- a/src/pwshPlaces/pwshPlaces.psd1 +++ b/src/pwshPlaces/pwshPlaces.psd1 @@ -12,7 +12,7 @@ RootModule = 'pwshPlaces.psm1' # Version number of this module. - ModuleVersion = '0.5.1' + ModuleVersion = '0.5.2' # Supported PSEditions # CompatiblePSEditions = @() @@ -70,6 +70,7 @@ # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. FunctionsToExport = @( + 'Find-BingPlace' 'Find-GMapPlace' 'Get-GMapPlaceDetail' 'Invoke-BingGeoCode' @@ -106,12 +107,19 @@ 'API', 'Area', 'Atmosphere', + 'Bing', + 'BingMap' + 'BingMaps', 'Contact', 'Find', + 'FindLocation', 'FindPlace', 'Geo', + 'Geoencode', + 'Geoencoding', 'Geolocation', 'Google', + 'GoogleMap', 'GoogleMaps', 'GMap', 'GMaps', @@ -121,7 +129,9 @@ 'Place', 'Places', 'Map', + 'MapAPI', 'Maps', + 'MapsAPI', 'Rating', 'Ratings', 'Search', From a43b85f1c542e5b2d5e018bbaa131c8425b06863 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sun, 10 Oct 2021 09:12:05 -0500 Subject: [PATCH 14/22] added query to bing geocode --- docs/Find-BingPlace.md | 3 +- docs/Invoke-BingGeoCode.md | 33 ++++++++++++++++++- docs/pwshPlaces.md | 2 +- .../Unit/Public/Invoke-BingGeoCode.Tests.ps1 | 2 +- src/pwshPlaces/Public/Find-BingPlace.ps1 | 2 +- src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 | 23 +++++++++++++ src/pwshPlaces/pwshPlaces.psd1 | 2 +- 7 files changed, 60 insertions(+), 7 deletions(-) diff --git a/docs/Find-BingPlace.md b/docs/Find-BingPlace.md index db331e2..2b5ab57 100644 --- a/docs/Find-BingPlace.md +++ b/docs/Find-BingPlace.md @@ -105,8 +105,7 @@ Returns place information for the query location biased by provided lat/long poi ## PARAMETERS ### -Query -Text input that identifies the search target, such as a name, address, or phone number. -Phone numbers must be in international format (prefixed by a plus sign ("+"), followed by the country code, then the phone number itself) +A string that contains information about a location, such as an address or landmark name. ```yaml Type: String diff --git a/docs/Invoke-BingGeoCode.md b/docs/Invoke-BingGeoCode.md index 5875478..feaf070 100644 --- a/docs/Invoke-BingGeoCode.md +++ b/docs/Invoke-BingGeoCode.md @@ -24,6 +24,11 @@ Invoke-BingGeoCode -Latitude -Longitude [-Language [] ``` +### textquery +``` +Invoke-BingGeoCode -Query [-Language ] [-MaxResults ] [] +``` + ## DESCRIPTION Geocoding is the process of converting addresses addresses (like "1600 Amphitheatre Parkway, Mountain View, CA") into geographic coordinates. This function can take in an address and return coordinate information. @@ -47,6 +52,13 @@ Performs Reverse geocoding (address lookup) on provided coordinates and can retu ### EXAMPLE 3 ``` +Invoke-BingGeoCode -Query 'The Alamo' +``` + +Searches for provided query and if a match is found will return Geocoding (latitude/longitude lookup) of the results. + +### EXAMPLE 4 +``` Invoke-BingGeoCode -AddressLine '148 S Castell Ave' -City 'New Braunfels' -State TX -PostalCode 78130 -Country us -Language en -MaxResults 20 ``` @@ -55,7 +67,7 @@ Results are biased to the United States country. Results are returned in English. Up to 20 results are returned. -### EXAMPLE 4 +### EXAMPLE 5 ``` $invokeBingGeoCodeSplat = @{ AddressLine = '148 S Castell Ave' @@ -184,6 +196,21 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -Query +A string that contains information about a location, such as an address or landmark name. + +```yaml +Type: String +Parameter Sets: textquery +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -Language The language in which to return results. @@ -231,6 +258,10 @@ Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ Example: http://dev.virtualearth.net/REST/v1/Locations?countryRegion={countryRegion}&adminDistrict={adminDistrict}&locality={locality}&postalCode={postalCode}&addressLine={addressLine}&userLocation={userLocation}&userIp={userIp}&usermapView={usermapView}&includeNeighborhood={includeNeighborhood}&maxResults={maxResults}&key={BingMapsKey} +While the Bing Location API does support a text query option, I have found it to be fairly unreliable. +For GeoCode info stick to Addresses and Lat/Long for reverse Geocoding. +For Text Queries use other Bing Maps functions. + ## RELATED LINKS [https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Invoke-BingGeoCode.md](https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Invoke-BingGeoCode.md) diff --git a/docs/pwshPlaces.md b/docs/pwshPlaces.md index d72961c..259b93c 100644 --- a/docs/pwshPlaces.md +++ b/docs/pwshPlaces.md @@ -2,7 +2,7 @@ Module Name: pwshPlaces Module Guid: 9a9914bd-d115-4f42-bb5d-19c5e5561a3f Download Help Link: NA -Help Version: 0.5.2 +Help Version: 0.5.3 Locale: en-US --- diff --git a/src/Tests/Unit/Public/Invoke-BingGeoCode.Tests.ps1 b/src/Tests/Unit/Public/Invoke-BingGeoCode.Tests.ps1 index fbcc31d..fc843f9 100644 --- a/src/Tests/Unit/Public/Invoke-BingGeoCode.Tests.ps1 +++ b/src/Tests/Unit/Public/Invoke-BingGeoCode.Tests.ps1 @@ -41,7 +41,7 @@ InModuleScope 'pwshPlaces' { status = 'ZERO_RESULTS' } } #endMock - Invoke-BingGeoCode -AddressLine '148 S Castell Ave' -City 'New Braunfels' -State TX -PostalCode 78130 -Country us + Invoke-BingGeoCode -Query 'The Alamo' Assert-MockCalled -CommandName Write-Warning -Times 1 Assert-VerifiableMock } #it diff --git a/src/pwshPlaces/Public/Find-BingPlace.ps1 b/src/pwshPlaces/Public/Find-BingPlace.ps1 index e7ad597..78ceeb9 100644 --- a/src/pwshPlaces/Public/Find-BingPlace.ps1 +++ b/src/pwshPlaces/Public/Find-BingPlace.ps1 @@ -42,7 +42,7 @@ Returns place information for the query location biased by provided lat/long point with a maximum of 20 results in English. .PARAMETER Query - Text input that identifies the search target, such as a name, address, or phone number. Phone numbers must be in international format (prefixed by a plus sign ("+"), followed by the country code, then the phone number itself) + A string that contains information about a location, such as an address or landmark name. .PARAMETER PointLatitude Prefer results in a specified area by specifying a single coordinate for the north–south position of a point on the Earth's surface. .PARAMETER PointLongitude diff --git a/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 b/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 index 681532c..a25de86 100644 --- a/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 +++ b/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 @@ -13,6 +13,10 @@ Invoke-BingGeoCode -Latitude '29.7030' -Longitude '-98.1245' Performs Reverse geocoding (address lookup) on provided coordinates and can return multiple address results. +.EXAMPLE + Invoke-BingGeoCode -Query 'The Alamo' + + Searches for provided query and if a match is found will return Geocoding (latitude/longitude lookup) of the results. .EXAMPLE Invoke-BingGeoCode -AddressLine '148 S Castell Ave' -City 'New Braunfels' -State TX -PostalCode 78130 -Country us -Language en -MaxResults 20 @@ -44,6 +48,8 @@ Geographic coordinate that specifies the north–south position of a point on the Earth's surface. .PARAMETER Longitude Geographic coordinate that specifies the east–west position of a point on the Earths surface. +.PARAMETER Query + A string that contains information about a location, such as an address or landmark name. .PARAMETER Language The language in which to return results. .PARAMETER MaxResults @@ -55,6 +61,10 @@ Example: http://dev.virtualearth.net/REST/v1/Locations?countryRegion={countryRegion}&adminDistrict={adminDistrict}&locality={locality}&postalCode={postalCode}&addressLine={addressLine}&userLocation={userLocation}&userIp={userIp}&usermapView={usermapView}&includeNeighborhood={includeNeighborhood}&maxResults={maxResults}&key={BingMapsKey} + + While the Bing Location API does support a text query option, I have found it to be fairly unreliable. + For GeoCode info stick to Addresses and Lat/Long for reverse Geocoding. + For Text Queries use other Bing Maps functions. .COMPONENT pwshPlaces .LINK @@ -114,6 +124,12 @@ function Invoke-BingGeoCode { [ValidateNotNullOrEmpty()] [string]$Longitude, + [Parameter(Mandatory = $true, + ParameterSetName = 'textquery', + HelpMessage = 'A string that contains information about a location, such as an address or landmark name')] + [ValidateNotNullOrEmpty()] + [string]$Query, + [Parameter(Mandatory = $false, HelpMessage = 'The language in which to return results')] [languages]$Language, @@ -148,6 +164,13 @@ function Invoke-BingGeoCode { $uri = '{0}{1}' -f $bingMapsBaseURI, $latLong Write-Debug -Message ('Base function URI: {0}' -f $uri) } #location + 'textquery' { + Write-Debug -Message 'Query specified' + $uri = '{0}{1}' -f $bingMapsBaseURI, 'v1/Locations?output=json' + Write-Debug -Message ('Base function URI: {0}' -f $uri) + $fQuery = '&query={0}' -f [uri]::EscapeDataString($Query) + $uri += $fQuery + } #textquery } #switch_parametersetname if ($MaxResults) { diff --git a/src/pwshPlaces/pwshPlaces.psd1 b/src/pwshPlaces/pwshPlaces.psd1 index e2c26c0..a02316d 100644 --- a/src/pwshPlaces/pwshPlaces.psd1 +++ b/src/pwshPlaces/pwshPlaces.psd1 @@ -12,7 +12,7 @@ RootModule = 'pwshPlaces.psm1' # Version number of this module. - ModuleVersion = '0.5.2' + ModuleVersion = '0.5.3' # Supported PSEditions # CompatiblePSEditions = @() From 679221ef6d71dc9d0093d7da46323f7d99da1c53 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sun, 10 Oct 2021 10:08:53 -0500 Subject: [PATCH 15/22] added Search-BingNearbyPlace --- docs/Find-BingPlace.md | 2 +- docs/Invoke-BingGeoCode.md | 2 + docs/Search-BingNearbyPlace.md | 349 ++++++++++++++++++ docs/pwshPlaces.md | 5 +- .../Infrastructure/pwshPlaces-Infra.Tests.ps1 | 14 + .../Public/Search-BingNearbyPlace.Tests.ps1 | 106 ++++++ src/pwshPlaces/Public/Find-BingPlace.ps1 | 6 +- src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 | 2 + .../Public/Search-BingNearbyPlace.ps1 | 249 +++++++++++++ src/pwshPlaces/pwshPlaces.psd1 | 3 +- 10 files changed, 730 insertions(+), 8 deletions(-) create mode 100644 docs/Search-BingNearbyPlace.md create mode 100644 src/Tests/Unit/Public/Search-BingNearbyPlace.Tests.ps1 create mode 100644 src/pwshPlaces/Public/Search-BingNearbyPlace.ps1 diff --git a/docs/Find-BingPlace.md b/docs/Find-BingPlace.md index 2b5ab57..1e4fd99 100644 --- a/docs/Find-BingPlace.md +++ b/docs/Find-BingPlace.md @@ -332,7 +332,7 @@ Example: [https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Find-BingPlace.md](https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Find-BingPlace.md) -[https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-query](https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-query) +[https://docs.microsoft.com/bingmaps/rest-services/locations/local-search](https://docs.microsoft.com/bingmaps/rest-services/locations/local-search) [https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/user-context-parameters](https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/user-context-parameters) diff --git a/docs/Invoke-BingGeoCode.md b/docs/Invoke-BingGeoCode.md index feaf070..8223df1 100644 --- a/docs/Invoke-BingGeoCode.md +++ b/docs/Invoke-BingGeoCode.md @@ -270,6 +270,8 @@ For Text Queries use other Bing Maps functions. [https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-point](https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-point) +[https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-query](https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-query) + [https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes](https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes) [https://www.microsoft.com/maps/product/terms.html](https://www.microsoft.com/maps/product/terms.html) diff --git a/docs/Search-BingNearbyPlace.md b/docs/Search-BingNearbyPlace.md new file mode 100644 index 0000000..c065f20 --- /dev/null +++ b/docs/Search-BingNearbyPlace.md @@ -0,0 +1,349 @@ +--- +external help file: pwshPlaces-help.xml +Module Name: pwshPlaces +online version: https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Search-BingNearbyPlace.md +schema: 2.0.0 +--- + +# Search-BingNearbyPlace + +## SYNOPSIS +Nearby Search lets you search for different place types within a specified area. + +## SYNTAX + +### PlaceType (Default) +``` +Search-BingNearbyPlace -Type [-RegionBias ] [-Language ] + [-MaxResults ] [] +``` + +### Rectangle +``` +Search-BingNearbyPlace [-Type ] -SouthLatitude -WestLongitude + -NorthLatitude -EastLongitude [-RegionBias ] [-Language ] + [-MaxResults ] [] +``` + +### Circle +``` +Search-BingNearbyPlace [-Type ] [-CircleLatitude ] [-CircleLongitude ] + [-CircleRadius ] [-RegionBias ] [-Language ] [-MaxResults ] + [] +``` + +### Point +``` +Search-BingNearbyPlace [-Type ] [-PointLatitude ] [-PointLongitude ] + [-RegionBias ] [-Language ] [-MaxResults ] [] +``` + +## DESCRIPTION +Performs a nearby search request with provided parameters. +Nearby search is useful for finding place types near a specific geographic location. +By default the location bias is IP based. +Location bias can be controlled via parameters. + +## EXAMPLES + +### EXAMPLE 1 +``` +Search-BingNearbyPlace -Type Attractions +``` + +Performs a nearby search biased by IP and returns Attraction places types. + +### EXAMPLE 2 +``` +Search-BingNearbyPlace -Type Restaurants -MaxResults 20 +``` + +Performs a nearby search biased by IP and returns Restaurant places types with a maximum of 20 results returned. + +### EXAMPLE 3 +``` +Search-BingNearbyPlace -Type CafeRestaurants -PointLatitude '29.7049806' -PointLongitude '-98.068343' +``` + +Performs a nearby search near the provided Lat/Long and returns CafeRestaurant places types. + +### EXAMPLE 4 +``` +Search-BingNearbyPlace -Type BreweriesAndBrewPubs -CircleLatitude '29.7049806' -CircleLongitude '-98.068343' -CircleRadius '5000' +``` + +Performs a nearby search biased by circle lat/long/radius and returns Bars and Pubs places types. + +### EXAMPLE 5 +``` +Search-BingNearbyPlace -Type Parks -SouthLatitude '39.8592387' -WestLongitude '-75.295486' -NorthLatitude '40.0381942' -EastLongitude '-75.0064087' +``` + +Performs a nearby search biased by rectangular two lat/lng pairs in decimal degrees, representing the south/west and north/east points of a rectangle. +Park places types are returned. + +### EXAMPLE 6 +``` +Search-BingNearbyPlace -Type Museums -PointLatitude '29.7049806' -PointLongitude '-98.068343' -Language en -MaxResults 20 +``` + +Performs a nearby search near the provided Lat/Long and returns Museum places types. +Results are returned in english with a maximum of 20 results returned. + +### EXAMPLE 7 +``` +$searchBingNearbyPlaceSplat = @{ + Type = 'Museums' + PointLatitude = '29.7049806' + PointLongitude = '-98.068343' + Language = 'en' + MaxResults = 20 +} +Search-BingNearbyPlace @searchBingNearbyPlaceSplat +``` + +Performs a nearby search near the provided Lat/Long and returns Museum places types. +Results are returned in english with a maximum of 20 results returned. + +## PARAMETERS + +### -Type +Restricts the results to places matching the specified type + +```yaml +Type: typeIdentifier +Parameter Sets: PlaceType +Aliases: +Accepted values: AmusementParks, AntiqueStores, Attractions, BanksAndCreditUnions, Bars, BarsGrillsAndPubs, BelgianRestaurants, Bookstores, BreweriesAndBrewPubs, BritishRestaurants, BuffetRestaurants, CDAndRecordStores, CafeRestaurants, CaribbeanRestaurants, Carnivals, Casinos, ChildrensClothingStores, ChineseRestaurants, CigarAndTobaccoShops, CocktailLounges, CoffeeAndTea, ComicBookStores, Delicatessens, DeliveryService, DepartmentStores, Diners, DiscountStores, Donuts, FastFood, FleaMarketsAndBazaars, FrenchRestaurants, FrozenYogurt, FurnitureStores, GermanRestaurants, GreekRestaurants, Grocers, Grocery, HawaiianRestaurants, HomeImprovementStores, Hospitals, HotelsAndMotels, HungarianRestaurants, IceCreamAndFrozenDesserts, IndianRestaurants, ItalianRestaurants, JapaneseRestaurants, JewelryAndWatchesStores, Juices, KitchenwareStores, KoreanRestaurants, LandmarksAndHistoricalSites, LiquorStores, MallsAndShoppingCenters, MensClothingStores, MexicanRestaurants, MiddleEasternRestaurants, MiniatureGolfCourses, MovieTheaters, Museums, MusicStores, OutletStores, Parking, Parks, PetShops, PetSupplyStores, Pizza, PolishRestaurants, PortugueseRestaurants, Pretzels, Restaurants, RussianAndUkrainianRestaurants, Sandwiches, SchoolAndOfficeSupplyStores, SeafoodRestaurants, ShoeStores, SightseeingTours, SpanishRestaurants, SportingGoodsStores, SportsBars, SteakHouseRestaurants, Supermarkets, SushiRestaurants, TakeAway, Taverns, ThaiRestaurants, TouristInformation, ToyAndGameStores, TurkishRestaurants, VegetarianAndVeganRestaurants, VietnameseRestaurants, VitaminAndSupplementStores, WomensClothingStores, Zoos + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +```yaml +Type: typeIdentifier +Parameter Sets: Rectangle, Circle, Point +Aliases: +Accepted values: AmusementParks, AntiqueStores, Attractions, BanksAndCreditUnions, Bars, BarsGrillsAndPubs, BelgianRestaurants, Bookstores, BreweriesAndBrewPubs, BritishRestaurants, BuffetRestaurants, CDAndRecordStores, CafeRestaurants, CaribbeanRestaurants, Carnivals, Casinos, ChildrensClothingStores, ChineseRestaurants, CigarAndTobaccoShops, CocktailLounges, CoffeeAndTea, ComicBookStores, Delicatessens, DeliveryService, DepartmentStores, Diners, DiscountStores, Donuts, FastFood, FleaMarketsAndBazaars, FrenchRestaurants, FrozenYogurt, FurnitureStores, GermanRestaurants, GreekRestaurants, Grocers, Grocery, HawaiianRestaurants, HomeImprovementStores, Hospitals, HotelsAndMotels, HungarianRestaurants, IceCreamAndFrozenDesserts, IndianRestaurants, ItalianRestaurants, JapaneseRestaurants, JewelryAndWatchesStores, Juices, KitchenwareStores, KoreanRestaurants, LandmarksAndHistoricalSites, LiquorStores, MallsAndShoppingCenters, MensClothingStores, MexicanRestaurants, MiddleEasternRestaurants, MiniatureGolfCourses, MovieTheaters, Museums, MusicStores, OutletStores, Parking, Parks, PetShops, PetSupplyStores, Pizza, PolishRestaurants, PortugueseRestaurants, Pretzels, Restaurants, RussianAndUkrainianRestaurants, Sandwiches, SchoolAndOfficeSupplyStores, SeafoodRestaurants, ShoeStores, SightseeingTours, SpanishRestaurants, SportingGoodsStores, SportsBars, SteakHouseRestaurants, Supermarkets, SushiRestaurants, TakeAway, Taverns, ThaiRestaurants, TouristInformation, ToyAndGameStores, TurkishRestaurants, VegetarianAndVeganRestaurants, VietnameseRestaurants, VitaminAndSupplementStores, WomensClothingStores, Zoos + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PointLatitude +Prefer results in a specified area by specifying a single coordinate for the north-south position of a point on the Earth's surface. + +```yaml +Type: String +Parameter Sets: Point +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PointLongitude +Prefer results in a specified area by specifying a single coordinate for the east-west position of a point on the Earths surface. + +```yaml +Type: String +Parameter Sets: Point +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -CircleLatitude +Prefer results in a specified area by specifying a radius plus lat/long - north-south position of a point on the Earth's surface. + +```yaml +Type: String +Parameter Sets: Circle +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -CircleLongitude +Prefer results in a specified area by specifying a radius plus lat/long - east-west position of a point on the Earths surface. + +```yaml +Type: String +Parameter Sets: Circle +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -CircleRadius +Prefer results in a specified area by specifying a radius plus lat/long - radius in meters + +```yaml +Type: String +Parameter Sets: Circle +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SouthLatitude +Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - south latitude + +```yaml +Type: String +Parameter Sets: Rectangle +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WestLongitude +Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - west longitude + +```yaml +Type: String +Parameter Sets: Rectangle +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -NorthLatitude +Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - north latitude + +```yaml +Type: String +Parameter Sets: Rectangle +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -EastLongitude +Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - east longitude + +```yaml +Type: String +Parameter Sets: Rectangle +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RegionBias +The region code, specified as a ccTLD ("top-level domain") two-character value. + +```yaml +Type: ccTLD +Parameter Sets: (All) +Aliases: +Accepted values: ac, ad, ae, af, ag, ai, al, am, ao, aq, ar, as, at, au, aw, ax, az, ba, bb, bd, be, bf, bg, bh, bi, bj, bm, bn, bo, br, bs, bt, bv, bw, by, bz, ca, cc, cd, cf, cg, ch, ci, ck, cl, cm, cn, co, cr, cu, cv, cw, cx, cy, cz, de, dj, dk, dm, do, dz, ec, ee, eg, er, es, et, eu, fi, fj, fk, fm, fo, fr, ga, gb, gd, ge, gf, gg, gh, gi, gl, gm, gn, gp, gq, gr, gs, gt, gu, gw, gy, hk, hm, hn, hr, ht, hu, id, ie, il, im, in, io, iq, ir, is, it, je, jm, jo, jp, ke, kg, kh, ki, km, kn, kp, kr, kw, ky, kz, la, lb, lc, li, lk, lr, ls, lt, lu, lv, ly, ma, mc, md, me, mg, mh, mk, ml, mm, mn, mo, mp, mq, mr, ms, mt, mu, mv, mw, mx, my, mz, na, nc, ne, nf, ng, ni, nl, no, np, nr, nu, nz, om, pa, pe, pf, pg, ph, pk, pl, pm, pn, pr, ps, pt, pw, py, qa, re, ro, rs, ru, rw, sa, sb, sc, sd, se, sg, sh, si, sj, sk, sl, sm, sn, so, sr, ss, st, su, sv, sx, sy, sz, tc, td, tf, tg, th, tj, tk, tl, tm, tn, to, tr, tt, tv, tw, tz, ua, ug, uk, us, uy, uz, va, vc, ve, vg, vi, vn, vu, wf, ws, ye, yt, za, zm, zw + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Language +The language in which to return results. + +```yaml +Type: languages +Parameter Sets: (All) +Aliases: +Accepted values: af, sq, am, ar, hy, az, eu, be, bn, bs, bg, my, ca, zh, hr, cs, da, nl, en, et, fa, fi, fil, fr, ka, de, el, iw, hi, hu, is, id, it, ja, kn, kk, km, ko, ky, lo, lv, lt, mk, ms, ml, mr, mn, ne, no, pl, pt, pa, ro, ru, sr, sk, es, sw, ta, te, th, uk, ur, uz, vi, zu + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -MaxResults +Specifies the maximum number of locations to return in the response + +```yaml +Type: Int32 +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: 0 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### Output from this cmdlet (if any) +## NOTES +Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + +Example: + http://dev.virtualearth.net/REST/v1/Locations?countryRegion={countryRegion}&adminDistrict={adminDistrict}&locality={locality}&postalCode={postalCode}&addressLine={addressLine}&userLocation={userLocation}&userIp={userIp}&usermapView={usermapView}&includeNeighborhood={includeNeighborhood}&maxResults={maxResults}&key={BingMapsKey} + +## RELATED LINKS + +[https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Search-BingNearbyPlace.md](https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Search-BingNearbyPlace.md) + +[https://docs.microsoft.com/bingmaps/rest-services/locations/local-search](https://docs.microsoft.com/bingmaps/rest-services/locations/local-search) + +[https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/user-context-parameters](https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/user-context-parameters) + +[https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes](https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes) + +[https://www.microsoft.com/maps/product/terms.html](https://www.microsoft.com/maps/product/terms.html) + +[https://privacy.microsoft.com/en-us/privacystatement](https://privacy.microsoft.com/en-us/privacystatement) + diff --git a/docs/pwshPlaces.md b/docs/pwshPlaces.md index 259b93c..6fd0f5a 100644 --- a/docs/pwshPlaces.md +++ b/docs/pwshPlaces.md @@ -2,7 +2,7 @@ Module Name: pwshPlaces Module Guid: 9a9914bd-d115-4f42-bb5d-19c5e5561a3f Download Help Link: NA -Help Version: 0.5.3 +Help Version: 0.5.4 Locale: en-US --- @@ -26,6 +26,9 @@ Engages Bing Maps API to return address and geographic coordinates based on prov ### [Invoke-GMapGeoCode](Invoke-GMapGeoCode.md) Engages Geocoding API to return address and geographic coordinates based on provided query parameters. +### [Search-BingNearbyPlace](Search-BingNearbyPlace.md) +Nearby Search lets you search for different place types within a specified area. + ### [Search-GMapNearbyPlace](Search-GMapNearbyPlace.md) Nearby Search lets you search for places within a specified area. You can refine your search request by supplying keywords, type of place you are searching for and other parameters. diff --git a/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 b/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 index 6bf4dac..62522c0 100644 --- a/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 +++ b/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 @@ -142,5 +142,19 @@ Describe 'Infrastructure Tests' -Tag Infrastructure { Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) } #it } #context_Find-BingPlace + Context 'Search-BingNearbyPlace' { + It 'should return the expected results' { + $searchBingNearbyPlaceSplat = @{ + Type = 'Museums' + PointLatitude = '29.7049806' + PointLongitude = '-98.068343' + Language = 'en' + MaxResults = 20 + } + $eval = Search-BingNearbyPlace @searchBingNearbyPlaceSplat + ($eval.name | Measure-Object).Count | Should -BeGreaterOrEqual 1 + Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) + } #it + } #context_Find-BingPlace } #context_BingMaps } #describe_infra_tests diff --git a/src/Tests/Unit/Public/Search-BingNearbyPlace.Tests.ps1 b/src/Tests/Unit/Public/Search-BingNearbyPlace.Tests.ps1 new file mode 100644 index 0000000..e43ef3c --- /dev/null +++ b/src/Tests/Unit/Public/Search-BingNearbyPlace.Tests.ps1 @@ -0,0 +1,106 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +$PathToTestObjects = [System.IO.Path]::Combine('..', 'TestObjects.psm1') +Import-Module $PathToTestObjects -DisableNameChecking -Global -Force +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + Describe 'Search-BingNearbyPlace' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + } #beforeAll + BeforeEach { + Mock -CommandName Invoke-RestMethod -MockWith { + $findBingPlace + } #endMock + } + Context 'Error' { + + It 'should throw if an error is encountered with invoking the API' { + Mock -CommandName Invoke-RestMethod -MockWith { + throw 'Fake Error' + } #endMock + { Search-BingNearbyPlace -Type Attractions } | Should -Throw + } #it + + It 'should warn the user if the API does not return an OK status' { + Mock Write-Warning { } + Mock -CommandName Invoke-RestMethod -MockWith { + [PSCustomObject]@{ + results = '' + status = 'ZERO_RESULTS' + } + } #endMock + Search-BingNearbyPlace -Type Restaurants -MaxResults 20 + Assert-MockCalled -CommandName Write-Warning -Times 1 + Assert-VerifiableMock + } #it + + } #context_Error + Context 'Success' { + + It 'should warn the user if the API call was successful, but no results were found' { + Mock Write-Warning { } + Mock -CommandName Invoke-RestMethod -MockWith { + [PSCustomObject]@{ + resourceSets = [PSCustomObject]@{ + estimatedTotal = 0 + } + statusCode = '200' + statusDescription = 'OK' + } + } #endMock + Search-BingNearbyPlace -Type Attractions + Assert-MockCalled -CommandName Write-Warning -Times 1 + Assert-VerifiableMock + } #it + + It 'should return expected results if no issues are encountered' { + $eval = Search-BingNearbyPlace -Type CafeRestaurants -PointLatitude '29.7049806' -PointLongitude '-98.068343' + ($eval | Measure-Object).Count | Should -BeExactly 1 + $eval.Latitude | Should -BeExactly '29.7015113830566' + $eval.Longitude | Should -BeExactly '-98.1247940063477' + } #it + + # jake- put all the things here + It 'should call the API with the expected parameters when all options are provided' { + Mock -CommandName Invoke-RestMethod { + $Uri | Should -BeLike 'https://dev.virtualearth.net/REST/v1/LocalSearch?output=json*' + $Uri | Should -BeLike '*type=*' + $Uri | Should -BeLike '*userLocation=*' + $Uri | Should -BeLike '*culture=en*' + $Uri | Should -BeLike '*maxResults=*' + } -Verifiable + Search-BingNearbyPlace -Type Museums -PointLatitude '29.7049806' -PointLongitude '-98.068343' -Language en -MaxResults 20 -RegionBias us + Assert-VerifiableMock + } #it + + It 'should call the API with the expected parameters with circle' { + Mock -CommandName Invoke-RestMethod { + $Uri | Should -BeLike 'https://dev.virtualearth.net/REST/v1/LocalSearch?output=json*userCircularMapView=*' + } -Verifiable + Search-BingNearbyPlace -Type BreweriesAndBrewPubs -CircleLatitude '29.7049806' -CircleLongitude '-98.068343' -CircleRadius '5000' + Assert-VerifiableMock + } #it + + It 'should call the API with the expected parameters with rectangle' { + Mock -CommandName Invoke-RestMethod { + $Uri | Should -BeLike 'https://dev.virtualearth.net/REST/v1/LocalSearch?output=json*userMapView=*' + } -Verifiable + Search-BingNearbyPlace -Type Parks -SouthLatitude '39.8592387' -WestLongitude '-75.295486' -NorthLatitude '40.0381942' -EastLongitude '-75.0064087' + Assert-VerifiableMock + } #it + + } #context_Success + } #describe_Search-BingNearbyPlace +} #inModule diff --git a/src/pwshPlaces/Public/Find-BingPlace.ps1 b/src/pwshPlaces/Public/Find-BingPlace.ps1 index 78ceeb9..bce621c 100644 --- a/src/pwshPlaces/Public/Find-BingPlace.ps1 +++ b/src/pwshPlaces/Public/Find-BingPlace.ps1 @@ -77,7 +77,7 @@ .LINK https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Find-BingPlace.md .LINK - https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-query + https://docs.microsoft.com/bingmaps/rest-services/locations/local-search .LINK https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/user-context-parameters .LINK @@ -172,7 +172,6 @@ function Find-BingPlace { Write-Debug -Message ($PSCmdlet.ParameterSetName) - # $uri = '{0}{1}' -f $bingMapsBaseURI, 'v1/Locations?output=json' $uri = '{0}{1}' -f $bingMapsBaseURI, 'v1/LocalSearch?output=json' Write-Debug -Message ('Base function URI: {0}' -f $uri) @@ -183,7 +182,6 @@ function Find-BingPlace { 'Point' { Write-Debug -Message 'Point specified' $combinedPoint = '{0},{1}' -f $PointLatitude, $PointLongitude - # $fLocationBias = '&userLocation={0}' -f $combinedPoint $fLocationBias = '&userLocation={0}' -f [uri]::EscapeDataString($combinedPoint) $uri += $fLocationBias } #point @@ -196,7 +194,6 @@ function Find-BingPlace { 'Rectangle' { Write-Debug -Message 'Rectangle specified' $combinedRectangle = '{0},{1},{2},{3}' -f $SouthLatitude, $WestLongitude, $NorthLatitude, $EastLongitude - # $fLocationBias = '&userMapView={0}' -f $combinedRectangle $fLocationBias = '&userMapView={0}' -f [uri]::EscapeDataString($combinedRectangle) $uri += $fLocationBias } #rectangle @@ -245,7 +242,6 @@ function Find-BingPlace { } else { $finalResults = ($results.resourceSets.resources | Format-BingPlace) - # $finalResults = $results } return $finalResults diff --git a/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 b/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 index a25de86..5913de9 100644 --- a/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 +++ b/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 @@ -73,6 +73,8 @@ https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-address .LINK https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-point +.LINK + https://docs.microsoft.com/bingmaps/rest-services/locations/find-a-location-by-query .LINK https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes .LINK diff --git a/src/pwshPlaces/Public/Search-BingNearbyPlace.ps1 b/src/pwshPlaces/Public/Search-BingNearbyPlace.ps1 new file mode 100644 index 0000000..44c62c7 --- /dev/null +++ b/src/pwshPlaces/Public/Search-BingNearbyPlace.ps1 @@ -0,0 +1,249 @@ +<# +.SYNOPSIS + Nearby Search lets you search for different place types within a specified area. +.DESCRIPTION + Performs a nearby search request with provided parameters. + Nearby search is useful for finding place types near a specific geographic location. + By default the location bias is IP based. + Location bias can be controlled via parameters. +.EXAMPLE + Search-BingNearbyPlace -Type Attractions + + Performs a nearby search biased by IP and returns Attraction places types. +.EXAMPLE + Search-BingNearbyPlace -Type Restaurants -MaxResults 20 + + Performs a nearby search biased by IP and returns Restaurant places types with a maximum of 20 results returned. +.EXAMPLE + Search-BingNearbyPlace -Type CafeRestaurants -PointLatitude '29.7049806' -PointLongitude '-98.068343' + + Performs a nearby search near the provided Lat/Long and returns CafeRestaurant places types. +.EXAMPLE + Search-BingNearbyPlace -Type BreweriesAndBrewPubs -CircleLatitude '29.7049806' -CircleLongitude '-98.068343' -CircleRadius '5000' + + Performs a nearby search biased by circle lat/long/radius and returns Bars and Pubs places types. +.EXAMPLE + Search-BingNearbyPlace -Type Parks -SouthLatitude '39.8592387' -WestLongitude '-75.295486' -NorthLatitude '40.0381942' -EastLongitude '-75.0064087' + + Performs a nearby search biased by rectangular two lat/lng pairs in decimal degrees, representing the south/west and north/east points of a rectangle. Park places types are returned. +.EXAMPLE + Search-BingNearbyPlace -Type Museums -PointLatitude '29.7049806' -PointLongitude '-98.068343' -Language en -MaxResults 20 + + Performs a nearby search near the provided Lat/Long and returns Museum places types. Results are returned in english with a maximum of 20 results returned. +.EXAMPLE + $searchBingNearbyPlaceSplat = @{ + Type = 'Museums' + PointLatitude = '29.7049806' + PointLongitude = '-98.068343' + Language = 'en' + MaxResults = 20 + } + Search-BingNearbyPlace @searchBingNearbyPlaceSplat + + Performs a nearby search near the provided Lat/Long and returns Museum places types. Results are returned in english with a maximum of 20 results returned. +.PARAMETER Query + A string that contains information about a location, such as an address or landmark name. +.PARAMETER PointLatitude + Prefer results in a specified area by specifying a single coordinate for the north–south position of a point on the Earth's surface. +.PARAMETER PointLongitude + Prefer results in a specified area by specifying a single coordinate for the east–west position of a point on the Earths surface. +.PARAMETER CircleLatitude + Prefer results in a specified area by specifying a radius plus lat/long - north–south position of a point on the Earth's surface. +.PARAMETER CircleLongitude + Prefer results in a specified area by specifying a radius plus lat/long - east–west position of a point on the Earths surface. +.PARAMETER CircleRadius + Prefer results in a specified area by specifying a radius plus lat/long - radius in meters +.PARAMETER SouthLatitude + Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - south latitude +.PARAMETER WestLongitude + Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - west longitude +.PARAMETER NorthLatitude + Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - north latitude +.PARAMETER EastLongitude + Prefer results in a specified area by specifying two lat/lng pairs representing the south/west and north/east points of a rectangle - east longitude +.PARAMETER RegionBias + The region code, specified as a ccTLD ("top-level domain") two-character value. +.PARAMETER Language + The language in which to return results. +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + + Example: + http://dev.virtualearth.net/REST/v1/Locations?countryRegion={countryRegion}&adminDistrict={adminDistrict}&locality={locality}&postalCode={postalCode}&addressLine={addressLine}&userLocation={userLocation}&userIp={userIp}&usermapView={usermapView}&includeNeighborhood={includeNeighborhood}&maxResults={maxResults}&key={BingMapsKey} +.COMPONENT + pwshPlaces +.LINK + https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Search-BingNearbyPlace.md +.LINK + https://docs.microsoft.com/bingmaps/rest-services/locations/local-search +.LINK + https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/user-context-parameters +.LINK + https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes +.LINK + https://www.microsoft.com/maps/product/terms.html +.LINK + https://privacy.microsoft.com/en-us/privacystatement +#> +function Search-BingNearbyPlace { + [CmdletBinding( + PositionalBinding = $false, + DefaultParameterSetName = 'PlaceType')] + param ( + + [Parameter(Mandatory = $true, + ParameterSetName = 'PlaceType', + HelpMessage = 'Restricts the results to places matching the specified type')] + [Parameter(ParameterSetName = 'Point', Mandatory = $false)] + [Parameter(ParameterSetName = 'Circle', Mandatory = $false)] + [Parameter(ParameterSetName = 'Rectangle', Mandatory = $false)] + [typeIdentifier]$Type, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Point', + HelpMessage = 'Location bias by point lat')] + [ValidateNotNullOrEmpty()] + [string]$PointLatitude, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Point', + HelpMessage = 'Location bias by point long')] + [ValidateNotNullOrEmpty()] + [string]$PointLongitude, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Circle', + HelpMessage = 'Location bias circular lat')] + [ValidateNotNullOrEmpty()] + [string]$CircleLatitude, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Circle', + HelpMessage = 'Location bias circular long')] + [ValidateNotNullOrEmpty()] + [string]$CircleLongitude, + + [Parameter(Mandatory = $false, + ParameterSetName = 'Circle', + HelpMessage = 'Location bias circular radius')] + [ValidateRange(0, 5000)] + [string]$CircleRadius, + + # A string specifying two lat/lng pairs in decimal degrees, representing the south/west and north/east points of a rectangle. + [Parameter(Mandatory = $true, + ParameterSetName = 'Rectangle', + HelpMessage = 'Location bias rectangle south lat')] + [ValidateNotNullOrEmpty()] + [string]$SouthLatitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Rectangle', + HelpMessage = 'Location bias rectangle west long')] + [ValidateNotNullOrEmpty()] + [string]$WestLongitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Rectangle', + HelpMessage = 'Location bias rectangle north lat')] + [ValidateNotNullOrEmpty()] + [string]$NorthLatitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Rectangle', + HelpMessage = 'Location bias rectangle east long')] + [ValidateNotNullOrEmpty()] + [string]$EastLongitude, + + [Parameter(Mandatory = $false, + HelpMessage = 'The region code, specified as a ccTLD')] + [ccTLD]$RegionBias, + + [Parameter(Mandatory = $false, + HelpMessage = 'The language in which to return results')] + [languages]$Language, + + [Parameter(Mandatory = $false, + HelpMessage = 'Specifies the maximum number of locations to return in the response')] + [ValidateRange(1, 20)] + [int]$MaxResults + ) + + Write-Debug -Message ($PSCmdlet.ParameterSetName) + + $uri = '{0}{1}' -f $bingMapsBaseURI, 'v1/LocalSearch?output=json' + Write-Debug -Message ('Base function URI: {0}' -f $uri) + + $fType = '&type={0}' -f [uri]::EscapeDataString($type) + $uri += $fType + + switch ($PSCmdlet.ParameterSetName) { + 'Point' { + Write-Debug -Message 'Point specified' + $combinedPoint = '{0},{1}' -f $PointLatitude, $PointLongitude + $fLocationBias = '&userLocation={0}' -f [uri]::EscapeDataString($combinedPoint) + $uri += $fLocationBias + } #point + 'Circle' { + Write-Debug -Message 'Circle specified' + $combinedCircle = '{0},{1},{2}' -f $CircleLatitude, $CircleLongitude, $CircleRadius + $fLocationBias = '&userCircularMapView={0}' -f [uri]::EscapeDataString($combinedCircle) + $uri += $fLocationBias + } #circle + 'Rectangle' { + Write-Debug -Message 'Rectangle specified' + $combinedRectangle = '{0},{1},{2},{3}' -f $SouthLatitude, $WestLongitude, $NorthLatitude, $EastLongitude + $fLocationBias = '&userMapView={0}' -f [uri]::EscapeDataString($combinedRectangle) + $uri += $fLocationBias + } #rectangle + } #switch_parametersetname + + if ($RegionBias) { + Write-Debug -Message ('RegionBias: {0}' -f $RegionBias) + $fRegion = '&userRegion={0}' -f $RegionBias + $uri += $fRegion + } + if ($MaxResults) { + Write-Debug -Message ('MaxResults: {0}' -f $MaxResults) + $fMaxResults = '&maxResults={0}' -f $MaxResults + $uri += $fMaxResults + } + if ($Language) { + Write-Debug -Message ('Language: {0}' -f $Language) + $fLanguage = '&culture={0}' -f $Language + $uri += $fLanguage + } + + Write-Verbose -Message ('Querying Bing API: {0}' -f $uri) + + Write-Debug -Message 'Adding API key' + $fAPIKey = '&key={0}' -f $env:BingAPIKey + $uri += $fAPIKey + + $invokeRestMethodSplat = @{ + Uri = $uri + ErrorAction = 'Stop' + } + try { + $results = Invoke-RestMethod @invokeRestMethodSplat + } + catch { + throw $_ + } + + if ($results.statusDescription -ne 'OK') { + Write-Warning -Message 'Did not get a succcessful return from Bing Location API endpoint' + $finalResults = $results + } + elseif (-not ($results.resourceSets.estimatedTotal -ge 1)) { + Write-Warning -Message 'No results returned from query' + $finalResults = $results + } + else { + $finalResults = ($results.resourceSets.resources | Format-BingPlace) + } + + return $finalResults + +} #Search-BingNearbyPlace diff --git a/src/pwshPlaces/pwshPlaces.psd1 b/src/pwshPlaces/pwshPlaces.psd1 index a02316d..f8791e9 100644 --- a/src/pwshPlaces/pwshPlaces.psd1 +++ b/src/pwshPlaces/pwshPlaces.psd1 @@ -12,7 +12,7 @@ RootModule = 'pwshPlaces.psm1' # Version number of this module. - ModuleVersion = '0.5.3' + ModuleVersion = '0.5.4' # Supported PSEditions # CompatiblePSEditions = @() @@ -75,6 +75,7 @@ 'Get-GMapPlaceDetail' 'Invoke-BingGeoCode' 'Invoke-GMapGeoCode' + 'Search-BingNearbyPlace' 'Search-GMapNearbyPlace' 'Search-GMapText' ) From 64a627f49388eef9920ba7c86c13e6749febc43a Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sun, 10 Oct 2021 12:32:47 -0500 Subject: [PATCH 16/22] Added Find-BingTimeZone --- docs/Find-BingTimeZone.md | 150 ++++++++++++++++++ docs/pwshPlaces.md | 5 +- .../Infrastructure/pwshPlaces-Infra.Tests.ps1 | 12 ++ .../Private/Format-BingTimeZone.Tests.ps1 | 57 +++++++ .../Unit/Public/Find-BingTimeZone.Tests.ps1 | 110 +++++++++++++ src/Tests/Unit/TestObjects.psm1 | 65 ++++++++ .../Private/Format-BingTimeZone.ps1 | 116 ++++++++++++++ src/pwshPlaces/Public/Find-BingTimeZone.ps1 | 143 +++++++++++++++++ src/pwshPlaces/pwshPlaces.psd1 | 4 +- 9 files changed, 660 insertions(+), 2 deletions(-) create mode 100644 docs/Find-BingTimeZone.md create mode 100644 src/Tests/Unit/Private/Format-BingTimeZone.Tests.ps1 create mode 100644 src/Tests/Unit/Public/Find-BingTimeZone.Tests.ps1 create mode 100644 src/pwshPlaces/Private/Format-BingTimeZone.ps1 create mode 100644 src/pwshPlaces/Public/Find-BingTimeZone.ps1 diff --git a/docs/Find-BingTimeZone.md b/docs/Find-BingTimeZone.md new file mode 100644 index 0000000..2f76a41 --- /dev/null +++ b/docs/Find-BingTimeZone.md @@ -0,0 +1,150 @@ +--- +external help file: pwshPlaces-help.xml +Module Name: pwshPlaces +online version: https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Find-BingTimeZone.md +schema: 2.0.0 +--- + +# Find-BingTimeZone + +## SYNOPSIS +Retrieve time zone information for any point on Earth + +## SYNTAX + +### textquery +``` +Find-BingTimeZone -Query [-RegionBias ] [-Language ] [] +``` + +### Point +``` +Find-BingTimeZone -PointLatitude -PointLongitude [-RegionBias ] + [-Language ] [] +``` + +## DESCRIPTION +Given a pair of coordinates or a place name query the Time Zone API will return local time zone and daylight savings (DST) information for that location. + +## EXAMPLES + +### EXAMPLE 1 +``` +Find-BingTimeZone -Query 'New Braunfels, TX' +``` + +Returns Time Zone information for matches found for the provided query. + +### EXAMPLE 2 +``` +Find-BingTimeZone -PointLatitude 29.70 -PointLongitude -98.11 +``` + +Returns Time Zone information for the provided coordinates. + +## PARAMETERS + +### -Query +A string that contains information about a location, such as an address or landmark name. + +```yaml +Type: String +Parameter Sets: textquery +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PointLatitude +Prefer results in a specified area by specifying a single coordinate for the north-south position of a point on the Earth's surface. + +```yaml +Type: String +Parameter Sets: Point +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PointLongitude +Prefer results in a specified area by specifying a single coordinate for the east-west position of a point on the Earths surface. + +```yaml +Type: String +Parameter Sets: Point +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -RegionBias +The region code, specified as a ccTLD ("top-level domain") two-character value. + +```yaml +Type: ccTLD +Parameter Sets: (All) +Aliases: +Accepted values: ac, ad, ae, af, ag, ai, al, am, ao, aq, ar, as, at, au, aw, ax, az, ba, bb, bd, be, bf, bg, bh, bi, bj, bm, bn, bo, br, bs, bt, bv, bw, by, bz, ca, cc, cd, cf, cg, ch, ci, ck, cl, cm, cn, co, cr, cu, cv, cw, cx, cy, cz, de, dj, dk, dm, do, dz, ec, ee, eg, er, es, et, eu, fi, fj, fk, fm, fo, fr, ga, gb, gd, ge, gf, gg, gh, gi, gl, gm, gn, gp, gq, gr, gs, gt, gu, gw, gy, hk, hm, hn, hr, ht, hu, id, ie, il, im, in, io, iq, ir, is, it, je, jm, jo, jp, ke, kg, kh, ki, km, kn, kp, kr, kw, ky, kz, la, lb, lc, li, lk, lr, ls, lt, lu, lv, ly, ma, mc, md, me, mg, mh, mk, ml, mm, mn, mo, mp, mq, mr, ms, mt, mu, mv, mw, mx, my, mz, na, nc, ne, nf, ng, ni, nl, no, np, nr, nu, nz, om, pa, pe, pf, pg, ph, pk, pl, pm, pn, pr, ps, pt, pw, py, qa, re, ro, rs, ru, rw, sa, sb, sc, sd, se, sg, sh, si, sj, sk, sl, sm, sn, so, sr, ss, st, su, sv, sx, sy, sz, tc, td, tf, tg, th, tj, tk, tl, tm, tn, to, tr, tt, tv, tw, tz, ua, ug, uk, us, uy, uz, va, vc, ve, vg, vi, vn, vu, wf, ws, ye, yt, za, zm, zw + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Language +The language in which to return results. + +```yaml +Type: languages +Parameter Sets: (All) +Aliases: +Accepted values: af, sq, am, ar, hy, az, eu, be, bn, bs, bg, my, ca, zh, hr, cs, da, nl, en, et, fa, fi, fil, fr, ka, de, el, iw, hi, hu, is, id, it, ja, kn, kk, km, ko, ky, lo, lv, lt, mk, ms, ml, mr, mn, ne, no, pl, pt, pa, ro, ru, sr, sk, es, sw, ta, te, th, uk, ur, uz, vi, zu + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### Output from this cmdlet (if any) +## NOTES +Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + +Example: + https://dev.virtualearth.net/REST/v1/TimeZone/{point}?datetime={datetime_utc}&key={BingMapsAPIKey} + +## RELATED LINKS + +[https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Find-BingTimeZone.md](https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Find-BingTimeZone.md) + +[https://docs.microsoft.com/bingmaps/rest-services/timezone/find-time-zone](https://docs.microsoft.com/bingmaps/rest-services/timezone/find-time-zone) + +[https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes](https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes) + +[https://www.microsoft.com/maps/product/terms.html](https://www.microsoft.com/maps/product/terms.html) + +[https://privacy.microsoft.com/en-us/privacystatement](https://privacy.microsoft.com/en-us/privacystatement) + diff --git a/docs/pwshPlaces.md b/docs/pwshPlaces.md index 6fd0f5a..5e70671 100644 --- a/docs/pwshPlaces.md +++ b/docs/pwshPlaces.md @@ -2,7 +2,7 @@ Module Name: pwshPlaces Module Guid: 9a9914bd-d115-4f42-bb5d-19c5e5561a3f Download Help Link: NA -Help Version: 0.5.4 +Help Version: 0.5.5 Locale: en-US --- @@ -14,6 +14,9 @@ tbd ### [Find-BingPlace](Find-BingPlace.md) Returns a list of business entities centered around a location or a geographic region +### [Find-BingTimeZone](Find-BingTimeZone.md) +Retrieve time zone information for any point on Earth + ### [Find-GMapPlace](Find-GMapPlace.md) Find Place request takes a text input and returns a place. The input can be any kind of Places text data, such as a name, address, or phone number. diff --git a/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 b/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 index 62522c0..e9f6ed6 100644 --- a/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 +++ b/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 @@ -156,5 +156,17 @@ Describe 'Infrastructure Tests' -Tag Infrastructure { Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) } #it } #context_Find-BingPlace + Context 'Find-BingTimeZone' { + It 'should return the expected results' { + $findBingTimeZoneSplat = @{ + PointLatitude = '29.70' + PointLongitude = '-98.11' + } + $eval = Find-BingTimeZone @findBingTimeZoneSplat + $eval.TimeZoneName | Should -BeExactly 'Central Standard Time' + $eval.TimeZoneShort | Should -BeExactly 'CST' + Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) + } #it + } #context_Find-BingPlace } #context_BingMaps } #describe_infra_tests diff --git a/src/Tests/Unit/Private/Format-BingTimeZone.Tests.ps1 b/src/Tests/Unit/Private/Format-BingTimeZone.Tests.ps1 new file mode 100644 index 0000000..e3fbdfa --- /dev/null +++ b/src/Tests/Unit/Private/Format-BingTimeZone.Tests.ps1 @@ -0,0 +1,57 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +$PathToTestObjects = [System.IO.Path]::Combine('..', 'TestObjects.psm1') +Import-Module $PathToTestObjects -DisableNameChecking -Global -Force +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + #------------------------------------------------------------------------- + $WarningPreference = "SilentlyContinue" + #------------------------------------------------------------------------- + Describe 'Format-BingTimeZone' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + } #beforeAll + # Context 'Error' { + # } #context_Error + Context 'Success' { + + # BeforeEach { + # } #beforeEach + + It 'should return the expected results for queries' { + $eval = ($findBingTimeZone.resourceSets.resources.timeZoneAtLocation.timeZone | Format-BingTimeZone) + $eval.TimeZoneName | Should -BeExactly 'Central Standard Time' + $eval.TimeZoneShort | Should -BeExactly 'CST' + $eval.UTCOffSet | Should -BeExactly '-6:00' + $eval.TimeZoneID | Should -BeExactly 'America/Chicago' + $eval.LocalTime | Should -BeExactly '10/10/21 10:58:29' + $eval.TimeZoneCurrentName | Should -BeExactly 'Central Daylight Time' + $eval.TimeZoneCurrentShort | Should -BeExactly 'CDT' + $eval.UTCOffSetDST | Should -BeExactly '-5:00' + } #it + + It 'should return the expected results for point' { + $eval = ($findBingTimeZonePoint.resourceSets.resources.timeZone | Format-BingTimeZone) + $eval.TimeZoneName | Should -BeExactly 'Central Standard Time' + $eval.TimeZoneShort | Should -BeExactly 'CST' + $eval.UTCOffSet | Should -BeExactly '-6:00' + $eval.TimeZoneID | Should -BeExactly 'America/Chicago' + $eval.LocalTime | Should -BeExactly '10/10/21 10:58:29' + $eval.TimeZoneCurrentName | Should -BeExactly 'Central Daylight Time' + $eval.TimeZoneCurrentShort | Should -BeExactly 'CDT' + $eval.UTCOffSetDST | Should -BeExactly '-5:00' + } #it + } #context_Success + } #describe_Format-BingTimeZone +} #inModule diff --git a/src/Tests/Unit/Public/Find-BingTimeZone.Tests.ps1 b/src/Tests/Unit/Public/Find-BingTimeZone.Tests.ps1 new file mode 100644 index 0000000..c46dace --- /dev/null +++ b/src/Tests/Unit/Public/Find-BingTimeZone.Tests.ps1 @@ -0,0 +1,110 @@ +#------------------------------------------------------------------------- +Set-Location -Path $PSScriptRoot +#------------------------------------------------------------------------- +$ModuleName = 'pwshPlaces' +$PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1") +$PathToTestObjects = [System.IO.Path]::Combine('..', 'TestObjects.psm1') +Import-Module $PathToTestObjects -DisableNameChecking -Global -Force +#------------------------------------------------------------------------- +if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') { + #if the module is already in memory, remove it + Remove-Module -Name $ModuleName -Force +} +Import-Module $PathToManifest -Force +#------------------------------------------------------------------------- + +InModuleScope 'pwshPlaces' { + Describe 'Find-BingTimeZone' -Tag Unit { + BeforeAll { + $WarningPreference = 'SilentlyContinue' + $ErrorActionPreference = 'SilentlyContinue' + } #beforeAll + BeforeEach { + Mock -CommandName Invoke-RestMethod -MockWith { + $findBingTimeZone + } #endMock + } + Context 'Error' { + + It 'should throw if an error is encountered with invoking the API' { + Mock -CommandName Invoke-RestMethod -MockWith { + throw 'Fake Error' + } #endMock + { Find-BingTimeZone -Query 'New Braunfels, TX' } | Should -Throw + } #it + + It 'should warn the user if the API does not return an OK status' { + Mock Write-Warning { } + Mock -CommandName Invoke-RestMethod -MockWith { + [PSCustomObject]@{ + results = '' + status = 'ZERO_RESULTS' + } + } #endMock + Find-BingTimeZone -PointLatitude 29.70 -PointLongitude -98.11 + Assert-MockCalled -CommandName Write-Warning -Times 1 + Assert-VerifiableMock + } #it + + } #context_Error + Context 'Success' { + + It 'should warn the user if the API call was successful, but no results were found' { + Mock Write-Warning { } + Mock -CommandName Invoke-RestMethod -MockWith { + [PSCustomObject]@{ + resourceSets = [PSCustomObject]@{ + estimatedTotal = 0 + } + statusCode = '200' + statusDescription = 'OK' + } + } #endMock + Find-BingTimeZone -PointLatitude 29.70 -PointLongitude -98.11 + Assert-MockCalled -CommandName Write-Warning -Times 1 + Assert-VerifiableMock + } #it + + It 'should return expected results if no issues are encountered with query' { + $eval = Find-BingTimeZone -Query 'New Braunfels, TX' + ($eval | Measure-Object).Count | Should -BeExactly 1 + $eval.TimeZoneName | Should -BeExactly 'Central Standard Time' + $eval.TimeZoneShort | Should -BeExactly 'CST' + $eval.UTCOffSet | Should -BeExactly '-6:00' + $eval.TimeZoneID | Should -BeExactly 'America/Chicago' + $eval.LocalTime | Should -BeExactly '10/10/21 10:58:29' + $eval.TimeZoneCurrentName | Should -BeExactly 'Central Daylight Time' + $eval.TimeZoneCurrentShort | Should -BeExactly 'CDT' + $eval.UTCOffSetDST | Should -BeExactly '-5:00' + } #it + + It 'should return expected results if no issues are encountered with point' { + Mock -CommandName Invoke-RestMethod -MockWith { + $findBingTimeZonePoint + } #endMock + $eval = Find-BingTimeZone -PointLatitude 29.70 -PointLongitude -98.11 + ($eval | Measure-Object).Count | Should -BeExactly 1 + $eval.TimeZoneName | Should -BeExactly 'Central Standard Time' + $eval.TimeZoneShort | Should -BeExactly 'CST' + $eval.UTCOffSet | Should -BeExactly '-6:00' + $eval.TimeZoneID | Should -BeExactly 'America/Chicago' + $eval.LocalTime | Should -BeExactly '10/10/21 10:58:29' + $eval.TimeZoneCurrentName | Should -BeExactly 'Central Daylight Time' + $eval.TimeZoneCurrentShort | Should -BeExactly 'CDT' + $eval.UTCOffSetDST | Should -BeExactly '-5:00' + } #it + + # jake- put all the things here + It 'should call the API with the expected parameters when all options are provided' { + Mock -CommandName Invoke-RestMethod { + $Uri | Should -BeLike 'https://dev.virtualearth.net/REST/v1/TimeZone*?output=json*' + $Uri | Should -BeLike '*userRegion=*' + $Uri | Should -BeLike '*culture=en*' + } -Verifiable + Find-BingTimeZone -PointLatitude 29.70 -PointLongitude -98.11 -Language en -RegionBias us + Assert-VerifiableMock + } #it + + } #context_Success + } #describe_Find-BingTimeZone +} #inModule diff --git a/src/Tests/Unit/TestObjects.psm1 b/src/Tests/Unit/TestObjects.psm1 index 6830a37..8e7367e 100644 --- a/src/Tests/Unit/TestObjects.psm1 +++ b/src/Tests/Unit/TestObjects.psm1 @@ -1100,6 +1100,71 @@ $findBingPlace = [PSCustomObject]@{ traceId = 'xxxxxxxxxxxxxxxxx|XXXXXXX|0.0.0.1|Ref A:XXXXXXXXXXXXX Ref B: XXXXXXXXX Ref C: 2021-10-06T03:08:54Z' } +$findBingTimeZone = [PSCustomObject]@{ + authenticationResultCode = 'ValidCredentials' + brandLogoUri = 'http://dev.virtualearth.net/Branding/logo_powered_by.png' + copyright = 'Copyright © 2021 Microsoft and its suppliers. All rights reserved. This API + cannot be accessed and the content and any results may not be used, reproduced + or transmitted in any manner without express written permission from Microsoft + Corporation.' + resourceSets = [PSCustomObject]@{ + estimatedTotal = 1 + resources = [PSCustomObject]@{ + '__type' = 'RESTTimeZone:http://schemas.microsoft.com/search/local/ws/rest/v1' + timeZoneAtLocation = [PSCustomObject]@{ + placeName = 'New Braunfels, TX' + timeZone = [PSCustomObject]@{ + genericName = 'Central Standard Time' + abbreviation = 'CST' + ianaTimeZoneId = 'America/Chicago' + windowsTimeZoneId = 'Central Standard Time' + utcOffset = '-6:00' + convertedTime = [PSCustomObject]@{ + localTime = '10/10/21 10:58:29' + utcOffsetWithDst = '-5:00' + timeZoneDisplayName = 'Central Daylight Time' + timeZoneDisplayAbbr = 'CDT' + } + } + } + } + } + statusCode = '200' + statusDescription = 'OK' + traceId = 'xxxxxxxxxxxxxxxxx|XXXXXXX|0.0.0.1|Ref A:XXXXXXXXXXXXX Ref B: XXXXXXXXX Ref C: 2021-10-06T03:08:54Z' +} + +$findBingTimeZonePoint = [PSCustomObject]@{ + authenticationResultCode = 'ValidCredentials' + brandLogoUri = 'http://dev.virtualearth.net/Branding/logo_powered_by.png' + copyright = 'Copyright © 2021 Microsoft and its suppliers. All rights reserved. This API + cannot be accessed and the content and any results may not be used, reproduced + or transmitted in any manner without express written permission from Microsoft + Corporation.' + resourceSets = [PSCustomObject]@{ + estimatedTotal = 1 + resources = [PSCustomObject]@{ + '__type' = 'RESTTimeZone:http://schemas.microsoft.com/search/local/ws/rest/v1' + timeZone = [PSCustomObject]@{ + genericName = 'Central Standard Time' + abbreviation = 'CST' + ianaTimeZoneId = 'America/Chicago' + windowsTimeZoneId = 'Central Standard Time' + utcOffset = '-6:00' + convertedTime = [PSCustomObject]@{ + localTime = '10/10/21 10:58:29' + utcOffsetWithDst = '-5:00' + timeZoneDisplayName = 'Central Daylight Time' + timeZoneDisplayAbbr = 'CDT' + } + } + } + } + statusCode = '200' + statusDescription = 'OK' + traceId = 'xxxxxxxxxxxxxxxxx|XXXXXXX|0.0.0.1|Ref A:XXXXXXXXXXXXX Ref B: XXXXXXXXX Ref C: 2021-10-06T03:08:54Z' +} + #endregion Export-ModuleMember -Variable '*' diff --git a/src/pwshPlaces/Private/Format-BingTimeZone.ps1 b/src/pwshPlaces/Private/Format-BingTimeZone.ps1 new file mode 100644 index 0000000..4d30bba --- /dev/null +++ b/src/pwshPlaces/Private/Format-BingTimeZone.ps1 @@ -0,0 +1,116 @@ +<# +.SYNOPSIS + Formats TimeZone object with easier to understand properties while leaving original properties intact +.DESCRIPTION + Changes TimeZone object to custom PSType and creates additional properties that contains information most likely to be viewed. +.EXAMPLE + $results.resourceSets.resources.timeZone | Format-BingTimeZone + + Formats TimeZone object results with a set of easier to understand properties +.PARAMETER Results + TimeZone API results +.OUTPUTS + Bing.TimeZone +.NOTES + Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + + Based on code from: https://github.com/Kreloc/PoshGMaps +.COMPONENT + pwshPlaces +#> +function Format-BingTimeZone { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, + HelpMessage = 'TimeZone API results', + ValueFromPipeline = $true)] + $Results + ) + begin { + Write-Verbose ('Starting {0}' -f $myinvocation.mycommand) + } #begin + process { + Write-Debug -Message ($Results | Out-String) + + $Results.PSTypeNames.Insert(0, 'Bing.TimeZone') + + Write-Debug -Message ($Results.PSTypeNames | Out-String) + + $updateTypeDataSplat = @{ + TypeName = 'Bing.TimeZone' + MemberType = 'ScriptProperty' + MemberName = 'TimeZoneName' + Value = { $this.genericName } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'Bing.TimeZone' + MemberType = 'ScriptProperty' + MemberName = 'TimeZoneShort' + Value = { $this.abbreviation } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'Bing.TimeZone' + MemberType = 'ScriptProperty' + MemberName = 'TimeZoneID' + Value = { $this.ianaTimeZoneId } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'Bing.TimeZone' + MemberType = 'ScriptProperty' + MemberName = 'LocalTime' + Value = { $this.convertedTime.localTime } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'Bing.TimeZone' + MemberType = 'ScriptProperty' + MemberName = 'UTCOffSetDST' + Value = { $this.convertedTime.utcOffsetWithDst } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'Bing.TimeZone' + MemberType = 'ScriptProperty' + MemberName = 'TimeZoneCurrentName' + Value = { $this.convertedTime.timeZoneDisplayName } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $updateTypeDataSplat = @{ + TypeName = 'Bing.TimeZone' + MemberType = 'ScriptProperty' + MemberName = 'TimeZoneCurrentShort' + Value = { $this.convertedTime.timeZoneDisplayAbbr } + Force = $true + } + Update-TypeData @updateTypeDataSplat + + # set a default display of the above properties, all other properties are still there just not displayed + $updateTypeDataSplat = @{ + TypeName = 'Bing.TimeZone' + DefaultDisplayPropertySet = 'TimeZoneName', 'TimeZoneShort', 'UTCOffSet', 'TimeZoneID', 'LocalTime', 'TimeZoneCurrentName', 'TimeZoneCurrentShort', 'UTCOffSetDST' + DefaultKeyPropertySet = 'TimeZoneName' + Force = $true + } + Update-TypeData @updateTypeDataSplat + + $Results + } #process + end { + Write-Verbose ('Ending {0}' -f $myinvocation.mycommand) + } #end +} #Format-BingTimeZone diff --git a/src/pwshPlaces/Public/Find-BingTimeZone.ps1 b/src/pwshPlaces/Public/Find-BingTimeZone.ps1 new file mode 100644 index 0000000..5073935 --- /dev/null +++ b/src/pwshPlaces/Public/Find-BingTimeZone.ps1 @@ -0,0 +1,143 @@ +<# +.SYNOPSIS + Retrieve time zone information for any point on Earth +.DESCRIPTION + Given a pair of coordinates or a place name query the Time Zone API will return local time zone and daylight savings (DST) information for that location. +.EXAMPLE + Find-BingTimeZone -Query 'New Braunfels, TX' + + Returns Time Zone information for matches found for the provided query. +.EXAMPLE + Find-BingTimeZone -PointLatitude 29.70 -PointLongitude -98.11 + + Returns Time Zone information for the provided coordinates. +.PARAMETER Query + A string that contains information about a location, such as an address or landmark name. +.PARAMETER PointLatitude + Prefer results in a specified area by specifying a single coordinate for the north–south position of a point on the Earth's surface. +.PARAMETER PointLongitude + Prefer results in a specified area by specifying a single coordinate for the east–west position of a point on the Earths surface. +.PARAMETER RegionBias + The region code, specified as a ccTLD ("top-level domain") two-character value. +.PARAMETER Language + The language in which to return results. +.OUTPUTS + Output from this cmdlet (if any) +.NOTES + Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ + + Example: + https://dev.virtualearth.net/REST/v1/TimeZone/{point}?datetime={datetime_utc}&key={BingMapsAPIKey} +.COMPONENT + pwshPlaces +.LINK + https://github.com/techthoughts2/pwshPlaces/blob/master/docs/Find-BingTimeZone.md +.LINK + https://docs.microsoft.com/bingmaps/rest-services/timezone/find-time-zone +.LINK + https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes +.LINK + https://www.microsoft.com/maps/product/terms.html +.LINK + https://privacy.microsoft.com/en-us/privacystatement +#> +function Find-BingTimeZone { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, + ParameterSetName = 'textquery', + HelpMessage = 'A string that contains information about a location, such as an address or landmark name')] + [ValidateNotNullOrEmpty()] + [string]$Query, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Point', + HelpMessage = 'Location bias by point lat')] + [ValidateNotNullOrEmpty()] + [string]$PointLatitude, + + [Parameter(Mandatory = $true, + ParameterSetName = 'Point', + HelpMessage = 'Location bias by point long')] + [ValidateNotNullOrEmpty()] + [string]$PointLongitude, + + [Parameter(Mandatory = $false, + HelpMessage = 'The region code, specified as a ccTLD')] + [ccTLD]$RegionBias, + + [Parameter(Mandatory = $false, + HelpMessage = 'The language in which to return results')] + [languages]$Language + ) + + Write-Debug -Message ($PSCmdlet.ParameterSetName) + + switch ($PSCmdlet.ParameterSetName) { + 'textquery' { + Write-Debug -Message 'Query specified' + + $uri = '{0}{1}' -f $bingMapsBaseURI, 'v1/TimeZone?output=json' + Write-Debug -Message ('Base function URI: {0}' -f $uri) + + $fQuery = '&query={0}' -f [uri]::EscapeDataString($Query) + $uri += $fQuery + } #point + 'Point' { + Write-Debug -Message 'Point specified' + + Write-Debug -Message 'Location specified' + $latLong = 'v1/TimeZone/{0},{1}?output=json' -f $PointLatitude, $PointLongitude + $uri = '{0}{1}' -f $bingMapsBaseURI, $latLong + Write-Debug -Message ('Base function URI: {0}' -f $uri) + } #point + } #switch_parametersetname + + if ($RegionBias) { + Write-Debug -Message ('RegionBias: {0}' -f $RegionBias) + $fRegion = '&userRegion={0}' -f $RegionBias + $uri += $fRegion + } + if ($Language) { + Write-Debug -Message ('Language: {0}' -f $Language) + $fLanguage = '&culture={0}' -f $Language + $uri += $fLanguage + } + + Write-Verbose -Message ('Querying Bing API: {0}' -f $uri) + + Write-Debug -Message 'Adding API key' + $fAPIKey = '&key={0}' -f $env:BingAPIKey + $uri += $fAPIKey + + $invokeRestMethodSplat = @{ + Uri = $uri + ErrorAction = 'Stop' + } + try { + $results = Invoke-RestMethod @invokeRestMethodSplat + } + catch { + throw $_ + } + + if ($results.statusDescription -ne 'OK') { + Write-Warning -Message 'Did not get a succcessful return from Bing Location API endpoint' + $finalResults = $results + } + elseif (-not ($results.resourceSets.estimatedTotal -ge 1)) { + Write-Warning -Message 'No results returned from query' + $finalResults = $results + } + else { + if ($PSCmdlet.ParameterSetName -eq 'Point') { + $finalResults = ($results.resourceSets.resources.timeZone | Format-BingTimeZone) + } + else { + $finalResults = ($results.resourceSets.resources.timeZoneAtLocation.timeZone | Format-BingTimeZone) + } + } + + return $finalResults + +} #Find-BingTimeZone diff --git a/src/pwshPlaces/pwshPlaces.psd1 b/src/pwshPlaces/pwshPlaces.psd1 index f8791e9..b2bacc0 100644 --- a/src/pwshPlaces/pwshPlaces.psd1 +++ b/src/pwshPlaces/pwshPlaces.psd1 @@ -12,7 +12,7 @@ RootModule = 'pwshPlaces.psm1' # Version number of this module. - ModuleVersion = '0.5.4' + ModuleVersion = '0.5.5' # Supported PSEditions # CompatiblePSEditions = @() @@ -71,6 +71,7 @@ # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. FunctionsToExport = @( 'Find-BingPlace' + 'Find-BingTimeZone' 'Find-GMapPlace' 'Get-GMapPlaceDetail' 'Invoke-BingGeoCode' @@ -137,6 +138,7 @@ 'Ratings', 'Search', 'SearchPlace' + 'TimeZone' ) # A URL to the license for this module. From 58c1e54098e841f22684c805d2fe2c6f69759fef Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Sun, 10 Oct 2021 22:16:47 -0500 Subject: [PATCH 17/22] cleanup and documentation --- .github/CHANGELOG.md | 8 +----- .github/CONTRIBUTING.md | 28 +++++++++++++++++++ docs/Find-BingPlace.md | 4 +-- docs/Find-BingTimeZone.md | 2 +- docs/Find-GMapPlace.md | 2 +- docs/Get-GMapPlaceDetail.md | 2 +- docs/Invoke-BingGeoCode.md | 2 +- docs/Invoke-GMapGeoCode.md | 2 +- docs/Search-BingNearbyPlace.md | 4 +-- docs/Search-GMapNearbyPlace.md | 2 +- docs/Search-GMapText.md | 2 +- docs/pwshPlaces.md | 2 +- .../Infrastructure/pwshPlaces-Infra.Tests.ps1 | 6 ++++ .../Unit/Private/Format-BingGeoCode.Tests.ps1 | 3 -- .../Unit/Private/Format-BingPlace.Tests.ps1 | 3 -- .../Private/Format-BingTimeZone.Tests.ps1 | 4 +-- .../Unit/Private/Format-GMapGeoCode.Tests.ps1 | 3 -- .../Private/Format-GMapNearbyPlace.Tests.ps1 | 3 -- .../Unit/Private/Format-GMapPlace.Tests.ps1 | 3 -- .../Private/Format-GMapPlaceDetail.Tests.ps1 | 3 -- .../Private/Format-GMapPlaceText.Tests.ps1 | 3 -- src/pwshPlaces/Public/Find-BingPlace.ps1 | 5 ++-- src/pwshPlaces/Public/Find-BingTimeZone.ps1 | 2 +- src/pwshPlaces/Public/Find-GMapPlace.ps1 | 2 +- src/pwshPlaces/Public/Get-GMapPlaceDetail.ps1 | 2 +- src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 | 2 +- src/pwshPlaces/Public/Invoke-GMapGeoCode.ps1 | 2 +- .../Public/Search-BingNearbyPlace.ps1 | 4 +-- .../Public/Search-GMapNearbyPlace.ps1 | 2 +- src/pwshPlaces/Public/Search-GMapText.ps1 | 2 +- src/pwshPlaces/pwshPlaces.psd1 | 5 ++-- 31 files changed, 61 insertions(+), 58 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 93bbb4f..0c87d9b 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -5,12 +5,6 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] - -- TBD - -## [0.0.1] - -### Added +## [0.6.0] - Initial release. diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 7b6e40c..32bac33 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -10,10 +10,38 @@ Please note there is a code of conduct, please follow it in all your interaction ## Reporting Bugs/Feature Requests +When filing an issue, please check [existing open](https://github.com/techthoughts2/pwshPlaces/issues), or [recently closed](https://github.com/techthoughts2/pwshPlaces/issues?q=is%3Aissue+is%3Aclosed), issues to make sure somebody else hasn't already +reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: + +* A reproducible test case or series of steps +* The version of the module being used +* Any modifications you've made relevant to the bug +* Anything unusual about your environment or deployment + ## Contributing via Pull Requests +Contributions via pull requests are much appreciated. Before sending a pull request, please ensure that: + +1. You are working against the latest source on the *dev* branch. +2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. +3. You open an issue to discuss any significant work - I'd hate for your time to be wasted. + +To send a pull request, please: + +1. Fork the repository. +2. Checkout the *dev* branch +3. Modify the source; please focus on the specific change you are contributing. Please refrain from code styling changes, it will be harder to focus on your change. +4. Ensure local tests pass. +5. Commit to your fork using clear commit messages. +6. Send a pull request, answering any default questions in the pull request interface. + +GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and +[creating a pull request](https://help.github.com/articles/creating-a-pull-request/). + ## Finding contributions to work on +Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (dev/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/techthoughts2/pwshPlaces/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) issues is a great place to start. + ## Code of Conduct This project has a [Code of Conduct](CODE_OF_CONDUCT.md). diff --git a/docs/Find-BingPlace.md b/docs/Find-BingPlace.md index 1e4fd99..b5c0c15 100644 --- a/docs/Find-BingPlace.md +++ b/docs/Find-BingPlace.md @@ -321,12 +321,12 @@ For more information, see about_CommonParameters (http://go.microsoft.com/fwlink ## OUTPUTS -### Output from this cmdlet (if any) +### Bing.Place ## NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ Example: - http://dev.virtualearth.net/REST/v1/Locations?countryRegion={countryRegion}&adminDistrict={adminDistrict}&locality={locality}&postalCode={postalCode}&addressLine={addressLine}&userLocation={userLocation}&userIp={userIp}&usermapView={usermapView}&includeNeighborhood={includeNeighborhood}&maxResults={maxResults}&key={BingMapsKey} + https://dev.virtualearth.net/REST/v1/LocalSearch/?query={query}&userLocation={point}&key={BingMapsAPIKey} ## RELATED LINKS diff --git a/docs/Find-BingTimeZone.md b/docs/Find-BingTimeZone.md index 2f76a41..2be929c 100644 --- a/docs/Find-BingTimeZone.md +++ b/docs/Find-BingTimeZone.md @@ -129,7 +129,7 @@ For more information, see about_CommonParameters (http://go.microsoft.com/fwlink ## OUTPUTS -### Output from this cmdlet (if any) +### Bing.TimeZone ## NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ diff --git a/docs/Find-GMapPlace.md b/docs/Find-GMapPlace.md index 8c042eb..083a745 100644 --- a/docs/Find-GMapPlace.md +++ b/docs/Find-GMapPlace.md @@ -342,7 +342,7 @@ For more information, see about_CommonParameters (http://go.microsoft.com/fwlink ## OUTPUTS -### Output from this cmdlet (if any) +### GMap.Place ## NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ diff --git a/docs/Get-GMapPlaceDetail.md b/docs/Get-GMapPlaceDetail.md index a5363d1..97f0494 100644 --- a/docs/Get-GMapPlaceDetail.md +++ b/docs/Get-GMapPlaceDetail.md @@ -145,7 +145,7 @@ For more information, see about_CommonParameters (http://go.microsoft.com/fwlink ## OUTPUTS -### Output from this cmdlet (if any) +### GMap.PlaceDetail ## NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ diff --git a/docs/Invoke-BingGeoCode.md b/docs/Invoke-BingGeoCode.md index 8223df1..303e624 100644 --- a/docs/Invoke-BingGeoCode.md +++ b/docs/Invoke-BingGeoCode.md @@ -251,7 +251,7 @@ For more information, see about_CommonParameters (http://go.microsoft.com/fwlink ## OUTPUTS -### Output from this cmdlet (if any) +### Bing.GeoCode ## NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ diff --git a/docs/Invoke-GMapGeoCode.md b/docs/Invoke-GMapGeoCode.md index dc26f6a..e2eda16 100644 --- a/docs/Invoke-GMapGeoCode.md +++ b/docs/Invoke-GMapGeoCode.md @@ -170,7 +170,7 @@ For more information, see about_CommonParameters (http://go.microsoft.com/fwlink ## OUTPUTS -### Output from this cmdlet (if any) +### GMap.GeoCode ## NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ diff --git a/docs/Search-BingNearbyPlace.md b/docs/Search-BingNearbyPlace.md index c065f20..b63ed0b 100644 --- a/docs/Search-BingNearbyPlace.md +++ b/docs/Search-BingNearbyPlace.md @@ -326,12 +326,12 @@ For more information, see about_CommonParameters (http://go.microsoft.com/fwlink ## OUTPUTS -### Output from this cmdlet (if any) +### Bing.Place ## NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ Example: - http://dev.virtualearth.net/REST/v1/Locations?countryRegion={countryRegion}&adminDistrict={adminDistrict}&locality={locality}&postalCode={postalCode}&addressLine={addressLine}&userLocation={userLocation}&userIp={userIp}&usermapView={usermapView}&includeNeighborhood={includeNeighborhood}&maxResults={maxResults}&key={BingMapsKey} + https://dev.virtualearth.net/REST/v1/LocalSearch/?type={type_string_id_list}&userLocation={point}&key={BingMapsAPIKey} ## RELATED LINKS diff --git a/docs/Search-GMapNearbyPlace.md b/docs/Search-GMapNearbyPlace.md index b6ae95d..d9ac55b 100644 --- a/docs/Search-GMapNearbyPlace.md +++ b/docs/Search-GMapNearbyPlace.md @@ -318,7 +318,7 @@ For more information, see about_CommonParameters (http://go.microsoft.com/fwlink ## OUTPUTS -### Output from this cmdlet (if any) +### GMap.NearbyPlace ## NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ diff --git a/docs/Search-GMapText.md b/docs/Search-GMapText.md index 2eb32a2..a84f952 100644 --- a/docs/Search-GMapText.md +++ b/docs/Search-GMapText.md @@ -422,7 +422,7 @@ For more information, see about_CommonParameters (http://go.microsoft.com/fwlink ## OUTPUTS -### Output from this cmdlet (if any) +### GMap.PlaceText ## NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ diff --git a/docs/pwshPlaces.md b/docs/pwshPlaces.md index 5e70671..acb9923 100644 --- a/docs/pwshPlaces.md +++ b/docs/pwshPlaces.md @@ -2,7 +2,7 @@ Module Name: pwshPlaces Module Guid: 9a9914bd-d115-4f42-bb5d-19c5e5561a3f Download Help Link: NA -Help Version: 0.5.5 +Help Version: 0.6.0 Locale: en-US --- diff --git a/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 b/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 index e9f6ed6..8a83e65 100644 --- a/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 +++ b/src/Tests/Infrastructure/pwshPlaces-Infra.Tests.ps1 @@ -115,7 +115,9 @@ Describe 'Infrastructure Tests' -Tag Infrastructure { } #it } #context_Search-GMapText } #context_GoogleMaps + Context 'Bing Maps Function Tests' { + Context 'Invoke-BingGeoCode' { It 'should return the expected results for lat long lookup' { $eval = Invoke-BingGeoCode -AddressLine '148 S Castell Ave' -City 'New Braunfels' -State TX -PostalCode 78130 @@ -128,6 +130,7 @@ Describe 'Infrastructure Tests' -Tag Infrastructure { Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) } #it } #context_Invoke-GMapGeoCode + Context 'Find-BingPlace' { It 'should return the expected results' { $findBingPlaceSplat = @{ @@ -142,6 +145,7 @@ Describe 'Infrastructure Tests' -Tag Infrastructure { Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) } #it } #context_Find-BingPlace + Context 'Search-BingNearbyPlace' { It 'should return the expected results' { $searchBingNearbyPlaceSplat = @{ @@ -156,6 +160,7 @@ Describe 'Infrastructure Tests' -Tag Infrastructure { Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) } #it } #context_Find-BingPlace + Context 'Find-BingTimeZone' { It 'should return the expected results' { $findBingTimeZoneSplat = @{ @@ -168,5 +173,6 @@ Describe 'Infrastructure Tests' -Tag Infrastructure { Start-Sleep -Milliseconds (Get-Random -Minimum 250 -Maximum 1000) } #it } #context_Find-BingPlace + } #context_BingMaps } #describe_infra_tests diff --git a/src/Tests/Unit/Private/Format-BingGeoCode.Tests.ps1 b/src/Tests/Unit/Private/Format-BingGeoCode.Tests.ps1 index b701b15..0cdfb3c 100644 --- a/src/Tests/Unit/Private/Format-BingGeoCode.Tests.ps1 +++ b/src/Tests/Unit/Private/Format-BingGeoCode.Tests.ps1 @@ -14,9 +14,6 @@ Import-Module $PathToManifest -Force #------------------------------------------------------------------------- InModuleScope 'pwshPlaces' { - #------------------------------------------------------------------------- - $WarningPreference = "SilentlyContinue" - #------------------------------------------------------------------------- Describe 'Format-BingGeoCode' -Tag Unit { BeforeAll { $WarningPreference = 'SilentlyContinue' diff --git a/src/Tests/Unit/Private/Format-BingPlace.Tests.ps1 b/src/Tests/Unit/Private/Format-BingPlace.Tests.ps1 index c9aebbc..e7550ec 100644 --- a/src/Tests/Unit/Private/Format-BingPlace.Tests.ps1 +++ b/src/Tests/Unit/Private/Format-BingPlace.Tests.ps1 @@ -14,9 +14,6 @@ Import-Module $PathToManifest -Force #------------------------------------------------------------------------- InModuleScope 'pwshPlaces' { - #------------------------------------------------------------------------- - $WarningPreference = "SilentlyContinue" - #------------------------------------------------------------------------- Describe 'Format-BingPlace' -Tag Unit { BeforeAll { $WarningPreference = 'SilentlyContinue' diff --git a/src/Tests/Unit/Private/Format-BingTimeZone.Tests.ps1 b/src/Tests/Unit/Private/Format-BingTimeZone.Tests.ps1 index e3fbdfa..be81ba1 100644 --- a/src/Tests/Unit/Private/Format-BingTimeZone.Tests.ps1 +++ b/src/Tests/Unit/Private/Format-BingTimeZone.Tests.ps1 @@ -14,9 +14,6 @@ Import-Module $PathToManifest -Force #------------------------------------------------------------------------- InModuleScope 'pwshPlaces' { - #------------------------------------------------------------------------- - $WarningPreference = "SilentlyContinue" - #------------------------------------------------------------------------- Describe 'Format-BingTimeZone' -Tag Unit { BeforeAll { $WarningPreference = 'SilentlyContinue' @@ -52,6 +49,7 @@ InModuleScope 'pwshPlaces' { $eval.TimeZoneCurrentShort | Should -BeExactly 'CDT' $eval.UTCOffSetDST | Should -BeExactly '-5:00' } #it + } #context_Success } #describe_Format-BingTimeZone } #inModule diff --git a/src/Tests/Unit/Private/Format-GMapGeoCode.Tests.ps1 b/src/Tests/Unit/Private/Format-GMapGeoCode.Tests.ps1 index b55d2f5..f7aa40a 100644 --- a/src/Tests/Unit/Private/Format-GMapGeoCode.Tests.ps1 +++ b/src/Tests/Unit/Private/Format-GMapGeoCode.Tests.ps1 @@ -14,9 +14,6 @@ Import-Module $PathToManifest -Force #------------------------------------------------------------------------- InModuleScope 'pwshPlaces' { - #------------------------------------------------------------------------- - $WarningPreference = "SilentlyContinue" - #------------------------------------------------------------------------- Describe 'Format-GMapGeoCode' -Tag Unit { BeforeAll { $WarningPreference = 'SilentlyContinue' diff --git a/src/Tests/Unit/Private/Format-GMapNearbyPlace.Tests.ps1 b/src/Tests/Unit/Private/Format-GMapNearbyPlace.Tests.ps1 index ca06db6..3b236f4 100644 --- a/src/Tests/Unit/Private/Format-GMapNearbyPlace.Tests.ps1 +++ b/src/Tests/Unit/Private/Format-GMapNearbyPlace.Tests.ps1 @@ -14,9 +14,6 @@ Import-Module $PathToManifest -Force #------------------------------------------------------------------------- InModuleScope 'pwshPlaces' { - #------------------------------------------------------------------------- - $WarningPreference = "SilentlyContinue" - #------------------------------------------------------------------------- Describe 'Format-GMapNearbyPlace' -Tag Unit { BeforeAll { $WarningPreference = 'SilentlyContinue' diff --git a/src/Tests/Unit/Private/Format-GMapPlace.Tests.ps1 b/src/Tests/Unit/Private/Format-GMapPlace.Tests.ps1 index a9c48e3..6ce84c7 100644 --- a/src/Tests/Unit/Private/Format-GMapPlace.Tests.ps1 +++ b/src/Tests/Unit/Private/Format-GMapPlace.Tests.ps1 @@ -14,9 +14,6 @@ Import-Module $PathToManifest -Force #------------------------------------------------------------------------- InModuleScope 'pwshPlaces' { - #------------------------------------------------------------------------- - $WarningPreference = "SilentlyContinue" - #------------------------------------------------------------------------- Describe 'Format-GMapPlace' -Tag Unit { BeforeAll { $WarningPreference = 'SilentlyContinue' diff --git a/src/Tests/Unit/Private/Format-GMapPlaceDetail.Tests.ps1 b/src/Tests/Unit/Private/Format-GMapPlaceDetail.Tests.ps1 index 4e4746f..e0fee8c 100644 --- a/src/Tests/Unit/Private/Format-GMapPlaceDetail.Tests.ps1 +++ b/src/Tests/Unit/Private/Format-GMapPlaceDetail.Tests.ps1 @@ -14,9 +14,6 @@ Import-Module $PathToManifest -Force #------------------------------------------------------------------------- InModuleScope 'pwshPlaces' { - #------------------------------------------------------------------------- - $WarningPreference = "SilentlyContinue" - #------------------------------------------------------------------------- Describe 'Format-GMapPlaceDetail' -Tag Unit { BeforeAll { $WarningPreference = 'SilentlyContinue' diff --git a/src/Tests/Unit/Private/Format-GMapPlaceText.Tests.ps1 b/src/Tests/Unit/Private/Format-GMapPlaceText.Tests.ps1 index 8dc08f0..27e0bff 100644 --- a/src/Tests/Unit/Private/Format-GMapPlaceText.Tests.ps1 +++ b/src/Tests/Unit/Private/Format-GMapPlaceText.Tests.ps1 @@ -14,9 +14,6 @@ Import-Module $PathToManifest -Force #------------------------------------------------------------------------- InModuleScope 'pwshPlaces' { - #------------------------------------------------------------------------- - $WarningPreference = "SilentlyContinue" - #------------------------------------------------------------------------- Describe 'Format-GMapPlaceText' -Tag Unit { BeforeAll { $WarningPreference = 'SilentlyContinue' diff --git a/src/pwshPlaces/Public/Find-BingPlace.ps1 b/src/pwshPlaces/Public/Find-BingPlace.ps1 index bce621c..f653a04 100644 --- a/src/pwshPlaces/Public/Find-BingPlace.ps1 +++ b/src/pwshPlaces/Public/Find-BingPlace.ps1 @@ -66,12 +66,12 @@ .PARAMETER Language The language in which to return results. .OUTPUTS - Output from this cmdlet (if any) + Bing.Place .NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ Example: - http://dev.virtualearth.net/REST/v1/Locations?countryRegion={countryRegion}&adminDistrict={adminDistrict}&locality={locality}&postalCode={postalCode}&addressLine={addressLine}&userLocation={userLocation}&userIp={userIp}&usermapView={usermapView}&includeNeighborhood={includeNeighborhood}&maxResults={maxResults}&key={BingMapsKey} + https://dev.virtualearth.net/REST/v1/LocalSearch/?query={query}&userLocation={point}&key={BingMapsAPIKey} .COMPONENT pwshPlaces .LINK @@ -247,4 +247,3 @@ function Find-BingPlace { return $finalResults } #Find-BingPlace - diff --git a/src/pwshPlaces/Public/Find-BingTimeZone.ps1 b/src/pwshPlaces/Public/Find-BingTimeZone.ps1 index 5073935..54eba19 100644 --- a/src/pwshPlaces/Public/Find-BingTimeZone.ps1 +++ b/src/pwshPlaces/Public/Find-BingTimeZone.ps1 @@ -22,7 +22,7 @@ .PARAMETER Language The language in which to return results. .OUTPUTS - Output from this cmdlet (if any) + Bing.TimeZone .NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ diff --git a/src/pwshPlaces/Public/Find-GMapPlace.ps1 b/src/pwshPlaces/Public/Find-GMapPlace.ps1 index f293acb..2f1e9d2 100644 --- a/src/pwshPlaces/Public/Find-GMapPlace.ps1 +++ b/src/pwshPlaces/Public/Find-GMapPlace.ps1 @@ -80,7 +80,7 @@ .PARAMETER Language The language in which to return results. .OUTPUTS - Output from this cmdlet (if any) + GMap.Place .NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ diff --git a/src/pwshPlaces/Public/Get-GMapPlaceDetail.ps1 b/src/pwshPlaces/Public/Get-GMapPlaceDetail.ps1 index 99863a0..a002c44 100644 --- a/src/pwshPlaces/Public/Get-GMapPlaceDetail.ps1 +++ b/src/pwshPlaces/Public/Get-GMapPlaceDetail.ps1 @@ -36,7 +36,7 @@ .PARAMETER RegionBias The region code, specified as a ccTLD ("top-level domain") two-character value. .OUTPUTS - Output from this cmdlet (if any) + GMap.PlaceDetail .NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ diff --git a/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 b/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 index 5913de9..6c4e41f 100644 --- a/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 +++ b/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 @@ -55,7 +55,7 @@ .PARAMETER MaxResults Specifies the maximum number of locations to return in the response. If not specified the default is 5. .OUTPUTS - Output from this cmdlet (if any) + Bing.GeoCode .NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ diff --git a/src/pwshPlaces/Public/Invoke-GMapGeoCode.ps1 b/src/pwshPlaces/Public/Invoke-GMapGeoCode.ps1 index e5092a1..1c238ae 100644 --- a/src/pwshPlaces/Public/Invoke-GMapGeoCode.ps1 +++ b/src/pwshPlaces/Public/Invoke-GMapGeoCode.ps1 @@ -35,7 +35,7 @@ .PARAMETER RegionBias The region code, specified as a ccTLD ("top-level domain") two-character value. This parameter will only influence, not fully restrict, results from the geocoder. .OUTPUTS - Output from this cmdlet (if any) + GMap.GeoCode .NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ diff --git a/src/pwshPlaces/Public/Search-BingNearbyPlace.ps1 b/src/pwshPlaces/Public/Search-BingNearbyPlace.ps1 index 44c62c7..1e720fd 100644 --- a/src/pwshPlaces/Public/Search-BingNearbyPlace.ps1 +++ b/src/pwshPlaces/Public/Search-BingNearbyPlace.ps1 @@ -66,12 +66,12 @@ .PARAMETER Language The language in which to return results. .OUTPUTS - Output from this cmdlet (if any) + Bing.Place .NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ Example: - http://dev.virtualearth.net/REST/v1/Locations?countryRegion={countryRegion}&adminDistrict={adminDistrict}&locality={locality}&postalCode={postalCode}&addressLine={addressLine}&userLocation={userLocation}&userIp={userIp}&usermapView={usermapView}&includeNeighborhood={includeNeighborhood}&maxResults={maxResults}&key={BingMapsKey} + https://dev.virtualearth.net/REST/v1/LocalSearch/?type={type_string_id_list}&userLocation={point}&key={BingMapsAPIKey} .COMPONENT pwshPlaces .LINK diff --git a/src/pwshPlaces/Public/Search-GMapNearbyPlace.ps1 b/src/pwshPlaces/Public/Search-GMapNearbyPlace.ps1 index abce373..194fe70 100644 --- a/src/pwshPlaces/Public/Search-GMapNearbyPlace.ps1 +++ b/src/pwshPlaces/Public/Search-GMapNearbyPlace.ps1 @@ -76,7 +76,7 @@ .PARAMETER AllSearchResults By default 20 results are returned from a standard search. Using this switch increases the search results from 20 to the maximum of 60. This does increase the number of API calls. .OUTPUTS - Output from this cmdlet (if any) + GMap.NearbyPlace .NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ diff --git a/src/pwshPlaces/Public/Search-GMapText.ps1 b/src/pwshPlaces/Public/Search-GMapText.ps1 index 8017874..fa206ac 100644 --- a/src/pwshPlaces/Public/Search-GMapText.ps1 +++ b/src/pwshPlaces/Public/Search-GMapText.ps1 @@ -95,7 +95,7 @@ .PARAMETER AllSearchResults By default 20 results are returned from a standard search. Using this switch increases the search results from 20 to the maximum of 60. This does increase the number of API calls. .OUTPUTS - Output from this cmdlet (if any) + GMap.PlaceText .NOTES Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ diff --git a/src/pwshPlaces/pwshPlaces.psd1 b/src/pwshPlaces/pwshPlaces.psd1 index b2bacc0..d4b0bf2 100644 --- a/src/pwshPlaces/pwshPlaces.psd1 +++ b/src/pwshPlaces/pwshPlaces.psd1 @@ -12,7 +12,7 @@ RootModule = 'pwshPlaces.psm1' # Version number of this module. - ModuleVersion = '0.5.5' + ModuleVersion = '0.6.0' # Supported PSEditions # CompatiblePSEditions = @() @@ -127,6 +127,7 @@ 'GMaps', 'Latitude', 'Longitude', + 'Locale', 'Location', 'Place', 'Places', @@ -173,5 +174,3 @@ # DefaultCommandPrefix = '' } - - From f6901537ca1bee0e571fef84e4a28585e5521150 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Mon, 11 Oct 2021 00:05:43 -0500 Subject: [PATCH 18/22] updated documentation --- README.md | 100 ++++++++++--- bing.ps1 | 50 ------- docs/BingMapsAPI.md | 136 ++++-------------- docs/GoogleMapsAPI.md | 2 +- docs/pwshPlaces-FAQ.md | 42 +++++- docs/pwshPlaces.md | 2 +- ...pi_key.PNG => bing_map_create_api_key.PNG} | Bin src/pwshPlaces/pwshPlaces.psd1 | 2 +- 8 files changed, 146 insertions(+), 188 deletions(-) delete mode 100644 bing.ps1 rename media/{bin_map_create_api_key.PNG => bing_map_create_api_key.PNG} (100%) diff --git a/README.md b/README.md index 15c0762..f5b0660 100644 --- a/README.md +++ b/README.md @@ -14,37 +14,55 @@ dev | [![Build Status Windows PowerShell dev](https://github.com/techthoughts2/p ## Synopsis -pwshPlaces is a PowerShell module - -tbd - - +pwshPlaces is a PowerShell module that can help you discover places and search for points of interest around the globe. ## Description -pwshPlaces enables you to +pwshPlaces enables you to leverage the Google Maps and/or Bing Maps API(s) to perform a variety of maps related tasks using PowerShell: -* TBD -* TBD -* TBD -* TBD +* Search for places, entities, addresses, and other points of interest +* Discover locations near your or near a specified place +* Easily perform Geocoding and reverse Geocoding actions +* Get detailed place information including opening hours, website information, and contact information [pwshPlaces](docs/pwshPlaces.md) provides the following functions: +* [Find-BingPlace](docs/Find-BingPlace.md) +* [Find-BingTimeZone](docs/Find-BingTimeZone.md) * [Find-GMapPlace](docs/Find-GMapPlace.md) +* [Get-GMapPlaceDetail](docs/Get-GMapPlaceDetail) +* [Invoke-BingGeoCode](docs/Invoke-BingGeoCode) * [Invoke-GMapGeoCode](docs/Invoke-GMapGeoCode.md) +* [Search-BingNearbyPlace](docs/Search-BingNearbyPlace) * [Search-GMapNearbyPlace](docs/Search-GMapNearbyPlace.md) * [Search-GMapText](docs/Search-GMapText.md) ## Why -TBD +The Google Maps and Bing Maps API require very specific formatting and criteria for API map interaction. The goal of this project is to abstract that complexity away in favor of simple and direct PowerShell commands. ## Installation ### Prerequisites -Set those API Keys in the PoshGMaps.psm1 file to the appropriate variables. +To use pwshPlaces you will require a Google Maps or Bing Maps API key. To use all of the functions you will require both. The API key(s) will need to be loaded into environment variables in your current session. + +> 🙄 Not another module that requires an API Key! + +Both of these APIs are *easy to create* and have *no cost* pricing tiers which should meet your needs. I have provided detailed guides on how to get your API keys: + +* [How to get a Google Maps API Key](docs/GoogleMapsAPI.md#how-to-get-a-google-maps-api-key) +* [How to get a Bing Maps API Key](docs/BingMapsAPI.md#how-to-get-a-bing-maps-api-key) + +```powershell +# Set your API Keys in the pwshPlaces.psm1 file +# using the approriate variable names: + +$env:GoogleAPIKey = 'yourGoogleAPIKey' +$env:BingAPIKey = 'yourBingAPIKey' +``` + +If you don't want to adjust the ```.psm1``` then simply ensure that these environment variables are populated in your current session. ### Install pwshPlaces @@ -56,19 +74,55 @@ Install-Module -Name pwshPlaces -Repository PSGallery -Scope CurrentUser ## Quick start ```powershell -# TBD -TBD - +###################################################################################### +# Google Maps +$env:GoogleAPIKey = 'yourGoogleAPIKey' +###################################################################################### +# I want to find a specific place +Find-GMapPlace -Query "Krause's cafe" +Find-GMapPlace -Query '+18306252807' +Find-GMapPlace -Query 'cafe' -PointLatitude '29.7049806' -PointLongitude '-98.068343' +#------------------------------------------------------------------------------------- +# I want to search for a type of place +Search-GMapText -Query "Cupcakes" -Type bakery -AllSearchResults +Search-GMapText -Query "italian restaurants in New York" -MinPrice 4 +#------------------------------------------------------------------------------------- +# I want to search for nearby places +Search-GMapNearbyPlace -Latitude '29.7049806' -Longitude '-98.068343' -Radius 5000 +Search-GMapNearbyPlace -Latitude '29.7049806' -Longitude '-98.068343' -Radius 10000 -RankByProminence -Keyword 'butcher' -Type store +#------------------------------------------------------------------------------------- +# I want to get very detailed information about a place - place ID retrieved from other commands +Get-GMapPlaceDetail -PlaceID 'ChIJf9Yxhme9XIYRkXo-Bl62Q10' -Contact -Atmosphere +#------------------------------------------------------------------------------------- +# I want to GeoCode an address +Invoke-GMapGeoCode -Address '148 S Castell Ave, New Braunfels, TX 78130, United States' +#------------------------------------------------------------------------------------- +# I want to reverse GeoCode a location +Invoke-GMapGeoCode -Latitude '29.7012853' -Longitude '-98.1250235' +###################################################################################### +# Bing Maps +$env:BingAPIKey = 'yourBingAPIKey' +###################################################################################### +# I want to find a specific place +Find-BingPlace -Query "Krause's cafe" +Find-BingPlace -Query 'cafe' -PointLatitude '29.7049806' -PointLongitude '-98.068343' +#------------------------------------------------------------------------------------- +# I want to search for nearby places +Search-BingNearbyPlace -Type Attractions +Search-BingNearbyPlace -Type CafeRestaurants -PointLatitude '29.7049806' -PointLongitude '-98.068343' +#------------------------------------------------------------------------------------- +# I want to GeoCode an address +Invoke-BingGeoCode -AddressLine '148 S Castell Ave' -City 'New Braunfels' -State TX -PostalCode 78130 +#------------------------------------------------------------------------------------- +# I want to reverse GeoCode a location +Invoke-BingGeoCode -Latitude '29.7030' -Longitude '-98.1245' +#------------------------------------------------------------------------------------- +# I want to determine the Time Zone of a specific place +Find-BingTimeZone -Query 'New Braunfels, TX' +Find-BingTimeZone -PointLatitude 29.70 -PointLongitude -98.11 +#------------------------------------------------------------------------------------- ``` -### Potential uses - -I am going to this address and want to know local businesses around it - -search for place and get lat/long - -search for businesses close by - ## FAQ **[pwshPlaces - FAQ](docs/pwshPlaces-FAQ.md)** diff --git a/bing.ps1 b/bing.ps1 deleted file mode 100644 index 97b16aa..0000000 --- a/bing.ps1 +++ /dev/null @@ -1,50 +0,0 @@ -# Bing Maps REST Services -<# -https://docs.microsoft.com/en-us/bingmaps/rest-services/ - -https://docs.microsoft.com/en-us/bingmaps/rest-services/getting-started-with-the-bing-maps-rest-services - -Bing Maps Locations API -https://docs.microsoft.com/en-us/bingmaps/rest-services/locations/ - -Bing Maps API Best Practices -https://docs.microsoft.com/en-us/bingmaps/getting-started/bing-maps-api-best-practices - -When a request is rate limited, the response will return no results. This may be confusing at -first as it looks like Bing Maps was unable to find results. To indicate that the request was rate -limited a flag is added to the header of the response (X-MS-BM-WS-INFO) which is set to the -value of 1 as documented the Status Codes and Error Handling page. -https://msdn.microsoft.com/en-us/library/ff701703.aspx - -Supported Culture Codes -https://docs.microsoft.com/en-us/bingmaps/rest-services/common-parameters-and-types/supported-culture-codes - -The Bing Maps geocoder will attempt to find the closest match as possible to your query. In some cases, -it will not be able to find an exact match. This is where the match code parameter of the returned results -becomes useful. The match code parameter is an array of values and can have any combination of the following -three values; Good, Ambiguous, or UpHierarchy. If you are only interested in exact matches then keep a look -out for UpHierachy as this indicates that your exact query was not found but an upper level address value was found. - -REST services take your IP address into consideration when making a request -o help reduce this issue you can set the userIp parameter of the request to 127.0.0.1. -This will trick the service into thinking you are making the call from a local application -and cause it to ignore your IP address. - -Base URL Structure -https://docs.microsoft.com/en-us/bingmaps/rest-services/common-parameters-and-types/base-url-structure -https://dev.virtualearth.net/REST/version/restApi/resourcePath?queryParameters&key=BingMapsKey -http://dev.virtualearth.net/REST/v1/Locations?q=seattle&output=xml&key=BingMapsKey - -Limit your coordinates to 6 decimal places. -don’t encode coordinate based locations. - -Output Parameters - https://docs.microsoft.com/en-us/bingmaps/rest-services/common-parameters-and-types/output-parameters -Culture Parameter - https://docs.microsoft.com/en-us/bingmaps/rest-services/common-parameters-and-types/culture-parameter - &c= -User Context Parameters - https://docs.microsoft.com/en-us/bingmaps/rest-services/common-parameters-and-types/user-context-parameters -Types - https://docs.microsoft.com/bingmaps/rest-services/common-parameters-and-types/type-identifiers/ -#> \ No newline at end of file diff --git a/docs/BingMapsAPI.md b/docs/BingMapsAPI.md index 4228aa8..a0610de 100644 --- a/docs/BingMapsAPI.md +++ b/docs/BingMapsAPI.md @@ -1,155 +1,77 @@ # Bing Maps API -***[pwshPlaces](https://github.com/techthoughts2/pwshPlaces)** includes Google Maps features and content; use of Google Maps features and content is subject to the [terms of service](https://www.microsoft.com/maps/product/terms.html) and [Microsoft privacy policy](https://privacy.microsoft.com/en-us/privacystatement).* - -https://blogs.bing.com/maps - -https://docs.microsoft.com/en-us/bingmaps/ +***[pwshPlaces](https://github.com/techthoughts2/pwshPlaces)** includes Bing Maps features and content; use of Bing Maps features and content is subject to the [terms of service](https://www.microsoft.com/maps/product/terms.html) and [Microsoft privacy policy](https://privacy.microsoft.com/en-us/privacystatement).* - [Bing Maps API](#bing-maps-api) - [Bing Maps API Key](#bing-maps-api-key) - [How to get a Bing Maps API Key](#how-to-get-a-bing-maps-api-key) - - [1. Create a new GCP project](#1-create-a-new-gcp-project) - - [2. Enable the Places API and the Geocoding API](#2-enable-the-places-api-and-the-geocoding-api) - - [3. Create API Key](#3-create-api-key) - - [4. Restrict to places API](#4-restrict-to-places-api) - - [5. Enable Billing on the Google Cloud project](#5-enable-billing-on-the-google-cloud-project) - - [Monitoring Google Maps API usage](#monitoring-google-maps-api-usage) + - [1. Create a new Bing maps dev account](#1-create-a-new-bing-maps-dev-account) + - [2. Create a Bing Maps Basic API Key](#2-create-a-bing-maps-basic-api-key) + - [Monitoring Bing Maps API usage](#monitoring-bing-maps-api-usage) - [Understanding Bing Maps API pricing](#understanding-bing-maps-api-pricing) - [API Caching](#api-caching) -Bing Maps API FAQ - https://www.microsoft.com/en-us/maps/faq - -https://www.bingmapsportal.com/Application - ## Bing Maps API Key -https://www.microsoft.com/en-us/maps/create-a-bing-maps-key -Getting a Bing Maps Key - https://docs.microsoft.com/en-us/bingmaps/getting-started/bing-maps-dev-center-help/getting-a-bing-maps-key - -**[pwshPlaces](https://github.com/techthoughts2/pwshPlaces)** requires a Google API key to run Google maps functions. +**[pwshPlaces](https://github.com/techthoughts2/pwshPlaces)** requires a Bing Maps API key to run Bing Maps functions. To utilize all of the functions of pwshPlaces you must: -- Create a Google Maps API with both the Places and Geocoding APIs enabled and enable billing on the project. - -You can read more about the Google Maps API in the links below: +- Create a Bing Maps API key -https://docs.microsoft.com/en-us/bingmaps/getting-started/ +You can read more about the Bing Maps API in the links below: -- [Google Maps Platform Documentation](https://developers.google.com/maps/documentation#places) -- [Places API](https://developers.google.com/maps/documentation/places/web-service/overview) -- [Places API Support](https://developers.google.com/maps/documentation/places/web-service/support) +- [Getting Started with Bing Maps](https://docs.microsoft.com/bingmaps/getting-started/) ### How to get a Bing Maps API Key -button create api - -Prompted to create a Bing Maps Dev Center account, - -Yes, let's create a new account - - - - - -Official documentation link for creating a Google Maps API Key: - -- [Google Maps Creating API Keys](https://developers.google.com/maps/documentation/places/web-service/get-api-key#creating-api-keys) +Official documentation link for creating a Bing Maps API Key: -Google Maps API Keys are created and managed through Google Cloud Platform (GCP). The GCP console is constantly changing so some of the steps below may look slightly different. Here is what you need to accomplish at a high level: +- [Create a Bing Maps Key](https://www.microsoft.com/en-us/maps/create-a-bing-maps-key) -#### 1. Create a new GCP project +> First, you will need a Bing Maps account and an API key. When you register for an account, you'll create a Bing Maps key -Log into your [GCP console](https://console.cloud.google.com/home/) and create a new project: -![alt text](../media/gcp_new_project.PNG 'Title') +Here is what you need to accomplish at a high level: -#### 2. Enable the Places API and the Geocoding API +#### 1. Create a new Bing maps dev account -- Top left Navigation Menu - - Other Google Solutions - - Google Maps Platform - - Maps APIs and Services - - Places API - --Enable-- -- Google Maps Platform - - APIs - - Additional APIs - - Geocoding API - --Enable-- +Log into the [Bing Maps Dev Center Portal](https://www.bingmapsportal.com) - if you do not yet have an account go ahead and create one: +![Bing Maps Dev Center New Account](../media/bing_map_create_bing_maps_dev_account.PNG 'New Bing Maps Account') -![Google Cloud (GCP) Top Left Navigation Menu](../media/google_cloud_top_left_navigation_menu.PNG 'GCP Navigation Menu') -![Google Cloud (GCP) Google Maps Platform](../media/gcp_google_maps_platform.PNG 'GCP Google Maps Platform') -![Google Cloud (GCP) Google Maps Platform Maps APIs and Services](../media/google_maps_platform_maps_api_and_services.PNG 'Google Maps Platform Maps APIs and Services') -![Google Maps Places API](../media/gcp_enable_places_api.PNG 'Google Maps Places API') -![Google Maps Geocoding API](../media/gcp_enable_geocoding_api.PNG 'Google Maps Geocoding API') +#### 2. Create a Bing Maps Basic API Key -#### 3. Create API Key +- Under My account tab click *My Keys* + - Create a new api key -- Google Maps Platform - - Credentials - - Create Credentials - - API key +![Bing Maps API Key Choices](../media/create_bing_maps_api_key.PNG 'Bing Map API Key Choice') +![Bing Maps Dev Center New API Key](../media/bing_map_create_api_key.PNG 'New Bing Maps API Key') -![GCP Google Maps Platform Credentials](../media/gcp_google_maps_create_credential_api.PNG 'Google Maps Platform Credentials') +### Monitoring Bing Maps API usage -#### 4. Restrict to places API - -Restrict API access to just the two enabled - -- Google Maps Platform - - Credentials - - Restrict API to secure account - -![GCP API Restrict Access](../media/gcp_api_services_restrict_api_key.PNG 'API Restrict Access') - -#### 5. Enable Billing on the Google Cloud project - -You must [enable billing](https://console.cloud.google.com/project/_/billing/enable) on the Google Cloud Project. - --Note: Even though you need to enable billing keep in mind the following:- - -> For most of our users, the $200 monthly credit is enough to support their needs. You can also set daily quotas to protect against unexpected increases. - -### Monitoring Google Maps API usage - -Visit the [GCP API dashboard](https://console.developers.google.com/apis/dashboard). From the ‘Select a Project’ drop-down menu, select or create the project. - -Additional reading: - -- [Monitoring API usage](https://cloud.google.com/apis/docs/monitoring) -- [Monitor Google API usage programmatically?](https://stackoverflow.com/questions/62511759/monitor-google-api-usage-programmatically) +Visit the [Bing Maps Dev Center Portal Summary Report](https://www.bingmapsportal.com/Report). ### Understanding Bing Maps API pricing -https://www.microsoft.com/maps/licensing/licensing.aspx -https://www.microsoft.com/en-us/maps/licensing/licensing-options - -- [Google Maps Platform pricing](https://cloud.google.com/maps-platform/pricing) -- [Places product API pricing](https://developers.google.com/maps/billing/gmp-billing#places-product) -- [Places API Usage and Billing](https://developers.google.com/maps/documentation/places/web-service/usage-and-billing) - - [Places SKU breakdown cost data](https://developers.google.com/maps/billing/gmp-billing#basic-data) +- [Bing Maps Licensing](https://www.microsoft.com/maps/licensing/licensing.aspx) +- [Bing Maps Licensing Options](https://www.microsoft.com/en-us/maps/licensing/licensing-options) ## API Caching -IAW with the [terms of service](https://cloud.google.com/maps-platform/terms/): - -> Pre-Fetching, Caching, or Storage of Content -Applications using the Places API are bound by the Google Maps Platform Terms of Service. Section 3.2.3(a) and (b) of the terms states that you must not pre-fetch, index, store, or cache any Content except under the limited conditions stated in the terms. -Note that the place ID, used to uniquely identify a place, is exempt from the caching restriction. You can therefore store place ID values indefinitely. The place ID is returned in the place_id field in Places API responses. +There doesn't seem to be anything in the [terms of service](https://www.microsoft.com/maps/product/terms.html) the explicitly forbids local caching of Bing Maps data. -This means that doing something like the following is not permitted: +This means that doing something like this should be fine: ```powershell #-------------------------------------------------------------- -# scrape and locally cache up to 60 local restaurants +# scrape and locally cache local restaurants Import-Module Convert Import-Module pwshPlaces $scrapePath = $env:Temp -$locale = Invoke-GMapGeoCode -Address 'New Braunfels' +$locale = Invoke-BingGeoCode -Query 'New Braunfels, TX' -$areaRestaraunts = Search-GMapNearbyPlace -Latitude $locale.Latitude -Longitude $locale.Longitude -Radius 10000 -RankByProminence -Type restaurant -AllSearchResults +$areaRestaraunts = Search-BingNearbyPlace -Type Restaurants -PointLatitude $locale.Latitude -PointLongitude $locale.Longitude -MaxResults 20 ConvertTo-Clixml -InputObject $areaRestaraunts -Depth 100 | Out-File "$scrapePath\localRestaraunts.xml" #-------------------------------------------------------------- diff --git a/docs/GoogleMapsAPI.md b/docs/GoogleMapsAPI.md index fed35b7..e9fdbd1 100644 --- a/docs/GoogleMapsAPI.md +++ b/docs/GoogleMapsAPI.md @@ -39,7 +39,7 @@ Google Maps API Keys are created and managed through Google Cloud Platform (GCP) #### 1. Create a new GCP project Log into your [GCP console](https://console.cloud.google.com/home/) and create a new project: -![alt text](../media/gcp_new_project.PNG 'Title') +![Google Cloud (GCP) new project](../media/gcp_new_project.PNG 'New GCP Project') #### 2. Enable the Places API and the Geocoding API diff --git a/docs/pwshPlaces-FAQ.md b/docs/pwshPlaces-FAQ.md index ea10721..1819c97 100644 --- a/docs/pwshPlaces-FAQ.md +++ b/docs/pwshPlaces-FAQ.md @@ -3,15 +3,47 @@ - [pwshPlaces - FAQ](#pwshplaces---faq) - [FAQs](#faqs) - [Do I need an API key us to use pwshPlaces](#do-i-need-an-api-key-us-to-use-pwshplaces) + - [Do I need a Google Maps API key and a Bing Maps API key](#do-i-need-a-google-maps-api-key-and-a-bing-maps-api-key) + - [How do I get a Maps API key](#how-do-i-get-a-maps-api-key) + - [Does the Google Maps API key cost money](#does-the-google-maps-api-key-cost-money) + - [Does the Bing Maps API key cost money](#does-the-bing-maps-api-key-cost-money) + - [How do load my API keys into pwshPlaces](#how-do-load-my-api-keys-into-pwshplaces) ## FAQs -Bing API +### Do I need an API key us to use pwshPlaces -Applications using up to 125,000 billable transactions per calendar year qualify for limited website and mobile app terms within the Bing Maps API Terms of Use. +Yes. pwshPlaces requires API keys in order to make calls to the various Map services. -Less than 50,000 cumulative billable transactions with any 24-hour period +### Do I need a Google Maps API key and a Bing Maps API key -### Do I need an API key us to use pwshPlaces +No. If you prefer one Map provider over another you can just get that API key. For example, if you prefer Google Maps you can just get a Google Maps API key and load that into the ```$env:GoogleAPIKey``` variable. This enables only the ```GMap``` functions in pwshPlaces. You will be unable to use the ```Bing``` functions. To unlock all functions inside pwshPlaces you will require both API keys. + +### How do I get a Maps API key + +- [How to get a Google Maps API Key](GoogleMapsAPI.md#how-to-get-a-google-maps-api-key) +- [How to get a Bing Maps API Key](BingMapsAPI.md#how-to-get-a-bing-maps-api-key) + +### Does the Google Maps API key cost money + +The Google Maps API has $200 free monthly usage for all users. This should be more than sufficient for most people. + +You can dive into more details by [Understanding Google Maps API pricing](/GoogleMapsAPI.md#understanding-google-maps-api-pricing) + +### Does the Bing Maps API key cost money + +The Basic API key gives you up to 125,000 billable transactions per calendar year and less than 50,000 cumulative billable transactions with any 24-hour period. This should be more than sufficient for most people. + +You can dive into more details by [Understanding Bing Maps API pricing](/BingMapsAPI.md#understanding-bing-maps-api-pricing) + +### How do load my API keys into pwshPlaces + +```powershell +# Set your API Keys in the pwshPlaces.psm1 file +# using the approriate variable names: + +$env:GoogleAPIKey = 'yourGoogleAPIKey' +$env:BingAPIKey = 'yourBingAPIKey' +``` -Yes +If you don't want to adjust the ```.psm1``` then simply ensure that these environment variables are populated in your current session. diff --git a/docs/pwshPlaces.md b/docs/pwshPlaces.md index acb9923..840a15b 100644 --- a/docs/pwshPlaces.md +++ b/docs/pwshPlaces.md @@ -8,7 +8,7 @@ Locale: en-US # pwshPlaces Module ## Description -tbd +Search for places, establishments, points of interest, and other detailed information about points around the globe using the Google Maps and/or Bing Maps API(s) ## pwshPlaces Cmdlets ### [Find-BingPlace](Find-BingPlace.md) diff --git a/media/bin_map_create_api_key.PNG b/media/bing_map_create_api_key.PNG similarity index 100% rename from media/bin_map_create_api_key.PNG rename to media/bing_map_create_api_key.PNG diff --git a/src/pwshPlaces/pwshPlaces.psd1 b/src/pwshPlaces/pwshPlaces.psd1 index d4b0bf2..a16c50a 100644 --- a/src/pwshPlaces/pwshPlaces.psd1 +++ b/src/pwshPlaces/pwshPlaces.psd1 @@ -30,7 +30,7 @@ Copyright = '(c) Jake Morrison. All rights reserved.' # Description of the functionality provided by this module - Description = 'tbd' + Description = 'Search for places, establishments, points of interest, and other detailed information about points around the globe using the Google Maps and/or Bing Maps API(s)' # Minimum version of the PowerShell engine required by this module # PowerShellVersion = '' From 38ca6c50cdfbf3e212616d3858a732da6d59695b Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Mon, 11 Oct 2021 00:11:45 -0500 Subject: [PATCH 19/22] updated docs --- README.md | 6 +++--- docs/pwshPlaces-FAQ.md | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index f5b0660..c5081c5 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,10 @@ pwshPlaces enables you to leverage the Google Maps and/or Bing Maps API(s) to pe * [Find-BingPlace](docs/Find-BingPlace.md) * [Find-BingTimeZone](docs/Find-BingTimeZone.md) * [Find-GMapPlace](docs/Find-GMapPlace.md) -* [Get-GMapPlaceDetail](docs/Get-GMapPlaceDetail) -* [Invoke-BingGeoCode](docs/Invoke-BingGeoCode) +* [Get-GMapPlaceDetail](docs/Get-GMapPlaceDetail.md) +* [Invoke-BingGeoCode](docs/Invoke-BingGeoCode.md) * [Invoke-GMapGeoCode](docs/Invoke-GMapGeoCode.md) -* [Search-BingNearbyPlace](docs/Search-BingNearbyPlace) +* [Search-BingNearbyPlace](docs/Search-BingNearbyPlace.md) * [Search-GMapNearbyPlace](docs/Search-GMapNearbyPlace.md) * [Search-GMapText](docs/Search-GMapText.md) diff --git a/docs/pwshPlaces-FAQ.md b/docs/pwshPlaces-FAQ.md index 1819c97..2037249 100644 --- a/docs/pwshPlaces-FAQ.md +++ b/docs/pwshPlaces-FAQ.md @@ -21,20 +21,20 @@ No. If you prefer one Map provider over another you can just get that API key. F ### How do I get a Maps API key -- [How to get a Google Maps API Key](GoogleMapsAPI.md#how-to-get-a-google-maps-api-key) -- [How to get a Bing Maps API Key](BingMapsAPI.md#how-to-get-a-bing-maps-api-key) +- [How to get a Google Maps API Key](docs/GoogleMapsAPI.md#how-to-get-a-google-maps-api-key) +- [How to get a Bing Maps API Key](docs/BingMapsAPI.md#how-to-get-a-bing-maps-api-key) ### Does the Google Maps API key cost money The Google Maps API has $200 free monthly usage for all users. This should be more than sufficient for most people. -You can dive into more details by [Understanding Google Maps API pricing](/GoogleMapsAPI.md#understanding-google-maps-api-pricing) +You can dive into more details by [Understanding Google Maps API pricing](docs/GoogleMapsAPI.md#understanding-google-maps-api-pricing) ### Does the Bing Maps API key cost money The Basic API key gives you up to 125,000 billable transactions per calendar year and less than 50,000 cumulative billable transactions with any 24-hour period. This should be more than sufficient for most people. -You can dive into more details by [Understanding Bing Maps API pricing](/BingMapsAPI.md#understanding-bing-maps-api-pricing) +You can dive into more details by [Understanding Bing Maps API pricing](docs/BingMapsAPI.md#understanding-bing-maps-api-pricing) ### How do load my API keys into pwshPlaces From 6f62fc13be48f6ea6b42b5c980727ffd4b5fa224 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Mon, 11 Oct 2021 00:13:31 -0500 Subject: [PATCH 20/22] adjusted path --- docs/pwshPlaces-FAQ.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/pwshPlaces-FAQ.md b/docs/pwshPlaces-FAQ.md index 2037249..9d9965e 100644 --- a/docs/pwshPlaces-FAQ.md +++ b/docs/pwshPlaces-FAQ.md @@ -21,20 +21,20 @@ No. If you prefer one Map provider over another you can just get that API key. F ### How do I get a Maps API key -- [How to get a Google Maps API Key](docs/GoogleMapsAPI.md#how-to-get-a-google-maps-api-key) -- [How to get a Bing Maps API Key](docs/BingMapsAPI.md#how-to-get-a-bing-maps-api-key) +- [How to get a Google Maps API Key](/GoogleMapsAPI.md#how-to-get-a-google-maps-api-key) +- [How to get a Bing Maps API Key](/BingMapsAPI.md#how-to-get-a-bing-maps-api-key) ### Does the Google Maps API key cost money The Google Maps API has $200 free monthly usage for all users. This should be more than sufficient for most people. -You can dive into more details by [Understanding Google Maps API pricing](docs/GoogleMapsAPI.md#understanding-google-maps-api-pricing) +You can dive into more details by [Understanding Google Maps API pricing](/GoogleMapsAPI.md#understanding-google-maps-api-pricing) ### Does the Bing Maps API key cost money The Basic API key gives you up to 125,000 billable transactions per calendar year and less than 50,000 cumulative billable transactions with any 24-hour period. This should be more than sufficient for most people. -You can dive into more details by [Understanding Bing Maps API pricing](docs/BingMapsAPI.md#understanding-bing-maps-api-pricing) +You can dive into more details by [Understanding Bing Maps API pricing](/BingMapsAPI.md#understanding-bing-maps-api-pricing) ### How do load my API keys into pwshPlaces From ae6d004c9a7d3caf9c6730119e5d49177a8c832f Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Mon, 11 Oct 2021 00:14:33 -0500 Subject: [PATCH 21/22] adjusted relative path --- docs/pwshPlaces-FAQ.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/pwshPlaces-FAQ.md b/docs/pwshPlaces-FAQ.md index 9d9965e..ce8039f 100644 --- a/docs/pwshPlaces-FAQ.md +++ b/docs/pwshPlaces-FAQ.md @@ -21,20 +21,20 @@ No. If you prefer one Map provider over another you can just get that API key. F ### How do I get a Maps API key -- [How to get a Google Maps API Key](/GoogleMapsAPI.md#how-to-get-a-google-maps-api-key) -- [How to get a Bing Maps API Key](/BingMapsAPI.md#how-to-get-a-bing-maps-api-key) +- [How to get a Google Maps API Key](GoogleMapsAPI.md#how-to-get-a-google-maps-api-key) +- [How to get a Bing Maps API Key](BingMapsAPI.md#how-to-get-a-bing-maps-api-key) ### Does the Google Maps API key cost money The Google Maps API has $200 free monthly usage for all users. This should be more than sufficient for most people. -You can dive into more details by [Understanding Google Maps API pricing](/GoogleMapsAPI.md#understanding-google-maps-api-pricing) +You can dive into more details by [Understanding Google Maps API pricing](GoogleMapsAPI.md#understanding-google-maps-api-pricing) ### Does the Bing Maps API key cost money The Basic API key gives you up to 125,000 billable transactions per calendar year and less than 50,000 cumulative billable transactions with any 24-hour period. This should be more than sufficient for most people. -You can dive into more details by [Understanding Bing Maps API pricing](/BingMapsAPI.md#understanding-bing-maps-api-pricing) +You can dive into more details by [Understanding Bing Maps API pricing](BingMapsAPI.md#understanding-bing-maps-api-pricing) ### How do load my API keys into pwshPlaces From 8da266ad2f2cd5c706f9dc56190ac743400d6511 Mon Sep 17 00:00:00 2001 From: Jake Morrison Date: Mon, 11 Oct 2021 09:47:15 -0500 Subject: [PATCH 22/22] minor corrections --- README.md | 4 ++-- docs/BingMapsAPI.md | 8 ++++---- docs/Find-BingPlace.md | 8 ++++---- docs/Find-BingTimeZone.md | 2 +- docs/Find-GMapPlace.md | 6 +++--- docs/GoogleMapsAPI.md | 6 +++--- docs/Invoke-BingGeoCode.md | 8 ++++---- docs/Invoke-GMapGeoCode.md | 4 ++-- docs/Search-BingNearbyPlace.md | 8 ++++---- docs/Search-GMapNearbyPlace.md | 6 +++--- docs/Search-GMapText.md | 10 +++++----- docs/pwshPlaces-FAQ.md | 2 +- src/pwshPlaces/Public/Find-BingPlace.ps1 | 8 ++++---- src/pwshPlaces/Public/Find-BingTimeZone.ps1 | 2 +- src/pwshPlaces/Public/Find-GMapPlace.ps1 | 6 +++--- src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 | 8 ++++---- src/pwshPlaces/Public/Invoke-GMapGeoCode.ps1 | 4 ++-- src/pwshPlaces/Public/Search-BingNearbyPlace.ps1 | 8 ++++---- src/pwshPlaces/Public/Search-GMapNearbyPlace.ps1 | 6 +++--- src/pwshPlaces/Public/Search-GMapText.ps1 | 10 +++++----- 20 files changed, 62 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index c5081c5..303b725 100644 --- a/README.md +++ b/README.md @@ -49,14 +49,14 @@ To use pwshPlaces you will require a Google Maps or Bing Maps API key. To use al > 🙄 Not another module that requires an API Key! -Both of these APIs are *easy to create* and have *no cost* pricing tiers which should meet your needs. I have provided detailed guides on how to get your API keys: +Both of these Map API keys are *easy to create* and have *no cost* pricing tiers which should meet your needs. I have provided detailed guides on how to get your API keys: * [How to get a Google Maps API Key](docs/GoogleMapsAPI.md#how-to-get-a-google-maps-api-key) * [How to get a Bing Maps API Key](docs/BingMapsAPI.md#how-to-get-a-bing-maps-api-key) ```powershell # Set your API Keys in the pwshPlaces.psm1 file -# using the approriate variable names: +# using the appropriate variable names: $env:GoogleAPIKey = 'yourGoogleAPIKey' $env:BingAPIKey = 'yourBingAPIKey' diff --git a/docs/BingMapsAPI.md b/docs/BingMapsAPI.md index a0610de..7d280c6 100644 --- a/docs/BingMapsAPI.md +++ b/docs/BingMapsAPI.md @@ -41,7 +41,7 @@ Log into the [Bing Maps Dev Center Portal](https://www.bingmapsportal.com) - if #### 2. Create a Bing Maps Basic API Key - Under My account tab click *My Keys* - - Create a new api key + - Create a new API key ![Bing Maps API Key Choices](../media/create_bing_maps_api_key.PNG 'Bing Map API Key Choice') ![Bing Maps Dev Center New API Key](../media/bing_map_create_api_key.PNG 'New Bing Maps API Key') @@ -71,12 +71,12 @@ $scrapePath = $env:Temp $locale = Invoke-BingGeoCode -Query 'New Braunfels, TX' -$areaRestaraunts = Search-BingNearbyPlace -Type Restaurants -PointLatitude $locale.Latitude -PointLongitude $locale.Longitude -MaxResults 20 +$areaRestaurants = Search-BingNearbyPlace -Type Restaurants -PointLatitude $locale.Latitude -PointLongitude $locale.Longitude -MaxResults 20 -ConvertTo-Clixml -InputObject $areaRestaraunts -Depth 100 | Out-File "$scrapePath\localRestaraunts.xml" +ConvertTo-Clixml -InputObject $areaRestaurants -Depth 100 | Out-File "$scrapePath\localRestaurants.xml" #-------------------------------------------------------------- # where should we eat today? -$myLocalRestaurants = Get-Content -Path "$scrapePath\localRestaraunts.xml" -Raw | ConvertFrom-Clixml +$myLocalRestaurants = Get-Content -Path "$scrapePath\localRestaurants.xml" -Raw | ConvertFrom-Clixml Get-Random $myLocalRestaurants ``` diff --git a/docs/Find-BingPlace.md b/docs/Find-BingPlace.md index b5c0c15..cb94c1a 100644 --- a/docs/Find-BingPlace.md +++ b/docs/Find-BingPlace.md @@ -41,7 +41,7 @@ Find-BingPlace [-Query ] [-PointLatitude ] [-PointLongitude ] [-PointLatitude ] [-PointLongitude [-Language ] [-MaxResults ] ``` ## DESCRIPTION -Geocoding is the process of converting addresses addresses (like "1600 Amphitheatre Parkway, Mountain View, CA") into geographic coordinates. +Geocoding is the process of converting addresses (like "1600 Amphitheatre Parkway, Mountain View, CA") into geographic coordinates. This function can take in an address and return coordinate information. You can also provide coordinates to return multiple nearby address results. @@ -182,7 +182,7 @@ Accept wildcard characters: False ``` ### -Longitude -Geographic coordinate that specifies the east-west position of a point on the Earths surface. +Geographic coordinate that specifies the east-west position of a point on the Earth's surface. ```yaml Type: String @@ -229,7 +229,7 @@ Accept wildcard characters: False ### -MaxResults Specifies the maximum number of locations to return in the response. -If not specified the default is 5. +If not specified, the default is 5. ```yaml Type: Int32 @@ -258,7 +258,7 @@ Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/ Example: http://dev.virtualearth.net/REST/v1/Locations?countryRegion={countryRegion}&adminDistrict={adminDistrict}&locality={locality}&postalCode={postalCode}&addressLine={addressLine}&userLocation={userLocation}&userIp={userIp}&usermapView={usermapView}&includeNeighborhood={includeNeighborhood}&maxResults={maxResults}&key={BingMapsKey} -While the Bing Location API does support a text query option, I have found it to be fairly unreliable. +While the Bing Location API does support a text query option, I have found it to be unreliable. For GeoCode info stick to Addresses and Lat/Long for reverse Geocoding. For Text Queries use other Bing Maps functions. diff --git a/docs/Invoke-GMapGeoCode.md b/docs/Invoke-GMapGeoCode.md index e2eda16..5c30151 100644 --- a/docs/Invoke-GMapGeoCode.md +++ b/docs/Invoke-GMapGeoCode.md @@ -29,7 +29,7 @@ Invoke-GMapGeoCode -PlaceID [-Language ] [-RegionBias -Longitude -Radius [ ## DESCRIPTION Performs a nearby search request with provided parameters. Nearby search is useful for finding places near a specific geographic location. -By default 20 results are returned from a standard search. +By default, 20 results are returned from a standard search. You can increase this to a maximum of 60 places results by providing the AllSearchResults switch. ## EXAMPLES @@ -85,7 +85,7 @@ Search-GMapNearbyPlace -Latitude '26.1202' -Longitude '127.7025' -Radius 10000 - ``` Performs a nearby search and returns only amusement parks places near provided coordinates within a range of 10000 meters. -Results are ranked by prominence and returned in Engish. +Results are ranked by prominence and returned in English. ### EXAMPLE 7 ``` @@ -138,7 +138,7 @@ Accept wildcard characters: False ``` ### -Longitude -Geographic coordinate that specifies the east-west position of a point on the Earths surface. +Geographic coordinate that specifies the east-west position of a point on the Earth's surface. ```yaml Type: String diff --git a/docs/Search-GMapText.md b/docs/Search-GMapText.md index a84f952..528538a 100644 --- a/docs/Search-GMapText.md +++ b/docs/Search-GMapText.md @@ -43,7 +43,7 @@ Search-GMapText [-Query ] -Latitude -Longitude [-Type Text based search for finding places based on a provided string and optional parameters. Text search is especially useful for making ambiguous queries when searching for places. Returned results can be heavily biased based on factors such as including a location in -the query iteself, or by providing direct location information in optional parameters. +the query itself, or by providing direct location information in optional parameters. By default 20 results are returned from a standard search. You can increase this to a maximum of 60 places results by providing the AllSearchResults switch. @@ -86,7 +86,7 @@ Places results are biased to the region of Spain. Search-GMapText -Query "italian restaurants in New York" -MinPrice 4 ``` -Performs a text search with the provided query and returns expensive restaraunt options. +Performs a text search with the provided query and returns expensive restaurant options. Since a location is provided in the query, places results will be biased by that location. ### EXAMPLE 6 @@ -144,7 +144,7 @@ Only restaurant places are returned. Results are returned based on the provided coordiantes and are ranked by their distance from the coordinates. Places data is returned in English. Results with a cheap to moderate price are returned. -Only restaraunts that are currently open are returned. +Only restaurants that are currently open are returned. The maximum of 60 places results is returned. ### EXAMPLE 12 @@ -169,7 +169,7 @@ Only restaurant places are returned. Results are returned based on the provided coordiantes and are ranked by their distance from the coordinates. Places data is returned in English. Results with a cheap to moderate price are returned. -Only restaraunts that are currently open are returned. +Only restaurants that are currently open are returned. The maximum of 60 places results is returned. ## PARAMETERS @@ -229,7 +229,7 @@ Accept wildcard characters: False ``` ### -Longitude -Geographic coordinate that specifies the east-west position of a point on the Earths surface. +Geographic coordinate that specifies the east-west position of a point on the Earth's surface. ```yaml Type: String diff --git a/docs/pwshPlaces-FAQ.md b/docs/pwshPlaces-FAQ.md index ce8039f..0bec0b8 100644 --- a/docs/pwshPlaces-FAQ.md +++ b/docs/pwshPlaces-FAQ.md @@ -40,7 +40,7 @@ You can dive into more details by [Understanding Bing Maps API pricing](BingMaps ```powershell # Set your API Keys in the pwshPlaces.psm1 file -# using the approriate variable names: +# using the appropriate variable names: $env:GoogleAPIKey = 'yourGoogleAPIKey' $env:BingAPIKey = 'yourBingAPIKey' diff --git a/src/pwshPlaces/Public/Find-BingPlace.ps1 b/src/pwshPlaces/Public/Find-BingPlace.ps1 index f653a04..0f1e89f 100644 --- a/src/pwshPlaces/Public/Find-BingPlace.ps1 +++ b/src/pwshPlaces/Public/Find-BingPlace.ps1 @@ -4,7 +4,7 @@ .DESCRIPTION Performs a find place request with provided parameters. A text search is performed that returns a list of business entities. - By default the location bias is IP based. + By default, the location bias is IP based. Location bias and language can be controlled via parameters. .EXAMPLE Find-BingPlace -Query "Krause's cafe" @@ -13,7 +13,7 @@ .EXAMPLE Find-BingPlace -Query "Krause's cafe" -Language es - Returns place information for the query location biased by IP and returns a few portion of the results in Spanish. + Returns place information for the query location biased by IP and returns a few portions of the results in Spanish. .EXAMPLE Find-BingPlace -Query 'cafe' -PointLatitude '29.7049806' -PointLongitude '-98.068343' @@ -46,11 +46,11 @@ .PARAMETER PointLatitude Prefer results in a specified area by specifying a single coordinate for the north–south position of a point on the Earth's surface. .PARAMETER PointLongitude - Prefer results in a specified area by specifying a single coordinate for the east–west position of a point on the Earths surface. + Prefer results in a specified area by specifying a single coordinate for the east–west position of a point on the Earth's surface. .PARAMETER CircleLatitude Prefer results in a specified area by specifying a radius plus lat/long - north–south position of a point on the Earth's surface. .PARAMETER CircleLongitude - Prefer results in a specified area by specifying a radius plus lat/long - east–west position of a point on the Earths surface. + Prefer results in a specified area by specifying a radius plus lat/long - east–west position of a point on the Earth's surface. .PARAMETER CircleRadius Prefer results in a specified area by specifying a radius plus lat/long - radius in meters .PARAMETER SouthLatitude diff --git a/src/pwshPlaces/Public/Find-BingTimeZone.ps1 b/src/pwshPlaces/Public/Find-BingTimeZone.ps1 index 54eba19..e53a0ce 100644 --- a/src/pwshPlaces/Public/Find-BingTimeZone.ps1 +++ b/src/pwshPlaces/Public/Find-BingTimeZone.ps1 @@ -16,7 +16,7 @@ .PARAMETER PointLatitude Prefer results in a specified area by specifying a single coordinate for the north–south position of a point on the Earth's surface. .PARAMETER PointLongitude - Prefer results in a specified area by specifying a single coordinate for the east–west position of a point on the Earths surface. + Prefer results in a specified area by specifying a single coordinate for the east–west position of a point on the Earth's surface. .PARAMETER RegionBias The region code, specified as a ccTLD ("top-level domain") two-character value. .PARAMETER Language diff --git a/src/pwshPlaces/Public/Find-GMapPlace.ps1 b/src/pwshPlaces/Public/Find-GMapPlace.ps1 index 2f1e9d2..6880e9b 100644 --- a/src/pwshPlaces/Public/Find-GMapPlace.ps1 +++ b/src/pwshPlaces/Public/Find-GMapPlace.ps1 @@ -4,7 +4,7 @@ .DESCRIPTION Performs a find place request with provided parameters. A text search is performed unless a properly formatted phone number is provided in which case - a phonenumber search is completed. By default the location bias and language is IP based. + a phonenumber search is completed. By default, the location bias and language is IP based. Location bias and language can be controlled via parameters. The information returned in a normal call contains all basic field types. Additional field types including contact and atmosphere information can be called for but these carry an additional cost. The Find Place return does not return @@ -58,11 +58,11 @@ .PARAMETER PointLatitude Prefer results in a specified area by specifying a single coordinate for the north–south position of a point on the Earth's surface. .PARAMETER PointLongitude - Prefer results in a specified area by specifying a single coordinate for the east–west position of a point on the Earths surface. + Prefer results in a specified area by specifying a single coordinate for the east–west position of a point on the Earth's surface. .PARAMETER CircleLatitude Prefer results in a specified area by specifying a radius plus lat/long - north–south position of a point on the Earth's surface. .PARAMETER CircleLongitude - Prefer results in a specified area by specifying a radius plus lat/long - east–west position of a point on the Earths surface. + Prefer results in a specified area by specifying a radius plus lat/long - east–west position of a point on the Earth's surface. .PARAMETER CircleRadius Prefer results in a specified area by specifying a radius plus lat/long - radius in meters .PARAMETER SouthLatitude diff --git a/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 b/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 index 6c4e41f..16e9a24 100644 --- a/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 +++ b/src/pwshPlaces/Public/Invoke-BingGeoCode.ps1 @@ -2,7 +2,7 @@ .SYNOPSIS Engages Bing Maps API to return address and geographic coordinates based on provided query parameters. .DESCRIPTION - Geocoding is the process of converting addresses addresses (like "1600 Amphitheatre Parkway, Mountain View, CA") into geographic coordinates. + Geocoding is the process of converting addresses (like "1600 Amphitheatre Parkway, Mountain View, CA") into geographic coordinates. This function can take in an address and return coordinate information. You can also provide coordinates to return multiple nearby address results. .EXAMPLE @@ -47,13 +47,13 @@ .PARAMETER Latitude Geographic coordinate that specifies the north–south position of a point on the Earth's surface. .PARAMETER Longitude - Geographic coordinate that specifies the east–west position of a point on the Earths surface. + Geographic coordinate that specifies the east–west position of a point on the Earth's surface. .PARAMETER Query A string that contains information about a location, such as an address or landmark name. .PARAMETER Language The language in which to return results. .PARAMETER MaxResults - Specifies the maximum number of locations to return in the response. If not specified the default is 5. + Specifies the maximum number of locations to return in the response. If not specified, the default is 5. .OUTPUTS Bing.GeoCode .NOTES @@ -62,7 +62,7 @@ Example: http://dev.virtualearth.net/REST/v1/Locations?countryRegion={countryRegion}&adminDistrict={adminDistrict}&locality={locality}&postalCode={postalCode}&addressLine={addressLine}&userLocation={userLocation}&userIp={userIp}&usermapView={usermapView}&includeNeighborhood={includeNeighborhood}&maxResults={maxResults}&key={BingMapsKey} - While the Bing Location API does support a text query option, I have found it to be fairly unreliable. + While the Bing Location API does support a text query option, I have found it to be unreliable. For GeoCode info stick to Addresses and Lat/Long for reverse Geocoding. For Text Queries use other Bing Maps functions. .COMPONENT diff --git a/src/pwshPlaces/Public/Invoke-GMapGeoCode.ps1 b/src/pwshPlaces/Public/Invoke-GMapGeoCode.ps1 index 1c238ae..b55e41a 100644 --- a/src/pwshPlaces/Public/Invoke-GMapGeoCode.ps1 +++ b/src/pwshPlaces/Public/Invoke-GMapGeoCode.ps1 @@ -2,7 +2,7 @@ .SYNOPSIS Engages Geocoding API to return address and geographic coordinates based on provided query parameters. .DESCRIPTION - Geocoding is the process of converting addresses addresses (like "1600 Amphitheatre Parkway, Mountain View, CA") into geographic coordinates. + Geocoding is the process of converting addresses (like "1600 Amphitheatre Parkway, Mountain View, CA") into geographic coordinates. This function can take in an address and return coordinate information. You can also provide coordinates to return multiple nearby address results. If you know the exact google placeID this can also be provided to return Geocoding information about that location. @@ -27,7 +27,7 @@ .PARAMETER Latitude Geographic coordinate that specifies the north–south position of a point on the Earth's surface. .PARAMETER Longitude - Geographic coordinate that specifies the east–west position of a point on the Earths surface. + Geographic coordinate that specifies the east–west position of a point on the Earth's surface. .PARAMETER PlaceID The place ID of the place for which you wish to obtain the human-readable address. The place ID is a unique identifier that can be used with other Google APIs. .PARAMETER Language diff --git a/src/pwshPlaces/Public/Search-BingNearbyPlace.ps1 b/src/pwshPlaces/Public/Search-BingNearbyPlace.ps1 index 1e720fd..a458a7c 100644 --- a/src/pwshPlaces/Public/Search-BingNearbyPlace.ps1 +++ b/src/pwshPlaces/Public/Search-BingNearbyPlace.ps1 @@ -29,7 +29,7 @@ .EXAMPLE Search-BingNearbyPlace -Type Museums -PointLatitude '29.7049806' -PointLongitude '-98.068343' -Language en -MaxResults 20 - Performs a nearby search near the provided Lat/Long and returns Museum places types. Results are returned in english with a maximum of 20 results returned. + Performs a nearby search near the provided Lat/Long and returns Museum places types. Results are returned in English with a maximum of 20 results returned. .EXAMPLE $searchBingNearbyPlaceSplat = @{ Type = 'Museums' @@ -40,17 +40,17 @@ } Search-BingNearbyPlace @searchBingNearbyPlaceSplat - Performs a nearby search near the provided Lat/Long and returns Museum places types. Results are returned in english with a maximum of 20 results returned. + Performs a nearby search near the provided Lat/Long and returns Museum places types. Results are returned in English with a maximum of 20 results returned. .PARAMETER Query A string that contains information about a location, such as an address or landmark name. .PARAMETER PointLatitude Prefer results in a specified area by specifying a single coordinate for the north–south position of a point on the Earth's surface. .PARAMETER PointLongitude - Prefer results in a specified area by specifying a single coordinate for the east–west position of a point on the Earths surface. + Prefer results in a specified area by specifying a single coordinate for the east–west position of a point on the Earth's surface. .PARAMETER CircleLatitude Prefer results in a specified area by specifying a radius plus lat/long - north–south position of a point on the Earth's surface. .PARAMETER CircleLongitude - Prefer results in a specified area by specifying a radius plus lat/long - east–west position of a point on the Earths surface. + Prefer results in a specified area by specifying a radius plus lat/long - east–west position of a point on the Earth's surface. .PARAMETER CircleRadius Prefer results in a specified area by specifying a radius plus lat/long - radius in meters .PARAMETER SouthLatitude diff --git a/src/pwshPlaces/Public/Search-GMapNearbyPlace.ps1 b/src/pwshPlaces/Public/Search-GMapNearbyPlace.ps1 index 194fe70..3450e9a 100644 --- a/src/pwshPlaces/Public/Search-GMapNearbyPlace.ps1 +++ b/src/pwshPlaces/Public/Search-GMapNearbyPlace.ps1 @@ -4,7 +4,7 @@ .DESCRIPTION Performs a nearby search request with provided parameters. Nearby search is useful for finding places near a specific geographic location. - By default 20 results are returned from a standard search. + By default, 20 results are returned from a standard search. You can increase this to a maximum of 60 places results by providing the AllSearchResults switch. .EXAMPLE Search-GMapNearbyPlace -Latitude '29.7049806' -Longitude '-98.068343' -Radius 5000 @@ -29,7 +29,7 @@ .EXAMPLE Search-GMapNearbyPlace -Latitude '26.1202' -Longitude '127.7025' -Radius 10000 -RankByProminence -Type amusement_park -Language en - Performs a nearby search and returns only amusement parks places near provided coordinates within a range of 10000 meters. Results are ranked by prominence and returned in Engish. + Performs a nearby search and returns only amusement parks places near provided coordinates within a range of 10000 meters. Results are ranked by prominence and returned in English. .EXAMPLE Search-GMapNearbyPlace -Latitude '29.7049806' -Longitude '-98.068343' -Radius 5000 -RankByProminence -Keyword 'pasta' -Type restaurant -Language en -OpenNow -MaxPrice 4 -MinPrice 2 -AllSearchResults @@ -54,7 +54,7 @@ .PARAMETER Latitude Geographic coordinate that specifies the north–south position of a point on the Earth's surface. .PARAMETER Longitude - Geographic coordinate that specifies the east–west position of a point on the Earths surface. + Geographic coordinate that specifies the east–west position of a point on the Earth's surface. .PARAMETER Radius Distance (in meters) within which to return place results. Instructs the Places service to prefer showing results within that circle; results outside of the defined area may still be displayed. .PARAMETER RankByProminence diff --git a/src/pwshPlaces/Public/Search-GMapText.ps1 b/src/pwshPlaces/Public/Search-GMapText.ps1 index fa206ac..09d2105 100644 --- a/src/pwshPlaces/Public/Search-GMapText.ps1 +++ b/src/pwshPlaces/Public/Search-GMapText.ps1 @@ -5,7 +5,7 @@ Text based search for finding places based on a provided string and optional parameters. Text search is especially useful for making ambiguous queries when searching for places. Returned results can be heavily biased based on factors such as including a location in - the query iteself, or by providing direct location information in optional parameters. + the query itself, or by providing direct location information in optional parameters. By default 20 results are returned from a standard search. You can increase this to a maximum of 60 places results by providing the AllSearchResults switch. .EXAMPLE @@ -27,7 +27,7 @@ .EXAMPLE Search-GMapText -Query "italian restaurants in New York" -MinPrice 4 - Performs a text search with the provided query and returns expensive restaraunt options. Since a location is provided in the query, places results will be biased by that location. + Performs a text search with the provided query and returns expensive restaurant options. Since a location is provided in the query, places results will be biased by that location. .EXAMPLE Search-GMapText -Query "main plaza New Braunfels" -Type restaurant @@ -51,7 +51,7 @@ .EXAMPLE Search-GMapText -Query 'Coco' -Latitude '26.1202' -Longitude '127.7025' -RankByDistance -Type restaurant -Language en -OpenNow -MinPrice 1 -MaxPrice 2 -AllSearchResults - Performs a text search with the provided query. Only restaurant places are returned. Results are returned based on the provided coordiantes and are ranked by their distance from the coordinates. Places data is returned in English. Results with a cheap to moderate price are returned. Only restaraunts that are currently open are returned. The maximum of 60 places results is returned. + Performs a text search with the provided query. Only restaurant places are returned. Results are returned based on the provided coordiantes and are ranked by their distance from the coordinates. Places data is returned in English. Results with a cheap to moderate price are returned. Only restaurants that are currently open are returned. The maximum of 60 places results is returned. .EXAMPLE $searchGMapTextSplat = @{ Query = 'Coco' @@ -67,13 +67,13 @@ } Search-GMapText @searchGMapTextSplat - Performs a text search with the provided query. Only restaurant places are returned. Results are returned based on the provided coordiantes and are ranked by their distance from the coordinates. Places data is returned in English. Results with a cheap to moderate price are returned. Only restaraunts that are currently open are returned. The maximum of 60 places results is returned. + Performs a text search with the provided query. Only restaurant places are returned. Results are returned based on the provided coordiantes and are ranked by their distance from the coordinates. Places data is returned in English. Results with a cheap to moderate price are returned. Only restaurants that are currently open are returned. The maximum of 60 places results is returned. .PARAMETER Query Text string on which to search .PARAMETER Latitude Geographic coordinate that specifies the north–south position of a point on the Earth's surface. .PARAMETER Longitude - Geographic coordinate that specifies the east–west position of a point on the Earths surface. + Geographic coordinate that specifies the east–west position of a point on the Earth's surface. .PARAMETER Radius Distance (in meters) within which to return place results. Instructs the Places service to prefer showing results within that circle; results outside of the defined area may still be displayed. .PARAMETER RankByProminence

d8ub#icDnG4v}E)m5X=uZf4TlxpA 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 Hy&Lp@6l`Os literal 0 HcmV?d00001 diff --git a/media/gcp_google_maps_platform.PNG b/media/gcp_google_maps_platform.PNG new file mode 100644 index 0000000000000000000000000000000000000000..25924ac55adbd179d2f722f2f912456d374c9dda GIT binary patch literal 41598 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 Iu1oZP0S^MIq5uE@ literal 0 HcmV?d00001 diff --git a/media/gcp_new_project.PNG b/media/gcp_new_project.PNG new file mode 100644 index 0000000000000000000000000000000000000000..7d8b1478fed7db8ccd11daff89426b737e1da7b1 GIT binary patch literal 147785 zcmY&<1yEbt_jQHhUMOy*6pFh`DNx*6+ybSzyOZJ+rxYl~3KVw_!J$ZT_Ym9(P6(DS zy!U?pneWapOd$8%efC*#K&EJRUYB_M=CS@DvqfKRkN$EcnqQG(Jpp)L)ik z_54x49=m;zfA^?jgnAeC0nJKURr=AR>Uf-6vuCK!Sk4OiZjT-jyFdIqUbdw3e)I^L zuP7_6& zMq!qoNsu(ifymKRVM!ZgdK%h>rC4NmBxO>VU*QBPZ8N@rIRV)$TwRG}|L+=CQBnEP z+t;^xhT!Js56#M=t*ftJU2gTWwzcglH*6dm8+%);(BNZk&iFGueSBdd3I=m@gZ4{) z3t+m5k>)1)-_;}gtn-t-J#JoJp5@Bi?5tII{NdrDC5uY!(RiNx&feZTC#T9L_0OnV zKishOG@V8M-}Q-sLzT(;yH24=+xuuuht>AtkMeqE-fAcdD3yT)hf6Ky$-#f!fN#Ji^{_o25-VIj# z82}Do{NNt;HPRY}pmK1yT5P|~z3{3q>5-CjXJLI)NCoIW_c&wv_om!GscQ!^!I6=c zy?@3uGRvIFl$?x&lN&=J|$KIjUHKDPIz=kCaw+jc=mTmuvRzYINw_iTMOrRL0+!eYM|yR{-h#Z_@mCAHpLdq-AA& z*CCKAg0{OC$e!zqTG}GDX(?#Eax-V*E!WXfC*bzBHoNRh>UNK95?JGu-E=?D?z8&r z&_6r0F3@vioeqe|7ddJd_nR>igz!H9cWE^bKA>Y@JdBMT?+jU3;r)qRMQjhhJwsOe z)QZIJ9;j~V9StSmM%s=mUqxFStzLq;T=@6P^i70lup3Tl7yB0j z=U*+VHe{csa+UMl)mj0j9o>A|Pw$RSMwa~+Z2o60%L5W9i8UH3|MG;GcoDui`pX^O z#&0D@1%G|Rgqt8dL`ziI7h-nuv{P;p+BS z|1U0vb#a5gTAL((;WkPoAbxott1HQUlWmdkL-=>{F%(eq`ZG|ek%%{@JoG=5kfS{x z7iTC3GLgGSgiYjX89b}ap8vzl(b!rE3|AMP#gSHI6(&8kDUc%%GInlD`@xgwUy}4x=!=ECa;Kt82(91B0RXS zmDtmu;u)4!e2d{&z9SzT>8U3~0 zpH5qBT357%8tMkV`)DlibH8#;$AgJ8g(T zxr=-0mWJ&H&xOgas7%Vl@1;w4v5!-?8Tp9`@KQLQ4e?F7&3-I7)A8W>j|bqnZ-{Do z-6_bb&qi_4ewwW~a#^)za5Q4?9%kFLE-U6Y>WWpi0J*PGZ8-W;8P1k>jl_6dt>v-% zU+k(KKyEps+J~ekV@s`D48C@=0s8KHfPW&=ZmQP?1rJ*ao<3kn;WR10XD1bVe~uJQ zRme-(ZCCQ0t|Pcg;2)35b?J1HjC>1$cwa^|D~RdFLv^*+z3P({noP{TwQovLytepV z=157>&LJYj;N>CeS>}t^hkwx1lLXB<@0Zrf5{>}`ipMoilkV7qzn0{7vn;gY$=B9u zWZdu!;KMq@j__BOxujOFn?7k}ON6Z*7+;;k+ht(N(JlvPqgC})CSs$^J*YS(j;ouy zMd5puVCVic-{Sx~*fP`|XZ1kL`?Vo@<@I}D=RXnhYQtC4i$?Km)-BAzvcoRC?Skx+ z`S)a(&qfgbH-aJnlJ%7tyt$K0TmJ^0r}AetF2!}2J%A&5#CYYn3GmtS<%^he@m}w3 z8S(o~W_M$e=#jy~aZL|OCStl3v$v01F_)fQi+6+} zaH=t{8%p0jwsH8r#W_W##O%P>*_p_>z-+gW_#<^MF-I-kmBQy?EZ3hfMrcO6H*30u z4ZlZ7_{i4}a%(>Xl$pW`8$s|#hT}sIfbAfWst^`XTZrgX?vIK;;#c$BKiR`|!dQOd z_9cf;ekq1=l^7{6M+1Hw>_*IyZ*^~ zcfj$bXZOvHqQYs>+8s{?XNO}>xw0*sG6B}2D6IlK)hR~_0h zj`IA-y~n-;`3Z3^`C{Zj%E=FH`kcMQt`|3tqubIQ(iWFRC2+h{A_wRe@OIS6YrKC64lI8M zZ+(yJ(U>lMoWJ(+cj4V*3@`sLI6V>0Ym2Q{&eNrOHbe0G@6h$+A-cN37X%N*Z@aY? zPJ6GtaAx^P=%dsibClfj<={QntAd+O7cfr1L*9PL4Don1OaO+_yBbgp>$HPAgor8R zdp*?Ew{p_q{%~Jup*YxL2!yNkOZPt7LE- zz>a%vA~I*@wfn4Y&gvg&EnpK4nIz(oP}?0z<|cH#aV^n~mshqF!2%KMfVN_5{MyBhsX(Xh_X0qw7loIf11WsTF*Upx8 z__h0?Q-sI1BN+uPHf&RQbZ~?5KBVa^(~f76e6s%Bg&W4iG7~GMD^Q0R+Dz4j9Phqf ztUeDXBLMdWHvkH)miz(m9FJaaK#CJ*#5BN&nm1L`#G^a&v&8SRkx{t(Fc+nJU*ZCO z^^iHZ-?iVRJf*V6M%EB!lQh%5$6!p1xj!)UqJB8zN^bCW^2V~kM|{Agm`YN6Z!NIF z$bJe4lc1&UTRxRO6jsdlB?)+*bSzFiLy#TJk^0`*$@+-?14tmLGX-{1mJ=eBsBeFJz-qn4&x5#>rmmKD&Z%moHEWGYDjL z=Lp&UKt|L&ioc>UJ@!%Te)fgudP8-rt&?`%Mud!T9h}j>-u$^_!0NLD1t0Y04_Q5z zD724-VUVR%*JP(d^}iA%@=Z;&)KLt zoy>b1(tmWcVlWoj(sX~}x%(QVNj;XFJ&EpIEk9#HtxXDEMOCl!x}6F}t7x=*SUBM1 z=Wwrj^|wRHVwYb_XNoLkR9=F=GfN4uZSsN8Vs{LpIF&(&Rn^ePM)q1&SM2%>FuR4| zhOT%A7d-I2cEB^GD1y};FF%*tKac&BYM=W741+R9f3J27Bp)x?bxeQkJ2AW?y`pW* zEo^$6d7*pqs|B+$-v4X59EPTkv(WX=z41%8XPk6%Vd3i-&g*)#3wwd@)EA$+3nHW1 zlzW6TTAyvJ`-goDYwFi;CQfTNG`&>3l~$sZyzQo|HtUu?tm%EZMK7H4#jYev2a|;~ z!5}%mCl;n43ar$K&QumgxV{l&=Jp&NbLxscH&*q4^p)vEZd@UG;lrnH6RS{ zF=CQVM{@+$?=T%6&$}LW76F@^{)WlqP7{~~Y)da+Xf9Dv%6o)aUcp0H_R0Ga>ioZ7 z&}F~%iXdx(?hpF(mAkH+Keuj`ilKov4KNk8``cvt7!7pepdz#@AW`c1#+D*YBk_~{ z0R`@|0R`(aHkq6@$LhUHsN=I`Hs4oAvFp6ey7Vt!VlyyQfrX-&a8vew=-lY4PQ%~V zTWmdrcx>2f!h6+~gboX(-)-PoM7 zWqMDVl-=`H=hO-nZm&|)v_{7?%RwW|;Mo8_g6$GzP1jwF43IN!{-zvDsc_W5!X(J0 zk`@o{_^YIiSc>Avhb{0eaNcXjv83A>E`uuwed}~+;jWw6(>>7*0`e0C)RXayX+$rB zqjz}t{hKl1aRFZ&-1?4p_C#>&_*b@X)m=>2MU8}AFqxnMaZ6I|ArOkvW1HUexdwY4 z!Fw1*ZF;1xm&##h;8{bw={A-`s!Ts~&dfs{$^OoF9#b#(`zA!0W8EJsILy|Cc{RsZ z-62A6izxOd5M(2g%0mr4oLR8+LA1(0&=gkO7to zrzJgBQ~T9Rg9a1|{V8oecZCLn&~?W5R{Q5zP@Cl4UahcP+6@Q@_=ODkh_%jbWLO55 z_#^$!KqM2|p%p4EOJoQ>X~&u=9=4#$iWm)J`TpS)$E%N;yrBbeF1RJ;?w_7WKp2Hd zrZA2O_ab7=0`i0xc7(GIYXF(<-^(v^pyV^qy(N5F|3FBD{QEm`hINYf;l0k~oZ*s5 zl?d+7-{BIpoy@$M={mE7jJ^I+H!Y1?-kMOM$JsmqZ?>r@Ej|`-R{g;>^+aU9y5Ax-i&{Va4zY()>c$# zio6-1zp3+k!g%Sc5~KR7w7Wh#GLpqcq*7V-H}@RH6PzZUv{(SAss}A!lRbF9e?Au$ zoBiE!p;omaznQ6ub2b58>U7`PN~EdKD>eNM%#k5iirx{o9YWhN^gLO4yOp zoq%XcKo&PvxNxz7F7W+kEY4N+7D*Iav@`gWM9o+{j!!qrIe+(w?axvTmvRy&-MDq> zVIS{-xHZi?^_>>YSb3?;_woqEx)(Hm%5P~vy6%qze6m-&V8fs~AX!vnTSPV-7<$d+ znTxpL8q+iS(${FKQ73_eA^1D5<%&@4#nvb2%*EWzwpSIGorGtFFIM^s_CLK-QftE( z5p{#q!!5YMo1wZG6Yjut`s7fwcQ0q2@-Mq+`RqFBns`{q*3s*2G2Jbx)IUA9o{SIs z`5ttU5WuwmW;3+z?aamS`cn95qaP^2rkEGJdfGOmd@bgAX)FPet~%T1-;=1PaX-^o ze9MvQ{tad#zYQ+78Ep7)Br@24RT6VsK2YSU#!L5xQ7S0W;=3;7Htc6OaMgEFtx-l}3$&mPnJg#y-b}q2;!FuCJ1`^H(GCA7;ZW zYLFzH%rSaz-ANGQ{?K6inKfM-5Aa?x$WY4g$icR%*DLh~mh+vePu*(D@2fI6;!4+M zRNb!BR7BnKXYD=)#JOiaAk^`y3{}pbVv)w0pPTKoa8h0@*2iJRkPnhAVN}wfDMMS{ z&tD4W9XzF5Xq^Gah|_k`YU?~lJ8BZJRC5~=3%}kXGGF2mr%iTY9y2<^7lRyNlu=mt ziO)P;Z;{C3iTGJP;y0+BjYw$zI_|MGI^u#f&Yd*KG(PC26D-;wCE< z7oN1pjOZ-?-fI2b2M@i$!kX})lfXge(E$y0w}3gFf>i&+=;_7}O;`)7kadh5M9at5 zzlaw;E!kl!yR5{_5!Z3HZ zJo8Y>Ab53ksv#z~6-Z45jPyL@7I=XCHx=nBK2s9n%YhqL04sdLHNFtGxgj~DuQN2$ zb`_xQ%my(~|8h)wRjXDda0WXJ+i(vaD76heNAnW^O!_q`} zr*Fnh&Ligb`3UvK-{!Nu0$1mwyK^U7gL8E&6rT&kL(X;Y%Z#_Iw=4+Dz$}C=5&UNT zkBhs+nRk(|m&6Nr<3crIPURcG?cr9|(t<?}JFmN!DkolFfvuX$kg; zr#qjiM7r&)ddkvMoCB>zps60?4g?I+%kCJRwkCTay@)J7+SP`j12?Ni{Bg+y^EZrB z=b85g- zLN&KAvl^3Xjz%)L(YjLAI<7gibwzIS3+ZkoEuF{hLhUKEgR%3gkw>FE5{FV)mtR0;>YcZG?^J&xG8YlaX;s^Kj zYOE5x#$(2C$sZNnqNM)6!GK=-UAZkyPeOnd ztQ~D-u77I=mJYU=k84vaZSUpi_2CTi1nxVJ`NNkegk&}vUi-DZ7tzO$*HlYR46uDR z{T$>Xz|BcS#MG!@c07q4J%@#8rwq52=-dd>oL- zB!1srRqdr~~P8;!(fB9938TA+($;8J2-hER6*-{D=B#pED9Fj%{#EUZ_!bQWcQ!nH@uOHZyfua!Qxf=GZS zH6&EJme#2vKYxUn&L6W5r8(Bpz(9twy91bz8rG2zjeC5uA8%k|_N?oFh&QmbO~Rs2 zOO}%y4l|rmHLHtVU(SpvH3U&^D_&;*Y*ZOVwDDnn=OtbqjHq;j{;eswTQQ=A*O6>r zemweHBbM#Ude@;Og7DPvct)Sx-ZF4Avb!ssDkC&Rksu1MT)-dk5uVi!ALM4ZQE9E5 z(Jo-Jm~szYXnbizff&;{Dt0X?a}(tSq@}iqHY+$+g!qm&Nlc$xfEEPzu99~9MMVqW zbWaI>JNZ0^^cn249D5yfY!AoS*jj3j0zXPHSEONctmg2NstKg-=o64Ur&vF)$6sHk zlep@@|2V4?muuApBBVK9t>GD^qmm!z45}QBI6CBQPVeP$jM?9%7HBrVs-AZ&w@Udc zen)Q>yyC2dvtqpoho;_%*T3lepgY@$9yhJ`SD4SElf67RU!aOQdqPz2el|He84Su+ z^c#FCB;b0mH_$(vEXvG8IFp>lhCMv9GZN@?Nbfxt@lIEt^viV!G=Y9@oj~0QDY}8_ zBGJ#Y2X4W6N))mp(R-fH7KvrP==1xcrZ)NDFGB{ea_SSygC< zE2MY;j;FdZO4Q~KBz~w2FX2`-fv)W^e<%bjNVyGC4}rC*$)7%c!?g&JP=N_7O=e=j zFnVIu^=8|vBZV+iY{a&i&OEtB?cFS&e-jW_yyqvKkMK0#zvq|>u*QhfrGB3_kN1Z_ z*yn_M1ZnhXDP1@BcH2!DpdD3{t)v-H|D-XBU}b7XfaP|@!|28qLoEP=9U)kd=iZmC zc{6M><=;#&4LE#nu`GYJ2C2U~AI@i4PK!HgEbsYhe6-SBP9gm5EU_9Hw`Q;T7(ei5 zSb!L>i#5_QL->3AT34mUt;6FeYyvw}eE1-$ghkAzTRgf+w|T)L>b_Q2jHG#@+?!uK z!YxNG+~f0D-D~rIn^Rx3x!nvplXm=dwlZaz5})!FO`X=4RtA+Ur|uSg(bV=#6gJe} z5ARdr$a7mn!JX_^8UwgBb_y)g=b|>K7+{SB_v4kY0&#s#7jB1quNhet9odZh(`sTX zCcMo69CR)IHLiFlZ!CXdOPiRYn>_BoCK9Nv$F_e|VZ8~gH_iZ17ujIzOTxWJ92on4 zx`A#FX#sdQsGcAq#56727g(X$_dyu8&c^OAizic*n5{t&yY__98crU*_+hIf}YS5D=)*T+2T&mD5Wyu;`% zUyRXKJ;&w$yDTOzea8JSs@(`>)w`~pN&cEVB~mMGfGBa;fHCViR>0iR_9U?4GP|=2 zI8s|IXCIqPAC<|lOIKmjGSe**bl_kG<88NE*EA<4=)jkAT=@C@PAuv)P75{N(~aq3 zRyTY~lgs7yS{-C89Gs6Q@K`gJ9Qf_hAYb~1 zw-;A7CtaE%MqqyrOoq-JiAu!mB40kHs;zW!k+PJscK*$d`?WKn>F*{=0Ht1xsKH^@ z_-Ghb+Sk?rH=J2HJGT(ds(-QVS>7GnEdm093GtrYXlB>q)Mp2T{%jS~fFBkL*RMNJ z^9>xT0HzOPalqooi#a1`Rv`$9b8=% z$0r0c6@}ODr0=+HhK)^x`&=4c=}ZX{j;yO+qo*Vs zO5LqRCz!c?bwhY$09s^!t?rK>QQ zPWfP8v9#<4(Y@qX4=-QJ&pr{suMY35C3?aJTu&w#GC!|;(fXT)mQAF=Dx_AsDj`LX zG?sA-FXsB2s>?n9S#b$%eXw>d(ugaL(j&5tQo^DkIJ1|2ZbMovmTY#Rcg%6Azqmqg zuOhrX=VQ6W(K6o!I^wX95q4RO5R(YPcmI1d$#AUN7to;+(edxW6MX7ZiCL9fMqy_wt>Xxx@Puenq1f{+w`f!2 zHe%)Oo?R`S3&tomwY9OYA;K>AEK01=nwo||QQ3no1tlcgB|zEv{7)pQG}8JOSQS$` zIj7dN*n;KnF89b1&t{Z`ugyeD2w?A&^%)$==>BkFc>P+dRngkA$hp_UkF&B`SwFX! zyWeuNzQ15?$;&(TzUJm$IiaE^c}jjvUfGM3>4nm+J3)Bm`M8?HozaaGyC@*1#o4W; z3B&q9MZAuz^dIg9h5N7?VYbxMYm@WAbH+OTuHcALoBq<~7_{u>!FM;V$=K@ez}7di zLhZ#GgDjIDQAiY=z=GjgThNK7_K9#X!`q@fXtefq>qi+iC%?OFI2AhQlxQq=N)XHw zOvoqJHa|lw&U;n)f%ond21^I}U7I3`=}n$6z`2=8$&2rP7f`^cMAK4P^U^C9&}$Ae zj*xduc0&n=+5Ts$b1qiV3v_C>H)6A+97e(w`8c-2raDp%Nfc;s(?bMN-4BA)pMQQh zQI|X9344r()Z2=FS_oc|qy|X^x#TUiUOV4>eiYVwLJ!e0a-`}T3w1H_@U7N16!aYL zTA9ZU>dDF!xYy~7Xi&TRr0A6+^>O31GHqb)VxXfN1Fj_G&7f$Ioz$~-I`vt?67_{D zW0?%9N7e{0mqH;o=w`rRHI%iyjwQ!#?P&B?RL_l+0;3UUr2OA&|LuZHMk zJ;(f~L$)>^`;5R*e4e(1j@fx)z5amMiUWJs@Xj_DHry0KP_=|}rX&?Z)flQ*@M2q{ ze$8=%5iSYibsRZW4`Hu$Y$BP~7`ofHD+Iw#vfeHQpozVbq3dLg*X$BlOMg?yl_j$| zjh#_09_yB>q-o%S%{=lV=XWkzvOubaF(4#e6%RD+{WR5%YrXdneJYu@`+i7Z4zwoX zU*(D=$PUB@IH(DQtZXG=Xe2cglf>WXNUdrVAj{?;3M!vwQ9LsTM{eww3uRwYs(^EB|xYY1A3jD+E+O4K&CK zbD4s&PI~bt51(+`MQxzBcvo0wEzJ`)XwF2_MKcA2~@gVybu&6yt*S75q?lt5SVi;41Rp0Xn$uR-&OAKMNd>-6QJ`^FsK z8;xi>llOx#y5;bLW8JQTst;p!y<>I};1&i5PiTx&ZAe#$%d!}i{VZI{P(N>xK9?IGfl)|f5wva)9(M(M&gXr4cD04k{zvk+UKjh|_T4Tw{`DKc@PFE zJ{d~cGvL+ggmo*fJ)qH42))?kYTe z+}H4eEfz+6{SIQnM=4~(af&nPUh=AL3*t1g+k)TSr<%XLqk}!w-l}|}j@l@G93*nODr^XGqqS`V zTevy;Z8tneRc%OCD3xx%cVals_NC65CNg4CZN$ZWa+;>{Qw3V*2o6=FLZ9tYo%A6$ zb6MGt!Jd{4uIMcUHBoiU7o-+ZZ-V1 zsgM;P--ur4!)y8mFB^n)Vm4RY> z>}s7QDA1n(|F5S&9F`kJtjEDVMNcs{eE5i7&9V4mm;{Pa zXbC3NTTU`_J%j}EeR4LZS3>8$LGMYt`%AEb{e$xkDEcao(uYRy-Jkh_{ym)*UrzyDYSPH(l5o@HyL!D^gepT;DM@w=E`1&e!mjho>^iy=vtQYF35 zZ2F3(Eo9eO7G4RblXuTQPb{Q+r9#-!;7UULM4fW*I7vn7522^>{6~|eq!nNPC#u6U zRXFhSl#un1ydX!`g1;jl;uVGL8(!HFvM-q(2W4k;?ixMMi8p;liS?3(0v4iJvS;lidb zF)Gf*KWFixUI2z)@TEI{rhEAzq%keQ1%xMXA;7{Z76rNCOU!JIX;dU0692$j)X0>xO*k`Q}aN8<0N{U%ZEB9I_iu&I@@ zjS!qyDov8wnzDNZByd=;&{0)Bod*))4&w1^TMptes&J9S9SJ%5`843E^1i5gJ3;<- zCRxmC;St$u%m#z&g~=I8nXks44!hi(Uh&;_qgMX*PiP!WHvGxNhd(C{Nmps0vRt68 zmph857#T?{$Iej2OV+(Ilv{X)^WvXAx%6?;gzAlr^EO4)5>)YWr49Z9mSHIfYK}-q zXz#i#Y#gzz$9-jyDy;3fcC=WJmGRQSAoo?K=~8fS_2nDI(Yx21p&keOLpRl?EhV`gnlcy||IS-R$oj*jl!V)-I?1@TVJzIf@C zO46)1n}LXiMT>V|=78`>4RPDw$2+*=Q()QBvV#3?*)1lsQZbEGWd5h=Vfp1$3;f0y z-ng>#??k)-UXONvzq7HjU|7whlvnMO$YO8i+ekXGXycWj(Cz)o50IOY85r>04Ufoc z2=SxkmC&cFUpj4MFU9?MwA+yRU9&rkdURwpvDf3NP!49+9%S2pGf1ucf_w7*YJE7NN-ztf zFKj*VZAOC6Zpx}n!VU1R?W;T=1Nd?!jeXB<6fr-)PzN7*Kiccwz7?92Po~b8cUjVB z^^JuD#+eY%tUCr?`)%;`0^s-~LZ5oM87Kcnsw@BKa&-?5$Zgo6ugJVdmm&kkI(Z%a z$xDH93-ZLBoVe7cWBFKTh?A%V11_9}NuLZto#?Wzeg4o3ODp8RGA31M7hQcPEJDb{ z;!eP*^qCcNWHC@*EW?^JA*JJ=sE=GDa~fPmED-CV$bJ*I$2TP_FsjhHtxP2$BHp+P zrm7(sp(8{ENbs1=diQcnXs^4-iKM%`n;aF3fNb#{Rf7Zk+`>Wv0-&ATdaUmf=#r1p z)=pFNk}(QJPETuz*Sx_Tfvm1R!SNs?&RAzt{Q>XbgU@)n;S+$ z-uYN6Xwe(T*f?|R{M94cM!@D{cVhIxr)$6Eoc+A$bZ92H%*)8pmAz`7-6Vo!~g&6SxjFzPU z)G59nuL{{C96mI`g7S1`{kEdxs}KV$>z=DCwD5eO>FBR{4q3O4wK-T2noRFG*79Jd zUpW={!+1iP#`;0oBguJ}Yd%`p!lBU-k}}$6_^i?KIfxk!RMzZV>G;w#`d&WZ81c%U zmT#Mpp(?bqX*;XM4khuzdVg`ZhxABSGhOw;_b)vc)NJ1kT`psOf==KEHHg0QeZ8kf1Z^_1}vMuHtU6dy9 zP8T;erb9^3(Nly$`go^k$c~z+9o0n~r56rTY$Uv;|MeOE!1tGF7=X9WqMZD5dESoz zDR@C~M(zMe%Hw!mDiC%Z{V!RXVK(}~<=O583DL7gzT8H+pb2q%^!gwS@ZXRn^s&Xo z2v`MeEpTOTK*`mC+S#8DFSc10R%XEtQ?x`OSFRv|nr!Gtd`V@x(B{#|_2wqv-Z<~6s@6~Pc`o}I) ztS}FYPxX6LchCNjx+Es-%RNxJ0TbVZ4vi!}ROniVm~iBk#dPa*eDun<>4!Bpk{M?j z@4)s@!6EN3!6Zxd({cHo1ww=xam_|T!zqi{CC(7{MeD;RSlvkMW|8ou?uo#5ZrkC; zr#d2~6N^$#Cer|T(ZFF6UuMN@Re*E;<&Ig)w2vP2P#Kr-)H0MZ$892_*-6FF&h*4q zy7Dp@MQlRR9Q!YFQB-;BznzZaH{Hg3E6EkKLxG`8)Pnuc(=6O1-VZuLcu}Lp*?wc& zyE1lzPS$>Nw&7hghndzkHl24{mQ%M{Uu)K0YJE@sdG~bIsDvLW3HT6Gle^9$s`cfA zxwqmtk5&eUoVJAsC6(g}N*QU%W{wpMEX!_7>A*&5W`0gSNKjDC+PkW~@aGbEm4V}{ z$ZwxS4W6&2io{jEquv*sqO4hIS0WQ6dHl=qp;L1xYRls8V)wl0)Qh+ zqFjxd{jofzwTsHZp?d>3MVwM01GR-N6$c~(Cq1O8ga}sTj zUzL@!*ujR2W3KJbP{1EL)~!dcX#QYv4*(d3Wpicm8RBFktI1PYN7lAWqODs_aA1Ov zu4?7@s=b6jlgS`d9U8VdO%R^m`(R+UH$XW2+6wbl$OQ2gCB!Hb|J{D|pcu(TC{_@7 z%*M*{d;O+^b*?HKTZ7IBX$}uTi&LRg^#UNzP39>r?X}d>RF`!F0m{9KHQP;*??}C1 zyXjO7fMM*ywV|-qa#THZ#J`aSRS2xrZm!k=w>jyzNF*O6YY-@i62+qP6A_`rO@Kl>B5%{6d2hq1fgq zJg&mJ>`#fjPLsPQ)VnUv8g^9LKsTKhni>8AdmZ$!@ZUm=j{bVkJw<`!&BFvn>>gwU z&JU-a_1#}ByY`l5e%*h`w*a5(m$N9A2uAu+-n~|1J z9<*JUtQkpff826_!2tOWb>51|$%#|lXB`t{&L|zoLe0Okk^TCh z5oW?gq_trmTqOngen6=t;dJV2D0%1nA?AZt0=28;K&`=djo$)Qp`H`2NjWsCVeZdz z3{r7+$sV}t4*CyL5)`05Cw?$C#(SA7dqOV-rCYh{iK9U|XZ1YbhU0#i4!I*0e!u%u z0A!+>!||UpzpH%M+uxU#{m#N^(h>=*GYg?uyFf({elM}6&U;$-0ofXi@;;0yBN z8xy&xpN?V5zs_dS&#$Yi`x42bIW;|*Pw(I%U4Rp4g`OGy`pMgW*ZQ;KKk{bO92^|*e2$K?#dirF zA~$(-5dCc-Tw`GYH0_sx?%%h-dfQCW7@R=l{Eh|KvJ24it6cu3+(JB+mP8C z+c!@;fepa+23)3w_T^~{nBnvjBShuI4zf7M3dH{x@=9&1+T9&6Lb^fF4`&#(D1;AHmw`(tF_ znJQ543eL(}x5>hD%Oy^Go8;8ii99cqLcoi!)Z4F~AWQq=>(~DiJSUnAY;3$LC@JwF z*^j?8+f9`qIusX(!Ha0^N4TKP!eVU-Kn|!F^TZXWK6pofcgA8x69`|hlkTiMbu#hpJRs8pM~tb4{5Q)i zl_BZlF#`Fq##N4U2ZQ)-fUezBQ>L3b$#c9y&`e<_Gf|>pi!`d?-ZAp%Te+H5O6U>s z-hCi>LJpspf~I-Fr-L-PdvgiEAsN#J7zc_ri8buU}PBrVyv zUq(5yN>^QZy_X-J>42Gjpq0J!+S`{I_;~QU=LmS-O>o5}c|~u%2)^5&E**Y!kLq0v zVqE7D?!ctb}=Vt#P=k3x>qfcx(Njia_|^hdp# zhb>lGm%a-;vp-dje+wKeUc zI|=RtcZuQd8f=pU2oT(*gS#{?!6A4;a0vtrZjD140!?st4H_DU#v16e$lmY!?e~1& zzcbFbcieH;FQiwmxoXy|s#(udHS?c)1%f%Jj2CRFsZYXVRF7IRI%rv0SzpW=R?xk! z-QYS-p+Q1tC^GtidWe+Ddc0XXlW+HD&sj^n*5=6_n&i*(WvZBO(3D>MBH$~)#r`#% ze1nDA3%T$mBeS$ya`wN*u_5M|*VM;?7ye7ZRaGY#XQrLyX#NlfZ*6{C!^aOI^QO$? z!n-Xy4wptFpWK_SUmM0S(ZR=QsOYWr4oAmLF>~-Bc65KD&CtV7g_hz3fyAQ4 zQazz}pb}o**n3giU}GLW9`s!2nc$uthe1Z{7;>MR&yp8wpHrqM_}j4r>iR_2GgZc! zBfsD)S_kT;#zH2yu#PhM*6zt4_&Yr-j#9}qU4u6rk16ouY{I6)JGIV4So;$Lb#yHE z6Qn*_v=y-9{~D5UAZZ9ZiXdGOHjei|AUI} zwKgSZX9n-W`lrn8%*f{2u3WNlOeh>FVXArl9)CHfCoRP?RSl>4Lf2XnvkazrNS(dL z*MoFxGE9dFFi z8{Nit(V*d4VbNG8GH4s)Z$`IargevmQ54JNnaU{5gwOu_8)TF z^c&+-8r>LAc}WhW0L5Q=VvZ?}!PqoX2E0vm3ZB+^fhH3TqZi*@3@fZ2r@?a4h=Kgvi zMxHkRqslb5?S_1=X|&F>NDAKM)Ig$|7B=Y?{szBIY{Ua^6YXr z&s0JQovM{$HQ9Y9uAT19oi-V!s@@Xud^)G6mpg8|?<|SOPV9o^1OU#pt2U!ncu_@9 zq7bY~)P5>>B}t1V2BIPsZ(85c$^;ED_5Td-zRANA&({mhnq-SfYX^u4o;U9LYE`n~ zMN}tK_^MohMzN1!R)l^T4Ib5fp|low>-Uw8Hd@-$J)VqKk=d*i=hNB~e>(A^C#&UX z3$M!HPd4(k>d@9}R5Is#8P3v@85@|qXfTu!*Jeaz7hgT~=M~$NIGiG;MHhS-6sV%h z_Ua@ERoqshKM#?>s~De6QD)MLkwNSI;ie(PJ1sOVEarEr)^DNcLh-VK`Y&^2W zYONRJevB3%CgZ%aHK*jd6QZAoewydiHkl{rU{!BBh zTzm0er!Az{d&@W2s8c$2Q?T?qF7+4ZgvX}BdeYdR3ks?n4bTJ_J)>ydN~@igZPx_R zhpE8D?Yo))pB~!R%>n1%Zd$Cr8fG<-bRD=!w6zC$!2S*DyDiPwAaF;# zIM$MZuPn{|Xg$K<$yhI2j8_urt3oE1mZe&UZlcB0csX{KkFb_9?NAev4$r;{Zg8-1 z=m#$>4Dv&i`MGiOsM7ss5kmg#TaMr4@u zfWHhNQkFZH4Xx|3ZsVsh^taehfXB3xn=84>xjilV{Hye{PNGG|vE1TBb^8^Tm}Ivu zcVLkN%)-HLq9j`yFPPKe;tbyo*=9uA9?h(!$T8eeO82+AlD64Jc7`x99ln^==10?Z zUu*jDVC~GL1#sz~W(k7D<8?V_2YBT8C7v!J8xuOP*>4EbYU!6g8u>_HY_+_0iC>em z(-WHFQmMUf!`k6Wf@9}<=z@N>|35Vox8d)Lb$NhLDtajjtb)BY*R-9YiJ1x|{sgB3 z;n~Vds(xD7+?%pNuI`&>e#MiS*uf@4av?rM<}(WC zO`65_BwqaEDKY75@4)Gf4g{0i3Z)JqQLJ4@Sor~`i@&8xKQF*92Ck&mJZX-KT}?GC ziPJ&IXChr?3ATwixaRHW*EF|c{^Po3be@F*8*TPW9Iu=DBbHp>auT2=?nj(+ypn!6 zX98MSyBJAwI@hpI$XNOIAer23lo@`b8@#gAFMgCqW%z=~RdWvZ!=W5kOtj8CtuTk%L$+hS^6xDM%V0D}bPU23@=haYjG05IA=l;O!CXKt+=XJf z-7Mn%?H(PL2}P?qkz7tXFNWS%g)bc&UX4dSF5X+wQ)1~%y)83W6_2paE4x(uI>77@ z>Zx?jQjMy&1nk{J#=U@fpZ81Y; zVRibbZ@gLWyY)6kAB>AMwCE>KkU8nXAYv)kxnHUmaSdfkT=pFx@a=CQFUmKR1&6rZ z{6Sd35Bz6~es-6=5g`0Nbt5MM4)}hubXkxMx_UavEHRmy-PYE*Cv0NJ%eT9?y6kk@ z%yeoNbf+M&e<{d%9tQM_a0OCs1-hU@S!zQ25G}*3>X{)b;iL6lQ&fx+gI$+N(asrs z?#Qa|<4qC-Us2mYI4hd(eXxG~Wpm#(bpBXkD|U~x=P2TJbb|W2{p7lW+%3&554SDR zg55${hVVpmRnx%eao==U&7d}A9-(^(x&yxoOgNs#qT_b3sfnORdhR>BwETMe zQ6F|%tQ{X_B9?-RUToVN_(H%CLd^`^cWfxo2x%Z2LDR1eqfknijIL2`iPs3EEMyo) ztrRI_sBhXs?RTT|cy81&^;a>LaIr{u(tk>CUc*#VM_zI&z1qQ97ZlO|C>Hl55po6p z?6B`p)wLQ)NFMFzhz*o%^jG_H0i-fyWC#8MZhZgM~0p@Y_8su<)5H)CCzD67YIn)oS(OqrD({otcx930WR!c`@uUS4tbJJ6TBbv$bGoP=^d%C3Mc&pk>5Ru#Rrl<9{fZm+!UeRN-V@~7`hf*nC{ zVtV^d@YAJ@oH)?$6l^5RtO9;;x2X($&(88#ct@gFg>*!gAhIsEaz1%Sa?X1=e?@Iv zR2lu5qsJjAa;ZENM|!NPcFu?U)&&UpI@3KZ^$u0q^Kh}`oH{4n@Ap3}BT>{=q^2jT z8Ppu1oXD%<%tx6z@DL?(2}BclrKcyH*9e-Rd<^>``pbn}JtUwMPyi#Wz?8WQaiDux)OAZ4!zr|8BLZO+3g zz-=Lw9OKmc2gp_u*jV|Y2eih4<*V;IDJ$F=uZyn15$;&c{*jT}4?rLtDorjPUtj<| z3bvTh){MaPKRR=xO>=Bd9L61NZ%eh{Tzh}NE;LEFc#S2FQTGU6Lf*(m3Q_?M?UXU{ z`);zOD1LBb;w6%zb93B<7#VpnuR86zbXrVcHIxZWYgX(*9dVmZA5v0@9uhZnQuI3l#G&KC(#AM3fP`hHsfOfk`E$+y;qp*^!>NCxM2jj&h_3pZgj@;*Ynxhs-#`%h9!30T)W zd21CpO@rm5ju%t2hb44%yjTQwTo}-g?fo;3QdPqQGB=!0vKAG#LrhIH?k({!s99#_ zRJKQ#8=U8kNMH`FWW)}q&9hsZ04b<057Cvb=O<*O`}6NTb;R1=B_uaK8N(UZ(|+bG zp-4iD_Zo2>6~OTd%csEE3&Rrf$3tx2Zn{ejUK2Vl# zrC%pSOQv#2a`WswcaikFbljDMi<&e^0e-0_3|dG4kjz6gH5 z&jjpU{Zv%CYSW(&ndL~x}RBRXs zZ_Bvn+ImXcapfRzDe4D7l_#LNsjn3&79O{IY!o)gusv$#7uWrj6vO|DN3P8YgYik? zaq6L!8lbL-xhmnzRvN|nlXSYcqUK8ODJe!+K5oFop!YV$PPrn`;pOQ;%XUcXx8ap(ry+sq(Mti(T!X^oU^1qI%S(p#eB59JVe|>6 z*6pp579doT>!38pTbV-Yx4(LDPmw@@abQ{@D^_+NF9j!&IT5WT-6T>;2vj>OHoo}g z4Fy_h&NsWWEE)7m8Kf*abS|PBoqn_MzA%cn06qi_jN9HiAZ_BRxit7we7FhNf0@N8 z1TGTIsaC7aa~$)MqdemMjIGZcW-9nN+UFLlB{^QBS5#pBLdU(PmX);UToRL>^LA2) zO}nnI>o3ZNN@a2m)a6NVy!Q9bi<@su4%Cms{_X7Z)+uy|IC>nprZK+#gvPqRHJmHJ z_XFoEMdnr)T|ZATUc*>&`}GtT**njK$RZQw4a0V^Vh;7P`1U3xqHq0di=SU6vC%ZJpG zxj2<~ggK@25>BexAzs^wm9QTN_amFtAhXou?e%4RSwJ>sF!r)SdPf8!zjEC#KLeJ> zq)b#s$j6KZ)ezYPlol_zs~ohlby=7YQTQu( z*%A>2ETZ{3*5wK~MZu$vp2^@@;ddsu<9o@AU*k>XGQk0LC&ubvf7`Dd9k-36s&Fox z0soKh$wY@7_9Y1D=D92W5fEH<)1j#n2->wo9vTJ`hzH)v(p-d(i;Yy|z&K6>>9En9 zS#hgIZuqULO{r?QOP|%u)B3mdJ?JgVQN+AjGE53UQyHQeV~t(Ix`(%8rlh?b(Gy$M zwxAwjD(B>#jLNk+Cdyjz2KEeDDP0ZkAz_5a)Cn!$sSEA=zZyL?AvxZoaZl@*rO2P# z#3cv0%p`}E=vIBB97d6V6$6W+g}y8hH!Az=B$jTjUc5xg);g)Fc$b%8=v^K8sa$$| zGpkB@iLhugJu+uk^Sr@ZK*{?dFZ?_rPVPn6N;Nai5N-Xvo&xA5yK3Lk$r-%b>68`a z7M@=%hb~D^9i_eRj^5*z&n)-WB5E}ax-{iLJ(#)nHz_h#2+&Z|z3A2D5+n@t4!j}P zUm8Rys3z@WD}RkQ50vDYJbBhxeNp`Vwy8tLO}VI|m$2N|=*~b7gR@mV_iZqXfVIUyWIAbf<RdE@e}BR7zUTAfPG&J4|rw>!kjaZm{WU zTj0IR3~h{HH9bXN{ls9#CvOsp0_IBLZo<2Km-_0-cli)G{}`H!PZ>Ds%_TEZdi%#?2iOx>6^l$&W1skAP%hnq0y{6qZ6I)uh{zB({O#N!b166}!?l8@qGJYa7+{^lKbxbt+ zTNab2vs>yhK_(LOlE>b}0n6$AO`K|5g@v4gJK217LbEV+AedH|Tn-vpuIPu5=Y2Io z!P9l&*VbEYA158;E~Gry=A3$tIgB!5-@qzmGk;zUq=)}2j7|f9Ch|4TmK&MFTsX4c z%t>TffZVR=v_FnwI?T^M2iW69gA8bjgu8!33Xw^ym{9XF7yLdN*SlN9D>eY6 zYZYN!@f~br_Y@@;x~as|$Cye9^xA&<+uSnem3ZYbdRgbwP^CysVYG|Afy~2qtWucm zF3Fwp3r(RkO~t=lCGvkvzyFDcl#wruZ=`?q3E(!7gqQ+g@?Vz#nJOt-G~n`qko1uS zc>MDVANB0|nVosdKFC zG-S^68bAV+fxj+moWdtqzi|qtD$^7qc>$x}l*->v>~@+9HmzRMH-3SYsp0toz>=-m z{`p`15L2U4Q*TwB|KT5rF26v5SR8@yJ|bcjG63lRTYwiTzC_n5plWHX^l<4Ul(bI4PkJ1*p%%@M@r(+kN?$oo3w)p8{ptt z-f>?3^@uyFLTKl|Uy&u?jzf?O^gaFi6Ym-BhzBgdU;h@uPuN`t&;Q$B!TRv)--s*l zy6VT~(RYJ*Q zF#nd}|Nj;LC$h*$WNd6{p;1v$nKP4@R}KD$U;*V!CIaw!IT7cTKe_;ti^o3{NEj%b z26E?=7$l?a|Dm z>CkJkk{5bac=I^yYSX$A?>ilIA&lrikTrTb(Y5lLR!LRC_KMftHiBdjfCT3%W?$n@hXi6>;G@pb5Js`9FL ztLR@#PDK>U19I^x`5PM^f#QABNtN#lSRvvrZ^1ZkrYO2d_y$6LB6_OG(5-oI&nNeL z+<>gl{0fH~#bv)n0_3J<(IJGe++x1Ub@hI2bQC(S4s%Nl`$&P@rRCav)gmwS0ffxW3$=p~R*6%|A;jd#cBo8F>4@gfjK*j~T%dOuCGR-st^?2ukP@1I73 z6&(t+J#8|$ucM=bM5QFm7~TGgfNsoWehA*U^c3uR>LMH{`sNJ~-&}Xliw-ySEe*ns zlLU6lAh!pc%P|T-NStjFhDk@L_Nn%M$z9IMsX<66WJQz1%Z$!7dT2#?@e5@k4K{*qgSL6AoA{q=B z37Tr2)Rt&I$1uzYi5hxTn)m@iGP#MGPH5|$71OQDb^i1yNibwZi^X1}i!-qZP7wTM z7)Fa~qMZ=$F==1Wr9epttn#bh|Az(XXbds6q9A-9+G>08iCyRVK{ktg9wdF>xCXPzG#wg@kD+$J zb$wazc3&cRlC{)jz3^tPWC?elEtnHZ_Q}!BF0fjP(LH`4w zlf4Ik0S)%d71+EGj88<@ZTyXb30hc1!)qOlCXDD72B{wL{fL7nktI7d#UUEK~}$Qn zGF-|IPny6>vStvmpXRJM;Sh9Sow7{HomAIRhId_5gTZUL zeby*@3+JKF{OEo?D$c!{-m!T<1EISK;xV`{-GHX_hR*2u3kuQ__Nva*>^i)&c%>xM zY)hiuJ-2|%H=+1{N**0&=g=L1K`SLonN;T380Mx+*2=6G6B+HlRL)giK8q_TVivs7 zUAdQ@?jTanI1^Fm=lyw$Ie#lTZ(jzJe&Q3e=c4&ZTUoSfDOYw6qsWuV8474l?t8`d z1%dv7T*iwH$&1;*cB$t^He6#A1&oLS!-@H={Upblu1wEOinboBg9_Z(ZLg6yNmj-&625f$7EWqw(ohp=n-gjo<g$ExeE|S`!M}WBw`u z&dCe4NtEB<5BtRvLxLT-@XHZ>2tGRn7f;d0nw7AXU-C^WqpCWdGISPFaYy$FvuZUD z1h^Kq7Vufs{T@ETB9KxoF#ge789PQj5>e4-j}pN(?tLCGx}OjYYyhbs<%W^yo0lC# z?6vHp7TG8df2IR=GpCqVYms*BO0k``Z^wG@jm+1kbiV5FVr~i!!>HXpF2!D(*bMJt z$_(QKM1mOi*lBQs#`fth!hdo{n@Mm_%bs04RC&$m2EAnxKoshM4j*>s8T6-ixV6$A z2soCNBuxN~evmOeTkJ+X#DHxq*-_S|v|X^wnpM{<$spc*P_l` zW4ub>k#uqYeGMnh;~OLV7s4d-YMaIwR-R}*?#7GS;c{s~U~FS6LE}?@;_vOmy+1x_ zccgPu4iZV=&$~e$4f=Pj*eT3HKIt|-pOS%qFmPyEgH|`UES?fvHq`q|H8zhQg0;+- z=P1hd$Q%tsLJ2KGhAkFVJe(Y)_%zSyd9ysL8P1!ppv_E6v3U!Vn*nt_^~054KJ}hW z-{aO@Yd*Uii+MyGAm+$u=aSp2+7oMiWlvL_j-d?;8r*pby29ZXQK}b^$o-v zoHm5X3Wx;Yld-+>w`j0kHher@AO8rnTrmiqoZLLJ<<2T_QqI3=)+}AJ$(-JifxT{S?k9HhnH}TU$DVf-SdspHA~5tEQGVq5Y&4Lv=m)fw7=yq+d*VJ4xc!p1zfaHC=6a znc#&4p=}b#Q<8FmGq*6HP7gW9a$vQ0-WUhxK`1ubh{GD>FBY)b&L6{41qru~(VVOz zSaQgkPaZvPbf>MXcECjT`|5ap*ldh*bd_!JJQOtC?YA^UkvetazNxf{w?pa8_>|LK zXs*!SVqyJm=YwUU3$djKliDYz+qaV2n_s6>i;kA^PW?2~EL^KP8@&w77oK0l;I;?t z6S$K)@bt{SV+OU;`42@O{sDi61agKG*7n1g#q0y$nAd`R5X8R-V9`>bg`D%&T@;o7 z`MZUME43WZ&46UlPSB;>GH%N{1ULYY0%dDm60k{Q+C0Ky zUC>Y{kZphe)sNQIM4FX^cb}&liG|Kq^YBR1;A&P2nKbZ~UAGBZSmSC{Lw#UJ5fGLJ zN|u|92&TBwroJIN?MSXD)p4ciJ+We3J<+4BgYV4i3MH| z-MIoyjCXS!Qg;UvjxjE>lvS(>cL+Q zLdiOuIUva!O(GCSh-jQTCaIqEqDft?*fHOCXS|+3g1LL3US2ai9honc*q1%Gh~b9n zUJ2BjSQ@vRK}$Tur#8bkCKlvVR7mD3$p#Z`SQ{oq?OQ$OEY;k+EY&IAWZMNztGucq zT`BOj7;<5sv&U!l8I{6jfEM_*8m=GGFmdnATh(VeXAy4mO~cT}hJrz=rP7K%St*n( zoV?ppubmV}f@s!1TjACaCp-CxkI}<%kL=DZWe$YushHNew@p~E%>1Op>n8yYC z-HtZxOmhe}v(vJD;!$2(O+P6P6c&33p1A}xHw_D?%tQ0t`zhS_sm6H zyMeFMYzq|{y!DWS~PL^A?^8AGJ4mCPiJb}+fU*bFZrz)ukPtE z&iSPo-!Ky_z!_MojuDVftsapf?z3{|850JWGd=~f=103x#6ljwh{idK+SKsevyu`U zuQd{6s!)T~VZH8z7)$bSa7)jT4ZY&(fy&QH=}2p?R0yN)cBg6hH+g}qO+O<0WkyU# zdX6cDd>pBTU2S(I*Xx@koSa!P7Uya(=X~P|STeIevx489mz&v$BAqKYC>8Oou6%j< zG=-O2H>7W3^+YEdHs?eKhqLn=sGviF>Q!W~bc91+A5hoCM!%fw`{6U(UM1wXz1{|F zJVG2FE4L|l&8I5P(74yyWj+@cpYlt=G_s!FlGxHES8>jr4c`=UbMSS$WVVOTgqR}l zDOcPa5U`Z{@6FMl9c`k}BfT{e-y^z*l4aUheCC_t_Q7%O-1o<8W|`7Y3GF#s9-vcUvN(A@_B8xb}|ftDZo^W0i4rgU&D=d3qJ+gUV>n-yS)_eOC@}FNlRwdEIqbI zxct1ojW&ve4`Mz%^%qhqu}{R5WnYVT}enUb+yMoRIY9360p`a)YBA6?kB+iKY&&CcCaX zt$~brapf+ErLnyRQq&RC#5FqftYLfWBRHl>ec{1djW%6qnG~1WYg2>>`0S2qRmEwe2l#mBA_94h&A( zKG@sev@)BUT&q{Q6uL|GXfG>tw7ZtqUS94RlOtOX54cOE)I0om&imc|G)g7kHjrMA zt|glC%Yx0-O){k0M2yiDc`%m7rP+w}3?OjW);8xbI}v)h;%8+iljm2Kcl6#`rP`V)!BRci6@;rl1k-_`g3rMFXzx{WQ7rdY~A zeb5jlbThWN5FFu8T+%U8=cxInmJ6eU!99qwFs7wDYICzs#org@<3YSb4-8PggOOt2 zf#}v;?5)pca{)8l+*x!>rOMl-Den)?xYbeanex52oFBnvtyjG&NG-0O^7H%BT@z>& z=?;`Wxux7&q+)UPyJKSmc|8uYOZ`3QEjVM>nG|Op7sc4;!Ob_kDK_Xh`oaCF{Xb0< zr^R4Z+?fX%11`HarjT3Lx;pozg!KM35h-xy_y<(|{G|U!P(!cpk^j1hHQu-nOKKB- zFr?!N_^5eXniGsY+h7(Kmf*@eMR;|h>bYwdXCk*GH$VeS}mO?r7Y>(G6j^fe~n@ZJpVb%n# zc*89#L}NZ#``yaIx%Ld@<}7(n-2yoW?!FkbjSJ8og^jtQYJ01_v&bt^l7ic)RZ1*z z!V?M2)fjMvh%`;`^bcE^Yggly+(o83nDZg;Llnd_OQ`~+T#prSbOSH~@J@&p6F}2q z9?ZsT*3(b=E-5wqDY{yX;JfVo0?7&|8v$yJcIXH;ua7=&&I)`!9a}C^ohoD-Y`gF| zAQUIo47dAJ??KY11n5AU$Ctx|S=%{eybd(yN7UmUSo>3tM83suP;+HlxP8JV_Tyla z*^5%xtI%;+OsTU3O9=0dj#{0Ru(kaR?C?t^5?H}^c!XRU< zH8bKV%6Dp*VS`dA@cu6b;eqP6SoRMFUFS0AJ$f4%r#UqaA?_;d;r^?c$v-57LY&CU zlAn3>Q%=gNxJh{(q%ixI?|_89b*OgP>$uVJz2eDVf|rA7<4a!nf=S{q5icnR<`|}i zUt2JwHe=G3TW~N5+Z}TRb*kJ3oLy(aDSSi{9MzR90Kqi5Pp##E^f^qHbQFVCL zbRoxqep{bqu5Jd5X}0Z7!s=(X4*IJwVPmnEeL~Z^>LU+RS!TJdR5~V}b<$zjs<61t09Bt>v7HbCIq6Q>IuB+k`@fCvHl)sbC$fFEh zqqS4M*JL4(d{;q(iU}@AlqJkAOl@A0_*I})eiX!Cw2ByWS$D^-H?l4DfxrPT~tt0L;fUPfqaDsWz#bb~#yG`snN5EIOfV_pV5``GRY zJE=#*{&ZHv5QzWGVw_e-=JW(tj4*FXrrM8OUd%Idp8NJL#BB#c-0n<&5nABLx~7te zHfdz1;YAwf?Lv7zo~5+&DwjZcba}!Qnhb@3c3MG>F?Kr?f+(RW1C)!d)j#MKSyOqr zOxVWQ;P`qlpp*XV;edZ4<=@7Lv%5$~c3J^3YH2(XUMCe30Cik?OGVMVar_lHlH_B+ zfVnjI+nmzi1zgL4{$Y7z7Oy>>OXght_%@iKCLTc$itIXk7EK+;0*APs)9e{PK{ zD%FK}LM7+FAr{VA!M7O@>mk+j-C3$BzWSS2kXtt%-EO;D*VMt>+K^*YvYusmgWgk~ z#fydle*((+SM1wcr&nw0iY@p_JUL2$D^)U|9ojrg1%kYHg?A<^Qh?CSm!{ucCobr7 zL~PSE>l8T@Am#}T)>yY=MFSns`|16%MRvTOE&oCP_10!Q9v$M=TWv=tPF(3S;PO*~ z0rd62Jhj0ttDGEK!4(rai)sQHq{2FJNDT#ywc4x#qH55Z1RtJ8%sK|-!hQf=kC$%i zicdRwMLFrmmGU^RWrfbnaJgFZ@Oxc|%Jva;zXy;|+%Mynux%AXe)zWmGvlm8rV@w| zniq%U1(NG-DXjaFq@?Z;GNDX(tRPA^DicDbrOI@RCm~ViUF;0^@aJ|!h-f3EiL3nDM4Dqn2SIZxz*@1MJ*MwQ5P(&$0A*9+r>qPKOPNxNq zz5R*<@#)N~8WP)~ti1J632#f|kk^tw<(aeN_L-T}=sa{S4VDG(f7-HiR2c%#jP^B{ z%k}A-Urr;u#lgYrlaf!b_SXz7T8&f8T5%wn-+Gfkx${96a-u0^l{Y2LJ6W-DxMI%d=zSiAl3hY*g26GAa5`Ps2so~pdqGxK0EzL#i+ekK-oMLYnUb?lB$7Rr zP)#R28XRqeoS;>NC{)~#1|p-jhpPURBwlpk(&ap+WvWvu6Mnk?xw{qmaZgV_0y9=e ztd6j+eJPJaQWX%a@;)j1~=B*vM1!m3$!!kWwoyK*%p z<|8nc`NF$AwgA?(-~ICWXxB{vqLf&j?OL(kck7(ZzVF7fp#lr?HE4*3Th8k{U4{hu1Wfs4z*%pOzg{u3pygzPls&U3 zA14pv1h%QY%_f|)vjKh|_o&h()NnJ}iqx%GH8&QTZpUAhBIn%PYG0FxyrdQ%vyz$c z{iu7kXOv{G9~}dN_AAM&QULJHD;C$p+`nuk$C$~KP+(48iH%ZXq6y8>&o`&WLuc`| zD`9x+6ng~iW`Y;`{Z%T67OMs4)+!!xyWzVq_7H||Z;u66BiSDL^EwBav!`2G0okK)OgAdop7AV`s};^1adwSV&R+41iH(ewE)xU2qvXOL60GdQ8@lPnK&qIkcm6r>7V99gu87WMc44uZA}Gm7>Nl zW+hU#%>A60ws6SZX*vNoq+=LJ&WICxFE!h>uk1lgS6{8o*x*+*;7x^)8FgUQ8VF02pKeZkIy>f$aFtAj$w@ww=FyxJZp#)0uF`2!w>#4EfY>Dg*$MyfvzY? zr(f7rKx9bA+_C^fATh2XC_TzpAna~T6--IjzGm5dtD z4-)e({_YnsNMCzkaZZsbFOMC0$I(c7iys`p?a=kJ8=k-}?I{qbZ*g;Nt3K8JIp8dk z*$&#^ly5c*VLq|)yUl4Rtau*u1<{{**U2L?auaL$xiEDltw4(i_Ob;IvHH(DBpdsQ zw*lID9>iJWP?fbo;lf5ro$~nP`)>VE&TC6X=}y({E!yAcvVdY8=?hOa+{4a7bK?{e z^*4Xt{a@&5+V3~}zfE`f?aBTD3;#buy7_XdZII(1e1?oSM49$LAw%L{P#=?p7Sr5< z#V(_lTNC`|hcRiTszTofLxGtCfS#4E_s>_|Acw}&OCD=*24@{~%L?z!Zppm-lkJW; zqR~cT!&<5~v&lvxgq8h$@p|LM%h?!LBx;0lCOUjAnyL04U_$iMwPWyJu1j$ zpHZYPtO|1y-JlwQ%s4~IlinRl{P%T~u_fb7gQHWxXn`OG3W@Z9HdYatK8m8^SjiQ1 z!JOY}94xF6=zZaK#Mi%bVy95M4pn)Lf6{(5aDufCOJAVA?ceFlS(z>S_peE$Wm02Q zUc)+ZgC(pl=Jn{jfPw z2+%s-Bpjc4dI6{Q*s&prY**Gord5oP)6f0A0fsnL+m z-oEEJu_mY4vHMyQtvXSe<5Vf7C=>!S18fZR~$4`n3ZwU`c=3U_ePo zND6^2fHASLX728!#+5n%yOD+XW!6)0#)Qk8=@OrK1OxFC@u@(00h6#&l)DA%5g;H( zTU%LxxMkw$>DlXBJ))8k$?~D;AsW(8Dkdhz)Y|%vBl+)dSq&xvZcmEQMG=qskyYG| ze=7Jc9M3?mC?93bg$Dg9*n4=$BSCK@y#}<1dATD{GOt-mq;*hz`zY@%>?%HTv-AZb zr$XY15THUyYS|t{9Lot`Y3^Nao*u2i?phf|y|}w+BKBRa78YC@=vrKc0uCE^uZjBA zr(yn^7-#{scRn6Z3ktgD4hGu*jf9>smyG8-eiY*}B{ zNyC+?I?Z}ax6`j`oxOPsus4POy5%*3Wb6CgJ!HS{aYrzOtgQb&_P%et_3(~!`Xf#T zi+E7y_bA3D1Mz}C{uT47o^%>epfxl!*!?{Mb9`AqDC&G>H;VEnpDJ!aM47Gswr2uv zl%YhUe%*HxU^lvfF^YKqo6u>!$%Dm|cljQen?arCt9Tjb<2$z9Zvy1#fEkgj{KO0bL5Yf6vC9 zDi6|PFag?eH(!^pbWprluZ{ohZPG>YWP!Ob|Nrm{{&*OweDUWRpXg@S_u`|kY2?I% zgg@S(h>5$E{+lqc=|X3O*_Zm<4tIxShppz1yw0amU(DX_a^M+>kO*)xr%OLJ$liPEYG_34vr-4X|ZTBc^;}_dks?T1%XfnPTxkId@8q@Ybl}h*p6gc1XL|y)JgANZftbk%#UtZU z7QXj?9#*twQ^LYOylnL~zaQ%$r5xwWD3 z_N7;V>ue)fdMzK?xE)wIa}_A}>oH$Efhp>|+-qSW_(wLq^4S?xWjwE0*}Qy&nKKbd zk59xLNLDfGCbV+UV&uW}D4l9g!^7L{ZFCyZt(G|}& zO~}DM-Dx1ZOcgKP(go3=c$5KZcG?=`kV-q_G!yfq0!-)+(C;&k z0~$A>Uk_S)uc3|DRZf4bBicy5%(xcQ(ReJ%|M+EjDkS^`r7amwgQqe`Y2*E_ngDd; zLl3HHnQw$v>A&Y;WO`*BMHBjh&S5g>xT>)_f|HUj8T>qWC0BjHUNpu{SUa~Y;7Nc$ z?{Wvk&o2D?gPvwQDn!PCBgqwE2|2WED{?auG*~dRFQgMR2dB)-izCgT*NS2srFD#@Xnhwx{2_%TYevO%cV>yeD9f^q}Q4_w@_~w>d371f3f$LVNthT`=|=S zsKfv&4FgI@cZak}2}nqXbaxCPAss46OG-&g3=9k*Fo?9o&>_x(K2>-~S; z{bhgJ$FcVpKjFY!*Sc1m>s;qLYhxCmUT+CC5PW%RMiS~UoO996U5z#htL;bS?7yUe zM@7yR!9xZ|wRk}^+go=-S{j)lFJ9as4-ryQN;F$Nb6;(~xDhPD*(hUXWy9JUcgQ)v zvOF#1X;x~2Zxh|zy>8Ts9wpf!h&8ja!@g*qLC(#?Vyx4LRMNsf>U|#xSl6{X$Z$r( zZpVM#Hv1+{LV~8mlG+K!ZuQeyup{!-N4x-Uc5r%zaY^umU`cLw=0_@zshttA=y9eF zS%3iH#eZ6^$PsQe`K$LV83&tm)g^W1Y!;l_v^#K z_5qUxcYd+iGFitqKfDupZZV-yIP|2@>c>;_HpX)|+o#fF$Lkk?BZ)$28w1Sv*1ykO@&zk|3sxwtc!#gGQ4D&zbOoGRVlK z4VBBtu^q3hS!+>tGBPk{1M8k(DX`k!&>x{3FKBv`aHSHOygB}63gl}%4XW;rdAkd9 ze#A9;Nq2e%=W>|BOD{opZiFdR_;33qBu;&wE3Y|5&m~!PD=Vz5A-v9qUb~U{g>8K_ z^U~Lh?As<>7;ME_ZFm_ws9;a#Xxp|}IFdxwW}LGauOk&MbwOdes@GNhbi~t(-e~F_bTx(A6_RSrpd$jCWnH0`)wAieZIGPB{C^|@xV(~ColNu8O;KGLY)TS8x%7gR z#3qcV@Sb(g#dwf4j@%7aP;hR96H2CAy@f5&Ohl^Ane?%^CHe+!{UWZm_qu0KZaYxx z&p+YnkzG)WL;Y?xYlv&ujWXU3K_)n=2V;{>I3{KRsR=U8@F)?K3#=nXk~fXaaau28 z>pcg zYxqfH`wKB(wQq{)r~PGd^8Ny4fU?(KwwiVg!un;o{Kd%8UHM7LKviAr*#w9evr^O? zU2)vp2dT~ay*s0yp_D140?7he=D)2LOsdL_L#1T9l>g}m_{ButG!Y!l1RmfEj$f8Z z;t2?UH&(rJB-;YQti~gn*}BMDEOM)}-^y;V&6yCE!l~h)op~1pFEl4_M9RSsmmJaG=s~ElT(4v}7mjR(^Kqu7=D*o3wqWEz}5e zb3M(H;OOh<<|PDR6$`&g(S;6OQbrdByueaSC5oZcO?`VMC_ZB+4R(Kg_(%1ekpMH9 zBs>M~iHpzK1AM;@*&CNPw8_>v+LAp%q`hGsayCR_#tD=yiy!wx17)Uo^ckBwEw7eS?QSxFMM7dIu{31Rc^aUoC) zb$tae!f-1K23;`Ecynh3MLhZ!z1IWAvl*`7xh6eA=NbmwPxyLHrQVW#Bjr3;bNhn7 zl=onb+OABbNffoeUvxVh7&zAIVq;3b<&V%wRb&UiE)INW@Q4_yWDBntH&JS{k59!z z>3}i2m*t&g63b{Axi;`9)zNQ64xKW1lV1-zjsRmemYmpMmqme(~X9wr}yuO~a<+Cl3?RPvsQZ85!`l?AzNP-3gxM|1p%ilucL6{mZ~^ zhU>tyI;$WXXBry{!G^`Bilts6a)@{Y}kH(vu(p#fv#wqywqG3KcEncK^Iz|+?V9HlR{5pX+;^2 zP>eBdKewG%gh|M{1E-PZhplHIqg4GI%*GzffagDytZlZ_7{R>uSp7m!!UdP4tuxxT zK{|e%Vr-WFSajhKg44ih+@mw2ql+EqgUdCb88ly3&TXgE=|Z+JL$4G)b0<}hh=KO+ z@Zb9k>^s+Tv-uzNr#avw=$u>-~vVq~pjL(fED1Tcx zGj_0Xcily{{+=GbA>w0{_D{*S@89B_=B4bj%qysIRBKE59SBsi9F2eJEISp>WF`gC5a4@Vg>GdFxM8Yu@`Z5=HVoU}rEOgJVRz5w zxpU6j3^`OO!C?4)sBNKBkUtPNiE${0X!-D{?`8ns`*VBY)n=GBLFV@_mZj6Q6>176 z&uLqKIqvX8yKRO!wuk*pL+I>JgJYeZuLCqR9xWHtvn*4Cj!Y9O3e z0_5H%!kM_61Kr9>>aw$UGOeRiOTC0CPcf+|fZZXn-vG?*&AXNh12S7dj=jlQq%m5= z%cg3;ed(4iAFQVt!R zuF!r{l1&%@2;|&K(Wc)lNf>FHt!r=`V7j|1$p$iwu^FLIvXAD}6f(A`{<_ih;3|vE zmP{Z^fO(9zhzf5g|t>oxlB^0KjB4S)GQcMk(dNAcZMHDWy#e}w!dAwc_3a4<18A~uH1-kyl9ZJRqZ8PI-u3|Y=~+WB*h^j7xT+@H zy^8Cg_-=63z-#Y^g!kfd_#H|8Cz}bIm;54X8}U~~;C;+h4`-0Kl-!O?T-;3oLh*-g12f7{rti`)1?g{HS6qw=-HjXQxm60*5_7u$dvL#&Y_G%sm zh=Ok`OyeUfh`dhExP$~EGeiLGJi!7J6~%n((AMH!Z{=8hd_%w}SzMbgUDvzYWaFx* zE^fqI0Da69@NyO1L^Os5aXWKG56>O*8}-|jc~bN3gu&VFe&0pm@s}I#&boJ3+NgD$ zeTh-2VO%1MtyX82T41}d?n_7=#`OX)gkS%2S+%vbSuL>I(K-k$On5ePU&_gXT=xs@ zTs69`BqN-~7Z?Ie4H{AS+IvHg8MMV8%KoDDn)EIXD6M^^D&hLc(Nz@Y_$#U@mf*Z` z#r#WSBd#Q6fG6Q`^lk}6h@T(7yY|8Fo|H^r1zG+QL6E`FmKB@aXjIWN12tn9$5Gbf zM-QGv@w^i)KNA^d2;U9s_`^M`GNh4M~8=}Uk_Z}9M1cK>p11-#A zeyQLwf}kb$RiAun9LLrLJ=CD{A%zGl>wqfScehDN1sBh0EKIu2Gwm{Gn-`2!5OPuel2b{5Z*gI|$|LTG+Hjr!O#2s_n)E+%cIw zL_9-cVcRGMQ)2RsL&hw36)_mHHD$gtsyp=2`e(H{P5j}#81KZ_`vAO`kg)83!L%vj zG{?nwhN47yZuHoS4duePPn_5pMHzbh2*u@Sf6wD?=PpcZu8!~Ez-Nr?KQ==JO1|eR zZ|uk%sSVGfuXms{)lMV%Mk!HYu@74>XpMhqSoOxE0%V{62R6z(3$2wddGTCM{&|*W zRl#GdqHBOx=Vlo%s3{S_{8&hUmL&;JzH|i5HjvR7dOqn-E^!6L(FWVat`OvHFPnM4 zpzzS@zS4>^EB;g|KJ{;M?^!_3V_+t1jAlf^>BLgU;hAXF2wor)BA$$FwN+xO|G%JAGFpwQ8PvaSp~ZfLjmVjUQdoV4C8)@z{#*#V9XjPgKanR ztKvXppWBz=(vf^6SZ8Zn9C?MO$-#9_6HFQq)*3l$Qn>E9I)nMB7IzU!H_MEJgUc<% z_l8U$5jtf@U2>VIP0nck#m=aW+6`@Bp(2ydFhupWdYNuN)lSmBH|-Fjrk=WSnAvgH z9I2qkEv$v_*x&JX>#o;XG1rtA-(w7}vR7 zCVN)KzREjl*~mmnLWoL1g=&G%Z!(4nn7AAV@jH(C{c-HQ6{9xhX{lKn%E5{-P-HFx$iSa}VoLBCR>*iT*MTh~qz+>pxo!nd*^8CF^OJo+?xLp;u;#h?14 zM8Cq|(Qc=epC$W5?VBuguqXb8aw#P$mtp91@@i%o->VKN-)aNGD@P5ISG`bhiG(t` zFXm2hyO?Le;zl^qvR(fIh^r{D1^M|?mhK;34iSTbnC4k$qlW>J--N9PJrBQIkNFD& zQ_m1kQ|P7~@+wy1EtdKR_rcVo;UHs7Vt!ugzQN9S-Ob|7NH7fv1JGi+ z&b6z6T)U`8YJyx8`-npD7Gip5I3PUZBWlq5G4(VP>bomiJi2DA^eq}U;u%P6>O?#= z6ghy}ZjE(q^IDozJ3l$#5`ms_@z_kgIY{RYFclJ>q5Xy@o8WuxSVsIvW<2nwMMIkM z%LfBiY!_;7AYyO_XZQF;nr5PBXMFFJZfIw@PZw8m|GYd}?p{5%i5HHUL6-Mev$SEF zknKBdS>{0L%!ApGEZ_#*JJPE^iEN`MxZF>YQS4-uV=8tOHY+=s$vaTX4Zh*&*w>N= zL(QG*Ii>%JrhJP>7gL+)=Zf6~8l)T|Xrca#ZBBD3>rDrX3D^_M7a#%JTBp z_<(%G3Kwv|zwv^Y{D4j-`|aYplLPM?u%9Tp3>qi8hE{1q>O4(x6J3eDB-E*%nrq5BTH8~bR!gu z9Oa<%hSdR8Sf9g&xR1M`t?YrCz)Ge#v?b2&vS-`aF;G6y9GSXyf#J~8m^Ib!f>T!g zip{{8iV-t_c4L$&x{c4pB_b--a{YOtyNh=(bzr!;f(|XH0joOmW_i<3*OJx=oqs7iWPo~9>r@!fQmTpazB8a|IL&obkuBbUPQ^Gly@Bg+u1?5RX>Lj67Mv<>4Ln~1{<^#adQw&y-jSTv@ZGf??^ip#GH7=P3IZoHs7xDPml0K5z)A_j(k zLzf;QHCi_sacnabTR-X_l8||VHvs`=YowRAmCMnB=(ugVSfB$%59HW9H#)$JP0A@* zB4{#}ZsA0G$NTdx27Rl<=hB_Z$_Wp3NU4a9KP5Jsqn@wc|R+Kpb>*W~FkICc_)XA&e$i+6;pyv~;I0C=7eOPA$M@KKJ1K{`23KH`DJr8FeGan;xjBM-)y~M1fQuM(Yz4n98eBueIq_nr5!M{(F)EFgaxIp9UM8YV_J9u#dwd#HU z5@S$pk5`S8*n;`7QJzv7*lb{3pHxqPzI@mw?|lMo^KtV}4D5=HS(f?D7-}1|BKJo$ z3Whsc$;`7XAPzf@WEMggK?2u&uZSby!3>Y+QzrX5`?fE4&FX5| z%-DgilB6p#wN@2OlMOn(Z1N$g_`_+;FwP6J_Lb_ zl4dSWz=p@xgo&>f=iWv3EA<;4A4C+cB}ZE~8)&rLNVcMR_T{wS6r~s}XF)dAv>;w> zuA5y}#qTr%uMw*It$Dvp-^8o;ykW}WLCJShTPiyCAVKmW(T8G$^e=4wF4|I2*Nh?> zoK^s8K6v(s@l4RP#2rgadsYEMxV9>Glwm?GmZa6XKgS#zisg4pQE?7~e%R7Vw?p>r z1=FBSz)gN4K2D%L96=mXNEx5H#VDrzDR_lr6Ir#CN%oDpT!Sb%RLOPslX%^*H>*{~ z^~=h;yhkq;<4i3y7(nJXPK<4td~sE4|LxYyEDvg-Vwyrn+W1azp4^ULXhX_&a%m8j zloO86x0yECeorJ{CzioWAO-&?Zrt{g_SYjA*LbG6#M<~|azyq9CD*SC92vqm(=pM| zOMk*zMNe=THC@Hsw{e7KZAH&F#RLOK4Q+jVpHdB;e|#nt4j1mSXX~iaKAL-XFVl4Q z_8k{ZW~$7NW7I0ZINPfKaw-Z49Q0dDKpg2#v^A2Y3o;eivI`liMfE;(xGZJPpNe zW(d{TYbG?(jLWTjv;(a7OSbZVQ4Nuu&N_%8psy+e_fJgAveoJxN!ZqcwMzYhPiFUV zI~#V>qb-$Wq~{zQ0|vx^b=?fQ7X?aW-Hhck6BGyb-h_mLmdT}oocZMfw8YvbjhEjp z*{Aw_aoIypJ%`k+8$CB;J_*5&l-(%ICk2|rE+rjXc0MVNx}mL!2hX$qfv|VB>;{Uj z^BQ(GTG`RI4H_{zRoLJ`S>zI6Abn#KxrX1HMiQsN6>Fa_s0s5hED8UqG} zk2cOW?hbZ@eV zQdSQ=&RI+WZmysJK#KH#7^rNyxnf7*9G$!Ild()V&gF)Z=y*IK?bq^;>_~F0 zsI!TayDXcsCz$lf1udbQzYA{ds|E{7$nLA=paNK0sLPt(cn}TJnQSj(Af>^d=gT|R z38Z!JKmlpVs3oZ(NY06z_SLQr^Pk*|#{gPD<~dyrm`!%s3Qb=PYC%>pW^FUqXJ4Fr znQen6DSSEZP2tt6_Zx`UaZReVX>{doXAlGFLh#rojj2ZHIFr+CS?SKG!95D#NB;$+ z{z3kDEC)7?Vj4ET0dP&!uZrd@riQ}i?^zC32~tk$38r4$x_5Hs+{c0UnY}}&-^^BQ zG*EUw^&iKiB+KXekpbkaF33ZC6ssJaw&*xB2mYYJGZH|8+!MLV;7T0##1P1*rA0TN z_271|{RFJ>OYxQ0=Y&5QDj%PK=zyI|0Lg`TPDvKzZB8abL(lV1{99I*muW2sOrJyc z|5b*_|7$2PINN^uKW0Nd-6MrCFm${JFf`i_25$Ed@V%kUtNxjbD}LuC`DZ|-dMQYx_O6@7e%;D`Z%Qr_Bb=W-ep;7MWVjPZ*^Eqi+QUy;St$6{$;t* z)v*tGjGcD*;L(r5quq`Ul}(Lull+hPlP{_3V?u2&Js znnU#^W6b%2(90`UMg_~ew?3rT#XdU}uw&+y#4u1+m|KFVF(k2T(Wx7+zM0(f2+gSz z|KO&?I*sqBIb;R%(;a@#!yWg{FWfrAHi=3sY~7ynC4CaPFG&FTs48svW74ikk&eY$ zSlwn}fNfVv-kAu0T&WfnsqN494V`xZ?e1}tOJ*krId_{c>)#ZSZ*&z3>Jc>+2l&=} zOp=r>8bkgfv4;0xMv}A&p{~e6enqVYH6k-=={7NvUsM$K6`}4~}-1Dwh zuAjlC)QSS8D>J#_>2dT_6EW;8_c=&5#6PEw7S@-WZa=A#kZl8@{ju`)PFhh;J1#!D zPi)6NP|4Qm`vzcl6Vd34U>in9={{=HQB#10(dRI_|BiKli&fmpN|(OU>{bPz$Fb}h z=(AtW<9)u#=I`8p_1^V3ToR_6=3_7wCOnQ2sf~0pu}Rf@BCg zk%$iB`O=Cka}SpPz5=}g#P)EE{Q>_do@8`tT77RI39$k+&nrd|X1Y=Q`>@PTL0@z_%4b}PEqG4))#{-t#{W5iKpNfdFUj{y ziiSaRUZO0)HxnX{hKd!dZL3D)pU_PhZ(RV2jLf127iQp11Ar%2Sa>V~^7q0KO|;qU zoP0?~JL`-?=pI*2gwtBj?ZdFulG1?OQ1_`&;GO1aEjvurs!lNh1sne?mnM|1)zbP( zt0TaFXj{PR6OW_z`n6gM?zv(>EN+?+=?0B#uiV0sx{1P`R`3Mv(NFF&MwVK3#RiX}3Fd%THpTDbw6l88)nfk7n{x%HM{5@0Y{v2u z*2HxOUv$PVkY)OAiVdhvDRc%N2qm~|j$=_{K2)gYrf}%M$wg(jqw5IR4y2rJVMGbO zbg~m9n(p_3O&_Hcu>5r9Zu_K{_&W13W0}IQ1r3}Mlc`gG~7WBy*AI0{X<*; zuP}M#AP}k#!hTU(`?- zw3r-^%d?TK)-OO=Ko_+ZU5S7uk>_-l5awxyD{s(v>WXY~pbBke^=er0&45-K4^+FX`#&P51xn(N0;Ds|Ed}E zX{2IbK3)b)^4rh|zzm(a=CnpeW&%2U{Kln2(TcTMB2<7*^t;;TkK?>OseKfL>ap6d z5pvY}qMd~!)T{Ynd0ysF(1(4OsoyqcC5o7${#(f3C6`L+SZ?}_HBRQTqT z)WiKZ8T{Ekoi;wz97fuUZWa(SJbLE!;jLU3->KYF=dr3$ZSK!Hs-1)`9HVe-BX7!i zR>=it`NGdf^d_CvV}v}|9;n^To{7^B-r3!8?N_xEsb`+=>?Oa_PJ5VL&1lrk>m;TL zzmaDd-clH1bk@_@j<)9@aff5;d319pF4bi%`)mrCiP|o6=q}d%DB5PK1gMVAnjO{T zQWXwt}apvDQ{Odr8qeb3(e(dgXTC zF=FY9j2c~ctC~Dm%m+ub9ggiO%VkF>L;U-x6b^pvu23nYu9{_e6=52ps(ARLR);o@(|O_LoG-a(JeC+`9Mx8w$+YG=QBk=lBuw^o{E9Yz~My z_-Vi5PcwOc9MEBQVH0%l33z{JY9-nl&3+RM$u|dz@nPy1a+%F9nEH;fW%bH!w57Gq zEcaT*2d(Lu$II4)S?UX4^P5D!m2OA*NiH|}vS7=pUD;unX!NDLl6GZ$y`v5#s5(-p zzs10?KA1r5Uu3}y{WD&4tW2Dn6l|0EpKTbKtr(@#ZMYq<^Q+o=r4GmONDY=bAJoAn z9M?|wP2C5-E|llYC%R|W+x5zMR*fLrdv4@trpyDa#sA|P$EM%%2TL`)dgevM&x8Fe zhBNJo-8*Olt$@J-d)8(sRN zE>aaESS2~V-k)s!;!Jt*yxcie@(dM*MsD_u5#&$}l|%IDbR&WYrAzwZ9#NBTm;MRz>V&@M>AJbli#9}R<3-He+k{gp9 z+SWsaT&==~D{c>Qzv|NHgbAz&iG^ep2QMG392r#pg6PoR$lHQ_KH?B=4*Qi}6F|nk zbh_q35Tsq*yLG7BwO0hb?|Z=;)~cQp_9`x5HkA`_-viAg9$f6?z~QCi+Rn7t?acx@f< zNZZ$A3UVF&QakGS&cPc`N5!0u17(iH{&~Z zWT6=nDDz-u4IV~$*82g+n~=@L?M;n6VGIE{qoej!ck^EDVRE_(PV=ZeD|W5JV|IKY-IR66xi>m!8$j0_rHVvjH2&!c)31$e2!+S#i8bV&8nG(jHyBkLx)XZI3rmViGoT*3XYftR*O0Y%skoRpGrW zc_GyJ(L4KzUfi}mpxWH)Zd8KS3KkjhJ%M=HH_;{;0q33bHGt9VdnTkL zUTF7-lzdmBO-SyFvjp+?Bke^OeW{bL!N#_1iYrA?D$CX>Mb2F0*SAszX}`PHeo@By z(~@RqMOVA$>B}inUvp7uqH#*);i6e`cbF2}>?sk4FqxK_TmD80!l9P!g#7bXNh|Am zJ!Pfqwpx|LR%c&~OS(#BEbcEEAu@iH0D%Qx^uU(jOO{Mdo7vXxKHAg7yP_pD?OX5+ zIz8&1lLmSWWQ;;m-1f#}oi@DJh(cHVAoI8G7Ga0*?!Pig80DE^kK+kM$18igQ$I=d zT~^(C<`a&Y%x~1MJiy}1Q0^*$*Y@m|_nyqoY_&QT6?3 zsv2e6vt4sd_rdkLtmd5x{uu82il;dZKpij&K&#xKqcZ+GLE1TUL38bXZXq6~u0`j2 zL`E<3($vVCVk7b>I%N-j9ZP_;i0fwO8|Tz24z$N=&zMF0eKuF!zbIko)$L;jEmWY8 z$n9zIL7x1{=+D{73z6L)FK_r#Ab_p1RU87uY#qy=>DuKt#ijAOA~rzU4$s*O-Ylqu zs3YQ)Z47#{WT>7dIh4sB`*41DY3#_-skQ%{&l$E8`gLBa@q~2YH*<=~+l2OKJ^t>O z#CBs^G0)12VFxV1b8j3G6t+5&iEmN|p`Gi9ACTm`ij}wNwBi&oE9%geObvs|Tdj<4 z?o`iE)gSS594toL7N6l|e@^T5)^)GK!tin&BtLO(zGtH58em>4rKvpe@ik%0U$9b? zj>>%)6OZlYFW{N6zTB+J_qUv`>DI!{OK)Oz!4E1R@>A@yjL<+b6qDAB+X`WTz3j0N zj}~2{efMp|n{(zQMKBxU2gXdLyFmJ-9k4vbZ<)Hav{>Mi-B{@Qv*qzOLkOZ*%_g-` zZzfB5qBjsGX!83*zb{`D2``cOc0m6PBbc{e!#oOvjiRCr^qI-eK1>#Urw(<7HfBcrj+aSy=q#w}(hSKI<{|JvS2C z^SMz@dy;eO5nqF^+f-Z7KaXa5$BPIapC6xhXrtLs8sA$G#XtrsYp&u&7KY!qjHm+G~PuT z@2$P}1cYlET@LecroLf*QO6iJJaQVv!{+MN4oWj3iTcqP!rvlp z4mEQx*S2N-xzgfan+*1@XE;wDY|s*&0Q024z7Kb%Vw3hBiDvDiKO+t4V8piE;g3=*n`Aw+RpbQkLtcn6A_SjU(cKW_dVMx2hDYLJ%6yru`*s|`R)O>Vi!@n zv}k4hFvu`i>I8QG!5|R|*fF2$ zD^=lM{hcg!1lT_ZdDylUO@FI{CIu1--I>RAB6bd$k8Y#I!{W&zsGlj5FpmTO?@_Yv zwOYsZoBrpWAAXmrI1gZGI$baRem96$DHpb;oPZtVg`P84vMr#?Ndi``r~!Kvj=3GC z;qRKympFgEyGOb+q$+8yr0_2IU&c5%VSHA8y!uxGpsNXHgJN_|wrsjgv(h|G-iy1% z{kB@EUgoCvNde&A2NEasLcYfp&NxxXM0UNqjns2SKm+9mFnb(sh&LHdwEXH9&5gQ|;o(BVNAQz@?p9#< z`Pv|?4#zH89sc%NTGYS@GXf7UXl19OoH~;~^rg05)Wn30(781$e7n~s-+*&rRfKUg z@33~ck}Ae?K6!%Xv)0t8ctKW7E@oTJ?XtqKy!$>pF3N9&tSx+Ncd|6~;wyA}O1{`@ zQwOy!VYvrsnH~$cI7AWMedn}3{N$CEmW5c8StkLyadnA#6VjdwIF-A%HfCQ`UL-}J zCGP=W5@;&^nLVv=kB+br+*ltZ-e?~H<(!vbJ{6`ssYVoRg(&s5dv|x?sj**? zy@Qq9Mucui-^H9y0BHT`92p#Gfaxd9&8>Xs{$U#+%#>a}eR_0SA-H93W;Da8dJ(_S z(KQ44)*0TYYWTEWqO`gRcO)TZ>uF2uVLt#mf6%VDEWJM&z)3k7P_6X`==FOA;`Q6K z%Btt{_ZZn_vxv%@2Zz(0)##>^uC#D}AF?pnwz67|5act`tzMB#m=KiE;Dda~dOP3x zt4d}E65>&-$QL-?Y_3ot2+f&+i{ixFWKv< zKsrPE@f*JFV`Va7yRSECEJpa`AC3B->cOQNrcTNF#r@WBbmM+lM-LIj1V?)4Z$!@h zpcC#F36XH#${psbB(b3-@9wdC+246abk?Kqh;A~Rmrx{^QsP^t6ba>aUBb4JS=ni8 zv`w|cz4aZfRVh(~RWL#g`hjd}FyW-U8hwykdbTJhU9vJ(@M(V{p=0GykGbAfW7V2G>akCQ$V4+|X6e!=Y8 zHL)fCA^CKgRFR+4B4$GS%%Ie#E#kaCb>s2;4ICpb}Gaqd8c01ux*ig2+{SFwhEmYZ5 zK)HUS0VN|MRPpMg!2{43nCl$UK`xwm*v6`LsPvq{>dGNu(xad;z`lx4~dze6273KyKbiRUiUw`6hnFSS+~Jc64y-TYckS z*069|3Q1PsA6s$O$e2l5zwmEaV|O|V`?bTV9h(H0*w*gnlkGeuU}EzDEA5i6OKsIvw%th z?5BDQ~{ioveWA zkly*Q(6UC8WC%ov=#yWktgDdr;=cm|?PS2~l{~WUH)otNXvyt?e{^Mx-RZ(77FIKU z`YQ3uYv6n2Dug$Bg}B1+=-WNSR~#`GgodQU=f&PBtxD=8IgEY9S-hjKR#2YD?hVPJ z$cZ_&8JJnE?lJ8X$V~910WDTbunL1$JI9CRq`oOvy$bfBi729TQvlw2^KEgL*)oev zcE%k8*+wl>VcnzR@M4r&KqdIv_naRLsZJmfax|bH&Wo2D&6kR2b#G#56*#rCap*G2 z0%Tu-bpXH9EyDQ@Eh$)g)d%$7shN|yw4gC)AMnR2Qh^qEWd1q%|@OMp(;Q78U1ky!A4ae~>ds9w4?Q8A#;2&NQ2)FgXy*s(ACd1lln)&CKOqb_O@SaY$rP!+VmKE>2xEba3w9>f-b+Vqh+xJ}Q~bOT7Hw zdw2WlOZtg%Z@C0yA}sXzeF`awD*HEaUjxyEt#78~$=L?oQSRU)*-hL1Ipe%DHs^%| z9hiK(Jg|g{fVgCc6a_@oq9H8vIIysMdLvKumUG5K9ih7dAR;lntMEcd#bxD%rO6qm zr`?rz@ZTi?P+YxwbxwobJwvmb2_HONGod2J7x2D2mffa&T!J7ZG!VyKW^$yrQPw7v zHv4i9vx$)WG7eph8*a%^)=@rFiA-6?-yg+Fog%Pq)@Q^E z<{lsH(AC7&gvExtH%2_)fVB78EsCnxD{@2Oi(Zh58ow+0h(G^ZfrH5}1I`iF^7*Rkih~PN8!*bfuG6G$80qD4v4H=A6znw-U~Mi9_dPEj?NN?Oie5)y zJ>lA`$fQ4RgABV|())$pndRtOuseufe!#uoe;2&{JFsQFt3Ol>QW1BLiSlaiKZyt-u?%0In4JDee{%-%weE$|gzoII0M0 z7c*_IV0GoJpD`+y*fG7MRY`l4t+7w0Mt7~B_}@2;Z~}|*@r7h$(D)vXXs>Utt`>U0 zgAxGFkXZQBaSlHB0~0G>kRP@3nC8Q$6=KmqLrs{I%}A=kqDfGi`CbB@Tbsu$4}g7V zUn_O}_ve=a?3klXat;G{$USRc1DV|splP`(1wLtUwvSh$eDD$^d>gT1Q;cDl=Qh7xg6JHzd9B6 zH0v(Yl3cet^ABU?r+Y&hT z{FOO&?R9aU+NOc62Cpana4EaK+vjJRqL=3UoNXg!m~X_2lKYn3qs9kAUy`NDbhk@E zv&x)`rTw+|%pZnsD^}L?1o=;Lk);6imkZ0{-ld=RW6?jIIP*2)NJ_5-xBkM!{_(1> z>);cd%3HIXO~=xQ1c{h`H8%P#roNjTWKB~v6?^x{-To?-VCPGzJh(43E118P`4H2c zP3rNkywHT9j1QpVjfI5jSr9H9%MBNrFcM_j8dEJ`Q5Smmf?f?tIS~h&>^9EX7Os)C z93S7v`D6~lW*xAIMHdIn8H4j2X|(pq*Q2u3dju=Qg8(dGZ}*Fr;eBYkFGjY*1!?*I z{k{io>yUjR2yw<;77A0J=TnP?U;bE;N-Y)LyKCa+HIIw^?F2G6lW)F+KMSZqxLPMQyw`v5; zMj2hf2}tet$?g27xoJJYb_enV3uWF=XYSaH#EY>jnCP;7&LIGf9(%Cb*v4hs>hJ4F zJ)7%v%sD=5Msk(=i8Uh|VzZBQNRa?-Fzm!jazau(TBfFk(_MUYMhG4oVQ+)5pJ|HG zs*LG`8_rk`+B(1{Fx%al6;k0}1572Uw~+~3&elM+zQk8kT2~77o$fXHA{vBz`B@h; zItjP7@?KcIfZqQs*<(YaXS;tquMetmC-Q~mlg0|HFY7kq5=;6Aug+e*tMtBD_~}I& z`@jvF&Go?Uf@GQIDEp!cC~)7z6w9pUsuH20;ljPu)h^uugrtVz{Y4KKBWzqJn{17i z;R6$YC!953A$2gAplvcM^!8-iOkQ1PLz5N-_N0vVyaSmYmejC*^)%CzjTire^snHW z#@lVRoxHd7__tlE@g@r*0FH?m>i=Tzy`q}j+P7Z|0!kO@9aL0$3B8CQs0ausy(7JM z=>pQ5l@6gulimUb0wPVM3nW13EkFoW5+IcCLDzc6TK~`YVDB;Z7<=sfop8icGUt5e zyytyi*Kab1a*D*!2*d4wQbiZbku{p?sPW0QKt*c}%iQEB1=k$rF^0Kp5z-6=4ONyk z13$rq6z{;&JH$G8PriG31kJ$SCG3zG8hKMtXfX}$BO*WFF*MwfIaL?mSXzx{l3$e9vla(pE{y> zL=NqAtT3UosadomqjlLf%BKy$g8u9Z0w6?u{JH^(rH*Q{i{kmK^^1aR84l}(V&{jRuCeWDWFi|2o8Y<&P)XIRarp2H^4td)AzaxaQJH)IkENbDO>s_Qt z3Ywf`ZwfGSD_Z)y@@7hUC{Nh{qu0NceP5Z_YW|?V%2%zG(dgQ6(K&HYR%Hjnn0jEd zsyszE=^F$;vHEO~3bC{}lO=6o@&{RBu}%euY~gb*Z&ui=%Z3#exqI#G4X=R)K`#-u zZd8t_(i5PV!e*I^2JDG*p71eRa;4ct3=OffI=nY`4Plm`ecH!QDXo}>zw3(f@`4ijZV*7}sEC{=4n+z1io|G8uw5O7=kkw4JwV9z zLJQJih*@ z=_2~)O>_^RLKP$B@Bdu>n1_q84`6G2x!K_toLlg&$Dt#>+ZP!y8F#>{iS{7|1f&h{ zEC#v$Y4p91Ly%0&aa0LL6fxS&0@=#~H$@kLdKHa{Lvg zl;kdlwPQvvjA{G;s^<$r_~r*1^}YVum@dlZqoFhe=T&j_XuC|J&uuJZMNTUZz)m7S zMvH3Kb36`l2k9V~_#&7T%pwH8k7xMy`oP3_GqDf{JCL)5-9(@s*qa8?dIX+~*r4By z90qYF`LEXQgB7-Z^j`d$vcAW3cvT+C3O=1x@*ifuYG(0SW4+&=8%vrrwL@mi|nG=JI)tCNdhm zA}sF(bc6T6RyOQ!VF}~*Jc4h-y^(MaEaM5U3HY1O zYV4gJ#IkqEn6ja3qo-O=r%cVl2-)?ZBP|#hT9`3hYAfBhIR+i%wrDZ^YPTIMb-f46 zC~(SBPGUCVlUXOX(>QN{uLf!=0sOt2pHz!CT|5rTk2QI()SVO$d_49a5DsJu47^CM zJ@aN6wfGg6u$j^cXZl>fc?}Iq4WdA>O65AK8dL{+hg+eI3r73}yzj{hJj-)WMN}hg z)ZXE7t`NU+JTEl(RaHTEzIAP|HH2jZHDpg`?NYIp1U~re4H57#2CrjmPywY@g)TPw zrXDK=+T!bV$P@_wP9~Zcx{l=KtBPZiPpD;nP*H6cD((SIJ84d z3BpCms}k$5@@lb+(D4d^=D2f0a4AV>nOi_QQKrJq&xrr?@6kjbow=ArP2W{SXHNhSP3T1lOh^ZyUdeiNn*Gh zDIGVwFV!0e|R~pebC+kF;0vMWNh`?-tR5-%@*{(SlI5l_r{^~1kh>J&S9#Jlj#bmUWN~MS~HRQhWjYSf+o>tseuykCy$H+G&nff*r|7l7=kspD#k|eN z4j-3q$%=?Oj3(dAXyG|YLz)YOrw zD_#1Zjr*LekHzepN>?}7$Br3MJ1iUIW?F58N=BPA`4c1#d!N7UmkZa|ZCrD{W-h2* zv?s6)q_+g(4n>?u(3!os_xq)+F5(da^lJ%4kfH63+a76F6F!iG5!S0+>j|61QrqK$ zL`VAajgq5{kJn(_$ndV*l?`;;mz1N&%fb~#5SOKyw(&LJP8-c1gsnZJ$~JwE>PZA* z#GJ5L`_3H?ThrxgIn{bFX7{0hbf7fyP(26VFxIsbDYh%AEU|uKu3?ZHpQXx_rt`ZN zgaCvo4BHb#L{Q)W zI;2*4=fD(Ab7;=C8|mJCO`vXBF=E`IEva_IX+P2gMEdN<4a^A~Qy$_8u^=F@H&s-N zG>UX1_3ZW{w&=36lwYPLz|ET3oy&jbM9=7F#w^$nYDNDHMukyf zA#s?DE*O?jg;M6{9=GlOI?_`>MyOA1e4$M&zDgsr$9K}7kc`YUcLpM7Ntc$S$JWh~ zRIo{siEpjSvd3eHe!Lym=A?OEw09^{K2GueDFsN^<%&qdH>srj@g6usS}NKqqSy!7 zasG|NX$kIe=9q~W*dG}ersQ+iqL7?;9WPmkEATxm@p_&8HItB8n)XqooV`D~9X~k6 z3c8tDg2|LO%7Ax^k4e@&vU@-F1|(8Ej|AWClfRK#F#B;lvApA}GvKxdsUd$= zhMV|4BNAF*%>?GtePA6VrzP*20v1B~-+p)4GzK@Ea*i`sn(iq-y>~ZIpug6;Pqu;6G$6=TaByJk$zi}{sHE2p~>%C|$t)iz@@kY&dvU>l8Jk*FkNdi0!~@ouH3hx{|kYJ%3z{m(>|PKwcf&UX{QOjpU2k^7&!-_Vmcna5Qy@djQbvf$QSA`Z>B`x(J= zR)3FP@*I6L{d6;NGSqBn>v)pXyH6-)N@2^w{X+6RI3&r;(uy9Dhi`|%5|$M_SQ!)* z8xU&iYzb741%R`>*NME9EfK!&d3J|g>#I&ONKjM0C>|!wt2Tq0RIzLr z{3w0SouzaY&a(h|opC-oU8we}-DItJ3QL?}!!;e$QCy-@dU6?S`C z#G(;hTB+Qu@!ZVn_``4sPW_Pm9xSVmPRP7ZL%7Y&G7E~hE9mbdmbLLUQ*&sg4;q{_ zKS42p=&B3YgNiN8zY1jZ*}}ThI8x?fGq#+OR$bH@u}{EfEx`BTo&9Njl6hXj7E%A3^Dy#eFEeP>;>G`;9ZBHeZ{MQ-#5W zNNWVA}AwNf_c%H`B(jC$lS(*C6NLqhXn`^u+&g`K>%;RnDQ`7X@$bwaWAw zIjO?f-~xn~OG?PFHT<47J`Gm?8i0UQE;D)5#Ik9>(xJx0*88+hGNYS4ZBwN!=c)N3Sp9Rm|aRoVrgdF+b`rX4tVFX++ z-dLV5$x^c(F!KekRV7JL2E=92;-m^erWusOD<&7i7`c&Ros-;Uvg2JLw955Lp46-d$XlP1j@u? z0DBw#`4>=bJ${gyA|kIh06eZ3X#~+e_4Rg1wwCrNeb?{xZRha$x_>?B(1`chFemKA zGPGq7NMa1X#)yJQRgRPQHID_CPBQ2xH@lXQK54juk0xkhKX9rS@17BQ&qrP$*{=|+ zyX-HJ?8{J}Jk^{(U6XcDXe$TqAIR${+u_9|MQ&p?delF8T_e>sNT z(G44<#Co|%Q?2mw8>HBewcpZ}zcSZbSBbnoiN8V5EBt7`FB%*1Ziu))N2Ss?&C3JH z5@%rPZe=$s&1Bi%Svthk=k>j4Bv^;}MM1qHXnK+;eS+}gLy(?`zgn?!k&_(PPOcVk z1_p&%zTf8O!Xdt{6(`#`K-;!g0`7l^c#Xht<%x#{8fk-$(bT1+|23WLAA2gzBhYACyKg;6yW3rQ6AR+&ug!kgvF?MBdPlk&jS9x2q1AnyTg%jSs*GdSz^)JWicxGTby-kD+dTNRmFN$$UD zEB(qvis}m_)(l+xUF4#m424ZgH^cgjxNWldFb$h*$H`>-s3lS5{PBHn(fx24m;u$&#E*tqZs6T)-mdLFPh|GQ2x8UhA!FhyxSTkS$5o)9k=f zhCbkX@7h(I->XSvxCOZ_$AXBg`_6pA;&itSCC);+=|Sns+H_Yv(cR8^BU&d~FC?<35SQdPGn!N051MvV-$U%1 z5BfgA1j(<-DW=xq@0A();XO*qIw9a@y9)iZw7d&o!VIY!Noe9o_hLKeP72w&;0+x* z;g@k6=QlIU5mP1Z#$hHcqB-aJ`f(h?aF-FV{p ziRev)#@60zUqil`aTBk8>3Zza4tl|P_hIT^leoTVhsBQU|Uh=zMy38&y`4qgUF6bcdhJy?e)nM=fX8W@^jI>7K8QTG2SROU~ zTI}3n*ZjFJ)2|_&3sSUg$Emlg0(`-Z+bNh&dy$j}{8Q%;EUy`nYxYGGai)$sNQPC` zt4PThX(35dd_Zq!?)vr!cL4*7lF!c+w@3AX`u0t|l$wPu)5F*0&KiiSrv_If()F$O z^kuf5E~>tq(-}s$ral`3rHnZNrO*($V7-Qng=Si1#!4NW6=wzsl!+RtWUVuVQ`73P zdu{?VUUlvcraev`O+ZxpmGmCLUTP)VtMpCPs?GKDMZac}nr&u%>I(A*0feQvuwyfi zj!lN!mYLy>y3O*}T78ONw(ZAB&Zv&3SR$bUC-1b6)ezm}`fRnEUA$hsRtK&ehza|n zK{~0a*yw0Gk^LW|%)8et-C9H{uO^k*@!RW>O?^P$5P2nHiZX(TJWE!BHE@|MMCUkk z-abk|JUwMZX>p6dTPI9>J445&hopsSzu_wIFq@iR;VnPT>#-BMcZH=E6zfz+#%rm@4uYtj#b5M%gdphlWSmbs8* zLI<)|bxguvwZ;2v#0&kBAHr~xn6F05ABM4IJN|mQ1KK@}1rx*20TXqQrOvv?c9Uo0 z;6C#x$R|H|@JFq#$a1D4-u+;&yX<&9OQSOYgmw@_frlO{D2gWO2KYs|`k6DAoRMAJ_CuR$5mM7nSF+r`mC- z%jWrv{VGM4S0DZJ8ZIi@0mdCpTT%wH?Z5J%T>FMAIC+kHV_#+qY?NhyoC zHeI%xiy?W>I$#US7sl;Ephm>4c**sshJNE~20#tWt3r z$qbub&L5@sQj19fLv3ep4eT2CYt@0CkxN@DK`c-s@jEy9yR}V{rOp|vgfqTcA^#dL z*fY+=vtT9~IZ)%*U*&D2I(qFu&R!*WGUzpQ2Nx$M@tS#a{7fA>g7tj|oJ%Qvy;nK2 z6D`%#RvB;%f-gPrn_P&)Sz@KE>jN6t7xfIg{Cl5NZ}1+D1|FtaW?Ezj9fenVs?~@n zM&D4^)WIW~B+S*3w~Lm7ElTLb1?Fn^XILOs&7D1nhf`8Tn?JcaJw|-6b=WvBcfFE< zaKA)w=Z&gLf)zJo(;U>BfQ&dsbl`Ox84K}|$cF5h()hz4T&^_us9IVc)Q28R5 zZw45N9*0_ovb@OXHyczQ#8Ks~TaS(sAyXo(wp5|z=7xiFS`cfG6Ia=9s|f$E zvUI?iq;^T4gNWlGm)y)NM^RJIuXN|Vo`Hj8Ait-)0j-ccyyYLJ3t5(m!TznmPIU?x4mjfWtPhH5i;P<(XK}vw5zXC>a@zF}#O_s< zC;MdNi%fg*20ChG$C$Ht{8Q+6iX|3fwDq#Vv*1cPBW-6vo}|(noANx2?*RQ@f%D9L z|3JPqs(fsA!9=i=lUNeLh<1@T#qyZ>qOvwN8EckxB*L$Y@P8y9R zYQ4nvqc1V1M89?%ZAgh``r6)05OHWBaZuH?$$R)LlKkC7q?$yq_>?o4eoe77pS8|Q zEsAV_Y52yWn@%kr%{Y+j@A~vH_p&cvjAdkd)yuKu8u$@2pah}~GrOYYh$PVoKuWy|0sO&;w83^j9;W9exK*1cw{Fex4CrY6b{uJj{ zWtuSeHHBf`paAM-R6CmJqmjRrFFX*k9BEq70$G{kpF6owtW7Ya;w9M_j2m0>*DdM!L?J#%haSUG{Lvdp4;K z+Hk)dS_2YO`!vMG_!F_=#o@mAdfzn58_Qr(u02d^vzf#5BkD<}3`i}jnYN?vp{}J* z&{gp~F#YgI_}0UpH~BNY#gG1~;u-cFUc(%_<>9IiUNp%^4D@L8%p!O(6PL%bWdd+mihKr1 z4kYJd8{8w@cgUoy#7W8VdLX!Uj1})5?_}5~rk6C+rRtK1B;Xf|T~(iYa=v`GilCG5 zaL^}MDsbkilgFM^s`FEp2>k z&2gvG=zbYBS;_(1cE0V4+G#N+X8EA#Cr%>#>Uslxx|BwdiYn@P{l zoO@ABQn`ZH#H5)@O-cb33*63?OGq?k&u-&&;(*ytb*8lYT;(S{Y?)-9oCaFJq5-H} zo)+!71T`okJMH4)Q-*s1m`H8x8c-k_pub{PS#rNFy&s#NdBOU=;S+Ld_>b_`%R@Jr z{wmd&indivhRs5ulnM76hY;c~tJ>Ys;)zN|yqkVXwM<+M{E?z5nIg+Jc(@l6n0p~r3bQd%BT7g2pD)Lpowl1Mkh~vl=xbjPb{mN9O$ot)1zBSB&e?Liu;?E?CEqV z?bOh;u~Z$O2~llIASbFvwk*^%t^XbsECd4Iztq#J(RGes<`M{N=vtd>XQPx;C9k!Q zT^d>;i|$le^F3rATjO|R?O?Qgji6CoTKl}`q2!upJyg5Fyk)H8h(dxJ!U1yZ=%vY^ zB+CQpnX=I~ZWzGVs71uuN#B*@AwR~bs+?D^{+Mf11m0!e%h2h6ny`X6R?bU_a@Q&X z%tD&YH1@|#hlkXn0oXFW_OvcF-{to-j(xG-CYcWO=WCp7!^1vhK0mE8(ZVR8L)$(R zwf1B6$kE)A_r%*CYmlrNIX&cBubX(=&pu{PR9F#fJ_(78cD8S1IX`=+o+C1_=?L4f ziu2WhLJk5hP?UFnsV3(x*F)d*2SZAPLds&hz4qdH-Et%zwwNkg#OLw}NN3X5du`?! z0iA`5IxvVqh{2A0Cmrazq>Al&j{}>Sw2ST9tJ{N$OJqZMM0OxR5u!qSL%~%MFN@rX z=h&Zw4UTRnVBFB;Bl(WeXzWpOAeZaL%|o zoY8FO@U4L{&6+a9w@PAr$pvKLekC-MjM1_g?$PU2=f^!(RFzQHnPQLt!&SGs&E_np zZ(MfLBolIwvkoiS_N3d0n}CEx>3nR(p;@UFiA2~0U_quBTL+W zqoJ30nmH%kDQ!76rEt7Q54J)ivR(j`P9sSA9s=1}aYsD^+NLSVFYEvV;ghz0>bt75Aae98) zrqQ&Z6ypyTi=T0UYbNEE`m|mCS}n&=)aS$yPkg%pV&o`hR^oqnpXh{ul+Hel!QRI@ zP|#>4)egdSfo^X(mKuUu4V$H7W3(t{m#Eoxb`wnzB_e!l|3ZHNhIGzgEYS9$Jzn-0 zNio;4)J;H-PSmtFI4XVAehiGWA%i<(hvIBq8dGJ(=<6RPCbU#9<&Gnt+X+w-2-F8@ zDf@2<`58D4L+LSkeSRf(`{-G}4so!@_P%!hfUI1X>$mcs91y~O<{HaL2T9vZb{yQ? zHo`+nyllT7H0n#a@tVt>yc3c!%#_e^HCF0>ZPn6{z#xpXNkGCT0UosCN6F;E;6y2! zN0b={(|kV{uKgo`-IpbX1f_1SRQjDWOk`-00mpOZ zXL83-H7#Nrz?S5)vy5wBvd6Jj6U&5s_m_Ds=?34|9aqctj6ozZzdUwVi`5w3A&yOLc> zmfzjZiAcxW?WrFACwY}qDL&gK|T9*^4_93bB_gBW09ZK z7FoOgllW z0nMG)NbN6Qh|34$>oz%)Ab;T-fcOkkMCas=drg++^<9YggkLLiqLZ9dI^hxl&6+iN ziA2RZJJTS4!zP2~|$R@&{#Ln77pNv}~XpP;?)#MJwIEz+r$_UwJBzd1%4dOcp z4hOz#kERWI+dO?N^2))6DIQY^qA%mQT<^)Ci>xdEhTl#O`=qk99A)n_`Pt-Gf- z+f^aoX2T+H{qxDq+*%+P1B{6ZLG+AFkOZCZ#KSo>`dsZn2%893=FkX zaq4AKuO5=9@e7^$L$ud0xra&or0P*(<7ZhBL{9l<63aVZ9tjj$x^k-eKc-7sstyW; zX1fv>`g02kIhAYYve{rT?WvlR(RJB!pnwqmyVuTw(SB3pJGkBQ_sgSM@l)W|r!pKH zh8VHM%EaU;)=d3L=MR`!<%|tznCAF99sZVMZLjkU%dwEX-rK~qT^9k>NjY`JULj_M zRTNPt5b=%;k#n}Ht&m62c$oG;JRg@wzUZ&3vAwoi6GRC@zf4)m4;YgJ3Tb=`F7Vy|ggzWfAQCZQ<2VNSQt*Z<7AZ)w4wtE)*jhXL=%G z#SAM0bNpB^I`R8$j{jS#zN?Fw&~A9+Dr;?$(mI~5==V^eQuIu7HLj{J23h8+ z!zxO7pl=TBJ(Lb~EB9QS38r)mAJx4(+&T`o9-6MgRc3a;%83~jy*{ycu6(nxZIN7E znUa+ErPl1C&!1|r+3YBua8&t`Xj9wu(_G&fEuN6|j;+M(^M+&a;pYTz3zmD}+FWTb zg&JOkN=cb^_qKbtqS=PrdTp5|x>!u6#CTg0lc%$Ig*yjmFiSUuHk%{+=LP^i&kf0& zu0H5OiGTpHno{fvskLr&ejdBoho&yuAq@wvNaP0MmcibBDSPXK)E;>pl?2l%Ox&nnQ zI@5qRS3)om5fQb+EdiG&H;K(r%UT2%&l7~^?~g(*t~7uLAFC>b|Jm?gXRT04>hHx- zIWj$69@yXGU7yd~dY8c)n#Ibx~%2(J9K6itO zhiW4eBHN{BGTMDs<0rqbSxxm}&g5}n!JC31rt)@c2RSCl++D|ZDxDcJm-}W8vbk!~ zPZ-~$-5!=DX2@BY7CL1qO}7F-#Q)vTva?O!>Q<{u2pAIb=DuINUOP-INz{7&eUmS} z@kRHjX!4P!n<(QDh#gu|nUeXIFLh)ip`e`H%Y-xpB`JaCkoBd`hd-HlsR#VYKrHTQ z97dNn@9Aeh=9Oo;Q^GDmue6$UF)Bko(S@jR>xCAtI8>#yi&d$s<5YwhmC_Xb-@3js zVByNhVOs-_OQLe+6cwrJL!*<*Yau_vR)jXS6 z&iOz464D4;lK>Tlxx2d-UT^N<{I-TM@#c&jc^73n51=Kgx(A#FXXbMbPif;l7HKOO zYK97+-QMa=81Z;lb!YpOJi~V-!@3H^{^%mW)^(T^i--_xvy>)mUA*|`&!dT;wSy-F z&jNbE2T(v-SuKsGpAogju1wP1&8}vtS%b(Ci)9%`WA#O5M=yQ0X90%T!$02%L=kG` zGFw$8l%MT?DRFP^=)gtDmaSjmA*T+_1ER7L^3cd3t>%D4fS$KA;t|ipGd9+di@s1D7%Qe#-ye&kmBjDYf% zOKW8l3&1$}0)n_y)9qC>FA9YM>Z)f^pS#F!?f`J#Kbb&CF17B&b1Iq`@0V!n(IuuU zqnd>YLM!HAu0)3sokDW1G;b~%KDi1=x>7Ygpqfe$BFbAON}hMshr+)nE4JxjIVCC(}Y156#>zA@0?SEQaMWOMDS<)X5y)c-L|2|i#}T_qeS zOFOUf-+zXrj9_iJ=*;Qz=kFi(gfd{cm%(YaF{8Cr0doWgGgC{v%1l?Kde7mMO~3?M zSGpx;5l7+pD52eTmdqpVZF~`_iY8b{REb8tlYExUtM&7_M`AjhKfn+A+OC9_s6&@& zR#iAb@uKn5uKB)mQbJ%dr0bVDIeh^1(YSwv(H&_D1JM~LQu$u|GjU^7p^};W9^KAz zE(~TYJ&^lhc&tgEpH@YQ2cY!+;bXU;Y@!AFxC}5J{HY%Rjh^pZ{U|w^ro;ll8Nycy z9r4F6bnl)ekRvY>|Kn}`E&X}GzGPY7f+g1v9iE@mw)40zvYxpxo$jdR4$lutq z%~}U2;0dgg6=!=(-N0Jh2_d`D34QPQCF#3hxyJRqVVlwD!1)7!bq!d{l$d4t@KjRb zQ6I5xcdq@{hXahNJ3qZ5Tiu(?{3&_W)YYX5ZeIuBLQEmc&FWK@4tFm#RV;jK>3sJ3 zCfS}>ww*4+h1Qwu)g*>5<*Jm-T^)>{ClODmKgXP}W9l)4oxjPM$+UQmC-e-hx6$Fb=H@U1 zT6mk%|Kd38)|64aSeMifgR`mY4<^|=#Lb?oZ^eF&x>2xcK1iYneYYZMOKv_W^m2Rq zuZWTqFIDE|^^Tr2nX4$ZU^$n;Q@uWilm4#0)d({oN9gxzPl3tBg@@Zsx3B~k#;8BE ziS@E`fRoo-6(pw|Kr8f=I0|D0J@TbldZ0PP!fr5aduv}q4dBclPi?*h5wqTZ-Z(}f z-A}K`S$dOr!{uwiUCJdgUBT-RmuxiU_a!XrdbjYjvwWIZv{lkG&coq_b<3S{GrR{y zD0K=IdcT6Jf@|xL>PYoS{y;ARlB%$^k_w=F5pKF;ljRAFO|;jL4C;worPGS@%|FB` z@>EOn_9h4+DuVXviVm@VTx0>~qF%FtXHG=|X}s6&ErK4x);ualinExzF=fKyYO*}< z{cHfxzKD6wjlDG0#(ce_DXiGlYi-ki8*Pf1%PossH`_&*zZ@kN#hhQZeJ*{W^-Aq{ zS1%}1k`8ip{RxO^8iMqm@e$V^s;4DhSJuCzMs_;wvEDiJ zrdD78D!ed`p^V|r6VPu6))S_qwQKhDO-5(1eaU+*@3X>g)rAfklDzW`6Gy#_uxeM1iUy%Yf+@fi6V%wO#u5<#XF#6;pxLg}b{HobmnsZix$Ln*#q3g{B&e65 zXnZlH>g!Nk|@09GBo<0jlKtMav_{_>d;F2WF6RyVa#8 z&Ppa~8Br$aZG{AbSzFII-g^yp4VRWkLrw4ex#s|Qpi~DXp#U90%QyN~SvHr}3fu{c z_B_N{a(Jk|R>AcdudMpUqt0(Y9gf+hgt9)<{6%#=YehkUZwv`OINlU-)J8RCfARUd zE1eh92VHw4Z*I-c1IID|LigodDD0C^=z>!bWj)VCFUejp>SwM=uQ(TR5R4%VF1i7b z;4KM6h)s0=yl6CCYSqe#Y`xR&e@uMxf$>hO?DKn9Wr=zyf%7=i63)AwQkECZkvw`b z?i}9s5WuKX)v68Cy`eMXX=_%uWaN_JRa}ZbV@@in3?p9vfPM@yiNEU;!i?V*lDK#2 z*Kplgbrqx8mUl}LgEX&vqW5kWEBW7H?sK7Zd^LCe{WE1Dc5L5WU25-WuWAjEDV>n) zv1a2r9{Q`pr24X_mm4~NY_zQu-P>}&B~_<`Q-6jiZYVdncV z2ivHQ7Zh^S7QBs3R(g}k353W%Jjr)bX4{2 zTEOF5P61R%-hucK?5_Y4QPbI)v3WH^wH}?7tWB7 zR=>EAs-yB#Kc7y*LBvUmu9Q1{`TlWHwvypj2?qN5=DOc;r=+9|{^RlnM+IVl)a6Tc zhP@os+S3r1rK$I#06Nm7y@x#X2KugNFe(N3(l0cWnob%(T4CwR!qXE*>U_zivb zry}W7Fm$!J;g`@yix^-YhL13EJNx-Da&d93IYuJuUGnPd=@1pBDjFJz?t5#`ICDcS zMhhJf<;8w`Q$90u_|2BC;FDdpXTzQgZD+(%I)J40#ni}Zvi*Xe@gBl zA|et7#HEvsJ{l~fKXJH{ix+_Raz*vCkdl(l7J`Gc>K?;Ir}kaXS_AZ}Nj}5nr-X!P zfO9zjc8`fQCGR)|;i5nRd^N<<(sE7pDVF?A%O`_~$jIoZD={$Thw`UKHJ{Akb|K?_ zVP{OQsv5+t=(B$OYLfTS2+ihu7N_001GK5?4xP3`X~PSd1eHYAVpHwtsF>(dy$-OLiQ5NXxqN1jCplgE_z6(5lcoKT2`%$rQ%HV4g_1xOEAS{*=0ikO5&f!tS~>P1)Xr=7I_DiiXj(x@;9F;dDH-4{?D z_W!x+DuJP=Y1Z3~*rceU*DLnPA4|NXpr}VsD=I3QtHzkOo^|RfIHQO4yqvlBa!ZWg zmc!qO|7z&7y}PZ`|D`K(IHIE9S!a(2e@xdA*8ut>yTlGU!M$2A+V>84>y@*&ep3&u zak;r#wsf)YOtazV@U)UEa#Wf^t_T5~!uhi?_@OcA7q7Mfjd0&fY&y#)(|kx~AwaeO z$H$#Ju(CJy-2>pB53XNTQo64I=f!=+q699%C+b^W4_kCJye-)1Aalwqa1=( zxWY@=_UX@6?cV;kU!+}VS}VajI@29G(6JX-s^ zdj&*@;VcB-1T>~DDbFB>h3QE#0G0puK}Hwp<-eyg z;34`8rEc@oUSduNR@+UL$3AgZ~PCy2BaH ze8F&0Y7HJ(_UDk$MB)sM(V=S^7!HT)?BRgK=o;C_^rR@0IQ|!WN>DFTon&m0GiAHSNe>CsNC zQEB5wl_QS&&FTN7?gB5-0OTXXn>T=nl+KYNG#|hMcZpuQ?aRQH#K^G#oTjxm%-ch( zS|71#&&uOnayb-X8{96CTfqBr)&Ue{#PZ7yoJ&-hfBmI!mE15C^}GhSCpEquZ(&+^ z+{{EA?RAG_s&cAc?jP@T1uL+1;L95|0o&pY3IF_geVFQvfY2Ecc*o-Sojg|H8w6|> z?j(!b^%|zs-2Qz^6!5P5y{RI17V9Egg|}pVcb+R#^0t}dc1hH#J=j7+uB;<UC zl|jS2z*$7Y6YGhQHs0)%V+r4ic25?UC^Q*g(2&(<-~{aYLT8gz=%5=iJH&1CRpDJV z5=%krUwK)hyCVGikg)REf#o5McM@2b?JS>+Vy|2xwZ#cZCjg3m)iO;z49t%e5CFSy zPyt}Vc%BFO4xApb^+Hs(d)_G0pH?z15MeFmpODRSr*E$-Ye3xw1pGNocP-A!h9v*s zot11*IbMPZlO~y0@Dn6mkta^bg9%67z0Wi+OQiYfGRtN}JtyT@q&hM%7TEgRhsWG8 z6ZN~sv~Ip2>eqI5npYCX-(lf{3Dk|k=%)+u`30#P_Z!?r9)-D|+!(9GoU`D1h?I%@ zQvGS~>blXH4~lUrw)T3|K%NV4py^qX0}d&{kmmVJ zV3~C(n&IX1++Oo*F5#2vf={8Cmuom6Yyd7)x?wQqAZ=0feW&IIh;{P zv1gR%4|M36V+Yv=u7s(4q?0KpKU_L5xw5H@i2=l; zN>FrG*k4w6q0-h5Tm0`YeXpz-W;7LxZgrImO|!G-PcyCUW@Q$QR9T^?@7n*hML9@{ z_Ih+FQ(1!HR|#)1fN;?3L9h6enCfcX%93J|iwg_%D`Syr7Em>{DCVtj}c7|C!X(GpdKq|n0MkL(Dr zK~d4|o}ex}Kvf!AW;6QLe@%?8&d)EJU^g=DWW%{Z{(?{!ab@|Ur@>u|r=v8TroLdo z+mBBN{9jB2BU6Z4entm$$0|hCZUwMDteW1-h4pqJH@re`}25zQ5hL-pPq z*p^7w6El{Zx?>MZ8uKrmO1z*n9UYlmAQHK&gDL)XAMYhVXM|L8Bl=) z$Q3uRq>BR#;M!Zs@!xPO0S=Tb7_+9yg@&0~#!UiedLsRH5;&`6UuLItva(7m?ippF zlG@wzUo%pVt=JjHyLLGt!skm7W#{YHaV5ttOgLWvm+JmzZlyT^lWmI6l|$v>zdeJ491%M4D)%mRU&e;`|b%>(Y#8nFfrjS?r0}X~49Wz*uCy#1^-ZMd>1pXX6dT@Q zOA&RSmz0ddZHeQ@cp%oG@>vnfUgC;u#%%ss8Wt|tWzi}<|H zbp%_JeVj|Ci`XaSJJGb zSF#c(uX850UmxPw9!N>v8){%Bb9V6xy6VpFruL&sO+`+vok0ld;O}E z84GAj!d58423TOgH#Gx6AvUoj4W|M%g&Q$pv*sCx-C|f52WCtAL(L=YrbIBgMzP%q z4w5nuZ~+5Bjj#TSV@x6rtoYg{yVGP}m|-tKh+3%G);kruy<4g)u4)HgRcH3-jg2~L zV^WA}^zNH8@nPaTg^}?sEqw={O8dAUwm2gr$~y@W0ny)7o1UCb=BOdFaDa|SeV&o)tYFN-P%y`&J>bKPJ1y?fNnQtt;wbzeXDcjFu6d0o-46ZaJ zqZShP)aXkzJyAN*`l%2Fv+kpa-lM@ppc1#XIysIOe3teNMp{T3g9N^{M2xWoyG#q% zFR=9?=Uwd6>V4*a7zTf7NjwF6=qoMW?l3vkauVCd&1m~@AjT^9@WeaL~T-yH4wY1A}JT4;llCZV+pz90_X`_pw{=bMF0 zV$(1N6&>NFvZd}=rs|(74>f9KeP7Viz|1#?c?m|_8?{mt zcAJ3f_Mb)XV^3e4%atE0J(zY|{gFBGf?V6lbmq3V4RX#Vz>TrOUuWH_<$;95SB92aOa3fyx z!ky(nM}}A^~PH!fHh6^=M!a?i~GPSEvp%605b%HJSwueAbBTKD`~$E zyu2obD8De5;VH{(x0ja|^&@)y0NOtKkdQ{i;RNHQ*@8yL?M2$7onm$aRBCSj!W5vs zK3&8uYxoI5PE~s!zVDZEKh>C`uJvht`#jh*y^}lyJyw1H9Uywx^Fiv57!3I{Jh|PS zNBl%oPDTBM?g=fY-deZu+ZLshQ#O=(3HL9&i33~CkjYeaIuDf(Y(ti*V=3*8G&Sst zEDV>nK;EnjjJ*ypZ2y*z=Wl?Ia3A)w<~v7H;fh9~U^hRbSd2b(l?iJv3x1h>%(BO= z;IQykiHi8lHS`=WfJ#PujHnmoK#jKaonyZ^7%p=p)JyPgc%X%PyE{;4NxP#ie_jRB zVo&eNM1*A;Xq6dHR(09;53R7i(O6z{Y7QFD9>eLZ2+R$-9JLL(lx;hBJU%!^o9iDo zZ$Y$HU#@=>f=qV7TbbC8DpyJ6hZ&O338LGY1!igdDg?E|dOq$Y`!RJ*q=OHSo1jl7 zyEB)d+`pDSL%ToZhdeyTU>A%weGue@{DX53SwGgeKb!dRrLC53XjzW(BR91j#z1h# z1Tngl)!amB&?Xc7oK`-67kfu|{MK+EE~Ws2?CzJUOy~XCj;rvdq9iSj(@t zYb^VpJ>x?h{5_Z~1jbrXDO2h*PxwCM^PaMRhVTo%q8M}2-$FaTXO`}g zuB_GaorQq>%#|=?`o;L)x>t&P(?oz|3DCTc~7#z}wN;8#S!P z1x-BD=$ckCc8`%70la-uBhF>+{Wyu1K=zV4OG0 zII-I~;uZp<0fwy=>;#Jad7v{K5$iuST^Y+;#c0Ql@l;Jm*tEwJR_dez*c23gVr(G& zjUi*!hlJR`(b5SDN(@MXyC(W$T7eSk{t8YbfsdzOeKqkA6s! z;ZLm5Di!|G%QD^1AdDG;q=qWN7#GlFSf1^bulXUEU<=jvBveCV5A7Eq0E*|XsKMyMzl!Q3EEW52MfVl^Wnh0bWRC?p!W}>qj03yh z8-c5dU4Z5=G{=Rl*7W`&p;4!z?b7Ck#cqNFwDppbJz)F{I5&|*Y7I2 zQx}0q*|p&BZJo8-guZ(+&cEC_gqX_txwvc1+$`Y|fXM7{LrbX_1j<;}kI7)@g992o zL%{oF!6)9+5Nt4&cACjz3k9x1735^~iTS<}s` ztALvQY%0P{CQ$eIr))xCwrgDm2 zlY-A~3Elfa0@89u(|UzL9>7YOlb705PN`b4aR8qm-!|d|^x4}zMJD)tb1{57llsS% z+c(;_mf6T9Pf=4<>z2wfl3*}w*i3dYJ3Rb%bA9GdJnSHV7O*4^0f8L42!5zm9tnOj zW-;1K5h0{eCmktz>@^eJb1M!}bofqW?OG1FP+ zfj1nhX|a!J@jhtFt}w9_UH|og+{!|>*3ECb@FGuf4X6E!KPEaPIP;hLPY^ZT42F!w z2p)oXja<9%PPaK3A`U5Md%OnU{{un+x`y%d%yK#d zyO_iUy(JI&e%A8{TG&3{!ZRG(9N$x5%Qx&_kk}P|?f3F1%zgL;KBRcR3j<{v$7)5k zx%!*Z6Ep=cd%;-GF3T zde@&Xc$L_ynMyE)PBMBIeGLyk*G3TrhF{bRJ?e%o3XM=DoI0spIm{hOiD<&hZOHXK z#$*BFd^R;Y^mtP;&hlZ6;aTIKC7+^^O`y_R3*;nk!a7KTh;M}~n`i$|{f+TB+Q*Em z@WxyNu312n?ZSa0*upM&8_yUaB8FraDj^RXr2Dq&DhK$jD;S8a}ESVObmg%1|d zqU(KdodyAm=GR{lru2DLfzLJyBi1uMZy?{pZFQ`UD|K6kANcPE2$Ph)GCSzp^wUk7 zw;&-sEZto}*AjW*D%_-67ittpZ@IV{G&JfO_JM2HlzY@UZFvqg4(oRxaCfa_-URw5 zi#qnF$fkkJ@{3n8q9%j|(Opj~xywm{aJG43K-SEg|=*>Y&{FOQl${R%%OE=&LiVF?<^|BHa*8~V!1BTl z_krVCo~^WL!Rk+LIA#xLHvOH;AMQp4D9H$kp+%I{o1^EXyjIa?o>^_Kv;>Nz(sco; z+m!wW^H}2vh)>&gnttP`vI}!@1@xU>VDb1uGKd+L_rC_ zP#fK1bT{U#;(W+)7`qpLt`SD^&_1gynj{RYiR@e`JR5^zZgYZnJE~TAhA{{kk)^Oh zTRt@w>LCk-cl|q2Y=jkL&sex}50{b{Dr$}`?9cnI`(Je36((to2a=i!@kUiZ87`B| zbbCbR%CG`2$4?1XDR(7iuUN(#K)Bc+N-*UF%)q)=2Q?%5D2`02RM1 zdYA^UCGA@}FKP5X7{KxC$Q>LWiN&DTOyu~M*kz_k{`J#KP~^w z;OuwId_&Mdd|39H_Py#LOEV6LuP=Q%zNOcTInxDTxP?v+=jaNG`#0(By+It4pObx& zUN&SVeN&t4fsFxbVcf16#~esvKOxBFb(+l4H>Ds-pJzh&Y*TN?7RdKahw4ae?T42< zMZ`OoxrG&yp)W#a3Xl{U{N@{|yDJmiN zme%)VN#Z347Zh|5=*|RS=hN_xu^?4%Nh$8BL(0|o1aHalyk4R} z*(3f8+!YIrGK%mB#gg^x3MWdn_EI|VQN+Oe`&R`raeE*8;I{*Uy|5^JzgF)kP{J*~ zVc2`*b&MqC%R}Dq%Opt-J{RWbai=0-FpUb%rt0-XQ~EaUq9Wa9p_SgE#c6dQbE#t! zMI`NCcVn%IS5Qwc$ju-y`BO=?9_1gK0rtJtI8 z0a}V0f2r$avpg-4d zdihdvH~9)ewB8?%YtaQ-*I7goN^o|=(M}eMS0%C-3MZA!l?R8-QW)@B9+)iaa-NeX z$K~qSmysrKvEypj!EMH#g2G1&aJggR<85Ta3dsti)cqzEUaNHV@OB@_M5ZTBc(j~5 zrF~yu<8b_2h5hgNtwnMwK#dRC=`i=t%r~0M4j&*!&&FsKv>mVcxp+={s-dDK#dO1F zpxUc1)i(1Lul(;i)+vqo?UPtZF21a@4pqrLhb$^dqxd%(d;GBhH{-)2#!!naoWOQn{+ck<%4C z19fnqd4yW58M9*%<(PSP)YYDlCp4pdWYoHR%}JvhH(I_|7A?MXyK8lrUpf<0S7EpV zh!RTY(FIdjQ~2L$+q-&_-&aH{e~uhcpbI>g$$;^*VxQO#t#M`y&-VqBs46cB-S|`? z)9J@`h|6y_x@)`XDIIWrmr8?HP~?~px}Dq;H(r&0`S5*HLT?ZS(0E1i08V!)B+C}E zd{%MKZW^zubO2mCoWcd&{WR?_-g4YFR*Uf3B-v{Z3t!@pxX+SGnR~W8bF4QE(}>0` zQJ%FVaj{fkkrEdwhPJZdP!`G1aUh>E_nfMcRb0RMPg_0okQY=ZH9YqblWh@v$6PX6 z!F@?5Wsq>bbnJB)Z)bgIx#VLAIlRT9z27~G_RRCeBZnUF7wYF7jLb-A2FgY+SZ7AH zjfRFMt1v-rj1=cSlSwl`83(#$EWZ49FYVtE?FYqP*L3;m;7fb-24P^pir}Cnp>&|i zM4?i59yT^?tnOoSW2j11baHw_L|DbyO^JzE%9Q@Eil+qH9pxl1*XefJ`o?d~2*XK2 z+ES=%+{wsU0NB7$BM|2cSkGs?bkk@=R40UYNI=nrPMvOMf+(6xbsS{?bmqOWnIoJq zDiddTe|sHII^{Cn2GaU~?u@bfO1Y@}xX2lOyl`H6O5zwm+0!0YCIm@Z62?Vt{`yb6 zkBkC(lwH9yyk4?c5lN(BJ3^+0G~g^;xKE5QTJv?@6sPaK-r%o*Qc2_S_A)3XHu3PCF@Na50<&3 z+*5sI|Ng`+)>Kd0=~X1S^F{*F-=2Bn>6=7xkC1YVmuJ+3cbiOv^LA;^QItcw@ z1?w5(Gx!*~6xZnphJ-?ByInuIJ*`lyuxBBm^wAfZX!|3KlLlJQwHgW(#deKef8Q(1 z4}moGqg8$_5lLsz(+1LryfStk@gHVK(9_lk1(FfFq7h2WY1UF7`iuSsBmfTa`w~g* z9dY!UY0sDIpn8fICL0HR!d2%AJA8|n)myf0zA-uJ8qTY)m|)Y0!_nFu?|N&H@)DY3 zKb(whKH>4PSo}-esl~3HUre2BW{>*e6?5Kg@8hyt&Bs1BkhKr8t)2D5SVw*IAAQWD zeonzot`_Kqmh_+$j_+|724J(hX60jy z>ax}#noJLKY=hN>;<|*=Yg{o)V-=!;Vk!OtB;t)-))>5kgTg_zZAXFMdj+l3Xfu5x z`-F2=eX_|45z~=v;Rp*6-L!(9)%kaBUljk!eu1HwmoLpI(sF(CVWVq1bHebsigy|U zJuavw?s|{2`@Jk&A0kK14hv2+nfRn>VlVVK^T6iSR^-Zyv*BOj1bY0tlhAAR$s6=E zRtQ0149Qub`f@5(ulhtP+`KYG$epWQhx+)pH-XU#(g#JAj{~cW0zC?&_i= zujKzaU;)q!NwDzUgySdD>3!L{d12PVbg2w-OHUvpq@EmC$g&qpeq`vf^xoDX?n8AA zVqXT?_Thaa@hKM)t!a&%{Y!++wp~{yT3|WVPfSo8dwW%b#oWbH83t8mx>KL@RB=($ zUatS@iakT7!6L@;zD7ji_0rviRHC4zS8NA4U!DSaMOKMG+z6JQj}viV60+0zxvd)^bTY(FpqxQiMRy**f?nZ1$3irI2w)kk zK1&VWo~OyRTJ>hi?A&#SSXsA<;TUiNBRJ05FSOwtN5ucw&YqR6X-HViDx6$sw-Fu_ z3mjLI(-GxtD7I&#NLr}fp^3?~nZ+(EHq%MoMgn`C>#RBUxp_)u8F@CJb_5Oy22E7A zQQ?LVj$8KaplNKBz`kd+Wn}m}y9UMe=RJ2qzxD10pq$o%pR7&RQk)0q5T-ruD^Y>d zJY9y3-!i;3Q@+`yP1k(>IK0EJXGunxQ2K5FUm{yy_qrU#NAMlsQV$3za}(z~X7(9m zju!05@7jKz4u4`gy@Y?*W+u7@l?a9RcjZ0lRw89uxW8=~Ru~eU(^NrM*4;U5Z53+? zD7E4Ju1$PZBj#3yjCu}Nmt_o zT|(Rava7buQ`*o)lmr4J17_^lkee526-07Z0p~079#TwqV zK%sGio5CI+m%PHB4e8bCd6+FnjanZbufLX#jyE;4uhWxS>RXMWaB5%e9FO@0oDBaM zoOb3qy@~O^-p09_-@F+7U_nLmoVRO!I&5NzIO1?n47>u(_Sn3%5eW3yvaoM4m3I8l zQSQH}0{8t+>7XEE+iHJ};zFh3CK~}Si7dDOyB;C>8@PDgzNdU#nJYyGF4R}8eyIDN zQ0$%0t7SwX8r;r@5#lr(pSA?OD{n*#15pG$kj%XU{^)ea0#ntw90WSfcLbiu4agdJ zY|~^&)WbR}v9Q9&0Gl-P7d6&HZ+zlPu>+gWLQHW)L3zU$RanZ4uzxVe?dX~OB)=^T z#~Bq7xmwnv=SB#qclFJXcAd~n@+|%%Hc{g%Is@F>`7&RMp)Gz9)1rg;kH&pKR}LH{ zMEJ5;|MWzfCRaY$kESns`xcX!-;JSbiUe%A`6S`D;apwI9V)tNBNm4joHVO_-8ha7 z=}f64ImHa^;!|V;JpsAKgRiZ2*ZpQ`m16zEy_6ObVkqG3Pzs>+|31%~f%eqVT#N=h zL?O<;ospjo*bhf}@%|s{x2`i4oy`=G?pxY7Qoi`EY~R4=e@t0>^*X!-%qSDsB-`u6 zpBoYLq9sf~#8lOb13TeG5F*^W_2YNHH`AO{oZ3R$(1Kov+yR38W7D zhG1~lit7fYkIZ)_bKt%Wlx@_t#txcYPx{->+hL<)GT4Cap+#BXvKMboCeNh!ph>hj z^7VA)T1eYy)={+2?pp)Rj>t>ibk%Hr(Rep8T0v<`s4U-jXjDbn_?WVz5rXNK| zGZ97fkGh|Z=5yQA`cVE05=j#5R`*i?iMYzzjy%PDgTTATtncmHTpbdd)}JQ&JRDQvF|$onHhR}1O21GFRg#=zrR*H7W^|5DmOQwOZg3PDDizl zGJDds(v8EOp1?;A5A*a!S;fn#R{%-*Fl_GgjYoiL7?Qu!01y6KYcS^jAic<2CRfgh zXR_da^EQ4`V)mo*ThB2mZyiOJwGQE2^aN!F6ns;8kKO^;Dd5wrl|MfP<}qXlI(lOM z>vUHStG7wQ_NjqydEcq`zaW~Xes~O?KoM=c#Z1$YU+D#E_<5V2cfZVz_7!@Y>a9J zo_Efpdl_KGtqt4iSkBku>kl(~eh+!nnkl^ZmVOZ&``Ju!r>@agi(802u?mosNag~d zpmP+BkAmK89|EeHXF4^;@-}k>7Pvp`6)o#&$KMAk@`wRHx_=vO@AiwHL=rXg^SG6f zW``a1T+^{n*)ApBW;KMxJQz-g$QIo{RTl}8C>#5!{ZU*=#2wQ^-pJXOm5$bd{y`Z5Oe>7it zGn=31Td};oZXBLr6o7J4nEj@^#Ck(&FQ;z?oDLI9rlXL#M{+wz5w?NIcMzVpo z&t7VyhyV%^v&Z~x7MZ$WgeRYv69*w#_8SXo_5cMs@MdS0YsFIWw3rY_;+X)GkIcL2 z_}^23@B8Auej!RP3t4V5v)6){)(?O^J=rH*z_;d3dJ!F}5YHI)N+U<4r=qe)JTdRQ z%2d39G*BvjQ7-pnyNX%S($5eQd)GrI>>A3$mPJ6<3VjcdkJz~na7M80R!f5V87_+) z^5YD>JSn_i9!BR=?u~sagtC_UNoy3_y?fK94$!~Z^s5toL3h}rk7HW0doSx`CtL~| z;`Hsb@nECB8YeWXtcsWU%ySZSu6+j^kED>lS_1^Fd z!w;ShAF^U8J@I+x#$#8#rFcSmCG}g3OK!AXT_(?M6E%S|Tu^+*p0ZZr`y^Efnj zlzo#Elp37BFGz{>R( zJgAJyfZE+wX2TqC`0#JbPkbim*qG@%lHhUs@jSu7M9JCxjB$g$8sMhUHxvB3<+r2R z;!uNMA9x2u3QH9`kMZRX-8nsJUf<)BvruN;`a~4GCs%!#OymHgm|@1>5ufHhuFX!Y z3% zy*F-s+xr2bD4Aoec~LR-4B4VieLN6yC8&KVs7MA^N)q$!04>rN*mAy|cL3q)uVQ1{ zI56xFPJ*r@wc^f#FNNv#KamYsE|1=ssgfh9heICniT)3$R?$ynrx$aQug3sGMkVoD z0ggI7SB9mk&yCC|iY0w+zTnyZQB+Fy)>Cz_C^X-)5SDuB^3Eet`#-he<7l>-28~Dd zu#9ho(_g6X*xVQdMk-YbU$0H%ertVGi66VI>VG?Kv0}m68qktktW(At-)t~F4TTX( zB^iNrzS;tUmqReb$jdS3kt=pr{0=es-WQaTfP|&ysGcQ7T30hYz8^4Hau_%|)vrlg zua+6RT*6v!5{uv;rKq3NW~(i_1M+(`Uh;3JIbnTcXKC46{?b!9@;+H1uVuO^MKeRM zmr7zlQcTvfQVSpA@P+sm{GwZb#DJ;2mWLNaH6tAcn$;t#hwUiEGE!v|V*hQ8Nq0KJZnW<3!qkh-`Jy&4zzh%YeKgCmpjGKsq>1K(v0ecpAqquG!dSXNiOZ8iw!S# zOq9AxPTcNPY3D|4=m#2q5^_(5Ps2jKh-j;LauVv8M_ZV9EC+Uq#_HLfDGB89-?5)q z7(P&}!5BNV-$mbynY_kh(FMEeh3Atwv!llR?xCJ0rzQ z{#PJ9b=q4It81A!? z7LZUbr_Z-$l2(JXhfE}G0z<$|8!ew$&pm`PCmv}&qQkciRObT*ce~M$cSnh49tO1d zOAbQnI}gxCgp?8^x{qScj1%%05?4$$E`x6mq^caI*uX(1GjT7vlS_T0?dg)O+m~^0C;3Gy=C`%W!$rOWEP5lch_DQD1ZKa$yvYH*F;4ahS z)cYJjQ$#(CCA5DrRav9(YrfD{%6Dn$5N20~3yzP}tngWehDk`33>68xZspCU_^6b- zePLQ2FcHJfYMar1Vr0}-;Vhg9xmsw)!5%MEUX|*m6tA zICxNYoYl-_{m7eWy2gziHVp?I2>$*;eEi6eq`hNRi4|i<_&jb^%Azef&pRE})XN=5 z9>_a|la_sDfze;HMw#)|82e6@({8IMxk&B!z5T)}K4VZe!v7SLZ`0yL*M3K2s_nD@ z+G{O+25@EZb@0x`p4M)wvYs>4MxF}HR5Ge4p6_?(>;bHfj;)X1`eX- z%3Ff0ZxY6ttPlV8A1hX1JU1&&mW0$$Y5g6g%{PQ)z*cj33LuCHXr6z3HhJzDp3lEM z#4lX_hY1g=h(W4r#BfTbs^pXY;^2nGBX&Uj`s19)yV6{vUT4yjw}2#fb0<)_U^3K(yVo5?k2Ty+x|y=inbHU4nmTvss~9UwsO(Nz8m*1qva#HnK|* zyAreIm?bB>ba{Pf7q)YC*hA!HqH_Gz!-Qrk*{e4CsXj=a-lFh-0<~g5Eo`NViFT42 z5Ml2@_$0UxXem>Cvcm|^anO4>+!!PBIdB>=nYTVoD~X!Hqu-H#vwATTcs@GFEUUhP z^y`uQEw8Zb`ZmctHpzkh8W{iH? z1qa5xc#yJQzf9$=7Kn=p-7{}x0ILm--J( ztv~_G-^>#9k=Z;3%iY&<^DD3=8W>^Ox*52v!iHykd}ayw)KbHwFN_!VSVU$%xuaHlYtv1+FpcT zNcf%2XDM%M=IqITPeg6VIosLs`uh3`N=OvsJ}6{`UmjJ4kro8o3Ty+(fAP3!@OSUE z#~^-@r08tBfGzsb8GSG?ACyCxJGdpEWEg8gduoZ`JL#njE9u~Q6Pi9$8t-Uuv!?ko zOeN68m`pFP^N-(xb7Q_0vT;7#LaXBGHaRHlOkazl>WGbj;L~c}Ez$;CF2DOL|J)CJ~N7$FDHX2z$NXiW#3DW@+B= zP13HGln({QO-_AB>NOhNDi{{19cq6}OM81w*_nl*`z8AUu-Kb>QLLQQn={aQG4gLE zl8Ka|Z`R1JhEb6@duHXn3Hqm<^{t`yNTZ7MQ%>?9zdmRs6qwbzCOzG$$>r$9YA#YlU*S!iZ<#3K_N*3PIua;(!>iV+OssOUZ%u8#3$C8XI$Jz|c zOl{XZ_=~kynrumPS|5zXk238@2u_&c;oP!yiCCbpKY~v=9t%`_Ya?qAdk6x=>9dfh|4-n z=VfEi=~}%H>W^I!bddu*;89d7NR{+^`5mu&9Cw9W@5gLUc<*`Eh6D(&R|h5w2R>Fk zTQnGJuBP&Kz8h1gr2+qX9{2&0{{=lrZDV6e3?N^hPO<7%LA9yy?Vy^~3z^$3#mPgy zKtA5ksybrA{Nw7~z_ngrCVVOn`|GN~h>LK|S2vleEX#!(oC6e2!#K`s za$9^)Z42wlz37$TejS~!-ND{B%bFKLORrzpm5Dr3q_^egzfDJ30+6gpJbL*2i<~nP zt=;;$wdJ|dyB~&A$^8FFFTo+ zI^}W)IJBtjSgmzftB}wFpgSQ0vUGBki03n;y)oR<`?Of0`rm+sKgXs>+$~v){pQ*8 z60*u6ohDK_gnkcollPUn11G0qimIr7CE3?+@0*Y-f$`@AI9HRWJldPOKals{^c{ZZ z1yH+Ke;HASrhN5y8TX25w_*wTh9v%WH#p9Q;TIzHC0id^t=Pd|*BA{7^GVQ41xc8T zagT+z!w{i7KoOvN6J%8;m1E3#=>2M{mY#DL;N9qR&nz)bIBl1uSNLq0G~wOStK^%0 z{rfivTugm3keal`JQWD|Q#FPNkw`0g66?KRJM$(p5#e+SCOp!Vb<^yGp7>&@w{C<_ zht2K=L&dW%_$A^ui0DV)h_yfyzKDP2{=eF=Pj6DRLCzt#{=Q(rK)ZjGChwU*zN44?4acVq-Tc>^Ee9w=X>D{1?i4MSj=_VAA znK1L!<23F`RqsGmI(C>fc{A+JYl=?{pgPT|pjZCh5=IdZgFmDJBM@GOw5s}P%BgGS zPp!%fURtEnil}DS8OMFhz%bw|zgv?`l@sKDcBefzH}JSMI{%}Bc)fhgx+19XP4coV zTudSSdD}&7a=ahO&^*F2MoTX$%4UNc^M29SY6XmNpnvSsrCprt_q~`Z+-&%E)4*|a{fhTSYX2&7lIbTL$ zdC7u*x!R*oTc$PNttRK08ggnh^EahX#JaD>`LrcmMRa!AeO6;U8mqI&!!r=7J&RB+crc;uc9e0Lfcww$m+UK7=}&l{I2+F1wCigje>nPJCXFg zPc$HxRxocO zC3pfh0e~jMS5FrQuuA;bwoJ%}q*yt@7QSLAzz7ov^mTx8(?3}v3O|CdUzh0Nslt-YH0S zO$W;4@E;M%G`o`&Ep0s#y;4>b#CS8Lxlzj-k))NkVnYrY(sU`g&Sz0Wt5h^F3`? z;AD%JV~&=zXR)0}rmzpivg2+W_Hu_XOkUh$`wkB;uQ1C}g++v?@rmmlPm0wsfJ)|O z(5cgRICiKTl^F&s?e8G~3hFqf+p(nqT|2dTe`;o9P5=<1N2XutE_l^KvV2B-b(`>l z`cLVHhwEYH>St+uy-jghC_vW>;GN8DvMDQ53P1z&l|F)#v1^4c;Laq7EsGB5#&5l= z7L!T8yuZ}0QpZcNj~@rp%*)8Np05(`xwqjkNapc?qXBOE@v)&SDT;Cnj2pmAwN70O z*1 zBgS2_cs;j)(%oP@^1`30<-Ka&9w~Gos9l=NN%?SVMZvtaM%?}Ub@f@FFk^nAAsK%0 z+tL9KS#$eoKpu_Hlf257A&1fqf_bp;)yOd*29eR~j#r|x{-}2=vR6(?s?Dq+~9hnCd=*IY*FNS zE#CDN&m!H-iJL!@t48EQHQhx~$XL?UR9D`c1w_x5*X%e&&p+Z2rlTK^$?WChy zUkbsxSsT|2%ull^(iF4uklDpEPgU+9&VW|Z>}w-UuElBr2YeSL^5rdheH zxCG&B8gK0tRkrUuN}^^WoM4s=9$x_LmQz2@g<$M#0I&Na1f_&Snh>ck=Gl z47`4{Kx&&)VLUx=*2?1bW6F>lb((ZOmNtqTU2J9^ zpRBtPk%3q*0@3qxw4mQ^gBM z6331yNG^@!H2b70NV>?Q4{3dyLLQ(SGxpiHX_}0-M)yeZi|JVs8^t4Qr;*S7Gp%B} z(LINC`EpN8rXh-ap%aix=m~BU_gSk5ONoD0hTjnhe@%stpeH10Qq_1WiIlSz5kcFo z+=}-44nZ2a8~zNE8F)Z!{hq{RTm6f8$MdwN)+4vs3l?YY2gCyRD*7G-*yRL0whXAA zEz8%EOv4)x-5`l5P5_T=9B6|;GopPDX6dCx>4!P{7(ESng&%bu|AFx4VP2jMutuk( zrS&b>u6$dQ5!tlQn~O;aqx8rx2^y*WwZGst;%w)+g%BOl+qi5P@RJdufAI}s9bXVQ zDKO4JNP_gxdBChj0LB}z?rhsf5!`5`crsrRKdEyQL!B+cT3-A9EPBle31XAc#ZgpH zyuvlU0G@gbry2u%UZ#a33`Xk&n=0#z=i+U%wNbLH87IlyE1G1GMw6h-+)P9eVN-qtGq?1e1e9 ze8(keTtYE9e|r*DFusPtX05hUkw3M1`md86=gFYQn34G>AldC^P&o4(V@- z@$!+6<16?K33Kw^6h6AZ*7JyCj+t;>GDDl-#%DxYqp4enL(G}!C_$agRK9;B!;b^5=F$(du7~$c#mT41C z#hrG&vmx5ngRmSF@G`POJ_MFPBXtQ201w>W=dC$PJHaV`!%ai z<(z%lB5(CIC`qX-C3z|rF{1`!D2$}DJ)8FScekGQJ=`m|7M54n*G5xUc8gSjlqGB5 zf{yU(#4(q%k))s-Z&ln2r5udlTPOQ2=wOWI-uh$K>BH)W6uN6xIs!zmoKlsUx6SIj z5XyBn&aZwBWUeG`&eyt)IL_{9lW-xmj-+!}w7SR7##(islmOd_ziIbjl^b&M@#CF- z3>JxN^=UiV=`-_sU`z3H`jniKnC&zkYqAjV{UX1i#EI-3kB&!6~Wf|%WpBQ`BX${GfO z55@DnCO0_<7NWM7P0I{~4TNbci^cMqTu5 zQw%PX^pp~y8=t=jt2Euz*>#oj+94Y8iOcJF{21Yf`Z=hTBgXFA-1Qt zp-!|Ezb>t970QW_WMr!L9YOI+-Iu5>aO~I^JG+nz#$B#@li)K1$h;7iuU1YgC2?37 zoxTxmVHWbCyY)X_)qH|GQpJ@)s<**%&bVh3F_AKsGa;rh6g*&tU2F%=u|WAW;*E#jrwWqNO^s6CBy`8>A*Vyn>OZrdnw z(5m{v57$Vmn-@ZWoSNJQ;D=|Mgmw`W16(+?b>%Unzcvk+XL_YR6X0!S$HiKNRtq5u4=xrX5$m!Qv5(Tda61l`da2bEta<)ik8L@+l_z8%_l$koV93h-SLs z=MghiVc~L@kj1I4$t^y0GcM!xg{|RfQ4rqv!pw7P+LKli{Mo9p$*h)3NmgOGC~mnY zHVr#q^Ov54+kyta%%E=MfnoiRmOTe2w?1Ys!%4j=tA@L(iQm9H zJ1+1x{SG_InmFcYUb%zwqOxk3)EG3tx&3*XR>JA9*9a36 z@Ee*Z!0HNWhEK^W>|fz*zXQ)v#=M0)&DF+m5bm3tNf9mrS+vw%^|)>4lF#wR_tqUF zWMKm)&27X*Y~DGf0lW(-`B4+8-xt^OnU#*R!i_4F)m-m8md#wR=3nmCXd-uz_`sl0 z_#O3?<9xl#geXyr%);P4MPRbheLQxw7dtFX^sOMED!E}E_=k} zpX-CuZ90p(a9kZSS3m_K((Z-#Ua0sPM&p{(l%D*c5!pLlWmy6>R!|c%^P!%@mSQKUWnz&U!8} z>M|;^OukSp(kn`hf#$nHPiwoq z?4Q&wRQ0uR)Whudz<`$tvYR6~3FW#gp8xHCsQFE0>Q&{K+(FGyyceit zSz`Y&j0T&I+r#>=N;vw7w71MNG}ruItl8@EV)sf9I(Wq8&5ja(mfOAsJoakHr03j%&7t(NOzhA6nq zV<;Zd5Bwd73oY?O25}SA&>`X%f<9{$sWMr^K5D^T^ICQ@UM7h+gP*n47<=pz=*sQd3^X;q|Rxa`6LP zy$)%qTJ6jx4H%cS-vHvAQ)?}6>{i&__W?EFRbh;4rf03n<~~a=p>vymFduZ@-wznT zc^N`2T#FG6U72q0{ERD|+8pjOp@h@dSkIN~_RndX@W`(?y!x+Hf8M>f!E`de?v0yG z_jUMn_}RjzRLUl9e`!;jjO7m|T+qNpep`lXF?Hi5u-27tU;S+|4IW9=|3BQlXH=8v zyEi&20xBSiBE5*>jM4-`=m@CDAfO_>i`0epfDkwj>g+x9e`oLW>8y3u>j#(1_2h0>|6SL0-z9qNwJx@$x^Xpxoyk-JZqV4! zEw%iQk>w0ql+p+_P=5t)Ia|DShwS_ArxLw+eKCze_=$;8KHx4HA$PRc2@O?e8LqSp zeq=umr-bH94Ugg$nn^1jkD0?OTbh#8sV|SPc{6qLCS%eV-!TbH&5*k^h(gR({u?m_ z!P;GNV;>8+`e@15&BQ$m|Jz(0E~zIj?Y~o+_!L1*_HjJA>;qw}6fM=5nnjxb*0V)uMyzSAo=OeEQCiNJ)P; z^WMH_m&XN( z-^Kzdx=RtMzB%|>51)^jlXWnw74)6|RS`ROrX=oJ>u7vG!r^9@Z!cVdJQ=^PT5J$C zNseR@`FfjoN-cyaV)|Bk^LB4pR@eCO<^rUTDxSmBrkds)#vAUp%Q zFAf3#=oRLWp_;KlqvwT{VP}PC$&ENUl5?lnn5#2``0G-KQ9;J`%du?X{j|)$=e!o% zA@DlxF5I#3Zq*ik6Zp*)Bh=bPKM}KVGqa!fTAacUhzwJI=X1Hp3&?b1j?SatGu8H|6HF+U|k-cwo0Hr z@W{0Qou1Dq#Y6Q3ygt+9F#gN?&ugxZ=m*g91>KeU9&Pc!dj-VLdH78GYW^=YJsy7c z+vN^uMQe$}K9E6{B1&um?!{F>nX%S|38TXk4ep_<%A_W@L80L{!a@CUu;MB8oQ9;5&Jb&6$0-X%1#tVQJsG3J8H8eO#Wo%R#xprLnS64vgVN zStoXG)eUs|wF#p4m*qp*F1OAWCL4WMyv(eZR_mErvzim?4KYU5%eJ)VT9A{L{_N_F zS|E<{hWmu&F1ikh!Hxn?3xAed12^6Z^q}P=-c2 z#9X~pRmf~i{qjm>)hgt0puXz%lq?sn$Ob}#$zLA69WgK^*KqxMKp@}l*!M1_T?Ig_ ztQQe)8v3BMQ$b+AVZoa5UebG^tw%@pzwk?68ganiM0u_VQ3(%I)zX3{zjLFKhcf)# zKX!&K#qTZofkUTnqM-PTOS_FgW`Doy(9);Z=@#jefs{5$9Ys6)6LYGInW^;yOx zq65@##V&qAm?UIkwU8tj`aH1Fi|sbmYr<=9pw7YFUy4_ue*Y-HiHJNpc#MgFIB6&_ zV1>8-LUK^$oCsea%Yk$~s-JAucOQ_|YM@ovdD$=Sju_^#8`ggZA|DwQ|O&15i z{hhqWAVNi2)m6`IdcHZ@xXRPWkNQ~K(ymuOigw$r)EKH(cmJln5Y>MTHTU`3X^22( zF_UZ2ksysV3&FmRr-lZ`1f2gzkISba+-B~Gb^b_W${)2p3%L2%$(swz)DjXu!?I6} zT(S3hykD8p%BKiIEfG*1CI7px3%LAADXc~8!%R)@C^+^dH>?t~DxTl-ZIYW`a%xrW z=3#f@z;Vl%JfB4qi(}!ZPAOedXFi`~I4=nN^(#_2%@9aw?7hdHa#V~oeZJHJP$0kJ zl7I6UeQrnCwA{JkE&l$0W}MRucGwDyq4WQ?ZR?90~k_SsT)SDBGd(TB`@`AV3x@B@8Q;Q5tdD1XWlqv&l< z8O|baUevND9$f5wV$An`0Dch^7>AWDC6*%7h0vX|qm>V%c)8w8CN1`Llg=_&FU{zt zOo(;@fmcab>N#{i2P0v_K+@OT7YZNZ6uyH5V)-j8sH&W_z;!S84zbkrbSON3eC zrQMppbE9&1E)?&$D%CwF?#nLStD6SE(3Yhm z!ww0lY6=*)f~MylyNj|Pb6qr67w=!Y!5&Ky171~NmdHsz8Qy+L-QDi*M3@osqmA?@ zbhT;2M#g%nWMaTmbIjUtIMf}#f-r<3_II{VX;s_JB0XxFFLL%JizKruMg_{TU>g6> z%Et3wweMjSPX{Y9kCivFvg-M8Fue?Bz3pwlbPm%=^R_0<{z)aj#^foqKC9%ng-l2- z`W68?Tt!-`UL@XU9k*D_`ZXGkHuOT|3*fJM8DYE}T4~3Sk=a@&?K3N7vr{J=#0Md1 z_f#@3NeoYHK8)8^8mcDp`pPzYB}hzP#Ue*fNgTQ3U!OcH=2hOeZsA{-$hL48^>Jr# z?GSjCOT{-6U*}*&h9K%UE!M||Y6bVw7_sx+C4<{g-$jM4IOm-Vz6FG`22Iy$Xh0q1 zv|j&$)^C?Q*LBi5S2Zvz>DmZMjwLRLVm14qtAM|eCRq16StQ~eXUMtD#o`dT1=gNE z{G~3R1qjS~c}6q>9?IfhHJ9_5O~V0mG=(BJzk4xrTSwo6;}YNOOt+ftKw$rOs=86g z&i>GH)}76je$JzIomK#@1Vff>96>-hNB*1!PRW{ z$IcZpR;|@XmXxjSuLN`ZlNCl!F9x=o@86v7U%?53RknjOUJd*x-k`o zsMa}T8q&W$gdw+)%_USTJ!2bPUymYIzXK2dWjE(cvpBFg3*w2@+h&S(1*r{f@cB&u zKe%*}ziDo1AO?lDtf@jLmggENmV%Bv@A;jtt*I+aBnO=wBPZHj{@F69Aj2`czuGN6 zG_Id8_xjTQcpa*5j^Ao|X5M1Ut2{WJH{}IiclH#>utC(yUzNNMJt2|DxRW@fI)O+@ zPN&7i^sOt}_FaJA|Jd+>7nMsh_tTKR#>M4*B?$e|Fi(Y#u8F@^)BHr#IMf2_tb+dY^RJQQuEe8Q?B`0^Q%w~oqk34m*z?7ObzkcGMw4% zd9LH=fzFJA(W^tqZaN?<9+~(AS1*jihQ1QfGGjNCI`(xo&)+=UzO;hUjnb}PmWK@9 z>KQCmONJWQ;f#6ZFE5(GlXW819W7*Tx|sPmS47e8 zlI=>&uR2lGngHSH51vu*ZMZP7yTNDlI`X)SDWQZpRDd4cAjVf*lYKv<-fdSvRt=n} zcA5p9Uv6xqs&8tp;Jlf#xc(}OsJ(y7gtsE6q;iJ|kp|WDiP$UCWDs_t`URlL{g1yv?-fwx<{B8FrZjhw4AR(K#vtsc3R zA2&%Y1`@1_c8T`V1z|14pO+$!9a+k@pNx%Cfz6pW(_3y%-s1EXKsh;<#$An&SyC1? z>e{|F3j&>R7wxjlBpUhGkJ24Wg4dK$!t&G_PDqu$>G`z;;#8X#F=fKT z{9LOJ_x+4=2j?f>x4ifR$GkWK=$>%k5lz@qij7c>&%0Dk0sR26%FO)K&0_Zm?b({@ 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 V+}8!aD6?VcUkxswFVJ&{`aiY4wDJG| literal 0 HcmV?d00001 diff --git a/media/google_cloud_top_left_navigation_menu.PNG b/media/google_cloud_top_left_navigation_menu.PNG new file mode 100644 index 0000000000000000000000000000000000000000..23f44d957436a315c180601ab4717750e6522bdc GIT binary patch literal 6569 zcmbVRc|25Y`#;0PFqX0J#-LCN*-01`3MoArWG_Qy3u8C7L1m4EtWm0m82b{&I%H4T z#=e(*Cu6+hdEe*r`ThO-dDLvYmZ2nb87BM2`A@S7WlDJp zHbfBAydlqYs6v`l@~FeF^Ht$~=Y3bzh?=4HFEgf}K3+5{-w?a|(DuUj*Pds`_h&up zOOM8nNFKdiJy+MphxX~=81IFz=mm29VprVnu%kSr?C63hx9{qbaQ^Wt?=Gu7ezXm-S>i;&^HFt0vRNvRoq6m?27}8Ug zo#s@e7yJK+1Lwi@o4NLDStoW07Ub?~xuVIf`)f9+hyE8T7Bd)pg zR@u<~w?xC%&zU8-Xb6k2JZOxCxK1o36XBF<2L`Hrl$r?-LUx%lfS1o7h~ORGBx09? z{=AWKz)Vz59vQ8yNHMkJCjZ=&8?S#`KevGO*Osk6h46g70|HYEtLEE9SC=7`fZ~Q;C?`LirH^QLYtdf@G zgF5Z2dl(S+*`US96Je$cr-^w|^{5?PbaaBRWS3`1Dx^T$hJsQTkvqlxp3z^(DWdn6 z^J=zV1w=R<&Q+}!DRU07=rKX4K)p7>!-7lSZ@2ylzA>45(wJV@x;2#ya)2VIPa%?f z{URJlm(JRc94K5I0F?uB!Iwc}mm#=MII}oQH&&NrkKQ`>y7s!|B5-pB&7@gCN4J@~ zDurp4T35g7Lv9)$IFJP+K)#Ml>_tj&OVVwa&l;!PJZwwk8IL^?cGDkJmSuZM1Hl=S z9p;ya&F+Vre52N`eX&nscWM(Cb!P*d8h#7Cth8@{qn*oy=ASs=w+2=N-TA0yuG$(f zrIuxh2)i6UwYXsxv#pOjlJq@Kl3f?^AvP*<45Tj6oQvkT5+qOxpqSc!dD~>cv?SK7 zfnCu#k?(|~Gm`h}{d;q4QVOzXak-Uy+H>v0s^(!jPu{=GoF}3ku^J({y>==SO2VB{ zsnFWGR1~=_rYib?X|*z2c%EtTEmjyWR5EvmHNF8maSM_ZxfrUr1I;N$DhNDB0`fqL zLnRF`c}xVCdb<5Ie{Td-o-cNUJ!&m{`Pf>YiA}3kNrlaNj^fDNfEPMKz{J5HngVPV zFU3_K`WJDz>Q5z#J?3|?CRe@Aq?Kn-Kan;XwUU6`R+-6fWUv5r1)6P1(tiWKgO$+E zZdS7gNl=-supIGbRrremzn$vlp?8dy0?%0K_U|`)=1F}rekp8yBvAx#VNd|!h2FzU-guHS%dJf#rgSkUbR~(859>ZBEAg1D9{y4 zSe61i>N}Z5I>h1h7SR%sjD<=+MOMrUv5>@Zr=lxwifUbT!tB?MXNSgD>`)9L4z@2~ z1QTEnOS@4Y>|n;3!c}VpG>LGYW59eZcEBLZWyg^OwYmZ^QS6TqCnR8l0q7PRo#my# zPx(l@V_7VcQ?Cj%MoaD@WEWz;j;{}L@p+z%sIxhHeK~o6)n?LzC_qiZgT3Aj9DbYn z1-6TDg}2m%7^lE6*Y2$!z2oJ|)&b01#qRM(PP;bu%E^S#%hHBy{h59$a4x1Rp1V1G&t842$&bDk^L_$Jn0Pg#RG}luS^?@*lwr3F z5^^4QbiCkFY75JXSZ8W>+|wBa9%T$hv~v6JvIi~K>`QW?f+5aK~j zNw>mY)nP=1txA+#vcOnn&g;x8pYK7Ut6rPzS;p>ZE5y_)*KS%Mv&|&gXm}4j47J3p zIq$J<%mHT%2g_;F-$ndf7QL=Z>>1x4aqT8s<&U;;^%dCePX9!QGpnV0 zts76-Qn*a@(PXB