Skip to content

Commit 2b62ac9

Browse files
committed
Merge from the develop
2 parents ea5a923 + 3179653 commit 2b62ac9

File tree

8 files changed

+413
-18
lines changed

8 files changed

+413
-18
lines changed

api/controllers/astra.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package controllers
22

33
import (
44
"context"
5+
"errors"
56
"net/http"
67
"time"
78

@@ -31,14 +32,19 @@ func AstraEvents(c *gin.Context) {
3132

3233
date := c.Param("date")
3334

34-
var astra_events schema.MultiBuildingEvents[schema.AstraEvent]
35+
var astraEvents schema.MultiBuildingEvents[schema.AstraEvent]
3536

3637
// Find astra event given date
37-
err := astraCollection.FindOne(ctx, bson.M{"date": date}).Decode(&astra_events)
38+
err := astraCollection.FindOne(ctx, bson.M{"date": date}).Decode(&astraEvents)
3839
if err != nil {
39-
respondWithInternalError(c, err)
40-
return
40+
if errors.Is(err, mongo.ErrNoDocuments) {
41+
astraEvents.Date = date
42+
astraEvents.Buildings = []schema.SingleBuildingEvents[schema.AstraEvent]{}
43+
} else {
44+
respondWithInternalError(c, err)
45+
return
46+
}
4147
}
4248

43-
respond(c, http.StatusOK, "success", astra_events)
49+
respond(c, http.StatusOK, "success", astraEvents)
4450
}

api/controllers/events.go

Lines changed: 160 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package controllers
22

33
import (
44
"context"
5+
"errors"
56
"net/http"
67
"time"
78

@@ -12,6 +13,7 @@ import (
1213
"github.com/gin-gonic/gin"
1314

1415
"go.mongodb.org/mongo-driver/bson"
16+
"go.mongodb.org/mongo-driver/bson/primitive"
1517
"go.mongodb.org/mongo-driver/mongo"
1618
)
1719

@@ -37,10 +39,14 @@ func Events(c *gin.Context) {
3739
// find and parse matching date
3840
err := eventsCollection.FindOne(ctx, bson.M{"date": date}).Decode(&events)
3941
if err != nil {
40-
respondWithInternalError(c, err)
41-
return
42+
if errors.Is(err, mongo.ErrNoDocuments) {
43+
events.Date = date
44+
events.Buildings = []schema.SingleBuildingEvents[schema.SectionWithTime]{}
45+
} else {
46+
respondWithInternalError(c, err)
47+
return
48+
}
4249
}
43-
4450
respond(c, http.StatusOK, "success", events)
4551
}
4652

@@ -68,8 +74,13 @@ func EventsByBuilding(c *gin.Context) {
6874
// find and parse matching date
6975
err := eventsCollection.FindOne(ctx, bson.M{"date": date}).Decode(&events)
7076
if err != nil {
71-
respondWithInternalError(c, err)
72-
return
77+
if errors.Is(err, mongo.ErrNoDocuments) {
78+
events.Date = date
79+
events.Buildings = []schema.SingleBuildingEvents[schema.SectionWithTime]{}
80+
} else {
81+
respondWithInternalError(c, err)
82+
return
83+
}
7384
}
7485

7586
// filter for the specified building
@@ -92,3 +103,147 @@ func EventsByBuilding(c *gin.Context) {
92103

93104
respond(c, http.StatusOK, "success", eventsByBuilding)
94105
}
106+
107+
// @Id eventsByRoom
108+
// @Router /events/{date}/{building}/{room} [get]
109+
// @Tags Events
110+
// @Description "Returns all sections with meetings on the specified date in the specified building and room"
111+
// @Produce json
112+
// @Param date path string true "ISO date of the set of events to get"
113+
// @Param building path string true "building abbreviation of the event location"
114+
// @Param room path string true "room number"
115+
// @Success 200 {object} schema.APIResponse[[]schema.SectionWithTime] "All sections with meetings on the specified date in the specified building and room"
116+
// @Failure 500 {object} schema.APIResponse[string] "A string describing the error"
117+
// @Failure 404 {object} schema.APIResponse[string] "A string describing the error"
118+
func EventsByRoom(c *gin.Context) {
119+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
120+
defer cancel()
121+
122+
date := c.Param("date")
123+
building := c.Param("building")
124+
room := c.Param("room")
125+
126+
var events schema.MultiBuildingEvents[schema.SectionWithTime]
127+
var foundSections []schema.SectionWithTime
128+
129+
// find and parse matching date
130+
err := eventsCollection.FindOne(ctx, bson.M{"date": date}).Decode(&events)
131+
if err != nil {
132+
if errors.Is(err, mongo.ErrNoDocuments) {
133+
events.Date = date
134+
events.Buildings = []schema.SingleBuildingEvents[schema.SectionWithTime]{}
135+
} else {
136+
respondWithInternalError(c, err)
137+
return
138+
}
139+
}
140+
141+
// filter for the specified building and room
142+
for _, b := range events.Buildings {
143+
if b.Building == building {
144+
for _, r := range b.Rooms {
145+
if r.Room == room {
146+
foundSections = r.Events
147+
break
148+
}
149+
}
150+
break
151+
}
152+
}
153+
154+
if len(foundSections) == 0 {
155+
c.JSON(http.StatusNotFound, schema.APIResponse[string]{
156+
Status: http.StatusNotFound,
157+
Message: "error",
158+
Data: "No events found for the specified building and room",
159+
})
160+
return
161+
}
162+
163+
respond(c, http.StatusOK, "success", foundSections)
164+
}
165+
166+
// @Id sectionsByRoomDetailed
167+
// @Router /events/{date}/{building}/{room}/sections [get]
168+
// @Tags Events
169+
// @Description "Returns full section objects with meetings on the specified date in the specified building and room"
170+
// @Produce json
171+
// @Param date path string true "ISO date of the set of events to get"
172+
// @Param building path string true "building abbreviation of the event location"
173+
// @Param room path string true "room number"
174+
// @Success 200 {object} schema.APIResponse[[]schema.Section] "Full section objects with meetings on the specified date in the specified building and room"
175+
// @Failure 500 {object} schema.APIResponse[string] "A string describing the error"
176+
// @Failure 404 {object} schema.APIResponse[string] "A string describing the error"
177+
func SectionsByRoomDetailed(c *gin.Context) {
178+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
179+
defer cancel()
180+
181+
date := c.Param("date")
182+
building := c.Param("building")
183+
room := c.Param("room")
184+
185+
var events schema.MultiBuildingEvents[schema.SectionWithTime]
186+
187+
// Step 1: Find events for the specified date
188+
err := eventsCollection.FindOne(ctx, bson.M{"date": date}).Decode(&events)
189+
if err != nil {
190+
if errors.Is(err, mongo.ErrNoDocuments) {
191+
events.Date = date
192+
events.Buildings = []schema.SingleBuildingEvents[schema.SectionWithTime]{}
193+
} else {
194+
respondWithInternalError(c, err)
195+
return
196+
}
197+
}
198+
199+
// Step 2: Extract section IDs for the specified building and room
200+
var sectionIDs []primitive.ObjectID
201+
for _, b := range events.Buildings {
202+
if b.Building == building {
203+
for _, r := range b.Rooms {
204+
if r.Room == room {
205+
for _, event := range r.Events {
206+
sectionIDs = append(sectionIDs, event.Section)
207+
}
208+
break
209+
}
210+
}
211+
break
212+
}
213+
}
214+
215+
if len(sectionIDs) == 0 {
216+
c.JSON(http.StatusNotFound, schema.APIResponse[string]{
217+
Status: http.StatusNotFound,
218+
Message: "error",
219+
Data: "No sections found for the specified building and room",
220+
})
221+
return
222+
}
223+
224+
// Step 3: Fetch full section objects from the sections collection
225+
sectionsCollection := configs.GetCollection("sections")
226+
cursor, err := sectionsCollection.Find(ctx, bson.M{"_id": bson.M{"$in": sectionIDs}})
227+
if err != nil {
228+
respondWithInternalError(c, err)
229+
return
230+
}
231+
defer cursor.Close(ctx)
232+
233+
var sections []schema.Section
234+
if err = cursor.All(ctx, &sections); err != nil {
235+
respondWithInternalError(c, err)
236+
return
237+
}
238+
239+
if len(sections) == 0 {
240+
c.JSON(http.StatusNotFound, schema.APIResponse[string]{
241+
Status: http.StatusNotFound,
242+
Message: "error",
243+
Data: "No section details found",
244+
})
245+
return
246+
}
247+
248+
respond(c, http.StatusOK, "success", sections)
249+
}

api/controllers/grades.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -423,9 +423,6 @@ func gradesAggregation(flag string, c *gin.Context) {
423423
// and then we perform the grades aggregation against the sections collection,
424424
// matching on the course_reference and professor
425425

426-
var profIDs []primitive.ObjectID
427-
var courseIDs []primitive.ObjectID
428-
429426
collection = sectionCollection
430427

431428
// Find valid professor ids
@@ -447,6 +444,7 @@ func gradesAggregation(flag string, c *gin.Context) {
447444
return
448445
}
449446

447+
profIDs := make([]primitive.ObjectID, 0, len(results))
450448
for _, prof := range results {
451449
profID := prof["_id"].(primitive.ObjectID)
452450
profIDs = append(profIDs, profID)
@@ -471,6 +469,7 @@ func gradesAggregation(flag string, c *gin.Context) {
471469
return
472470
}
473471

472+
courseIDs := make([]primitive.ObjectID, 0, len(results))
474473
for _, course := range results {
475474
courseID := course["_id"].(primitive.ObjectID)
476475
courseIDs = append(courseIDs, courseID)

api/controllers/mazevo.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package controllers
22

33
import (
44
"context"
5+
"errors"
56
"net/http"
67
"time"
78

@@ -30,14 +31,19 @@ func MazevoEvents(c *gin.Context) {
3031

3132
date := c.Param("date")
3233

33-
var mazevo_events schema.MultiBuildingEvents[schema.MazevoEvent]
34+
var mazevoEvents schema.MultiBuildingEvents[schema.MazevoEvent]
3435

3536
// Find mazevo event for input date
36-
err := mazevoCollection.FindOne(ctx, bson.M{"date": date}).Decode(&mazevo_events)
37+
err := mazevoCollection.FindOne(ctx, bson.M{"date": date}).Decode(&mazevoEvents)
3738
if err != nil {
38-
respondWithInternalError(c, err)
39-
return
39+
if errors.Is(err, mongo.ErrNoDocuments) {
40+
mazevoEvents.Date = date
41+
mazevoEvents.Buildings = []schema.SingleBuildingEvents[schema.MazevoEvent]{}
42+
} else {
43+
respondWithInternalError(c, err)
44+
return
45+
}
4046
}
4147

42-
respond(c, http.StatusOK, "success", mazevo_events)
48+
respond(c, http.StatusOK, "success", mazevoEvents)
4349
}

0 commit comments

Comments
 (0)