From 886089fbcd2787b1f7c4872fb6c862135fa0059c Mon Sep 17 00:00:00 2001 From: Daniel Barlow Date: Sun, 10 Nov 2024 16:18:18 +0000 Subject: [PATCH] extract Session module --- app/Main.hs | 3 ++- lib/Session.hs | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/Store.hs | 49 +++++++---------------------------- souplesse.cabal | 1 + 4 files changed, 82 insertions(+), 40 deletions(-) create mode 100644 lib/Session.hs diff --git a/app/Main.hs b/app/Main.hs index 197d662..9cd42b3 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -13,6 +13,7 @@ import Data.List as List import Data.Time.Clock.POSIX (posixSecondsToUTCTime) import Database.Persist.Postgresql (ConnectionPool, ConnectionString, SqlBackend, runMigration, runSqlPool, withPostgresqlPool) import Debug.Trace (traceShow) +import Session import Store import Track (parseBS) import Yesod.Core @@ -56,7 +57,7 @@ instance YesodPersist Souplesse where getCalendarR :: Handler Html getCalendarR = do (formWidget, _) <- generateFormPost uploadForm - sessions' <- runDB Store.sessions + sessions' <- runDB Session.recents defaultLayout [whamlet|

Calendar diff --git a/lib/Session.hs b/lib/Session.hs new file mode 100644 index 0000000..1860307 --- /dev/null +++ b/lib/Session.hs @@ -0,0 +1,69 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE EmptyDataDecls #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE QuasiQuotes #-} +{-# LANGUAGE StandaloneDeriving #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE UndecidableInstances #-} + +module Session + ( Session(..) + , recents + , updateSessions + , migrateSession + ) where + +import Data.Text +import Text.RawString.QQ (r) +import Data.Time.Clock ( + UTCTime, + ) + +import Database.Persist +-- import Database.Persist.Class +import Database.Persist.TH +import Database.Persist.Postgresql + ( SqlBackend, + PgInterval + ) +import Control.Monad.IO.Class (MonadIO) +import Control.Monad.Trans.Reader (ReaderT) + + +share + [mkPersist sqlSettings, mkMigrate "migrateSession"] + [persistLowerCase| +Session + startTime UTCTime + duration PgInterval + draft Bool default=True + notes String Maybe +|] + +updateSessions :: Text +updateSessions = [r| +-- delete existing drafts as new data may extend one of them +delete from session where draft; +-- find all potential start points in the new data +insert into session(start_time, duration, draft) (select time as start_time, make_interval(0) as duration, true as draft from trkpt as p where not exists (select id from session where start_time <= p.time and (start_time + duration) > p.time) and not exists(select * from trkpt as p1 where time > p.time - '600 seconds'::interval and time < p.time)); +-- reset durations + update session s1 + set duration = + coalesce( + (select max(time) from trkpt t1 + where t1.time < coalesce((select min(start_time) from session s2 where s2.start_time > s1.start_time), now())) - s1.start_time + , make_interval()) +where draft; +|] + +recents :: (MonadIO m) => ReaderT SqlBackend m [Session] +recents = do + s <- selectList [SessionDraft !=. True] [Desc SessionStartTime, LimitTo 10] + return $ Prelude.map (\(Entity _ x) -> x) s diff --git a/lib/Store.hs b/lib/Store.hs index 60250aa..e634180 100644 --- a/lib/Store.hs +++ b/lib/Store.hs @@ -13,9 +13,13 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} -module Store (save, fetch, sessions, sessionStartTime, - sessionDuration, migrateSession, migrateTrkpt - ) where +module Store + ( save, + fetch, + migrateTrkpt, + module Session, + ) +where import Control.Exception import Control.Monad.IO.Class (MonadIO, liftIO) @@ -30,30 +34,19 @@ import Database.Persist.Postgresql createPostgresqlPool, pgConnStr, pgPoolSize, + rawExecute, runMigration, runSqlPool, - rawExecute, - PgInterval ) import Database.Persist.TH +import Session import Text.Read (readMaybe) import Track (Point (..), Pos (..)) import Track as T -import Text.RawString.QQ (r) connString :: ConnectionString connString = "host=127.0.0.1 port=5432 user=souplesse dbname=souplesse password=secret" -share - [mkPersist sqlSettings, mkMigrate "migrateSession"] - [persistLowerCase| -Session - startTime UTCTime - duration PgInterval - draft Bool default=True - notes String Maybe -|] - share [mkPersist sqlSettings, mkMigrate "migrateTrkpt"] [persistLowerCase| @@ -67,7 +60,6 @@ Trkpt heartRate Int Maybe |] - fromPoint :: Point -> Trkpt fromPoint p = let Pos lat lon ele = T.pos p @@ -84,31 +76,10 @@ toPoint entity = (trkptPower tkp) (trkptHeartRate tkp) -updateSessions = [r| --- delete existing drafts as new data may extend one of them -delete from session where draft; --- find all potential start points in the new data -insert into session(start_time, duration, draft) (select time as start_time, make_interval(0) as duration, true as draft from trkpt as p where not exists (select id from session where start_time <= p.time and (start_time + duration) > p.time) and not exists(select * from trkpt as p1 where time > p.time - '600 seconds'::interval and time < p.time)); --- reset durations - update session s1 - set duration = - coalesce( - (select max(time) from trkpt t1 - where t1.time < coalesce((select min(start_time) from session s2 where s2.start_time > s1.start_time), now())) - s1.start_time - , make_interval()) -where draft; -|] - data OverlapExists = OverlapExists String deriving (Show) instance Exception OverlapExists -sessions :: (MonadIO m) => ReaderT SqlBackend m [Session] -sessions = do - s <- selectList [SessionDraft !=. True] [Desc SessionStartTime, LimitTo 10] - return $ map (\(Entity _ x) -> x) s - - save :: (MonadIO m) => Track -> ReaderT SqlBackend m (Either OverlapExists Track) save track = do let start = startTime track @@ -118,7 +89,7 @@ save track = do then return $ Left (OverlapExists "track overlaps with existing data") else do mapM_ (insert . fromPoint) track - rawExecute updateSessions [] + rawExecute Session.updateSessions [] return $ Right track fetch :: (MonadIO m) => UTCTime -> NominalDiffTime -> ReaderT SqlBackend m [Point] diff --git a/souplesse.cabal b/souplesse.cabal index f59672e..1e69bb9 100644 --- a/souplesse.cabal +++ b/souplesse.cabal @@ -99,6 +99,7 @@ library souplesse-lib Track Store Point + Session hs-source-dirs: lib build-depends: