Always form a monoidal sum during a run of dbTable

Fixes #142
This commit is contained in:
Gregor Kleen 2018-08-06 17:39:31 +02:00
parent 8d70518fbb
commit d2242f21ff
9 changed files with 103 additions and 117 deletions

View File

@ -187,7 +187,7 @@ getCourseListR = do -- TODO: Suchfunktion für Kurse und Kürzel!!!
whereClause = const $ E.val True whereClause = const $ E.val True
validator = def validator = def
& defaultSorting [("course", SortAsc), ("term", SortDesc)] & defaultSorting [("course", SortAsc), ("term", SortDesc)]
coursesTable <- makeCourseTable whereClause colonnade validator ((), coursesTable) <- makeCourseTable whereClause colonnade validator
defaultLayout $ do defaultLayout $ do
setTitleI MsgCourseListTitle setTitleI MsgCourseListTitle
[whamlet|TODO: Such-/Filterfunktion hier einbauen|] -- TODO [whamlet|TODO: Such-/Filterfunktion hier einbauen|] -- TODO
@ -217,7 +217,7 @@ getTermCourseListR tid = do
whereClause = \(course, _, _) -> course E.^. CourseTerm E.==. E.val tid whereClause = \(course, _, _) -> course E.^. CourseTerm E.==. E.val tid
validator = def validator = def
& defaultSorting [("cshort", SortAsc)] & defaultSorting [("cshort", SortAsc)]
coursesTable <- makeCourseTable whereClause colonnade validator ((), coursesTable) <- makeCourseTable whereClause colonnade validator
defaultLayout $ do defaultLayout $ do
setTitleI . MsgTermCourseListTitle $ tid setTitleI . MsgTermCourseListTitle $ tid
$(widgetFile "courses") $(widgetFile "courses")

View File

