示例#1
0
def distribute_personal(distribution_proposals, students_done=[]):
    """
    Distribute all students with a private proposal to the private proposal.

    :param distribution_proposals: List of distributions
    :param students_done: list of distributed students
    :return:
    """
    stds = get_all_students().filter(
        personal_proposal__isnull=False,
        personal_proposal__TimeSlot=get_timeslot()).distinct(
        ).prefetch_related('personal_proposal')
    for s in stds:
        try:
            p = s.personal_proposal.filter(TimeSlot=get_timeslot()).get()
        except MultipleObjectsReturned:
            raise Exception(
                "User {} has multiple private proposals ({}). Please resolve this!"
                .format(
                    s,
                    print_list(
                        s.personal_proposal.filter(
                            TimeSlot=get_timeslot()).all())))
        if p.TimeSlot != get_timeslot():
            raise Exception(
                "User {} of this timeslot has private proposal {} of other timeslot {}"
                .format(s, p, p.TimeSlot))
        distribution_proposals.append(DistributionProposal(s.id, p.id, 0))
        students_done.append(s)
    return [distribution_proposals, students_done]
示例#2
0
def get_valid_students():
    """
    All students with applications, without personal, in this timeslot.

    :return: list of user objects.
    """
    # TODO personal_proposal should be filtered by timeslot
    return get_all_students().filter(
        personal_proposal__isnull=True, applications__isnull=False).filter(
            applications__Proposal__TimeSlot=get_timeslot()).distinct()
示例#3
0
def planning_public():
    """
    Check if presentations planning is public visible
    """
    if get_timephase_number() < 5:
        # no distributions yet in phase 5.
        return False
    ts = get_timeslot()
    try:
        options = ts.presentationoptions
    except PresentationOptions.DoesNotExist:
        return False
    if get_timephase_number() == 7 or options.Public:
        return True
    return False
示例#4
0
def calculate_2_from_project(distribute_random, automotive_preference):
    """
    Type 2, calculated new way. Loop over proposals and find a student for it.

    :return:
    """
    projects = list(get_valid_proposals().select_related())
    shuffle(projects)
    students_done = []  # list of student objects
    projects_done = []  # list of proposal objects
    distribution_proposals = []  # list of DistributionProposal objects

    distribution_proposals, students_done = distribute_personal(
        distribution_proposals, students_done)

    # iterate for all preferences twice
    # once to first handle all automotive
    # second time the leftovers plus ele
    if automotive_preference:
        track_automotive = Track.objects.get(Name='Automotive')
        for n in range(1, settings.MAX_NUM_APPLICATIONS + 1):
            # iterate all projects
            for proj in projects:
                # skip non AU
                if proj.Track != track_automotive:
                    continue
                # select all applicants of current selected cohort and preference, sort it for cohort >  ects > random
                apps = list(proj.applications.filter(Priority=n, Proposal__TimeSlot=get_timeslot()).distinct().select_related() \
                            .order_by('-Student__usermeta__Cohort', '-Student__usermeta__ECTS', '?'))
                assigned = count_distributions(proj.id, distribution_proposals)
                # while project is not yet full
                while assigned != proj.NumStudentsMax:
                    # take first from list and check if not yet distributed
                    # if list of applications is empty move on
                    if len(apps) == 0:
                        break
                    app = apps.pop(0)
                    # check if student is automotive
                    if (not app.Student.usermeta.Study) or (
                            'Automotive' not in app.Student.usermeta.Study):
                        continue  # not automotive.
                    # check if there is not an ele project at higher preference for this student, than wait for next round
                    students_appls = app.Student.applications.filter(
                        Priority__lt=app.Priority,
                        Proposal__TimeSlot=get_timeslot()).distinct()
                    students_appls = [
                        True if a.Proposal.Track != track_automotive else False
                        for a in students_appls
                    ]
                    if True in students_appls:
                        continue
                    if app.Student not in students_done:
                        # put it in the distribute list to this proposal
                        distribution_proposals.append(
                            DistributionProposal(app.Student_id, proj.id, n))
                        students_done.append(app.Student)
                        assigned += 1
                if assigned == proj.NumStudentsMax:
                    projects_done.append(proj)

    # all students not only au
    for n in range(1, settings.MAX_NUM_APPLICATIONS + 1):
        # iterate all projects
        for proj in projects:
            # select all applicatants of current selected cohort and preference, sort it for cohort >  ects > random
            apps = list(proj.applications.filter(Priority=n, Proposal__TimeSlot=get_timeslot()).distinct().select_related() \
                        .order_by('-Student__usermeta__Cohort', '-Student__usermeta__ECTS', '?'))
            assigned = count_distributions(proj.id, distribution_proposals)
            # while project is not yet full
            while assigned != proj.NumStudentsMax:
                # take first from list and check if not yet distributed
                # if list of applications is empty move on
                if len(apps) == 0:
                    break
                app = apps.pop(0)
                if app.Student not in students_done:
                    # put it in the distribute list to this proposal
                    distribution_proposals.append(
                        DistributionProposal(app.Student_id, proj.id, n))
                    students_done.append(app.Student)
                    assigned += 1
            if assigned == proj.NumStudentsMax:
                projects_done.append(proj)

    # distribute leftover students random
    if distribute_random:
        distribution_proposals, students_done = distribute_remaining_random(
            distribution_proposals, students_done)

    return distribution_proposals
