Assignment 3.

You are required to implement a console-based Gym Management application. The application's architecture is illustrated below.

The components of the architecture are:

  • The MenuController provides a console-based user interface to the application's feature set.
  • The Gym API class implements the application's 'business logic'.
    • Reusable parts of the 'business logic' is delegated to a utility class.
  • The Data model contains classes based on the problem domain, e.g. Member, Trainer

The detail specification for each aspect of this architecture are provided in the sections that follow.

This assignment is worth 40% of your overall grade.

Starter Pack.

Download this archive and unzip it. The base folder, Assignment3 is an InterriJ skeleton project. Open it inside your InyrlliJ environment.

You are required to develop the application code in the classes of the src/main folder. Some classes already contain initial code to help you get started - although this code is incomplete. The src/test folder contains unit test code, which will be provided incrementally (via Slack) over the duration of the assignment.

Data model requirements.

The app's data model consists of the following entities: Premium Member, Student Member, Trainer, and Assessment. Clearly the two member types will have common fields and methods (see below). Applying an inheritance design to their implementation will be rewarded with additional marks - see grading spectrum. Inheritance also applies between Trainer and Member (a Person type) which must be implemented. A visual representation of the data model is shown below:

The design detail for the classes are as follows:

  • Person - Stores email, name, address and gender. The email is used to uniquely identify a person in the system.
  • Member - Subclass of Person. Stores a person’s height, starting weight, chosenPackage and a hashmap to record all the member's progress i.e. assessments performed by trainers. The map key will be the date (as a string) the assessment was performed, in the format YY/MM/DD, e.g. 18/05/04 (required for sorting - see later). The map values will be an assessment's details - see Assessment object later.

  • PremiumMember - Subclass of Member. Stores no additional data.

  • StudentMember - Subclass of Member. Stores studentId and collegeName.
  • Trainer - Subclass of Person. Stores the trainer’s specialty.

The following rules should be applied to these entities:

  • The following validation rules apply to these fields (fields not listed below indicates that no validation is done on them):

    • Height is measured in metres and must be between 1 and 3 inclusive.
    • Starting Weight is measured in kgs and must be between 35 and 250.
    • The name is maximum 30 characters; any name entered should be truncated to 30 characters.
    • The gender can be either “M” or “F”. If it is not either of these then apply a default value of “Unspecified”.
  • The Person class should have a String toString() method that formats the printing of the object state and returns it. It’s subclasses should override the superclass method String toString(), call the superclass toString method and also report on the new fields defined in these subclasses.

  • Each class should define a constructor that initialises each instance fields based on user input data.
  • Each class should define accessors and mutators for all instance fields, except for the following cases:
    + Assessment hashmap (Member) - no mutator.
    + Email (Person), StudentId and CollegeName (both StudentMember) - no mutators.

Specifics for class Member:

  • public Assessment latestAssessment() - Returns the latest assessment based on last entry (by calendar date).
  • public SortedSet sortedAssessmentDates() - Returns the assessments dates (as strings) sorted in date order.
  • public abstract void chosenPackage(String chosenPackage); The concrete implementation of this method will be completed in Member subclasses.

Specifics for class PremiumMember:

  • public void chosenPackage(String packageChoice) - Provides the concrete implementation for this method. The chosenPackage is set to the value passed as a parameter. There is no validation on the entered data.

Specifics for class StudentMember:

  • public void chosenPackage(String packageChoice) - Provides the concrete implementation for this method. The chosenPackage is set to the package associated with their collegeName. If there is no package associated with their college, default to “Package 3”.

The last model class is Assessment. It stores weight, thigh, waist, comment and a Trainer that entered the member’s assessment (i.e. personal trainer). This class just has the standard constructor, accessor and mutator method with no validation on any fields.

Gym API.

This class operates between the model classes and the menu driver class (see later). It stores:

  • an ArrayList of Members
  • an ArrayList of Trainers.

It contains the following, self-explanatory methods:

  • public void addMember(Member member)
  • public void addTrainer(Trainer trainer)
  • public int numberOfMembers()
  • public int numberOfTrainers()
  • public ArrayList (of Members) getMembers()
  • public ArrayList (of Trainers) getTrainers()

