def selectList_old(self, request, tl, one, two, module, extra, prog): """ Allow use of the "old style" user selector if that is desired for generating a list of users. """ from esp.users.views import get_user_list from esp.users.models import User from esp.users.models import PersistentQueryFilter if not request.GET.has_key('filterid'): filterObj, found = get_user_list(request, self.program.getLists(True)) else: filterid = request.GET['filterid'] filterObj = PersistentQueryFilter.getFilterFromID( filterid, ESPUser) found = True if not found: return filterObj return self.generateList(request, tl, one, two, module, extra, prog, filterObj=filterObj)
def commpanel_old(self, request, tl, one, two, module, extra, prog): from esp.users.views import get_user_list filterObj, found = get_user_list(request, self.program.getLists(True)) if not found: return filterObj listcount = ESPUser.objects.filter(filterObj.get_Q()).distinct().count() return render_to_response(self.baseDir()+'step2.html', request, (prog, tl), {'listcount': listcount, 'filterid': filterObj.id })
def commpanel_old(self, request, tl, one, two, module, extra, prog): from esp.users.views import get_user_list filterObj, found = get_user_list(request, self.program.getLists(True)) if not found: return filterObj sendto_fn_name = request.POST.get('sendto_fn_name', MessageRequest.SEND_TO_SELF_REAL) sendto_fn = MessageRequest.assert_is_valid_sendto_fn_or_ESPError(sendto_fn_name) listcount = self.approx_num_of_recipients(filterObj, sendto_fn) return render_to_response(self.baseDir()+'step2.html', request, {'listcount': listcount, 'filterid': filterObj.id, 'sendto_fn_name': sendto_fn_name })
def mailinglabel(self, request, tl, one, two, module, extra, prog): """ This function will allow someone to generate mailing labels. """ from esp.users.views import get_user_list combine = True if extra is None or extra.strip() == '': return render_to_response( self.baseDir() + 'mailinglabel_index.html', request, {}) if 'nocombine' in extra.strip().lower(): combine = False if 'schools' in extra.strip(): if request.method == 'POST': if 'filter_id' in request.POST: """ A filter was passed. """ f = PersistentQueryFilter.objects.get( id=request.POST['filter_id']) combine = (request.POST['combine'].upper() in ('TRUE', '1', 'T')) infos = f.getList(ContactInfo).distinct() else: form = SchoolSelectForm(request.POST) if form.is_valid(): try: zipc = ZipCode.objects.get( zip_code=form.cleaned_data['zip_code']) except: raise ESPError( 'Please enter a valid US zipcode. "%s" is not valid.' % form.cleaned_data['zip_code'], log=False) zipcodes = zipc.close_zipcodes( form.cleaned_data['proximity']) combine = form.cleaned_data['combine_addresses'] Q_infos = Q(k12school__id__isnull=False, address_zip__in=zipcodes) grades = form.cleaned_data['grades'].strip().split(',') if len(form.cleaned_data['grades_exclude'].strip() ) == 0: grades_exclude = [] else: grades_exclude = form.cleaned_data[ 'grades_exclude'].strip().split(',') if len(grades) > 0: Q_grade = reduce(operator.or_, [ Q(k12school__grades__contains=grade) for grade in grades ]) Q_infos &= Q_grade if len(grades_exclude) > 0: Q_grade = reduce(operator.or_, [ Q(k12school__grades__contains=grade) for grade in grades_exclude ]) Q_infos &= ~Q_grade f = PersistentQueryFilter.create_from_Q( ContactInfo, Q_infos, description= "All ContactInfos for K12 schools with grades %s and %s miles from zipcode %s." % (form.cleaned_data['grades'], form.cleaned_data['proximity'], form.cleaned_data['zip_code'])) num_schools = ContactInfo.objects.filter( Q_infos).distinct().count() return render_to_response( self.baseDir() + 'schools_confirm.html', request, { 'filter': f, 'num': num_schools, 'combine': combine }) else: return render_to_response( self.baseDir() + 'selectschools.html', request, {'form': form}) else: form = SchoolSelectForm(initial={ 'zip_code': '02139', 'combine_addresses': True }) return render_to_response( self.baseDir() + 'selectschools.html', request, {'form': form}) else: filterObj, found = get_user_list(request, self.program.getLists(True)) if not found: return filterObj infos = [ user.getLastProfile().contact_user for user in ESPUser.objects.filter(filterObj.get_Q()).distinct() ] infos_filtered = [ info for info in infos if (info != None and info.undeliverable != True) ] output = MailingLabels.gen_addresses(infos, combine) if 'csv' in extra.strip(): response = HttpResponse('\n'.join(output), content_type='text/plain') return response
def selectList(self, request, tl, one, two, module, extra, prog): """ Select the type of list that is requested. """ from esp.users.views import get_user_list from esp.users.models import User from esp.users.models import PersistentQueryFilter if not request.GET.has_key('filterid'): filterObj, found = get_user_list(request, self.program.getLists(True)) else: filterid = request.GET['filterid'] filterObj = PersistentQueryFilter.getFilterFromID( filterid, ESPUser) found = True if not found: return filterObj if request.method == 'POST' and 'fields' in request.POST: form = ListGenForm(request.POST) if form.is_valid(): lists = [] lists_indices = {} split_by = form.cleaned_data['split_by'] labels_dict = UserAttributeGetter.getFunctions() fields = [labels_dict[f] for f in form.cleaned_data['fields']] # If a split field is specified, make sure we fetch its data if split_by and labels_dict[split_by] not in fields: fields.append(labels_dict[split_by]) output_type = form.cleaned_data['output_type'] users = list( ESPUser.objects.filter( filterObj.get_Q()).filter(is_active=True).distinct()) users.sort() for u in users: ua = UserAttributeGetter(u, self.program) user_fields = [ ua.get(x) for x in form.cleaned_data['fields'] ] u.fields = user_fields # Add information for split lists if desired if split_by: if ua.get(split_by) not in lists_indices: lists.append({ 'key': labels_dict[split_by], 'value': ua.get(split_by), 'users': [] }) lists_indices[ua.get(split_by)] = len(lists) - 1 lists[lists_indices[ua.get(split_by)]]['users'].append( u) if split_by: lists.sort(key=lambda x: x['value']) else: lists.append({'users': users}) if output_type == 'csv': # properly speaking, this should be text/csv, but that # causes Chrome to open in an external editor, which is # annoying mimetype = 'text/plain' elif output_type == 'html': mimetype = 'text/html' else: # WTF? mimetype = 'text/html' return render_to_response( self.baseDir() + ('list_%s.html' % output_type), request, (prog, tl), { 'users': users, 'lists': lists, 'fields': fields, 'listdesc': filterObj.useful_name }, mimetype=mimetype, ) else: return render_to_response(self.baseDir() + 'options.html', request, (prog, tl), { 'form': form, 'filterid': filterObj.id }) else: form = ListGenForm() return render_to_response(self.baseDir() + 'options.html', request, (prog, tl), { 'form': form, 'filterid': filterObj.id })
def satprep_schedulestud(self, request, tl, one, two, module, extra, prog): """ An interface for scheduling all the students, provided the classes have already been generated. """ from esp.program.modules.module_ext import SATPrepTeacherModuleInfo import string import random import copy # Get confirmation and a list of users first. if not request.method == 'POST' and not request.POST.has_key( 'schedule_confirm'): return render_to_response(self.baseDir() + 'schedule_confirm.html', request, (prog, tl), {}) filterObj, found = get_user_list(request, self.program.getLists(True)) if not found: return filterObj # Find the user's scores and put them in a python list. users = list(filterObj.getList(User).distinct()) subjects = ['math', 'verb', 'writ'] # Expire existing enrollments reg_bits = UserBit.valid_objects().filter( verb=DataTree.get_by_uri('V/Flags/Registration/Enrolled')).filter( QTree(qsc__below=prog.anchor)) """ print 'Expiring %d enrollment bits' % reg_bits.count() """ for bit in reg_bits: bit.expire() # Add scores to each user for user in users: satprepreginfo = SATPrepRegInfo.getLastForProgram( user, self.program) user.scores = {} for subject in subjects: user.scores[subject] = SATPrepAdminSchedule.getScore( satprepreginfo, subject) # Get an independently sorted list for each subject sorted_lists = {} for subject in subjects: sorted_lists[subject] = copy.deepcopy(users) sorted_lists[subject].sort(key=lambda x: x.scores[subject]) # Generate list of possible orderings def combinations(lst): if len(lst) == 1: return [lst] else: result = [] for i in range(len(lst)): other_items = [y for y in lst if y != lst[i]] result += [[lst[i]] + x for x in combinations(other_items)] return result orderings = combinations(subjects) # Divide students into orderings num_orderings = len(orderings) num_subjects = len(subjects) ordering_index = 0 subject_index = 0 def lists_non_empty(): for subject in subjects: if len(sorted_lists[subject]) > 0: return True return False ordering_lists = [[] for ordering in orderings] while lists_non_empty(): # Pull a student from the top of the list in the current subject new_student = sorted_lists[subjects[subject_index]].pop() # Put them in the list for the current ordering ordering_lists[ordering_index].append(new_student) # Remove them from the other lists for subject in subjects: if subject != subjects[subject_index]: sorted_lists[subject].remove(new_student) # Debug statement: # print 'Took %s (scores: %s) from %s list to ordering %s' % (new_student, new_student.scores, subjects[subject_index], orderings[ordering_index]) # Move to the next subject list subject_index = (subject_index + 1) % num_subjects # Move to the next ordering list ordering_index = (ordering_index + 1) % num_orderings """ # Debug statements print '--------------' for i in range(num_orderings): print 'Ordering %s: %d students' % (orderings[i], len(ordering_lists[i])) """ # Retrieve the class sections of the program, keeping track of their subject and level # in the class_list dictionary. tmi = SATPrepTeacherModuleInfo.objects.filter(program=prog) class_list = {} timeslots = prog.getTimeSlots() for timeslot in timeslots: class_list[timeslot] = {} for subject in subjects: class_list[timeslot][subject] = {} for t in tmi: section = t.section subject = t.get_subject_display().lower()[:4] cl = ESPUser(t.user).getTaughtClasses(prog) for c in cl: for s in c.get_sections(): timeslot = s.start_time() if section not in class_list[timeslot][subject]: class_list[timeslot][subject][section] = [] class_list[timeslot][subject][section].append( (s, s.room_capacity())) """ # Debug statements # print class_list """ # For each timeslot/subject combination, find the orderings that include it for timeslot_index in range(len(timeslots)): for subject in subjects: valid_orderings = filter( lambda o: o[timeslot_index] == subject, orderings) # Get a list of students in those orderings sorted by their score in the current subject # (Exclude students that have no score) timeslot = timeslots[timeslot_index] students = [] for ordering in valid_orderings: students += ordering_lists[orderings.index(ordering)] students = filter(lambda s: s.scores[subject] >= 200, students) students.sort(key=lambda s: s.scores[subject]) students.reverse() """ # Debug statement print 'Timeslot %s; subject %s: %d students' % (timeslots[timeslot_index], subject, len(students)) """ # Parcel out the spots in each level proportional to space num_students = len(students) num_spots = 0 section_dict = class_list[timeslot][subject] level_space = {} level_thresholds = {} indiv_thresholds = {} ordered_sections = section_dict.keys() ordered_sections.sort() prev_section = None for section in ordered_sections: level_space[section] = 0 for item in section_dict[section]: num_spots += item[1] level_space[section] += item[1] for section in ordered_sections: if prev_section is None: prev_threshold = 0 else: prev_threshold = level_thresholds[prev_section] section_size = level_space[section] * float( num_students) / num_spots level_thresholds[section] = prev_threshold + section_size indiv_thresholds[section] = [ section_size * item[1] / level_space[section] + prev_threshold for item in section_dict[section] ] prev_section = section """ # Debug statement # print ' -> Section %s (%d/%d students): threshold = %f, indiv = %s' % (section, level_thresholds[section] - prev_threshold, level_space[section], level_thresholds[section], indiv_thresholds[section]) """ # Assign students num_students_assigned = 0 section_index = 0 current_item = 0 for student in students: if (section_index >= len(ordered_sections)): raise ESPError(False), 'Overran number of sections' current_section = ordered_sections[section_index] if (current_item >= len( indiv_thresholds[current_section])): raise ESPError( False), 'Overran number of sections in section' target_section = section_dict[current_section][ current_item][0] if not hasattr(target_section, 'min_score'): target_section.min_score = 800 if not hasattr(target_section, 'max_score'): target_section.max_score = 200 target_section.preregister_student(student, overridefull=True) if student.scores[subject] < target_section.min_score: target_section.min_score = student.scores[subject] if student.scores[subject] > target_section.max_score: target_section.max_score = student.scores[subject] num_students_assigned += 1 """ # Debug statements print ' Assigning student %s (scores: %s) to %s' % (student, student.scores, target_section) print ' -> %d assigned (current thresholds are %f, %f)' % (num_students_assigned, indiv_thresholds[current_section][current_item], level_thresholds[current_section]) """ # Increment section if necessary if num_students_assigned > level_thresholds[ current_section]: section_index += 1 current_item = 0 # Increment item if necessary elif num_students_assigned > indiv_thresholds[ current_section][current_item]: current_item += 1 """ # Check results for section in ordered_sections: # This code assumes multiple sections per level+timeblock+subject print ' -> Section %s' % section for item in section_dict[section]: print ' (%d/%d) %s' % (item[0].num_students(), item[1], item[0]) # This code assumes one section per level+timeblock+subject item = section_dict[section][0] print ' -> Section %s (%d/%d) %s: Scores %d-%d' % (section, item[0].num_students(), item[1], item[0], item[0].min_score, item[0].max_score) """ return HttpResponseRedirect('/manage/%s/schedule_options' % self.program.getUrlBase())