def testGradeChange(self): # Create the admin user adminUser, c1 = ESPUser.objects.get_or_create(username='******') adminUser.set_password('password') adminUser.makeAdmin() # Create the student user studentUser, c2 = ESPUser.objects.get_or_create(username='******') # Make it a student studentUser.makeRole("Student") # Give it a starting grade student_studentinfo = StudentInfo(user=studentUser, graduation_year=ESPUser.YOGFromGrade(9)) student_studentinfo.save() student_regprofile = RegistrationProfile(user=studentUser, student_info=student_studentinfo, most_recent_profile=True) student_regprofile.save() # Check that the grade starts at 9 self.assertTrue(studentUser.getGrade() == 9) # Login the admin self.assertTrue(self.client.login(username="******", password="******")) testGrade = 11 curYear = ESPUser.current_schoolyear() gradYear = curYear + (12 - testGrade) self.client.get("/manage/userview?username=student&graduation_year="+str(gradYear)) self.assertTrue(studentUser.getGrade() == testGrade, "Grades don't match: %s %s" % (studentUser.getGrade(), testGrade)) # Clean up if (c1): adminUser.delete() if (c2): studentUser.delete()
def students_status(self, request, tl, one, two, module, extra, prog): resp = HttpResponse(mimetype='application/json') grade_query = """ SELECT (12 + %d - "users_studentinfo"."graduation_year") FROM "users_studentinfo", "program_registrationprofile" WHERE "program_registrationprofile"."most_recent_profile" = true AND "program_registrationprofile"."student_info_id" = "users_studentinfo"."id" AND "users_studentinfo"."user_id" = "auth_user"."id" ORDER BY program_registrationprofile.id DESC LIMIT 1 """ % ESPUser.current_schoolyear() # Try to ensure we don't miss anyone students_dict = self.program.students(QObjects=True) student_types = [ 'student_profile' ] # You could add more list names here, but it would get very slow. students_Q = Q() for student_type in student_types: students_Q = students_Q | students_dict[student_type] students = ESPUser.objects.filter(students_Q).distinct() data = students.extra({ 'grade': grade_query }).values_list('id', 'last_name', 'first_name', 'grade').distinct() simplejson.dump(list(data), resp) return resp
def testGradeChange(self): # Create the admin user adminUser, c1 = ESPUser.objects.get_or_create(username='******') adminUser.set_password('password') adminUser.makeAdmin() # Create the student user studentUser, c2 = ESPUser.objects.get_or_create(username='******') # Make it a student studentUser.makeRole("Student") # Give it a starting grade student_studentinfo = StudentInfo(user=studentUser, graduation_year=ESPUser.YOGFromGrade(9)) student_studentinfo.save() student_regprofile = RegistrationProfile(user=studentUser, student_info=student_studentinfo, most_recent_profile=True) student_regprofile.save() # Check that the grade starts at 9 self.assertTrue(studentUser.getGrade() == 9) # Login the admin self.assertTrue(self.client.login(username="******", password="******")) testGrade = 11 curYear = ESPUser.current_schoolyear() gradYear = curYear + (12 - testGrade) self.client.get("/manage/userview?username=student&graduation_year="+str(gradYear)) self.assertTrue(studentUser.getGrade() == testGrade, "Grades don't match: %s %s" % (studentUser.getGrade(), testGrade)) # Clean up if (c1): adminUser.delete() if (c2): studentUser.delete()
def testGradeChange(self): # Create the admin user adminUser, c1 = ESPUser.objects.get_or_create(username='******') adminUser.set_password('password') make_user_admin(adminUser) # Create the student user studentUser, c2 = ESPUser.objects.get_or_create(username='******') # Make it a student role_bit, created = UserBit.objects.get_or_create(user=studentUser, qsc=GetNode('Q'), verb=GetNode('V/Flags/UserRole/Student'), recursive=False) # Give it a starting grade student_studentinfo = StudentInfo(user=studentUser, graduation_year=ESPUser.YOGFromGrade(9)) student_studentinfo.save() student_regprofile = RegistrationProfile(user=studentUser, student_info=student_studentinfo, most_recent_profile=True) student_regprofile.save() # Check that the grade starts at 9 self.failUnless(studentUser.getGrade() == 9) # Login the admin self.failUnless(self.client.login(username="******", password="******")) testGrade = 11 curYear = ESPUser.current_schoolyear() gradYear = curYear + (12 - testGrade) self.client.get("/manage/userview?username=student&graduation_year="+str(gradYear)) self.failUnless(studentUser.getGrade() == testGrade, "Grades don't match: %s %s" % (studentUser.getGrade(), testGrade)) # Clean up if (c1): adminUser.delete() if (c2): studentUser.delete()
def schoolyear(request): path_parts = request.path.lstrip('/').split('/') if len(path_parts) > 3: program_url = '/'.join(path_parts[1:3]) if Program.objects.filter(url=program_url).count() == 1: program = Program.objects.get(url=program_url) return {'schoolyear': ESPUser.program_schoolyear(program)} return {'schoolyear': ESPUser.current_schoolyear()}
def schoolyear(request): path_parts = request.path.lstrip('/').split('/') if len(path_parts) > 3: program_url = '/'.join(path_parts[1:3]) if Program.objects.filter(url=program_url).count() == 1: program = Program.objects.get(url=program_url) return {'schoolyear': ESPUser.program_schoolyear(program)} return {'schoolyear': ESPUser.current_schoolyear()}
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])
def onsite_create(self, request, tl, one, two, module, extra, prog): if request.method == 'POST': form = OnSiteRegForm(request.POST) if form.is_valid(): new_data = form.cleaned_data username = ESPUser.get_unused_username(new_data['first_name'], new_data['last_name']) new_user = ESPUser(username=username, first_name=new_data['first_name'], last_name=new_data['last_name'], email=new_data['email'], is_staff=False, is_superuser=False) new_user.save() self.student = new_user regProf = RegistrationProfile.getLastForProgram( new_user, self.program) contact_user = ContactInfo(first_name=new_user.first_name, last_name=new_user.last_name, e_mail=new_user.email, user=new_user) contact_user.save() regProf.contact_user = contact_user student_info = StudentInfo( user=new_user, graduation_year=ESPUser.YOGFromGrade(new_data['grade'])) try: if isinstance(new_data['k12school'], K12School): student_info.k12school = new_data['k12school'] else: if isinstance(new_data['k12school'], int): student_info.k12school = K12School.objects.get( id=int(new_data['k12school'])) else: student_info.k12school = K12School.objects.filter( name__icontains=new_data['k12school'])[0] except: student_info.k12school = None student_info.school = new_data[ 'school'] if not student_info.k12school else student_info.k12school.name student_info.save() regProf.student_info = student_info regProf.save() if new_data['paid']: self.createBit('paid') self.updatePaid(True) else: self.updatePaid(False) self.createBit('Attended') if new_data['medical']: self.createBit('Med') if new_data['liability']: self.createBit('Liab') self.createBit('OnSite') new_user.groups.add(Group.objects.get(name="Student")) new_user.recoverPassword() return render_to_response( self.baseDir() + 'reg_success.html', request, { 'student': new_user, 'retUrl': '/onsite/%s/classchange_grid?student_id=%s' % (self.program.getUrlBase(), new_user.id) }) else: form = OnSiteRegForm() return render_to_response(self.baseDir() + 'reg_info.html', request, { 'form': form, 'current_year': ESPUser.current_schoolyear() })
def onsite_create(self, request, tl, one, two, module, extra, prog): if request.method == 'POST': form = OnSiteRegForm(request.POST) if form.is_valid(): new_data = form.cleaned_data username = ESPUser.get_unused_username(new_data['first_name'], new_data['last_name']) new_user = ESPUser(username = username, first_name = new_data['first_name'], last_name = new_data['last_name'], email = new_data['email'], is_staff = False, is_superuser = False) new_user.save() self.student = new_user regProf = RegistrationProfile.getLastForProgram(new_user, self.program) contact_user = ContactInfo(first_name = new_user.first_name, last_name = new_user.last_name, e_mail = new_user.email, user = new_user) contact_user.save() regProf.contact_user = contact_user student_info = StudentInfo(user = new_user, graduation_year = ESPUser.YOGFromGrade(new_data['grade'])) student_info.save() regProf.student_info = student_info regProf.save() if new_data['paid']: self.createBit('Paid') self.updatePaid(True) else: self.updatePaid(False) self.createBit('Attended') if new_data['medical']: self.createBit('MedicalFiled') if new_data['liability']: self.createBit('LiabilityFiled') self.createBit('OnSite') v = GetNode( 'V/Flags/UserRole/Student') ub = UserBit() ub.user = new_user ub.recursive = False ub.qsc = GetNode('Q') ub.verb = v ub.save() new_user.recoverPassword() return render_to_response(self.baseDir()+'reg_success.html', request, (prog, tl), { 'student': new_user, 'retUrl': '/onsite/%s/classchange_grid?student_id=%s' % (self.program.getUrlBase(), new_user.id) }) else: form = OnSiteRegForm() return render_to_response(self.baseDir()+'reg_info.html', request, (prog, tl), {'form':form, 'current_year':ESPUser.current_schoolyear()})
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) # 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] 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) now = datetime.now() # Populate interest matrix interest_regs = StudentRegistration.objects.filter(section__parent_class__parent_program=self.program, relationship__name='Interested', end_date__gte=now).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.objects.filter(section__parent_class__parent_program=self.program, relationship__name='Priority/1', end_date__gte=now).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 # 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).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