Dannyar608 commited on
Commit
38fde1b
·
verified ·
1 Parent(s): 44de816

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +188 -53
app.py CHANGED
@@ -7,8 +7,46 @@ from PyPDF2 import PdfReader
7
  from collections import defaultdict
8
 
9
  # ========== TRANSCRIPT PARSING FUNCTIONS ==========
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  def parse_transcript(file):
11
- if file.name.endswith('.pdf'):
 
 
 
 
12
  text = ''
13
  reader = PdfReader(file)
14
  for page in reader.pages:
@@ -20,16 +58,17 @@ def parse_transcript(file):
20
  grade_match = re.search(r'(Grade|Year)[\s:]*(\d+|Freshman|Sophomore|Junior|Senior)', text, re.IGNORECASE)
21
  grade_level = grade_match.group(2) if grade_match else "Unknown"
22
 
23
- # GPA extraction
24
  gpa_data = {'weighted': "N/A", 'unweighted': "N/A"}
25
  gpa_patterns = [
26
  r'Weighted GPA[\s:]*(\d\.\d{1,2})',
27
  r'GPA \(Weighted\)[\s:]*(\d\.\d{1,2})',
 
28
  r'Unweighted GPA[\s:]*(\d\.\d{1,2})',
29
  r'GPA \(Unweighted\)[\s:]*(\d\.\d{1,2})',
 
30
  r'GPA[\s:]*(\d\.\d{1,2})'
31
  ]
32
-
33
  for pattern in gpa_patterns:
34
  for match in re.finditer(pattern, text, re.IGNORECASE):
35
  gpa_value = match.group(1)
@@ -43,6 +82,8 @@ def parse_transcript(file):
43
  if gpa_data['weighted'] == "N/A":
44
  gpa_data['weighted'] = gpa_value
45
 
 
 
46
  output_text = f"Grade Level: {grade_level}\n\n"
47
  if gpa_data['weighted'] != "N/A" or gpa_data['unweighted'] != "N/A":
48
  output_text += "GPA Information:\n"
@@ -53,12 +94,43 @@ def parse_transcript(file):
53
  else:
54
  output_text += "No GPA information found\n"
55
 
 
 
56
  return output_text, {
57
  "gpa": gpa_data,
58
- "grade_level": grade_level
 
59
  }
60
  else:
61
- return "Currently only PDF transcripts are supported", None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
  # ========== LEARNING STYLE QUIZ ==========
