Important

You must start working on the projects as soon as they are assigned to detect any problems and to address them with us well before the deadline so that we have time to get back to you.

Plenty of time will be provided for the completion of the project. Don’t wait for the last minute. There will be no extension or negotiation about project grades after the submission deadline.


Project 3: Profémon!

Well done! You’ve made it to the final project of the semester! Time to take the stage with your Profémons and prepare for the final battle! profemon

Introduction

In project 2, you learned how classes can be helpful to group data together into one package. However, classes can offer so much more than that! This project will test your knowledge about classes through the application of object-oriented programming.

Things you need to know for this project:


Implementation:

Work incrementally! Work through the tasks sequentially (implement and test). Only move on to a task when you are positive that the previous one has been completed correctly. Remember that the function prototypes and global-variables must be exactly as specified in this project specification. Lastly, do NOT use any libraries that we haven’t learned yet in class. If you don’t understand this project specification and its requirements, ask for clarification before you proceed. TEST YOUR CODE BEFORE SUBMITTING!!!


Task A: Gotta Catch Em’ All

cheer

Define and implement the Skill and Profemon class with a header and a source file (From now on, when you implement a class, assume you will implement two files: .hpp and .cpp).

The Skill class must have the following information stored in their private member variables:

- The name of the skill - The description of the skill - The total number of times the skill can be used - An integer that represents the specialty of the skill (0, 1 or 2)

The Skill class must have the following in it’s public access modifier:

/* @post : Initializes the name and description of the skill as "Undefined". Initializes the total uses of the skill and the skill specialty as -1 */ Skill();
/* @post : Parameterized constructor that sets the corresponding data members equal to the respective parameters */ Skill(std::string name, std::string description, int specialty, int uses);
/* @return : name of the skill */ std::string getName();
/* @return : description of the skill */ std::string getDescription();
/* @return : total uses of the skill */ int getTotalUses();
/* @return : specialty of the skill */ int getSpecialty();
/* @post : set the name of the skill equal to the given parameter */ void setName(std::string name);
/* @post : set the description of the skill equal to the given parameter */ void setDescription(std::string description);
/* @post : set the total uses of the skill equal to the given parameter */ void setTotalUses(int uses);
/* @return : Return 'true' if the given parameter is either 0, 1 or 2. Otherwise, return 'false' @post : set the specialty of the skill equal to the given parameter only if the given parameter is valid (0,1,2) Return 'true' if the specialty is successfully updated */ bool setSpecialty(int specialty);

The header file of the Profemon class must have an enumeration type called “Specialty” with three possible values: ML, SOFTWARE, and HARDWARE in this exact order. The enum should be defined outside the class.

The Profemon class must have the following information stored in their private member variables:

- The name of the profémon - The level of the profémon - The required experience to level up - The current experience - The maximum health level - The specialty of the profémon - A 'Skill' array of size 3 containing skills learned by the profémon

The Profemon class must have the following in it’s public access modifier:

/* @post : Initializes the name of the profémon as "Undefined" */ Profemon();
/* @post : Initializes the name, max health and specialty as the corresponding parameters. Set the required experience equal to 50. Initializes the current experience and level as 0 */ Profemon(std::string name, double max_health, Specialty specialty);
/* @return : name of the profémon */ std::string getName();
/* @return : specialty of the profémon */ Specialty getSpecialty();
/* @return : level of the profémon */ int getLevel();
/* @return : maximum health of the profémon */ double getMaxHealth();
/* @post : set the name of the profémon equal to the given parameter */ void setName(std::string name);
/* @param : experience points earned by the profémon @post : Increase the profémon's level based on the given 'exp'. The profémon will level up if it reaches the required experience. Depending on the profémon's specialty, the required experience goes up by a certain amount everytime the profémon levels up. 'ML' required experience goes up by 10, 'SOFTWARE' goes up by 15, and 'HARDWARE' goes up by 20. Make sure to update the required, current experience and level private data members accordingly. The given 'exp' can result in the profémon leveling up multiple times For example : starting at lvl 0, calling 'levelUp(115)' on different types of profémon would result in the following: ML: - new level: 2 - current exp: 5 - required exp: 70 SOFTWARE: - new level: 2 - current exp: 0 - required exp: 80 HARDWARE: - new level: 1 - current exp: 65 - required exp: 70 As stated above, each specialty has a different speed of leveling up */ void levelUp(int exp);
/* @param : the skill slot or index @param : the new skill to be learned @return : return 'true' if the skill has been successfully learned. Return 'false' if 'slot' parameters is not within the valid range(0,1,2) or the specialty of the 'skill' does not match the specialty of the profémon @post : if the given slot is valid(0,1,2) and the skill specialty matched with the profémon, add the 'skill' to the 'slot' index of the learned skills array */ bool learnSkill(int slot, Skill skill);
/* @param : bool indicating whether or not the profémon's skills should be printed @post : Prints the profémon's information in a specific format. Additionally, lists the profémon's skills if the given 'print_skills' parameter is true. Only print the skills that are not "Undefined" Format: (ProfemonName) [(Specialty)] | lvl (Level) | exp (CurrentExp)/(RequiredExp) | hp (MaxHP) (SkillNameSlot0) [(Uses)] : (description of skill in slot 0) (SkillNameSlot1) [(Uses)] : (description of skill in slot 1) (SkillNameSlot2) [(Uses)] : (description of skill in slot 2) For example: Maryash [SOFTWARE] | lvl 2 | exp 30/80 | hp 13500 OOP [30] : a programming paradigm based on the concept of objects Vector [30] : a c++ dynamic array library Pointer [10] : a pointer stores a memory address Note: There are four spaces before the each line of skills. The last line prints an endline. */ void printProfemon(bool print_skills);

