This project was built upon the AddressBook-Level3 (AB3) codebase provided by the National University of Singapore’s CS2103T Software Engineering module.
Refer to the guide Setting up and getting started.
The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of main components and how they interact with each other.
Main components of the architecture
Main (consisting of classes Main and MainApp) is in
charge of the app launch and shut down.
The bulk of the app's work is done by the following four components:
UI: The UI of the App.Logic: The command executor.Model: Holds the data of the App in memory.Storage: Reads data from, and writes data to, the hard disk.Commons represents a collection of classes used by multiple other components.
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues
the command delete-a n/LeBron s/Basketball.
Each of the four main components (also shown in the diagram above),
interface with the same name as the Component.{Component Name}Manager class (which follows the corresponding API
interface mentioned in the previous point).For example, the Logic component defines its API in the Logic.java interface and implements its functionality using
the LogicManager.java class which follows the Logic interface.
Other components interact with a given component through its interface rather than the concrete class (reason: to
prevent outside components from being coupled to the implementation of a component), as illustrated in the (partial)
class diagram below.
The sections below give more details of each component.
The API of this component is specified in Ui.java
The UI consists of a MainWindow that is made up of parts e.g. CommandBox, ResultDisplay, AthleteListPanel,
OrganizationListPanel, ContractListPanel, StatusBarFooter, etc.
All these, including the MainWindow, inherit from the abstract UiPart class which captures the commonalities between
classes that represent parts of the visible GUI.
The UI component uses the JavaFX UI framework.
The layout of these UI parts is defined in matching .fxml files that are in the src/main/resources/view folder.
For example, the layout of the MainWindow
is specified in MainWindow.fxml.
The UI component,
Logic component.Model data so that the UI can be updated with the modified data.Logic component, because the UI relies on the Logic to execute commands.Model component, as it displays Athlete, Organization, and Contract objects
residing in the Model.API : Logic.java
Here's a (partial) class diagram of the Logic component:
The sequence diagrams below illustrate the interactions within the Logic component,
taking the add-a and delete-a commands as examples.
How the Logic component works:
Logic is called upon to execute a command, it passes the user input to an AddressBookParser object, which
in turn creates a parser that matches the command (e.g., AddAthleteCommandParser or DeleteAthleteCommandParser)
and uses it to parse the command.Command object (more precisely, an instance of one of its subclasses such as
AddAthleteCommand or DeleteAthleteCommand) which is executed by the LogicManager.Model when executed (e.g., to add or delete an athlete).
Although this is shown as a single step in the diagrams above for simplicity, the actual implementation involves
multiple interactions between the Command and the Model.CommandResult object, which is returned back from Logic.Here are the other classes in Logic (omitted from the class diagram above) that are used for parsing user commands:
How the parsing works:
AddressBookParser class creates an XYZCommandParser
(XYZ is a placeholder for the specific command name, e.g., AddAthleteCommandParser,
AddOrganizationCommandParser,
AddContractCommandParser, DeleteAthleteCommandParser, etc.), which uses the other classes shown above to parse
the user command and create an XYZCommand object (e.g., AddAthleteCommand).XYZCommandParser classes (e.g., AddAthleteCommandParser, DeleteAthleteCommandParser,
AddOrganizationCommandParser)
implement the Parser interface so that they can be treated uniformly (e.g., during testing).API : Model.java
The Model component,
Athlete, Organization, and Contract objects, which are contained in
UniqueAthleteList, UniqueOrganizationList, and UniqueContractList objects respectively.ObservableList<> objects (for example, ObservableList<Athlete>). This allows the UI
to automatically update when the underlying data changes.UserPrefs object that represents the user’s preferences. This is exposed to the outside as a
ReadOnlyUserPrefs object.Model represents domain data that should make sense
independently of other layers).API : Storage.java
The Storage component,
Athlete, Organization, and Contract information) and user preference
data in JSON format, and read them back into corresponding objects.AddressBookStorage and UserPrefsStorage, which means it can be treated as either one if only
the functionality of one is needed.Model component, because the Storage component’s job is to save and retrieve
objects that belong to the Model.Classes used by multiple components are in the seedu.address.commons package.
Contract Amount Handling
The application has been designed to handle large contract amounts that are common in professional sports:
long integers (64-bit) instead of int (32-bit)ensureNoTotalOverflow() method validates total contract amounts using predicate-based filtering and checks both athlete and organization totals before adding new contractssumForPredicate() to calculate current totals and wouldOverflow() to detect if adding a new contract would exceed the maximum limitNumberFormat for large amountsWhy long Instead of int
int limit: ~2.1 billion)int limitsThis section describes noteworthy details on how certain features are implemented.
The Find command enables users to perform keyword-based searches across different data types within the system —
athletes, organizations, and contracts — using flexible, case-insensitive, and fuzzy matching.
It temporarily filters the displayed lists in memory without altering any saved data.
The FindCommand extends Command and is invoked with one required flag that specifies the search scope.
The following flags are supported:
| Flag | Description |
|---|---|
-an | Finds athletes by name |
-as | Finds athletes by sport |
-on | Finds organizations by name |
-ca | Finds contracts by athlete name |
-co | Finds contracts by organization name |
-cs | Finds contracts by sport |
Example usage:
find -an Lionel
Upon execution, the command:
Model, depending on the flag.CommandResult reporting how many entities matched.
Each flag maps to a SearchScope enum constant that defines:
UiTab to display in the interfaceapply(Model, keyword) implementation that calls the relevant model filterThis enum-based design ensures that each scope encapsulates its filtering logic neatly within a single override, improving maintainability and readability.
The matching mechanism performs three-tier Levenshtein-based fuzzy matching implemented within the command itself:
This approach allows tolerant and human-friendly searches (e.g., find -an leo matches “Lionel Messi”;
find -co arsnal matches “Arsenal”).
The following scenario demonstrates how a typical command executes:
Step 1. The user executes find -co Arsenal.
Step 2. The parser constructs a FindCommand with scope CONTRACT_ORGANIZATION and keyword Arsenal.
Step 3. The command invokes model.updateFilteredContractList(predicate).
Step 4. The UI’s observable list updates, displaying all contracts linked to organizations matching “Arsenal”.
Step 5. A CommandResult reports the number of matching contracts and switches the active tab to Contracts.
Aspect: How search scope is determined
SearchScope) with one method per scope.
Aspect: Matching method
Target user profile:
Value proposition: The ultimate platform that empowers sports agents to stay organized, build stronger relationships, and drive success for their athletes and partners.
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a … | I want to … | So that I can… |
|---|---|---|---|
* * * | new user | see usage instructions | refer to instructions when I forget how to use the App |
* * * | sports agent | create a new athlete profile | keep track of the athletes I currently represent |
* * * | sports agent | delete an athlete profile | remove athletes I no longer represent |
* * * | sports agent | create a new organization | store details of teams, sponsors, or brands I work with |
* * * | sports agent | delete an organization | remove organizations that are no longer relevant |
* * * | sports agent | upload a new contract | track my athletes’ active agreements |
* * * | sports agent | delete a contract | keep my records up to date |
* * | sports agent | search for an athlete, organization, or contract | quickly find the information I need without scrolling |
* * | sports agent | edit an athlete's profile information | update their details as their career progresses |
* * | sports agent | edit an organization's information | keep organization details current and accurate |
* * | sports agent | edit a contract's information | keep contract details current and accurate |
* * | sports agent | sort contracts by amount | identify the most valuable deals quickly |
* * | sports agent | export contract data | share reports with clients or use in other applications |
* | sports agent | view analytics on contracts & deals | gain insights into performance and opportunities |
* | sports agent | link travel plans to competition and appearance schedules | coordinate logistics efficiently and avoid scheduling conflicts |
* | sports agent | manage and sync my athletes’ competition schedules and training events in a central calendar | coordinate effectively with teams, sponsors, and travel arrangements |
* | sports agent | set reminders for contract renewal dates | never miss important negotiation windows |
* | sports agent | track payment schedules within contracts | ensure timely payments and cash flow management |
* | sports agent | compare multiple contracts side by side | make informed decisions during negotiations |
* | sports agent | attach documents to contracts | keep all related paperwork in one place |
* | sports agent | receive notifications for contract milestones | stay informed of important contract events automatically |
* | sports agent | track commission earned from each contract | manage my own finances and business performance |
(For all use cases below, the System is the playbook.io and the Actor is the user, unless specified
otherwise)
Use case: Add Athlete Profile
MSS
Agent requests to add athlete
playbook.io creates and stores the new athlete profile
Use case ends.
Extensions
1a. The given command is invalid
1a1. playbook.io shows an error message
Use case ends.
1b. Missing required parameter
1b1. playbook.io shows an error message
Use case ends.
1c. The given parameter is invalid
1c1. playbook.io shows an error message
Use case ends.
2a. Duplicate athlete
2a1. playbook.io shows an error message
Use case ends.
Use case: Delete Athlete Profile
MSS
Agent requests to delete athlete
playbook.io deletes the athlete profile
Use case ends.
Extensions
1a. The given command is invalid
1a1. playbook.io shows an error message
Use case ends.
1b. Missing required parameter
1b1. playbook.io shows an error message
Use case ends.
1c. The given parameter is invalid
1c1. playbook.io shows an error message
Use case ends.
2a. No athlete found
2a1. playbook.io shows an error message
Use case ends.
2b. Athlete has active contracts
2b1. playbook.io shows an error message
Use case ends.
Use case: Add Organization Profile
MSS
Agent requests to add organization
playbook.io creates and stores the new organization profile
Use case ends.
Extensions
1a. The given command is invalid
1a1. playbook.io shows an error message
Use case ends.
1b. Missing required parameter
1b1. playbook.io shows an error message
Use case ends.
1c. The given parameter is invalid
1c1. playbook.io shows an error message
Use case ends.
2a Duplicate organization
2a1. playbook.io shows an error message
Use case ends.
Use case: Delete Organization
MSS
Agent requests to delete an organization
playbook.io deletes the organization profile
Use case ends.
Extensions
1a. The given command is invalid
1a1. playbook.io shows an error message
Use case ends.
1b. Missing required parameter
1b1. playbook.io shows an error message
Use case ends.
1c. The given parameter is invalid
1c1. playbook.io shows an error message
Use case ends.
2a. No organization found
2a1. playbook.io shows an error message
Use case ends.
2b. Organization has active contracts
2b1. playbook.io shows an error message
Use case ends.
Use case: Add Contract
MSS
Agent requests to add contract
playbook.io creates and stores the new contract
Use case ends.
Extensions
1a. The given command is invalid
1a1. playbook.io shows an error message
Use case ends.
1b. Missing required parameter
1b1. playbook.io shows an error message
Use case ends.
1c. The given parameter is invalid
1c1. playbook.io shows an error message
Use case ends.
2a. Athlete does not exist
2a1. playbook.io shows an error message
Use case ends.
2b. Organization does not exist
2b1. playbook.io shows an error message
Use case ends.
2c. Duplicate contract
2c1. playbook.io shows an error message
Use case ends.
Use case: Delete Contract
MSS
Agent requests to delete a contract
playbook.io deletes the contract
Use case ends.
Extensions
1a. The given command is invalid
1a1. playbook.io shows an error message
Use case ends.
1b. Missing required parameter
1b1. playbook.io shows an error message
Use case ends.
1c. The given parameter is invalid
1c1. playbook.io shows an error message
Use case ends.
2a. No contract found
2a1. playbook.io shows an error message
Use case ends.
Use case: Find Athlete
MSS
Agent requests to find an athlete, specifying either the athlete’s name or sport as a parameter
playbook.io returns the list of athletes
Use case ends.
Extensions
1a. The given command is invalid
1a1. playbook.io shows an error message
Use case ends.
1b. Missing required parameter
1b1. playbook.io shows an error message
Use case ends.
1c. The given parameter is invalid
1c1. playbook.io shows an error message
Use case ends.
2a. No athlete found
2a1. playbook.io returns an empty list
Use case ends.
Use case: Find Organization
MSS
Agent requests to find an organization, , specifying the organization’s name
playbook.io returns the list of organization
Use case ends.
Extensions
1a. The given command is invalid
1a1. playbook.io shows an error message
Use case ends.
1b. Missing required parameter
1b1. playbook.io shows an error message
Use case ends.
1c. The given parameter is invalid
1c1. playbook.io shows an error message
Use case ends.
2a. No organization found
2a1. playbook.io returns an empty list
Use case ends.
Use case: Find Contract
MSS
Agent requests to find a contract, specifying either the athlete’s name, sport, or organization’s name as a parameter
playbook.io returns the list of contracts
Use case ends.
Extensions
1a. The given command is invalid
1a1. playbook.io shows an error message
Use case ends.
1b. Missing required parameter
1b1. playbook.io shows an error message
Use case ends.
1c. The given parameter is invalid
1c1. playbook.io shows an error message
Use case ends.
2a. No contract found
2a1. playbook.io returns an empty list
Use case ends.
Use case: Refresh Data
MSS
Agent requests to refresh to clear any active search filters
playbook.io returns the latest lists of athletes, organizations, and contracts.
Use case ends.
Extensions
1a1. playbook.io shows an error message
Use case ends.
Use case: View Help Information
MSS
Agent requests to open the help window
playbook.io opens the help window
Use case ends.
Extensions
1a1. playbook.io shows an error message
Use case ends.
Use case: Close Session
MSS
Agent requests to exit the system
playbook.io closes the session
Use case ends.
Extensions
1a1. playbook.io shows an error message
Use case ends.
17 or above installed.Given below are instructions to test the app manually.
Note: These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.
Expected: Shows the GUI. The window size may not be optimum.
Expected: The most recent window size and location is retained.
add-a n/Lebron James s/Basketball a/40 p/99876543 e/James@example.comadd-a n/ s/Football a/39 p/87654321 e/cr7@example.comadd-a, add-a n/Messi2 s/Football a/39 p/87654321 e/cr7@example.com,
...delete-a n/Lebron James s/Basketballdelete-a n/Lebron James s/delete-a, delete-a n/Lebron James s/Basket-ball, ...add-o o/Nike p/98765432 e/partnerships@nike.comadd-o o/Nike p/+6598765432 e/partnerships@nike.comadd-o, add-o o/Nike123 p/98765432 e/partnerships@nike.com, ...delete-o n/Nikedelete-o n/delete-o, delete-o n/Nike1, ...add-c n/LeBron James s/Basketball o/Nike sd/01012024 ed/01012025 am/50000000add-c n/LeBron James s/Basketball o/Nike sd/01012024 ed/01012025 am/add-c,
add-c n/LeBron James s/Basketball o/Nike sd/01012024 ed/01012025 am/50.90, ...delete-c n/LeBron James s/Basketball o/Nike sd/01012024 ed/01012025 am/50000000delete-c n/LeBron James s/Basketball o/Nike sd/01012024 ed/ am/50000000delete-c,
delete-c n/ s/Basketball o/Nike sd/01012024 ed/01012025 am/50000000, ...find -an LeBron Jamesfind -as Basketballfind -anfind -as, find, ...find -on Nikefind -onfind, ...find -ca LeBron Jamesfind -cs Basketballfind -co Nikefind -cafind -cs, find -co, ...data folder.athletelist.json, contractlist.json, organizationlist.json).Expected:
contractlist.json is not empty but one or more of the other files are missing, all JSON files are re-generated as empty lists.athletelist.json).Expected: The app detects that the files are corrupted and loads empty lists for all entities.
⚠️ Important: New JSON files are only created once data is written (e.g., after adding an athlete, contract, or organization).
Expected: Data is persisted correctly in the JSON files.