Example #1
0
def dumbledore():
	l_groups = []
	l_students = []
	for group in Groups.objects:
		Groups.objects(
			group_name=group.group_name
			).update(
			members=[], preferences=[]
			)
		group.reload()
	for student in Students.objects:
		Students.objects(
			identikey=student.identikey
			).update(
			group_assigned=None
			)
		student.reload()
	removeExtraGroups()
	registerStudents()
	ret_val = unpopular()
	if ret_val != 0:
		return ret_val
	for group in Groups.objects:
		l_groups.append(group)
	for student in Students.objects:
		l_students.append(student)
	matched = sortThemStudents(l_students, l_groups)
	writeToDatabase(matched)


	success_list = []
	for group in matched:
		s_list = []
		print(group.group_name + ":")
		for student in matched[group]:
			s_list.append(student)
		for student in matched[group]:
			success = 0
			if len(student.work_with) > 0:
				for s in student.work_with:
					if s in s_list:
						success += 1

			success_list.append(success)
			# out_string += (student.student_name + ","
			# 	+ group.group_name + ","
			# 	+ str(success) + "\n")
			print("\t" + student.student_name)

	print(averagePreference())
	print(avgFriendsPlaced(success_list))
	prefDistribution()
	count(matched)

	writeResults()

	# with open("results.csv", 'w') as fp:
	# 	fp.write(out_string)

	return matched
def registerStudents():
    storeIdentikeyListJson()
    updateCountJson()
    known_score = 0
    learn_score = 0
    ip_score = 0
    ec = 0
    for student in Students.objects:
        addWorkWith(student)
        for group in student.preferences:
            for attr in group.skills:
                if attr in student.known_skills and known_score < MAX_SKILL_LEN:
                    known_score += KNOWN_WEIGHT
                if attr in student.learn_skills and learn_score < MAX_SKILL_LEN:
                    learn_score += LEARN_WEIGHT
            if student.ip_pref == 'NO_PREF':
                ip_score = 0
            elif student.ip_pref == 'RETAIN' and group.ip == 'OPEN':
                ip_score = IP_WEIGHT
            else:
                ip_score = -IP_WEIGHT
            if student.extra_credit:
                ec = EXTRA_CREDIT
            pref = calcGroupPreference(known_score, learn_score, ip_score, ec)
            pref_doc = Preference(student=student, pref_score=pref)
            Groups.objects(group_name=group.group_name).update(
                add_to_set__preferences=pref_doc)
Example #3
0
def loadProjects(group_data):
    print("In Load projects")
    if len(Groups.objects.all()) > 0:
        Groups.drop_collection()
        print("Dropping collections")
    # group_data = dataSet(group_path)

    for line in group_data:
        print("parsing: " + line)
        parseGroups(line)
Example #4
0
def nopeStudents(student, group, matched):
    if len(student.dont_work_with) > 0:
        for s in student.dont_work_with:
            if s in matched[group]:
                matched[group].remove(s)
                print("Removing " + s.student_name + " from group " +
                      group.group_name)
            Groups.objects(
                group_name=group.group_name, preferences__student=s).update(
                    dec__preferences__S__pref_score=GROUP_WEIGHT * 10)
            group.reload()
    return group.preferences, matched
Example #5
0
def buildDB(student_path, group_path):
    #assert(len(student_path) > 0)
    if len(Groups.objects.all()) > 0:
        Groups.drop_collection()
    if len(Students.objects.all()) > 0:
        Students.drop_collection()
    student_data = dataSet(student_path)
    group_data = dataSet(group_path)
    for line in group_data.readData:
        g = parseGroups(line)
        # TODO add proper mongoengine command here if this doesn't work
    for line in student_data.readData:
        s = parseStudent(line)
Example #6
0
def writeToDatabase(matched):
	for group in matched:
		for student in matched[group]:
			Groups.objects(
				group_name=group.group_name
				).update(
				add_to_set__members=student
				)
			Students.objects(
				identikey=student.identikey
				).update(
				group_assigned=group
				)
			group.reload()
			student.reload()
Example #7
0
def partnerUpStudents(student, group):
    if len(student.work_with) > 0:
        # group.update(inc__preferences__S__pref_score=GROUP_WEIGHT)
        Groups.objects(group_name=group.group_name,
                       preferences__student=student).update(
                           inc__preferences__S__pref_score=GROUP_WEIGHT)
        group.reload()
        # s_to_update = group(preferences__student=student)
        # new_score = s_to_update.pref_score + GROUP_WEIGHT
        # s_to_update.update(pref_score=new_score)
        for s in student.work_with:
            Groups.objects(group_name=group.group_name,
                           preferences__student=s).update(
                               inc__preferences__S__pref_score=GROUP_WEIGHT)
            group.reload()
    return group.preferences
