import slate
import re
import numpy as np
from pprint import pprint

# Assumptions: Precisely one student per page. No +'s or -'s in grades.

def GPA_from_letter_grades(letterGrades):
    """
    Computes a floating point GPA for a student given a list of their letter grades.
    """
    letter2number = {'A':4.0, 'B':3.0, 'C':2.0, 'D':1.0, 'F':0.0}
    return np.mean([letter2number[letter] for letter in letterGrades])

# First, find the file.

# Then, extract text from the file.
with open('streamPDF.pdf', 'rb') as f:
    raw = slate.PDF(f)

# Parse the text.
students = []
for page in raw:
    # First find the name of the student.
    name = re.search(r"Progress Report For (.*) \(", page).group(1)
    if name == "Ansar Abdusemed Bahrun":
        continue
    # Then grab the section containing their grades.
    # The section contraining the grades begins with "Overall".
    gradeSection = re.search(r"Overall(.*?)Date", page, re.S).group(1)
    # Break that section into classes.
    # Each class ends with a number of missing assignments; split on that.
    classChunks = re.split(r"\n[\d]+\n", gradeSection)[:-1] # Last one is empty.
    # Now extract their overall grade for each class.
    letterGrades = []
    for chunk in classChunks:
        try:
            letterGrades.append(re.search(r"(\w)\n\n", chunk).group(1))
        except:
            # Only known exception is no grades in yet; just ignore for GPA.
            pass

    students.append({'name': name,
                     'letterGrades' : letterGrades,
                     'GPA' : GPA_from_letter_grades(letterGrades)})

pprint(students)
print("Class Average GPA: " + str(np.mean([student['GPA'] for student in students])))

# Display results.

@@ -60,16 +60,31 @@
 t pprint
+%0Aimport Tkinter
 %0A%0A# Assu
@@ -1634,110 +1634,389 @@
 ts)%0A
-print(%22Class Average GPA: %22 + str(np.mean(%5Bstudent%5B'GPA'%5D for student in students%5D)))%0A%0A# Display results.
+%0A# Display results.%0Atop = Tkinter.Tk()%0Atext = Tkinter.Text(top)%0Aoutput = %22%22%0Afor student in sorted(students, key=lambda x: x%5B'GPA'%5D):%0A    output += student%5B'name'%5D + ' : ' + str(student%5B'GPA'%5D) + '%5Cn'%0Aoutput += %22Class Average GPA: %22 + str(np.mean(%5Bstudent%5B'GPA'%5D for student in students%5D))%0Atext.insert(Tkinter.INSERT, output)%0Atext.pack()%0Atext.configure(state=%22disabled%22)%0Atop.mainloop()
 %0A

Add Tkinter text output