示例#1
0
    def test_json_view(self):
        self.client.login(username='******', password='******')
        r = self.client.get('/onsite/' + self.program.url + '/unenroll_status')
        data = json.loads(r.content)

        self.assertGreaterEqual(len(data['student_timeslots']), 20)
        self.assertGreater(len(data['section_timeslots']), 0)
        self.assertGreater(len(data['enrollments']), 0)

        for student_id, ts_id in data['student_timeslots'].items():
            self.assertTrue(self.timeslots.filter(id=ts_id).exists())
            self.assertTrue(StudentRegistration.valid_objects().filter(
                user=student_id, section__meeting_times=ts_id).exists())
            self.assertFalse(
                Record.objects.filter(event='attended',
                                      program=self.program,
                                      user=student_id).exists())

        for section_id, ts_id in data['section_timeslots'].items():
            self.assertTrue(self.timeslots.filter(id=ts_id).exists())
            sec = ClassSection.objects.get(id=section_id)
            self.assertTrue(sec.meeting_times.filter(id=ts_id).exists())
            self.assertTrue(StudentRegistration.valid_objects().filter(
                section=section_id).exists())

        for sr_id, (user_id, section_id) in data['enrollments'].items():
            sr = StudentRegistration.objects.get(id=sr_id)
            self.assertEqual(sr.user_id, user_id)
            self.assertEqual(sr.section_id, section_id)
            self.assertIn(str(user_id), data['student_timeslots'])
            self.assertIn(str(section_id), data['section_timeslots'])
    def test_json_view(self):
        self.client.login(username='******', password='******')
        r = self.client.get('/onsite/' + self.program.url + '/unenroll_status')
        data = json.loads(r.content)

        self.assertGreaterEqual(len(data['student_timeslots']), 20)
        self.assertGreater(len(data['section_timeslots']), 0)
        self.assertGreater(len(data['enrollments']), 0)

        for student_id, ts_id in data['student_timeslots'].items():
            self.assertTrue(self.timeslots.filter(id=ts_id).exists())
            self.assertTrue(StudentRegistration.valid_objects().filter(
                user=student_id, section__meeting_times=ts_id).exists())
            self.assertFalse(Record.objects.filter(
                event='attended', program=self.program,
                user=student_id).exists())

        for section_id, ts_id in data['section_timeslots'].items():
            self.assertTrue(self.timeslots.filter(id=ts_id).exists())
            sec = ClassSection.objects.get(id=section_id)
            self.assertTrue(sec.meeting_times.filter(id=ts_id).exists())
            self.assertTrue(StudentRegistration.valid_objects().filter(
                section=section_id).exists())

        for sr_id, (user_id, section_id) in data['enrollments'].items():
            sr = StudentRegistration.objects.get(id=sr_id)
            self.assertEqual(sr.user_id, user_id)
            self.assertEqual(sr.section_id, section_id)
            self.assertIn(str(user_id), data['student_timeslots'])
            self.assertIn(str(section_id), data['section_timeslots'])
示例#3
0
 def lottery_preferences_legacy(self, request, prog):
     # DEPRECATED: see comments in lottery_preferences method
     sections = list(prog.sections().values('id'))
     sections_interested = StudentRegistration.valid_objects().filter(
         relationship__name='Interested',
         user=request.user,
         section__parent_class__parent_program=prog).select_related(
             'section__id').values_list('section__id',
                                        flat=True).distinct()
     sections_priority = StudentRegistration.valid_objects().filter(
         relationship__name='Priority/1',
         user=request.user,
         section__parent_class__parent_program=prog).select_related(
             'section__id').values_list('section__id',
                                        flat=True).distinct()
     for item in sections:
         if item['id'] in sections_interested:
             item['lottery_interested'] = True
         else:
             item['lottery_interested'] = False
         if item['id'] in sections_priority:
             item['lottery_priority'] = True
         else:
             item['lottery_priority'] = False
     return {'sections': sections}
    def viewlotteryprefs(self, request, tl, one, two, module, extra, prog):
        context = {}
        context['student'] = request.user

        priority_classids = set()
        uniquified_flags = []
        priority_flags = StudentRegistration.valid_objects().filter(user=request.user, section__parent_class__parent_program=prog, relationship__name='Priority/1')
        for flag in priority_flags:
            if flag.section.id not in priority_classids:
                priority_classids.add(flag.section.id)
                uniquified_flags.append(flag)
        context['priority'] = uniquified_flags
        if priority_flags.count() == 0:
            context['pempty'] = True
        else: context['pempty'] = False

        interested_classids = set()
        uniquified_interested = []
        interested = StudentRegistration.valid_objects().filter(user=request.user, section__parent_class__parent_program=prog, relationship__name='Interested')
        for flag in interested:
            if flag.section.id not in interested_classids:
                interested_classids.add(flag.section.id)
                uniquified_interested.append(flag)
        context['interested' ] = uniquified_interested
        if interested.count() == 0:
            context['iempty'] = True
        else: context['iempty'] = False

        return render_to_response(self.baseDir()+'view_lottery_prefs.html', request, context)
示例#5
0
    def viewlotteryprefs(self, request, tl, one, two, module, extra, prog):
        context = {}
        context['student'] = request.user
        context['program'] = prog

        priority_classids = set()
        uniquified_flags = []
        priority_flags = StudentRegistration.valid_objects().filter(user=request.user, section__parent_class__parent_program=prog, relationship__name='Priority/1')
        for flag in priority_flags:
            if flag.section.id not in priority_classids:
                priority_classids.add(flag.section.id)
                uniquified_flags.append(flag)
        context['priority'] = uniquified_flags
        if priority_flags.count() == 0:
            context['pempty'] = True
        else: context['pempty'] = False

        interested_classids = set()
        uniquified_interested = []
        interested = StudentRegistration.valid_objects().filter(user=request.user, section__parent_class__parent_program=prog, relationship__name='Interested')
        for flag in interested:
            if flag.section.id not in interested_classids:
                interested_classids.add(flag.section.id)
                uniquified_interested.append(flag)
        context['interested' ] = uniquified_interested
        if interested.count() == 0:
            context['iempty'] = True
        else: context['iempty'] = False

        return render_to_response(self.baseDir()+'view_lottery_prefs.html', request, (prog, tl), context)
    def classchangerequest(self, request, tl, one, two, module, extra, prog):
        timeslots = prog.getTimeSlots()
        sections = prog.sections().filter(status=10, meeting_times__isnull=False).distinct()

        enrollments = {}
        for timeslot in timeslots:
            try:
                enrollments[timeslot] = ClassSubject.objects.get(nest_Q(StudentRegistration.is_valid_qobject(), 'sections__studentregistration'), sections__studentregistration__relationship__name="Enrolled", sections__studentregistration__user=request.user, sections__meeting_times=timeslot, parent_program=prog)
            except ClassSubject.DoesNotExist:
                enrollments[timeslot] = None

        context = {}
        context['timeslots'] = timeslots
        context['enrollments'] = enrollments
        context['user'] = request.user
        if 'success' in request.GET:
            context['success'] = True
        else:
            context['success'] = False

        if request.user.isStudent():
            sections_by_slot = dict([(timeslot,[(section, 1 == StudentRegistration.valid_objects().filter(user=context['user'], section=section, relationship__name="Request").count()) for section in sections if section.get_meeting_times()[0] == timeslot and section.parent_class.grade_min <= request.user.getGrade(prog) <= section.parent_class.grade_max and section.parent_class not in enrollments.values() and ESPUser.getRankInClass(request.user, section.parent_class) in (5,10)]) for timeslot in timeslots])
        else:
            sections_by_slot = dict([(timeslot,[(section, False) for section in sections if section.get_meeting_times()[0] == timeslot]) for timeslot in timeslots])

        fields = {}
        for i, timeslot in enumerate(sections_by_slot.keys()):
            choices = [('0', "I'm happy with my current enrollment.")]
            initial = '0'
            for section in sections_by_slot[timeslot]:
                choices.append((section[0].emailcode(), section[0].emailcode()+": "+section[0].title()))
                if section[1]:
                    initial = section[0].emailcode()
            fields['timeslot_'+str(i+1)] = forms.ChoiceField(label="Timeslot "+str(i+1)+" ("+timeslot.pretty_time()+")", choices=choices, initial=initial)

        form = type('ClassChangeRequestForm', (forms.Form,), fields)
        context['form'] = form()
        if request.method == "POST":
            old_requests = StudentRegistration.valid_objects().filter(user=context['user'], section__parent_class__parent_program=prog, relationship__name="Request")
            for r in old_requests:
                r.expire()
            form = form(request.POST)
            if form.is_valid():
                for value in form.cleaned_data.values():
                    section = None
                    for s in sections:
                        if s.emailcode() == value:
                            section = s
                            break
                    if not section:
                        continue
                    r = StudentRegistration.valid_objects().get_or_create(user=context['user'], section=section, relationship=RegistrationType.objects.get_or_create(name="Request", category="student")[0])[0]
                    r.save()

                return HttpResponseRedirect(request.path.rstrip('/')+'/?success')
        else:
            return render_to_response(self.baseDir() + 'classchangerequest.html', request, context)
 def lottery_preferences_legacy(self, request, prog):
     # DEPRECATED: see comments in lottery_preferences method
     sections = list(prog.sections().values('id'))
     sections_interested = StudentRegistration.valid_objects().filter(relationship__name='Interested', user=request.user, section__parent_class__parent_program=prog).select_related('section__id').values_list('section__id', flat=True).distinct()
     sections_priority = StudentRegistration.valid_objects().filter(relationship__name='Priority/1', user=request.user, section__parent_class__parent_program=prog).select_related('section__id').values_list('section__id', flat=True).distinct()
     for item in sections:
         if item['id'] in sections_interested:
             item['lottery_interested'] = True
         else:
             item['lottery_interested'] = False
         if item['id'] in sections_priority:
             item['lottery_priority'] = True
         else:
             item['lottery_priority'] = False
     return {'sections': sections}
