diff --git a/teaching/scheduleProcess.go b/teaching/scheduleProcess.go new file mode 100644 index 0000000..3c20545 --- /dev/null +++ b/teaching/scheduleProcess.go @@ -0,0 +1,145 @@ +package teaching + +import "sort" + +// FilterThisWeek 过滤出本周课程, 会原地修改原课表 +// 注意:只是根据接口返回的 IsThisWeek 字段来判断是否是本周课程 +// 如果采用的是salmon base 优先级 3 的请求方式,则需要自己计算是否是本周课程 +func (courses *Courses) FilterThisWeek() *Courses { + if len(courses.Items) == 0 { + return courses + } + for _, course := range courses.Items { + if course.Schedule == nil { + continue + } + for scheduleID, schedule := range course.Schedule.Items { + if !schedule.IsThisWeek { + delete(course.Schedule.Items, scheduleID) + } + } + } + return courses +} + +// FilterByWeekdays 过滤出星期几的课程,会原地修改原课表 +func (courses *Courses) FilterByWeekdays(weekdays ...int32) *Courses { + in := func(i int32, list []int32) bool { + for _, v := range list { + if i == v { + return true + } + } + return false + } + if len(courses.Items) == 0 { + return courses + } + for _, course := range courses.Items { + if course.Schedule == nil { + continue + } + for scheduleID, schedule := range course.Schedule.Items { + if !in(schedule.WeekDay, weekdays) { + delete(course.Schedule.Items, scheduleID) + } + } + } + return courses +} + +func (schedule *ScheduleItem) StartSection() int { + return int(schedule.Section[0]) +} + +func (schedule *ScheduleItem) EndSection() int { + return int(schedule.Section[len(schedule.Section)-1]) +} + +type scheduleWithCourse struct { + *ScheduleItem + CourseName string +} + +type ScheduleLess func(s1, s2 *ScheduleItem) bool + +type scheduleWithCourseSlice struct { + schedules []*scheduleWithCourse + less ScheduleLess +} + +// Iterator 遍历课表,返回课程名,ScheduleItem,可自定义排序方法 +// 用法详见 test +func (courses *Courses) Iterator(less ScheduleLess) func() (courseName string, schedule *ScheduleItem, ok bool) { + if len(courses.Items) == 0 { + return func() (courseName string, schedule *ScheduleItem, ok bool) { + return + } + } + index := 0 + // 把课表拉平 + schedules := scheduleWithCourseSlice{less: less} + for _, course := range courses.Items { + if course.Schedule == nil { + continue + } + for _, schedule := range course.Schedule.Items { + schedules.append(&scheduleWithCourse{CourseName: course.CourseName, ScheduleItem: schedule}) + } + } + + length := schedules.Len() + sort.Sort(schedules) + + return func() (courseName string, schedule *ScheduleItem, ok bool) { + if index >= length { + return + } + courseName, schedule, ok = schedules.schedules[index].CourseName, schedules.schedules[index].ScheduleItem, true + index++ + return + } +} + +func (s *scheduleWithCourseSlice) append(item *scheduleWithCourse) { + s.schedules = append(s.schedules, item) +} + +func (s scheduleWithCourseSlice) Len() int { + return len(s.schedules) +} + +func (s scheduleWithCourseSlice) Less(i, j int) bool { + return s.less(s.schedules[i].ScheduleItem, s.schedules[j].ScheduleItem) +} + +func (s scheduleWithCourseSlice) Swap(i, j int) { + s.schedules[i], s.schedules[j] = s.schedules[j], s.schedules[i] +} + +func DefaultSort(s1, s2 *ScheduleItem) bool { + // 只考虑本周课程 + // 先按星期升序,再按开始节次升序 + switch { + case s1.WeekDay < s2.WeekDay: + return true + case s1.WeekDay > s2.WeekDay: + return false + case s1.WeekDay == s2.WeekDay: + switch { + case s1.StartSection() < s2.StartSection(): + return true + case s1.StartSection() > s2.StartSection(): + return false + default: + return true + } + } + return true +} + +func Reverse(less ScheduleLess) ScheduleLess { + return func(s1, s2 *ScheduleItem) bool { + return !less(s1, s2) + } +} diff --git a/teaching/scheduleProcess_test.go b/teaching/scheduleProcess_test.go new file mode 100644 index 0000000..4d69291 --- /dev/null +++ b/teaching/scheduleProcess_test.go @@ -0,0 +1,94 @@ +package teaching + +import ( + "fmt" + "testing" +) + +func getCourses() *Courses { + return &Courses{Items: map[string]*CourseItem{ + "课程id1": &CourseItem{ + CourseName: "课程名称1", + Schedule: &Schedule{Items: map[string]*ScheduleItem{ + // 此 schedule 在本测试中应当被过滤 + "课程1-a-应当被过滤": &ScheduleItem{ + IsThisWeek: true, + Teachers: nil, + //Week: []int32{1, 2, 3, 4}, + WeekDay: 3, + Section: []int32{6, 7, 8, 9}, + // 借用一下 Location 字段用来更明显地测试,其实这个是教室字段 + Location: "应当被过滤", + }, + // 此 schedule 在本测试中应当排在第四 + "课程1-b-应当第四": &ScheduleItem{ + IsThisWeek: true, + Teachers: nil, + //Week: []int32{1, 2, 3, 4}, + WeekDay: 2, + Section: []int32{3, 4}, + Location: "应当第四", + }, + }, + }, + }, + "课程id2": &CourseItem{ + CourseName: "课程名称2", + Schedule: &Schedule{Items: map[string]*ScheduleItem{ + // 此 schedule 在本测试中应当排在第五 + "课程2-a-应当第五": &ScheduleItem{ + IsThisWeek: true, + Teachers: nil, + WeekDay: 2, + Section: []int32{6, 7, 8, 9}, + Location: "应当第五", + }, + // 此 schedule 在本测试中应当排在第二 + "课程2-b-应当第二": &ScheduleItem{ + IsThisWeek: true, + Teachers: nil, + WeekDay: 1, + Section: []int32{3, 4}, + Location: "应当第二", + }, + }, + }, + }, + "课程id3": &CourseItem{ + CourseName: "课程名称3", + Schedule: &Schedule{Items: map[string]*ScheduleItem{ + // 此 schedule 在本测试中应当排在第三 + "课程3-a-应当第三": &ScheduleItem{ + IsThisWeek: true, + Teachers: nil, + WeekDay: 1, + Section: []int32{6, 7, 8, 9}, + Location: "应当第三", + }, + // 此 schedule 在本测试中应当排在第一 + "课程3-b-应当第一": &ScheduleItem{ + IsThisWeek: true, + Teachers: nil, + WeekDay: 1, + Section: []int32{1, 2}, + Location: "应当第一", + }, + }, + }, + }, + }} +} + +func TestScheduleProcess(t *testing.T) { + courses := getCourses() + courses.FilterThisWeek().FilterByWeekdays(1, 2) + // 这里测试一下反序函数,所以实际输出一二三四五会反序,懒得改中文表述了 + it := courses.Iterator(Reverse(DefaultSort)) + for { + courseName, schedule, ok := it() + if !ok { + break + } + fmt.Println(courseName, schedule) + } +}