You will submit the following files to gradescope:

profemon.hpp, profemon.cpp, skill.hpp, skill.cpp

Here is a sample main file. Make sure to add your own code to test all functions.

Compile your code locally using:

g++ skill.cpp profemon.cpp main.cpp

Task B: Profémon Trainers

profedex

In the world of Profémon, trainers are always busy training their beloved profémons for the battles to come. They are looking to challenge departments to a profémon battle and gain a degree. Departments are trainers who specialize in a single type of profémon. Since we have a working profémon class, it’s time to implement the Trainer class and some department classes which will inherit from the Trainer class.

Each trainer has a team of three profémons and a profédex. The profédex serves as a storage for all the profémons collected by the trainer. Each trainer also has a profémon which they choose to accompany them on their adventures!

Since the Department classes will inherit from the Trainer, the Trainer class should have the following protected data members:

- A vector of profémons which represents a profedéx - A profémon array of size 3 which represents the trainer's current team - A pointer to a profémon which is currently selected from the team

The Trainer class must have the following in it’s public access modifier:

/* @post : Initializes the pointer to the currently selected profémon as 'nullptr' */ Trainer();
/* @param : a vector of profémons @post : Adds the profémons from given parameter vector to the team and the profédex. If the team is full, add the profémons to the profedéx. Maintain the order of the given 'profemons' vector. Assume that the parameter vector has atleast one item. Select the profémon at 0 index of the team array to accompany the trainer */ Trainer(std::vector <Profemon> profemons);
/* @param : the name of a profémon @return : 'true' if profémon with given name is in the team or profedex, otherwise 'false' @post : return 'true' if the profémon with the name same as the given parameter is found either in current team, or in the profédex. Return false if the profémon is not found */ bool contains(std::string name);
/* @param : a profémon that is to be added @return : boolean indicating successful add operation @post : Add the given parameter profémon to the team or the profedex. Only add the profemon to profédex if the current team is full. If the profémon is being added to the team, add it to the smallest index possible. The profémon can't be added if another profémon with the same name already exists in the team or the profédex */ bool addProfemon(Profemon profemon);
/* @param : the name of the profémon that is to be removed @return : boolean indicating successful remove operation @post : remove the profémon with the given name from the current team or the profédex. If the profémon is removed from the profédex, make sure the order of the remaining profémons is maintained. If the profémon is on the team, it should be swapped with an empty profémon object. The profémon cannot be removed if no profémon with the given name exists in the team or the profédex. Hint : What is the default value of the profémons in an empty array of 'Profemon' objects? */ bool removeProfemon(std::string name);
/* @param : integer representing a slot in the team (0,1 or 2) @param : name of the profémon that is to be added to the team @post : assuming that a profémon with the given 'name' exists in the profédex and given 'slot' is valid (0,1,2), add the profémon to the team at the given slot. If the slot already contains a profémon, swap the profémon with the profémon that is being added to the team. If the 'slot' doesn't contain a profémon, move the profémon from the profédex to the slot For example : Let's suppose the current team array is: ["Enxhi", "Undefined", "Kimberly"] And profédex is: ["Sadab", "Yoomin", "Zilola", "Brandon"] If we call 'setTeamMember(1,"Yoomin")', the team and profédex becomes: Team: ["Enxhi", "Yoomin", "Kimberly"] Profédex: ["Sadab", "Zilola", "Brandon"] The profémon is moved to the team's empty slot (Undefined means empty) However, if we call 'setTeamMember(0,"Zilola")': Team: ["Zilola", "Undefined", "Kimberly"] Profédex: ["Sadab", "Yoomin", "Enxhi", "Brandon"] The profémon is swapped with the profémon in slot 0 */ void setTeamMember(int slot, std::string name);
/* @param : integer representing a slot in the team (0,1 or 2) @return : 'true' if the profémon at given slot is successfully chosen. Otherwise, return 'false' @post : choose a profemon to accompany the Trainer from the team (refers to the pointer Profemon data member). The profémon cannot be chosen if the given slot doesn't contain a profémon. Assume that the given 'slot' is valid(0,1,2) Hint : What is the name of the objects in an empty profémon array? */ bool chooseProfemon(int slot);
/* @return : profémon that is currently accompanying the trainer */ Profemon getCurrent();
/* @post : prints profémons in the profédex in a specific format Format : (Profemon1Name) [(Specialty)] | lvl (Level) | exp (CurrentExp)/(RequiredExp) | hp (MaxHP) (empty line) (Profemon2Name) [(Specialty)] | lvl (Level) | exp (CurrentExp)/(RequiredExp) | hp (MaxHP) (empty line) . . . PRINT ALL THE PROFEMONS IN THE PROFEDEX . . . (ProfemonName) [(Specialty)] | lvl (Level) | exp (CurrentExp)/(RequiredExp) | hp (MaxHP) (empty line) For example: Maryash [SOFTWARE] | lvl 2 | exp 30/80 | hp 13500 Saad [HARDWARE] | lvl 3 | exp 20/110 | hp 15000 Raja [ML] | lvl 1 | exp 10/60 | hp 35000 Hint : The format looks familiar from Task A doesn't it? */ void printProfedex();
/* @post : prints profémons in the team in a specific format. Do not print "Undefined" profémons Format : (Profemon1Name) [(Specialty)] | lvl (Level) | exp (CurrentExp)/(RequiredExp) | hp (MaxHP) (SkillNameSlot0) [(Uses)] : (description of skill in slot 0) (SkillNameSlot1) [(Uses)] : (description of skill in slot 1) (SkillNameSlot2) [(Uses)] : (description of skill in slot 2) (empty line) (Profemon2Name) [(Specialty)] | lvl (Level) | exp (CurrentExp)/(RequiredExp) | hp (MaxHP) (SkillNameSlot0) [(Uses)] : (description of skill in slot 0) (SkillNameSlot1) [(Uses)] : (description of skill in slot 1) (SkillNameSlot2) [(Uses)] : (description of skill in slot 2) (empty line) (Profemon3Name) [(Specialty)] | lvl (Level) | exp (CurrentExp)/(RequiredExp) | hp (MaxHP) (SkillNameSlot0) [(Uses)] : (description of skill in slot 0) (SkillNameSlot1) [(Uses)] : (description of skill in slot 1) (SkillNameSlot2) [(Uses)] : (description of skill in slot 2) (empty line) */ void printTeam();

