Omar Dahleh commited on
Commit
7fc2e0c
·
1 Parent(s): 5b39df4

woooohoooo

Browse files
all_schools_minified.json ADDED
The diff for this file is too large to render. See raw diff
 
en.data.json ADDED
The diff for this file is too large to render. See raw diff
 
minify_schools.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+
3
+ INPUT_PATH = "en.data.json" # Replace with your full file name
4
+ OUTPUT_PATH = "all_schools_minified.json"
5
+
6
+ def extract_minimal_school_data(input_path, output_path):
7
+ with open(input_path, "r", encoding="utf-8") as f:
8
+ try:
9
+ data = json.load(f)
10
+ except json.JSONDecodeError as e:
11
+ print("❌ Failed to parse JSON:", e)
12
+ return
13
+
14
+ # Only keep selected fields
15
+ minified = [
16
+ {
17
+ "id": s.get("id", ""),
18
+ "name": s.get("school", ""),
19
+ "address": s.get("address", "")
20
+ }
21
+ for s in data if isinstance(s, dict)
22
+ ]
23
+
24
+ with open(output_path, "w", encoding="utf-8") as f:
25
+ json.dump(minified, f, ensure_ascii=False, indent=2)
26
+
27
+ print(f"✅ Saved {len(minified)} entries to {output_path}")
28
+
29
+ if __name__ == "__main__":
30
+ extract_minimal_school_data(INPUT_PATH, OUTPUT_PATH)
src/chat.py CHANGED
@@ -413,6 +413,7 @@ Key facts:
413
  if last_results and re.search(r'tell me more about|more information|details (about|on)|what about|where is', user_input, re.IGNORECASE):
414
  # Try to identify which school they're asking about
415
  schools = last_results # Use the retrieved value
 
416
 
417
  # Check for school number references (e.g., "Tell me more about #3")
418
  number_match = re.search(r'#?(\d+)', user_input)
@@ -420,19 +421,117 @@ Key facts:
420
  try:
421
  index = int(number_match.group(1)) - 1
422
  if 0 <= index < len(schools):
423
- school = schools[index]
424
- return f"Here's more information about {school.get('name', 'the school')}:\n\nAddress: {school.get('address', 'Information not available')}\nReferenceID: {school.get('referenceId', 'N/A')}\n\nFor complete details and registration information, please visit https://boston.explore.avela.org/ or contact a BPS Welcome Center at 617-635-9010."
425
  except:
426
  pass
427
 
428
- # Check for school name mentions
429
- for idx, school in enumerate(schools):
430
- school_name = school.get('name', '').lower()
431
- if school_name and school_name in user_input.lower():
432
- return f"Here's more information about {school.get('name', 'the school')}:\n\nAddress: {school.get('address', 'Information not available')}\nReferenceID: {school.get('referenceId', 'N/A')}\n\nFor complete details and registration information, please visit https://boston.explore.avela.org/ or contact a BPS Welcome Center at 617-635-9010."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
433
 
434
  return None
435
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
436
  def search_eligible_schools(self):
437
  """Search for eligible schools using the information we have"""
438
  try:
 
413
  if last_results and re.search(r'tell me more about|more information|details (about|on)|what about|where is', user_input, re.IGNORECASE):
414
  # Try to identify which school they're asking about
415
  schools = last_results # Use the retrieved value
416
+ target_school = None
417
 
418
  # Check for school number references (e.g., "Tell me more about #3")
419
  number_match = re.search(r'#?(\d+)', user_input)
 
421
  try:
422
  index = int(number_match.group(1)) - 1
423
  if 0 <= index < len(schools):
424
+ target_school = schools[index]
 
425
  except:
426
  pass
427
 
428
+ # If we didn't find a school by number, try to find it by name
429
+ if not target_school:
430
+ for school in schools:
431
+ school_name = school.get('name', '').lower()
432
+ if school_name and school_name in user_input.lower():
433
+ target_school = school
434
+ break
435
+
436
+ # If we found a school, get its details from en.data.json
437
+ if target_school:
438
+ school_id = target_school.get('id', '')
439
+ if school_id:
440
+ # Try to get full details from en.data.json
441
+ full_details = self.eligibility_api.get_full_school_details(school_id)
442
+
443
+ # If we got full details, format and return them
444
+ if full_details and isinstance(full_details, dict) and full_details.get('name'):
445
+ return self.format_school_details_response(full_details)
446
+
447
+ # Fallback to basic info if we couldn't get full details
448
+ return f"Here's more information about {target_school.get('name', 'the school')}:\n\nAddress: {target_school.get('address', 'Information not available')}\nReferenceID: {target_school.get('referenceId', 'N/A')}\n\nFor complete details and registration information, please visit https://boston.explore.avela.org/ or contact a BPS Welcome Center at 617-635-9010."
449
 