@ -65,7 +65,7 @@ homeAnonymous = do
E.||. (course E.^. CourseRegisterTo E.>=. E.val (Just cTime))) E.||. (course E.^. CourseRegisterTo E.>=. E.val (Just cTime)))
return course return course
colonnade :: Colonnade Sortable (DBRow (Entity Course)) (DBCell (WidgetT UniWorX IO) ()) colonnade :: Colonnade Sortable (DBRow (Entity Course)) (DBCell (HandlerT UniWorX IO) ())
colonnade = mconcat colonnade = mconcat
[ -- dbRow [ -- dbRow
sortable (Just "course") (textCell MsgCourse) $ \DBRow{ dbrOutput=(Entity {entityVal = course}) } -> do sortable (Just "course") (textCell MsgCourse) $ \DBRow{ dbrOutput=(Entity {entityVal = course}) } -> do
@ -77,7 +77,7 @@ homeAnonymous = do
, sortable (Just "deadline") (textCell MsgRegisterTo) $ \DBRow{ dbrOutput=(Entity {entityVal = course}) } -> , sortable (Just "deadline") (textCell MsgRegisterTo) $ \DBRow{ dbrOutput=(Entity {entityVal = course}) } ->
cell $ traverse (formatTime SelFormatDateTime) (courseRegisterTo course) >>= maybe mempty toWidget cell $ traverse (formatTime SelFormatDateTime) (courseRegisterTo course) >>= maybe mempty toWidget
] ]
courseTable <- dbTable def $ DBTable ((), courseTable) <- dbTable def $ DBTable
{ dbtSQLQuery = tableData { dbtSQLQuery = tableData
, dbtColonnade = colonnade , dbtColonnade = colonnade
, dbtProj = return , dbtProj = return
@ -144,7 +144,7 @@ homeUser uid = do
, E.Value UTCTime , E.Value UTCTime
, E.Value (Maybe SubmissionId) , E.Value (Maybe SubmissionId)
)) ))
(DBCell (WidgetT UniWorX IO) ()) (DBCell (HandlerT UniWorX IO) ())
colonnade = mconcat colonnade = mconcat
[ -- dbRow [ -- dbRow
sortable (Just "course") (textCell MsgCourse) $ \DBRow{ dbrOutput=(E.Value tid, E.Value csh, _, _, _) } -> sortable (Just "course") (textCell MsgCourse) $ \DBRow{ dbrOutput=(E.Value tid, E.Value csh, _, _, _) } ->
@ -162,7 +162,7 @@ homeUser uid = do
tickmark tickmark
] ]
let validator = def & defaultSorting [("done",SortDesc), ("deadline",SortDesc)] let validator = def & defaultSorting [("done",SortDesc), ("deadline",SortDesc)]
sheetTable <- dbTable validator $ DBTable ((), sheetTable) <- dbTable validator $ DBTable
{ dbtSQLQuery = tableData { dbtSQLQuery = tableData
, dbtColonnade = colonnade , dbtColonnade = colonnade
, dbtProj = \dbRow@DBRow{ dbrOutput = (E.Value tid, E.Value csh, E.Value shn, _, _) } , dbtProj = \dbRow@DBRow{ dbrOutput = (E.Value tid, E.Value csh, E.Value shn, _, _) }

View File

@ -56,6 +56,8 @@ import qualified Data.Map as Map
import Data.Map (Map, (!), (!?)) import Data.Map (Map, (!), (!?))
import qualified Data.Map as Map import qualified Data.Map as Map
import Data.Monoid (Sum(..))
import Control.Lens import Control.Lens
import Utils.Lens import Utils.Lens
@ -199,7 +201,8 @@ getSheetListR tid csh = do
mkRoute = do mkRoute = do
cid <- mkCid cid <- mkCid
return $ CSubmissionR tid csh sheetName cid CorrectionR return $ CSubmissionR tid csh sheetName cid CorrectionR
in anchorCellM mkRoute $(widgetFile "widgets/rating") protoCell = anchorCellM mkRoute $(widgetFile "widgets/rating")
in protoCell & cellContents %~ (<* tell (sheetTypeSum (sheetType, submissionRatingPoints)))
, sortable Nothing -- (Just "percent") , sortable Nothing -- (Just "percent")
(i18nCell MsgRatingPercent) (i18nCell MsgRatingPercent)
$ \(Entity _ Sheet{sheetType=sType}, _, mbSub) -> case mbSub of $ \(Entity _ Sheet{sheetType=sType}, _, mbSub) -> case mbSub of
@ -214,7 +217,7 @@ getSheetListR tid csh = do
] ]
psValidator = def psValidator = def
& defaultSorting [("submission-since", SortAsc)] & defaultSorting [("submission-since", SortAsc)]
table <- dbTable psValidator $ DBTable (SheetTypeSummary{..}, table) <- dbTable psValidator $ DBTable
{ dbtSQLQuery = sheetData { dbtSQLQuery = sheetData
, dbtColonnade = sheetCol , dbtColonnade = sheetCol
, dbtProj = \DBRow{ dbrOutput = dbrOutput@(Entity _ Sheet{..}, _, _) } , dbtProj = \DBRow{ dbrOutput = dbrOutput@(Entity _ Sheet{..}, _, _) }
@ -248,19 +251,6 @@ getSheetListR tid csh = do
, dbtStyle = def , dbtStyle = def
, dbtIdent = "sheets" :: Text , dbtIdent = "sheets" :: Text
} }
cTime <- Just <$> liftIO getCurrentTime -- TODO: HACK - remove me and the 2 next TODOs, see issue #142
rawStats <- runDB $ do -- compute the values of the table once again, since dbTable does not provide a list of raw values for summation/statistics
E.select $ E.from $ \(sheet `E.LeftOuterJoin` (submission `E.InnerJoin` submissionUser)) -> do
E.on $ submission E.?. SubmissionId E.==. submissionUser E.?. SubmissionUserSubmission
E.on $ (E.just $ sheet E.^. SheetId) E.==. submission E.?. SubmissionSheet
E.&&. submissionUser E.?. SubmissionUserUser E.==. E.val muid
E.where_ $ sheet E.^. SheetCourse E.==. E.val cid
E.&&. (E.not_ $ E.isNothing $ sheet E.^. SheetVisibleFrom) -- TODO see above #142
E.&&. sheet E.^. SheetVisibleFrom E.<=. E.val cTime -- TODO see above #142
return $ (sheet E.^. SheetType, submission E.?. SubmissionRatingPoints)
let sheetTypeSummary = foldl' sumSheetTypes emptySheetTypeSummary
$ map (\(st,mp) -> (E.unValue st, join $ E.unValue mp)) rawStats
defaultLayout $ do defaultLayout $ do
$(widgetFile "sheetList") $(widgetFile "sheetList")
$(widgetFile "widgets/sheetTypeSummary") $(widgetFile "widgets/sheetTypeSummary")
@ -301,7 +291,7 @@ getSShowR tid csh shn = do
] ]
let psValidator = def let psValidator = def
& defaultSorting [("type", SortAsc), ("path", SortAsc)] & defaultSorting [("type", SortAsc), ("path", SortAsc)]
fileTable <- dbTable psValidator $ DBTable ((), fileTable) <- dbTable psValidator $ DBTable
{ dbtSQLQuery = fileData { dbtSQLQuery = fileData
, dbtColonnade = colonnadeFiles , dbtColonnade = colonnadeFiles
, dbtProj = \DBRow{ dbrOutput = dbrOutput@(E.Value fName, _, E.Value fType) } , dbtProj = \DBRow{ dbrOutput = dbrOutput@(E.Value fName, _, E.Value fType) }

View File

@ -246,7 +246,7 @@ submissionHelper tid csh shn (SubmissionMode mcid) = do
maySubmit <- (== Authorized) <$> isAuthorized actionUrl True maySubmit <- (== Authorized) <$> isAuthorized actionUrl True
-- Maybe construct a table to display uploaded archive files -- Maybe construct a table to display uploaded archive files
let colonnadeFiles :: _ -> Colonnade Sortable _ (DBCell (WidgetT UniWorX IO) ()) let colonnadeFiles :: _ -> Colonnade Sortable _ (DBCell (HandlerT UniWorX IO) ())
colonnadeFiles cid = mconcat colonnadeFiles cid = mconcat
[ sortable (Just "path") (textCell MsgFileTitle) $ \(coalesce -> (mOrig, mCorr)) -> let [ sortable (Just "path") (textCell MsgFileTitle) $ \(coalesce -> (mOrig, mCorr)) -> let
Just fileTitle' = fileTitle . entityVal . snd <$> (mOrig <|> mCorr) Just fileTitle' = fileTitle . entityVal . snd <$> (mOrig <|> mCorr)
@ -299,7 +299,7 @@ submissionHelper tid csh shn (SubmissionMode mcid) = do
] ]
, dbtFilter = [] , dbtFilter = []
} }
mFileTable <- traverse (dbTable def) . fmap smid2ArchiveTable $ (,) <$> msmid <*> mcid mFileTable <- traverse (fmap snd . dbTable def) . fmap smid2ArchiveTable $ (,) <$> msmid <*> mcid
defaultLayout $ do defaultLayout $ do
setTitleI $ MsgSubmissionEditHead tid csh shn setTitleI $ MsgSubmissionEditHead tid csh shn

