feat(exams): check exam_discouraged_modes
This commit is contained in:
parent
f7bab3befc
commit
f9c50c80f2
@ -1917,6 +1917,7 @@ ExamClosedMustBeAfterEnd: "Noten stehen fest ab" muss nach Ende liegen
|
|||||||
ExamRegistrationMustFollowSchoolSeparationFromStart dayCount@Int: Nach Regeln des Instituts #{pluralDE dayCount "muss" "müssen"} zwischen "Anmeldung ab" und "Beginn" mindestens #{dayCount} #{pluralDE dayCount "Tag" "Tage"} liegen.
|
ExamRegistrationMustFollowSchoolSeparationFromStart dayCount@Int: Nach Regeln des Instituts #{pluralDE dayCount "muss" "müssen"} zwischen "Anmeldung ab" und "Beginn" mindestens #{dayCount} #{pluralDE dayCount "Tag" "Tage"} liegen.
|
||||||
ExamRegistrationMustFollowSchoolDuration dayCount@Int: Nach Regeln des Instituts #{pluralDE dayCount "muss" "müssen"} zwischen "Anmeldung ab" und "Anmeldung bis" mindestens #{dayCount} #{pluralDE dayCount "Tag" "Tage"} liegen.
|
ExamRegistrationMustFollowSchoolDuration dayCount@Int: Nach Regeln des Instituts #{pluralDE dayCount "muss" "müssen"} zwischen "Anmeldung ab" und "Anmeldung bis" mindestens #{dayCount} #{pluralDE dayCount "Tag" "Tage"} liegen.
|
||||||
ExamModeRequiredForRegistration: Nach Regeln des Institus muss die "Ausgestaltung der Prüfung" vollständig angegeben sein, bevor "Anmeldung ab" festgelegt werden kann.
|
ExamModeRequiredForRegistration: Nach Regeln des Institus muss die "Ausgestaltung der Prüfung" vollständig angegeben sein, bevor "Anmeldung ab" festgelegt werden kann.
|
||||||
|
ExamModeSchoolDiscouraged: Nach Regeln des Instituts wird von der angegebenen "Ausgestaltung der Prüfung" abgeraten
|
||||||
|
|
||||||
ExamOccurrenceEndMustBeAfterStart eoName@ExamOccurrenceName: Beginn des Termins #{eoName} muss vor seinem Ende liegen
|
ExamOccurrenceEndMustBeAfterStart eoName@ExamOccurrenceName: Beginn des Termins #{eoName} muss vor seinem Ende liegen
|
||||||
ExamOccurrenceStartMustBeAfterExamStart eoName@ExamOccurrenceName: Beginn des Termins #{eoName} muss nach Beginn der Prüfung liegen
|
ExamOccurrenceStartMustBeAfterExamStart eoName@ExamOccurrenceName: Beginn des Termins #{eoName} muss nach Beginn der Prüfung liegen
|
||||||
|
|||||||
@ -1916,6 +1916,7 @@ ExamClosedMustBeAfterEnd: "Exam achievements registered" must be after "end"
|
|||||||
ExamRegistrationMustFollowSchoolSeparationFromStart dayCount: As per school rules there #{pluralEN dayCount "needs" "need"} to be at least #{dayCount} #{pluralEN dayCount "day" "days"} between "Register from" and "Start".
|
ExamRegistrationMustFollowSchoolSeparationFromStart dayCount: As per school rules there #{pluralEN dayCount "needs" "need"} to be at least #{dayCount} #{pluralEN dayCount "day" "days"} between "Register from" and "Start".
|
||||||
ExamRegistrationMustFollowSchoolDuration dayCount: As per school rules there #{pluralEN dayCount "needs" "need"} to be at least #{dayCount} #{pluralEN dayCount "day" "days"} between "Register from" and "Register to".
|
ExamRegistrationMustFollowSchoolDuration dayCount: As per school rules there #{pluralEN dayCount "needs" "need"} to be at least #{dayCount} #{pluralEN dayCount "day" "days"} between "Register from" and "Register to".
|
||||||
ExamModeRequiredForRegistration: As per school rules "Exam design" needs to be fully specified before "Register from" may be set.
|
ExamModeRequiredForRegistration: As per school rules "Exam design" needs to be fully specified before "Register from" may be set.
|
||||||
|
ExamModeSchoolDiscouraged: As per school rules the specified "Exam design" is discouraged
|
||||||
|
|
||||||
ExamOccurrenceEndMustBeAfterStart eoName: End of the occurrence #{eoName} must be after it's start
|
ExamOccurrenceEndMustBeAfterStart eoName: End of the occurrence #{eoName} must be after it's start
|
||||||
ExamOccurrenceStartMustBeAfterExamStart eoName: Start of the occurrence #{eoName} must be after the exam start
|
ExamOccurrenceStartMustBeAfterExamStart eoName: Start of the occurrence #{eoName} must be after the exam start
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import Handler.Exam.CorrectorInvite ()
|
|||||||
|
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
import Handler.Utils.Invitations
|
import Handler.Utils.Invitations
|
||||||
|
import Handler.Utils.Exam (evalExamModeDNF)
|
||||||
|
|
||||||
import Data.Map ((!))
|
import Data.Map ((!))
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
@ -428,3 +429,5 @@ validateExam cId oldExam = do
|
|||||||
, is _Just examSynchronicity
|
, is _Just examSynchronicity
|
||||||
, is _Just examRequiredEquipment
|
, is _Just examRequiredEquipment
|
||||||
]
|
]
|
||||||
|
|
||||||
|
warnValidation MsgExamModeSchoolDiscouraged . not $ evalExamModeDNF schoolExamDiscouragedModes efExamMode
|
||||||
|
|||||||
@ -26,8 +26,9 @@ getEShowR tid ssh csh examn = do
|
|||||||
cTime <- liftIO getCurrentTime
|
cTime <- liftIO getCurrentTime
|
||||||
mUid <- maybeAuthId
|
mUid <- maybeAuthId
|
||||||
|
|
||||||
(Entity eId Exam{..}, examParts, examVisible, (gradingVisible, gradingShown), (occurrenceAssignmentsVisible, occurrenceAssignmentsShown), results, result, bonus, occurrences, (registered, mayRegister), registeredCount, lecturerInfoShown) <- runDB $ do
|
(Entity eId Exam{..}, School{..}, examParts, examVisible, (gradingVisible, gradingShown), (occurrenceAssignmentsVisible, occurrenceAssignmentsShown), results, result, bonus, occurrences, (registered, mayRegister), registeredCount, lecturerInfoShown) <- runDB $ do
|
||||||
exam@(Entity eId Exam{..}) <- fetchExam tid ssh csh examn
|
exam@(Entity eId Exam{..}) <- fetchExam tid ssh csh examn
|
||||||
|
school <- getJust examCourse >>= belongsToJust courseSchool
|
||||||
|
|
||||||
let examVisible = NTop (Just cTime) >= NTop examVisibleFrom
|
let examVisible = NTop (Just cTime) >= NTop examVisibleFrom
|
||||||
|
|
||||||
@ -82,7 +83,7 @@ getEShowR tid ssh csh examn = do
|
|||||||
|
|
||||||
lecturerInfoShown <- hasReadAccessTo $ CExamR tid ssh csh examn EEditR
|
lecturerInfoShown <- hasReadAccessTo $ CExamR tid ssh csh examn EEditR
|
||||||
|
|
||||||
return (exam, examParts, examVisible, (gradingVisible, gradingShown), (occurrenceAssignmentsVisible, occurrenceAssignmentsShown), results, result, bonus, occurrences, (registered, mayRegister), registeredCount, lecturerInfoShown)
|
return (exam, school, examParts, examVisible, (gradingVisible, gradingShown), (occurrenceAssignmentsVisible, occurrenceAssignmentsShown), results, result, bonus, occurrences, (registered, mayRegister), registeredCount, lecturerInfoShown)
|
||||||
|
|
||||||
let occurrenceNamesShown = lecturerInfoShown
|
let occurrenceNamesShown = lecturerInfoShown
|
||||||
partNumbersShown = lecturerInfoShown
|
partNumbersShown = lecturerInfoShown
|
||||||
@ -174,6 +175,11 @@ getEShowR tid ssh csh examn = do
|
|||||||
|
|
||||||
let heading = prependCourseTitle tid ssh csh $ CI.original examName
|
let heading = prependCourseTitle tid ssh csh $ CI.original examName
|
||||||
|
|
||||||
|
notificationDiscouragedExamMode <- runMaybeT $ do
|
||||||
|
guard $ evalExamModeDNF schoolExamDiscouragedModes examExamMode
|
||||||
|
guardM . hasWriteAccessTo $ CExamR tid ssh csh examn EEditR
|
||||||
|
return $ notification NotificationBroad =<< messageI Warning MsgExamModeSchoolDiscouraged
|
||||||
|
|
||||||
siteLayoutMsg heading $ do
|
siteLayoutMsg heading $ do
|
||||||
setTitleI heading
|
setTitleI heading
|
||||||
let
|
let
|
||||||
|
|||||||
@ -76,7 +76,7 @@ mkSchoolForm mSsh template = renderAForm FormStandard $ SchoolForm
|
|||||||
<*> aopt daysField (fslI MsgSchoolExamMinimumRegisterBeforeStart & setTooltip MsgSchoolExamMinimumRegisterBeforeStartTip) (sfExamMinimumRegisterBeforeStart <$> template)
|
<*> aopt daysField (fslI MsgSchoolExamMinimumRegisterBeforeStart & setTooltip MsgSchoolExamMinimumRegisterBeforeStartTip) (sfExamMinimumRegisterBeforeStart <$> template)
|
||||||
<*> aopt daysField (fslI MsgSchoolExamMinimumRegisterDuration & setTooltip MsgSchoolExamMinimumRegisterDurationTip) (sfExamMinimumRegisterDuration <$> template)
|
<*> aopt daysField (fslI MsgSchoolExamMinimumRegisterDuration & setTooltip MsgSchoolExamMinimumRegisterDurationTip) (sfExamMinimumRegisterDuration <$> template)
|
||||||
<*> apopt checkBoxField (fslI MsgSchoolExamRequireModeForRegistration & setTooltip MsgSchoolExamRequireModeForRegistration) (sfExamRequireModeForRegistration <$> template)
|
<*> apopt checkBoxField (fslI MsgSchoolExamRequireModeForRegistration & setTooltip MsgSchoolExamRequireModeForRegistration) (sfExamRequireModeForRegistration <$> template)
|
||||||
<*> areq (jsonField False) (fslI MsgSchoolExamDiscouragedModes) (sfExamDiscouragedModes <$> template <|> pure (ExamModeDNF predDNFFalse))
|
<*> areq pathPieceField (fslI MsgSchoolExamDiscouragedModes) (sfExamDiscouragedModes <$> template <|> pure (ExamModeDNF predDNFFalse))
|
||||||
where
|
where
|
||||||
ldapOrgs :: HandlerFor UniWorX (OptionList (CI Text))
|
ldapOrgs :: HandlerFor UniWorX (OptionList (CI Text))
|
||||||
ldapOrgs = fmap (mkOptionList . map (\t -> Option (CI.original t) t (CI.original t)) . Set.toAscList) . runDB $
|
ldapOrgs = fmap (mkOptionList . map (\t -> Option (CI.original t) t (CI.original t)) . Set.toAscList) . runDB $
|
||||||
|
|||||||
@ -12,6 +12,7 @@ module Handler.Utils.Exam
|
|||||||
, examAutoOccurrence
|
, examAutoOccurrence
|
||||||
, deregisterExamUsersCount, deregisterExamUsers
|
, deregisterExamUsersCount, deregisterExamUsers
|
||||||
, examAidsPresetWidget, examOnlinePresetWidget, examSynchronicityPresetWidget, examRequiredEquipmentPresetWidget
|
, examAidsPresetWidget, examOnlinePresetWidget, examSynchronicityPresetWidget, examRequiredEquipmentPresetWidget
|
||||||
|
, evalExamModeDNF
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Import
|
import Import
|
||||||
@ -657,3 +658,25 @@ examSynchronicityPresetWidget preset = $(i18nWidgetFile "exam-mode/synchronicity
|
|||||||
|
|
||||||
examRequiredEquipmentPresetWidget :: ExamRequiredEquipmentPreset -> Widget
|
examRequiredEquipmentPresetWidget :: ExamRequiredEquipmentPreset -> Widget
|
||||||
examRequiredEquipmentPresetWidget preset = $(i18nWidgetFile "exam-mode/requiredEquipment")
|
examRequiredEquipmentPresetWidget preset = $(i18nWidgetFile "exam-mode/requiredEquipment")
|
||||||
|
|
||||||
|
|
||||||
|
evalExamModeDNF :: ExamModeDNF -> ExamMode -> Bool
|
||||||
|
evalExamModeDNF (ExamModeDNF PredDNF{..}) ExamMode{..}
|
||||||
|
= dnfTerms
|
||||||
|
& map (Set.toList . toNullable) . Set.toList
|
||||||
|
& map ( maybe True (ofoldr1 (&&))
|
||||||
|
. fromNullable
|
||||||
|
. map (\pl -> bool id not (is _PLNegated pl) . evalPred $ plVar pl)
|
||||||
|
)
|
||||||
|
& maybe False (ofoldr1 (||)) . fromNullable
|
||||||
|
where
|
||||||
|
evalPred :: ExamModePredicate -> Bool
|
||||||
|
evalPred = \case
|
||||||
|
ExamModePredAids p
|
||||||
|
-> examAids == Just (ExamAidsPreset p)
|
||||||
|
ExamModePredOnline p
|
||||||
|
-> examOnline == Just (ExamOnlinePreset p)
|
||||||
|
ExamModePredSynchronicity p
|
||||||
|
-> examSynchronicity == Just (ExamSynchronicityPreset p)
|
||||||
|
ExamModePredRequiredEquipment p
|
||||||
|
-> examRequiredEquipment == Just (ExamRequiredEquipmentPreset p)
|
||||||
|
|||||||
@ -549,9 +549,11 @@ deriveJSON defaultOptions
|
|||||||
{ constructorTagModifier = camelToPathPiece' 3
|
{ constructorTagModifier = camelToPathPiece' 3
|
||||||
, sumEncoding = TaggedObject "setting" "preset"
|
, sumEncoding = TaggedObject "setting" "preset"
|
||||||
} ''ExamModePredicate
|
} ''ExamModePredicate
|
||||||
|
derivePathPiece ''ExamModePredicate (camelToPathPiece' 3) "--"
|
||||||
|
deriveFinite ''ExamModePredicate
|
||||||
|
|
||||||
newtype ExamModeDNF = ExamModeDNF { examModeDNF :: PredDNF ExamModePredicate }
|
newtype ExamModeDNF = ExamModeDNF { examModeDNF :: PredDNF ExamModePredicate }
|
||||||
deriving (Eq, Ord, Read, Show, Generic, Typeable)
|
deriving (Eq, Ord, Read, Show, Generic, Typeable)
|
||||||
deriving newtype (Semigroup, Monoid, ToJSON, FromJSON)
|
deriving newtype (Semigroup, Monoid, ToJSON, FromJSON, PathPiece)
|
||||||
|
|
||||||
derivePersistFieldJSON ''ExamModeDNF
|
derivePersistFieldJSON ''ExamModeDNF
|
||||||
|
|||||||
@ -20,6 +20,9 @@ $maybe desc <- examDescription
|
|||||||
#{desc}
|
#{desc}
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
$maybe warn <- notificationDiscouragedExamMode
|
||||||
|
^{warn}
|
||||||
|
|
||||||
<dl .deflist>
|
<dl .deflist>
|
||||||
$if not examVisible
|
$if not examVisible
|
||||||
<dt .deflist__dt>_{MsgExamVisibleFrom}
|
<dt .deflist__dt>_{MsgExamVisibleFrom}
|
||||||
|
|||||||
Reference in New Issue
Block a user