souplesse

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

Point.elm (2739B)


      1 module Point exposing(Point, decoder, downsample, duration, subseq, startTime, centre)
      2 
      3 import Json.Decode as D
      4 import Pos exposing (Pos)
      5 
      6 
      7 type alias Point =
      8     { time : Float
      9     , pos : Pos
     10     , cadence : Maybe Int
     11     , power : Maybe Int
     12     , heartRate : Maybe Int
     13     }
     14 
     15 posDecoder : D.Decoder Pos
     16 posDecoder = D.map3 Pos
     17              (D.field "lat" D.float)
     18              (D.field "lon" D.float)
     19              (D.field "ele" (D.maybe D.float))
     20 
     21 
     22 decoder : D.Decoder Point
     23 decoder = D.map5 Point
     24           (D.field "time" D.float)
     25           (D.field "pos" posDecoder)
     26           (D.field "cadence" (D.maybe D.int))
     27           (D.field "power" (D.maybe D.int))
     28           (D.field "heartRate" (D.maybe D.int))
     29 
     30 
     31 last x xs =
     32     case xs of
     33         [] -> x
     34         (x_::xs_) -> last x_ xs_
     35 
     36 -- divide the points into n equal time buckets and return the first
     37 -- point in each
     38 downsample : Int -> List Point -> List Point
     39 downsample n points =
     40     let
     41         nextpoint step prev points_ =
     42             case points_ of
     43                 (next::rest) ->
     44                     if next.time - prev.time > step
     45                     then prev :: (nextpoint step next rest)
     46                     else nextpoint step prev rest
     47                 _ -> [prev]
     48     in
     49         case points of
     50             (first::rest) ->
     51                 let step = (duration points) / (toFloat n)
     52                 in nextpoint step first rest
     53             [] -> []
     54 
     55 duration : List Point -> Float
     56 duration points =
     57     case points of
     58         (p::ps) -> (last p ps).time - p.time
     59         _ -> 0
     60 
     61 startTime : List Point -> Maybe Float
     62 startTime points =
     63     case points of
     64         (p::_) -> Just p.time
     65         _ -> Nothing
     66 
     67 type Bound = Bound Pos Pos | NoBound
     68 
     69 extendBound : Pos -> Bound -> Bound
     70 extendBound pos b =
     71     let {lat, lon} = pos
     72     in case b of
     73            (Bound p1 p2) ->
     74                Bound
     75                (Pos (min lat p1.lat)  (min lon p1.lon) Nothing)
     76                (Pos (max lat p2.lat)  (max lon p2.lon) Nothing)
     77            NoBound ->
     78                Bound pos pos
     79 
     80 bounds : List Point -> Bound
     81 bounds points =
     82     List.foldr extendBound NoBound (List.map .pos points)
     83 
     84 centre : List Point -> Pos
     85 centre points =
     86     case bounds points of
     87         Bound min max -> Pos
     88                          ((max.lat + min.lat) / 2)
     89                          ((max.lon + min.lon) / 2)
     90                              Nothing
     91         NoBound -> Pos 0 0 Nothing
     92 
     93 subseq : List Point -> Float -> Float -> List Point
     94 subseq points start dur =
     95     case points of
     96         [] -> []
     97         (p::ps) ->
     98             if p.time < start
     99             then subseq ps start dur
    100             else if p.time >= (start + dur)
    101                  then []
    102                  else p::(subseq ps start dur)