(P) Company

Goal: I will practice to read code written by another programmer and I will learn modularity.

I will practice to use recursion, pointers and dynamic memory management in more detail. I will also consider how to divide program into parts by using functions.

Instructions: Retrieve the code template: templates/07/company2/ -> student/07/company2/.

Important

Before starting to write code, read carefully the whole assignment. Especially, note the sections Implementing the program in stages (required commits) and Special requirements.

From the section Assessment, note especially that the program must first pass all automated tests. Otherwise the work will not be evaluated by assistants, and no points will be given.

Note

This project may (but does not have to) be done in pairs. For pair submissions, a group must be formed by submitting the form found in the left-hand menu under the title “Create a new group”. In addition, the submission box at the bottom of this page shows two options: “Submit alone” / “Submit in a group”. Be careful to select the correct option, as the choice cannot be changed afterwards. Only the Git repository address of one group member is submitted. Both names and other required information must be written in the code file comments.

You can look for a group via Kooditorio’s Discord link (see Timetable & links).

Implement the module Company into the program that first reads company information from the input file, and the permits the user to make searches concerning the relationships in the company.

To simplify the problem, you can assume that loop relationships are not possible, e.g. if A is the boss of B, then B cannot be the boss of A. The program will be tested only with reasonable test cases. Of course, if you want to practice more, you can make your program to not allow extraordinary relationships.

An essential “difficult” test case in automated tests is, for example, such that an employee has no boss (or the boss is not known). Your program must not crash with the cases like this, but it informs that the employee has no boss(es).

Header comment and feedback language

In the same way as earlier, the header comment is again required. This time the template code contains no header comment, but it is your task to write it. You can use the first project’s assignment as an example. Write the header comment in the file main.cpp.

The header comment must include at least:

  • a short description of the program

  • author’s name

  • student number

  • username

  • email address

  • a short description of the STL data structures used and commands implemented

  • justification of implementation choices (mandatory).

If working in pairs, include information for both students.

Unlike the first project, now there are more code files. Note the comments at the beginning of header files describing the class/module in question. Update them if necessary.

As in the previous project, the feedback language will be chosen in the submission box (at the very end of this page). We will only use the language you have given in the submission box of the final submission.

Modules of the program

The program consists of four modules: main, Cli, Utils and Company. The modules main, Cli, and Utils are ready-made by the course staff. Your task is to finish the module Company.

  • Module main starts the program. It asks for the user the input file and takes care of processing the input file.

  • Module Cli contains the command line interpreter of the program. It identifies the commands from the user input.

  • Module Utils contains some general utility functions. It is also a namespace.

  • Module Company implements a data structure, to which it is possible to store employees and their relationships. You must not edit the public part of the class, but in the private part, you can, for example, add those utility functions you wish.

You need not modify the ready-made functions. It is not necessary to understand the functionality of the command line interpreter. However, since the topic of the round is modularity, this is a good example to be explored as a whole.

Lines 149-162 in main.cpp contains code related to exception handling. The code checks the validity of the input. Exception handling is not a topic of this course, and thus, you should not pay too much attention to these code lines, and you need not understand the code.

Functionality of the program

The input of the program is a CSV file, from which the data will be read. The program parses the data and passes it to the Company module to be implemented by the student. After that the command line interpreter starts to search for information about the company. The actual command is case-insensitive, but the ID given as a parameter for the command is case-sensitive. IDs can also be enclosed with quotes.

  • QUIT - Closes the program.

  • PRINT - Prints all the employees stored in the program.

  • COLLEAGUES <ID> - Prints the colleagues of ID (sharing the same boss).

  • BOSSES <ID> <N> - Prints all the bosses of ID up to level N, i.e. with value 1 of N prints the boss of ID, with value 2 of N prints also the boss of the boss of ID, and so on.

  • SUBORDINATES <ID> <N> - Prints all the subordinates of ID up to level N, i.e. with value 1 of N prints the subordinates of ID, with value 2 of N prints also the subordinates of the subordinates of ID, and so on.

  • LONGEST <ID> - Prints the employee with the longest time in service, starting from ID and spreading to all the subordinates of ID.

  • SHORTEST <ID> - Prints the employee with the shortest time in service, starting from ID and spreading to all the subordinates of ID.

Functionality of the Company module

The file company.hh contains the ready-made struct for storing information about an employee. In a data structure to be implemented, each employee will be stored in the struct like this. You must dynamically allocate memory for these structs, and the structs are linked together with pointers that describe the boss-subordinate relationships. Start your task by exploring the definition of the struct.

When implementing the data structure, you can choose by yourself which container of STL you will use to store the pointers to structs, but the structs must be linked together as explained above.

