def __organize_examiners(self): assignment = self.request.cradmin_role period_tag_queryset = self.get_queryset_for_role(role=assignment) candidates = Candidate.objects \ .filter(assignment_group__parentnode=assignment)\ .select_related('assignment_group', 'relatedstudent') relatedstudent_to_group_map = {} groups = [candidate.assignment_group for candidate in candidates] self.__clear_examiners(groups) for candidate in candidates: if candidate.relatedstudent_id not in relatedstudent_to_group_map: relatedstudent_to_group_map[candidate.relatedstudent_id] = [candidate.assignment_group] else: relatedstudent_to_group_map[candidate.relatedstudent_id].append(candidate.assignment_group) examiners_to_create = [] for periodtag in period_tag_queryset: group_list = [] for relatedstudent in periodtag.relatedstudents.all(): relatedstudent_id = relatedstudent.id if relatedstudent_id in relatedstudent_to_group_map: group_list.extend(relatedstudent_to_group_map[relatedstudent_id]) del relatedstudent_to_group_map[relatedstudent_id] for relatedexaminer in periodtag.relatedexaminers.all(): for group in group_list: examiners_to_create.append(Examiner(assignmentgroup=group, relatedexaminer=relatedexaminer)) Examiner.objects.bulk_create(examiners_to_create)
def copy_groups_from_another_assignment(self, sourceassignment): """ Copy all AssignmentGroup objects from another assignment. Copies: - The name of the group. """ from devilry.apps.core.models import AssignmentGroup from devilry.apps.core.models import Candidate from devilry.apps.core.models import Examiner if self.assignmentgroups.exists(): raise AssignmentHasGroupsError( _('The assignment has students. You can not ' 'copy use this on assignments with students.')) # Step1: Bulk create the groups with no candidates or examiners, but set copied_from. groups = [] for othergroup in sourceassignment.assignmentgroups.all(): newgroup = AssignmentGroup(parentnode=self, name=othergroup.name, copied_from=othergroup) groups.append(newgroup) AssignmentGroup.objects.bulk_create(groups) # Step2: Bulk create candidate and examiners from group.copied_from.<candidates|examiners>. candidates = [] examiners = [] for group in self.assignmentgroups \ .prefetch_related( models.Prefetch( 'copied_from', to_attr='copied_from_list', queryset=AssignmentGroup.objects.prefetch_related( models.Prefetch('candidates', to_attr='candidatelist', queryset=Candidate.objects.all()), models.Prefetch('examiners', to_attr='examinerlist', queryset=Examiner.objects.all()), ) ) ): for othercandidate in group.copied_from_list.candidatelist: newcandidate = Candidate( assignment_group=group, relatedstudent_id=othercandidate.relatedstudent_id, ) candidates.append(newcandidate) for otherexaminer in group.copied_from_list.examinerlist: newexaminer = Examiner( assignmentgroup=group, relatedexaminer_id=otherexaminer.relatedexaminer_id) examiners.append(newexaminer) Candidate.objects.bulk_create(candidates) Examiner.objects.bulk_create(examiners)
def __create_examiner_objects(self, groupqueryset): examiners = [] groupcount = 0 candidatecount = 0 for group in groupqueryset: examiner = Examiner(assignmentgroup=group, relatedexaminer=self.get_relatedexaminer()) examiners.append(examiner) groupcount += 1 candidatecount += len(group.candidates.all()) Examiner.objects.bulk_create(examiners) return groupcount, candidatecount
def setup_examiners_by_relateduser_syncsystem_tags(self): from devilry.apps.core.models import Candidate from devilry.apps.core.models import Examiner period = self.period # We use this to avoid adding examiners to groups they are already on # We could have used an exclude query, but this is more efficient because # it only requires one query. groupid_to_examineruserid_map = dict( Examiner.objects.filter( assignmentgroup__parentnode=self).values_list( 'assignmentgroup_id', 'relatedexaminer__user_id')) # We collect all the examiners to be created in this list, and bulk create # them at the end examinerobjects = [] for relatedexaminer_syncsystem_tag in RelatedExaminerSyncSystemTag.objects\ .filter(relatedexaminer__period=period)\ .select_related('relatedexaminer__user'): # Step1: Collect all relatedstudents with same tag as examiner relatedstudentids = [] for relatedstudent_syncsystem_tag in RelatedStudentSyncSystemTag.objects\ .filter(relatedstudent__period=period, tag=relatedexaminer_syncsystem_tag.tag): relatedstudentids.append( relatedstudent_syncsystem_tag.relatedstudent_id) # Step2: Find the group of all the students matching the tag # and bulk create Examiner objects for the groups # if the user is not already examiner. if relatedstudentids: relatedexaminer = relatedexaminer_syncsystem_tag.relatedexaminer examineruser = relatedexaminer_syncsystem_tag.relatedexaminer.user groupids = set() for candidate in Candidate.objects\ .filter(assignment_group__parentnode=self, relatedstudent_id__in=relatedstudentids)\ .distinct(): if groupid_to_examineruserid_map.get( candidate.assignment_group_id, None) != examineruser.id: groupids.add(candidate.assignment_group_id) examinerobjects.extend([ Examiner(assignmentgroup_id=groupid, relatedexaminer=relatedexaminer) for groupid in groupids ]) if examinerobjects: Examiner.objects.bulk_create(examinerobjects)
def __random_organize_examiners(self, groupqueryset, relatedexaminerqueryset): relatedexaminer_ids = list(relatedexaminerqueryset.values_list('id', flat=True)) group_ids = list(groupqueryset.values_list('id', flat=True)) random.shuffle(relatedexaminer_ids) random.shuffle(group_ids) examiners_to_create = [] while group_ids: for relatedexaminer in relatedexaminer_ids: if not group_ids: break examiners_to_create.append( Examiner(relatedexaminer_id=relatedexaminer, assignmentgroup_id=group_ids.pop(0)) ) Examiner.objects.bulk_create(examiners_to_create)
def __add_examiners(self, groupqueryset, relatedexaminerqueryset): examiners = [] groupcount = 0 candidatecount = 0 relatedexaminers = list(relatedexaminerqueryset) for group in groupqueryset: groupcount += 1 candidatecount += len(group.candidates.all()) ignored_relatedexaminers_for_group = self.get_ignored_relatedexaminerids_for_group(group=group) for relatedexaminer in relatedexaminers: if relatedexaminer.id not in ignored_relatedexaminers_for_group: examiner = Examiner(assignmentgroup=group, relatedexaminer=relatedexaminer) examiners.append(examiner) Examiner.objects.bulk_create(examiners) return groupcount, candidatecount, relatedexaminers
def __random_organize_examiners(self, groupqueryset, relatedexaminerqueryset): relatedexaminers = list(relatedexaminerqueryset) groups = list(groupqueryset) max_per_examiner = int(math.ceil(len(groups) / len(relatedexaminers))) relatedexaminer_to_count_map = {} examiners_to_create = [] for group in groupqueryset: relatedexaminer = random.choice(relatedexaminers) if relatedexaminer.id not in relatedexaminer_to_count_map: relatedexaminer_to_count_map[relatedexaminer.id] = 0 relatedexaminer_to_count_map[relatedexaminer.id] += 1 if relatedexaminer_to_count_map[ relatedexaminer.id] > max_per_examiner: relatedexaminers.remove(relatedexaminer) examiner_to_create = Examiner(relatedexaminer=relatedexaminer, assignmentgroup=group) examiners_to_create.append(examiner_to_create) Examiner.objects.bulk_create(examiners_to_create)
def setup_examiners_by_relateduser_syncsystem_tags(self): from devilry.apps.core.models import Candidate from devilry.apps.core.models import Examiner from . import period_tag period = self.period # We use this to avoid adding examiners to groups they are already on # We could have used an exclude query, but this is more efficient because # it only requires one query. groupid_to_examineruserid_map = dict( Examiner.objects.filter( assignmentgroup__parentnode=self).values_list( 'assignmentgroup_id', 'relatedexaminer__user_id')) examinerobjects = [] for periodtag in period_tag.PeriodTag.objects.filter(period=period): relatedstudentids = [ relatedstudent.id for relatedstudent in periodtag.relatedstudents.all() ] if relatedstudentids: candidate_queryset = Candidate.objects \ .filter(assignment_group__parentnode=self, relatedstudent_id__in=relatedstudentids) \ .select_related('assignment_group', 'relatedstudent', 'relatedstudent__user') \ .distinct() for relatedexaminer in periodtag.relatedexaminers.all( ).select_related('user'): examineruser = relatedexaminer.user groupids = set() for candidate in candidate_queryset: if groupid_to_examineruserid_map.get( candidate.assignment_group_id, None) != examineruser.id: groupids.add(candidate.assignment_group_id) examinerobjects.extend([ Examiner(assignmentgroup_id=groupid, relatedexaminer=relatedexaminer) for groupid in groupids ]) if examinerobjects: Examiner.objects.bulk_create(examinerobjects)