diff --git a/backend/model/eventModel.go b/backend/model/eventModel.go index 142fa0b..8a492cf 100644 --- a/backend/model/eventModel.go +++ b/backend/model/eventModel.go @@ -79,7 +79,7 @@ func (e *Event) SetCourse(course string) Event { return *e } -// Creates an AnonymizedEventDTO from an Event hiding all sensitive data +// AnonymizeEvent Creates an AnonymizedEventDTO from an Event hiding all sensitive data func (e *Event) AnonymizeEvent() AnonymizedEventDTO { return AnonymizedEventDTO{ Day: e.Day, diff --git a/backend/model/eventModel_test.go b/backend/model/eventModel_test.go index 95d4954..c153f23 100644 --- a/backend/model/eventModel_test.go +++ b/backend/model/eventModel_test.go @@ -217,3 +217,264 @@ func TestEvent_AnonymizeEvent(t *testing.T) { }) } } + +func TestEvent_GetName(t *testing.T) { + type fields struct { + UUID string + Day string + Week string + Start types.DateTime + End types.DateTime + Name string + EventType string + Compulsory string + Prof string + Rooms string + Notes string + BookedAt string + Course string + Semester string + BaseModel models.BaseModel + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "empty event", + fields: fields{}, + want: "", + }, + { + name: "one event", + fields: fields{Name: "Event"}, + want: "Event", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := &Event{ + UUID: tt.fields.UUID, + Day: tt.fields.Day, + Week: tt.fields.Week, + Start: tt.fields.Start, + End: tt.fields.End, + Name: tt.fields.Name, + EventType: tt.fields.EventType, + Compulsory: tt.fields.Compulsory, + Prof: tt.fields.Prof, + Rooms: tt.fields.Rooms, + Notes: tt.fields.Notes, + BookedAt: tt.fields.BookedAt, + Course: tt.fields.Course, + Semester: tt.fields.Semester, + BaseModel: tt.fields.BaseModel, + } + if got := e.GetName(); got != tt.want { + t.Errorf("GetName() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestEvent_SetCourse(t *testing.T) { + type fields struct { + UUID string + Day string + Week string + Start types.DateTime + End types.DateTime + Name string + EventType string + Compulsory string + Prof string + Rooms string + Notes string + BookedAt string + Course string + Semester string + BaseModel models.BaseModel + } + type args struct { + course string + } + tests := []struct { + name string + fields fields + args args + want Event + }{ + { + name: "set course", + fields: fields{}, + args: args{course: "test"}, + want: Event{Course: "test"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := &Event{ + UUID: tt.fields.UUID, + Day: tt.fields.Day, + Week: tt.fields.Week, + Start: tt.fields.Start, + End: tt.fields.End, + Name: tt.fields.Name, + EventType: tt.fields.EventType, + Compulsory: tt.fields.Compulsory, + Prof: tt.fields.Prof, + Rooms: tt.fields.Rooms, + Notes: tt.fields.Notes, + BookedAt: tt.fields.BookedAt, + Course: tt.fields.Course, + Semester: tt.fields.Semester, + BaseModel: tt.fields.BaseModel, + } + if got := e.SetCourse(tt.args.course); !reflect.DeepEqual(got, tt.want) { + t.Errorf("SetCourse() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestEvent_SetName(t *testing.T) { + type fields struct { + UUID string + Day string + Week string + Start types.DateTime + End types.DateTime + Name string + EventType string + Compulsory string + Prof string + Rooms string + Notes string + BookedAt string + Course string + Semester string + BaseModel models.BaseModel + } + type args struct { + name string + } + tests := []struct { + name string + fields fields + args args + }{ + { + name: "set name", + fields: fields{ + Name: "name", + }, + args: args{ + name: "name", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := &Event{ + UUID: tt.fields.UUID, + Day: tt.fields.Day, + Week: tt.fields.Week, + Start: tt.fields.Start, + End: tt.fields.End, + Name: tt.fields.Name, + EventType: tt.fields.EventType, + Compulsory: tt.fields.Compulsory, + Prof: tt.fields.Prof, + Rooms: tt.fields.Rooms, + Notes: tt.fields.Notes, + BookedAt: tt.fields.BookedAt, + Course: tt.fields.Course, + Semester: tt.fields.Semester, + BaseModel: tt.fields.BaseModel, + } + e.SetName(tt.args.name) + }) + } +} + +func TestEvent_TableName(t *testing.T) { + type fields struct { + UUID string + Day string + Week string + Start types.DateTime + End types.DateTime + Name string + EventType string + Compulsory string + Prof string + Rooms string + Notes string + BookedAt string + Course string + Semester string + BaseModel models.BaseModel + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "table name", + fields: fields{}, + want: "events", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := &Event{ + UUID: tt.fields.UUID, + Day: tt.fields.Day, + Week: tt.fields.Week, + Start: tt.fields.Start, + End: tt.fields.End, + Name: tt.fields.Name, + EventType: tt.fields.EventType, + Compulsory: tt.fields.Compulsory, + Prof: tt.fields.Prof, + Rooms: tt.fields.Rooms, + Notes: tt.fields.Notes, + BookedAt: tt.fields.BookedAt, + Course: tt.fields.Course, + Semester: tt.fields.Semester, + BaseModel: tt.fields.BaseModel, + } + if got := e.TableName(); got != tt.want { + t.Errorf("TableName() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestEvents_Contains1(t *testing.T) { + type args struct { + event Event + } + tests := []struct { + name string + m Events + args args + want bool + }{ + { + name: "empty events", + m: Events{}, + args: args{event: Event{}}, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.m.Contains(tt.args.event); got != tt.want { + t.Errorf("Contains() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/backend/model/feedModel_test.go b/backend/model/feedModel_test.go new file mode 100644 index 0000000..111d8d1 --- /dev/null +++ b/backend/model/feedModel_test.go @@ -0,0 +1,45 @@ +package model + +import ( + "github.com/pocketbase/pocketbase/models" + "github.com/pocketbase/pocketbase/tools/types" + "testing" +) + +func TestFeed_SetModules(t *testing.T) { + type fields struct { + Modules string + Retrieved types.DateTime + BaseModel models.BaseModel + } + type args struct { + modules string + } + tests := []struct { + name string + fields fields + args args + }{ + { + name: "set modules", + fields: fields{ + Modules: "", + Retrieved: types.DateTime{}, + BaseModel: models.BaseModel{}, + }, + args: args{ + modules: "modules", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f := &Feed{ + Modules: tt.fields.Modules, + Retrieved: tt.fields.Retrieved, + BaseModel: tt.fields.BaseModel, + } + f.SetModules(tt.args.modules) + }) + } +} diff --git a/backend/model/moduleModel_test.go b/backend/model/moduleModel_test.go new file mode 100644 index 0000000..b2ebe5d --- /dev/null +++ b/backend/model/moduleModel_test.go @@ -0,0 +1,126 @@ +package model + +import "testing" + +func TestModuleDTO_GetName(t *testing.T) { + type fields struct { + UUID string + Name string + Prof string + Course string + Semester string + EventType string + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "get name", + fields: fields{ + Name: "name", + }, + want: "name", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &ModuleDTO{ + UUID: tt.fields.UUID, + Name: tt.fields.Name, + Prof: tt.fields.Prof, + Course: tt.fields.Course, + Semester: tt.fields.Semester, + EventType: tt.fields.EventType, + } + if got := m.GetName(); got != tt.want { + t.Errorf("GetName() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestModuleDTO_SetName(t *testing.T) { + type fields struct { + UUID string + Name string + Prof string + Course string + Semester string + EventType string + } + type args struct { + name string + } + tests := []struct { + name string + fields fields + args args + }{ + { + name: "set name", + fields: fields{ + Name: "name", + }, + args: args{ + name: "name", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &ModuleDTO{ + UUID: tt.fields.UUID, + Name: tt.fields.Name, + Prof: tt.fields.Prof, + Course: tt.fields.Course, + Semester: tt.fields.Semester, + EventType: tt.fields.EventType, + } + m.SetName(tt.args.name) + }) + } +} + +func TestModule_SetName(t *testing.T) { + type fields struct { + UUID string + Name string + Prof string + Course string + Semester string + Events Events + } + type args struct { + name string + } + tests := []struct { + name string + fields fields + args args + }{ + { + name: "set name", + fields: fields{ + Name: "name", + }, + args: args{ + name: "name", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &Module{ + UUID: tt.fields.UUID, + Name: tt.fields.Name, + Prof: tt.fields.Prof, + Course: tt.fields.Course, + Semester: tt.fields.Semester, + Events: tt.fields.Events, + } + m.SetName(tt.args.name) + }) + } +} diff --git a/backend/service/addRoute.go b/backend/service/addRoute.go index 9938aca..24991c3 100644 --- a/backend/service/addRoute.go +++ b/backend/service/addRoute.go @@ -22,7 +22,6 @@ import ( v1 "htwkalender/service/fetch/v1" v2 "htwkalender/service/fetch/v2" "htwkalender/service/functions/time" - "htwkalender/service/ical" "htwkalender/service/room" "log/slog" "net/http" @@ -380,29 +379,4 @@ func AddRoutes(app *pocketbase.PocketBase) { } return nil }) - - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { - _, err := e.Router.AddRoute(echo.Route{ - Method: http.MethodGet, - Path: "/api/feeds/migrate", - Handler: func(c echo.Context) error { - err := ical.MigrateFeedJson(app) - - if err != nil { - slog.Error("Failed to migrate feeds: %v", err) - return c.JSON(http.StatusInternalServerError, "Failed to migrate feeds") - } else { - return c.JSON(http.StatusOK, "Migrated") - } - }, - Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), - apis.RequireAdminAuth(), - }, - }) - if err != nil { - return err - } - return nil - }) } diff --git a/backend/service/addSchedule.go b/backend/service/addSchedule.go index 444429e..3c38153 100644 --- a/backend/service/addSchedule.go +++ b/backend/service/addSchedule.go @@ -23,6 +23,7 @@ import ( "htwkalender/service/course" "htwkalender/service/feed" "htwkalender/service/fetch/sport" + v1 "htwkalender/service/fetch/v1" v2 "htwkalender/service/fetch/v2" "htwkalender/service/functions/time" "log/slog" @@ -34,10 +35,21 @@ func AddSchedules(app *pocketbase.PocketBase) { app.OnBeforeServe().Add(func(e *core.ServeEvent) error { scheduler := cron.New() - // Every hour update all courses (5 segments - minute, hour, day, month, weekday) "0 * * * *" - // Every three hours update all courses (5 segments - minute, hour, day, month, weekday) "0 */3 * * *" - // Every 10 minutes update all courses (5 segments - minute, hour, day, month, weekday) "*/10 * * * *" - scheduler.MustAdd("updateCourse", "0 */3 * * *", func() { + // !! IMPORTANT !! CRON is based on UTC time zone so in Germany it is UTC+2 in summer and UTC+1 in winter + + // Every sunday at 10pm update all courses (5 segments - minute, hour, day, month, weekday) "0 22 * * 0" + scheduler.MustAdd("updateCourses", "0 22 * * 0", func() { + slog.Info("Started updating courses schedule") + groups, err := v1.FetchSeminarGroups(app) + if err != nil { + slog.Warn("Failed to fetch seminar groups: %v", err) + } + slog.Info("Successfully fetched " + strconv.FormatInt(int64(len(groups)), 10) + " seminar groups") + }) + + // Every day at 5am and 5pm update all courses (5 segments - minute, hour, day, month, weekday) "0 5,17 * * *" + // In Germany it is 7am and 7pm, syllabus gets updated twice a day at German 5:00 Uhr and 17:00 Uhr + scheduler.MustAdd("updateEventsByCourse", "0 5,17 * * *", func() { slog.Info("Started updating courses schedule") course.UpdateCourse(app) }) @@ -60,7 +72,7 @@ func AddSchedules(app *pocketbase.PocketBase) { }) //fetch all events for semester and delete from remote this should be done every sunday at 2am - scheduler.MustAdd("fetchEvents", "0 2 * * 0", func() { + scheduler.MustAdd("fetchEvents", "0 22 * * 6", func() { savedEvents, err := v2.FetchAllEventsAndSave(app, time.RealClock{}) if err != nil { slog.Error("Failed to fetch and save events: %v", err) diff --git a/backend/service/events/eventService_test.go b/backend/service/events/eventService_test.go new file mode 100644 index 0000000..6c5c23e --- /dev/null +++ b/backend/service/events/eventService_test.go @@ -0,0 +1,58 @@ +package events + +import ( + "htwkalender/model" + "testing" +) + +func TestContainsEvent(t *testing.T) { + type args struct { + events model.Events + event model.Event + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "contains event", + args: args{ + events: model.Events{ + { + UUID: "934807509832475", + Name: "name", + }, + }, + event: model.Event{ + UUID: "934807509832475", + Name: "name", + }, + }, + want: true, + }, + { + name: "contains no event", + args: args{ + events: model.Events{ + { + UUID: "9991929292921912343534", + Name: "Name1", + }, + }, + event: model.Event{ + UUID: "1111112312312312", + Name: "Name2", + }, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := ContainsEvent(tt.args.events, tt.args.event); got != tt.want { + t.Errorf("ContainsEvent() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/backend/service/fetch/sport/sportFetcher.go b/backend/service/fetch/sport/sportFetcher.go index f17f41c..583815c 100644 --- a/backend/service/fetch/sport/sportFetcher.go +++ b/backend/service/fetch/sport/sportFetcher.go @@ -24,6 +24,7 @@ import ( "htwkalender/model" "htwkalender/service/db" "htwkalender/service/functions" + clock "htwkalender/service/functions/time" "io" "log/slog" "net/http" @@ -81,7 +82,7 @@ func FetchAndUpdateSportEvents(app *pocketbase.PocketBase) ([]model.Event, error } // @TODO: delete and save events in one transaction and it only should delete events that are not in the new events list and save events that are not in the database - err = db.DeleteAllEventsByCourse(app, "Sport", functions.GetCurrentSemesterString()) + err = db.DeleteAllEventsByCourse(app, "Sport", functions.GetCurrentSemesterString(clock.RealClock{})) if err != nil { return nil, err } diff --git a/backend/service/fetch/v1/fetchSeminarGroupService.go b/backend/service/fetch/v1/fetchSeminarGroupService.go index 45abf67..7809ec9 100644 --- a/backend/service/fetch/v1/fetchSeminarGroupService.go +++ b/backend/service/fetch/v1/fetchSeminarGroupService.go @@ -23,6 +23,8 @@ import ( "github.com/pocketbase/pocketbase/models" "htwkalender/model" "htwkalender/service/db" + "htwkalender/service/functions" + "htwkalender/service/functions/time" "io" "log/slog" "net/http" @@ -59,23 +61,19 @@ func getSeminarHTML(semester string) (string, error) { func FetchSeminarGroups(app *pocketbase.PocketBase) ([]*models.Record, error) { var groups []model.SeminarGroup - resultSummer, err := getSeminarHTML("ss") + semesterString := functions.CalculateSemesterList(time.RealClock{}) + var results [2]string + var err error - if err != nil { - slog.Error("Error while fetching seminar groups for winter semester", err) - return nil, err + for i, semester := range semesterString { + results[i], err = getSeminarHTML(semester) + if err != nil { + slog.Error("Error while fetching seminar groups for: "+semester, err) + return nil, err + } + groups = append(groups, parseSeminarGroups(results[i], semester)...) } - resultWinter, _ := getSeminarHTML("ws") - - if err != nil { - slog.Error("Error while fetching seminar groups for summer semester", err) - return nil, err - } - - groups = parseSeminarGroups(resultSummer, "ss") - groups = append(groups, parseSeminarGroups(resultWinter, "ws")...) - // filter duplicates groups = removeDuplicates(groups) diff --git a/backend/service/fetch/v2/fetcher.go b/backend/service/fetch/v2/fetcher.go index 57a9aef..34dd2ad 100644 --- a/backend/service/fetch/v2/fetcher.go +++ b/backend/service/fetch/v2/fetcher.go @@ -25,10 +25,10 @@ import ( "htwkalender/service/db" "htwkalender/service/fetch" v1 "htwkalender/service/fetch/v1" + "htwkalender/service/functions" localTime "htwkalender/service/functions/time" "log/slog" "strings" - "time" ) func ParseEventsFromRemote(app *pocketbase.PocketBase) (model.Events, error) { @@ -70,7 +70,7 @@ func FetchAllEventsAndSave(app *pocketbase.PocketBase, clock localTime.Clock) ([ } // Fetch and save events for all semesters - for _, semester := range calculateSemesterList(clock) { + for _, semester := range functions.CalculateSemesterList(clock) { events, fetchErr := fetchAndSaveAllEventsForSemester(app, semester, stubUrl) if fetchErr != nil { return nil, fmt.Errorf("failed to fetch and save events for "+semester+": %w", err) @@ -104,25 +104,6 @@ func fetchAndSaveAllEventsForSemester( return savedRecords, err } -func calculateSemesterList(clock localTime.Clock) []string { - summerSemester := clock.Now().Month() >= time.March && clock.Now().Month() <= time.September - winterSemester := clock.Now().Month() <= time.March || clock.Now().Month() >= time.September - - if summerSemester && winterSemester { - return []string{"ss", "ws"} - } - - if summerSemester { - return []string{"ss"} - } - - if winterSemester { - return []string{"ws"} - } - - return []string{"ss", "ws"} -} - func parseEventForOneSemester(url string) ([]model.Event, error) { // Fetch Webpage from URL webpage, err := fetch.GetHTML(url) diff --git a/backend/service/fetch/v2/fetcher_test.go b/backend/service/fetch/v2/fetcher_test.go index 2223549..9b2dec1 100644 --- a/backend/service/fetch/v2/fetcher_test.go +++ b/backend/service/fetch/v2/fetcher_test.go @@ -18,10 +18,8 @@ package v2 import ( "htwkalender/model" - mockTime "htwkalender/service/functions/time" "reflect" "testing" - "time" ) func Test_switchNameAndNotesForExam(t *testing.T) { @@ -99,49 +97,3 @@ func Test_switchNameAndNotesForExam(t *testing.T) { }) } } - -func Test_calculateSemesterList(t *testing.T) { - type args struct { - clock mockTime.Clock - } - tests := []struct { - name string - args args - want []string - }{ - { - name: "is summer semester", - args: args{ - clock: mockTime.MockClock{ - NowTime: time.Date(2024, 6, 1, 0, 0, 0, 0, time.UTC), - }, - }, - want: []string{"ss"}, - }, - { - name: "is winter semester", - args: args{ - clock: mockTime.MockClock{ - NowTime: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC), - }, - }, - want: []string{"ws"}, - }, - { - name: "is in both", - args: args{ - clock: mockTime.MockClock{ - NowTime: time.Date(2024, 3, 22, 0, 0, 0, 0, time.UTC), - }, - }, - want: []string{"ss", "ws"}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := calculateSemesterList(tt.args.clock); !reflect.DeepEqual(got, tt.want) { - t.Errorf("calculateSemesterList() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/backend/service/functions/semester.go b/backend/service/functions/semester.go index b2f3b6a..2ac4ea6 100644 --- a/backend/service/functions/semester.go +++ b/backend/service/functions/semester.go @@ -16,15 +16,32 @@ package functions -import "time" +import ( + localTime "htwkalender/service/functions/time" + "time" +) // GetCurrentSemesterString returns the current semester as string // if current month is between 10 and 03 -> winter semester "ws" -func GetCurrentSemesterString() string { - - if time.Now().Month() >= 10 || time.Now().Month() <= 3 { +func GetCurrentSemesterString(localeTime localTime.Clock) string { + if localeTime.Now().Month() >= 10 || localeTime.Now().Month() <= 3 { return "ws" } else { return "ss" } } + +func CalculateSemesterList(clock localTime.Clock) []string { + summerSemester := clock.Now().Month() >= time.March && clock.Now().Month() <= time.September + winterSemester := clock.Now().Month() <= time.March || clock.Now().Month() >= time.September + + if summerSemester && !winterSemester { + return []string{"ss"} + } + + if !summerSemester && winterSemester { + return []string{"ws"} + } + + return []string{"ss", "ws"} +} diff --git a/backend/service/functions/semester_test.go b/backend/service/functions/semester_test.go new file mode 100644 index 0000000..eb71898 --- /dev/null +++ b/backend/service/functions/semester_test.go @@ -0,0 +1,91 @@ +package functions + +import ( + mockTime "htwkalender/service/functions/time" + "reflect" + "testing" + "time" +) + +func Test_calculateSemesterList(t *testing.T) { + type args struct { + clock mockTime.Clock + } + tests := []struct { + name string + args args + want []string + }{ + { + name: "is summer semester", + args: args{ + clock: mockTime.MockClock{ + NowTime: time.Date(2024, 6, 1, 0, 0, 0, 0, time.UTC), + }, + }, + want: []string{"ss"}, + }, + { + name: "is winter semester", + args: args{ + clock: mockTime.MockClock{ + NowTime: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + want: []string{"ws"}, + }, + { + name: "is in both", + args: args{ + clock: mockTime.MockClock{ + NowTime: time.Date(2024, 3, 22, 0, 0, 0, 0, time.UTC), + }, + }, + want: []string{"ss", "ws"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := CalculateSemesterList(tt.args.clock); !reflect.DeepEqual(got, tt.want) { + t.Errorf("calculateSemesterList() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetCurrentSemesterString(t *testing.T) { + type args struct { + localeTime mockTime.Clock + } + tests := []struct { + name string + args args + want string + }{ + { + name: "is winter semester", + args: args{ + localeTime: mockTime.MockClock{ + NowTime: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC), + }, + }, + want: "ws", + }, + { + name: "is summer semester", + args: args{ + localeTime: mockTime.MockClock{ + NowTime: time.Date(2024, 6, 1, 0, 0, 0, 0, time.UTC), + }, + }, + want: "ss", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := GetCurrentSemesterString(tt.args.localeTime); got != tt.want { + t.Errorf("GetCurrentSemesterString() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/backend/service/functions/string.go b/backend/service/functions/string.go index a0a74c0..77984a4 100644 --- a/backend/service/functions/string.go +++ b/backend/service/functions/string.go @@ -48,13 +48,6 @@ func Contains(s []string, e string) bool { return false } -func ReplaceEmptyString(word string, replacement string) string { - if OnlyWhitespace(word) { - return replacement - } - return word -} - func HashString(s string) string { hash := sha256.New() hash.Write([]byte(s)) diff --git a/backend/service/functions/string_test.go b/backend/service/functions/string_test.go index 7075f0a..ee8316a 100644 --- a/backend/service/functions/string_test.go +++ b/backend/service/functions/string_test.go @@ -17,6 +17,7 @@ package functions import ( + "reflect" "testing" ) @@ -96,3 +97,49 @@ func TestIsSeparator(t *testing.T) { }) } } + +func TestContains(t *testing.T) { + type args struct { + s []string + e string + } + tests := []struct { + name string + args args + want bool + }{ + {"empty slice", args{[]string{}, "a"}, false}, + {"slice with one element equal", args{[]string{"a"}, "a"}, true}, + {"slice with one element different", args{[]string{"a"}, "b"}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := Contains(tt.args.s, tt.args.e); got != tt.want { + t.Errorf("Contains() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestSeperateRoomString(t *testing.T) { + type args struct { + rooms string + } + tests := []struct { + name string + args args + want []string + }{ + {"empty string", args{""}, []string{}}, + {"one room", args{"a"}, []string{"a"}}, + {"two rooms", args{"a,b"}, []string{"a", "b"}}, + {"two rooms with whitespace", args{"a, b"}, []string{"a", "b"}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := SeperateRoomString(tt.args.rooms); !reflect.DeepEqual(got, tt.want) { + t.Errorf("SeperateRoomString() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/backend/service/ical/icalJsonMigrate.go b/backend/service/ical/icalJsonMigrate.go deleted file mode 100644 index 328f6ae..0000000 --- a/backend/service/ical/icalJsonMigrate.go +++ /dev/null @@ -1,74 +0,0 @@ -//Calendar implementation for the HTWK Leipzig timetable. Evaluation and display of the individual dates in iCal format. -//Copyright (C) 2024 HTWKalender support@htwkalender.de - -//This program is free software: you can redistribute it and/or modify -//it under the terms of the GNU Affero General Public License as published by -//the Free Software Foundation, either version 3 of the License, or -//(at your option) any later version. - -//This program is distributed in the hope that it will be useful, -//but WITHOUT ANY WARRANTY; without even the implied warranty of -//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -//GNU Affero General Public License for more details. - -//You should have received a copy of the GNU Affero General Public License -//along with this program. If not, see . - -package ical - -import ( - "encoding/json" - "github.com/pocketbase/dbx" - "github.com/pocketbase/pocketbase" - "htwkalender/model" -) - -//update ical feed json -//add uuid field -//remove module name field - -func MigrateFeedJson(app *pocketbase.PocketBase) error { - - records, err := app.Dao().FindRecordsByFilter("feeds", "1=1", "-created", 0, 0) - if err != nil { - return err - } - - for _, feed := range records { - - var modules []model.FeedCollection - - err := json.Unmarshal([]byte(feed.GetString("modules")), &modules) - if err != nil { - return err - } - - var uuidFeedCollections []model.FeedCollection - - for _, module := range modules { - uuid := searchUUIDForModule(app, module) - - if uuid != "" { - uuidFeedCollections = append(uuidFeedCollections, model.FeedCollection{UUID: uuid, Name: module.Name, Course: module.Course, UserDefinedName: module.UserDefinedName}) - } - } - - jsonModules, _ := json.Marshal(uuidFeedCollections) - feed.Set("modules", string(jsonModules)) - - err = app.Dao().SaveRecord(feed) - if err != nil { - return err - } - } - return nil -} - -func searchUUIDForModule(app *pocketbase.PocketBase, module model.FeedCollection) string { - var event model.Event - err := app.Dao().DB().Select("*").From("events").Where(dbx.NewExp("Name = {:name} AND course = {:course}", dbx.Params{"name": module.Name, "course": module.Course})).One(&event) - if err != nil { - return "" - } - return event.UUID -} diff --git a/backend/service/room/roomService.go b/backend/service/room/roomService.go index e8a18c5..fdf9ab9 100644 --- a/backend/service/room/roomService.go +++ b/backend/service/room/roomService.go @@ -74,6 +74,7 @@ func GetFreeRooms(app *pocketbase.PocketBase, from time.Time, to time.Time) ([]s return freeRooms, nil } +// Remove all rooms from the list that have events in the given time range func removeRoomsThatHaveEvents(rooms []string, schedule []model.Event) []string { var freeRooms []string for _, room := range rooms { @@ -84,6 +85,7 @@ func removeRoomsThatHaveEvents(rooms []string, schedule []model.Event) []string return freeRooms } +// Check if a room is in the schedule func isRoomInSchedule(room string, schedule []model.Event) bool { for _, event := range schedule { if event.Course != "Sport" { diff --git a/backend/service/room/roomService_test.go b/backend/service/room/roomService_test.go index 10a6b41..4f0f91f 100644 --- a/backend/service/room/roomService_test.go +++ b/backend/service/room/roomService_test.go @@ -191,6 +191,50 @@ func Test_isRoomInSchedule(t *testing.T) { }, want: false, }, + { + name: "schedule event.Course is sport", + args: args{ + room: "Klettergerüst", + schedule: []model.Event{ + { + UUID: "903784265784639527", + Day: "Montag", + Week: "52", + Start: types.DateTime{}, + End: types.DateTime{}, + Name: "Hampelmann", + EventType: "S", + Prof: "Prof. Dr. Bewegung", + Rooms: "Klettergerüst", + Notes: "A apple a day keeps the doctor away", + Course: "Sport", + }, + }, + }, + want: true, + }, + { + name: "schedule event.Course is sport with different room", + args: args{ + room: "HTWK Sportplatz", + schedule: []model.Event{ + { + UUID: "903784265784639527", + Day: "Montag", + Week: "52", + Start: types.DateTime{}, + End: types.DateTime{}, + Name: "Hampelmann", + EventType: "S", + Prof: "Prof. Dr. Bewegung", + Rooms: "Klettergerüst", + Notes: "A apple a day keeps the doctor away", + Course: "Sport", + }, + }, + }, + want: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/docker-compose.yml b/docker-compose.yml index 7c77c23..5b2ce9b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,8 +23,8 @@ services: context: ./backend target: dev # prod command: "--http=0.0.0.0:8090 --dir=/htwkalender/data/pb_data" - #ports: - # - "8090:8090" + ports: + - "8090:8090" volumes: - pb_data:/htwkalender/data # for production with volume # - ./backend:/htwkalender/data # for development with bind mount from project directory