-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
181 lines (143 loc) · 5.54 KB
/
Copy pathapp.py
File metadata and controls
181 lines (143 loc) · 5.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from controller import course_search
import os
import uvicorn
app = FastAPI()
# Mount static files
app.mount("/static", StaticFiles(directory="static"), name="static")
# Templates
templates = Jinja2Templates(directory="templates")
courses_controller = course_search(courses_data_path='data/rutgers_courses.json')
your_location = None
college_distances = None
@app.get("/health")
async def health_check():
"""Health check endpoint for monitoring and load balancers."""
return {"status": "healthy", "message": "Rutgers Course Finder is running"}
@app.get("/", response_class=HTMLResponse)
async def search_page(request: Request):
return templates.TemplateResponse("main.html", {"request": request})
@app.post("/save_location")
async def save_location(request: Request):
"""
Save user's current location.
Expects JSON payload with latitude and longitude.
Updates global your_location variable.
Returns:
JSON response with location status and coordinates
"""
data = await request.json()
latitude = data.get('latitude')
longitude = data.get('longitude')
global your_location
your_location = (latitude, longitude)
global college_distances
college_distances = await courses_controller.get_all_college_distances(your_location)
return {
'status': 'success',
'latitude': latitude,
'longitude': longitude
}
@app.post("/search_by_title")
async def search_by_title(request: Request):
"""
Handles search requests for courses by title.
This function processes a POST request containing a JSON payload with a 'searchTerm' field.
It validates the request, checks if a location is set, and then calls the courses_controller
to search for courses by title. The results are then returned as a JSON response.
Returns:
JSON response containing the search status, search term, and a list of course results.
"""
if not courses_controller:
return {
'status': 'error',
'message': 'Search functionality is disabled. Please check API keys in .env file.'
}
try:
data = await request.json()
search_term = data.get('searchTerm')
# Input validation
if not search_term:
return {'status': 'error', 'message': 'Search term is required'}
# Gets the top courses, along with their course info(title, course_string, instructors, prerequisites, equivalencies)
# that most closely macthes the title the user search
# Pass college_distances (which may be None if location not set)
results = await courses_controller.search_by_title(search_term, college_distances)
if not results:
return {
'status': 'success',
'message': 'No results found',
'results': []
}
return {
'status': 'success',
'searchTerm': search_term,
'courses': results
}
except Exception as e:
return {
'status': 'error',
'message': f'An error occurred: {str(e)}'
}
@app.post("/search_by_code")
async def search_by_code(request: Request):
"""
Handles search requests for courses by last 3 digits of course code.
Expects a POST request with JSON payload containing last 3 digits of course code'.
Uses the user's saved location to find nearby course equivalencies.
Returns:
JSON response with matching courses and their details
"""
try:
data = await request.json()
search_term = data.get('searchTerm', '')
if not search_term:
return {'status': 'error', 'message': 'Course code is required'}
# returns all courses and their course info that ends with the 3 digits the user specifies
# Pass college_distances (which may be None if location not set)
results = await courses_controller.search_by_code(search_term, college_distances)
if not results:
return {
'status': 'success',
'message': 'No results found',
'courses': []
}
return {
'status': 'success',
'courseCode': search_term,
'courses': results
}
except Exception as e:
return {
'status': 'error',
'message': f'An error occurred: {str(e)}'
}
@app.post("/search_by_professor")
async def search_by_professor(request: Request):
"""
Handles search requests for courses by professor's last name.
Expects a POST request with JSON payload containing 'searchTerm'.
Returns a list of professors and their courses, or suggestions.
"""
try:
data = await request.json()
search_term = data.get('searchTerm')
if not search_term:
return {'status': 'error', 'message': 'Search term is required'}
results = courses_controller.search_by_professor(search_term)
return {
'status': 'success',
'searchTerm': search_term,
'results': results
}
except Exception as e:
return {
'status': 'error',
'message': f'An error occurred: {str(e)}'
}
if __name__ == '__main__':
port = int(os.environ.get("PORT", 5005))
uvicorn.run(app, host="0.0.0.0", port=port)