示例#8
0
    def students(self, QObject=False):

        Enrolled = Q(studentregistration__relationship__name='Enrolled')
        Par = Q(studentregistration__section__parent_class__parent_program=self
                .program)
        Unexpired = nest_Q(StudentRegistration.is_valid_qobject(),
                           'studentregistration')

        # Force Django to generate two subqueries without joining SRs to SSIs,
        # as efficiently as possible since it's still a big query.
        sr_ids = StudentRegistration.valid_objects().filter(
            section__parent_class__parent_program=self.program).values(
                'user').distinct()
        ssi_ids = StudentSubjectInterest.valid_objects().filter(
            subject__parent_program=self.program).values('user').distinct()
        any_reg_q = Q(id__in=sr_ids) | Q(id__in=ssi_ids)

        qobjects = {
            'enrolled': Enrolled & Par & Unexpired,
            'classreg': any_reg_q,
        }

        if QObject:
            return qobjects
        else:
            return {
                k: ESPUser.objects.filter(v).distinct()
                for k, v in qobjects.iteritems()
            }
示例#9
0
    def getSchedule(program, student):

        schedule = """
Student schedule for %s:

 Time               | Class                   | Room""" % student.name()

        regs = StudentRegistration.valid_objects().filter(
            user=student,
            section__parent_class__parent_program=program,
            relationship__name='Accepted')
        classes = [x.section.parent_class for x in regs]

        # now we sort them by time/title
        classes.sort()

        for cls in classes:
            rooms = cls.prettyrooms()
            if len(rooms) == 0:
                rooms = 'N/A'
            else:
                rooms = ", ".join(rooms)

            schedule += """
%s|%s|%s""" % (",".join(
                cls.friendly_times()).ljust(20), cls.title.ljust(25), rooms)

        return schedule
    def students(self, QObject = False):

        Enrolled = Q(studentregistration__relationship__name='Enrolled')
        Par = Q(studentregistration__section__parent_class__parent_program=self.program)
        Unexpired = nest_Q(StudentRegistration.is_valid_qobject(), 'studentregistration')

        # Force Django to generate two subqueries without joining SRs to SSIs,
        # as efficiently as possible since it's still a big query.
        sr_ids = StudentRegistration.valid_objects().filter(
            section__parent_class__parent_program=self.program
        ).values('user').distinct()
        ssi_ids = StudentSubjectInterest.valid_objects().filter(
            subject__parent_program=self.program).values('user').distinct()
        any_reg_q = Q(id__in = sr_ids) | Q(id__in = ssi_ids)

        qobjects = {
            'enrolled': Enrolled & Par & Unexpired,
            'classreg': any_reg_q,
        }

        if QObject:
            return qobjects
        else:
            return {k: ESPUser.objects.filter(v).distinct()
                    for k, v in qobjects.iteritems()}
示例#11
0
 def num_users_enrolled(self, prog):
     # Querying for SRs and then extracting the users saves us joining the
     # users table.
     return StudentRegistration.valid_objects().filter(
         section__parent_class__parent_program=prog,
         relationship__name='Enrolled').values_list(
             'user').distinct().count()
    def getSchedule(program, student):

        schedule = u"""
Student schedule for %s:

 Time               | Class                   | Room""" % student.name()


        regs = StudentRegistration.valid_objects().filter(user=student, section__parent_class__parent_program=program, relationship__name='Accepted')
        classes = [x.section.parent_class for x in regs]

        # now we sort them by time/title
        classes.sort()

        for cls in classes:
            rooms = cls.prettyrooms()
            if len(rooms) == 0:
                rooms = u'N/A'
            else:
                rooms = u", ".join(rooms)

            schedule += u"""
%s|%s|%s""" % (u",".join(cls.friendly_times()).ljust(20),
               cls.title.ljust(25),
               rooms)

        return schedule
 def num_users_enrolled(self, prog):
     # Querying for SRs and then extracting the users saves us joining the
     # users table.
     return StudentRegistration.valid_objects().filter(
         section__parent_class__parent_program=prog,
         relationship__name='Enrolled'
     ).values_list('user').distinct().count()
示例#14
0
def lsr_submit_HSSP(request, program, priority_limit, data):  # temporary function. will merge the two later -jmoldow 05/31

    classes_flagged = [set() for i in range(0,priority_limit+1)] # 1-indexed
    sections_by_block = [defaultdict(set) for i in range(0,priority_limit+1)] # 1-indexed - sections_by_block[i][block] is a set of classes that were given priority i in timeblock block. This should hopefully be a set of size 0 or 1.

    for section_id, (priority, block_id) in data.iteritems():
        section_id = int(section_id)
        priority = int(priority)
        block_id = int(block_id)
        classes_flagged[0].add(section_id)
        classes_flagged[priority].add(section_id)
        sections_by_block[priority][block_id].add(section_id)

    errors = []

    for i in range(1, priority_limit+1):
        for block in sections_by_block[i].keys():
            if len(sections_by_block[i][block]) > 1:
                errors.append({"text": "Can't flag two classes with the same priority at the same time!", "cls_sections": list(sections_by_block[i][block]), "block": block, "priority": i, "doubled_priority": True})

    if len(errors):
        return HttpResponse(json.dumps(errors), content_type='application/json')

    reg_priority = [(None,None)] + [RegistrationType.objects.get_or_create(name="Priority/"+str(i), category="student") for i in range(1,priority_limit+1)]
    reg_priority = [reg_priority[i][0] for i in range(0, priority_limit+1)]

    allStudentRegistrations = StudentRegistration.valid_objects().filter(section__parent_class__parent_program=program, user=request.user)
    oldRegistrations = [] #[[] for i in range(0, priority_limit+1)] # 1-indexed for priority registrations, the 0-index is for interested registrations

    for i in range(1, priority_limit+1):
        oldRegistrations += [(oldRegistration, i) for oldRegistration in list(allStudentRegistrations.filter(relationship=reg_priority[i]))]

    for (oldRegistration, priority) in oldRegistrations:
        if oldRegistration.section.id not in classes_flagged[0]:
            oldRegistration.expire()
            continue
        for i in range(1, priority_limit + 1):
            if oldRegistration.section.id in classes_flagged[i]:
                if i != priority:
                    oldRegistration.expire()
                elif i == priority:
                    classes_flagged[i].remove(oldRegistration.section.id)
                    classes_flagged[0].remove(oldRegistration.section.id)
                break

    flagworthy_sections = [None] + [ClassSection.objects.filter(id__in=classes_flagged[i]).annotate(first_block=Min('meeting_times__start')) for i in range(1, priority_limit + 1)]

    for i in range(1, priority_limit + 1):
        for s in list(flagworthy_sections[i]):
            if not s.preregister_student(request.user, prereg_verb=reg_priority[i].name, overridefull=True):
                errors.append({"text": "Unable to add flagged class", "cls_sections": [s.id], "emailcode": s.emailcode(), "block": s.first_block, "flagged": True, "priority": i, "doubled_priority": False})

    if len(errors) != 0:
        s = StringIO()
        pprint(errors, s)
        mail_admins('Error in class reg', s.getvalue(), fail_silently=True)

    return HttpResponse(json.dumps(errors), content_type='application/json')
示例#15
0
def lsr_submit_HSSP(request, program, priority_limit, data):  # temporary function. will merge the two later -jmoldow 05/31
    
    classes_flagged = [set() for i in range(0,priority_limit+1)] # 1-indexed
    sections_by_block = [defaultdict(set) for i in range(0,priority_limit+1)] # 1-indexed - sections_by_block[i][block] is a set of classes that were given priority i in timeblock block. This should hopefully be a set of size 0 or 1.
    
    for section_id, (priority, block_id) in data.iteritems():
        section_id = int(section_id)
        priority = int(priority)
        block_id = int(block_id)
        classes_flagged[0].add(section_id)
        classes_flagged[priority].add(section_id)
        sections_by_block[priority][block_id].add(section_id)

    errors = []
    
    for i in range(1, priority_limit+1):
        for block in sections_by_block[i].keys():
            if len(sections_by_block[i][block]) > 1:
                errors.append({"text": "Can't flag two classes with the same priority at the same time!", "cls_sections": list(sections_by_block[i][block]), "block": block, "priority": i, "doubled_priority": True})
    
    if len(errors): 
        return HttpResponse(json.dumps(errors), mimetype='application/json')

    reg_priority = [(None,None)] + [RegistrationType.objects.get_or_create(name="Priority/"+str(i), category="student") for i in range(1,priority_limit+1)]
    reg_priority = [reg_priority[i][0] for i in range(0, priority_limit+1)] 
    
    allStudentRegistrations = StudentRegistration.valid_objects().filter(section__parent_class__parent_program=program, user=request.user)
    oldRegistrations = [] #[[] for i in range(0, priority_limit+1)] # 1-indexed for priority registrations, the 0-index is for interested registrations
    
    for i in range(1, priority_limit+1):
        oldRegistrations += [(oldRegistration, i) for oldRegistration in list(allStudentRegistrations.filter(relationship=reg_priority[i]).select_related(depth=3))]
    
    for (oldRegistration, priority) in oldRegistrations:
        if oldRegistration.section.id not in classes_flagged[0]:
            oldRegistration.expire()
            continue
        for i in range(1, priority_limit + 1):
            if oldRegistration.section.id in classes_flagged[i]:
                if i != priority:
                    oldRegistration.expire()
                elif i == priority:
                    classes_flagged[i].remove(oldRegistration.section.id)
                    classes_flagged[0].remove(oldRegistration.section.id)
                break
    
    flagworthy_sections = [None] + [ClassSection.objects.filter(id__in=classes_flagged[i]).select_related(depth=2).annotate(first_block=Min('meeting_times__start')) for i in range(1, priority_limit + 1)]
    
    for i in range(1, priority_limit + 1):
        for s in list(flagworthy_sections[i]):
            if not s.preregister_student(request.user, prereg_verb=reg_priority[i].name, overridefull=True):
                errors.append({"text": "Unable to add flagged class", "cls_sections": [s.id], "emailcode": s.emailcode(), "block": s.first_block, "flagged": True, "priority": i, "doubled_priority": False})

    if len(errors) != 0:
        s = StringIO()
        pprint(errors, s)
        mail_admins('Error in class reg', s.getvalue(), fail_silently=True)

    return HttpResponse(json.dumps(errors), mimetype='application/json')
