Implement assignSubmissions
This commit is contained in:
parent
071e8c2de1
commit
6d7522410a
@ -80,6 +80,7 @@ dependencies:
|
|||||||
- uuid
|
- uuid
|
||||||
- exceptions
|
- exceptions
|
||||||
- lens
|
- lens
|
||||||
|
- MonadRandom
|
||||||
|
|
||||||
# The library contains all of our application code. The executable
|
# The library contains all of our application code. The executable
|
||||||
# defined below is just a thin wrapper.
|
# defined below is just a thin wrapper.
|
||||||
@ -92,6 +93,7 @@ library:
|
|||||||
- -Wall
|
- -Wall
|
||||||
- -fwarn-tabs
|
- -fwarn-tabs
|
||||||
- -O0
|
- -O0
|
||||||
|
- -ddump-splices
|
||||||
cpp-options: -DDEVELOPMENT
|
cpp-options: -DDEVELOPMENT
|
||||||
else:
|
else:
|
||||||
ghc-options:
|
ghc-options:
|
||||||
|
|||||||
@ -15,19 +15,20 @@ module Handler.Utils.Submission
|
|||||||
, sinkSubmission
|
, sinkSubmission
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Import -- hiding ()
|
import Import hiding ((.=))
|
||||||
|
|
||||||
import Control.Lens
|
import Control.Lens
|
||||||
import Control.Lens.Extras (is)
|
import Control.Lens.Extras (is)
|
||||||
import Utils.Lens
|
import Utils.Lens
|
||||||
|
|
||||||
import Control.Monad.State hiding (forM_)
|
import Control.Monad.State hiding (forM_)
|
||||||
|
import qualified Control.Monad.Random as Rand
|
||||||
|
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
|
|
||||||
import Data.Set (Set)
|
import Data.Set (Set)
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
import Data.Map (Map)
|
import Data.Map (Map, (!?))
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
|
||||||
|
|
||||||
@ -41,10 +42,17 @@ import qualified Database.Esqueleto as E
|
|||||||
import qualified Data.Conduit.List as Conduit
|
import qualified Data.Conduit.List as Conduit
|
||||||
|
|
||||||
|
|
||||||
|
data AssignSubmissionException = NoCorrectorsByProportion
|
||||||
|
deriving (Typeable, Show)
|
||||||
|
|
||||||
|
instance Exception AssignSubmissionException
|
||||||
|
|
||||||
assignSubmissions :: SheetId -> YesodDB UniWorX ()
|
assignSubmissions :: SheetId -> YesodDB UniWorX ()
|
||||||
assignSubmissions sid = do
|
assignSubmissions sid = do
|
||||||
correctors <- selectList [SheetCorrectorSheet ==. sid] []
|
correctors <- selectList [SheetCorrectorSheet ==. sid] []
|
||||||
let (corrsGroup, normalize -> corrsProp) = partition (is _ByTutorial . sheetCorrectorLoad . entityVal) correctors
|
let (corrsGroup, corrsProp) = partition (is _ByTutorial . sheetCorrectorLoad . entityVal) correctors
|
||||||
|
countsToLoad' :: UserId -> Bool
|
||||||
|
countsToLoad' uid = fromMaybe (error "Called `countsToLoad'` on entity not element of `corrsGroup`") $ listToMaybe [sheetCorrectorLoad | Entity _ SheetCorrector{..} <- corrsGroup, sheetCorrectorUser == uid] >>= preview _ByTutorial
|
||||||
subs <- E.select . E.from $ \(submission `E.LeftOuterJoin` user) -> do
|
subs <- E.select . E.from $ \(submission `E.LeftOuterJoin` user) -> do
|
||||||
let tutors = E.subList_select . E.from $ \(submissionUser `E.InnerJoin` tutorialUser `E.InnerJoin` tutorial) -> do
|
let tutors = E.subList_select . E.from $ \(submissionUser `E.InnerJoin` tutorialUser `E.InnerJoin` tutorial) -> do
|
||||||
-- Uncomment next line for equal chance between tutors, irrespective of the number of students per tutor per submission group
|
-- Uncomment next line for equal chance between tutors, irrespective of the number of students per tutor per submission group
|
||||||
@ -56,17 +64,33 @@ assignSubmissions sid = do
|
|||||||
E.on $ user E.?. UserId `E.in_` E.justList tutors
|
E.on $ user E.?. UserId `E.in_` E.justList tutors
|
||||||
E.where_ $ submission E.^. SubmissionSheet E.==. E.val sid
|
E.where_ $ submission E.^. SubmissionSheet E.==. E.val sid
|
||||||
E.orderBy [E.rand] -- randomize for fair tutor distribution
|
E.orderBy [E.rand] -- randomize for fair tutor distribution
|
||||||
return (submission E.^. SubmissionId, user E.?. UserId) -- , listToMaybe tutors)
|
return (submission E.^. SubmissionId, user) -- , listToMaybe tutors)
|
||||||
let subTutor :: Map SubmissionId (Maybe UserId)
|
|
||||||
subTutor = Map.fromListWith (<|>) $ map (bimap E.unValue E.unValue) subs
|
|
||||||
-- TODO: Continue here --
|
|
||||||
return ()
|
|
||||||
where
|
|
||||||
_Load :: Traversal' (Entity SheetCorrector) Rational
|
|
||||||
_Load = _entityVal . _sheetCorrectorLoad . _ByProportion
|
|
||||||
|
|
||||||
normalize :: [Entity SheetCorrector] -> [Entity SheetCorrector]
|
queue <- liftIO . Rand.evalRandIO . sequence . repeat $ Rand.weightedMay [ (sheetCorrectorUser, load sheetCorrectorLoad) | Entity _ SheetCorrector{..} <- corrsProp]
|
||||||
normalize corrsProp = corrsProp & each . _Load //~ sumOf (each . _Load) corrsProp
|
|
||||||
|
let subTutor' :: Map SubmissionId (Maybe UserId)
|
||||||
|
subTutor' = Map.fromListWith (<|>) $ map (over (_2.traverse) entityKey . over _1 E.unValue) subs
|
||||||
|
|
||||||
|
subTutor <- fmap fst . flip execStateT (Map.empty, queue) . forM_ (Map.toList subTutor') $ \case
|
||||||
|
(smid, Just tutid) -> do
|
||||||
|
_1 %= Map.insert smid tutid
|
||||||
|
when (countsToLoad' tutid) $
|
||||||
|
_2 %= delFirst (Just tutid)
|
||||||
|
(smid, Nothing) -> do
|
||||||
|
(q:qs) <- use _2
|
||||||
|
_2 .= qs
|
||||||
|
case q of
|
||||||
|
Just q -> _1 %= Map.insert smid q
|
||||||
|
Nothing -> throwM NoCorrectorsByProportion
|
||||||
|
|
||||||
|
forM_ (Map.toList subTutor) $ \(smid, tutid) -> update smid [SubmissionRatingBy =. Just tutid]
|
||||||
|
|
||||||
|
return ()
|
||||||
|
where
|
||||||
|
delFirst _ [] = []
|
||||||
|
delFirst x (y:ys)
|
||||||
|
| x == y = ys
|
||||||
|
| otherwise = y:delFirst x ys
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user