450
  return None
451
 
452
+ def format_school_details_response(self, school_details):
453
+ """Format a comprehensive school details response using full data from en.data.json"""
454
+ name = school_details.get('name') or school_details.get('school', 'Unknown School')
455
+ address = school_details.get('address', 'Information not available')
456
+
457
+ # Start with basic information
458
+ response = f"Here's detailed information about {name}:\n\n"
459
+ response += f"Address: {address}\n"
460
+
461
+ # Add grade span if available
462
+ if grade_span := school_details.get('grade_span'):
463
+ response += f"Grade Span: {grade_span}\n"
464
+
465
+ # Add phone if available
466
+ if phone := (school_details.get('phone_number') or school_details.get('phone')):
467
+ response += f"Phone: {phone}\n"
468
+
469
+ # Add website if available
470
+ if website := school_details.get('website'):
471
+ response += f"Website: {website}\n"
472
+
473
+ # Add school hours if available
474
+ if hours := (school_details.get('hours_of_operation') or school_details.get('hours')):
475
+ response += f"Hours: {hours}\n"
476
+
477
+ # Add programs/features if available (checking multiple possible fields)
478
+ programs = []
479
+ if special_programs := school_details.get('specialized_education_programs'):
480
+ if special_programs and special_programs.strip():
481
+ programs.append(f"Specialized Education Programs: {special_programs}")
482
+
483
+ if language_text := school_details.get('language_programming_text'):
484
+ if language_text and language_text.strip():
485
+ programs.append(f"Language Programs: {language_text}")
486
+
487
+ if unique_features := school_details.get('unique_features'):
488
+ if isinstance(unique_features, list) and unique_features:
489
+ programs.append("Unique Features: " + ", ".join([f.strip() for f in unique_features if f.strip()]))
490
+ elif isinstance(unique_features, str) and unique_features.strip():
491
+ programs.append(f"Unique Features: {unique_features}")
492
+
493
+ # Add programs if we found any
494
+ if programs:
495
+ response += "\nPrograms & Features:\n"
496
+ for program in programs:
497
+ response += f"- {program}\n"
498
+
499
+ # Add additional amenities section if available
500
+ amenities = []
501
+ if school_details.get('library') == 'Yes':
502
+ amenities.append('Library')
503
+ if school_details.get('music_room') == 'Yes':
504
+ amenities.append('Music Room')
505
+ if school_details.get('gymnasium') == 'Yes':
506
+ amenities.append('Gymnasium')
507
+ if school_details.get('outdoor_classrooms') == 'Yes':
508
+ amenities.append('Outdoor Classroom')
509
+ if school_details.get('science_lab') == 'Yes':
510
+ amenities.append('Science Lab')
511
+ if school_details.get('cafeteria') == 'Yes':
512
+ amenities.append('Cafeteria')
513
+
514
+ if amenities:
515
+ response += f"\nAmenities: {', '.join(amenities)}\n"
516
+
517
+ # Add mission statement if available
518
+ if mission := school_details.get('overview_mission_statement'):
519
+ if mission and len(mission) > 30: # Only include if substantial
520
+ response += f"\nMission Statement: {mission[:200]}{'...' if len(mission) > 200 else ''}\n"
521
+
522
+ # Add before/after school info
523
+ if before := school_details.get('before_school_program'):
524
+ if before and before.strip():
525
+ response += f"\nBefore School Program: {before}\n"
526
+
527
+ if after := school_details.get('after_school_program'):
528
+ if after and after.strip():
529
+ response += f"\nAfter School Program: {after}\n"
530
+
531
+ response += "\nFor complete details and registration information, please visit https://boston.explore.avela.org/ or contact a BPS Welcome Center at 617-635-9010."
532
+
533
+ return response
534
+
535
  def search_eligible_schools(self):
536
  """Search for eligible schools using the information we have"""
537
  try:
src/eligibility_api.py CHANGED
@@ -6,7 +6,9 @@ in Boston based on student details and address information.
6
  """
7
 
8
  import requests
 
9
  from typing import Dict, Any, Optional, List
 
10
 
11
  class EligibilityAPI:
12
  """
