Implement assignSubmissions

This commit is contained in:
Gregor Kleen 2018-04-26 17:48:08 +02:00
parent 071e8c2de1
commit 6d7522410a
2 changed files with 39 additions and 13 deletions

View File

@ -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:

View File

@ -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