guards added as needed for plan generartion without exceptions

This commit is contained in:
Steffen Jost 2019-06-16 13:16:01 +02:00
parent c025c47385
commit 4f1b2886cd
3 changed files with 39 additions and 8 deletions

View File

@ -1164,14 +1164,29 @@ assignHandler tid ssh csh cid assignSids = do
}
in Map.insertWith (Map.unionWith (<>)) shnm cinf m
-- plan or assign unassigned submissions for given sheets
-- assignment :: Map SheetName ((Set SubmissionId, Set SubmissionId), Map (Maybe UserId) Int)
assignment <- fmap Map.fromList $ forM assignSids $ \sid -> do
plan <- planSubmissions sid Nothing
let shn = sheetName $ sheets ! sid
status <- case btnResult of
Nothing -> return (Set.empty, Set.empty)
(Just BtnSubmissionsAssign) -> writeSubmissionPlan plan
return (shn, (status, countMapElems plan))
let buildA :: (Map SheetName ((Set SubmissionId, Set SubmissionId), Map (Maybe UserId) Int)) -> SheetId -> DB (Map SheetName ((Set SubmissionId, Set SubmissionId), Map (Maybe UserId) Int))
buildA acc sid = maybeT (return acc) $ do
let shn = sheetName $ sheets ! sid
-- is sheet closed?
guardM $ lift $ hasWriteAccessTo $ CSheetR tid ssh csh shn SAssignR -- we must check, whether the submission is already closed and thus assignable
-- has at least one submisison?
[E.Value hasSubmission] <- lift $ E.select $ return $ E.exists $ E.from $ \submission ->
E.where_ $ submission E.^. SubmissionSheet E.==. E.val sid
guard hasSubmission
-- has at least one active corrector?
[E.Value hasCorrector] <- lift $ E.select $ return $ E.exists $ E.from $ \corrector -> do
E.where_ $ corrector E.^. SheetCorrectorSheet E.==. E.val sid
E.where_ $ corrector E.^. SheetCorrectorState E.==. E.val CorrectorNormal
-- E.where_ $ corrector E.^. SheetCorrectorLoad E./=. E.val (Load {byTutorial = Nothing, byProportion = 0})
guard hasCorrector
-- TODO: Refactor guards above! We already have these informations, but forcing the maps inside the DB acces might not be a good idea
-- TODO: Maybe refactor planSubmissions instead to not throw exceptions, but signal "ok" or "not possible" instead!
plan <- lift $ planSubmissions sid Nothing
status <- lift $ case btnResult of
Nothing -> return (Set.empty, Set.empty)
(Just BtnSubmissionsAssign) -> writeSubmissionPlan plan
return $ Map.insert shn (status, countMapElems plan) acc
assignment <- foldM buildA Map.empty assignSids
return (nrParticipants, groupsPossible, infoMap, correctorMap, assignment)
@ -1194,6 +1209,8 @@ assignHandler tid ssh csh cid assignSids = do
showAvgsDays :: Maybe NominalDiffTime -> Integer -> Text
showAvgsDays Nothing _ = mempty
showAvgsDays (Just dt) n = formatDiffDays $ dt / fromIntegral n
heat :: Double -> Double -> Double
heat achieved full = roundToDigits 3 $ cutOffPercent 0.4 full achieved
let headingShort = MsgMenuCorrectionsAssign
headingLong = prependCourseTitle tid ssh csh MsgMenuCorrectionsAssign
siteLayoutMsg headingShort $ do

View File

@ -86,6 +86,7 @@ writeSubmissionPlan newSubmissionData = do
tell (mempty, Set.singleton subId)
-- | Compute a map that shows which submissions ought the be assigned to each corrector according to sheet corrector loads, but does not alter database yet!
-- May throw an exception if there are no suitable correctors
planSubmissions :: SheetId -- ^ Sheet to distribute to correctors
-> Maybe (Set SubmissionId) -- ^ Optionally restrict submission to consider
-> YesodDB UniWorX (Map SubmissionId (Maybe UserId))

View File

@ -379,6 +379,19 @@ roundDiv :: (Integral a, Integral b, RealFrac c) => Int -> a -> b -> c
roundDiv digits numerator denominator
= roundToDigits digits $ fromIntegral numerator / fromIntegral denominator
-- | A value between 0 and 1, measuring how close `achieved` is to `full`; 0 meaning very and 1 meaning not at all
-- `offset` specifies minimum result value, unless the goal is already achieved )i.e. full <= max(0,achieved)
-- Useful for heat maps, with offset giving a visual step between completed and not yet completed
cutOffPercent :: Double -> Double -> Double -> Double
cutOffPercent offset full achieved
| full <= achieved = 0
| full <= 0 = 0
  | otherwise = offset + (1-offset * (1 - percent))
where
percent = achieved / full
------------
-- Monoid --
------------