def removeExtraGroups():
	print("REMOVING EXTRA GROUPS")
	opt_groups = []
	opt_dict = {}
	for group in Groups.objects:
		if group.option:
			opt_groups.append(group)
	for group in opt_groups:
		if group.opt_category in opt_dict:
			opt_dict[group.opt_category].append(group)
		else:
			opt_dict[group.opt_category] = [group]
	for cat in opt_dict:
		del_list = []
		max_pref = 100 # Just needs to be greater than 5
		chosen_group = None
		for group in opt_dict[cat]:
			avg = avgPref(group)
			if avg < max_pref:
				max_pref = avg
				if chosen_group:
					del_list.append(chosen_group)
					chosen_group = None
				chosen_group = group
			else:
				del_list.append(group)
		for group in del_list:
			print("WARNING: Removing group" + group.group_name)
			Groups.objects(group_name=group.group_name).delete()
			for student in Students.objects:
				if group in student.preferences:
					##! We have a couple options here, we can replace removed
					##! groups with the chosen group, or just delete the groups
					##! TODO Add variable flag to select either replacing or deleting
					##! TODO add logic to replace
					Students.objects(
						identikey=student.identikey
						).update(pull__preferences=group)
					student.reload()
Example #9
0
def addGroup(data):
    name = data["name"]
    print("Adding " + name + " to database")
    paid = data["paid"]
    ip = data["ipPref"]
    ##! Have to update the projectInformation.js
    option = data["option"]
    if option:
        opt_category = data["optionCategory"]
    skills = data["skills"]
    group_to_add = Groups(group_name=name,
                          paid=paid,
                          ip=ip,
                          option=option,
                          skills=skills)
    group_to_add.save()
    if option:
        group_to_add.update(opt_category=opt_category)
    group_to_add.reload()
Example #10
0
def swapThemStudents(shortGroup, firstPass):
    print("Fixing " + shortGroup.group_name)
    for group in Groups.objects:
        if group == shortGroup:
            continue
        if len(group.members) > OPT_SIZE:
            for student in group.members:
                if len(shortGroup.members) >= MIN_SIZE:
                    return
                if (shortGroup in student.preferences
                        and not checkLeader(student, shortGroup)
                        and not finalNopeStudents(student, shortGroup)):
                    Groups.objects(group_name=group.group_name).update(
                        pull__members=student)
                    group.reload()
                    # group.members.remove(student)
                    Groups.objects(group_name=shortGroup.group_name).update(
                        add_to_set__members=student)
                    shortGroup.reload()
                    # shortGroup.members.append(student)
                    if len(group.members) == OPT_SIZE:
                        break
                if len(group.members) == 0:
                    break
        elif not firstPass and len(group.members) > MIN_SIZE:
            #TODO add guard against overdrawing from group to below min_size
            for student in group.members:
                if len(group.members) == MIN_SIZE:
                    break
                if len(shortGroup.members) >= MIN_SIZE:
                    return
                if (shortGroup in student.preferences
                        and not checkLeader(student, shortGroup)
                        and not finalNopeStudents(student, shortGroup)):
                    Groups.objects(group_name=group.group_name).update(
                        pull__members=student)
                    group.reload()
                    # group.members.remove(student)
                    Groups.objects(group_name=shortGroup.group_name).update(
                        add_to_set__members=student)
                    shortGroup.reload()