General issues and error messages:

  • Each listed employee will be printed in a line of their own in the order that we call alphabetical order. This order is otherwise like the alphabetical one, but all upper-case letters precede all lower-case ones, i.e.: A ... Z a ... z. (This is the order used by string comparison operators < and >.)

  • If an existing person is tried to be inserted again, the program prints:

    Error. Employee already added.
    
  • To make the task easier: You need not take care of possible duplicates in adding boss-subordinate relationships.

  • You can assume that there are no loops in boss-subordinate relationships.

  • If the target employee of a command cannot be found, the program prints:

    Error. <ID> not found.
    
  • If a command targeting to a certain employee finds no matches, the program prints:

    <ID> has no <group to be printed>.
    

    where <group to be printed> can be e.g. subordinates, bosses, or colleagues.

  • In the commands SUBORDINATES and BOSSES: If N < 1, program prints:

    Error. Level can't be less than 1.
    

Short descriptions of the methods:

  • addNewEmployee - Based on the given information, creates a new employee that will be stored in the data structure. Note that in this phase, no boss nor subordinates are added yet.

  • addRelation - Completes the existing employees with boss-subordinate relationships, i.e. links the structs together by using pointers. If the boss given as a parameter does not exist, it is assumed that the given employee has no boss. This is not considered as an error, and no error message is given.

  • printEmployees - Prints all the employees stored in the data structure in alphabetical order as:

    <ID> <department> <time in service>
    
  • printColleagues - Prints the the colleagues of an employee (other employees with the same direct boss) in alphabetical order as:

    <ID> has <amount> colleagues:
    <ID1>
    <ID2>
    ...
    
  • printBossesN - Prints the bosses, up to level N, of a given employee as:

    <ID> has <amount> of bosses:
    <ID1>
    <ID2>
    ...
    
  • printSubordinatesN - Prints the subordinates, up to level N, of a given employee as:

    <ID> has <amount> of subordinates:
    <ID1>
    <ID2>
    ...
    
  • printLongestTimeInLineManagement - Prints the employee with the longest time in service, starting from the given employee and spreading to their subordinates as:

    With the time of <time in service>, <ID> is the longest-served employee in <ID>'s line management.
    

    or if the given employee themself is the longest-served one:

    With the time of <time in service>, <ID> is the longest-served employee in their line management.
    

    If there are two (or more) employees with the longest time in service, it does not matter, which to print.

    The command compares service times of <ID> and all their subordinates (whereupon direct and indirect subordinates, i.e. subordinates of subordinates as far as there are such are taken into account).

  • printShortestTimeInLineManagement - Prints the employee with the shortest time in service, starting from the given employee and spreading to their subordinates as:

    With the time of <time in service>, <ID> is the shortest-served employee in <ID>'s line management.
    

    or if the person themself is the shortest-served one:

    With the time of <time in service>, <ID> is the shortest-served employee in their line management.
    

    If there are two (or more) employees with the shortest time in service, print the one that is first in alphabetical order (or it is sufficient to print either of them, if your program passes automatic tests).

    The command compares service times of <ID> and all their subordinates (whereupon direct and indirect subordinates, i.e. subordinates of subordinates as far as there are such are taken into account).

Example data:

#CSV-fields
#<ID>;<Department>;<Time in service>;<Boss>

Margit;TiTe;15;Terhi
Kari;TiTe;7;Timo
Timo;TiTe;10;big boss
big boss;administration;1;
secretary;administration;4;big boss
Antti;TiTe;5;Kari
Terhi;TiTe;18;Timo
Eliisa;TiTe;5;Terhi
Mika;TiTe;10;Terhi
Minna;TiTe;1;Margit
Eero;Math;10;big boss
Markus;Math;5;Eero
Manu;Math;4;Eero
Jarno;TiTe;5;
Mikko;TiTe;0.5;Jarno
Arttu;TiTe;0.5;Jarno
lonely rider;desert;5;

Example execution:

Input file: data.txt
> print
Antti, TiTe, 5
Arttu, TiTe, 0.5
Eero, Math, 10
Eliisa, TiTe, 5
Jarno, TiTe, 5
Kari, TiTe, 7
Margit, TiTe, 15
Manu, Math, 4
Markus, Math, 5
Mika, TiTe, 10
Mikko, TiTe, 0.5
Minna, TiTe, 1
Terhi, TiTe, 18
Timo, TiTe, 10
big boss, administration, 1
lonely rider, desert, 5
secretary, administration, 4
> colleagues Margit
Margit has 2 colleagues:
Eliisa
Mika
> colleagues secretary
secretary has 2 colleagues:
Eero
Timo
> colleagues big boss
Error: Wrong amount of parameters.
> colleagues "big boss"
big boss has no colleagues.
> longest Timo
With the time of 18, Terhi is the longest-served employee in Timo's line management.
> longest Teri
Error. Teri not found.
> longest Terhi
With the time of 18, Terhi is the longest-served employee in their line management.
> subordinates Terhi 0
Error. Level can't be less than 1.
> subordinates Terhi 1
Terhi has 3 subordinates:
Eliisa
Margit
Mika
> subordinates Terhi 2
Terhi has 4 subordinates:
Eliisa
Margit
Mika
Minna
> subordinates Terhi 3
Terhi has 4 subordinates:
Eliisa
Margit
Mika
Minna
> bosses Margit 2
Margit has 2 bosses:
Terhi
Timo
> bosses Margit 7
Margit has 3 bosses:
Terhi
Timo
big boss
> bosses "big boss" 3
big boss has no bosses.
> colleagues Jarno
Jarno has no colleagues.
> bosses Jarno 1
Jarno has no bosses.
> subordinates Minna 1
Minna has no subordinates.
> subordinates "lonely rider" 5
lonely rider has no subordinates.
> bosses "lonely rider" 5
lonely rider has no bosses.
> quit

