{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DisambiguateRecordFields #-}

--module T1 where
import GHC.Generics

data Station = Station
  { id :: Int
  , name :: String
  , terminalName :: Int
  , lat :: Double
  , long :: Double
  , installed :: Bool
  , locked :: Bool
  , installDate :: Int
  , temporary :: Bool
  , nbBikes :: Int
  , nbEmptyDocks :: Int
  , nbDocks :: Int
  } deriving (Eq, Show, Generic)

zoo = Station 
  { id = 271
  , name = "London Zoo, The Regent's Park"
  , terminalName = 1136
  , lat = 51.53583617
  , long = -0.156285395
  , installed = True
  , locked = False
  , installDate = 1279720920000
  , temporary = False
  , nbBikes = 28 
  , nbEmptyDocks = 2
  , nbDocks = 32 }

-- Calculating distance between two coordinates:
-- From http://rosettacode.org/wiki/Haversine_formula#Haskell

-- The haversine of an angle.
hsin :: Floating a => a -> a
hsin t = let u = sin (t/2) in u*u

-- The distance between two points, given by latitude and longtitude, on a
-- circle. The points are specified in radians.
distRad :: (Floating a, Ord a) => a -> (a, a) -> (a, a) -> a
distRad radius (lat1, lng1) (lat2, lng2) =
  let hlat = hsin (lat2 - lat1)
      hlng = hsin (lng2 - lng1)
      root = sqrt (hlat + cos lat1 * cos lat2 * hlng)
  in 2 * radius * asin (min 1.0 root)

-- The distance between two points, given by latitude and longtitude, on a
-- circle. The points are specified in degrees.

distDeg :: (Floating a, Ord a) => a -> (a, a) -> (a, a) -> a
distDeg radius p1 p2 = distRad radius (deg2rad p1) (deg2rad p2)
  where deg2rad (t, u) = (d2r t, d2r u)
        d2r t = t * pi / 180

-- The approximate distance, in metres, between two points on Earth.
-- The latitude and longtitude are assumed to be in degrees.
distance :: (Double, Double) -> (Double, Double) -> Double
distance = ((* 1000) . ) . distDeg 6372.8