64
  learning_style_questions = [
@@ -66,7 +138,22 @@ learning_style_questions = [
66
  "When you need directions to a new place, you prefer:",
67
  "When you learn a new skill, you prefer to:",
68
  "When you're trying to concentrate, you:",
69
- "When you meet new people, you remember them by:"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  ]
71
 
72
  learning_style_options = [
@@ -74,7 +161,22 @@ learning_style_options = [
74
  ["Look at a map (Visual)", "Have someone tell you (Auditory)", "Write down directions (Reading/Writing)", "Try walking/driving there (Kinesthetic)"],
75
  ["Read instructions (Reading/Writing)", "Have someone show you (Visual)", "Listen to explanations (Auditory)", "Try it yourself (Kinesthetic)"],
76
  ["Need quiet (Reading/Writing)", "Need background noise (Auditory)", "Need to move around (Kinesthetic)", "Need visual stimulation (Visual)"],
77
- ["Their face (Visual)", "Their name (Auditory)", "What you talked about (Reading/Writing)", "What you did together (Kinesthetic)"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  ]
79
 
80
  def learning_style_quiz(*answers):
@@ -85,39 +187,36 @@ def learning_style_quiz(*answers):
85
  "Kinesthetic": 0
86
  }
87
 
 
88
  for i, answer in enumerate(answers):
89
- if answer == learning_style_options[i][0]:
90
  scores["Reading/Writing"] += 1
91
- elif answer == learning_style_options[i][1]:
92
  scores["Auditory"] += 1
93
- elif answer == learning_style_options[i][2]:
94
  scores["Visual"] += 1
95
- elif answer == learning_style_options[i][3]:
96
  scores["Kinesthetic"] += 1
97
 
 
98
  max_score = max(scores.values())
99
  dominant_styles = [style for style, score in scores.items() if score == max_score]
100
 
 
101
  if len(dominant_styles) == 1:
102
- return f"Your primary learning style is: {dominant_styles[0]}"
103
  else:
104
- return f"You have multiple strong learning styles: {', '.join(dominant_styles)}"
105
-
106
- # ========== PROFILE MANAGEMENT ==========
107
- def save_profile(name, age, interests, transcript, learning_style,
108
- movie, movie_reason, show, show_reason,
109
- book, book_reason, character, character_reason, blog):
110
- favorites = {
111
- "movie": movie,
112
- "movie_reason": movie_reason,
113
- "show": show,
114
- "show_reason": show_reason,
115
- "book": book,
116
- "book_reason": book_reason,
117
- "character": character,
118
- "character_reason": character_reason
119
- }
120
 
 
 
 
 
 
 
 
 
 
121
  data = {
122
  "name": name,
123
  "age": age,
@@ -127,36 +226,60 @@ def save_profile(name, age, interests, transcript, learning_style,
127
  "favorites": favorites,
128
  "blog": blog
129
  }
130
-
131
  os.makedirs("student_profiles", exist_ok=True)
132
  json_path = os.path.join("student_profiles", f"{name.replace(' ', '_')}_profile.json")
133
  with open(json_path, "w") as f:
134
  json.dump(data, f, indent=2)
135
-
136
- return "Profile saved successfully!"
137
 
138
- def load_profile():
139
- files = [f for f in os.listdir("student_profiles") if f.endswith('.json')]
140
- if files:
141
- with open(os.path.join("student_profiles", files[0]), "r") as f:
142
- return json.load(f)
143
- return {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
 
145
  # ========== GRADIO INTERFACE ==========
146
  with gr.Blocks() as app:
147
- # Profile tabs
148
  with gr.Tab("Step 1: Upload Transcript"):
149
- transcript_file = gr.File(label="Upload your transcript (PDF)")
150
  transcript_output = gr.Textbox(label="Transcript Output")
151
  transcript_data = gr.State()
152
- transcript_file.change(parse_transcript, inputs=transcript_file, outputs=[transcript_output, transcript_data])
153
 
154
  with gr.Tab("Step 2: Learning Style Quiz"):
 
155
  quiz_components = []
156
  for i, (question, options) in enumerate(zip(learning_style_questions, learning_style_options)):
157
- quiz_components.append(gr.Radio(options, label=f"{i+1}. {question}"))
 
 
158
 
159
- learning_output = gr.Textbox(label="Learning Style Result")
160
  gr.Button("Submit Quiz").click(
161
  learning_style_quiz,
162
  inputs=quiz_components,
@@ -177,18 +300,30 @@ with gr.Blocks() as app:
177
  character_reason = gr.Textbox(label="Why do you like that character?")
178
  blog_checkbox = gr.Checkbox(label="Do you want to write a blog?", value=False)
179
  blog_text = gr.Textbox(label="Write your blog here", visible=False, lines=5)
180
- blog_checkbox.change(lambda x: gr.update(visible=x), inputs=blog_checkbox, outputs=blog_text)
181
 
182
- with gr.Tab("Step 4: Save Profile"):
 
183
  save_btn = gr.Button("Save Profile")
184
- save_output = gr.Textbox(label="Save Status")
185
-
186
- save_btn.click(
187
- save_profile,
188
- inputs=[name, age, interests, transcript_data, learning_output,
189
- movie, movie_reason, show, show_reason,
190
- book, book_reason, character, character_reason, blog_text],
191
- outputs=save_output
192
- )
 
 
 
 
 
 
 
 
 
 
 
193
 
194
  app.launch()
 
7
  from collections import defaultdict
8
 
9
  # ========== TRANSCRIPT PARSING FUNCTIONS ==========
10
+ def extract_courses_with_grade_levels(text):
11
+ grade_level_pattern = r"(Grade|Year)\s*[:]?\s*(\d+|Freshman|Sophomore|Junior|Senior)"
12
+ grade_match = re.search(grade_level_pattern, text, re.IGNORECASE)
13
+ current_grade_level = grade_match.group(2) if grade_match else "Unknown"
14
+
15
+ course_pattern = r"""
16
+ (?:^|\n)
17
+ (?: (Grade|Year)\s*[:]?\s*(\d+|Freshman|Sophomore|Junior|Senior)\s*[\n-]* )?
18
+ (
19
+ (?:[A-Z]{2,}\s?\d{3})
20
+ |
21
+ [A-Z][a-z]+(?:\s[A-Z][a-z]+)*
22
+ )
23
+ \s*
24
+ (?: [:\-]?\s* ([A-F][+-]?|\d{2,3}%)? )?
25
+ """
26
+
27
+ courses_by_grade = defaultdict(list)
28
+ current_grade = current_grade_level
29
+
30
+ for match in re.finditer(course_pattern, text, re.VERBOSE | re.MULTILINE):
31
+ grade_context, grade_level, course, grade = match.groups()
32
+
33
+ if grade_context:
34
+ current_grade = grade_level
35
+
36
+ if course:
37
+ course_info = {"course": course.strip()}
38
+ if grade:
39
+ course_info["grade"] = grade.strip()
40
+ courses_by_grade[current_grade].append(course_info)
41
+
42
+ return dict(courses_by_grade)
43
+
44
  def parse_transcript(file):
45
+ if file.name.endswith('.csv'):
46
+ df = pd.read_csv(file)
47
+ elif file.name.endswith('.xlsx'):
48
+ df = pd.read_excel(file)
49
+ elif file.name.endswith('.pdf'):
50
  text = ''
51
  reader = PdfReader(file)
52
  for page in reader.pages:
 
58
  grade_match = re.search(r'(Grade|Year)[\s:]*(\d+|Freshman|Sophomore|Junior|Senior)', text, re.IGNORECASE)
59
  grade_level = grade_match.group(2) if grade_match else "Unknown"
60
 
61
+ # Enhanced GPA extraction
62
  gpa_data = {'weighted': "N/A", 'unweighted': "N/A"}
63
  gpa_patterns = [
64
  r'Weighted GPA[\s:]*(\d\.\d{1,2})',
65
  r'GPA \(Weighted\)[\s:]*(\d\.\d{1,2})',
66
+ r'Cumulative GPA \(Weighted\)[\s:]*(\d\.\d{1,2})',
67
  r'Unweighted GPA[\s:]*(\d\.\d{1,2})',
68
  r'GPA \(Unweighted\)[\s:]*(\d\.\d{1,2})',
69
+ r'Cumulative GPA \(Unweighted\)[\s:]*(\d\.\d{1,2})',
70
  r'GPA[\s:]*(\d\.\d{1,2})'
71
  ]
 
72
  for pattern in gpa_patterns:
73
  for match in re.finditer(pattern, text, re.IGNORECASE):
74
  gpa_value = match.group(1)
 
82
  if gpa_data['weighted'] == "N/A":
83
  gpa_data['weighted'] = gpa_value
84
 
85
+ courses_by_grade = extract_courses_with_grade_levels(text)
86
+
87
  output_text = f"Grade Level: {grade_level}\n\n"
88
  if gpa_data['weighted'] != "N/A" or gpa_data['unweighted'] != "N/A":
89
  output_text += "GPA Information:\n"
 
94
  else:
95
  output_text += "No GPA information found\n"
96
 
97
+ output_text += "\n(Courses not shown here)"
98
+
99
  return output_text, {
100
  "gpa": gpa_data,
101
+ "grade_level": grade_level,
102
+ "courses": courses_by_grade
103
  }
104
  else:
105
+ return "Unsupported file format", None
106
+
107
+ # For CSV/XLSX fallback
108
+ gpa = "N/A"
109
+ for col in ['GPA', 'Grade Point Average', 'Cumulative GPA']:
110
+ if col in df.columns:
111
+ gpa = df[col].iloc[0] if isinstance(df[col].iloc[0], (float, int)) else "N/A"
112
+ break
113
+
114
+ grade_level = "N/A"
115
+ for col in ['Grade Level', 'Grade', 'Class', 'Year']:
116
+ if col in df.columns:
117
+ grade_level = df[col].iloc[0]
118
+ break
119
+
120
+ courses = []
121
+ for col in ['Course', 'Subject', 'Course Name', 'Class']:
122
+ if col in df.columns:
123
+ courses = df[col].tolist()
124
+ break
125
+
126
+ output_text = f"Grade Level: {grade_level}\nGPA: {gpa}\n\nCourses:\n"
127
+ output_text += "\n".join(f"- {course}" for course in courses)
128
+
129
+ return output_text, {
130
+ "gpa": {"unweighted": gpa, "weighted": "N/A"},
131
+ "grade_level": grade_level,
132
+ "courses": courses
133
+ }
134
 
135
  # ========== LEARNING STYLE QUIZ ==========
136
  learning_style_questions = [
 
138
  "When you need directions to a new place, you prefer:",
139
  "When you learn a new skill, you prefer to:",
140
  "When you're trying to concentrate, you:",
141
+ "When you meet new people, you remember them by:",
142
+ "When you're relaxing, you prefer to:",
143
+ "When you're explaining something to someone, you:",
144
+ "When you're trying to remember something, you:",
145
+ "When you're in a classroom, you learn best when:",
146
+ "When you're trying to solve a problem, you:",
147
+ "When you're taking notes, you:",
148
+ "When you're learning new software, you prefer to:",
149
+ "When you're at a museum, you spend the most time:",
150
+ "When you're assembling furniture, you:",
151
+ "When you're learning new vocabulary, you:",
152
+ "When you're giving a presentation, you prefer:",
153
+ "When you're at a party, you enjoy:",
154
+ "When you're taking a break from studying, you:",
155
+ "When you're learning dance moves, you:",
156
+ "When you're choosing a book, you prefer:"
157
  ]
158
 
159
  learning_style_options = [
 
161
  ["Look at a map (Visual)", "Have someone tell you (Auditory)", "Write down directions (Reading/Writing)", "Try walking/driving there (Kinesthetic)"],
162
  ["Read instructions (Reading/Writing)", "Have someone show you (Visual)", "Listen to explanations (Auditory)", "Try it yourself (Kinesthetic)"],
163
  ["Need quiet (Reading/Writing)", "Need background noise (Auditory)", "Need to move around (Kinesthetic)", "Need visual stimulation (Visual)"],
164
+ ["Their face (Visual)", "Their name (Auditory)", "What you talked about (Reading/Writing)", "What you did together (Kinesthetic)"],
165
+ ["Read (Reading/Writing)", "Listen to music (Auditory)", "Watch TV (Visual)", "Do something active (Kinesthetic)"],
166
+ ["Write it down (Reading/Writing)", "Tell them verbally (Auditory)", "Show them (Visual)", "Demonstrate physically (Kinesthetic)"],
167
+ ["See it written down (Visual)", "Say it out loud (Auditory)", "Write it down (Reading/Writing)", "Do it physically (Kinesthetic)"],
168
+ ["Reading materials (Reading/Writing)", "Listening to lectures (Auditory)", "Seeing diagrams (Visual)", "Doing hands-on activities (Kinesthetic)"],
169
+ ["Write down steps (Reading/Writing)", "Talk through it (Auditory)", "Draw diagrams (Visual)", "Try different approaches (Kinesthetic)"],
170
+ ["Write detailed notes (Reading/Writing)", "Record lectures (Auditory)", "Draw mind maps (Visual)", "Take minimal notes (Kinesthetic)"],
171
+ ["Read the manual (Reading/Writing)", "Have someone explain it (Auditory)", "Watch tutorial videos (Visual)", "Just start using it (Kinesthetic)"],
172
+ ["Reading descriptions (Reading/Writing)", "Listening to audio guides (Auditory)", "Looking at exhibits (Visual)", "Interactive displays (Kinesthetic)"],
173
+ ["Read instructions first (Reading/Writing)", "Ask someone to help (Auditory)", "Look at diagrams (Visual)", "Start assembling (Kinesthetic)"],
174
+ ["Write them repeatedly (Reading/Writing)", "Say them repeatedly (Auditory)", "Use flashcards (Visual)", "Use them in conversation (Kinesthetic)"],
175
+ ["Having detailed notes (Reading/Writing)", "Speaking freely (Auditory)", "Using visual aids (Visual)", "Demonstrating something (Kinesthetic)"],
176
+ ["Conversations (Auditory)", "People-watching (Visual)", "Dancing/games (Kinesthetic)", "Reading about people (Reading/Writing)"],
177
+ ["Read for fun (Reading/Writing)", "Listen to music (Auditory)", "Watch videos (Visual)", "Exercise (Kinesthetic)"],
178
+ ["Watch demonstrations (Visual)", "Listen to instructions (Auditory)", "Read choreography (Reading/Writing)", "Try the moves (Kinesthetic)"],
179
+ ["Text-heavy books (Reading/Writing)", "Audiobooks (Auditory)", "Books with pictures (Visual)", "Interactive books (Kinesthetic)"]
180
  ]
181
 
182
  def learning_style_quiz(*answers):
 
187
  "Kinesthetic": 0
188
  }
189
 
190
+ # Map each answer to a learning style
191
  for i, answer in enumerate(answers):
192
+ if answer in learning_style_options[i][0]:
193
  scores["Reading/Writing"] += 1
194
+ elif answer in learning_style_options[i][1]:
195
  scores["Auditory"] += 1
196
+ elif answer in learning_style_options[i][2]:
197
  scores["Visual"] += 1
198
+ elif answer in learning_style_options[i][3]:
199
  scores["Kinesthetic"] += 1
200
 
201
+ # Get the highest score(s)
202
  max_score = max(scores.values())
203
  dominant_styles = [style for style, score in scores.items() if score == max_score]
204
 
205
+ # Generate result
206
  if len(dominant_styles) == 1:
207
+ result = f"Your primary learning style is: {dominant_styles[0]}"
208
  else:
209
+ result = f"You have multiple strong learning styles: {', '.join(dominant_styles)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
 
211
+ # Add detailed breakdown
212
+ result += "\n\nDetailed Scores:\n"
213
+ for style, score in sorted(scores.items(), key=lambda x: x[1], reverse=True):
214
+ result += f"{style}: {score}/20\n"
215
+
216
+ return result
217
+
218
+ # ========== SAVE STUDENT PROFILE FUNCTION ==========
219
+ def save_profile(name, age, interests, transcript, learning_style, favorites, blog):
220
  data = {
221
  "name": name,
222
  "age": age,
 
226
  "favorites": favorites,
227
  "blog": blog
228
  }
 
229
  os.makedirs("student_profiles", exist_ok=True)
230
  json_path = os.path.join("student_profiles", f"{name.replace(' ', '_')}_profile.json")
231
  with open(json_path, "w") as f:
232
  json.dump(data, f, indent=2)
 
 
233
 
234
+ markdown_summary = f"""### Student Profile: {name}
235
+ **Age:** {age}
236
+ **Interests:** {interests}
237
+ **Learning Style:** {learning_style}
238
+ #### Transcript:
239
+ {transcript_display(transcript)}
240
+ #### Favorites:
241
+ - Movie: {favorites['movie']} ({favorites['movie_reason']})
242
+ - Show: {favorites['show']} ({favorites['show_reason']})
243
+ - Book: {favorites['book']} ({favorites['book_reason']})
244
+ - Character: {favorites['character']} ({favorites['character_reason']})
245
+ #### Blog:
246
+ {blog if blog else "_No blog provided_"}
247
+ """
248
+ return markdown_summary
249
+
250
+ def transcript_display(transcript_dict):
251
+ if not transcript_dict:
252
+ return "No transcript uploaded."
253
+ if isinstance(transcript_dict, dict) and all(isinstance(v, list) for v in transcript_dict.values()):
254
+ display = ""
255
+ for grade_level, courses in transcript_dict.items():
256
+ display += f"\n**Grade {grade_level}**\n"
257
+ for course in courses:
258
+ display += f"- {course['course']}"
259
+ if 'grade' in course:
260
+ display += f" (Grade: {course['grade']})"
261
+ display += "\n"
262
+ return display
263
+ return "\n".join([f"- {course}" for course in transcript_dict["courses"]] +
264
+ [f"Grade Level: {transcript_dict['grade_level']}", f"GPA: {transcript_dict['gpa']}"])
265
 
266
  # ========== GRADIO INTERFACE ==========
267
  with gr.Blocks() as app:
 
268
  with gr.Tab("Step 1: Upload Transcript"):
269
+ transcript_file = gr.File(label="Upload your transcript (CSV, Excel, or PDF)")
270
  transcript_output = gr.Textbox(label="Transcript Output")
271
  transcript_data = gr.State()
272
+ transcript_file.change(fn=parse_transcript, inputs=transcript_file, outputs=[transcript_output, transcript_data])
273
 
274
  with gr.Tab("Step 2: Learning Style Quiz"):
275
+ gr.Markdown("### Complete this 20-question quiz to determine your learning style")
276
  quiz_components = []
277
  for i, (question, options) in enumerate(zip(learning_style_questions, learning_style_options)):
278
+ quiz_components.append(
279
+ gr.Radio(choices=options, label=f"{i+1}. {question}")
280
+ )
281
 
282
+ learning_output = gr.Textbox(label="Learning Style Result", lines=5)
283
  gr.Button("Submit Quiz").click(
284
  learning_style_quiz,
285
  inputs=quiz_components,
 
300
  character_reason = gr.Textbox(label="Why do you like that character?")
301
  blog_checkbox = gr.Checkbox(label="Do you want to write a blog?", value=False)
302
  blog_text = gr.Textbox(label="Write your blog here", visible=False, lines=5)
303
+ blog_checkbox.change(fn=lambda x: gr.update(visible=x), inputs=blog_checkbox, outputs=blog_text)
304
 
305
+ with gr.Tab("Step 4: Save & Review"):
306
+ output_summary = gr.Markdown()
307
  save_btn = gr.Button("Save Profile")
308
+
309
+ def gather_and_save(name, age, interests, movie, movie_reason, show, show_reason,
310
+ book, book_reason, character, character_reason, blog, transcript, learning_style):
311
+ favorites = {
312
+ "movie": movie,
313
+ "movie_reason": movie_reason,
314
+ "show": show,
315
+ "show_reason": show_reason,
316
+ "book": book,
317
+ "book_reason": book_reason,
318
+ "character": character,
319
+ "character_reason": character_reason,
320
+ }
321
+ return save_profile(name, age, interests, transcript, learning_style, favorites, blog)
322
+
323
+ save_btn.click(fn=gather_and_save,
324
+ inputs=[name, age, interests, movie, movie_reason, show, show_reason,
325
+ book, book_reason, character, character_reason, blog_text,
326
+ transcript_data, learning_output],
327
+ outputs=output_summary)
328
 
329
  app.launch()