Example #11
0
def sortThemStudents():
    fall_through = False
    students_free = []
    for student in Students.objects:
        students_free.append(student)
    matched = {}
    student_prefers = {}
    group_prefers = {}
    modPrefsForStudents()
    for student in Students.objects:
        student_prefers[student] = student.preferences

    for group in Groups.objects:
        # pref_list = []
        # for pref in group.preferences:
        # 	pref_list.append(pref)
        group_prefers[group] = group.preferences

    ##! First step is to ensure lightly chosen paid groups are filled
    ret, paid_dict = payForStudents()
    if ret != 0:
        return ret
    if paid_dict:
        for g in paid_dict:
            for s in paid_dict[g]:
                matched[g].append(s)
                students_free.remove(s)

    while students_free:
        s = students_free.pop(0)
        s_list = student_prefers[s]
        if len(s_list) < 1:
            print(s.student_name + " is out of options")
            return 1, matched
        g = s_list.pop(0)
        # g_name = g_ref.group_name
        # index = 0
        # g = None
        # for group in groups:
        #     if group.group_name == g_name:
        #         g = group

        match = matched.get(g)
        if not match:
            # group has no matches yet
            # print(g.group_name + " has no matches yet.")
            ##! TODO So much code repetition, fix this noise
            matched[g] = [s]
            if (s.leadership != "STRONG_FOLLOW"
                    and s.leadership != "STRONG_LEAD"):
                Groups.objects(group_name=g.group_name).update(has_leader=True)
                g.reload()
                s.reload()
            elif s.leadership == "STRONG_LEAD":
                Groups.objects(group_name=g.group_name).update(
                    has_strong_leader=True, has_leader=True)
                g.reload()
                s.reload()
            group_prefers[g] = partnerUpStudents(s, g)
            group_prefers[g], matched = nopeStudents(s, g, matched)

        elif len(match) < OPT_SIZE and not fall_through:
            #Open space in group
            # print(g.group_name + " is being filled")
            if checkLeader(s, g):
                students_free.append(s)
            else:
                matched[g].append(s)
                if (s.leadership != "STRONG_FOLLOW"
                        and s.leadership != "STRONG_LEAD"):
                    Groups.objects(group_name=g.group_name).update(
                        has_leader=True)
                    g.reload()
                    s.reload()
                if s.leadership == "STRONG_LEAD":
                    Groups.objects(group_name=g.group_name).update(
                        has_strong_leader=True, has_leader=True)
                    g.reload()
                    s.reload()
                group_prefers[g] = partnerUpStudents(s, g)
                group_prefers[g], matched = nopeStudents(s, g, matched)
        ##! Be more lenient on group size for second pass students
        elif len(match) < MAX_SIZE and fall_through:
            #Open space in group
            # print(g.group_name + " is being filled even more")
            if checkLeader(s, g):
                students_free.append(s)
            else:
                matched[g].append(s)
                if (s.leadership != "STRONG_FOLLOW"
                        and s.leadership != "STRONG_LEAD"):
                    Groups.objects(group_name=g.group_name).update(
                        has_leader=True)
                    g.reload()
                    s.reload()
                if s.leadership == "STRONG_LEAD":
                    Groups.objects(group_name=g.group_name).update(
                        has_strong_leader=True, has_leader=True)
                    g.reload()
                    s.reload()
                group_prefers[g] = partnerUpStudents(s, g)
                group_prefers[g], matched = nopeStudents(s, g, matched)

        else:
            # print(g.group_name + " is competitive.")
            g_list = group_prefers[g]
            replaced = False
            for m in match:
                for pref in g_list:
                    if pref.student == m:
                        cur_pref = pref.pref_score
                    elif pref.student == s:
                        new_pref = pref.pref_score
                if cur_pref < new_pref:
                    #replace less preferred student with current student
                    # print("Replacing " + m.student_name + " with " + s.student_name)
                    if (checkLeader(s, g)
                            and not (m.leadership == "STRONG_LEAD")):
                        continue
                    else:
                        matched[g].remove(m)
                        matched[g].append(s)
                        if (s.leadership != "STRONG_FOLLOW"
                                and s.leadership != "STRONG_LEAD"):
                            Groups.objects(group_name=g.group_name).update(
                                has_leader=True)
                            g.reload()
                            s.reload()
                        if s.leadership == "STRONG_LEAD":
                            Groups.objects(group_name=g.group_name).update(
                                has_strong_leader=True, has_leader=True)
                            g.reload()
                            s.reload()
                        if len(student_prefers[m]) > 0:
                            students_free.append(m)
                        else:
                            #No op, but this will break things, so here's one
                            #solution, but:
                            #TODO: make this work better
                            if len(match) < MAX_SIZE:
                                matched[g].append(m)
                        replaced = True
                        group_prefers[g] = partnerUpStudents(s, g)
                        group_prefers[g], matched = nopeStudents(s, g, matched)
                        break
            if not replaced:
                if len(s_list) > 0:
                    students_free.append(s)
                else:
                    if len(match) < MAX_SIZE:
                        matched[g].append(s)

        if len(students_free) < 1:
            unsorted = checkComplete(matched)
            if len(unsorted) > 0:
                for identikey in unsorted:
                    ##! This process takes an obscenely long time.
                    ##! I don't know how to streamline these updates,
                    ##! but this operation is one of the slowest in the
                    ##! entire algorithm
                    ##! TODO OPTIMIZE PRIME
                    student = Students.objects.get(identikey=identikey)
                    for group in student.preferences:
                        for pref in group.preferences:
                            Groups.objects(group_name=group.group_name).update(
                                pull__preferences__student=student)
                            score = pref.pref_score + GROUP_WEIGHT
                            np = Preference(student=student, pref_score=score)
                            Groups.objects(group_name=group.group_name).update(
                                add_to_set__preferences=np)
                            group.reload()
                            group_prefers[group] = group.preferences
                    students_free.append(student)
                    student_prefers[student] = student.preferences
                    print(student.student_name + " is being re-sorted.")
                fall_through = True

    ##! TODO this should be separate, single responsibility principle and all
    for group in matched:
        for student in matched[group]:
            Groups.objects(group_name=group.group_name).update(
                add_to_set__members=student)
            group.reload()
            # group.members.append(student)
    swapController()
    warnLeaders()
    ##! TODO same here
    for group in Groups.objects:
        if group.paid and len(group.members) < MIN_SIZE:
            print("MATCHING FAILED: paid group was unfilled: " +
                  group.group_name)
            return 1, matched
    ##! TODO this is a weird way to update the local object
    for group in Groups.objects:
        matched[group] = []
        matched[group] = group.members
        for student in group.members:
            Students.objects.get(identikey=student.identikey).update(
                group_assigned=group)
            student.reload()

    return 0, matched
Example #12
0
def removeGroup(group):
	print("WARNING: Removing group: " + group.group_name)
	Groups.objects(group_name=group.group_name).delete()
	for student in Students.objects:
		if group in student.preferences:
			student.update(pull__preferences=group)