Skip to content

Algorithm

Alex Quigley edited this page Mar 27, 2025 · 3 revisions

This sorting algorithm was constructed by the F24 Team in conjunction with .

Algorithm Breakdown

Overview

The algorithm takes two inputs:

Students: An array of Student objects.
Projects: An array of Project objects.
It outputs a mapping (of type TeamAssignments) that associates each project with a list of assigned students. The process involves:

  • Initializing teams for each project.
  • Sorting and grouping students based on their project preferences, degree (hardware/software/other), and class level.
  • Assigning students to teams according to these groupings.
  • Ensuring that each project team includes at least one upperclassman (3200-level student).
  • Balancing team sizes so that no team is significantly over- or under-staffed.

Data Structures

Student Each Student object contains:

  • id: ID Number
  • name: Student’s name.
  • major: The student’s field ("CS", "SE", "EE", etc.).
  • seniority: Academic year (Freshman, Sophomore, Junior, Senior).
  • choices: An ordered list of preferred project names.
  • choicesString: A string representation of the project choices.
  • class: Indicates class level ("2200" for lower-level, "3200" for upper-level).

Project Each Project object includes:

  • id: Unique identifier.
  • name: Project name.
  • type: Category of project, e.g., "SW" (software), "HW" (hardware), or "Both".

TeamAssignments A mapping (record) that links project names (as keys) to arrays of assigned Student objects.

Student Sort

Initialization:

Creates an empty team (array) for each project.

const teams: TeamAssignments = projects.reduce((acc, current) => {
    acc[current.name] = [];
    return acc;
}, {} as TeamAssignments);

Sorting Students:

Creates a shallow copy of the students.
Sorts students by the number of project choices they provided (those with fewer choices are prioritized).

const sortedStudents = [...students].sort((a, b) => a.choices.length - b.choices.length);

Grouping Students:

By Preference: Groups students by their highest-ranked (first) project preference.
By Degree Type: Within each preference group, further groups students based on degree type (Hardware, Software, or Other) using the getDegreeType helper.
By Class Level: Further groups these students into lower-level ("2200") and upper-level ("3200") categories.

const groupedByPreference = groupStudentsByPreference(sortedStudents);
const groupedByDegree = groupStudentsByDegree(groupedByPreference);
const groupedByClass = groupStudentsByClass(groupedByDegree);

Assigning Students to Teams:

The function placeStudentsInTeams() assigns students to their top-ranked project. If a student has no preferences, they are assigned to the smallest team available..

Ensuring Upperclassmen Presence:

For each project, the function ensureUpperClassmen() verifies if there is at least one upperclassman (3200-level). If a team lacks an upperclassman, it searches for one from other teams that have a surplus and moves them accordingly.

if (!team.some(student => student.class === "3200")) {
    const availableUpperClassman = findAvailableUpperClassman(teams, project.name);
    if (availableUpperClassman) {
        const currentTeam = studentLocations.get(availableUpperClassman.name);
        if (currentTeam) {
            teams[currentTeam] = teams[currentTeam].filter(s => s.name !== availableUpperClassman.name);
            teams[project.name].push(availableUpperClassman);
            studentLocations.set(availableUpperClassman.name, project.name);
        }
    }
}

Balancing Team Sizes to Maintain a Fair Distribution

Calculates the minimum number of students per team. Iteratively moves students from teams that are above this threshold to those below it. The selection of a student to move is based on an “impact score” which factors in how the move might affect the student’s preference and the project’s class level balance.

To ensure teams are evenly distributed, balanceTeamsFixed() redistributes students until all teams meet a minimum size. This is determined as:

const minStudents = Math.floor(students.length / projects.length);

If a team is too small, a student is transferred from a larger team using findBestStudentToMove().

Determining Best Student to Move

To find the best student to move, calculateImpactScore() computes a score based on:

  • How much the move affects their preference ranking.
  • Whether they are a 3200-level student.
const preferenceScore = preferenceIndex === -1 ? 100 : preferenceIndex + 1;
const classScore = student.class === "3200" ? 0.5 : 1;
return (preferenceScore + classScore) / 2;

A lower impact score means the move is less disruptive to the student’s preferences.

Return:

Finally, the function returns the complete TeamAssignments mapping.

Clone this wiki locally