csdepartment

Since you’ve been working so hard on this project, we will gift you the header file for the departments!

// This is an introductory comment #ifndef DEPARTMENT #define DEPARTMENT #include "trainer.hpp" class MLDepartment: public Trainer{ public: MLDepartment(std::vector<Profemon> profemons); bool addProfemon(Profemon profemon); }; class SoftwareDepartment: public Trainer{ public: SoftwareDepartment(std::vector<Profemon> profemons); bool addProfemon(Profemon profemon); }; class HardwareDepartment: public Trainer{ public: HardwareDepartment(std::vector<Profemon> profemons); bool addProfemon(Profemon profemon); }; #endif

Use a single .cpp file to implement all the department classes’ functions and constructors. For each of the derived classes, you need to change the implementation of the constructors and the addProfemon() function so that only the profémons of that particular specialty is added. For example: the MLDepartment can only have profémons of ML specialty. For the parameterized constructor, the given parameter vector can have profémons of all specialties. Add only the specialty that the Department specializes in. You can assume that the parameter vector will have atleast one profémon of correct specialty.

Submit the following files to gradescope:

profemon.hpp, profemon.cpp, skill.hpp, skill.cpp, trainer.hpp, trainer.cpp, department.hpp, department.cpp

Modify the main file from Task A to test your classes.

Compile your code locally using:

g++ skill.cpp profemon.cpp trainer.cpp department.cpp main.cpp

Credits: Genady Maryash, Ryan Vaz, Yoomin Song, Sadab Hafiz