Skip to content

Commit

Permalink
cleared up possibly confusing behaviour for some exported methods
Browse files Browse the repository at this point in the history
  • Loading branch information
karjo24 committed Oct 24, 2024
1 parent 05d1738 commit d089fd4
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 31 deletions.
55 changes: 38 additions & 17 deletions api/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,24 +138,17 @@ func semesterSearchHelper(c *gin.Context, m tools.MeiliSearchInterface, query st
if (err1 != nil || err2 != nil || len(semesters1) != 1 || len(semesters2) != 1) && err3 != nil {
return nil, errors.New("wrong parameters")
}
rangeSearch := false
if len(semesters1) > 0 && len(semesters2) > 0 {
firstSemester = semesters1[0]
lastSemester = semesters2[0]
rangeSearch = true
}

if !courseSearchOnly && (rangeSearch && firstSemester.Year == lastSemester.Year && firstSemester.TeachingTerm == lastSemester.TeachingTerm || len(semesters) == 1) {
isSingleSemesterSearch, singleSemester := determineSingleSemester(firstSemester, lastSemester, semesters)
if !courseSearchOnly && isSingleSemesterSearch {
// single semester search
var semester model.Semester
if rangeSearch {
semester = firstSemester
} else {
semester = semesters[0]
}
res = m.Search(query, limit, 6, meiliCourseFilter(c, user, firstSemester, lastSemester, semesters), meiliStreamFilter(c, user, semester, nil), "")
res = m.Search(query, limit, 6, meiliCourseFilter(c, user, singleSemester, singleSemester, nil), meiliStreamFilter(c, user, singleSemester, nil), "")
} else {
// multiple semester search
// multiple semester or course only search
res = m.Search(query, limit, 4, meiliCourseFilter(c, user, firstSemester, lastSemester, semesters), "", "")
}
return res, nil
Expand Down Expand Up @@ -379,12 +372,12 @@ func meiliStreamFilter(c *gin.Context, user *model.User, semester model.Semester
if user == nil {
permissionFilter = "(visibility = \"public\" AND private = 0)"
} else {
enrolledCourses := user.CoursesForSemestersWithoutAdministeredCourses(semester, semester, nil)
enrolledCourses := user.CoursesBetweenSemestersWithoutAdministeredCourses(semester, semester)
enrolledCoursesFilter := courseSliceToString(enrolledCourses)
if len(user.AdministeredCourses) == 0 {
permissionFilter = fmt.Sprintf("((visibility = \"loggedin\" OR visibility = \"public\" OR (visibility = \"enrolled\" AND courseID IN %s)) AND private = 0)", enrolledCoursesFilter)
} else {
administeredCourses := user.AdministeredCoursesForSemesters(semester, semester, nil)
administeredCourses := user.AdministeredCoursesBetweenSemesters(semester, semester)
administeredCoursesFilter := courseSliceToString(administeredCourses)
permissionFilter = fmt.Sprintf("((visibility = \"loggedin\" OR visibility = \"public\" OR (visibility = \"enrolled\" AND courseID IN %s)) AND private = 0 OR courseID IN %s)", enrolledCoursesFilter, administeredCoursesFilter)
}
Expand All @@ -398,7 +391,9 @@ func meiliStreamFilter(c *gin.Context, user *model.User, semester model.Semester

// meiliCourseFilter returns a filter conforming to MeiliSearch filter format that can be used for filtering courses
//
// Validation of model.Semester format is the caller's responsibility
// # Validation of model.Semester format is the caller's responsibility
//
// ignores either semesters or firstSemester/lastSemester, depending on semesters == nil
func meiliCourseFilter(c *gin.Context, user *model.User, firstSemester model.Semester, lastSemester model.Semester, semesters []model.Semester) string {
semesterFilter := meiliSemesterFilter(firstSemester, lastSemester, semesters)
if user != nil && user.Role == model.AdminType {
Expand All @@ -409,12 +404,22 @@ func meiliCourseFilter(c *gin.Context, user *model.User, firstSemester model.Sem
if user == nil {
permissionFilter = "(visibility = \"public\")"
} else {
enrolledCourses := user.CoursesForSemestersWithoutAdministeredCourses(firstSemester, lastSemester, semesters)
var enrolledCourses []model.Course
if semesters == nil {
enrolledCourses = user.CoursesBetweenSemestersWithoutAdministeredCourses(firstSemester, lastSemester)
} else {
enrolledCourses = user.CoursesForSemestersWithoutAdministeredCourses(semesters)
}
enrolledCoursesFilter := courseSliceToString(enrolledCourses)
if len(user.AdministeredCourses) == 0 {
permissionFilter = fmt.Sprintf("(visibility = \"loggedin\" OR visibility = \"public\" OR (visibility = \"enrolled\" AND ID IN %s))", enrolledCoursesFilter)
} else {
administeredCourses := user.AdministeredCoursesForSemesters(firstSemester, lastSemester, semesters)
var administeredCourses []model.Course
if semesters == nil {
enrolledCourses = user.CoursesBetweenSemestersWithoutAdministeredCourses(firstSemester, lastSemester)

Check failure on line 419 in api/search.go

View workflow job for this annotation

GitHub Actions / lint (./...)

ineffectual assignment to enrolledCourses (ineffassign)

Check failure on line 419 in api/search.go

View workflow job for this annotation

GitHub Actions / lint (./worker)

ineffectual assignment to enrolledCourses (ineffassign)
} else {
enrolledCourses = user.CoursesForSemestersWithoutAdministeredCourses(semesters)

Check failure on line 421 in api/search.go

View workflow job for this annotation

GitHub Actions / lint (./...)

ineffectual assignment to enrolledCourses (ineffassign)

Check failure on line 421 in api/search.go

View workflow job for this annotation

GitHub Actions / lint (./worker)

ineffectual assignment to enrolledCourses (ineffassign)
}
administeredCoursesFilter := courseSliceToString(administeredCourses)
permissionFilter = fmt.Sprintf("(visibility = \"loggedin\" OR visibility = \"public\" OR (visibility = \"enrolled\" AND ID IN %s) OR ID IN %s)", enrolledCoursesFilter, administeredCoursesFilter)
}
Expand All @@ -428,7 +433,9 @@ func meiliCourseFilter(c *gin.Context, user *model.User, firstSemester model.Sem

// meiliSemesterFilter returns a filter conforming to MeiliSearch filter format
//
// Validation of model.Semester format is the caller's responsibility
// # Validation of model.Semester format is the caller's responsibility
//
// ignores either semesters or firstSemester/lastSemester, depending on semesters == nil
func meiliSemesterFilter(firstSemester model.Semester, lastSemester model.Semester, semesters []model.Semester) string {
if len(semesters) == 0 && firstSemester.Year < 1900 && lastSemester.Year > 2800 {
return ""
Expand Down Expand Up @@ -489,6 +496,7 @@ func responseToMap(res *meilisearch.MultiSearchResponse) MeiliSearchMap {
return msm
}

// parseSemesters parses the URL Parameter semester and returns a slice containing every semester in the parameter or an error code
func parseSemesters(semestersParam string) ([]model.Semester, error) {
if semestersParam == "" {
return nil, errors.New("empty semestersParam")
Expand Down Expand Up @@ -568,6 +576,19 @@ func uintSliceToString(ids []uint) string {
return filter
}

func determineSingleSemester(firstSemester model.Semester, lastSemester model.Semester, semesters []model.Semester) (bool, model.Semester) {
if semesters == nil {
if firstSemester.IsEqual(lastSemester) {
return true, firstSemester
}
return false, model.Semester{}
}
if len(semesters) == 1 {
return true, semesters[0]
}
return false, model.Semester{}
}

// ToSearchCourseDTO converts Courses to slice of SearchCourseDTO
func ToSearchCourseDTO(cs ...model.Course) []SearchCourseDTO {
res := make([]SearchCourseDTO, len(cs))
Expand Down
27 changes: 17 additions & 10 deletions model/semester.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,8 @@ type Semester struct {
Year int
}

// InRangeOfSemesters checks if s is between firstSemester (inclusive) and lastSemester (inclusive) or is element of semesters slice
func (s *Semester) InRangeOfSemesters(firstSemester Semester, lastSemester Semester, semesters []Semester) bool {
if semesters == nil {
if firstSemester.Year == lastSemester.Year && firstSemester.TeachingTerm == lastSemester.TeachingTerm {
return s.Year == firstSemester.Year && s.TeachingTerm == firstSemester.TeachingTerm
}
return s.GreaterEqualThan(firstSemester) && lastSemester.GreaterEqualThan(*s)
}
// IsInRangeOfSemesters checks if s is element of semesters slice
func (s *Semester) IsInRangeOfSemesters(semesters []Semester) bool {
for _, semester := range semesters {
if s.Year == semester.Year && s.TeachingTerm == semester.TeachingTerm {
return true
Expand All @@ -21,7 +15,20 @@ func (s *Semester) InRangeOfSemesters(firstSemester Semester, lastSemester Semes
return false
}

// GreaterEqualThan checks if s comes after or is equal to s1
func (s *Semester) GreaterEqualThan(s1 Semester) bool {
// IsBetweenSemesters checks if s is between firstSemester (inclusive) and lastSemester (inclusive)
func (s *Semester) IsBetweenSemesters(firstSemester Semester, lastSemester Semester) bool {
if firstSemester.Year == lastSemester.Year && firstSemester.TeachingTerm == lastSemester.TeachingTerm {
return s.Year == firstSemester.Year && s.TeachingTerm == firstSemester.TeachingTerm
}
return s.IsGreaterEqualThan(firstSemester) && lastSemester.IsGreaterEqualThan(*s)
}

// IsEqual checks if s is equal to otherSemester
func (s *Semester) IsEqual(otherSemester Semester) bool {
return s.Year == otherSemester.Year && s.TeachingTerm == otherSemester.TeachingTerm
}

// IsGreaterEqualThan checks if s comes after or is equal to s1
func (s *Semester) IsGreaterEqualThan(s1 Semester) bool {
return s.Year > s1.Year || (s.Year == s1.Year && (s.TeachingTerm == "W" || s1.TeachingTerm == "S"))
}
34 changes: 30 additions & 4 deletions model/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,25 +303,51 @@ func (u *User) CoursesForSemester(year int, term string, context context.Context
}

// AdministeredCoursesForSemesters returns all courses, that the user is a course admin of, in the given semester range or semesters
func (u *User) AdministeredCoursesForSemesters(firstSemester Semester, lastSemester Semester, semesters []Semester) []Course {
func (u *User) AdministeredCoursesForSemesters(semesters []Semester) []Course {
var semester Semester
administeredCourses := make([]Course, 0)
for _, c := range u.AdministeredCourses {
semester = Semester{TeachingTerm: c.TeachingTerm, Year: c.Year}
if semester.InRangeOfSemesters(firstSemester, lastSemester, semesters) {
if semester.IsInRangeOfSemesters(semesters) {
administeredCourses = append(administeredCourses, c)
}
}
return administeredCourses
}

// AdministeredCoursesBetweenSemesters returns all courses, that the user is a course admin of, between firstSemester and lasSemester
func (u *User) AdministeredCoursesBetweenSemesters(firstSemester Semester, lastSemester Semester) []Course {
var semester Semester
administeredCourses := make([]Course, 0)
for _, c := range u.AdministeredCourses {
semester = Semester{TeachingTerm: c.TeachingTerm, Year: c.Year}
if semester.IsBetweenSemesters(firstSemester, lastSemester) {
administeredCourses = append(administeredCourses, c)
}
}
return administeredCourses
}

// CoursesForSemestersWithoutAdministeredCourses returns all courses of the user in the given semester range or semesters excluding administered courses
func (u *User) CoursesForSemestersWithoutAdministeredCourses(firstSemester Semester, lastSemester Semester, semesters []Semester) []Course {
func (u *User) CoursesForSemestersWithoutAdministeredCourses(semesters []Semester) []Course {
var semester Semester
courses := make([]Course, 0)
for _, c := range u.Courses {
semester = Semester{TeachingTerm: c.TeachingTerm, Year: c.Year}
if semester.IsInRangeOfSemesters(semesters) && !u.IsAdminOfCourse(c) {
courses = append(courses, c)
}
}
return courses
}

// CoursesBetweenSemestersWithoutAdministeredCourses returns all courses of the user in the given semester range or semesters excluding administered courses
func (u *User) CoursesBetweenSemestersWithoutAdministeredCourses(firstSemester Semester, lastSemester Semester) []Course {
var semester Semester
courses := make([]Course, 0)
for _, c := range u.Courses {
semester = Semester{TeachingTerm: c.TeachingTerm, Year: c.Year}
if semester.InRangeOfSemesters(firstSemester, lastSemester, semesters) && !u.IsAdminOfCourse(c) {
if semester.IsBetweenSemesters(firstSemester, lastSemester) && !u.IsAdminOfCourse(c) {
courses = append(courses, c)
}
}
Expand Down

0 comments on commit d089fd4

Please sign in to comment.