1+ package parser
2+
3+ import (
4+ "encoding/json"
5+ "fmt"
6+ "log"
7+ "os"
8+ "regexp"
9+ "slices"
10+ "strings"
11+
12+ "github.com/UTDNebula/api-tools/utils"
13+ "github.com/UTDNebula/nebula-api/api/schema"
14+ )
15+
16+ // Some events have only the building name, not the abbreviation
17+ // Maps building names to their abbreviations
18+ var buildingAbbreviations = map [string ]string {
19+ "Activity Center" : "AB" ,
20+ "Activity Center Bookstore" : "ACB" ,
21+ "Administration" : "AD" ,
22+ "Edith and Peter O’Donnell Jr. Athenaeum" : "APC" ,
23+ "Edith O'Donnell Arts and Technology Building" : "ATC" ,
24+ "Lloyd V. Berkner Hall" : "BE" ,
25+ "Bioengineering and Sciences Building" : "BSB" ,
26+ "Classroom Building" : "CB" ,
27+ "Callier Center Richardson" : "CR" ,
28+ "Callier Center Addition" : "CRA" ,
29+ "Davidson-Gundy Alumni Center" : "DGA" ,
30+ "Dining Hall West" : "DHW" ,
31+ "Engineering and Computer Science North" : "ECSN" ,
32+ "Engineering and Computer Science South" : "ECSS" ,
33+ "Engineering and Computer Science West" : "ECSW" ,
34+ "Energy Plant" : "EP" ,
35+ "Founders Annex" : "FA" ,
36+ "Facilities Management" : "FM" ,
37+ "Founders North" : "FN" ,
38+ "Founders Building" : "FO" ,
39+ "Cecil H. Green Hall" : "GR" ,
40+ "Karl Hoblitzelle Hall" : "HH" ,
41+ "Erik Jonsson Academic Center" : "JO" ,
42+ "Naveen Jindal School of Management" : "JSOM" ,
43+ "Eugene McDermott Library" : "MC" ,
44+ "Modular Lab 1" : "ML1" ,
45+ "Modular Lab 2" : "ML2" ,
46+ "North Office Building" : "NB" ,
47+ "North Lab" : "NL" ,
48+ "Police" : "PD" ,
49+ "Physics Annex" : "PHA" ,
50+ "Physics Building" : "PHY" ,
51+ "Natural Science and Engineering Research Lab" : "RL" ,
52+ "Research and Operations Center" : "ROC" ,
53+ "Research and Operations Center West" : "ROW" ,
54+ "Service Building" : "SB" ,
55+ "Sciences Building" : "SCI" ,
56+ "Safety and Grounds" : "SG" ,
57+ "Student Learning Center" : "SLC" ,
58+ "Student Services Building Addition" : "SSA" ,
59+ "Student Services Building" : "SSB" ,
60+ "Student Union" : "SU" ,
61+ "Student Union Food Court" : "SUFC" ,
62+ "Synergy Park North" : "SPN" ,
63+ "Synergy Park North 2" : "SP2" ,
64+ "University Theatre" : "TH" ,
65+ "Visitor Center" : "VC" ,
66+ "Waterview Science and Technology Center" : "WSTC" ,
67+ "Andromeda Hall & University Housing Office" : "RHA" ,
68+ "Capella Hall" : "RHC" ,
69+ "Helix Hall" : "RHH" ,
70+ "Sirius Hall" : "RHS" ,
71+ "Vega Hall" : "RHV" ,
72+ "Recreation Center West" : "RCW" ,
73+ "SP/N Gallery" : "SP2" ,
74+ }
75+
76+ // Valid building abreviations for checking
77+ var validAbbreviations []string = []string {
78+ "AB" ,
79+ "ACB" ,
80+ "AD" ,
81+ "APC" ,
82+ "ATC" ,
83+ "BE" ,
84+ "BSB" ,
85+ "CB" ,
86+ "CR" ,
87+ "CRA" ,
88+ "DGA" ,
89+ "DHW" ,
90+ "ECSN" ,
91+ "ECSS" ,
92+ "ECSW" ,
93+ "EP" ,
94+ "FA" ,
95+ "FM" ,
96+ "FN" ,
97+ "FO" ,
98+ "GR" ,
99+ "HH" ,
100+ "JO" ,
101+ "JSOM" ,
102+ "MC" ,
103+ "ML1" ,
104+ "ML2" ,
105+ "NB" ,
106+ "NL" ,
107+ "PD" ,
108+ "PHA" ,
109+ "PHY" ,
110+ "RL" ,
111+ "ROC" ,
112+ "ROW" ,
113+ "SB" ,
114+ "SCI" ,
115+ "SG" ,
116+ "SLC" ,
117+ "SSA" ,
118+ "SSB" ,
119+ "SU" ,
120+ "SUFC" ,
121+ "SPN" ,
122+ "SP2" ,
123+ "TH" ,
124+ "VC" ,
125+ "WSTC" ,
126+ "RHA" ,
127+ "RHC" ,
128+ "RHH" ,
129+ "RHS" ,
130+ "RHV" ,
131+ "RCW" ,
132+ }
133+
134+ func ParseCalendar (inDir string , outDir string ) {
135+
136+ calendarFile , err := os .ReadFile (inDir + "/eventScraped.json" )
137+ if err != nil {
138+ panic (err )
139+ }
140+
141+ var allEvents []schema.Event
142+
143+ err = json .Unmarshal (calendarFile , & allEvents )
144+ if err != nil {
145+ panic (err )
146+ }
147+
148+ multiBuildingMap := make (map [string ]map [string ]map [string ][]schema.Event )
149+
150+ for _ , event := range (allEvents ) {
151+
152+ // Get date
153+ dateTime := event .StartTime
154+ dateTimeString := dateTime .String ()
155+ date := dateTimeString [:10 ]
156+
157+ // Get building and room
158+ location := utils.ConvertFromInterface [string ](event .Location )
159+
160+ // Regexp to match building abbreviations and room numbers
161+ buildingRegexp := regexp .MustCompile (`[A-Z]{2,4}` )
162+ roomRegexp := regexp .MustCompile (`([0-9]{1,2}\.[0-9]{3})([A-Z])?` )
163+
164+ building := buildingRegexp .FindString (* location )
165+ room := roomRegexp .FindString (* location )
166+
167+ // buildingRegexp might capture something that isn't a valid building abbreviation (e.g., UTD)
168+ isValidBuilding := slices .Contains (validAbbreviations , building )
169+
170+ // If location doesn't have building abbreviation or buildingRegexp captured an invalid abbreviation,
171+ // check for the full building name
172+ lowercaseLocation := strings .ToLower (* location )
173+ if building == "" || ! isValidBuilding {
174+ for key := range buildingAbbreviations {
175+ if strings .Contains (lowercaseLocation , strings .ToLower (key )) {
176+ building = buildingAbbreviations [key ]
177+ isValidBuilding = true
178+ }
179+ }
180+ }
181+
182+ // If location doesn't have room number, check to see if location included a room
183+ if room == "" && isValidBuilding {
184+ locationParts := strings .SplitN (* location , "," , 2 )
185+ if len (locationParts ) == 2 {
186+ room = locationParts [1 ]
187+ }
188+ }
189+
190+ // If building is still empty string, then location was initally an empty string
191+ // or location was a place off campus
192+ if building == "" {
193+ building = "Other"
194+ }
195+
196+ // If room is still empty string, then location was initally an empty string, or
197+ // location did not include a room, or location was a place off campus
198+ if room == "" {
199+ room = "Other"
200+ }
201+
202+ if _ , exists := multiBuildingMap [date ]; ! exists {
203+ multiBuildingMap [date ] = make (map [string ]map [string ][]schema.Event )
204+ }
205+
206+ if _ , exists := multiBuildingMap [date ][building ]; ! exists {
207+ multiBuildingMap [date ][building ] = make (map [string ][]schema.Event )
208+ }
209+
210+ multiBuildingMap [date ][building ][room ] = append (multiBuildingMap [date ][building ][room ], event )
211+ }
212+
213+ var result []schema.MultiBuildingEvents [schema.Event ]
214+
215+ for date , buildings := range multiBuildingMap {
216+ var singleBuildings []schema.SingleBuildingEvents [schema.Event ]
217+ for building , rooms := range buildings {
218+ var roomEvents []schema.RoomEvents [schema.Event ]
219+ for room , events := range rooms {
220+ roomEvents = append (roomEvents , schema.RoomEvents [schema.Event ]{
221+ Room : room ,
222+ Events : events ,
223+ })
224+ }
225+
226+ singleBuildings = append (singleBuildings , schema.SingleBuildingEvents [schema.Event ]{
227+ Building : building ,
228+ Rooms : roomEvents ,
229+ })
230+ }
231+
232+ result = append (result , schema.MultiBuildingEvents [schema.Event ]{
233+ Date : date ,
234+ Buildings : singleBuildings ,
235+ })
236+ }
237+
238+ log .Print ("Parsed Calendar!" )
239+
240+ utils .WriteJSON (fmt .Sprintf ("%s/events.json" , outDir ), result )
241+ }
0 commit comments