View File

@ -78,7 +78,7 @@ getTermShowR = do
-- #{termToText termName} -- #{termToText termName}
-- |] -- |]
-- ] -- ]
table <- dbTable def $ DBTable ((), table) <- dbTable def $ DBTable
{ dbtSQLQuery = termData { dbtSQLQuery = termData
, dbtColonnade = colonnadeTerms , dbtColonnade = colonnadeTerms
, dbtProj = return . dbrOutput , dbtProj = return . dbrOutput

View File

@ -4,7 +4,7 @@
{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE RecordWildCards, NamedFieldPuns #-}
module Handler.Users where module Handler.Users where
@ -12,6 +12,8 @@ import Import
-- import Data.Text -- import Data.Text
import Handler.Utils import Handler.Utils
import Utils.Lens
import qualified Data.Map as Map import qualified Data.Map as Map
import qualified Data.Set as Set import qualified Data.Set as Set
@ -29,7 +31,7 @@ hijackUserForm uid csrf = do
getUsersR :: Handler Html getUsersR :: Handler Html
getUsersR = do getUsersR = do
let let
colonnadeUsers = dbColonnade . mconcat $ dbtColonnade = dbColonnade . mconcat $
[ dbRow [ dbRow
, sortable (Just "display-name") (i18nCell MsgName) $ \DBRow{ dbrOutput = Entity uid User{..} } -> anchorCellM , sortable (Just "display-name") (i18nCell MsgName) $ \DBRow{ dbrOutput = Entity uid User{..} } -> anchorCellM
(AdminUserR <$> encrypt uid) (AdminUserR <$> encrypt uid)
@ -40,32 +42,28 @@ getUsersR = do
-- , sortable (Just "last-name") (i18nCell MsgName) $ \DBRow{ dbrOutput = Entity uid User{..} } -> anchorCellM -- , sortable (Just "last-name") (i18nCell MsgName) $ \DBRow{ dbrOutput = Entity uid User{..} } -> anchorCellM
-- (AdminUserR <$> encrypt uid) -- (AdminUserR <$> encrypt uid)
-- (toWidget . display $ last $ impureNonNull $ words $ userDisplayName) -- (toWidget . display $ last $ impureNonNull $ words $ userDisplayName)
, sortable Nothing (i18nCell MsgAdminFor) $ \DBRow{ dbrOutput = Entity uid _ } -> mempty , sortable Nothing (i18nCell MsgAdminFor) $ \DBRow{ dbrOutput = Entity uid _ } -> flip (set' cellContents) mempty $ do
{ dbCellContents = do schools <- lift . E.select . E.from $ \(school `E.InnerJoin` userAdmin) -> do
schools <- E.select . E.from $ \(school `E.InnerJoin` userAdmin) -> do E.on $ school E.^. SchoolId E.==. userAdmin E.^. UserAdminSchool
E.on $ school E.^. SchoolId E.==. userAdmin E.^. UserAdminSchool E.where_ $ userAdmin E.^. UserAdminUser E.==. E.val uid
E.where_ $ userAdmin E.^. UserAdminUser E.==. E.val uid E.orderBy [E.asc $ school E.^. SchoolShorthand]
E.orderBy [E.asc $ school E.^. SchoolShorthand] return $ school E.^. SchoolShorthand
return $ school E.^. SchoolShorthand return [whamlet|
return [whamlet| <ul .list--inline .list--comma-separated>
<ul .list--inline .list--comma-separated> $forall (E.Value sh) <- schools
$forall (E.Value sh) <- schools <li>#{sh}
<li>#{sh} |]
|] , sortable Nothing (i18nCell MsgLecturerFor) $ \DBRow{ dbrOutput = Entity uid _ } -> flip (set' cellContents) mempty $ do
} schools <- lift . E.select . E.from $ \(school `E.InnerJoin` userLecturer) -> do
, sortable Nothing (i18nCell MsgLecturerFor) $ \DBRow{ dbrOutput = Entity uid _ } -> mempty E.on $ school E.^. SchoolId E.==. userLecturer E.^. UserLecturerSchool
{ dbCellContents = do E.where_ $ userLecturer E.^. UserLecturerUser E.==. E.val uid
schools <- E.select . E.from $ \(school `E.InnerJoin` userLecturer) -> do E.orderBy [E.asc $ school E.^. SchoolShorthand]
E.on $ school E.^. SchoolId E.==. userLecturer E.^. UserLecturerSchool return $ school E.^. SchoolShorthand
E.where_ $ userLecturer E.^. UserLecturerUser E.==. E.val uid return [whamlet|
E.orderBy [E.asc $ school E.^. SchoolShorthand] <ul .list--inline .list--comma-separated>
return $ school E.^. SchoolShorthand $forall (E.Value sh) <- schools
return [whamlet| <li>#{sh}
<ul .list--inline .list--comma-separated> |]
$forall (E.Value sh) <- schools
<li>#{sh}
|]
}
, sortable Nothing mempty $ \DBRow{ dbrOutput = Entity uid _ } -> cell $ do , sortable Nothing mempty $ \DBRow{ dbrOutput = Entity uid _ } -> cell $ do
(hijackView, hijackEnctype) <- liftHandlerT . generateFormPost $ hijackUserForm uid (hijackView, hijackEnctype) <- liftHandlerT . generateFormPost $ hijackUserForm uid
cID <- encrypt uid cID <- encrypt uid
@ -77,9 +75,9 @@ getUsersR = do
psValidator = def psValidator = def
& defaultSorting [("display-name", SortAsc)] & defaultSorting [("display-name", SortAsc)]
userList <- dbTable psValidator $ DBTable ((), userList) <- dbTable psValidator $ DBTable
{ dbtSQLQuery = return :: E.SqlExpr (Entity User) -> E.SqlQuery (E.SqlExpr (Entity User)) { dbtSQLQuery = return :: E.SqlExpr (Entity User) -> E.SqlQuery (E.SqlExpr (Entity User))
, dbtColonnade = colonnadeUsers , dbtColonnade
, dbtProj = return , dbtProj = return
, dbtSorting = Map.fromList , dbtSorting = Map.fromList
[ ( "display-name" [ ( "display-name"

View File

@ -40,6 +40,7 @@ module Handler.Utils.Table.Pagination
, dbRow, dbSelect , dbRow, dbSelect
, (&) , (&)
, module Control.Monad.Trans.Maybe , module Control.Monad.Trans.Maybe
, module Colonnade
) where ) where
import Handler.Utils.Table.Pagination.Types import Handler.Utils.Table.Pagination.Types
@ -271,46 +272,46 @@ cellAttrs = dbCell . _1
cellContents :: IsDBTable m x => Lens' (DBCell m x) (WriterT x m Widget) cellContents :: IsDBTable m x => Lens' (DBCell m x) (WriterT x m Widget)
cellContents = dbCell . _2 cellContents = dbCell . _2
instance IsDBTable (WidgetT UniWorX IO) () where instance Monoid x => IsDBTable (HandlerT UniWorX IO) x where
type DBResult (WidgetT UniWorX IO) () = Widget type DBResult (HandlerT UniWorX IO) x = (x, Widget)
-- type DBResult' (WidgetT UniWorX IO) () = () -- type DBResult' (WidgetT UniWorX IO) () = ()
data DBCell (WidgetT UniWorX IO) () = WidgetCell data DBCell (HandlerT UniWorX IO) x = WidgetCell
{ wgtCellAttrs :: [(Text, Text)] { wgtCellAttrs :: [(Text, Text)]
, wgtCellContents :: Widget , wgtCellContents :: WriterT x (HandlerT UniWorX IO) Widget
} }
dbCell = iso dbCell = iso
(\WidgetCell{..} -> (wgtCellAttrs, return wgtCellContents)) (\WidgetCell{..} -> (wgtCellAttrs, wgtCellContents))
(\(attrs, mkWidget) -> WidgetCell attrs . join . fmap fst $ runWriterT mkWidget) (\(attrs, mkWidget) -> WidgetCell attrs mkWidget)
-- dbWidget Proxy Proxy = iso (, ()) $ view _1 -- dbWidget Proxy Proxy = iso (, ()) $ view _1
dbWidget _ = return dbWidget _ = return . snd
dbHandler _ f x = return $ f x dbHandler _ f = return . over _2 f
runDBTable = return . join . fmap (view _2) runDBTable act = liftHandlerT act
instance Monoid (DBCell (WidgetT UniWorX IO) ()) where instance Monoid x => Monoid (DBCell (HandlerT UniWorX IO) x) where
mempty = WidgetCell mempty mempty mempty = WidgetCell mempty $ return mempty
(WidgetCell a c) `mappend` (WidgetCell a' c') = WidgetCell (mappend a a') (mappend c c') (WidgetCell a c) `mappend` (WidgetCell a' c') = WidgetCell (mappend a a') (mappend <$> c <*> c')
instance IsDBTable (ReaderT SqlBackend (HandlerT UniWorX IO)) () where instance Monoid x => IsDBTable (ReaderT SqlBackend (HandlerT UniWorX IO)) x where
type DBResult (ReaderT SqlBackend (HandlerT UniWorX IO)) () = Widget type DBResult (ReaderT SqlBackend (HandlerT UniWorX IO)) x = (x, Widget)
data DBCell (ReaderT SqlBackend (HandlerT UniWorX IO)) () = DBCell data DBCell (ReaderT SqlBackend (HandlerT UniWorX IO)) x = DBCell
{ dbCellAttrs :: [(Text, Text)] { dbCellAttrs :: [(Text, Text)]
, dbCellContents :: ReaderT SqlBackend (HandlerT UniWorX IO) Widget , dbCellContents :: WriterT x (ReaderT SqlBackend (HandlerT UniWorX IO)) Widget
} }
dbCell = iso dbCell = iso
(\DBCell{..} -> (dbCellAttrs, lift dbCellContents)) (\DBCell{..} -> (dbCellAttrs, dbCellContents))
(\(attrs, mkWidget) -> DBCell attrs . fmap fst $ runWriterT mkWidget) (\(attrs, mkWidget) -> DBCell attrs mkWidget)
dbWidget _ = return dbWidget _ = return . snd
dbHandler _ f x = return $ f x dbHandler _ f = return . over _2 f
-- runDBTable :: forall m. (MonadHandler m, HandlerSite m ~ UniWorX) => ReaderT SqlBackend (HandlerT UniWorX IO) ((), Widget) -> m (Widget) -- runDBTable :: forall m. (MonadHandler m, HandlerSite m ~ UniWorX) => ReaderT SqlBackend (HandlerT UniWorX IO) ((), Widget) -> m (Widget)
runDBTable = fmap snd . mapReaderT liftHandlerT runDBTable = mapReaderT liftHandlerT
instance Monoid (DBCell (ReaderT SqlBackend (HandlerT UniWorX IO)) ()) where instance Monoid x => Monoid (DBCell (ReaderT SqlBackend (HandlerT UniWorX IO)) x) where
mempty = DBCell mempty $ return mempty mempty = DBCell mempty $ return mempty
(DBCell a c) `mappend` (DBCell a' c') = DBCell (mappend a a') (mappend <$> c <*> c') (DBCell a c) `mappend` (DBCell a' c') = DBCell (mappend a a') (mappend <$> c <*> c')
@ -454,9 +455,9 @@ dbTable PSValidator{..} dbtable@(DBTable{ dbtIdent = (toPathPiece -> dbtIdent),
--- DBCell utility functions --- DBCell utility functions
widgetColonnade :: Headedness h widgetColonnade :: (Headedness h, Monoid x)
=> Colonnade h r (DBCell (WidgetT UniWorX IO) ()) => Colonnade h r (DBCell (HandlerT UniWorX IO) x)
-> Colonnade h r (DBCell (WidgetT UniWorX IO) ()) -> Colonnade h r (DBCell (HandlerT UniWorX IO) x)
widgetColonnade = id widgetColonnade = id
formColonnade :: (Headedness h, Monoid a) formColonnade :: (Headedness h, Monoid a)
@ -464,9 +465,9 @@ formColonnade :: (Headedness h, Monoid a)
-> Colonnade h r (DBCell (RWST (Maybe (Env, FileEnv), UniWorX, [Lang]) Enctype Ints (HandlerT UniWorX IO)) (FormResult a)) -> Colonnade h r (DBCell (RWST (Maybe (Env, FileEnv), UniWorX, [Lang]) Enctype Ints (HandlerT UniWorX IO)) (FormResult a))
formColonnade = id formColonnade = id
dbColonnade :: Headedness h dbColonnade :: (Headedness h, Monoid x)
=> Colonnade h r (DBCell (ReaderT SqlBackend (HandlerT UniWorX IO)) ()) => Colonnade h r (DBCell (ReaderT SqlBackend (HandlerT UniWorX IO)) x)
-> Colonnade h r (DBCell (ReaderT SqlBackend (HandlerT UniWorX IO)) ()) -> Colonnade h r (DBCell (ReaderT SqlBackend (HandlerT UniWorX IO)) x)
dbColonnade = id dbColonnade = id
cell :: IsDBTable m a => Widget -> DBCell m a cell :: IsDBTable m a => Widget -> DBCell m a

View File

@ -21,6 +21,7 @@ import qualified Data.Map as Map
import Data.Set (Set) import Data.Set (Set)
import qualified Data.Set as Set import qualified Data.Set as Set
import Data.Fixed import Data.Fixed
import Data.Monoid (Sum(..))
import Database.Persist.TH import Database.Persist.TH
import Database.Persist.Class import Database.Persist.Class
@ -42,6 +43,7 @@ import Data.Aeson (FromJSON(..), ToJSON(..), withText, Value(..))
import Data.Aeson.TH (deriveJSON, defaultOptions) import Data.Aeson.TH (deriveJSON, defaultOptions)
import GHC.Generics (Generic) import GHC.Generics (Generic)
import Generics.Deriving.Monoid (gmemptydefault, gmappenddefault)
import Data.Typeable (Typeable) import Data.Typeable (Typeable)
import Text.Shakespeare.I18N (ToMessage(..), RenderMessage(..)) import Text.Shakespeare.I18N (ToMessage(..), RenderMessage(..))
@ -77,29 +79,24 @@ deriveJSON defaultOptions ''SheetType
derivePersistFieldJSON "SheetType" derivePersistFieldJSON "SheetType"
data SheetTypeSummary = SheetTypeSummary data SheetTypeSummary = SheetTypeSummary
{ sumBonusPoints :: Points { sumBonusPoints :: Sum Points
, sumNormalPoints :: Points , sumNormalPoints :: Sum Points
, numPassSheets :: Int , numPassSheets :: Sum Int
, numNotGraded :: Int , numNotGraded :: Sum Int
, achievedBonus :: Maybe Points , achievedBonus :: Maybe (Sum Points)
, achievedNormal :: Maybe Points , achievedNormal :: Maybe (Sum Points)
, achievedPasses :: Maybe Int , achievedPasses :: Maybe (Sum Int)
} } deriving (Generic)
instance Monoid SheetTypeSummary where
mempty = gmemptydefault
mappend = gmappenddefault
emptySheetTypeSummary :: SheetTypeSummary sheetTypeSum :: (SheetType, Maybe Points) -> SheetTypeSummary
emptySheetTypeSummary = SheetTypeSummary 0 0 0 0 Nothing Nothing Nothing sheetTypeSum (Bonus{..}, achieved) = mempty { sumBonusPoints = Sum maxPoints, achievedBonus = Sum <$> achieved }
sheetTypeSum (Normal{..}, achieved) = mempty { sumNormalPoints = Sum maxPoints, achievedNormal = Sum <$> achieved }
-- TODO: refactor with lenses! sheetTypeSum (Pass{..}, achieved) = mempty { numPassSheets = Sum 1, achievedPasses = Sum . bool 0 1 . (passingPoints <=) <$> achieved}
sumSheetTypes :: SheetTypeSummary -> (SheetType, Maybe Points) -> SheetTypeSummary sheetTypeSum (NotGraded, _ ) = mempty { numNotGraded = Sum 1 }
sumSheetTypes sts@(SheetTypeSummary {..}) (Bonus {..}, achieved)
= sts{ sumBonusPoints =sumBonusPoints +maxPoints, achievedBonus = maybeAdd achievedBonus achieved }
sumSheetTypes sts@(SheetTypeSummary {..}) (Normal {..}, achieved)
= sts{ sumNormalPoints=sumNormalPoints+maxPoints, achievedNormal = maybeAdd achievedNormal achieved }
sumSheetTypes sts@(SheetTypeSummary {..}) (Pass {..}, achieved)
= sts{ numPassSheets=numPassSheets+1, achievedPasses = maybeAdd achievedPasses (bool 0 1 <$> (passingPoints <=) <$> achieved) }
sumSheetTypes sts@(SheetTypeSummary {..}) (NotGraded, _achieved)
= sts{ numNotGraded=numNotGraded+1 }
data SheetGroup data SheetGroup

View File

@ -1,23 +1,23 @@
<div> <div>
$if 0 < sumNormalPoints sheetTypeSummary $if 0 < getSum sumNormalPoints
Gesamtpunktzahl #{display (sumNormalPoints sheetTypeSummary)} Gesamtpunktzahl #{display (getSum sumNormalPoints)}
$maybe nPts <- (maybeAdd (achievedNormal sheetTypeSummary) (achievedBonus sheetTypeSummary)) $maybe nPts <- (maybeAdd (getSum <$> achievedNormal) (getSum <$> achievedBonus))
\ davon #{display nPts} erreicht \ davon #{display nPts} erreicht
$maybe bPts <- achievedBonus sheetTypeSummary $maybe bPts <- getSum <$> achievedBonus
\ (inklusive #{display bPts} # \ (inklusive #{display bPts} #
$if 0 < sumBonusPoints sheetTypeSummary $if 0 < getSum sumBonusPoints
von #{display $ sumBonusPoints sheetTypeSummary} erreichbaren # von #{display $ getSum sumBonusPoints} erreichbaren #
Bonuspunkten) Bonuspunkten)
\ #{textPercent $ realToFrac $ nPts / (sumNormalPoints sheetTypeSummary)} \ #{textPercent $ realToFrac $ nPts / (getSum sumNormalPoints)}
<div> <div>
$if 0 < numPassSheets sheetTypeSummary $if 0 < getSum numPassSheets
Blätter zum Bestehen: #{display (numPassSheets sheetTypeSummary)} Blätter zum Bestehen: #{display (getSum numPassSheets)}
$maybe passed <- achievedPasses sheetTypeSummary $maybe passed <- getSum <$> achievedPasses
\ davon #{display (achievedPasses sheetTypeSummary)} bestanden. \ davon #{display passed} bestanden.
<div> <div>
$if 0 < numNotGraded sheetTypeSummary $if 0 < getSum numNotGraded
Unbewertet: #{display (numNotGraded sheetTypeSummary)} Blätter Unbewertet: #{display (getSum numNotGraded)} Blätter