示例#5
0
def calculate_1_from_student(distribute_random, automotive_preference):
    """
    option1, calculated old way. Look for proposals for each student.

    :return:
    """
    # valid students:
    stds = get_valid_students()

    # list of students processed but not in distributionproposal
    students_done = []  # list of student objects
    projects_done = []
    distribution_proposals = []  # list of DistributionProposal objects

    # personal proposals:
    distribution_proposals, students_done = distribute_personal(
        distribution_proposals, students_done)

    # get all cohorts
    cohorts = get_cohorts()

    # loop over all cohorts, take the youngest students first
    if automotive_preference:
        # for AU students in AU applications
        track_automotive = Track.objects.get(Name='Automotive')
        for c in cohorts:
            # get students in this cohort with applications, ordered by ECTS
            stds_c = list(
                stds.filter(
                    Q(usermeta__Cohort=c)
                    & Q(usermeta__Study__contains='Automotive')).distinct().
                order_by('-usermeta__ECTS'))
            # filter on students without distributionproposal
            # Higher application have priority over ECTS
            for n in range(1, settings.MAX_NUM_APPLICATIONS + 1):
                # all students in this cohort, ordered by most ECTS first, with application number a
                stds_c = list(set(stds_c) - set(students_done))
                for s in stds_c:
                    # loop over applications. Lower choices have priority over ects/cohort
                    if s not in students_done:
                        try:
                            application = s.applications.filter(
                                Proposal__TimeSlot=get_timeslot()).get(
                                    Priority=n)
                        except Application.DoesNotExist:
                            # user does not have a'th application
                            continue
                        if application.Proposal.Track != track_automotive:
                            break
                        # apply to proposal:
                        proposal = application.Proposal
                        if proposal.TimeSlot != get_timeslot():
                            # application is to an invalid proposal
                            continue
                        num_dist = count_distributions(proposal.id,
                                                       distribution_proposals)
                        max_dist = proposal.NumStudentsMax
                        if num_dist < max_dist:
                            # proposal can handle more students
                            distribution_proposals.append(
                                DistributionProposal(s.id, proposal.id, n))
                            # remove this student from queryset because it is now distributed
                            students_done.append(s)
                        #else: this might be a tie between students, check and if yes log.

    # loop over all cohorts, take the youngest students first
    # for all students
    for c in cohorts:
        # get students in this cohort with applications, ordered by ECTS
        stds_c = list(
            stds.filter(
                Q(usermeta__Cohort=c)).distinct().order_by('-usermeta__ECTS'))
        # filter on students without distributionproposal
        # Higher application have priority over ECTS
        for n in range(1, settings.MAX_NUM_APPLICATIONS + 1):
            # all students in this cohort, ordered by most ECTS first, with application number a
            stds_c = list(set(stds_c) - set(students_done))
            for s in stds_c:
                # loop over applications. Lower choices have priority over ects/cohort
                if s not in students_done:
                    try:
                        application = s.applications.filter(
                            Proposal__TimeSlot=get_timeslot()).get(Priority=n)
                    except Application.DoesNotExist:
                        # user does not have a'th application
                        continue

                    # apply to proposal:
                    proposal = application.Proposal
                    if proposal.TimeSlot != get_timeslot():
                        # application is to an invalid proposal
                        continue

                    num_dist = count_distributions(proposal.id,
                                                   distribution_proposals)
                    max_dist = proposal.NumStudentsMax

                    if num_dist < max_dist:
                        # proposal can handle more students
                        distribution_proposals.append(
                            DistributionProposal(s.id, proposal.id, n))
                        # remove this student from queryset because it is now distributed
                        students_done.append(s)
                    #else: this might be a tie between students, check and if yes log.

    if distribute_random:
        distribution_proposals, students_done = distribute_remaining_random(
            distribution_proposals, students_done)

    # return the list of distributed students
    return distribution_proposals
def get_valid_students():
    """
    All students with applications, with personal, in this timeslot.
    Personal proposals are distributed as first, so personal prop students will not get to the other distribution.

    :return: list of user objects.
    """
    return get_all_students().filter(applications__isnull=False).filter(applications__Proposal__TimeSlot=get_timeslot()).distinct()