GoogleDirections (empty) → 0.3.0.0
raw patch · 5 files changed
+403/−0 lines, 5 filesdep +AttoJsondep +basedep +bytestringsetup-changed
Dependencies added: AttoJson, base, bytestring, containers, dataenc, download-curl
Files
- GoogleDirections.cabal +64/−0
- LICENSE +30/−0
- README +0/−0
- Setup.hs +2/−0
- src/Google/Directions.hs +307/−0
+ GoogleDirections.cabal view
@@ -0,0 +1,64 @@+-- GoogleDirections.cabal auto-generated by cabal init. For additional+-- options, see+-- http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/authors.html#pkg-descr.+-- The name of the package.+Name: GoogleDirections++-- The package version. See the Haskell package versioning policy+-- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for+-- standards guiding when and how versions should be incremented.+Version: 0.3.0.0++-- A short (one-line) description of the package.+Synopsis: Haskell Interface to Google Directions API++-- A longer description of the package.+Description: An interface to the Google Directions API++-- The license under which the package is released.+License: BSD3++-- The file containing the license text.+License-file: LICENSE++-- The package author(s).+Author: Favil Orbedios <favilo@gmail.com>++-- An email address to which users can send suggestions, bug reports,+-- and patches.+Maintainer: Favil Orbedios <favilo@gmail.com>++-- A copyright notice.+Copyright: (c) 2010 Favil Orbedios++Category: Network++Build-type: Simple++-- Extra files to be distributed with the package, such as examples or+-- a README.+Extra-source-files: README++-- Constraint on the version of Cabal needed to build this package.+Cabal-version: >=1.2+++Library+ -- Modules exported by the library.+ Exposed-modules: Google.Directions+ hs-source-dirs: src+ + -- Packages needed in order to build this package.+ Build-depends: containers+ , bytestring+ , dataenc+ , base >=4 && <5+ , AttoJson+ , download-curl+ + -- Modules not exported by this package.+ -- Other-modules: + + -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.+ -- Build-tools: +
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2010, Favil Orbedios++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Favil Orbedios nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README view
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Google/Directions.hs view
@@ -0,0 +1,307 @@+-- Author: Favil Orbedios <favilo@gmail.com>+-- Maintainer: Favil Orbedios <favilo@gmail.com>+-- +-- Copyright (C) 2010 Favil Orbedios, all rights reserved.+-- +-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- any later version.+-- +-- This program is distributed in the hope that it will be useful,+ -- but WITHOUT ANY WARRANTY; without even the implied warranty of+ -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ -- GNU General Public License for more details.+ -- + -- You should have received a copy of the GNU General Public License+ -- along with this program. If not, see <http://www.gnu.org/licenses/>.++{-# LANGUAGE OverloadedStrings, FlexibleInstances #-}+module Google.Directions (+ TravelMode (..),+ directions,+ Waypoints (..),+ Avoidable (..),+ Units (..),+ Directions (..),+ Route (..),+ Distance (..),+ Duration (..),+ Coord,+ Leg (..),+ Step (..),+ PolyLine (..),+ StatusCode (..),+ ) where++import Network.Curl.Download+import Text.JSON.AttoJSON as JSON+import Data.Ratio++import qualified Codec.Binary.Url as C+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as S+import qualified Data.Map as M+++data TravelMode = Driving + | Walking+ | Bicycling++instance Show TravelMode where+ show Driving = "driving"+ show Walking = "walking"+ show Bicycling = "bicycling"++data Waypoints = Waypoints Bool [B.ByteString]++instance Show Waypoints where+ show (Waypoints _ []) = ""+ show (Waypoints optimize points) = + "&waypoints=" + ++ (if optimize then "optimize:true|"+ else "")+ ++ showWaypoints points+ where+ showWaypoints [point] = C.encode (B.unpack point)+ showWaypoints (p:ps) = C.encode (B.unpack p) ++ "|" ++ showWaypoints ps++data Avoidable = Tolls+ | Highways++instance Show Avoidable where+ show Tolls = "avoid=tolls"+ show Highways = "avoid=highways"++showAvoidables [] = ""+showAvoidables as = '&':show' as+ where show' [a] = show a+ show' (a:as) = show a ++ showAvoidables as++data Units = Imperial+ | Metric++data Directions = Directions {+ status :: StatusCode,+ routes :: [Route]+} deriving (Show)++data Route = Route {+ summary :: B.ByteString,+ legs :: [Leg],+ waypointOrder :: [Integer],+ --overviewPolyline :: PolyLine,+ copyrights :: B.ByteString,+ warnings :: [B.ByteString]+} deriving (Show)++data Distance = Dist Double B.ByteString deriving (Show)+data Duration = Dur Double B.ByteString deriving (Show)+type Coord = (Double, Double)++data Leg = Leg {+ steps :: [Step],+ legDistance :: Distance,+ legDuration :: Duration,+ legStartLocation :: Coord,+ legEndLocation :: Coord,+ startAddress :: B.ByteString,+ endAddress :: B.ByteString+} deriving (Show)++data Step = Step {+ htmlInstructions :: B.ByteString,+ stepDistance :: Distance,+ stepDuration :: Duration,+ stepStartLocation :: Coord,+ stepEndLocation :: Coord+} deriving (Show)++data PolyLine = PolyLine {+ points :: B.ByteString,+ levels :: B.ByteString+} deriving (Show)++data StatusCode = OK+ | NotFound+ | ZeroResults+ | MaxWaypointsExceeded+ | InvalidRequest+ | OverQueryLimit+ | RequestDenied+ | UnknownError+ deriving (Show)++directions :: + B.ByteString -- The origin address+ -> B.ByteString -- The destination address+ -> Maybe TravelMode -- The mode of transport to use+ -> Maybe Waypoints -- Should google alter a route with waypoints+ -> Bool -- Should google search for alternate routes+ -> [Avoidable] -- Should google avoid tolls and/or highways+ -> Maybe Units -- the unit system to use+ -> Bool -- sensor+ -> IO (Either String Directions)+directions origin dest travelMode + waypoints alternate + avoidables units sensor = do+ let url = "http://maps.googleapis.com/maps/api/directions/json?"+ ++ ("origin=" ++ C.encode (B.unpack origin))+ ++ ("&destination=" ++ C.encode (B.unpack dest))+ ++ (case travelMode of+ Nothing -> ""+ Just mode -> "&mode=" ++ show mode+ )+ ++ (case waypoints of+ Nothing -> ""+ Just points -> (show points)+ )+ ++ "&alternates=" ++ if alternate then "true" else "false"+ ++ showAvoidables avoidables+ ++ (case units of+ Nothing -> ""+ Just Imperial -> "&units=imperial"+ Just Metric -> "&units=metric"+ )+ ++ "&sensor=" ++ if sensor then "true" else "false"+ string <- openURI url+ --putStrLn $ show string+ return $ parseDirections string++parseDirections (Left err) = Left err+parseDirections (Right json) = + case parseJSON json of+ Left err -> Left err+ Right jsvalue ->+ parseDirections' jsvalue++parseDirections' jsvalue = case JSON.lookup "status" jsvalue of+ Just (JSString str) -> Right $ Directions (parseStatus str) + (parseRoutes $ JSON.lookup "routes" jsvalue)+ _ -> Left "error, can't parse"++parseStatus "OK" = OK+parseStatus "NOT_FOUND" = NotFound+parseStatus "ZERO_RESULTS" = ZeroResults+parseStatus "MAX_WAYPOINTS_EXCEEDED" = MaxWaypointsExceeded+parseStatus "INVALID_REQUEST" = InvalidRequest+parseStatus "OVER_QUERY_LIMIT" = OverQueryLimit+parseStatus "REQUEST_DENIED" = RequestDenied+parseStatus _ = UnknownError++parseRoutes :: Maybe JSValue -> [Route]+parseRoutes routes = case routes of+ Just (JSArray jsRoutes) -> map parseRoute jsRoutes+ _ -> []++parseRoute route = Route + (case JSON.lookup "summary" route of+ Just (JSString sum) -> sum+ _ -> error "summary parse failed"+ ) + (case JSON.lookup "legs" route of+ Just (JSArray legs) -> map parseLeg legs+ _ -> error "legs parse failed"+ )+ (case JSON.lookup "waypoint_order" route of+ Just (JSArray warns) -> map + (\warn -> + (case warn of+ JSNumber n -> numerator n+ _ -> error "warning parse failed"+ )+ ) warns+ _ -> error "warnings parse failed"+ )+ (case JSON.lookup "copyrights" route of+ Just (JSString s) -> s+ _ -> error "copyrights parse failed"+ )+ (case JSON.lookup "warnings" route of+ Just (JSArray warns) -> map + (\warn -> + (case warn of+ JSString s -> s+ _ -> error "warning parse failed"+ )+ ) warns+ _ -> error "warnings parse failed"+ )++parseLeg :: JSValue -> Leg+parseLeg leg = Leg+ (case JSON.lookup "steps" leg of+ Just (JSArray stps) -> map parseStep stps+ _ -> error "step parse failed"+ )+ (case JSON.lookup "distance" leg of+ Just (JSObject m) -> parseDistance m+ _ -> error "distance parse failed"+ )+ (case JSON.lookup "duration" leg of+ Just (JSObject m) -> parseDuration m+ _ -> error "duration parse failed"+ )+ (case JSON.lookup "start_location" leg of+ Just (JSObject m) -> parseLocation m+ _ -> error "start_location parse failed"+ )+ (case JSON.lookup "end_location" leg of+ Just (JSObject m) -> parseLocation m+ _ -> error "end_location parse failed"+ )+ (case JSON.lookup "start_address" leg of+ Just (JSString string) -> string+ _ -> error "start_address parse failed"+ )+ (case JSON.lookup "end_address" leg of+ Just (JSString string) -> string+ _ -> error "end_address parse failed"+ )+ +parseStep :: JSValue -> Step+parseStep step = Step+ (case JSON.lookup "html_instructions" step of+ Just (JSString string) -> string+ _ -> error "html_instructions parse failed"+ )+ (case JSON.lookup "distance" step of+ Just (JSObject m) -> parseDistance m+ _ -> error "distance parse failed"+ )+ (case JSON.lookup "duration" step of+ Just (JSObject m) -> parseDuration m+ _ -> error "duration parse failed"+ )+ (case JSON.lookup "start_location" step of+ Just (JSObject m) -> parseLocation m+ _ -> error "start_location parse failed"+ )+ (case JSON.lookup "end_location" step of+ Just (JSObject m) -> parseLocation m+ _ -> error "end_location parse failed"+ )++parseDistance m = Dist+ (case m M.! "value" of+ JSNumber n -> fromRational n+ _ -> error "value parse failed"+ )+ (case m M.! "text" of+ JSString s -> s+ _ -> error "text parse failed"+ )+parseDuration m = Dur+ (case m M.! "value" of+ JSNumber n -> fromRational n+ _ -> error "value parse failed"+ )+ (case m M.! "text" of+ JSString s -> s+ _ -> error "text parse failed"+ )+parseLocation m = + (case m M.! "lat" of+ JSNumber n -> fromRational n,+ case m M.! "lat" of+ JSNumber n -> fromRational n)