示例#16
0
 def enrollment_status(self, request, tl, one, two, module, extra, prog):
     resp = HttpResponse(mimetype='application/json')
     data = StudentRegistration.valid_objects().filter(
         section__status__gt=0,
         section__parent_class__status__gt=0,
         section__parent_class__parent_program=prog,
         relationship__name='Enrolled').values_list('user__id',
                                                    'section__id')
     simplejson.dump(list(data), resp)
     return resp
 def load_data(self):
     lunch_registrations = list(StudentRegistration.valid_objects().filter(
         user=self.user,
         section__parent_class__category__category='Lunch',
         section__parent_class__parent_program=self.program))
     if len(lunch_registrations) > 0:
         section = lunch_registrations[0].section
         if len(section.get_meeting_times()) > 0:
             print 'Set initial to %s' % section.get_meeting_times()[0]
             self.initial['timeslot'] = section.get_meeting_times()[0].id
 def lottery_preferences_usepriority(self, request, prog):
     sections = list(prog.sections().values('id'))
     for i in range(1, prog.priorityLimit()+1, 1):
         priority_name = 'Priority/' + str(i)
         sections_priority = StudentRegistration.valid_objects().filter(relationship__name=priority_name, user=request.user, section__parent_class__parent_program=prog).select_related('section__id').values_list('section__id', flat=True).distinct()
         for item in sections:
             if item['id'] in sections_priority:
                 item[priority_name] = True
             #else:
             #   item['lottery_priority'] = False
     return {'sections': sections}
示例#19
0
 def num_users_with_lottery(self, prog):
     # Past empirical observation has shown that doing the union in SQL is
     # much, much slower for unknown reasons; it also means we would have to
     # query over the users table, so this saves us joining that table.
     users_with_ssis = set(StudentSubjectInterest.valid_objects().filter(
         subject__parent_program=prog).values_list('user').distinct())
     users_with_srs = set(StudentRegistration.valid_objects().filter(
         Q(relationship__name='Interested')
         | Q(relationship__name__contains='Priority/'),
         section__parent_class__parent_program=prog).values_list(
             'user').distinct())
     return len(users_with_ssis | users_with_srs)
示例#20
0
    def review_students(self, request, tl, one, two, module, extra, prog):
        """ Show a roster of the students in the class, allowing the administrators
        to accept students into the program based on the teachers' reviews and the
        students' applications. """

        try:
            cls = ClassSubject.objects.get(id=extra)
        except ClassSubject.DoesNotExist:
            raise ESPError(False), 'Cannot find class.'

        if not request.user.canEdit(cls):
            raise ESPError(False), 'You cannot edit class "%s"' % cls

        #   Fetch any student even remotely related to the class.
        students_dict = cls.students_dict()
        students = []
        for key in students_dict:
            students += students_dict[key]

        students = filter(
            lambda x: x.studentapplication_set.filter(program=self.program).
            count() > 0, students)

        for student in students:
            student.added_class = student.studentregistration_set.filter(
                section__parent_class=cls)[0].start_date
            try:
                student.app = student.studentapplication_set.get(
                    program=self.program)
            except:
                student.app = None

            if student.app:
                reviews = student.app.reviews.all()
            else:
                reviews = []

            if StudentRegistration.valid_objects().filter(
                    user=student,
                    section__parent_class=cls,
                    relationship__name='Accepted').count() > 0:
                student.status = 'Accepted'
            else:
                student.status = 'Not accepted'

        students = list(students)
        students.sort(key=lambda x: x.last_name)

        return render_to_response(self.baseDir() + 'roster.html', request, {
            'class': cls,
            'students': students,
            'program': prog
        })
示例#21
0
    def unenroll_status(prog):
        """
        Assemble the data necessary to compute the set of enrollments to
        expire for a given combination of student first class times
        and section start times.

        Returns:
        enrollments: { enrollment id -> (user id, section id) }
        student_timeslots: { user id -> event id of first class timeslot }
        section_timeslots: { section id -> event id of first timeslot }

        """
        enrolled = RegistrationType.objects.get(name='Enrolled')

        sections = prog.sections().filter(
            status__gt=0, parent_class__status__gt=0)
        sections = sections.exclude(
            parent_class__category__category='Lunch')

        enrollments = StudentRegistration.valid_objects().filter(
            relationship=enrolled, section__in=sections)

        # students not checked in
        students = ESPUser.objects.filter(
            id__in=enrollments.values('user'))
        students = students.exclude(
            record__program=prog, record__event='attended')

        # enrollments for those students
        relevant = enrollments.filter(user__in=students).values_list(
            'id', 'user', 'section', 'section__meeting_times')
        relevant = relevant.order_by('section__meeting_times__start')

        section_timeslots = {}  # section -> starting timeslot id
        student_timeslots = {}  # student -> starting timeslot id
        enrollments = {}        # id -> (student, section)
        for id, student, section, ts in relevant:
            if ts is None:
                continue

            if section not in section_timeslots:
                section_timeslots[section] = ts

            if student not in student_timeslots:
                student_timeslots[student] = ts

            enrollments[id] = (student, section)

        return {
            'section_timeslots': section_timeslots,
            'student_timeslots': student_timeslots,
            'enrollments': enrollments
        }
    def catalog_registered_classes_json(self, request, tl, one, two, module, extra, prog, timeslot=None):
        reg_bits = StudentRegistration.valid_objects().filter(user=request.user, section__parent_class__parent_program=prog).select_related()

        reg_bits_data = [
            { 'user': b.user.username,
              'section_id': b.section_id,
              'type': b.relationship.name
              }
            for b in reg_bits ]

        resp = HttpResponse(content_type='application/json')
        json.dump(reg_bits_data, resp)
        return resp
示例#23
0
 def load_data(self):
     lunch_registrations = StudentRegistration.valid_objects().filter(
         user=self.user,
         section__parent_class__category__category='Lunch',
         section__parent_class__parent_program=self.program).select_related(
             'section').prefetch_related('section__meeting_times')
     lunch_registrations = [
         lunch_registration for lunch_registration in lunch_registrations
         if list(lunch_registration.section.meeting_times.all())
         [0].start.day == self.day.day
     ]
     if len(lunch_registrations) > 0:
         section = lunch_registrations[0].section
         if len(section.get_meeting_times()) > 0:
             self.initial['timeslot'] = section.get_meeting_times()[0].id
示例#24
0
 def lottery_preferences_usepriority(self, request, prog):
     sections = list(prog.sections().values('id'))
     for i in range(1, prog.priorityLimit() + 1, 1):
         priority_name = 'Priority/' + str(i)
         sections_priority = StudentRegistration.valid_objects().filter(
             relationship__name=priority_name,
             user=request.user,
             section__parent_class__parent_program=prog).select_related(
                 'section__id').values_list('section__id',
                                            flat=True).distinct()
         for item in sections:
             if item['id'] in sections_priority:
                 item[priority_name] = True
             #else:
             #   item['lottery_priority'] = False
     return {'sections': sections}
 def num_users_with_lottery(self, prog):
     # Past empirical observation has shown that doing the union in SQL is
     # much, much slower for unknown reasons; it also means we would have to
     # query over the users table, so this saves us joining that table.
     users_with_ssis = set(
         StudentSubjectInterest.valid_objects()
         .filter(subject__parent_program=prog)
         .values_list('user').distinct())
     users_with_srs = set(
         StudentRegistration.valid_objects()
         .filter(
             Q(relationship__name='Interested') |
             Q(relationship__name__contains='Priority/'),
             section__parent_class__parent_program=prog)
         .values_list('user').distinct())
     return len(users_with_ssis | users_with_srs)
    def review_students(self, request, tl, one, two, module, extra, prog):
        """ Show a roster of the students in the class, allowing the administrators
        to accept students into the program based on the teachers' reviews and the
        students' applications. """

        try:
            cls = ClassSubject.objects.get(id = extra)
        except ClassSubject.DoesNotExist:
            raise ESPError('Cannot find class.', log=False)

        if not request.user.canEdit(cls):
            raise ESPError('You cannot edit class "%s"' % cls, log=False)

        #   Fetch any student even remotely related to the class.
        students_dict = cls.students_dict()
        students = []
        for key in students_dict:
            students += students_dict[key]

        students = filter(lambda x: x.studentapplication_set.filter(program=self.program).count() > 0, students)

        for student in students:
            student.added_class = student.studentregistration_set.filter(section__parent_class=cls)[0].start_date
            try:
                student.app = student.studentapplication_set.get(program = self.program)
            except:
                student.app = None

            if student.app:
                reviews = student.app.reviews.all()
            else:
                reviews = []

            if StudentRegistration.valid_objects().filter(user=student, section__parent_class=cls, relationship__name='Accepted').count() > 0:
                student.status = 'Accepted'
            else:
                student.status = 'Not accepted'

        students = list(students)
        students.sort(key=lambda x: x.last_name)

        return render_to_response(self.baseDir()+'roster.html',
                                  request,
                                  {'class': cls,
                                   'students':students, 'program': prog})
