class SubmissionForm(forms.Form):
    file = forms.FileField() class StudentProfileForm(forms.ModelForm):
    class Meta:
        model = Student
        exclude = ('user', 'course')

    fields = [ 'first_name', 'last_name'] class Submission(models.Model):
    date = models.DateTimeField(editable=False, auto_now_add=True)
    course = models.ForeignKey(Course) 
    grade = models.FloatField(null = True, blank = True)
    assignment = models.ForeignKey(Assignment)
    submitter = models.ForeignKey(Student)
    docfile = models.FileField(upload_to='documents/%Y/%m/%d')
    remarks = models.TextField()
    
    def get_grade_path(self, filename):
        savename = str(self.assignment.name) + os.path.splitext(filename)[1]
        return os.path.join('uploads/submitted_files/',
                            self.course.department,
                            self.course.name,
                            self.submitter.username,
                            savename)

    def __unicode__(self):
        return (self.assignment.__unicode__() + " - " + self.submitter.user.username) class Course(models.Model):
    name = models.CharField(max_length=512, unique = True)
    department = models.CharField(max_length=4)
    description = models.TextField(max_length=512)
    instructor = models.ForeignKey(Instructor)

    def __unicode__(self):
        return unicode(self.name) class Student(models.Model):
    first_name = models.CharField(max_length=20)
    last_name = models.CharField(max_length=30)
    user = models.OneToOneField(User, unique=True)
    course = models.ManyToManyField(Course, blank=True, null=True)

    def __unicode__(self):
        return unicode(self.user) class Lecture(models.Model):
    name = models.CharField(max_length=20)
    video = EmbedVideoField()
    course = models.ForeignKey(Course)
    #for future feature of notes?
    #notes = models.CharField(max_length=512)
    
    def __unicode__(self):
        return (self.course.name + " - " + self.name) class Assignment(models.Model):
    date = models.DateTimeField(editable=False, auto_now_add=True)
    due_date = models.DateTimeField(editable=True)
    course = models.ForeignKey(Course)
    name = models.CharField(max_length=20)
    description = models.TextField(max_length=512)
    points_possible = models.IntegerField(default=100)
    QUIZ = 'Quiz'
    EXAM = 'Exam'
    HOMEWORK = 'Homework'
    PROJECT = 'Project'
    SUBMISSION_TYPE_CHOICES = (
        (QUIZ, QUIZ),
        (EXAM, EXAM),
        (HOMEWORK, HOMEWORK),
        (PROJECT, PROJECT))
    submission_type = models.CharField(max_length=8,
                                       choices=SUBMISSION_TYPE_CHOICES,
                                       default=QUIZ)    



    def __unicode__(self):
        return (self.course.name + " - " + self.name) class Homework(Submission):
    weight = .2 class Quiz(Submission):
    weight = .2 class Exam(Submission):
    weight = .4 class Project(Submission):
    weight = .2 class CourseMaterial(models.Model):
    file = models.FileField(upload_to='/fucking/dont/upload/here')
    course = models.ForeignKey(Course)
    description = models.TextField(max_length=30)
from django.shortcuts import render_to_response, render, redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth import get_user_model
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse_lazy
from django.template import RequestContext
from django.core.context_processors import csrf
from django.conf import settings
from django.core.servers.basehttp import FileWrapper
from registration.backends.simple.views import RegistrationView
from django.views.static import serve
from django.views.generic.edit import UpdateView
from student_portal.forms import SubmissionForm, StudentProfileForm
from student_portal.models import Submission, Course, Student, Lecture, Assignment, Homework, Quiz, Exam, Project, CourseMaterial
import matplotlib.pyplot as plt
import numpy as np
import os
import mimetypes
    print sub.id
    dirlist = sub.docfile.name.split(os.sep)
    while dirlist[0] != 'media':
        dirlist.pop(0)
    print dirlist
    print dirlist[-1]
    type, _ = mimetypes.guess_type(dirlist[-1])
    print type
    f = open(sub.docfile.name, "r")
    response = HttpResponse(FileWrapper(f), content_type=type)
    response['Content-Disposition'] = 'attachment; filename=' + dirlist[-1]
    return response

def get_graded_material(student, course, model):
    student_model = []
    for x in model.objects.all():
        if x.submitter == student and x.course == course:
            student_model.append(x)
    return student_model

def get_grades(submissions):
    total = 0
    grade = 0
    weight = 0
    if submissions:
        weight = submissions[0].weight

    for submission in submissions:
        if not submission.grade == None:
            grade += submission.grade * weight
            total += submission.assignment.points_possible * weight

    return total, grade

