In the unit uStudent, could you please elaborate on the purpose of the records: TStudent and TStudents. I understand the former, but what is the function of the latter? What is the function of the TStudentArray?
TStudent packages data for a single student.
TStudents is a container for managing a group of students. TStudentArray simply provides indexed access to such a group, and allows you to enumerate every student in the group (if need be).
In mainStudents: Why is "uses uCreateStudentsDlg" placed after "implementation" whereas "uses uStudents" is placed earlier, between interface and type?
The uCreateStudentsDlg unit is only needed in the implementation of the TForm1 method CreateStudentsButtonClick, so that unit's visibility can be restricted to the implementation section. Whereas uStudents has to be in the interface because the interface contains a TStudents field in the TForm1 class. That type is declared in uStudents.
Some people put all needed units in the interface, even if the interface does not require them, and only the implementation section needs a particular unit or two.
I prefer to make the distinction and only use units that are absolutely required. It seems a cleaner way of working. It also minimises the possibility of name clashes where tens or scores of units are named in uses clauses, because the more units are used, the greater the possibility that some unit inadvertently duplicates the name of a variable or other entity. Sometimes a name clash is evident because the clashing codes wont compile in each other's scope. But in some rare situations a duplicate name can cause a silent bug in which the variable you imagine is being changed is not, but another remote variable of the same name is being changed instead.
I wasn't clear on the idea with grouping. Idea is that all students must join a certain group. This means that when user presses "Create random groups" user should be asked about number of students per group, and the program should create sufficiently many groups so that all students end up in a group. Say there are 12 students and user specifies 4 students per group, then program should generate 3 groups.
I just implemented what I took to be your ideas based on a few lines of description which were not a full specification.
My intent was to give you ideas to adapt, not to read your mind about the details of what you actually wanted.
In CreateRandomGroupButtonClick: What is purpose of rankSet, and how does Include(rankSet, r); work when basic type is Byte but r is an integer?
To create a 'balanced' group requires sorting the larger group of students into sub-groups based on rank, and choosing student(s) from each sub-group. Sets are a straighforward way of creating such sub-groups, and determining if a given student is inside or outside that group.
In the CreateRandomGroupButtonClick method rankSet is used more simply as a way of both counting the number of students added to the group, and ensuring that the same student is not added twice (since students are picked at random, the same random number could easily reappear in the sequence of choices).
The compiler casts the Integer r to a Byte variable for you (since the two are assignment-compatible), though I could have made an explicit typecast. I could also have declared r as a Byte variable in the first place, but did not do so because it is generally faster to use native integer types. Not that it makes the slightest difference in this case.
Regarding usage of the ranking parameter. The rank integer is a number I use to rank students according to performance. It doesn't align with number of students, instead it could follow a grading ranking, say numbers from 1 through 7 - even though there might be 30 students attending a class. This means several students will have the same rank and picking students for the balanced groups has to change a little.
Again, your requirement and definition of "rank" was not clear to me from what was originally written. So you will have to map your kind of rank to the simple ordering sequence I adopted. Or come up with a totally different approach.