@@ -15,23 +17,30 @@ class EligibilityAPI:
15
 
16
  BASE_URL = "https://prod.execute-api.apply.avela.org/eligibility/organizations/boston/formTemplates/2f58f4ce-b462-4028-ae59-7ab874fc1224/findEligibility"
17
 
18
- # Static list of all Boston schools - this would ideally come from a separate API call or database
19
- ALL_SCHOOLS = [
20
- {"id": "4532d8a9-7ef3-4a90-aa4f-3c5149560474", "name": "Madison Park Technical Vocational High School", "referenceId": "1210"},
21
- {"id": "71e955b2-36ea-4e34-848e-63a78ed0688e", "name": "Mission Grammar School", "referenceId": "259028"},
22
- {"id": "7d0ac7b2-c79a-4614-a614-c858e517e1b8", "name": "Murphy K-8 School", "referenceId": "4400"},
23
- {"id": "a35500f2-89da-4e4b-b088-8646cfd2fd5b", "name": "YMCA - Roxbury Tenants of Harvard (RTH)", "referenceId": "187660"},
24
- {"id": "4b084cc6-88e7-4417-8c67-dbb4a9cfaea0", "name": "Fenway High School", "referenceId": "1265"},
25
- {"id": "6ded6119-1572-4941-8c98-d2a19c48f390", "name": "Little Amigos Early Learning Center", "referenceId": "260040"},
26
- {"id": "779dc3b2-8056-4c81-b1bd-d507336435e3", "name": "O'Donnell Elementary School", "referenceId": "4543"},
27
- {"id": "6a3a0f1d-3861-434c-a084-b2b1a8334868", "name": "Bridge to Nature", "referenceId": "187594"},
28
- # Add more schools as they become known
29
- {"id": "school-1", "name": "Boston Arts Academy", "referenceId": "1001"},
30
- {"id": "school-2", "name": "Boston Latin School", "referenceId": "1002"},
31
- {"id": "school-3", "name": "Boston Latin Academy", "referenceId": "1003"},
32
- {"id": "school-4", "name": "John D. O'Bryant School", "referenceId": "1004"},
33
- {"id": "school-5", "name": "Josiah Quincy School", "referenceId": "1005"}
34
- ]
 
 
 
 
 
 
 
35
 
36
  # Grade to UUID mapping
37
  GRADE_TO_UUID = {
@@ -76,15 +85,6 @@ class EligibilityAPI:
76
  "Other": "64351764-04ed-4828-8320-35579deca69b"
77
  }
78
 