def get_total_grade(course, student): #not pythonic lyfe
    return sum([item for sublist in
                    ( map(get_grades, # that feel when no functional compose
                         map(lambda x: get_graded_material(student, course, x),
                             [Homework, Quiz, Exam, Project])))
                  for item in sublist][1::2])

def update_histogram(course):
    oldfn = settings.MEDIA_ROOT + '/' + course.department + '/' + str(course.id) + '/distribution.png'
    try:
        os.remove(oldfn)
    except OSError:
        None
    student_and_grade = []
    for student in course.student_set.all():
        homeworks, quizzes, exams, projects = map(lambda x: get_graded_material(student, course, x), [Homework, Quiz, Exam, Project])
        (hwtotal, hwgrade), (quiztotal, quizgrade), (examtotal, examgrade), (projecttotal, projectgrade) =  map(get_grades, [homeworks, quizzes, exams, projects])
        grade = hwgrade + quizgrade + examgrade + projectgrade
        total = hwtotal + quiztotal + examtotal + projecttotal
        if grade != 0:
            student_and_grade.append( (student, grade/total) )
    ranked_students = sorted( filter(lambda x: x[1] != 0, student_and_grade), key=lambda x: x[1])[::-1]
    ranked_grades = np.array(filter(lambda x: x != 0, map(lambda x: x[1], ranked_students) ))

    plt.clf()
    plt.cla()
    plt.figure()
    if ranked_students:
        n, bins, patches = plt.hist( ranked_grades , bins=20, color='b')
    else:
        return -1
    plt.axvline(ranked_grades.mean(), color='r', linestyle='dashed', linewidth=2, label='mean')
    print np.median(ranked_grades)
    plt.axvline(np.median(ranked_grades), color='g', linestyle='dashed', linewidth=2, label='median')
    plt.legend()
    plt.xlim([0, 1])
    plt.xlabel('Total Grade')
    plt.ylabel('Students')
    plt.yticks( range(1, n.max()+3) )
    fig = plt.gcf()
    fig.set_size_inches(10,4)
    fn = settings.MEDIA_ROOT + '/' + course.department + '/' + str(course.id) + '/distribution.png'
    plt.savefig(fn, bbox_inches=0, transparent=True)
    fn = fn.split('/')
    while fn[0] != 'media': fn.pop(0)
    fn_ = ''
    for d in fn: fn_ += '/' + d
    return fn_

def update_rank_and_histogram(course, student):
    all_grades = map(lambda x: get_total_grade(course, x), course.student_set.all())
    student_and_grade = zip(course.student_set.all(), all_grades)
    ranked_students = sorted( filter(lambda x: x[1] != 0, student_and_grade), key=lambda x: x[1])[::-1]
    amt_ranked = len(ranked_students)
    try: # get a student's rank
        rank = [y[0] for y in ranked_students ].index(student) + 1
    except ValueError:
        rank = 0
    fn = update_histogram(course)
    return rank, amt_ranked, fn

def display_grades(request, course_department, course_id):
    student = request.user.student
    course = get_course(int(course_id))
    homeworks, quizzes, exams, projects = map(lambda x: get_graded_material(student, course, x), [Homework, Quiz, Exam, Project])
    (hwtotal, hwgrade), (quiztotal, quizgrade), (examtotal, examgrade), (projecttotal, projectgrade) =  map(get_grades, [homeworks, quizzes, exams, projects])
    grade = hwgrade + quizgrade + examgrade + projectgrade
    total = hwtotal + quiztotal + examtotal + projecttotal
    rank, amt_ranked, hist_fn = update_rank_and_histogram(course, student)
    context = {'homeworks': homeworks,
               'quizzes': quizzes,
               'exams': exams,
               'projects': projects,
               'course': course,
               'total': total,
               'grade': grade,
               'hwtotal': hwtotal,           'hwgrade': hwgrade,
               'quiztotal': quiztotal,       'quizgrade': quizgrade,
               'examtotal': examtotal,       'examgrade': examgrade,
               'projecttotal': projecttotal, 'projectgrade': projectgrade,
               'rank' : rank, 'amt_ranked' : amt_ranked, 'hist_img' : hist_fn}
    return render(request, 'student_portal/grades.html', context)

def display_course_materials(request, course_dept, course_id):
    c = get_course(int(course_id))
    courses = list(request.user.student.course.all())

    cms = CourseMaterial.objects.all().filter(course=c)