initial work on score
This commit is contained in:
parent
e2c5ae179c
commit
b033d0c4b5
@ -52,6 +52,7 @@ import Handler.Presentation
|
|||||||
import Handler.Tags
|
import Handler.Tags
|
||||||
import Handler.EditSubmission
|
import Handler.EditSubmission
|
||||||
import Handler.Achievements
|
import Handler.Achievements
|
||||||
|
import Handler.Score
|
||||||
|
|
||||||
-- This line actually creates our YesodDispatch instance. It is the second half
|
-- This line actually creates our YesodDispatch instance. It is the second half
|
||||||
-- of the call to mkYesodData which occurs in Foundation.hs. Please see the
|
-- of the call to mkYesodData which occurs in Foundation.hs. Please see the
|
||||||
|
@ -134,6 +134,10 @@ instance Yesod App where
|
|||||||
isAuthorized (AvatarR _) _ = return Authorized
|
isAuthorized (AvatarR _) _ = return Authorized
|
||||||
|
|
||||||
isAuthorized CreateResetLinkR _ = isAdmin
|
isAuthorized CreateResetLinkR _ = isAdmin
|
||||||
|
isAuthorized (ScoreR _) _ = isAdmin
|
||||||
|
|
||||||
|
isAuthorized MyScoreR _ = return Authorized
|
||||||
|
|
||||||
isAuthorized (ResetPasswordR _) _ = return Authorized
|
isAuthorized (ResetPasswordR _) _ = return Authorized
|
||||||
|
|
||||||
-- Default to Authorized for now.
|
-- Default to Authorized for now.
|
||||||
|
51
Handler/AchievementUtils.hs
Normal file
51
Handler/AchievementUtils.hs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
module Handler.AchievementUtils where
|
||||||
|
|
||||||
|
import Import
|
||||||
|
|
||||||
|
import Handler.TagUtils
|
||||||
|
|
||||||
|
import qualified Yesod.Table as Table
|
||||||
|
|
||||||
|
data AchievementInfo = AchievementInfo {
|
||||||
|
achievementInfoId :: AchievementId,
|
||||||
|
achievementInfoName :: Text,
|
||||||
|
achievementInfoChallenge :: Entity Challenge,
|
||||||
|
achievementInfoDescription :: Maybe Text,
|
||||||
|
achievementInfoPoints :: Int,
|
||||||
|
achievementInfoDeadline :: UTCTime,
|
||||||
|
achievementInfoMaxWinners :: Maybe Int,
|
||||||
|
achievementInfoWorkingOn :: [Entity User],
|
||||||
|
achievementInfoCurrentUser :: Maybe (Entity User),
|
||||||
|
achievementInfoTags :: [Entity Tag] }
|
||||||
|
|
||||||
|
|
||||||
|
achievementDescriptionCell fun = Table.widget "description" ((
|
||||||
|
\ainfo -> fragmentWithTags (fromMaybe (""::Text) $ achievementInfoDescription ainfo) (achievementInfoTags ainfo)) . fun)
|
||||||
|
|
||||||
|
getAchievementInfo mUser (Entity achievementId achievement) = do
|
||||||
|
es <- selectList [WorkingOnAchievement ==. achievementId] []
|
||||||
|
let userIds = Import.map (workingOnUser . entityVal) es
|
||||||
|
users <- mapM get404 userIds
|
||||||
|
|
||||||
|
tags <- getAchievementTags achievementId
|
||||||
|
|
||||||
|
let challengeId = achievementChallenge achievement
|
||||||
|
challenge <- get404 challengeId
|
||||||
|
|
||||||
|
return $ AchievementInfo {
|
||||||
|
achievementInfoId = achievementId,
|
||||||
|
achievementInfoName = achievementName achievement,
|
||||||
|
achievementInfoChallenge = Entity challengeId challenge,
|
||||||
|
achievementInfoDescription = achievementDescription achievement,
|
||||||
|
achievementInfoPoints = achievementPoints achievement,
|
||||||
|
achievementInfoDeadline = achievementDeadline achievement,
|
||||||
|
achievementInfoMaxWinners = achievementMaxWinners achievement,
|
||||||
|
achievementInfoWorkingOn = Import.map (\(i,v) -> Entity i v) $ Import.zip userIds users,
|
||||||
|
achievementInfoCurrentUser = mUser,
|
||||||
|
achievementInfoTags = tags }
|
||||||
|
|
||||||
|
getAchievementTags achievementId = do
|
||||||
|
sts <- selectList [AchievementTagAchievement ==. achievementId] []
|
||||||
|
let tagIds = Import.map (achievementTagTag . entityVal) sts
|
||||||
|
tags <- mapM get404 $ tagIds
|
||||||
|
return $ Import.map (\(k, v) -> Entity k v) $ Import.zip tagIds tags
|
@ -9,6 +9,8 @@ import Handler.TagUtils
|
|||||||
import Handler.Tables
|
import Handler.Tables
|
||||||
import Handler.Shared
|
import Handler.Shared
|
||||||
|
|
||||||
|
import Handler.AchievementUtils
|
||||||
|
|
||||||
import Data.Time.Clock
|
import Data.Time.Clock
|
||||||
import Data.Time.LocalTime
|
import Data.Time.LocalTime
|
||||||
|
|
||||||
@ -16,20 +18,6 @@ import Data.Text
|
|||||||
|
|
||||||
import qualified Yesod.Table as Table
|
import qualified Yesod.Table as Table
|
||||||
|
|
||||||
data AchievementInfo = AchievementInfo {
|
|
||||||
achievementInfoId :: AchievementId,
|
|
||||||
achievementInfoName :: Text,
|
|
||||||
achievementInfoChallenge :: Entity Challenge,
|
|
||||||
achievementInfoDescription :: Maybe Text,
|
|
||||||
achievementInfoPoints :: Int,
|
|
||||||
achievementInfoDeadline :: UTCTime,
|
|
||||||
achievementInfoMaxWinners :: Maybe Int,
|
|
||||||
achievementInfoWorkingOn :: [Entity User],
|
|
||||||
achievementInfoCurrentUser :: Maybe (Entity User),
|
|
||||||
achievementInfoTags :: [Entity Tag] }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
getAchievementsR :: Handler Html
|
getAchievementsR :: Handler Html
|
||||||
getAchievementsR = do
|
getAchievementsR = do
|
||||||
(formWidget, formEnctype) <- generateFormPost achievementForm
|
(formWidget, formEnctype) <- generateFormPost achievementForm
|
||||||
@ -68,40 +56,11 @@ doAchievements mUser formWidget formEnctype = do
|
|||||||
setTitle "Achievements"
|
setTitle "Achievements"
|
||||||
$(widgetFile "achievements")
|
$(widgetFile "achievements")
|
||||||
|
|
||||||
getAchievementInfo mUser (Entity achievementId achievement) = do
|
|
||||||
es <- selectList [WorkingOnAchievement ==. achievementId] []
|
|
||||||
let userIds = Import.map (workingOnUser . entityVal) es
|
|
||||||
users <- mapM get404 userIds
|
|
||||||
|
|
||||||
tags <- getAchievementTags achievementId
|
|
||||||
|
|
||||||
let challengeId = achievementChallenge achievement
|
|
||||||
challenge <- get404 challengeId
|
|
||||||
|
|
||||||
return $ AchievementInfo {
|
|
||||||
achievementInfoId = achievementId,
|
|
||||||
achievementInfoName = achievementName achievement,
|
|
||||||
achievementInfoChallenge = Entity challengeId challenge,
|
|
||||||
achievementInfoDescription = achievementDescription achievement,
|
|
||||||
achievementInfoPoints = achievementPoints achievement,
|
|
||||||
achievementInfoDeadline = achievementDeadline achievement,
|
|
||||||
achievementInfoMaxWinners = achievementMaxWinners achievement,
|
|
||||||
achievementInfoWorkingOn = Import.map (\(i,v) -> Entity i v) $ Import.zip userIds users,
|
|
||||||
achievementInfoCurrentUser = mUser,
|
|
||||||
achievementInfoTags = tags }
|
|
||||||
|
|
||||||
getAchievementTags achievementId = do
|
|
||||||
sts <- selectList [AchievementTagAchievement ==. achievementId] []
|
|
||||||
let tagIds = Import.map (achievementTagTag . entityVal) sts
|
|
||||||
tags <- mapM get404 $ tagIds
|
|
||||||
return $ Import.map (\(k, v) -> Entity k v) $ Import.zip tagIds tags
|
|
||||||
|
|
||||||
|
|
||||||
achievementsTable :: Table.Table App (AchievementInfo)
|
achievementsTable :: Table.Table App (AchievementInfo)
|
||||||
achievementsTable = mempty
|
achievementsTable = mempty
|
||||||
++ Table.text "achievement" achievementInfoName
|
++ Table.text "achievement" achievementInfoName
|
||||||
++ Table.linked "challenge" (challengeTitle . entityVal . achievementInfoChallenge) (ShowChallengeR . challengeName . entityVal . achievementInfoChallenge)
|
++ Table.linked "challenge" (challengeTitle . entityVal . achievementInfoChallenge) (ShowChallengeR . challengeName . entityVal . achievementInfoChallenge)
|
||||||
++ achievementDescriptionCell
|
++ achievementDescriptionCell id
|
||||||
++ Table.int "points" achievementInfoPoints
|
++ Table.int "points" achievementInfoPoints
|
||||||
++ timestampCell "deadline" achievementInfoDeadline
|
++ timestampCell "deadline" achievementInfoDeadline
|
||||||
++ Table.string "max submitters" (formatMaxSubmitters . achievementInfoMaxWinners)
|
++ Table.string "max submitters" (formatMaxSubmitters . achievementInfoMaxWinners)
|
||||||
@ -197,10 +156,6 @@ determineWhetherCanGiveUpWorkingOn (Just (Entity userId user)) peopleWorkingOn =
|
|||||||
checkLimit _ Nothing = True
|
checkLimit _ Nothing = True
|
||||||
checkLimit peopleWorkingOn (Just m) = (Import.length peopleWorkingOn) < m
|
checkLimit peopleWorkingOn (Just m) = (Import.length peopleWorkingOn) < m
|
||||||
|
|
||||||
|
|
||||||
achievementDescriptionCell = Table.widget "description" (
|
|
||||||
\ainfo -> fragmentWithTags (fromMaybe (""::Text) $ achievementInfoDescription ainfo) (achievementInfoTags ainfo))
|
|
||||||
|
|
||||||
formatSubmitters userEnts = Data.Text.intercalate ", " $ Import.map (formatSubmitter . entityVal) userEnts
|
formatSubmitters userEnts = Data.Text.intercalate ", " $ Import.map (formatSubmitter . entityVal) userEnts
|
||||||
|
|
||||||
formatMaxSubmitters :: Maybe Int -> String
|
formatMaxSubmitters :: Maybe Int -> String
|
||||||
|
51
Handler/Score.hs
Normal file
51
Handler/Score.hs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
module Handler.Score where
|
||||||
|
|
||||||
|
import Import
|
||||||
|
|
||||||
|
import Handler.Shared
|
||||||
|
import Handler.Tables
|
||||||
|
|
||||||
|
import Handler.AchievementUtils
|
||||||
|
|
||||||
|
import qualified Database.Esqueleto as E
|
||||||
|
import Database.Esqueleto ((^.))
|
||||||
|
|
||||||
|
import qualified Yesod.Table as Table
|
||||||
|
|
||||||
|
getMyScoreR :: Handler Html
|
||||||
|
getMyScoreR = do
|
||||||
|
entUser <- requireAuth
|
||||||
|
doScore entUser
|
||||||
|
|
||||||
|
getScoreR :: UserId -> Handler Html
|
||||||
|
getScoreR userId = do
|
||||||
|
user <- runDB $ get404 userId
|
||||||
|
doScore (Entity userId user)
|
||||||
|
|
||||||
|
scoreTable :: Table.Table App (AchievementInfo, Entity Submission)
|
||||||
|
scoreTable = mempty
|
||||||
|
++ Table.text "name" (achievementInfoName . fst)
|
||||||
|
++ achievementDescriptionCell fst
|
||||||
|
++ timestampCell "deadline" (achievementInfoDeadline . fst)
|
||||||
|
++ Table.text "submission" (submissionDescription . entityVal . snd)
|
||||||
|
|
||||||
|
doScore :: Entity User -> Handler Html
|
||||||
|
doScore (Entity userId user) = do
|
||||||
|
entries <- runDB $ E.select
|
||||||
|
$ E.from $ \(working_on, achievement, submission) -> do
|
||||||
|
E.where_ (working_on ^. WorkingOnAchievement E.==. achievement ^. AchievementId
|
||||||
|
E.&&. E.just (submission ^. SubmissionId) E.==. working_on ^. WorkingOnFinalSubmission
|
||||||
|
E.&&. working_on ^. WorkingOnUser E.==. E.val userId)
|
||||||
|
E.orderBy [E.asc (submission ^. SubmissionStamp)]
|
||||||
|
return (achievement, submission)
|
||||||
|
|
||||||
|
entries' <- mapM (processEntry (Entity userId user)) entries
|
||||||
|
|
||||||
|
defaultLayout $ do
|
||||||
|
setTitle "Score"
|
||||||
|
$(widgetFile "score")
|
||||||
|
|
||||||
|
processEntry :: Entity User -> (Entity Achievement, Entity Submission) -> Handler (AchievementInfo, Entity Submission)
|
||||||
|
processEntry entUser (entAchievement, entSubmission) = do
|
||||||
|
aInfo <- runDB $ getAchievementInfo (Just entUser) entAchievement
|
||||||
|
return (aInfo, entSubmission)
|
@ -37,6 +37,9 @@
|
|||||||
/give-up-working-on/#AchievementId GiveUpWorkingOnR GET
|
/give-up-working-on/#AchievementId GiveUpWorkingOnR GET
|
||||||
/submission-for-achievement/#SubmissionId/#WorkingOnId SubmissionForAchievementR GET
|
/submission-for-achievement/#SubmissionId/#WorkingOnId SubmissionForAchievementR GET
|
||||||
|
|
||||||
|
/score/#UserId ScoreR GET
|
||||||
|
/my-score MyScoreR GET
|
||||||
|
|
||||||
/edit-submission/#SubmissionId EditSubmissionR GET POST
|
/edit-submission/#SubmissionId EditSubmissionR GET POST
|
||||||
|
|
||||||
/presentation/4real Presentation4RealR GET
|
/presentation/4real Presentation4RealR GET
|
||||||
|
@ -50,6 +50,8 @@ library
|
|||||||
Handler.SubmissionView
|
Handler.SubmissionView
|
||||||
Handler.Achievements
|
Handler.Achievements
|
||||||
Handler.TagUtils
|
Handler.TagUtils
|
||||||
|
Handler.Score
|
||||||
|
Handler.AchievementUtils
|
||||||
|
|
||||||
if flag(dev) || flag(library-only)
|
if flag(dev) || flag(library-only)
|
||||||
cpp-options: -DDEVELOPMENT
|
cpp-options: -DDEVELOPMENT
|
||||||
@ -136,6 +138,7 @@ library
|
|||||||
, yesod-auth-hashdb
|
, yesod-auth-hashdb
|
||||||
, pwstore-fast
|
, pwstore-fast
|
||||||
, nonce
|
, nonce
|
||||||
|
, esqueleto
|
||||||
|
|
||||||
executable gonito
|
executable gonito
|
||||||
if flag(library-only)
|
if flag(library-only)
|
||||||
|
3
templates/score.hamlet
Normal file
3
templates/score.hamlet
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<h1>Score for #{formatSubmitter user}
|
||||||
|
|
||||||
|
^{Table.buildBootstrap scoreTable entries'}
|
Loading…
Reference in New Issue
Block a user