StudyFeatures  -- multiple entries possible for students pursuing several degrees at once, usually created upon LDAP login
    user          UserId
    degree        StudyDegreeId   -- Abschluss, i.e. Master, Bachelor, etc.
    field         StudyTermsId    -- Fach, i.e. Informatics, Philosophy, etc.
    superField    StudyTermsId Maybe
    type          StudyFieldType  -- Major or minor, i.e. Haupt-/Nebenfach
    semester      Int
    firstObserved UTCTime Maybe
    lastObserved  UTCTime default=now() -- last update from LDAP
    valid         Bool default=true
    relevanceCached Bool default=false
    UniqueStudyFeatures user degree field type semester
    deriving Eq Show
    -- UniqueUserSubject ubuser degree field -- There exists a counterexample

RelevantStudyFeatures
    term          TermId
    studyFeatures StudyFeaturesId
    UniqueRelevantStudyFeatures term studyFeatures

StudyDegree   -- Studienabschluss
    key           Int            -- LMU-internal key
    shorthand     Text Maybe     -- admin determined shorthand
    name          Text Maybe     -- description given by LDAP
    Primary key                  -- column key is used as actual DB row key
                                 -- newtype Key StudyDegree = StudyDegreeKey' { unStudyDegreeKey :: Int }
    deriving Eq Show
StudyTerms    -- Studiengang
    key           Int            -- standardised key
    shorthand     Text Maybe     -- admin determined shorthand
    name          Text Maybe     -- description given by LDAP
    defaultDegree StudyDegreeId Maybe
    defaultType   StudyFieldType Maybe
    Primary key                  -- column key is used as actual DB row key
                                 -- newtype Key StudyTerms = StudyTermsKey' { unStudyTermsKey :: Int }
    deriving Eq Ord Show
StudySubTerms
    child         StudyTermsId
    parent        StudyTermsId
    UniqueStudySubTerms child parent
StudyTermNameCandidate    -- No one at LMU is willing and able to tell us the meaning of the keys for StudyDegrees and StudyTerms.
    -- Each LDAP login provides an unordered set of keys and an unordered set of plain text description with an unknown 1-1 correspondence.
    -- This table helps us to infer which key belongs to which plain text by recording possible combinations at login.
    -- If a login provides n keys and n plan texts, then n^2 rows with the same incidence are created, storing all combinations
    incidence     TermCandidateIncidence -- random id, generated once per login to associate matching pairs
    key           Int      -- a possible key for the studyTermName or studySubTermName
    name          Text     -- studyTermName as plain text from LDAP
    deriving Show Eq Ord
StudySubTermParentCandidate
    incidence     TermCandidateIncidence
    key           Int
    parent        Int
    deriving Show Eq Ord
StudyTermStandaloneCandidate
    incidence     TermCandidateIncidence
    key           Int
    deriving Show Eq Ord