The class also contains these methods:

  • public boolean isValidMemberIndex(int index) - Returns a boolean indicating if the index passed as a parameter is a valid index for the member’s array list.
  • public boolean isValidTrainerIndex( int index ) - ditto for trainers array list.
  • public Member searchMembersByEmail(String emailEntered) - Returns the member object that matches the email entered. If no member matches, return null.
  • public ArrayList (of Strings) searchMembersByName(String nameEntered) - Returns a list of member names that partially or entirely matches the entered name. An empty array is returned when their are no matches.
  • public Trainer searchTrainersByEmail(String emailEntered) - Returns the trainer object that matches the email entered. If no trainer matches, return null.
  • public ArrayList (of Members) listMembers() - Returns a list containing all the members in the gym. Returns an empty list if none are found.
  • public ArrayList (of Member) listMembersWithIdealWeight() - Returns a list containing all the members details in the gym whose latest assessment weight is an ideal weight (based on the devine method). Returns an empty list if none are found.
  • public ArrayList (of Member) listMembersBySpecificBMICategory (String category) Returns a string containing all the members details in the gym whose BMI category(based on the latest assessment weight) partially or entirely matches the entered category. Returns an empty list if none are found.
  • public String listMemberDetailsImperialAndMetric() List, for each member, their latest assessment weight and their height both imperially and metrically. The format of the output is like so:

Joe Soap: xx kg (xxx lbs) x.x metres (xx inches). Joan Soap: xx kg (xxx lbs) x.x metres (xx inches).

If there are no members in the gym, the message "No registered members" should be returned.

  • public void store() throws Exception - Push the members and trainers array lists out to the associated XML file.
  • public void load() throws Exception - Pull the members and trainers array lists from the associated XML file.

Utility class.

A utility class (or helper class) is a "structure" that has only static methods and encapsulates no state (fields). Typically the functionality of the methods is reusable across a range of applications.

For the Gym management application we can define an Analytics class that would hold the following methods:

  • public static double calculateBMI(Member member, Assessment assessment) - Return the BMI for the member based on the calculation: BMI is weight divided by the square of the height.
  • public static String determineBMICategory(double bmiValue) - Return the category the BMI belongs to, based on the following values:

    • BMI less than 16 (exclusive) is "SEVERELY UNDERWEIGHT"
    • BMI between 16 (inclusive) and 18.5 (exclusive) is "UNDERWEIGHT"
    • BMI between 18.5 (inclusive) and 25(exclusive) is "NORMAL"
    • BMI between 25 (inclusive) and 30 (exclusive) is "OVERWEIGHT"
    • BMI between 30 (inclusive) and 35 (exclusive) is "MODERATELY OBESE"
    • BMI greater than 35 (inclusive) and is "SEVERELY OBESE"
  • public static boolean isIdealBodyWeight(Member member, Assessment assessment) - Returns a boolean to indicate if the member has an ideal body weight based on the Devine formula:

    • For males, an ideal body weight is: 50 kg + 2.3 kg for each inch over 5 feet.
    • For females, an ideal body weight is: 45.5 kg + 2.3 kg for each inch over 5 feet.
    • Note: if no gender is specified, return the result of the female calculation.
    • Note: if the member is 5 feet or less, return 50kg for male and 45.5kg for female.

MenuController class.

The menu driver class (MenuController) uses the console I/O to interact with the user. It should create an instance of the GymApi class and allow the user to navigate (a subset of) the system's features through a series of menus. The following processing is required in this menu system:

  1. On app start-up, automatically load the gym data (trainers and members) from an XML file.
  2. Ask the user do they want to login(l) or register (r).
  3. Ask the user if they are a member(m) or a trainer(t).
    • If the user selected to login, verify that the email entered is stored in the appropriate arraylist i.e. the members or trainers list. If the email doesn’t exist, print out “access denied” to the console and exit the program.
    • If the user selected to register, ask them to enter the required details for the member/trainer. If they entered an email that is already used in the system (for either trainers/members), let them know it is an invalid email and ask them to enter a new one.
  4. Once logged in, display a trainer menu for the trainer and a member menu for the member.

    1. The trainer menu should allow the trainer to:
      • Add a new member
      • List all members
      • Search for a member by email
      • Assessment sub-menu:
        • Add an assessment for a member
        • Update comment on an assessment for a member
    2. The member menu should allow the member to:
       + View their profile
       + Update their profile
       + Progress sub-menu:
          + View progress by weight
          + View progress by waist measurement
  5. On app exit, automatically save the gym data (trainers and members) to an XML file.

