en-us/Creating_a_CitiBike_Station_Finder.walkthru.help.txt
<#
PowerShell Pipeworks is especially effective at creating quick sites around an existing service. In this sample, we'll walk thru creating a little bit more searchable view for [CitiBike](http://citibikenyc.com/stations). To start off, we need to create a folder to hold the module. #> New-Item -Path "$home\Documents\WindowsPowerShell\Modules\CitiBike\Pages" -ItemType Directory -ErrorAction SilentlyContinue -Force | Out-Null <# Next we'll create the PSM1 file, which tells PowerShell how to initialize the module. In this example, we'll include one function defined in the file Find-BikeStation #> { . $psScriptRoot\Find-BikeStation.ps1 } | Set-Content "$home\Documents\WindowsPowerShell\Modules\CitiBike\CitiBike.psm1" <# Now we'll add a PowerShell module manifest. In this manifest, we'll specify the version of the module, the .PSM1 file we will include, a format file, and a dependency on Pipeworks. The format file will make our CitiBike finder a lot more functional and fun. We depend on Pipeworks so that we can use the formatter built into Pipeworks for [http://schema.org/Place](http://schema.org/Place) #> { @{ ModuleVersion = 0.1 ModuleToProcess = 'CitiBike.psm1' FormatsToProcess = 'CitiBike.Format.ps1xml' RequiredModules = 'Pipeworks' } } | Set-Content "$home\Documents\WindowsPowerShell\Modules\CitiBike\CitiBike.psd1" <# We also need to have a Pipeworks manifest. In this manifest, we'll register one web command: Find-BikeStation, with a friendly name. #> { @{ UseBootstrap = $true DomainSchematics = @{ "CitiBike.PowerShellPipeworks.com" = "Default" } WebCommand = @{ "Find-BikeStation" = @{ FriendlyName = "Find a Bike" } } } } | Set-Content "$home\Documents\WindowsPowerShell\Modules\CitiBike\CitiBike.Pipeworks.psd1" <# The Find-BikeStation function is fairly simple. It contacts CitiBank to pull down a list of Bike Stations and caches it in memory. Then it compares the query you entered to the list, and returns all matching items in one object. It's very important to note that the output object is given it's own type name, which lets us format the object however we'd like. The code that does this looks like so: $bikeStations.pstypenames.clear() $bikeStations.pstypenames.add('Citi.Bike.Station.List') $bikeStations #> { function Find-BikeStation { <# .Synopsis Finds bike stations .Description Finds CitiBank bike stations in New York #> param( # The Location Where You'd Like to Find a Bike [Parameter(Mandatory=$true,Position=0)] [string]$At = "" ) if (-not $script:CachedStationsAt) { $script:CachedStationsAt = [DateTime]::MinValue } $elapsed = [Datetime]::Now -$script:CachedStationsAt if ($elapsed.TotalMinutes -gt 10) { $script:CachedBikeStations = $null } if (-not $script:CachedBikeStations) { $bsi = Get-Web -Url "http://appservices.citibikenyc.com/data2/stations.php" -AsJson -UseWebRequest | Select-Object -ExpandProperty Results $script:CachedBikeStations = foreach ($bs in $bsi) { $parts = $bs.Label -split " " $newParts = foreach ($p in $parts) { if ($p -as [uint32]) { $lastDigit = $p.ToCharArray()[-1] if ($lastDigit -eq '1') { ($p + "st") } elseif ('2', '3' -contains $lastDigit) { ($p + "rd") } elseif ('4', '5', '6', '7', '8', '9','0' -contains $lastDigit) { ($p + "th") } } else { $p } } $bs | Add-Member NoteProperty Location "$($newParts -join ' ')" -Force -PassThru } } $stationList = $script:CachedBikeStations| Where-Object { $At -and $_.Location -like "*$At*" } $bikeStations = New-Object PSObject -Property @{ At = $At Stations = $stationList } $bikeStations.pstypenames.clear() $bikeStations.pstypenames.add('Citi.Bike.Station.List') $bikeStations } } | Set-Content "$home\Documents\WindowsPowerShell\Modules\CitiBike\Find-BikeStation.ps1" <# In order to make the output of the function look good in a web site, we want to create a formatter for the results. The next chunk of code is an [EzFormat file](http://ezout.start-automating.com/Writing%20An%20EzFormat%20File/). It assumes you've loaded the module [EZOut](http://ezout.start-automating.com), which makes writing PowerShell formatters a lot friendlier. This particular ezFormat file is very simple. It creates one #> $ezFormat= { $moduleName = 'CitiBike' $ModuleRoot = "$home\Documents\WindowsPowerShell\Modules\$moduleName" $formatting = @() $formatting += Write-FormatView -TypeName "Citi.Bike.Station.List" -Action { $data = $_ if ($request -and $response) { foreach ($Station in $data.Stations) { $l = New-Object PSObject -Property @{ Latitude = $station.Latitude Longitude = $station.Longitude StreetAddress = $Station.Location Locality = " " } $l.pstypenames.clear() $l.pstypenames.add('http://schema.org/Place') "<h2> $($Station.Label) </h2> <h3 class='span4'> $($Station.AvailableBikes) <span style='vertical-alignment:middle;font-size:.66em'> Available Bikes </span> </h3> <h3 class='span4'> $($Station.AvailableDocks) <span style='vertical-alignment:middle;font-size:.66em'> Available Docks </span> </h3> <div class='span6 offset2'> $($l |Out-HTML) </div> <div class='span9'> </div> <hr style='line-height:200%;clear:both' /> " } } else { $data.Stations | Select * | Out-String -Width 10kb } } $formatting | Out-FormatData | Set-Content "$moduleRoot\$ModuleName.Format.ps1xml" } & $ezFormat $ezFormat | Set-Content "$home\Documents\WindowsPowerShell\Modules\CitiBike\CitiBike.Ezformat.ps1" <# Now we can import the module, and find any bike station on Broadway #> Import-Module CitiBike -Force -PassThru | ConvertTo-ModuleService -Force -Do "http://localhost/CitiBike/Find-BikeStation/Broadway/" |