示例#27
0
    def catalog_registered_classes_json(self,
                                        request,
                                        tl,
                                        one,
                                        two,
                                        module,
                                        extra,
                                        prog,
                                        timeslot=None):
        reg_bits = StudentRegistration.valid_objects().filter(
            user=request.user,
            section__parent_class__parent_program=prog).select_related()

        reg_bits_data = [{
            'user': b.user.username,
            'section_id': b.section_id,
            'type': b.relationship.name
        } for b in reg_bits]

        resp = HttpResponse(content_type='application/json')
        json.dump(reg_bits_data, resp)
        return resp
 def num_prefs(self, prog):
     num_srs = StudentRegistration.valid_objects().filter(
         section__parent_class__parent_program=prog).count()
     return num_srs + self.num_ssis(prog)
    def studentreg2phase(self, request, tl, one, two, module, extra, prog):
        """
        Serves the two-phase student reg page. This page includes instructions
        for registration, and links to the phase1/phase2 sub-pages.
        """

        timeslot_dict = {}
        # Populate the timeslot dictionary with the priority to class title
        # mappings for each timeslot.
        priority_regs = StudentRegistration.valid_objects().filter(
            user=request.user, relationship__name__startswith='Priority')
        priority_regs = priority_regs.select_related(
            'relationship', 'section', 'section__parent_class')
        for student_reg in priority_regs:
            rel = student_reg.relationship
            title = student_reg.section.parent_class.title
            sec = student_reg.section
            times = sec.meeting_times.all().order_by('start')
            if times.count() == 0:
                continue
            timeslot = times[0].id
            if not timeslot in timeslot_dict:
                timeslot_dict[timeslot] = {rel: title}
            else:
                timeslot_dict[timeslot][rel] = title

        star_counts = {}
        interests = StudentSubjectInterest.valid_objects().filter(
            user=request.user, subject__parent_program=prog)
        interests = interests.select_related(
            'subject').prefetch_related('subject__sections__meeting_times')
        for interest in interests:
            cls = interest.subject
            for sec in cls.sections.all():
                times = sec.meeting_times.all()
                if len(times) == 0:
                    continue
                timeslot = min(times, key=lambda t: t.start).id
                if not timeslot in star_counts:
                    star_counts[timeslot] = 1
                else:
                    star_counts[timeslot] += 1

        # Iterate through timeslots and create a list of tuples of information
        prevTimeSlot = None
        blockCount = 0
        schedule = []
        timeslots = prog.getTimeSlots(types=['Class Time Block', 'Compulsory'])
        for i in range(len(timeslots)):
            timeslot = timeslots[i]
            if prevTimeSlot != None:
                if not Event.contiguous(prevTimeSlot, timeslot):
                    blockCount += 1

            if timeslot.id in timeslot_dict:
                priority_dict = timeslot_dict[timeslot.id]
                priority_list = sorted(priority_dict.items())
            else:
                priority_list = []
            if timeslot.id in star_counts:
                priority_list.append((
                    'Starred', "(%d classes)" % star_counts[timeslot.id]))
            schedule.append((timeslot, priority_list, blockCount + 1))

            prevTimeSlot = timeslot

        context = {}
        context['timeslots'] = schedule

        return render_to_response(
            self.baseDir()+'studentregtwophase.html', request, context)
# lunch randomly for users with both lunch blocks free.

from script_setup import *

import random

from esp.cal.models import Event
from esp.program.models import Program, StudentRegistration, RegistrationType
from esp.program.models.class_ import ClassSection
from esp.users.models import ESPUser

program = Program.objects.get(id=115)  # Change me! (Splash 2014)
relationship = RegistrationType.objects.get(name='Enrolled')

srs = StudentRegistration.valid_objects().filter(
    section__parent_class__parent_program=program,
    relationship=relationship)

srs_pairs = srs.values_list('user', 'section')

users = ESPUser.objects.filter(id__in=srs.values_list('user'))
sections = ClassSection.objects.filter(
    parent_class__parent_program=program
).prefetch_related('meeting_times')
timeblocks = Event.objects.filter(
    program=program, event_type__description='Class Time Block')

