@@ -49,7 +49,10 @@ validate plan = do
4949validateAllSlotsHaveReserves
5050 :: Plan -> Writer [ValidationRecord ] ValidationResult
5151validateAllSlotsHaveReserves plan = do
52- tell [ValidationRecord Info " ### Validating all slots have a reserve invigilator" ]
52+ tell
53+ [ ValidationRecord Info
54+ " ### Validating all slots have a reserve invigilator"
55+ ]
5356 let slotsWithoutReserve =
5457 filter (isNothing . snd )
5558 $ map (second reserveInvigilator)
@@ -291,55 +294,93 @@ validateNotReserveOrInvigilatorIfExamInSlotOk
291294 -> Writer [ValidationRecord ] ValidationResult
292295validateNotReserveOrInvigilatorIfExamInSlotOk plan invigilatorID' invigilator'
293296 = do
294- let
295- ownReserveSlots =
296- map fst
297- $ filter ((== Just True ) . snd )
298- $ map
299- (second
300- (fmap ((== invigilatorID') . invigilatorID) . reserveInvigilator
301- )
302- )
303- $ M. toList
304- $ slots plan
305- ownExamSlots =
306- mapMaybe slot
307- $ filter ((== invigilatorID') . personID . lecturer)
308- $ scheduledExams plan
309- ownInvigilatorSlots =
310- mapMaybe slot
311- $ filter
312- (\ e ->
313- not
314- ( personID (lecturer e)
315- == invigilatorID'
316- && length (rooms e)
317- == 1
318- )
319- )
320- $ filter
321- ( elem (Just invigilatorID')
322- . map (fmap invigilatorID . invigilator)
323- . rooms
324- )
325- $ scheduledExams plan
326- notReserveOrInvigilatorIfExamInSlotOk =
327- if null (ownExamSlots `intersect` ownReserveSlots)
328- &&
329- -- null (ownExamSlots `intersect` ownInvigilatorSlots) &&
330- null (ownReserveSlots `intersect` ownInvigilatorSlots)
331- then EverythingOk
332- else HardConstraintsBroken
333- unless (notReserveOrInvigilatorIfExamInSlotOk == EverythingOk ) $ tell
334- [ ValidationRecord HardConstraintBroken
335- $ " - "
336- `append` invigilatorName invigilator'
337- `append` " has been scheduled as a reserve and invigilator"
338- `append` " during the same time, or reserve during own exams"
339- `append` " (exam, invig, reserve)"
340- `append` showt (ownExamSlots, ownInvigilatorSlots, ownReserveSlots)
341- ]
342- return notReserveOrInvigilatorIfExamInSlotOk
297+ slotsOk <- forM (M. toList $ slots plan)
298+ (validateSlotForInvigilator invigilatorID' invigilator')
299+ return $ validationResult slotsOk
300+
301+ validateSlotForInvigilator
302+ :: PersonID
303+ -> Invigilator
304+ -> ((DayIndex , SlotIndex ), Slot )
305+ -> Writer [ValidationRecord ] ValidationResult
306+ validateSlotForInvigilator invigilatorID' invigilator' (slotIdxs, slot') = do
307+ let
308+ exams = M. elems $ examsInSlot slot'
309+ ownExams = filter ((== invigilatorID') . personID . lecturer) exams
310+ ownInvigilations = filter
311+ ( (Just invigilatorID' `elem` )
312+ . map (fmap invigilatorID . invigilator)
313+ . rooms
314+ )
315+ exams
316+ if null ownExams && null ownInvigilations
317+ then return EverythingOk
318+ else if (invigilatorID <$> reserveInvigilator slot') == Just invigilatorID'
319+ then -- is reserve
320+ do
321+ tell
322+ [ ValidationRecord HardConstraintBroken
323+ $ " Problem in Slot "
324+ `append` showt slotIdxs
325+ `append` " : Reserveinvigilator "
326+ `append` invigilatorName invigilator'
327+ `append` if not $ null ownExams
328+ then " has own exam "
329+ `append` showt (map anCode ownExams)
330+ else " is invigilator "
331+ `append` showt (map anCode ownInvigilations)
332+ ]
333+ return HardConstraintsBroken
334+ else -- not reserve
335+ if null ownInvigilations
336+ then return EverythingOk
337+ else -- has invigilations
338+ let
339+ roomsOwnInvigilations =
340+ groupWith roomID
341+ $ filter
342+ ((Just invigilatorID' == ) . fmap invigilatorID . invigilator
343+ )
344+ $ concatMap rooms ownInvigilations
345+ roomsOwnExams = groupWith roomID $ concatMap rooms ownExams
346+ in
347+ if null ownExams
348+ then -- just invigilator, no own exams
349+ if length roomsOwnInvigilations <= 1
350+ then return EverythingOk
351+ else do
352+ tell
353+ [ ValidationRecord HardConstraintBroken
354+ $ " Problem in Slot "
355+ `append` showt slotIdxs
356+ `append` " : Invigilator "
357+ `append` invigilatorName invigilator'
358+ `append` " in more than one room: "
359+ `append` showt (map anCode ownInvigilations)
360+ ]
361+ return HardConstraintsBroken
362+ else -- invig and own exam (own exam must be in one room)
363+ if length roomsOwnInvigilations
364+ <= 1
365+ && length roomsOwnExams
366+ <= 1
367+ && roomID (head $ head roomsOwnInvigilations)
368+ == roomID (head $ head roomsOwnExams)
369+ then
370+ return EverythingOk
371+ else
372+ do
373+ tell
374+ [ ValidationRecord HardConstraintBroken
375+ $ " Problem in Slot "
376+ `append` showt slotIdxs
377+ `append` " : Invigilator "
378+ `append` invigilatorName invigilator'
379+ `append` " has also own exam in other room(s): "
380+ `append` showt
381+ (map anCode $ ownExams ++ ownInvigilations)
382+ ]
383+ return HardConstraintsBroken
343384
344385validateAllOwnSelfOk
345386 :: Plan
@@ -420,7 +461,8 @@ validateAllOwnSelfOk plan invigilator' examsThatShareRoomsMap = do
420461validateHandicapsInvigilator
421462 :: Plan -> Writer [ValidationRecord ] ValidationResult
422463validateHandicapsInvigilator plan = do
423- tell [ValidationRecord Info " ### Validating handicap invigilators constraints" ]
464+ tell
465+ [ValidationRecord Info " ### Validating handicap invigilators constraints" ]
424466 let days' =
425467 map slotAndNextSlot $ groupWith (fst . fst ) $ M. toList $ slots plan
426468 slotAndNextSlot day' =
@@ -435,11 +477,13 @@ validateHandicapsInvigilator'
435477 -> Writer [ValidationRecord ] ValidationResult
436478validateHandicapsInvigilator' ((si@ (d1, s1), slot'), ((d2, s2), nextSlot)) = do
437479 when (d1 /= d2) $ tell
438- [ ValidationRecord HardConstraintBroken
480+ [ ValidationRecord
481+ HardConstraintBroken
439482 " >>> This should not happen. Validating handicaps on different days"
440483 ]
441484 when (s1 + 1 /= s2) $ tell
442- [ ValidationRecord HardConstraintBroken
485+ [ ValidationRecord
486+ HardConstraintBroken
443487 " >>> This should not happen. Validating handicaps on non-following slots"
444488 ]
445489 let
0 commit comments