1
1
import { makePersisted } from "@solid-primitives/storage" ;
2
2
import { type ParentComponent , createResource } from "solid-js" ;
3
3
import { createStore , produce , reconcile } from "solid-js/store" ;
4
+ import { isServer } from "solid-js/web" ;
5
+
6
+ import localforage from "localforage" ;
4
7
5
8
import {
6
9
CourseDataContext ,
@@ -14,6 +17,7 @@ const CourseDataProvider: ParentComponent = (props) => {
14
17
createStore ( structuredClone ( defaultState ) ) ,
15
18
{
16
19
name : "courseRoadStore" ,
20
+ storage : ! isServer ? localforage : undefined ,
17
21
} ,
18
22
) ;
19
23
@@ -179,8 +183,130 @@ const CourseDataProvider: ParentComponent = (props) => {
179
183
} ) ,
180
184
) ;
181
185
} ,
182
- parseGenericCourses : ( ) => { } ,
183
- parseGenericIndex : ( ) => { } ,
186
+ parseGenericCourses : ( ) => {
187
+ setStore (
188
+ "genericCourses" ,
189
+ produce ( ( genericCourses ) => {
190
+ // clears array
191
+ genericCourses . length = 0 ;
192
+
193
+ const girAttributes = {
194
+ PHY1 : [ "Physics 1 GIR" , "p1" ] ,
195
+ PHY2 : [ "Physics 2 GIR" , "p2" ] ,
196
+ CHEM : [ "Chemistry GIR" , "c" ] ,
197
+ BIOL : [ "Biology GIR" , "b" ] ,
198
+ CAL1 : [ "Calculus I GIR" , "m1" ] ,
199
+ CAL2 : [ "Calculus II GIR" , "m2" ] ,
200
+ LAB : [ "Lab GIR" , "l1" ] ,
201
+ REST : [ "REST GIR" , "r" ] ,
202
+ } as const ;
203
+
204
+ const hassAttributes = {
205
+ "HASS-A" : [ "HASS Arts" , "ha" ] ,
206
+ "HASS-S" : [ "HASS Social Sciences" , "hs" ] ,
207
+ "HASS-H" : [ "HASS Humanities" , "hh" ] ,
208
+ "HASS-E" : [ "HASS Elective" , "ht" ] ,
209
+ } as const ;
210
+
211
+ const ciAttributes = {
212
+ "CI-H" : [ "Communication Intensive" , "hc" ] ,
213
+ "CI-HW" : [ "Communication Intensive with Writing" , "hw" ] ,
214
+ } as const ;
215
+
216
+ const baseGeneric = {
217
+ description :
218
+ "Use this generic subject to indicate that you are fulfilling a requirement, but do not yet have a specific subject selected." ,
219
+ total_units : 12 ,
220
+ } as const ;
221
+
222
+ const baseurl =
223
+ "http://student.mit.edu/catalog/search.cgi?search=&style=verbatim&when=*&termleng=4&days_offered=*&start_time=*&duration=*&total_units=*" as const ;
224
+
225
+ for ( const gir in girAttributes ) {
226
+ const offeredGir = actions . getMatchingAttributes (
227
+ gir ,
228
+ undefined ,
229
+ undefined ,
230
+ ) ;
231
+
232
+ genericCourses . push ( {
233
+ ...baseGeneric ,
234
+ ...offeredGir ,
235
+
236
+ gir_attribute : gir as keyof typeof girAttributes ,
237
+ title : `Generic ${ girAttributes [ gir as keyof typeof girAttributes ] [ 0 ] } ` ,
238
+ subject_id : gir ,
239
+ url : `${ baseurl } &cred=${ girAttributes [ gir as keyof typeof girAttributes ] [ 1 ] } &commun_int=*` ,
240
+ } ) ;
241
+ }
242
+
243
+ for ( const hass in hassAttributes ) {
244
+ const offeredHass = actions . getMatchingAttributes (
245
+ undefined ,
246
+ hass ,
247
+ undefined ,
248
+ ) ;
249
+
250
+ genericCourses . push ( {
251
+ ...baseGeneric ,
252
+ ...offeredHass ,
253
+ hass_attribute : hass as keyof typeof hassAttributes ,
254
+ title : `Generic ${ hass } ` ,
255
+ subject_id : hass ,
256
+ url : `${ baseurl } &cred=${ hassAttributes [ hass as keyof typeof hassAttributes ] [ 1 ] } &commun_int=*` ,
257
+ } ) ;
258
+
259
+ const offeredHassCI = actions . getMatchingAttributes (
260
+ undefined ,
261
+ hass ,
262
+ "CI-H" ,
263
+ ) ;
264
+
265
+ genericCourses . push ( {
266
+ ...baseGeneric ,
267
+ ...offeredHassCI ,
268
+ hass_attribute : hass as keyof typeof hassAttributes ,
269
+ communication_requirement : "CI-H" ,
270
+ title : `Generic CI-H ${ hass } ` ,
271
+ subject_id : `CI-H ${ hass } ` ,
272
+ url : `${ baseurl } &cred=${ hassAttributes [ hass as keyof typeof hassAttributes ] [ 1 ] } &commun_int=${ ciAttributes [ "CI-H" ] [ 1 ] } ` ,
273
+ } ) ;
274
+ }
275
+
276
+ for ( const ci in ciAttributes ) {
277
+ const offeredCI = actions . getMatchingAttributes (
278
+ undefined ,
279
+ undefined ,
280
+ ci ,
281
+ ) ;
282
+
283
+ genericCourses . push ( {
284
+ ...baseGeneric ,
285
+ ...offeredCI ,
286
+ communication_requirement : ci as keyof typeof ciAttributes ,
287
+ title : `Generic ${ ci } ` ,
288
+ hass_attribute : "HASS" ,
289
+ subject_id : ci as keyof typeof ciAttributes ,
290
+ url : `${ baseurl } &cred=*&commun_int=${ ciAttributes [ ci as keyof typeof ciAttributes ] [ 1 ] } ` ,
291
+ } ) ;
292
+ }
293
+ } ) ,
294
+ ) ;
295
+ } ,
296
+ parseGenericIndex : ( ) => {
297
+ setStore (
298
+ "genericIndex" ,
299
+ reconcile (
300
+ store . genericCourses . reduce (
301
+ ( obj , item , index ) => {
302
+ obj [ item . subject_id ] = index ;
303
+ return obj ;
304
+ } ,
305
+ { } as Record < string , number > ,
306
+ ) ,
307
+ ) ,
308
+ ) ;
309
+ } ,
184
310
parseSubjectsIndex : ( ) => { } ,
185
311
popClassStack : ( ) => { } ,
186
312
pushClassStack : ( id ) => { } ,
@@ -209,7 +335,9 @@ const CourseDataProvider: ParentComponent = (props) => {
209
335
setActiveRoad : ( activeRoad ) => {
210
336
setStore ( "activeRoad" , activeRoad ) ;
211
337
} ,
212
- setFullSubjectsInfoLoaded : ( isFull ) => { } ,
338
+ setFullSubjectsInfoLoaded : ( isFull ) => {
339
+ setStore ( "fullSubjectsInfoLoaded" , isFull ) ;
340
+ } ,
213
341
setLoggedIn : ( newLoggedIn ) => {
214
342
setStore ( "loggedIn" , newLoggedIn ) ;
215
343
} ,
@@ -243,7 +371,9 @@ const CourseDataProvider: ParentComponent = (props) => {
243
371
} ) ,
244
372
) ;
245
373
} ,
246
- setSubjectsInfo : ( data ) => { } ,
374
+ setSubjectsInfo : ( data ) => {
375
+ setStore ( "subjectsInfo" , reconcile ( data ) ) ;
376
+ } ,
247
377
setCurrentSemester : ( sem ) => {
248
378
setStore ( "currentSemester" , Math . max ( 1 , sem ) ) ;
249
379
} ,
@@ -255,11 +385,34 @@ const CourseDataProvider: ParentComponent = (props) => {
255
385
resetFulfillmentNeeded : ( ) => {
256
386
setStore ( "fulfillmentNeeded" , "all" ) ;
257
387
} ,
258
- setLoadSubjectsPromise : ( promise ) => { } ,
259
- setSubjectsLoaded : ( ) => { } ,
388
+ setLoadSubjectsPromise : ( promise ) => {
389
+ setStore ( "loadSubjectsPromise" , promise ) ;
390
+ } ,
391
+ setSubjectsLoaded : ( ) => {
392
+ setStore ( "subjectsLoaded" , true ) ;
393
+ } ,
260
394
queueRoadMigration : ( roadID ) => { } ,
261
- clearMigrationQueue : ( ) => { } ,
262
- loadSubjects : async ( ) => { } ,
395
+ clearMigrationQueue : ( ) => {
396
+ setStore ( "roadsToMigrate" , reconcile ( [ ] ) ) ;
397
+ } ,
398
+ loadAllSubjects : async ( ) => {
399
+ const promise = fetch (
400
+ `${ import . meta. env . VITE_FIREROAD_URL } /courses/all?full=true` ,
401
+ ) . then ( ( response ) => response . json ( ) as Promise < SubjectFull [ ] > ) ;
402
+
403
+ actions . setLoadSubjectsPromise ( promise ) ;
404
+ const response = await promise ;
405
+ actions . setSubjectsLoaded ( ) ;
406
+ actions . setSubjectsInfo ( response ) ;
407
+ actions . setFullSubjectsInfoLoaded ( true ) ;
408
+ actions . parseGenericCourses ( ) ;
409
+ actions . parseGenericIndex ( ) ;
410
+ actions . parseSubjectsIndex ( ) ;
411
+ for ( const roadID of store . roadsToMigrate ) {
412
+ actions . migrateOldSubjects ( roadID ) ;
413
+ }
414
+ actions . clearMigrationQueue ( ) ;
415
+ } ,
263
416
addAtPlaceholder : ( index ) => { } ,
264
417
waitLoadSubjects : async ( ) => { } ,
265
418
waitAndMigrateOldSubjects : ( roadID ) => { } ,
0 commit comments