users_by_id = {user.id: user for user in users}
sections_by_id = {section.id: section for section in sections}
timeblocks_by_id = {timeblock.id: timeblock for timeblock in timeblocks}
sections_by_user_timeblock = {
示例#31
0
    def review_student(self, request, tl, one, two, module, extra, prog):
        scrmi = prog.studentclassregmoduleinfo
        reg_nodes = scrmi.reg_verbs()

        try:
            cls = ClassSubject.objects.get(id = extra)
        except ClassSubject.DoesNotExist:
            raise ESPError('Cannot find class.', log=False)

        if not request.user.canEdit(cls):
            raise ESPError('You cannot edit class "%s"' % cls, log=False)

        student = request.GET.get('student',None)
        if not student:
            student = request.POST.get('student','')

        try:
            student = ESPUser.objects.get(id = int(student))
        except ESPUser.DoesNotExist:
            raise ESPError('Cannot find student, %s' % student, log=False)

        not_registered = not StudentRegistration.valid_objects().filter(section__parent_class = cls, user = student).exists()
        if not_registered:
            raise ESPError('Student not a student of this class.', log=False)

        try:
            student.app = student.studentapplication_set.get(program = self.program)
        except:
            student.app = None
            raise ESPError('Error: Student did not start an application.', log=False)

        student.added_class = StudentRegistration.valid_objects().filter(section__parent_class = cls, user = student)[0].start_date

        teacher_reviews = student.app.reviews.all().filter(reviewer=request.user)
        if teacher_reviews.count() > 0:
            this_review = teacher_reviews.order_by('id')[0]
        else:
            this_review = StudentAppReview(reviewer=request.user)
            this_review.save()
            student.app.reviews.add(this_review)

        if request.method == 'POST':
            form = this_review.get_form(request.POST)
            if form.is_valid():
                form.target.update(form)
                if 'submit_next' in request.POST or 'submit_return' in request.POST:
                    url = '/%s/%s/%s/review_students/%s/' % (tl, one, two, extra)
                    if 'submit_next' in request.POST:
                        url += '?prev=%s' % student.id
                    from django.shortcuts import redirect
                    return redirect(url) # self.review_students(request, tl, one, two, module, extra, prog)


        else:
            form = this_review.get_form()

        return render_to_response(self.baseDir()+'review.html',
                                  request,
                                  {'class': cls,
                                   'reviews': teacher_reviews,
                                  'program': prog,
                                   'student':student,
                                   'form': form})
示例#32
0
    def studentreg2phase(self, request, tl, one, two, module, extra, prog):
        """
        Serves the two-phase student reg page. This page includes instructions
        for registration, and links to the phase1/phase2 sub-pages.
        """

        context = {}
        timeslot_dict = {}
        # Populate the timeslot dictionary with the priority to class title
        # mappings for each timeslot.
        priority_regs = StudentRegistration.valid_objects().filter(
            user=request.user, relationship__name__startswith='Priority')
        priority_regs = priority_regs.select_related('relationship', 'section',
                                                     'section__parent_class')
        for student_reg in priority_regs:
            rel = student_reg.relationship
            title = student_reg.section.parent_class.title
            sec = student_reg.section
            times = sec.meeting_times.all().order_by('start')
            if times.count() == 0:
                continue
            timeslot = times[0].id
            if not timeslot in timeslot_dict:
                timeslot_dict[timeslot] = {rel: title}
            else:
                timeslot_dict[timeslot][rel] = title

        star_counts = {}
        interests = StudentSubjectInterest.valid_objects().filter(
            user=request.user, subject__parent_program=prog)
        interests = interests.select_related('subject').prefetch_related(
            'subject__sections__meeting_times')
        for interest in interests:
            cls = interest.subject
            for sec in cls.sections.all():
                times = sec.meeting_times.all()
                if len(times) == 0:
                    continue
                timeslot = min(times, key=lambda t: t.start).id
                if not timeslot in star_counts:
                    star_counts[timeslot] = 1
                else:
                    star_counts[timeslot] += 1

        # Iterate through timeslots and create a list of tuples of information
        prevTimeSlot = None
        blockCount = 0
        schedule = []
        timeslots = prog.getTimeSlots(types=['Class Time Block', 'Compulsory'])

        context['num_priority'] = prog.priorityLimit()
        context['num_star'] = Tag.getProgramTag("num_stars",
                                                program=prog,
                                                default=10)

        for i in range(len(timeslots)):
            timeslot = timeslots[i]
            if prevTimeSlot != None:
                if not Event.contiguous(prevTimeSlot, timeslot):
                    blockCount += 1

            if timeslot.id in timeslot_dict:
                priority_dict = timeslot_dict[timeslot.id]
                # (relationship, class_title) -> relationship.name
                priority_list = sorted(priority_dict.items(),
                                       key=lambda item: item[0].name)
            else:
                priority_list = []
            temp_list = []
            for i in range(0, context['num_priority']):
                if i < len(priority_list):
                    temp_list.append(
                        ("Priority " + str(i + 1), priority_list[i][1]))
                else:
                    temp_list.append(("Priority " + str(i + 1), ""))
            priority_list = temp_list
            star_count = 0
            if timeslot.id in star_counts:
                star_count = star_counts[timeslot.id]
            schedule.append(
                (timeslot, priority_list, blockCount + 1, star_count,
                 float(star_count) / context['num_star'] * 100))

            prevTimeSlot = timeslot

        context['timeslots'] = schedule

        return render_to_response(self.baseDir() + 'studentregtwophase.html',
                                  request, context)
示例#33
0
 def num_prefs(self, prog):
     num_srs = StudentRegistration.valid_objects().filter(
         section__parent_class__parent_program=prog).count()
     return num_srs + self.num_ssis(prog)
 def num_priority1s(self, prog):
     return StudentRegistration.valid_objects().filter(
         relationship__name='Priority/1',
         section__parent_class__parent_program=prog).count()
示例#35
0
    def initialize(self):
        """ Gather all of the information needed to run the lottery assignment.
            This includes:
            -   Students' interest (priority and interested bits)
            -   Class schedules and capacities
            -   Timeslots (incl. lunch periods for each day)
        """

        self.interest = numpy.zeros((self.num_students, self.num_sections), dtype=numpy.bool)
        self.priority = [numpy.zeros((self.num_students, self.num_sections), dtype=numpy.bool) for i in range(self.effective_priority_limit+1)]
        self.ranks = 10*numpy.ones((self.num_students, self.num_sections), dtype=numpy.int32)
        self.section_schedules = numpy.zeros((self.num_sections, self.num_timeslots), dtype=numpy.bool)
        self.section_start_schedules = numpy.zeros((self.num_sections, self.num_timeslots), dtype=numpy.bool)
        self.section_capacities = numpy.zeros((self.num_sections,), dtype=numpy.uint32)
        self.section_overlap = numpy.zeros((self.num_sections, self.num_sections), dtype=numpy.bool)

        # One array to keep track of the utility of each student
        # (defined as hours of interested class + 1.5*hours of priority classes)
        # and the other arrary to keep track of student weigths (defined as # of classes signed up for)
        self.student_utility_weights = numpy.zeros((self.num_students, ), dtype=numpy.float)
        self.student_utilities = numpy.zeros((self.num_students, ), dtype=numpy.float)

        #   Get student, section, timeslot IDs and prepare lookup table
        (self.student_ids, self.student_indices) = self.get_ids_and_indices(self.lotteried_students)
        (self.section_ids, self.section_indices) = self.get_ids_and_indices(self.sections)
        (self.timeslot_ids, self.timeslot_indices) = self.get_ids_and_indices(self.timeslots)
        self.parent_classes = numpy.array(self.sections.values_list('parent_class__id', flat=True))

        #   Get IDs of timeslots allocated to lunch by day
        #   (note: requires that this is constant across days)
        self.lunch_schedule = numpy.zeros((self.num_timeslots,))
        lunch_timeslots = Event.objects.filter(meeting_times__parent_class__parent_program=self.program, meeting_times__parent_class__category__category='Lunch').order_by('start').distinct()
        #   Note: this code should not be necessary once lunch-constraints branch is merged (provides Program.dates())
        dates = []
        for ts in self.timeslots:
            ts_day = date(ts.start.year, ts.start.month, ts.start.day)
            if ts_day not in dates:
                dates.append(ts_day)
        lunch_by_day = [[] for x in dates]
        ts_count = 0
        for ts in lunch_timeslots:
            d = date(ts.start.year, ts.start.month, ts.start.day)
            lunch_by_day[dates.index(d)].append(ts.id)
            self.lunch_schedule[self.timeslot_indices[ts.id]] = True
        self.lunch_timeslots = numpy.array(lunch_by_day)

        #   Populate interest matrix; this uses both the StudentRegistrations (which apply to a particular section) and StudentSubjectIntegests (which apply to all sections of the class).  If one does not exist, ignore it.  Be careful to only return SRs and SSIs for accepted sections of accepted classes; this might matter for SSIs where only some sections of the class are accepted.
        interest_regs_sr = StudentRegistration.valid_objects().filter(section__parent_class__parent_program=self.program, section__status__gt=0, section__parent_class__status__gt=0, section__registration_status=0, section__meeting_times__isnull=False, relationship__name='Interested').values_list('user__id', 'section__id').distinct()
        interest_regs_ssi = StudentSubjectInterest.valid_objects().filter(subject__parent_program=self.program, subject__status__gt=0, subject__sections__status__gt=0, subject__sections__registration_status=0, subject__sections__meeting_times__isnull=False).values_list('user__id', 'subject__sections__id').distinct()
        self.put_prefs_in_array(interest_regs_sr, self.interest)
        self.put_prefs_in_array(interest_regs_ssi, self.interest)

        #   Populate priority matrix
        priority_regs = [StudentRegistration.valid_objects().filter(section__parent_class__parent_program=self.program, relationship__name='Priority/%s'%i).values_list('user__id', 'section__id').distinct() for i in range(self.real_priority_limit+1)]
        if self.grade_range_exceptions:
            priority_regs.append(StudentRegistration.valid_objects().filter(section__parent_class__parent_program=self.program, relationship__name='GradeRangeException').values_list('user__id', 'section__id').distinct())
        for i in range(1,self.effective_priority_limit+1):
            self.put_prefs_in_array(priority_regs[i], self.priority[i])
        if self.options['use_student_apps']:
            for i in range(1,self.effective_priority_limit+1):
                for (student_id,section_id) in priority_regs[i]:
                    self.ranks[self.student_indices[student_id],self.section_indices[section_id]] = ESPUser.getRankInClass(student_id,self.parent_classes[self.section_indices[section_id]])
            for (student_id,section_id) in interest_regs_sr + interest_regs_ssi:
                self.ranks[self.student_indices[student_id],self.section_indices[section_id]] = ESPUser.getRankInClass(student_id,self.parent_classes[self.section_indices[section_id]])


        #   Set student utility weights. Counts number of classes that students selected. Used only for computing the overall_utility stat
        self.student_utility_weights = numpy.sum(self.interest.astype(float), 1) + sum([numpy.sum(self.priority[i].astype(float), 1) for i in range(1,self.effective_priority_limit+1)])

        #   Populate section schedule
        section_times = numpy.array(self.sections.values_list('id', 'meeting_times__id'))
        start_times = numpy.array(self.sections.annotate(start_time=Min('meeting_times')).values_list('id','start_time'))
        self.section_schedules[self.section_indices[section_times[:, 0]], self.timeslot_indices[section_times[:, 1]]] = True
        self.section_start_schedules[self.section_indices[start_times[:, 0]], self.timeslot_indices[start_times[:, 1]]] = True

        #   Populate section overlap matrix
        for i in range(self.num_sections):
            group_ids = numpy.nonzero(self.parent_classes == self.parent_classes[i])[0]
            self.section_overlap[numpy.meshgrid(group_ids, group_ids)] = True

        #   Populate section grade limits
        self.section_grade_min = numpy.array(self.sections.values_list('parent_class__grade_min', flat=True), dtype=numpy.uint32)
        self.section_grade_max = numpy.array(self.sections.values_list('parent_class__grade_max', flat=True), dtype=numpy.uint32)

        #   Populate student grades; grade will be assumed to be 0 if not entered on profile
        self.student_grades = numpy.zeros((self.num_students,))
        gradyear_pairs = numpy.array(RegistrationProfile.objects.filter(user__id__in=list(self.student_ids), most_recent_profile=True, student_info__graduation_year__isnull=False).values_list('user__id', 'student_info__graduation_year'), dtype=numpy.uint32)
        self.student_grades[self.student_indices[gradyear_pairs[:, 0]]] = 12 + ESPUser.program_schoolyear(self.program) - gradyear_pairs[:, 1]

        #   Find section capacities (TODO: convert to single query)
        for sec in self.sections:
            self.section_capacities[self.section_indices[sec.id]] = sec.capacity

        # Populate section lengths (hours)
        self.section_lengths = numpy.array([x.nonzero()[0].size for x in self.section_schedules])

        if self.options['fill_low_priorities']:
            #   Compute who has a priority when.  Includes lower priorities, since this is used for places where we check not clobbering priorities.
            self.has_priority = [numpy.zeros((self.num_students, self.num_timeslots), dtype=numpy.bool) for i in range(self.effective_priority_limit+1)]
            for i in range(1,self.effective_priority_limit+1):
                priority_at_least_i = reduce(operator.or_,[self.priority[j] for j in range(i,self.effective_priority_limit+1)])
                numpy.dot(priority_at_least_i,self.section_schedules,out=self.has_priority[i])

            self.sections_at_same_time = numpy.dot(self.section_schedules, numpy.transpose(self.section_schedules))

            #   And the same, overlappingly.
            self.has_overlapping_priority = [numpy.zeros((self.num_students, self.num_timeslots), dtype=numpy.bool) for i in range(self.effective_priority_limit+1)]
            for i in range(1,self.effective_priority_limit+1):
                priority_at_least_i = reduce(operator.or_,[self.priority[j] for j in range(i,self.effective_priority_limit+1)])
                numpy.dot(numpy.dot(priority_at_least_i,self.sections_at_same_time),self.section_schedules,out=self.has_overlapping_priority[i])

            #   Fill in preferences for students who haven't ranked them.  In particular, if a student has ranked some level of class in a timeblock (i.e. they plan to be at Splash that timeblock), but has not ranked any priority/n or lower-priority classes overlapping it, add a random class from their interesteds.

            for i in range(1,self.real_priority_limit+1): #Use self.real_priority_limit since we don't want to give people free grade range exceptions!
                should_fill = numpy.transpose(numpy.nonzero(self.has_priority[1]&~self.has_overlapping_priority[i]))
                if len(should_fill):
                    for student, timeslot in should_fill:
                        # student is interested, and class starts in this timeslot, and class does not overlap any lower or equal priorities
                        possible_classes = numpy.nonzero(self.interest[student] & self.section_start_schedules[:,timeslot] & ~numpy.dot(self.section_schedules, numpy.transpose(self.has_priority[i][student])))[0]
                        if len(possible_classes):
                            choice = numpy.random.choice(possible_classes)
                            self.priority[i][student,choice]=True
示例#36
0
 def get_regdate(self, ordering='start_date'):
     regs = StudentRegistration.valid_objects().filter(user=self.user, section__parent_class__parent_program=self.program, relationship__name='Enrolled')
     if regs.exists():
         return regs.order_by(ordering).values_list('start_date', flat=True)[0].strftime("%Y-%m-%d %H:%M:%S")
from django.db.models.aggregates import Min

parser = argparse.ArgumentParser(description='Unenroll missing students from classes.')
parser.add_argument('program_id', type=int, help='ID of the current program')
parser.add_argument('--per-hour', dest='per_hour', action='store_true', help='Include this argument to clear registrations only for classes starting in the next 60 minutes.')

args = parser.parse_args()

enrolled = RegistrationType.objects.get(name='Enrolled')

prog = Program.objects.get(id=args.program_id)
relevant_sections = prog.sections().annotate(begin_time=Min("meeting_times__start")).filter(status=10, parent_class__status=10).exclude(parent_class__category__category='Lunch')
# classes that started more than 60 minutes ago
passed_sections = relevant_sections.filter(begin_time__lt=datetime.now() - timedelta(minutes=60))
# students who are enrolled in a class that started more than 60 minutes ago, who have not checked in
students = ESPUser.objects.filter(studentregistration__in=StudentRegistration.valid_objects(), studentregistration__relationship=enrolled, studentregistration__section__in=passed_sections).distinct().exclude(record__program=prog, record__event='attended')
# classes that start in the next 60 minutes
upcoming_sections = relevant_sections.filter(begin_time__gt=datetime.now())
if args.per_hour:
    upcoming_sections = upcoming_sections.filter(begin_time__lt=datetime.now() + timedelta(minutes=60))

# registrations of missing students for upcoming classes
registrations = StudentRegistration.valid_objects().filter(user__in=students, section__in=upcoming_sections, relationship=enrolled)
print "Candidate Registrations to Delete:", len(registrations)
print registrations
cmd_str = raw_input("Would you like to delete these registrations [y/N]? --> ")
if cmd_str.strip().lower() == 'y':
    registrations.update(end_date=datetime.now())
    print 'Expired:', registrations
else:
    print 'Action cancelled.'
示例#38
0
    def classchangerequest(self, request, tl, one, two, module, extra, prog):
        timeslots = prog.getTimeSlots()
        sections = prog.sections().filter(
            status=10, meeting_times__isnull=False).distinct()

        enrollments = {}
        for timeslot in timeslots:
            try:
                enrollments[timeslot] = ClassSubject.objects.get(
                    nest_Q(StudentRegistration.is_valid_qobject(),
                           'sections__studentregistration'),
                    sections__studentregistration__relationship__name=
                    "Enrolled",
                    sections__studentregistration__user=request.user,
                    sections__meeting_times=timeslot,
                    parent_program=prog)
            except ClassSubject.DoesNotExist:
                enrollments[timeslot] = None

        context = {}
        context['timeslots'] = timeslots
        context['enrollments'] = enrollments
        context['user'] = request.user
        if 'success' in request.GET:
            context['success'] = True
        else:
            context['success'] = False

        if request.user.isStudent():
            sections_by_slot = dict([(timeslot, [
                (section, 1 == StudentRegistration.valid_objects().filter(
                    user=context['user'],
                    section=section,
                    relationship__name="Request").count())
                for section in sections
                if section.get_meeting_times()[0] == timeslot
                and section.parent_class.grade_min <= request.user.getGrade(
                    prog) <= section.parent_class.grade_max and
                section.parent_class not in enrollments.values() and ESPUser.
                getRankInClass(request.user, section.parent_class) in (5, 10)
            ]) for timeslot in timeslots])
        else:
            sections_by_slot = dict([(timeslot, [
                (section, False) for section in sections
                if section.get_meeting_times()[0] == timeslot
            ]) for timeslot in timeslots])

        fields = {}
        for i, timeslot in enumerate(sections_by_slot.keys()):
            choices = [('0', "I'm happy with my current enrollment.")]
            initial = '0'
            for section in sections_by_slot[timeslot]:
                choices.append(
                    (section[0].emailcode(),
                     section[0].emailcode() + ": " + section[0].title()))
                if section[1]:
                    initial = section[0].emailcode()
            fields['timeslot_' + str(i + 1)] = forms.ChoiceField(
                label="Timeslot " + str(i + 1) + " (" +
                timeslot.pretty_time() + ")",
                choices=choices,
                initial=initial)

        form = type('ClassChangeRequestForm', (forms.Form, ), fields)
        context['form'] = form()
        if request.method == "POST":
            old_requests = StudentRegistration.valid_objects().filter(
                user=context['user'],
                section__parent_class__parent_program=prog,
                relationship__name="Request")
            for r in old_requests:
                r.expire()
            form = form(request.POST)
            if form.is_valid():
                for value in form.cleaned_data.values():
                    section = None
                    for s in sections:
                        if s.emailcode() == value:
                            section = s
                            break
                    if not section:
                        continue
                    r = StudentRegistration.valid_objects().get_or_create(
                        user=context['user'],
                        section=section,
                        relationship=RegistrationType.objects.get_or_create(
                            name="Request", category="student")[0])[0]
                    r.save()

                return HttpResponseRedirect(
                    request.path.rstrip('/') + '/?success')
        else:
            return render_to_response(
                self.baseDir() + 'classchangerequest.html', request, context)
示例#39
0
    def initialize(self):
        """ Gather all of the information needed to run the lottery assignment.
            This includes:
            -   Students' interest (priority and interested bits)
            -   Class schedules and capacities
            -   Timeslots (incl. lunch periods for each day)
        """

        self.interest = numpy.zeros((self.num_students, self.num_sections),
                                    dtype=numpy.bool)
        self.priority = numpy.zeros((self.num_students, self.num_sections),
                                    dtype=numpy.bool)
        self.section_schedules = numpy.zeros(
            (self.num_sections, self.num_timeslots), dtype=numpy.bool)
        self.section_capacities = numpy.zeros((self.num_sections, ),
                                              dtype=numpy.uint32)
        self.section_overlap = numpy.zeros(
            (self.num_sections, self.num_sections), dtype=numpy.bool)

        # One array to keep track of the utility of each student
        # (defined as hours of interested class + 1.5*hours of priority classes)
        # and the other arrary to keep track of student weigths (defined as # of classes signed up for)
        self.student_utility_weights = numpy.zeros((self.num_students, ),
                                                   dtype=numpy.float)
        self.student_utilities = numpy.zeros((self.num_students, ),
                                             dtype=numpy.float)

        #   Get student, section, timeslot IDs and prepare lookup table
        (self.student_ids, self.student_indices) = self.get_ids_and_indices(
            self.program.students()['lotteried_students'])
        (self.section_ids, self.section_indices) = self.get_ids_and_indices(
            self.program.sections().filter(status__gt=0,
                                           registration_status=0))
        (self.timeslot_ids, self.timeslot_indices) = self.get_ids_and_indices(
            self.program.getTimeSlots())

        #   Get IDs of timeslots allocated to lunch by day
        #   (note: requires that this is constant across days)
        self.lunch_schedule = numpy.zeros((self.num_timeslots, ))
        lunch_timeslots = Event.objects.filter(
            meeting_times__parent_class__parent_program=self.program,
            meeting_times__parent_class__category__category='Lunch').order_by(
                'start').distinct()
        #   Note: this code should not be necessary once lunch-constraints branch is merged (provides Program.dates())
        dates = []
        for ts in self.program.getTimeSlots():
            ts_day = date(ts.start.year, ts.start.month, ts.start.day)
            if ts_day not in dates:
                dates.append(ts_day)
        lunch_by_day = [[] for x in dates]
        ts_count = 0
        for ts in lunch_timeslots:
            d = date(ts.start.year, ts.start.month, ts.start.day)
            lunch_by_day[dates.index(d)].append(ts.id)
            self.lunch_schedule[self.timeslot_indices[ts.id]] = True
        for i in range(len(lunch_by_day)):
            if len(lunch_by_day[i]) > ts_count:
                ts_count = len(lunch_by_day[i])
        self.lunch_timeslots = numpy.zeros((len(lunch_by_day), ts_count),
                                           dtype=numpy.int32)
        for i in range(len(lunch_by_day)):
            self.lunch_timeslots[i, :len(lunch_by_day[i])] = numpy.array(
                lunch_by_day[i])

        #   Populate interest matrix
        interest_regs = StudentRegistration.valid_objects().filter(
            section__parent_class__parent_program=self.program,
            relationship__name='Interested').values_list(
                'user__id', 'section__id').distinct()
        ira = numpy.array(interest_regs, dtype=numpy.uint32)
        self.interest[self.student_indices[ira[:, 0]],
                      self.section_indices[ira[:, 1]]] = True

        #   Populate priority matrix
        priority_regs = StudentRegistration.valid_objects().filter(
            section__parent_class__parent_program=self.program,
            relationship__name='Priority/1').values_list(
                'user__id', 'section__id').distinct()
        pra = numpy.array(priority_regs, dtype=numpy.uint32)
        self.priority[self.student_indices[pra[:, 0]],
                      self.section_indices[pra[:, 1]]] = True

        #   Set student utility weights. Counts number of classes that students selected. Used only for computing the overall_utility stat
        #   NOTE: Uses fixed (interest + priority) formula, needs attention when multiple priority levels are merged.
        self.student_utility_weights = numpy.sum(
            self.interest.astype(float), 1) + numpy.sum(
                self.priority.astype(float), 1)

        #   Populate section schedule
        section_times = numpy.array(self.program.sections().filter(
            status__gt=0, registration_status=0).filter(
                meeting_times__id__isnull=False).distinct().values_list(
                    'id', 'meeting_times__id'))
        self.section_schedules[self.section_indices[section_times[:, 0]],
                               self.timeslot_indices[section_times[:,
                                                                   1]]] = True

        #   Populate section overlap matrix
        parent_classes = numpy.array(self.program.sections().filter(
            status__gt=0, registration_status=0).order_by('id').values_list(
                'parent_class__id', flat=True))
        for i in range(self.num_sections):
            group_ids = numpy.nonzero(parent_classes == parent_classes[i])[0]
            self.section_overlap[numpy.meshgrid(group_ids, group_ids)] = True

        #   Populate section grade limits
        self.section_grade_min = numpy.array(self.program.sections().filter(
            status__gt=0, registration_status=0).order_by('id').values_list(
                'parent_class__grade_min', flat=True),
                                             dtype=numpy.uint32)
        self.section_grade_max = numpy.array(self.program.sections().filter(
            status__gt=0, registration_status=0).order_by('id').values_list(
                'parent_class__grade_max', flat=True),
                                             dtype=numpy.uint32)

        #   Populate student grades; grade will be assumed to be 0 if not entered on profile
        self.student_grades = numpy.zeros((self.num_students, ))
        gradyear_pairs = numpy.array(RegistrationProfile.objects.filter(
            user__id__in=list(self.student_ids),
            most_recent_profile=True,
            student_info__graduation_year__isnull=False).values_list(
                'user__id', 'student_info__graduation_year'),
                                     dtype=numpy.uint32)
        self.student_grades[self.student_indices[
            gradyear_pairs[:, 0]]] = 12 + ESPUser.current_schoolyear(
            ) - gradyear_pairs[:, 1]

        #   Find section capacities (TODO: convert to single query)
        for sec in self.program.sections().filter(status__gt=0,
                                                  registration_status=0):
            self.section_capacities[self.section_indices[
                sec.id]] = sec.capacity

        # Populate section lengths (hours)
        self.section_lengths = numpy.array(
            [x.nonzero()[0].size for x in self.section_schedules])
示例#40
0
args = parser.parse_args()

enrolled = RegistrationType.objects.get(name='Enrolled')

prog = Program.objects.get(id=args.program_id)
relevant_sections = prog.sections().annotate(
    begin_time=Min("meeting_times__start")).filter(
        status=10, parent_class__status=10).exclude(
            parent_class__category__category='Lunch')
# classes that started more than 60 minutes ago
passed_sections = relevant_sections.filter(begin_time__lt=datetime.now() -
                                           timedelta(minutes=60))
# students who are enrolled in a class that started more than 60 minutes ago, who have not checked in
students = ESPUser.objects.filter(
    studentregistration__in=StudentRegistration.valid_objects(),
    studentregistration__relationship=enrolled,
    studentregistration__section__in=passed_sections).distinct().exclude(
        record__program=prog, record__event='attended')
# classes that start in the next 60 minutes
upcoming_sections = relevant_sections.filter(begin_time__gt=datetime.now())
if args.per_hour:
    upcoming_sections = upcoming_sections.filter(
        begin_time__lt=datetime.now() + timedelta(minutes=60))

# registrations of missing students for upcoming classes
registrations = StudentRegistration.valid_objects().filter(
    user__in=students, section__in=upcoming_sections, relationship=enrolled)
print "Candidate Registrations to Delete:", len(registrations)
print registrations
cmd_str = raw_input("Would you like to delete these registrations [y/N]? --> ")
示例#41
0
def classchangerequest(request, tl, one, two):
    from esp.program.models import Program, StudentAppResponse, StudentRegistration, RegistrationType
    from esp.program.models.class_ import ClassSubject
    from urllib import quote
    try:
        prog = Program.by_prog_inst(one, two)  #DataTree.get_by_uri(treeItem)
    except Program.DoesNotExist:
        raise Http404("Program not found.")

    if tl != "learn":
        raise Http404

    if not request.user or not request.user.is_authenticated():
        return HttpResponseRedirect(
            '%s?%s=%s' %
            (LOGIN_URL, REDIRECT_FIELD_NAME, quote(request.get_full_path())))

    if not request.user.isStudent() and not request.user.isAdmin(prog):
        allowed_student_types = Tag.getTag("allowed_student_types",
                                           prog,
                                           default='')
        matching_user_types = any(
            x in request.user.groups.all().values_list("name", flat=True)
            for x in allowed_student_types.split(","))
        if not matching_user_types:
            return render_to_response('errors/program/notastudent.html',
                                      request, {})

    errorpage = 'errors/program/wronggrade.html'

    cur_grade = request.user.getGrade(prog)
    if (not Permission.user_has_perm(
            request.user, 'GradeOverride', program=prog)
            and (cur_grade != 0 and
                 (cur_grade < prog.grade_min or cur_grade > prog.grade_max))):
        return render_to_response(errorpage, request, {})

    setattr(request, "program", prog)
    setattr(request, "tl", tl)
    setattr(request, "module", "classchangerequest")

    from django import forms
    from datetime import datetime
    from esp.utils.scheduling import getRankInClass

    timeslots = prog.getTimeSlots()
    sections = prog.sections().filter(status=10)

    enrollments = {}
    for timeslot in timeslots:
        try:
            enrollments[timeslot] = ClassSubject.objects.get(
                nest_Q(StudentRegistration.is_valid_qobject(),
                       'sections__studentregistration'),
                sections__studentregistration__relationship__name="Enrolled",
                sections__studentregistration__user=request.user,
                sections__meeting_times=timeslot,
                parent_program=prog)
        except ClassSubject.DoesNotExist:
            enrollments[timeslot] = None

    context = {}
    context['timeslots'] = timeslots
    context['enrollments'] = enrollments
    context['user'] = request.user
    if 'success' in request.GET:
        context['success'] = True
    else:
        context['success'] = False

    if request.user.isStudent():
        sections_by_slot = dict([(timeslot, [
            (section, 1 == StudentRegistration.valid_objects().filter(
                user=context['user'],
                section=section,
                relationship__name="Request").count()) for section in sections
            if section.get_meeting_times()[0] == timeslot
            and section.parent_class.grade_min <= request.user.getGrade(
                prog) <= section.parent_class.grade_max
            and section.parent_class not in enrollments.values()
            and getRankInClass(request.user, section) in (5, 10)
        ]) for timeslot in timeslots])
    else:
        sections_by_slot = dict([(timeslot, [
            (section, False) for section in sections
            if section.get_meeting_times()[0] == timeslot
        ]) for timeslot in timeslots])

    fields = {}
    for i, timeslot in enumerate(sections_by_slot.keys()):
        choices = [('0', "I'm happy with my current enrollment.")]
        initial = '0'
        for section in sections_by_slot[timeslot]:
            choices.append(
                (section[0].emailcode(),
                 section[0].emailcode() + ": " + section[0].title()))
            if section[1]:
                initial = section[0].emailcode()
        fields['timeslot_' + str(i + 1)] = forms.ChoiceField(
            label="Timeslot " + str(i + 1) + " (" + timeslot.pretty_time() +
            ")",
            choices=choices,
            initial=initial)

    form = type('ClassChangeRequestForm', (forms.Form, ), fields)
    context['form'] = form()
    if request.method == "POST":
        old_requests = StudentRegistration.valid_objects().filter(
            user=context['user'],
            section__parent_class__parent_program=prog,
            relationship__name="Request")
        for r in old_requests:
            r.expire()
        form = form(request.POST)
        if form.is_valid():
            for value in form.cleaned_data.values():
                section = None
                for s in sections:
                    if s.emailcode() == value:
                        section = s
                        break
                if not section:
                    continue
                r = StudentRegistration.objects.get_or_create(
                    user=context['user'],
                    section=section,
                    relationship=RegistrationType.objects.get_or_create(
                        name="Request", category="student")[0])[0]
                r.end_date = datetime(9999, 1, 1, 0, 0, 0, 0)
                r.save()

            return HttpResponseRedirect(request.path.rstrip('/') + '/?success')
    else:
        return render_to_response('program/classchangerequest.html', request,
                                  context)
 def enrollment_status(self, request, tl, one, two, module, extra, prog):
     resp = HttpResponse(content_type='application/json')
     data = StudentRegistration.valid_objects().filter(section__status__gt=0, section__parent_class__status__gt=0, section__parent_class__parent_program=prog, relationship__name='Enrolled').values_list('user__id', 'section__id')
     json.dump(list(data), resp)
     return resp
    def select_students(self, request, tl, one, two, module, extra, prog):
        #   Get preregistered and enrolled students
        try:
            sec = ClassSection.objects.get(id=extra)
        except (ValueError, ClassSection.DoesNotExist):
            raise ESPError(
                'Class section not found.  If you came from a link on our site, please notify the webmasters.',
                log=False)

        students_list = sec.students_prereg()

        if request.method == 'POST':
            #   Handle form submission
            #   result_strs = []
            data = request.POST.copy()
            sections_dict = {}
            for key in data:
                key_dir = key.split('_')
                if key_dir[0] == 'regstatus' and len(key_dir) == 3:
                    student_id = int(key_dir[1])
                    sec_id = int(key_dir[2])
                    if sec_id not in sections_dict:
                        sections_dict[sec_id] = [{
                            'id': student_id,
                            'status': data[key]
                        }]
                    else:
                        sections_dict[sec_id].append({
                            'id': student_id,
                            'status': data[key]
                        })

            for sec_id in sections_dict:
                sec = ClassSection.objects.get(id=sec_id)
                sec.cache['students'] = None
                sec.cache['num_students'] = None
                for item in sections_dict[sec_id]:
                    student = ESPUser.objects.get(id=item['id'])
                    ignore = False
                    value = item['status']
                    if value == 'enroll':
                        verb_name = 'Enrolled'
                    elif value == 'reject':
                        verb_name = 'Rejected'
                    else:
                        ignore = True

                    if not ignore:
                        rel = RegistrationType.get_map(
                            include=['Enrolled', 'Rejected'],
                            category='student')[verb_name]
                        other_regs = sec.getRegistrations(student).filter(
                            relationship__name__in=['Enrolled', 'Rejected'])
                        found = False
                        for reg in other_regs:
                            if not found and reg.relationship == rel:
                                found = True
                            else:
                                reg.expire()

                        if not found:
                            new_reg = StudentRegistration(user=student,
                                                          relationship=rel,
                                                          section=sec)
                            new_reg.save()

        #   Jazz up this information a little
        #Not having much luck with query count/performance when selecting related parent_class and parent_class__category
        #Creating a lookup dict instead to strip out duplicate ClassSubject instances

        student_regs = StudentRegistration.valid_objects().filter(user__in=students_list) \
                       .order_by('start_date').select_related('section','user','relationship')
        student_regs = student_regs.filter(
            section__parent_class__parent_program=self.program)

        student_sections_dict = defaultdict(set)
        student_reg_dict = defaultdict(set)

        #need a unique set of parent_class ids
        #creating lookup dicts to avoid hitting database(was not solved with
        #select_related or prefecth_related
        parent_class_id_set = set()
        sections = set()
        for reg in student_regs:
            student_sections_dict[reg.user].add(reg.section)
            display_name = reg.relationship.displayName or reg.relationship.name
            sections.add(reg.section)
            parent_class_id_set.add(reg.section.parent_class_id)
            student_reg_dict['%i_%i' % (
                reg.user.id,
                reg.section.id,
            )].add(display_name)

        subjects = ClassSubject.objects.filter(
            id__in=parent_class_id_set).select_related('category')
        subject_categories_dict = dict([(s.id, (s, s.category))
                                        for s in subjects])

        for student in students_list:
            student.bits = student_reg_dict['%i_%i' % (
                student.id,
                sec.id,
            )]
            #this is a bit of a problem because it produces the side affect of application
            #creation if not found
            student.app = student.getApplication(self.program, False)
            student.other_classes = []
            for section in student_sections_dict[student]:
                parent_class, category = subject_categories_dict.get(
                    section.parent_class_id)
                regtypes = student_reg_dict['%i_%i' % (
                    student.id,
                    section.id,
                )]

                section_row = (section, regtypes, parent_class, category)
                student.other_classes.append(section_row)
            preregs = sec.getRegistrations(student).exclude(
                relationship__name__in=['Enrolled', 'Rejected'])

            if preregs.count() != 0:
                student.added_class = preregs[0].start_date
            if 'Enrolled' in student.bits:
                student.enrolled = True
            elif 'Rejected' in student.bits:
                student.rejected = True

        #   Detect if there is an application module

        from esp.program.modules.handlers.studentjunctionappmodule import StudentJunctionAppModule
        has_app_module = False
        for module in prog.getModules():
            if isinstance(module, StudentJunctionAppModule):
                has_app_module = True

        return render_to_response(
            self.baseDir() + 'select_students.html', request, {
                'has_app_module': has_app_module,
                'prog': prog,
                'sec': sec,
                'students_list': students_list
            })
示例#44
0
# Adds lunches in an empty block for users who don't have one.  Chooses the
# lunch randomly for users with both lunch blocks free.

from script_setup import *

import random

from esp.cal.models import Event
from esp.program.models import Program, StudentRegistration, RegistrationType
from esp.program.models.class_ import ClassSection
from esp.users.models import ESPUser

program = Program.objects.get(id=115)  # Change me! (Splash 2014)
relationship = RegistrationType.objects.get(name='Enrolled')

srs = StudentRegistration.valid_objects().filter(
    section__parent_class__parent_program=program, relationship=relationship)

srs_pairs = srs.values_list('user', 'section')

users = ESPUser.objects.filter(id__in=srs.values_list('user'))
sections = ClassSection.objects.filter(
    parent_class__parent_program=program).prefetch_related('meeting_times')
timeblocks = Event.objects.filter(program=program,
                                  event_type__description='Class Time Block')

users_by_id = {user.id: user for user in users}
sections_by_id = {section.id: section for section in sections}
timeblocks_by_id = {timeblock.id: timeblock for timeblock in timeblocks}
sections_by_user_timeblock = {
    (user_id, timeblock.id): section_id
    for user_id, section_id in srs_pairs
示例#45
0
    def review_students(self, request, tl, one, two, module, extra, prog):
        try:
            cls = ClassSubject.objects.get(id = extra)
        except ClassSubject.DoesNotExist:
            raise ESPError('Cannot find class.', log=False)

        if not request.user.canEdit(cls):
            raise ESPError('You cannot edit class "%s"' % cls, log=False)

        #   Fetch any student even remotely related to the class.
        students_dict = cls.students_dict()
        students = []
        for key in students_dict:
            students += students_dict[key]

        for student in students:
            now = datetime.now()
            student.added_class = StudentRegistration.valid_objects().filter(section__parent_class = cls, user = student)[0].start_date
            try:
                student.app = student.studentapplication_set.get(program = self.program)
            except:
                student.app = None

            if student.app:
                reviews = student.app.reviews.all().filter(reviewer=request.user, score__isnull=False)
                questions = student.app.questions.all().filter(subject=cls)
            else:
                reviews = []
                questions = []

            if len(reviews) > 0:
                student.app_reviewed = reviews[0]
            else:
                student.app_reviewed = None

            student.app_completed = False
            for i in questions:
                for j in i.studentappresponse_set.all():
                    if j.complete:
                        student.app_completed = True

        students = list(students)
        students.sort(lambda x,y: cmp(x.added_class,y.added_class))

        if 'prev' in request.GET:
            prev_id = int(request.GET.get('prev'))
            prev = students[0]
            current = None
            for current in students[1:]:
                if prev.id == prev_id and current.app_completed:
                    from django.shortcuts import redirect
                    url = "/%s/%s/%s/review_student/%s/?student=%s" % (tl, one, two, extra, current.id)
                    return redirect(url)
                if prev.id != prev_id:
                    prev = current


        return render_to_response(self.baseDir()+'roster.html',
                                  request,
                                  {'class': cls,
                                   'students':students})
示例#46
0
 def isCompleted(self):
     return StudentRegistration.valid_objects().filter(
         user=get_current_request().user,
         relationship__name="Request").exists()
 def isCompleted(self):
     return bool(StudentRegistration.valid_objects().filter(section__parent_class__parent_program=self.program, user=get_current_request().user))
 def isCompleted(self):
     return bool(StudentRegistration.valid_objects().filter(
         section__parent_class__parent_program=self.program,
         user=get_current_request().user))
示例#49
0
 def num_priority1s(self, prog):
     return StudentRegistration.valid_objects().filter(
         relationship__name='Priority/1',
         section__parent_class__parent_program=prog).count()
 def isCompleted(self):
     return StudentRegistration.valid_objects().filter(user=get_current_request().user,
                                                       relationship__name="Request").exists()