Tips for completing the assignment

  • Some of the functions do similar things (especially printLongestTimeInLineManagement and printShortestTimeInLineManagement). You should think carefully, which utility functions to implement in order to avoid repeating code.

  • Note that const functions inside a class cannot call non-const functions in the same class. You can notice this by the compilation error f[-fpermissive]. In other words, a function that cannot change the state of the object, cannot call a function that is able to change the state of the object.

  • Recall that as a default, the program will be compiled into a build directory. So, for testing purposes, you can move possible input data files to this same directory.

Implementing the program in stages

The assignment is intended to be implemented in multiple stages using version control. At minimum, your work should include several logical commits.

A possible order of implementation could for example be:

  • data structure design and file reading

  • inserting employees in the data structure

  • inserting employee relationships in the data structure

  • actual commands one by one

  • final polishing and comments.

Special requirements

The following requirements must be fulfilled in order to receive a passing grade for the assignment:

  • You must use the ready-made struct to store the data concerning each employee (struct Employee). You can find it from the file company.hh.

  • You must dynamically allocate memory for the employee structs. Pointers to these structs can be stored in any data structure, e.g. in an STL container chosen by yourself.

    • In dynamic memory management, use only smart (shared) pointers, not e.g. the commands new or delete.

  • Boss-subordinate relationships are stored by linking employee structs together by using pointers.

  • The input file may be opened for reading only once during program execution. All required information must be stored in memory during that read.

  • The public interface of the Company class must not be modified. You may add helper functions and data structures to the private section.

Evaluation

To end up to assistants’ evaluation, your work must first pass the automated tests. If the automated tests give 0 points for your work, also your final points will be 0, and your work will not be evaluated by an assistant.

The assistant evaluates the submissions that have passed the automated testing (= 1 p) and fulfilled the special requirements of the assignment based on the last commit before the deadline, according to the following criteria:

  • The overall principle of the solution: 0-20 points:

    • The learning goals of the exercise have been achieved.

    • The program code has been split into logical, suitably long segments using functions, classes, and/or methods.

    • If the program uses classes and objects, these have been implemented according to the basics of object-oriented programming (see About programming style in object-oriented programming).

    • The data structure does not include repetitive data nor unnecessary parts. The chosen data structures have been used in a reasonable way.

    • The program code does not include unnecessary repetitions nor other unnecessary parts.

    • The program code does not include unnecessary limitations or assumptions or other forced solutions.

    • The implementations of the program’s structures are easy to understand.

    • Global variables have not been used in the program code (global constants are OK).

    • The program does not terminate with the exit function.

    • Dynamic memory management has been used, and it has been implemented with smart pointers (shared_ptr), not e.g. with the commands new or delete.

  • Programming style: 0-20 points:

    • Note the sections About programming style on both project rounds.

    • Variables and functions are named clearly and appropriately. These items have named by using only one language, not e.g. Finnish and English mixed.

    • The program uses named constants instead of magic numbers.

    • The program code is neatly formatted.

    • The length of program code lines do not exceed 80 characters.

    • At the beginning of each file written/edited by yourself, there is a comment explaining the purpose of the file, your name, student number, and other necessary information.

    • At the beginning of each function/method (in the header file if such exists), there is a comment describing its working, return value and parameters.

    • There are comments in the code where necessary.

    • Comments are related to the current version of the program, not to an older one.

    • All comments have written in the same language (fi/en), but comments can be written in a language different from that used in naming variables and such.

    • All the variables have been initialized.

    • The compiler does not give warnings while compiling.

  • Using the version control: 0-10 points:

    • There are enough commits.

    • The content of commit messages is clear and relevant.

Note about evaluation

Automated tests check if your program works, but assistants pay attention to your coding style and other evaluation criteria listed above. Therefore, it could be possible that a fully working program brings you only zero points, if the above criteria are not met.

Requirements concerning especially good programming style can be found from the earlier material section on the current round.

Note about submission versions

The version to be evaluated is the one that corresponds to your latest successful Plussa submission (within the deadline). A successful submission means such a submission that passed automated tests.

After the first successful submission, you most probably want to improve your coding style (e.g. add comments), assuming that the deadline is not too close.

Anyway, remember finally this: After the final Git push, submit your work also in Plussa.

A+ presents the exercise submission form here.