79
- def __init__(self):
80
- """Initialize the API client with default headers."""
81
- self.headers = {
82
- "Content-Type": "application/json",
83
- "User-Agent": "Mozilla/5.0",
84
- "Origin": "https://boston.explore.avela.org",
85
- "Referer": "https://boston.explore.avela.org/"
86
- }
87
-
88
  def find_eligible_schools(self,
89
  grade_id: str,
90
  address: Dict[str, str],
@@ -133,26 +133,19 @@ class EligibilityAPI:
133
  Returns:
134
  List[Dict[str, Any]]: List of eligible schools
135
  """
136
- # Extract ineligible school IDs from the API response
137
  ineligible_school_ids = []
138
  if "ineligibleSchools" in api_response:
139
- ineligible_school_ids = [school["id"] for school in api_response["ineligibleSchools"]]
140
-
141
- # If API returns complete school list, use that instead of our static list
142
- all_schools = api_response.get("allSchools", self.ALL_SCHOOLS)
143
 
 
 
144
  # Filter out ineligible schools to get eligible ones
145
  eligible_schools = [
146
  school for school in all_schools
147
  if school["id"] not in ineligible_school_ids
148
  ]
149
 
150
- # If we're working with the static list, we need to add addresses
151
- # In a real implementation, this would come from the API
152
- for school in eligible_schools:
153
- if "address" not in school:
154
- school["address"] = f"Boston, MA"
155
-
156
  return eligible_schools
157
 
158
  def get_school_details(self, school_id: str) -> Dict[str, Any]:
@@ -171,6 +164,51 @@ class EligibilityAPI:
171
  """
172
  # Placeholder for future implementation
173
  pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
 
175
  @staticmethod
176
  def grade_options() -> Dict[str, str]:
 
6
  """
7
 
8
  import requests
9
+ import json
10
  from typing import Dict, Any, Optional, List
11
+ import os
12
 
13
  class EligibilityAPI:
14
  """
 
17
 
18
  BASE_URL = "https://prod.execute-api.apply.avela.org/eligibility/organizations/boston/formTemplates/2f58f4ce-b462-4028-ae59-7ab874fc1224/findEligibility"
19
 
20
+ # Load the complete list of schools from the minified JSON file
21
+ def __init__(self):
22
+ """Initialize the API client with default headers and load school data."""
23
+ self.headers = {
24
+ "Content-Type": "application/json",
25
+ "User-Agent": "Mozilla/5.0",
26
+ "Origin": "https://boston.explore.avela.org",
27
+ "Referer": "https://boston.explore.avela.org/"
28
+ }
29
+
30
+ # Load the schools data from the minified JSON file
31
+ try:
32
+ with open("all_schools_minified.json", "r", encoding="utf-8") as f:
33
+ schools_data = json.load(f)
34
+ self.ALL_SCHOOLS = []
35
+ for school in schools_data:
36
+ self.ALL_SCHOOLS.append({
37
+ "id": school.get("id", ""),
38
+ "name": school.get("name", ""),
39
+ "referenceId": school.get("id", ""), # Use the id as referenceId
40
+ "address": school.get("address", "")
41
+ })
42
+ except Exception as e:
43
+ print(f"Error loading schools data: {e}")
44
 
45
  # Grade to UUID mapping
46
  GRADE_TO_UUID = {
 
85
  "Other": "64351764-04ed-4828-8320-35579deca69b"
86
  }
87
 
 
 
 
 
 
 
 
 
 
88
  def find_eligible_schools(self,
89
  grade_id: str,
90
  address: Dict[str, str],
 
133
  Returns:
134
  List[Dict[str, Any]]: List of eligible schools
135
  """
136
+ # Extract ineligible school reference_ids from the API response
137
  ineligible_school_ids = []
138
  if "ineligibleSchools" in api_response:
139
+ ineligible_school_ids = [school["referenceId"] for school in api_response["ineligibleSchools"]]
 
 
 
140
 
141
+ all_schools = json.load(open("all_schools_minified.json"))
142
+
143
  # Filter out ineligible schools to get eligible ones
144
  eligible_schools = [
145
  school for school in all_schools
146
  if school["id"] not in ineligible_school_ids
147
  ]
148
 
 
 
 
 
 
 
149
  return eligible_schools
150
 
151
  def get_school_details(self, school_id: str) -> Dict[str, Any]:
 
164
  """
165
  # Placeholder for future implementation
166
  pass
167
+
168
+ def get_full_school_details(self, school_id: str) -> Dict[str, Any]:
169
+ """
170
+ Get comprehensive information about a specific school from en.data.json
171
+
172
+ Args:
173
+ school_id (str): The ID of the school to get details for
174
+
175
+ Returns:
176
+ Dict[str, Any]: Detailed school information or empty dict if not found
177
+ """
178
+ try:
179
+ # Load the full school data from en.data.json
180
+ # The file seems to have some formatting issues, so we need to handle it carefully
181
+ with open("en.data.json", "r", encoding="utf-8") as f:
182
+ # Read and fix json format
183
+ data = f.read()
184
+ data = data.replace("%", "") # Remove any trailing % characters
185
+ # Try loading as JSON
186
+ try:
187
+ schools_data = json.loads(data)
188
+ except json.JSONDecodeError:
189
+ # If the file doesn't parse correctly, it may need additional cleaning
190
+ print("Error parsing en.data.json - attempting alternative parsing")
191
+ # Try to extract schools as a list from the file content
192
+ if data.startswith("[{") and data.endswith("}]"):
193
+ # Remove any trailing characters after the last closing bracket
194
+ clean_data = data[:data.rindex("}]") + 2]
195
+ try:
196
+ schools_data = json.loads(clean_data)
197
+ except:
198
+ print("Failed to parse en.data.json even after cleaning")
199
+ return {}
200
+ else:
201
+ print("Cannot identify JSON structure in en.data.json")
202
+ return {}
203
+
204
+ # Find the school by ID - strictly compare strings to avoid type issues
205
+ for school in schools_data:
206
+ if str(school.get("id", "")) == str(school_id):
207
+ return school
208
+
209
+ except Exception as e:
210
+ print(f"Error loading full school data: {e}")
211
+ return {}
212
 
213
  @staticmethod
214
  def grade_options() -> Dict[str, str]: