class School_Population {
constructor() {
this.students = []
this.groups = []
}
make_links() {
for (const student of this.students) {
student.links = []
}
for (const group of this.groups) {
group.make_links()
}
}
get_grade(grade) {
return this.students.filter(student => student.grade == grade)
}
remove_all_classrooms() {
this._classrooms = undefined
this.groups = this.groups.filter(d => d.link_type != "classroom")
this.students.forEach(student => {
student.links = student.links.filter(d => d.link_type != "classroom")
})
}
set_classrooms(list_of_rooms) {
this._classrooms = list_of_rooms
for (let classroom of list_of_rooms) {
this.groups.push(new Classroom(classroom.students))
}
}
build_classrooms(order = "random") {
let students
this.remove_all_classrooms()
if (order === "random") {
students = this.grades.map(grade => {
const students_in_grade = this.get_grade(grade);
d3.shuffle(students_in_grade);
return students_in_grade
})
}
if (order === "network") {
// Get the order from the current network.
students = this.networked_groups
}
// Builds empty classrooms.
const classrooms = this.classrooms;
for (let set_of_students of students) {
if (set_of_students === undefined) {continue}
// Sort the classrooms by how filled they are. This sorting will persist through the currently
// active group of students--for instance, a pod or something. Unless the classroom is filled.
classrooms.sort((a, b) => a.students.length - b.students.length)
for (let student of set_of_students) {
const grade_classes = classrooms.filter(room => room.grade === student.grade)
const unfilled_classes = grade_classes.filter(room => room.students.length < room.max_size)
let destination_class;
if (unfilled_classes.length > 0) {
destination_class = unfilled_classes[0]
} else {
grade_classes.sort((a, b) => a.length - b.length);
destination_class = grade_classes[0]
}
destination_class.students.push(student)
}
}
this.set_classrooms(classrooms)
return this._classrooms
}
get networked_groups() {
let current_group = -1
const completed = new Set()
// Approach in a random order.
d3.shuffle(this.students)
// Reset values.
this.students.forEach(student => student._assigned_group = undefined)
const queue = [...this.students]
const groups = []
while (queue.length > 0) {
// pop the first element off the queue.
const kid = queue.shift()
if (completed.has(kid.id)) {
// We've already done the kid.
continue
}
// All kids start unassigned; but students added
// b/c of links will get added earlier.
if (kid._assigned_group === undefined) {
kid._assigned_group = current_group++
groups[current_group] = []
}
for (const link of kid.links) {
const {student, link_type} = link
// Put the kid in this group;
student._assigned_group = current_group;
// move the kid to the top of the queue, so that all of
// their linkages will be followed before we move on.
queue.unshift(student)
}
completed.add(kid.id);
if (groups[current_group] === undefined) {
groups[current_group] = []
}
groups[current_group].push(kid);
}
return groups
}
}