Notes:

Note 1: Aside from the above requirements, the design of the menu system and the contents you include is left open to you. The qualities to aim at include user-friendliness (e.g. report progress) and robustness (e.g. validation, formatted output).

Note 2. The following packages can be hard coded in this class into a HashMap:

("Package 1", "Allowed access anytime to gym.\nFree access to all classes.\nAccess to all changing areas including deluxe changing rooms.");

("Package 2", "Allowed access anytime to gym.\n€3 fee for all classes.\nAccess to all changing areas including deluxe changing rooms.");

("Package 3", "Allowed access to gym at off-peak times.
\n€5 fee for all classes. \nNo access to deluxe changing rooms.");

("WIT", "Allowed access to gym during term time.
\n€4 fee for all classes.  \nNo access to deluxe changing rooms.");

Ideally, this data would be read in from a file, however, we can just hard-code them for the purposes of this assignment.

Note 3. The options on the progress sub-menu should ideally display the member’s progress based on the metric chosen (e.g. weight). It should display the metric sorted by date and some form of indication as to whether the subsequent measurement was above or below the previous measurement.

Unit tests.

As noted earlier, the menu controller exercises only a portion of the API's feature set. For this reason, a full suite of unit test will be provided to prove the entire API and utility classes. You are not required to edit or indeed understand the test code as it was not part of the curriculum. You are simply required to run the tests and fix any logic errors it reports in your code - as illustrated in the lab exercise earlier. The test execution output is presented in a 'GIVEN-WHEN-THEN' fashion and will identify the specific class method with the bug as well as the conditions that produced it.

The starter pack provided in the first section of this specification has the test required for the Pass mark level in the grading spectrum. Only the GymAPUTest and MemberTest files are relevant for this level. Tests for the higher grades will be provided incrementally over the duration of the assignment.

Grading spectrum.

Pass (40-50) - Data Model: Basic implementation (Person, Member and Trainer). API: Add members/trainers, numberofMembers/Trainers methods, isValidMember/TrainerIndex methods, basic addMember/Trainer. Menu: Registration, Add New member, List all members. Input validation.

Good (50-65) - API: Various Search methods (by email and name), ; XML persistence. Menu: Login, Trainer and Member sub-menus, (Trainer) Add/List/Search members, (Member) View/update profile.

Excellent (65-85) - Data Model: Assessment class basic support. API: Utility class. Menu: (Trainer) Add assessment, Update assessment comment. Most unit tests pass

Outstanding (85-100) - Data model: Student and Premium Member support; Member assessment query support. API: Fully-featured. Menu: (Member) Progress sub-menu options; Fully-featured. All unit tests pass.

Handup of submission

When

The submission is due Sunday, 20th May 2018, 11.55PM.

No late submissions will be accepted (unless mitigating circumstances, with supporting documentation, apply).

Where

The dropbox is available in the 'Assignments' section in Moodle.

What

You received a skeleton IntelliJ project folder at the start of this assignment and developed your code inside it. Create an archive of this folder and simply name it Assignment3,zip (or .rar etc). Submit this archive.

Your files should be contained in a folder named according to the rule:

README

You should include a README text file in the project's base folder. The contents of should be as follows:

Name : 
Student Number:

A statement of how much of the application specification you implemented. 

Any extra features you wish to bring to the assessors attention, i.e. extra 
functionality, Java syntax not covered in the lectures, 
non-standard Libraries used 

Known bugs/problems:

Any sources referred to during the development of the assignment (no need to reference lecture/lab materials):