souplesse/frontend/src/Point.elm

104 lines
2.6 KiB
Elm

module Point exposing(Pos, Point, decoder, downsample, duration, subseq, startTime, centre)
import Json.Decode as D
type alias Pos =
{ lat : Float
, lon : Float
, ele : Maybe Float
}
type alias Point =
{ time : Float
, pos : Pos
, cadence : Maybe Int
, power : Maybe Int
, heartRate : Maybe Int
}
posDecoder : D.Decoder Pos
posDecoder = D.map3 Pos
(D.field "lat" D.float)
(D.field "lon" D.float)
(D.field "ele" (D.maybe D.float))
decoder : D.Decoder Point
decoder = D.map5 Point
(D.field "time" D.float)
(D.field "pos" posDecoder)
(D.field "cadence" (D.maybe D.int))
(D.field "power" (D.maybe D.int))
(D.field "heartRate" (D.maybe D.int))
last x xs =
case xs of
[] -> x
(x_::xs_) -> last x_ xs_
tracef x = Debug.log (String.fromFloat x) x
-- divide the points into n equal time buckets and return the first
-- point in each
downsample n points =
let
nextpoint step prev points_ =
case points_ of
(next::rest) ->
if next.time - prev.time > step
then prev :: (nextpoint step next rest)
else nextpoint step prev rest
_ -> [prev]
in
case points of
(first::rest) ->
let step = (duration points) / (toFloat n)
in nextpoint step first rest
[] -> []
duration points =
case points of
(p::ps) -> (last p ps).time - p.time
_ -> 0
startTime points =
case points of
(p::ps) -> Just p.time
_ -> Nothing
type Bound = Bound Pos Pos | NoBound
extendBound : Pos -> Bound -> Bound
extendBound pos b =
let {lat, lon} = pos
in case b of
(Bound p1 p2) ->
Bound
(Pos (min lat p1.lat) (min lon p1.lon) Nothing)
(Pos (max lat p2.lat) (max lon p2.lon) Nothing)
NoBound ->
Bound pos pos
bounds points =
List.foldr extendBound NoBound (List.map .pos points)
centre points =
case bounds points of
Bound min max -> Pos
((max.lat + min.lat) / 2)
((max.lon + min.lon) / 2)
Nothing
NoBound -> Pos 0 0 Nothing
subseq points start dur =
case points of
[] -> []
(p::ps) ->
if p.time < start
then subseq ps start dur
else if p.time >= (start + dur)
then []
else p::(subseq ps start dur)