module WeekDaze.ProblemConfiguration.ProblemAnalysis(
ProblemAnalysis(
getCoursesByTeacherIdBySynchronisationId,
getCoursesRequestingSeparatedLessonsWithinAnyDay,
getDistinctRunlengthsOfSpecifiedTimesByCourse,
getFreeLocationViewTimetable,
getFreeStudentViewTimetable,
getFreeTeacherViewTimetable,
getMeetingResourcesByTime,
getMeetingsByTime,
getNAvailableDaysPerStudentTimetable,
getNAvailableDaysPerTeacherTimetable,
getNStudents,
getNTeachers,
getNTimeslotsPerDay,
getRequiredLessonCombinationsByStudentBody,
getRequiredLessonCombinationsByStudentBodyAvailableByDay,
getStudentBodiesBySynchronisationId,
getSubjectsWithAnIdealTimeslotRequest,
getSuitableCoursesByTeacherIdBySubjectByStudentBody,
getTimeslotIdRange,
getTotalLessonsPerWeekByFacilityName
),
countStudentPlaces,
findCourseFor,
findCourseForLocationViewLesson,
findCourseForTeacherViewLesson,
findDistinctSynchronisationIds,
lookupCourseFor,
mkProblemAnalysis,
areAnyResourcesBookedForGroupMeeting,
areAvailableResources,
doAllCoursesSatifyingAnotherKnowledgeRequirementSpecifyThisTime,
isFree,
isValidTimeslotId
) where
import Control.Arrow((&&&), (***))
import Data.Map((!))
import qualified Data.Array.IArray
import qualified Data.Foldable
import qualified Data.Map
import qualified Data.Maybe
import qualified Data.Set
import qualified Factory.Data.Interval
import qualified WeekDaze.Aggregate.GroupCatalogue as Aggregate.GroupCatalogue
import qualified WeekDaze.Aggregate.LocationCatalogue as Aggregate.LocationCatalogue
import qualified WeekDaze.Aggregate.StudentBody as Aggregate.StudentBody
import qualified WeekDaze.Aggregate.StudentBodyRegister as Aggregate.StudentBodyRegister
import qualified WeekDaze.Aggregate.StudentClass as Aggregate.StudentClass
import qualified WeekDaze.Aggregate.TeacherRegister as Aggregate.TeacherRegister
import qualified WeekDaze.Data.Course as Data.Course
import qualified WeekDaze.Data.Group as Data.Group
import qualified WeekDaze.Data.HumanResource as Data.HumanResource
import qualified WeekDaze.Data.Location as Data.Location
import qualified WeekDaze.Data.Resource as Data.Resource
import qualified WeekDaze.Data.Student as Data.Student
import qualified WeekDaze.Data.Subject as Data.Subject
import qualified WeekDaze.Data.Teacher as Data.Teacher
import qualified WeekDaze.LocationView.Lesson as LocationView.Lesson
import qualified WeekDaze.LocationView.Timetable as LocationView.Timetable
import qualified WeekDaze.Model.Lesson as Model.Lesson
import qualified WeekDaze.Model.Meeting as Model.Meeting
import qualified WeekDaze.Model.Timetable as Model.Timetable
import qualified WeekDaze.ProblemConfiguration.ProblemParameters as ProblemConfiguration.ProblemParameters
import qualified WeekDaze.Size as Size
import qualified WeekDaze.StudentView.Lesson as StudentView.Lesson
import qualified WeekDaze.StudentView.LessonResourceIds as StudentView.LessonResourceIds
import qualified WeekDaze.StudentView.Timetable as StudentView.Timetable
import qualified WeekDaze.StudentView.TimetableCoordinates as StudentView.TimetableCoordinates
import qualified WeekDaze.TeacherView.Lesson as TeacherView.Lesson
import qualified WeekDaze.TeacherView.Timetable as TeacherView.Timetable
import qualified WeekDaze.Temporal.Availability as Temporal.Availability
import qualified WeekDaze.Temporal.Day as Temporal.Day
import qualified WeekDaze.Temporal.Time as Temporal.Time
import qualified WeekDaze.Temporal.TimeslotRequest as Temporal.TimeslotRequest
type CoursesByTeacherIdBySubjectByStudentBody synchronisationId level teacherId timeslotId = Data.Map.Map Aggregate.StudentBody.StudentBody (Data.Map.Map (Data.Subject.Subject level) (Data.Map.Map teacherId (Data.Course.Course synchronisationId level timeslotId)))
type DistinctTimeslotRunlengthsByCourse synchronisationId level timeslotId = Data.Map.Map (Data.Course.Course synchronisationId level timeslotId) (Data.Set.Set Size.NTimeslots)
type MeetingResourcesByTime timeslotId locationId teacherId = Data.Map.Map (Temporal.Time.Time timeslotId) (Data.Set.Set locationId, Data.Set.Set Aggregate.StudentBody.StudentBody, Data.Set.Set teacherId)
type LessonsByStudentBody locationId teacherId level = Data.Map.Map Aggregate.StudentBody.StudentBody [StudentView.Lesson.Lesson locationId teacherId level]
type LessonsByStudentBodyByDay locationId teacherId level = Data.Map.Map Temporal.Day.Day (LessonsByStudentBody locationId teacherId level)
type StudentBodiesBySynchronisationId synchronisationId = Data.Map.Map synchronisationId (Data.Set.Set Aggregate.StudentBody.StudentBody)
data ProblemAnalysis level locationId synchronisationId teacherId timeslotId = MkProblemAnalysis {
getCoursesByTeacherIdBySynchronisationId :: Aggregate.TeacherRegister.CoursesByTeacherIdBySynchronisationId synchronisationId teacherId level timeslotId,
getCoursesRequestingSeparatedLessonsWithinAnyDay :: Data.Set.Set (Data.Course.Course synchronisationId level timeslotId),
getDistinctRunlengthsOfSpecifiedTimesByCourse :: DistinctTimeslotRunlengthsByCourse synchronisationId level timeslotId,
getDistinctSubjects :: Data.Subject.Knowledge level,
getFreeLocationViewTimetable :: LocationView.Timetable.Timetable locationId timeslotId teacherId level,
getFreeStudentViewTimetable :: StudentView.Timetable.Timetable timeslotId locationId teacherId level,
getFreeTeacherViewTimetable :: TeacherView.Timetable.Timetable teacherId timeslotId locationId level,
getMeetingResourcesByTime :: MeetingResourcesByTime timeslotId locationId teacherId,
getMeetingsByTime :: Model.Meeting.MeetingsByTime timeslotId locationId teacherId,
getNAvailableDaysPerStudentTimetable :: Size.NDays,
getNAvailableDaysPerTeacherTimetable :: Size.NDays,
getNStudents :: Size.NStudents,
getNTeachers :: Size.NTeachers,
getNTeacherInternalAvailabilityGaps :: Size.NDays,
getNTimeslotsPerDay :: Size.NTimeslots,
getRequiredLessonCombinationsByStudentBodyAvailableByDay:: LessonsByStudentBodyByDay locationId teacherId level,
getRequiredLessonCombinationsByStudentBody :: LessonsByStudentBody locationId teacherId level,
getSpecifiedTimes :: Temporal.Time.TimeSet timeslotId,
getStudentBodiesBySynchronisationId :: StudentBodiesBySynchronisationId synchronisationId,
getSubjectsWithAnIdealTimeslotRequest :: Data.Set.Set (Data.Subject.Subject level),
getSuitableCoursesByTeacherIdBySubjectByStudentBody :: CoursesByTeacherIdBySubjectByStudentBody synchronisationId level teacherId timeslotId,
getTimeslotIdRange :: [timeslotId],
getTotalLessonsPerWeekByFacilityName :: Data.Map.Map Data.Location.FacilityName Size.NTimeslots
}
mkProblemAnalysis :: (
Data.Array.IArray.Ix timeslotId,
Enum timeslotId,
Ord level,
Ord locationId,
Ord synchronisationId,
Ord teacherId,
RealFrac teachingRatio,
Show locationId,
Show teacherId
) => ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId -> ProblemAnalysis level locationId synchronisationId teacherId timeslotId
mkProblemAnalysis problemParameters = problemAnalysis where
timeslotIdBounds = ProblemConfiguration.ProblemParameters.getTimeslotIdBounds problemParameters
teacherRegister = ProblemConfiguration.ProblemParameters.getTeacherRegister problemParameters
studentBodies = Aggregate.StudentBodyRegister.getStudentBodies $ ProblemConfiguration.ProblemParameters.getStudentBodyRegister problemParameters
problemAnalysis = MkProblemAnalysis {
getCoursesByTeacherIdBySynchronisationId = Aggregate.TeacherRegister.findCoursesByTeacherIdBySynchronisationId teacherRegister,
getCoursesRequestingSeparatedLessonsWithinAnyDay = findCoursesRequestingSeparatedLessonsWithinAnyDay problemParameters,
getDistinctRunlengthsOfSpecifiedTimesByCourse = findDistinctRunlengthsOfSpecifiedTimesByCourse problemParameters,
getDistinctSubjects = Aggregate.TeacherRegister.extractDistinctSubjects teacherRegister,
getFreeLocationViewTimetable = Model.Timetable.mkFreeTimetable (Aggregate.LocationCatalogue.getLocationIds $ ProblemConfiguration.ProblemParameters.getLocationCatalogue problemParameters) timeslotIdBounds,
getFreeStudentViewTimetable = Model.Timetable.mkFreeTimetable studentBodies timeslotIdBounds,
getFreeTeacherViewTimetable = Model.Timetable.mkFreeTimetable (Aggregate.TeacherRegister.getTeacherIds teacherRegister) timeslotIdBounds,
getMeetingResourcesByTime = findMeetingResourcesByTime problemParameters,
getMeetingsByTime = findMeetingsByTime problemParameters,
getNAvailableDaysPerStudentTimetable = Aggregate.StudentBodyRegister.countAvailableStudentDays $ ProblemConfiguration.ProblemParameters.getStudentBodyRegister problemParameters,
getNAvailableDaysPerTeacherTimetable = Aggregate.TeacherRegister.countAvailableTeacherDays $ ProblemConfiguration.ProblemParameters.getTeacherRegister problemParameters,
getNStudents = Aggregate.StudentClass.getSize studentBodies,
getNTeachers = Data.Map.size $ Data.Map.filter Data.Teacher.offersService teacherRegister,
getNTeacherInternalAvailabilityGaps = Data.Map.foldr ((+) . Temporal.Availability.countInternalAvailabilityGaps . Data.Resource.getAvailability) 0 teacherRegister,
getNTimeslotsPerDay = ProblemConfiguration.ProblemParameters.calculateNTimeslotsPerDay timeslotIdBounds,
getRequiredLessonCombinationsByStudentBodyAvailableByDay = generateRequiredLessonCombinationsByStudentBodyAvailableByDay problemParameters problemAnalysis ,
getRequiredLessonCombinationsByStudentBody = generateRequiredLessonCombinationsByStudentBody problemParameters,
getSpecifiedTimes = Aggregate.TeacherRegister.findSpecifiedTimes teacherRegister,
getStudentBodiesBySynchronisationId = findStudentBodiesBySynchronisationId problemParameters problemAnalysis ,
getSubjectsWithAnIdealTimeslotRequest = findSubjectsWithAnIdealTimeslotRequest problemParameters,
getSuitableCoursesByTeacherIdBySubjectByStudentBody = findSuitableCoursesByTeacherIdBySubjectByStudentBody problemParameters,
getTimeslotIdRange = Factory.Data.Interval.toList timeslotIdBounds,
getTotalLessonsPerWeekByFacilityName = Aggregate.TeacherRegister.countLessonsPerWeekByFacilityName teacherRegister
}
findMeetingsByTime :: (
Ord locationId,
Ord teacherId,
Ord timeslotId,
RealFrac teachingRatio,
Show locationId,
Show teacherId
) => ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId -> Model.Meeting.MeetingsByTime timeslotId locationId teacherId
findMeetingsByTime problemParameters = Data.Set.foldr (
\groupId m -> let
(meetingTimes, maybeLocationId) = Data.Group.getMeetingTimes &&& Data.Group.getMaybeLocationId $ ProblemConfiguration.ProblemParameters.getGroupCatalogue problemParameters ! groupId
getResourceIdSet :: Aggregate.GroupCatalogue.ResourceIdsByGroupId resourceId -> Data.Set.Set resourceId
getResourceIdSet = Data.Maybe.fromMaybe Data.Set.empty . Data.Map.lookup groupId
in Data.Set.foldr (
(
$ (
Data.Set.singleton . uncurry (
Model.Meeting.mkMeeting groupId maybeLocationId
) . (
getResourceIdSet *** getResourceIdSet
) $ ProblemConfiguration.ProblemParameters.findHumanResourceIdsByGroupId problemParameters
)
) . Data.Map.insertWith Data.Set.union
) m meetingTimes
) Data.Map.empty $ ProblemConfiguration.ProblemParameters.extractDistinctGroupMembership problemParameters
findMeetingResourcesByTime :: (
Ord locationId,
Ord teacherId,
Ord timeslotId,
RealFrac teachingRatio,
Show locationId,
Show teacherId
) => ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId -> MeetingResourcesByTime timeslotId locationId teacherId
findMeetingResourcesByTime problemParameters = Data.Map.map (
Data.Set.foldr (
\meeting (l, s, t) -> (
Data.Maybe.maybe l (`Data.Set.insert` l) $ Model.Meeting.getMaybeLocationId meeting,
s `Data.Set.union` Model.Meeting.getStudentClass meeting,
t `Data.Set.union` Model.Meeting.getTeacherIds meeting
)
) (
Data.Set.empty,
Data.Set.empty,
Data.Set.empty
)
) $ findMeetingsByTime problemParameters
areAnyResourcesBookedForGroupMeeting :: (
Ord locationId,
Ord teacherId,
Ord timeslotId
)
=> ProblemAnalysis level locationId synchronisationId teacherId timeslotId
-> Temporal.Time.Time timeslotId
-> Aggregate.StudentBody.StudentBody
-> locationId
-> teacherId
-> Bool
areAnyResourcesBookedForGroupMeeting problemAnalysis time studentBody locationId teacherId = Data.Maybe.maybe False (
\(locationIdSet, studentBodySet, teacherIdSet) -> or [
Data.Set.member locationId locationIdSet,
Data.Set.member studentBody studentBodySet,
Data.Set.member teacherId teacherIdSet
]
) . Data.Map.lookup time $ getMeetingResourcesByTime problemAnalysis
findSuitableCoursesByTeacherIdBySubjectByStudentBody
:: Ord level
=> ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId
-> CoursesByTeacherIdBySubjectByStudentBody synchronisationId level teacherId timeslotId
findSuitableCoursesByTeacherIdBySubjectByStudentBody problemParameters = Data.Map.mapWithKey (
\studentBody studentProfile -> Data.Map.fromList . map (
\subject -> (
subject,
Aggregate.TeacherRegister.findSuitableCourseByTeacherId (Aggregate.StudentBody.getSize studentBody) subject . Data.Map.filter (
Data.Resource.isAvailable . (,) studentProfile
) $ ProblemConfiguration.ProblemParameters.getTeacherRegister problemParameters
)
) . Data.Set.toList $ Data.Student.deriveAmalgamatedKnowledgeRequirement studentProfile
) $ ProblemConfiguration.ProblemParameters.getStudentBodyRegister problemParameters
doAllCoursesSatifyingAnotherKnowledgeRequirementSpecifyThisTime
:: (Ord level, Ord timeslotId)
=> ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId
-> ProblemAnalysis level locationId synchronisationId teacherId timeslotId
-> Data.Subject.Subject level
-> StudentView.TimetableCoordinates.Coordinates timeslotId
-> Bool
doAllCoursesSatifyingAnotherKnowledgeRequirementSpecifyThisTime problemParameters problemAnalysis subject (studentBody, time) = Data.Set.member time (
getSpecifiedTimes problemAnalysis
) && (
Data.Foldable.any (
Data.Foldable.all (
Data.Course.isASpecifiedTime time
) . (
getSuitableCoursesByTeacherIdBySubjectByStudentBody problemAnalysis ! studentBody !
)
) . Data.Set.filter (
/= subject
) . Data.Student.deriveAmalgamatedKnowledgeRequirement $ ProblemConfiguration.ProblemParameters.getStudentBodyRegister problemParameters ! studentBody
)
findSuitableLocations :: (
Eq level,
Ord locationId,
Ord teacherId
)
=> ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId
-> Size.NStudents
-> Data.Subject.Subject level
-> teacherId
-> [locationId]
findSuitableLocations ProblemConfiguration.ProblemParameters.MkProblemParameters {
ProblemConfiguration.ProblemParameters.getLocationCatalogue = locationCatalogue,
ProblemConfiguration.ProblemParameters.getTeacherRegister = teacherRegister
} requiredCapacity subject teacherId
| Just ownLocationId <- maybeOwnLocationId
, Data.Location.isSuitable requiredCapacity requiredFacilityNames $ locationCatalogue ! ownLocationId = [ownLocationId]
| otherwise = filter (
`Data.Set.notMember` Aggregate.TeacherRegister.extractDistinctOwnLocationIds teacherRegister
) . Aggregate.LocationCatalogue.getLocationIds $ Aggregate.LocationCatalogue.findSuitableLocations requiredCapacity requiredFacilityNames locationCatalogue
where
(maybeOwnLocationId, requiredFacilityNames) = Data.Teacher.getMaybeOwnLocationId . (teacherRegister !) &&& Data.Course.getRequiredFacilityNames . (Aggregate.TeacherRegister.findSuitableCourseByTeacherId requiredCapacity subject teacherRegister !) $ teacherId
generateRequiredLessonCombinationsByStudentBody :: (
Ord level,
Ord locationId,
Ord teacherId
)
=> ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId
-> LessonsByStudentBody locationId teacherId level
generateRequiredLessonCombinationsByStudentBody problemParameters = Data.Map.mapWithKey (
\studentBody studentProfile -> let
requiredCapacity = Aggregate.StudentBody.getSize studentBody
in [
Model.Lesson.MkLesson {
Model.Lesson.getResourceIds = StudentView.LessonResourceIds.MkLessonResourceIds locationId teacherId,
Model.Lesson.getSubject = subject
} |
subject <- Data.Set.toList $ Data.Student.deriveAmalgamatedKnowledgeRequirement studentProfile,
(teacherId, teacherProfile) <- Data.Map.toList . Data.Map.filter (Data.Teacher.offersSuitableCourse requiredCapacity subject) $ ProblemConfiguration.ProblemParameters.getTeacherRegister problemParameters,
locationId <- findSuitableLocations problemParameters requiredCapacity subject teacherId,
Data.Resource.isAvailable (
studentProfile,
teacherProfile,
ProblemConfiguration.ProblemParameters.getLocationCatalogue problemParameters ! locationId
)
]
) $ ProblemConfiguration.ProblemParameters.getStudentBodyRegister problemParameters
generateRequiredLessonCombinationsByStudentBodyAvailableByDay :: (
Ord level,
Ord locationId,
Ord synchronisationId,
Ord teacherId,
Ord timeslotId
)
=> ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId
-> ProblemAnalysis level locationId synchronisationId teacherId timeslotId
-> LessonsByStudentBodyByDay locationId teacherId level
generateRequiredLessonCombinationsByStudentBodyAvailableByDay problemParameters problemAnalysis = Data.Map.fromList $ map (
\day -> (
day,
Data.Map.mapWithKey (
\studentBody -> filter (
uncurry (&&) . (
areAvailableResources problemParameters day studentBody &&& Data.Maybe.maybe False (
uncurry (&&) . (
Data.Maybe.maybe True (
\synchronisationId -> Data.Foldable.all (
uncurry (||) . (
not . Data.Student.requiresAnySubjectBy (
`Data.Set.member` Data.Set.map Data.Course.getSubject (
Aggregate.TeacherRegister.findDistinctCoursesBySynchronisationId (getCoursesByTeacherIdBySynchronisationId problemAnalysis) ! synchronisationId
)
) &&& Data.Resource.isAvailableOn day
)
) $ ProblemConfiguration.ProblemParameters.getStudentBodyRegister problemParameters
) . Data.Course.getMaybeSynchronisationId &&& uncurry (||) . (
not . Data.Course.hasRigidlySpecifiedDays &&& Data.Course.isASpecifiedDay day
)
)
) . lookupCourseFor problemParameters
)
)
) $ generateRequiredLessonCombinationsByStudentBody problemParameters
)
) Temporal.Day.range
areAvailableResources
:: (Ord locationId, Ord teacherId)
=> ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId
-> Temporal.Day.Day
-> Aggregate.StudentBody.StudentBody
-> StudentView.Lesson.Lesson locationId teacherId level
-> Bool
areAvailableResources problemParameters day studentBody studentLesson = Data.Resource.isAvailableOn day (
ProblemConfiguration.ProblemParameters.getTeacherRegister problemParameters ! StudentView.LessonResourceIds.getTeacherId resourceIds,
ProblemConfiguration.ProblemParameters.getStudentBodyRegister problemParameters ! studentBody,
ProblemConfiguration.ProblemParameters.getLocationCatalogue problemParameters ! StudentView.LessonResourceIds.getLocationId resourceIds
) where
resourceIds = Model.Lesson.getResourceIds studentLesson
isFree :: (
Data.HumanResource.HumanResource humanResource,
Data.Resource.Resource humanResource,
Ord timeslotId
)
=> ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId
-> Temporal.Time.Time timeslotId
-> humanResource
-> Bool
isFree problemParameters time = uncurry (&&) . (
Data.Resource.isAvailableOn (
Temporal.Time.getDay time
) &&& Data.Set.notMember time . Aggregate.GroupCatalogue.getMeetingTimes (
ProblemConfiguration.ProblemParameters.getGroupCatalogue problemParameters
) . Data.HumanResource.getGroupMembership
)
countStudentPlaces
:: Ord locationId
=> ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId
-> Data.Course.Course synchronisationId level timeslotId
-> locationId
-> Size.NStudents
countStudentPlaces problemParameters course = Data.Course.countStudentPlaces course . (ProblemConfiguration.ProblemParameters.getLocationCatalogue problemParameters !)
lookupCourseFor
:: (Eq level, Ord teacherId)
=> ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId
-> StudentView.Lesson.Lesson locationId teacherId level
-> Maybe (Data.Course.Course synchronisationId level timeslotId)
lookupCourseFor problemParameters = uncurry Data.Teacher.lookupCourseIn . (
Model.Lesson.getSubject &&& (ProblemConfiguration.ProblemParameters.getTeacherRegister problemParameters !) . StudentView.LessonResourceIds.getTeacherId . Model.Lesson.getResourceIds
)
findCourseFor
:: (Eq level, Ord teacherId)
=> ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId
-> StudentView.Lesson.Lesson locationId teacherId level
-> Data.Course.Course synchronisationId level timeslotId
findCourseFor problemParameters = Data.Maybe.fromJust . lookupCourseFor problemParameters
findCourseForLocationViewLesson
:: (Eq level, Ord teacherId)
=> ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId
-> locationId
-> LocationView.Lesson.Lesson teacherId level
-> Data.Course.Course synchronisationId level timeslotId
findCourseForLocationViewLesson problemParameters locationId = findCourseFor problemParameters . LocationView.Lesson.toStudentView locationId
findCourseForTeacherViewLesson
:: (Eq level, Ord teacherId)
=> ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId
-> teacherId
-> TeacherView.Lesson.Lesson locationId level
-> Data.Course.Course synchronisationId level timeslotId
findCourseForTeacherViewLesson problemParameters teacherId = findCourseFor problemParameters . TeacherView.Lesson.toStudentView teacherId
findDistinctRunlengthsOfSpecifiedTimesByCourse :: (
Enum timeslotId,
Ord level,
Ord synchronisationId,
Ord timeslotId
) => ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId -> DistinctTimeslotRunlengthsByCourse synchronisationId level timeslotId
findDistinctRunlengthsOfSpecifiedTimesByCourse = Data.Map.fromList . map (
id &&& Temporal.TimeslotRequest.findDistinctRunlengthsOfSpecifiedTimes . Data.Course.getTimeslotRequest
) . Data.Set.toList . Aggregate.TeacherRegister.extractDistinctCourses . ProblemConfiguration.ProblemParameters.getTeacherRegister
findCoursesRequestingSeparatedLessonsWithinAnyDay :: (
Enum timeslotId,
Ord level,
Ord synchronisationId,
Ord timeslotId
) => ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId -> Data.Set.Set (Data.Course.Course synchronisationId level timeslotId)
findCoursesRequestingSeparatedLessonsWithinAnyDay = Data.Map.foldr (
Data.Set.union . Data.Set.filter Data.Course.requestsSeparatedTimelotsWithinAnyDay . Data.Teacher.getService
) Data.Set.empty . ProblemConfiguration.ProblemParameters.getTeacherRegister
findSubjectsWithAnIdealTimeslotRequest :: (
Ord level,
Ord synchronisationId,
Ord timeslotId
) => ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId -> Data.Set.Set (Data.Subject.Subject level)
findSubjectsWithAnIdealTimeslotRequest = Data.Set.map Data.Course.getSubject . Data.Set.filter (
Temporal.TimeslotRequest.isIdeally . Data.Course.getTimeslotRequest
) . Aggregate.TeacherRegister.extractDistinctCourses . ProblemConfiguration.ProblemParameters.getTeacherRegister
findStudentBodiesBySynchronisationId
:: Ord level
=> ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId
-> ProblemAnalysis level locationId synchronisationId teacherId timeslotId
-> StudentBodiesBySynchronisationId synchronisationId
findStudentBodiesBySynchronisationId problemParameters = Data.Map.map (
\synchronisedCoursesByTeacherId -> Data.Map.keysSet $ Data.Map.filter (
Data.Foldable.any (
`Data.Set.member` Data.Set.fromList (map Data.Course.getSubject $ Data.Map.elems synchronisedCoursesByTeacherId)
) . Data.Student.deriveAmalgamatedKnowledgeRequirement
) $ ProblemConfiguration.ProblemParameters.getStudentBodyRegister problemParameters
) . getCoursesByTeacherIdBySynchronisationId
isValidTimeslotId
:: Eq timeslotId
=> ProblemAnalysis level locationId synchronisationId teacherId timeslotId
-> timeslotId
-> Bool
isValidTimeslotId problemAnalysis = (`elem` getTimeslotIdRange problemAnalysis)
findDistinctSynchronisationIds :: ProblemAnalysis level locationId synchronisationId teacherId timeslotId -> [synchronisationId]
findDistinctSynchronisationIds = Data.Map.keys . getCoursesByTeacherIdBySynchronisationId