Developer Guide
- Acknowledgements
- Setting up, getting started
- Design
- Implementation
- Documentation, logging, testing, configuration, dev-ops
- Appendix: Requirements
- Appendix: Instructions for manual testing
- Appendix: Effort
Acknowledgements
- This project is based on the AddressBook-Level3 project created by the SE-EDU initiative.
Setting up, getting started
Refer to the guide Setting up and getting started.
Design
.puml
files used to create diagrams in this document can be found in the diagrams folder. Refer to the PlantUML Tutorial at se-edu/guides to learn how to create and edit diagrams.
Architecture
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
has two classes called Main
and MainApp
. It is responsible for,
- At app launch: Initializes the components in the correct sequence, and connects them up with each other.
- At shut down: Shuts down the components and invokes cleanup methods where necessary.
Commons
represents a collection of classes used by multiple other components.
The rest of the App consists of 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.
How the architecture components interact with each other
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delcus 1
.
Each of the four main components (also shown in the diagram above),
- defines its API in an
interface
with the same name as the Component. - implements its functionality using a concrete
{Component Name}Manager
class (which follows the corresponding APIinterface
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 component’s 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.
UI 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
, CustomerListPanel
, 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 are 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,
- executes user commands using the
Logic
component. - listens for changes to
Model
data so that the UI can be updated with the modified data. - keeps a reference to the
Logic
component, because theUI
relies on theLogic
to execute commands. - depends on some classes in the
Model
component, as it displaysCustomer
object residing in theModel
.
Logic component
API : Logic.java
Here’s a (partial) class diagram of the Logic
component:
How the Logic
component works:
- When
Logic
is called upon to execute a command, it uses theAddressBookParser
class to parse the user command. - This results in a
Command
object (more precisely, an object of one of its subclasses e.g.,AddCustomerCommand
) which is executed by theLogicManager
. - The command can communicate with the
Model
when it is executed (e.g. to add a customer). - The result of the command execution is encapsulated as a
CommandResult
object which is returned back fromLogic
.
The Sequence Diagram below illustrates the interactions within the Logic
component for the execute("delcus 1")
API call.
DeleteCustomerCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Here are the other classes in Logic
(omitted from the class diagram above) that are used for parsing a user command:
How the parsing works:
- When called upon to parse a user command, the
AddressBookParser
class creates anXYZCommandParser
(XYZ
is a placeholder for the specific command name e.g.,AddCustomerCommandParser
) which uses the other classes shown above to parse the user command and create aXYZCommand
object (e.g.,AddCustomerCommand
) which theAddressBookParser
returns back as aCommand
object. - All
XYZCommandParser
classes (e.g.,AddCustomerCommandParser
,DeleteCustomerCommandParser
, …) inherit from theParser
interface so that they can be treated similarly where possible e.g, during testing.
Model component
API : Model.java
The Model
component,
- stores the art buddy data i.e., all
Customer
objects (which are contained in aUniqueCustomerList
object). - stores all
Commission
objects within their respectiveCustomer
object (which are contained in aUniqueCommissionList
object). - stores all
Iteration
objects within their respectiveCommission
object (which are contained in aUniqueIterationList
object). - stores the currently ‘selected’
Customer
as anObservableObject<Customer>
respectively, which lets us listen to changes to the selected customer for performing UI updates.- the same applies to the currently selected
Commission
.
- the same applies to the currently selected
- stores the current ‘sorted’ and ‘filtered’ objects (sorted based on the
sortcus
orfind
commands) as a separate sorted and filtered list which is exposed to outsiders as an unmodifiableObservableList<Customer>
that can be ‘observed’ e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. - stores the current list of
Commission
objects belonging to the selectedCustomer
(e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiableObservableList<Commission>
that can be ‘observed’ e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list changes. - stores a
UserPref
object that represents the user’s preferences. This is exposed to the outside as aReadOnlyUserPref
objects. - does not depend on any of the other three components (as the
Model
represents data entities of the domain, they should make sense on their own without depending on other components) - keeps track of the currently selected GUI tab using a
GuiTab
enum. The tab that the GUI displays is updated after each command is executed.
Tag
list in the AddressBook
, which Customer
references. This allows AddressBook
to only require one Tag
object per unique tag, instead of each Customer
needing their own Tag
objects.Storage component
API : Storage.java
The Storage
component,
- can save both address book data and user preference data in json format, and read them back into corresponding objects.
- inherits from
AddressBookStorage
,UserPrefStorage
andImageStorage
, which means it can be treated as any one of them (if only the functionality of only one is needed). - depends on some classes in the
Model
component (because theStorage
component’s job is to save/retrieve objects that belong to theModel
) - handles the following image functionality:
- loading of
BufferedImage
from a specified path in the image directory. - storing a
BufferedImage
within the image directory. -
Note: the image directory (in which all images are stored) is defined by
imageBaseDirectoryPath
withinUserPrefs.java
.
- loading of
Common classes
Classes used by multiple components are in the seedu.addressbook.commons
package.
Implementation
This section describes some noteworthy details on how certain features are implemented.
Commissions
The class diagram below shows our current implementation of the Commission
class.
Each commission in ArtBuddy
contains…
- a
Title
- a
Fee
- a
Deadline
- a
Completion Status
- a
Set<Tags>
with any number ofTag
s - an optional
Description
- a reference to its
Customer
object - a
UniqueIterationList
containing itsIteration
s
Commissions are currently stored in the individual Customer
’s UniqueCommissionList
.
Design Considerations:
Aspect 1: Location to store the commission objects
-
Alternative 1 (current choice): Store all commission objects within their individual customer objects.
- Pros:
- Easy to implement.
- Commands requiring commissions of a specific customer becomes more efficient.
- Cons:
- Commands requiring commissions from all customers are less efficient.
- Pros:
-
Alternative 2: Store all commission objects in
AddressBook
.- Pros:
- Commands requiring commissions from all customers can be more efficient.
- Cons:
- More difficult to implement, since a deleted customer’s commissions has to be individually deleted from this master list of commissions.
- Less efficient for commands for an individual customer’s commissions.
- Pros:
Aspect 2: How to store the commission objects in Customer
-
Alternative 1 (current choice): create a
UniqueCommissionList
class- Pros:
- Supports indexing of commissions already, which is convenient for most of our commands.
- Cons:
- Another class is necessary.
- Pros:
-
Alternative 2: Use
Set<Commissions>
- Pros:
- Individual customers’ data does not require “ordering”. Sets thus provide more efficient add/delete/find operations.
- Cons:
- Does not support indexing. Would still need another data structure in
ModelManager
when commands request commissions by index. - Edit becomes tedious to implement as it requires a combination of create and delete.
- Does not support indexing. Would still need another data structure in
- Pros:
Deleting a Commission (delcom
)
Deletes a commission based on user input, and deletes the commission from the active customer.
Implementation
This section explains how the delcom
command is implemented.
Support for the delcom
command is integrated with DeleteCommissionCommandParser
and DeleteCommissionCommand
.
It is important to note that our commission commands usually require retrieving the customer to operate on the customer’s commission list directly, due to our method of storing commissions (inside their Customer objects).
-
User specified arguments (the commission index) are passed to the DeleteCommissionCommandParser and the arguments are broken up by the ArgumentTokenizer and ArgumentMultimap.
-
The arguments will then be parsed by ParserUtil. An error will be thrown if the inputs were invalid or if no customer is selected yet.
-
A new DeleteCommissionCommand object will be initialised.
-
DeleteCommissionCommand#execute() will then get the currently shown list of commissions and identify the target commission to delete.
-
The customer is retrieved from the reference stored in the Commission object.
-
This customer and target commission is passed into Model#removeCommission to be removed directly from the customer’s commission list.
-
Model updates the GuiTab to show the Commission tab and selectedCommission to not show the deletedCommission and these changes are observed by the UI.
-
The success message will be returned to the user by the CommandResult.
The sequence diagram below shows the interaction between Logic
and Model
when delcom 1
is executed.
The parser part is omitted for brevity, but it is very similar to the other commands.
Iterations
Iterations help users keep track of the progress of their commissions. Each commission iteration essentially represents a version of the commissioned artwork.
Iterations contain:
- a
Date
, which uses aLocalDate
in its underlying implementation, representing the date tied to the iteration - an
IterationDescription
, which represents a textual description of the iteration - a
Path
, which is the file path of an image representing the iteration artwork - and a
Feedback
, which represents textual feedback to the iteration.
Since an iteration must be tied to a commission, this composition is captured by storing the
iterations in a UniqueIterationList
inside the associated commission object.
Adding an Iteration (additer
)
Adding an Iteration
creates an iteration based on the user input, and adds the iteration to the
active commission. Like all other add commands, users may either add an iteration via the
command line or the GUI.
Implementation
Support for the add iteration command is integrated with the AddIterationParser
,
which enables ArtBuddy to parse user input into an AddIterationCommand
. The
AddIterationCommand
stores the iteration created from the user inputs. This
iteration is added to the active commission’s UniqueIterationList
when the
AddIterationCommand
is executed by the LogicManager
.
Note that if there is no presently active commission, the iteration will not be added.
The sequence diagram below shows the interactions between the Logic, Model, and Storage components when
the user runs the command additer d/2022-10-10 n/Changed the colour scheme p//Users/john/Downloads/Draft 1.png
f/Updated colour scheme is much better
.
Design Considerations
Aspect 1: Image File Handling | |||
---|---|---|---|
Alternative | Pros | Cons | |
1 | Store and use the image at the file path specified in the additer command |
Easy to implement | The user might modify the image at the given file path. For instance, the image may be edited, renamed, moved, or entirely deleted. This imposes the constraint on the user not to modify their files if they do not wish for their files on ArtBuddy to be similarly modified, which is not ideal in most cases. In addition, it exposes ArtBuddy to some vulnerabilities that may lead to unexpected behaviour. For example, the user might change the file to an unsupported file type. All these potential failures have to be gracefully handled- which poses a big challenge because there are so many areas for error that some may be overlooked. Furthermore, many of these issues might not have ideal solutions that do not diminish the user experience and are easy to implement. |
2 | Make a defensive copy of the uploaded image (current) | Making a defensive copy of the uploaded image in ArtBuddy protects the images used in ArtBuddy from modification and the problems associated to user modification, as explained above. | Additional overhead will have to be added to the execution of additer commands,
because a copy of the image has to be made each time the command is executed.
Furthermore, it introduces deeper coupling between the `Logic` and `Storage` components since
the `AddIterationCommand` class in `Logic` would have to depend on `Storage` to copy the image into ArtBuddy.
|
Overall, the team felt that the tradeoffs in overhead and coupling were worth making due to the severity of bugs that could have been introduced in ArtBuddy otherwise. |
Aspect 2: Image Copy File Naming | |||
---|---|---|---|
Alternative | Pros | Cons | |
1 | Naming the copy of the image file with the original filename | - | There may be files with the same original file name. This could result in duplicate filenames in the ArtBuddy storage folder, which is not allowed. |
2 | Creating sub-folders for each customer and commission, where the image copy will be stored. The image copy files will be named after their iteration description. | As iteration descriptions are guaranteed to be unique within each commission, we can guarantee that all filenames within each folder will be unique. | Many nested folders would have to be created in ArtBuddy just to store iteration images.
In addition, it would introduce overheads into other commands, such as deliter
and edititer because the filenames of these files would have to be modified to
ensure they can be referenced to the correct iteration, and also avoid the issue with duplicate filenames.
Furthermore, iteration descriptions may contain characters that result in invalid filenames.
|
3 | Keeping a global count and naming the image copy file after its customer, commission and this global count. | Each combination of customer name and commission title is guaranteed to be unique. Also, since there is a restriction on customer names and commission titles, they are suitable to be used as filenames. Editing and deletion of iterations will not incur additional overheads as the unique global count would ensure that each iteration image remains uniquely identifiable after these commands. | Even though we are getting closer to a unique hash, editing and deletion of customers and commissions would still be problematic. These commands still require the filenames to be renamed- else, they would risk facing the same issue of duplicate filenames within the image storage folder. In addition, the introduction of a global variable would introduce a high level of coupling. |
4 | Use a randomly generated hash as the filename (current) | High probability of the unique filenames. Removed dependency on the state of the `Customer`, `Commission`, or `Iteration` object it belongs to. Hence, no additional overhead will be incurred with delete or edit commands. | While small, there is a non-zero probability of getting duplicate filenames |
Overall, the team agreed that using a randomly generated hash was definitely the most elegant way of handling file naming. Furthermore, the tradeoffs are almost negligible as duplicate filenames can be easily handled by generating a new hash until a unique filename is obtained. |
Documentation, logging, testing, configuration, dev-ops
Appendix: Requirements
Product scope
Target user profile:
- An artist who works through commissions
- has a need to manage clients and commissions
- wants to review past commission works and feedbacks
- wants to market himself to the right clients
- prefers desktop apps over other types
- is reasonably comfortable using CLI apps
- prefers typing to mouse interactions
Value proposition: Allows artists to hone their craft systematically and tune their artworks to fit the taste of their clients which ultimately builds their reputation.
User stories
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
* * * |
artist | exit from the program | |
* * * |
artist | get a list of all my commissions of one specific customer | |
* * * |
new user | get help | know how to use the product |
* * * |
artist eager to improve his craft | review past feedback given by customers | better the quality of my subsequent works |
* * * |
artist | delete commissions | |
* * * |
artist | view uploaded images of my previous commissions | |
* * * |
artist | upload images of art | |
* * * |
artist | create a customer entry | |
* * * |
artist with loyal customers | see customer’s repeated payment / commissions | start a loyalty program to encourage their purchases |
* * |
artist | prioritize my commissions | keep track of the most urgent commissions |
* * |
artist | categorize the artstyle of my commissions | |
* * |
artist | sort my commissions by due date | easily access all commissions with pressing due dates |
* * |
artist | search for commissions by date | |
* * |
artist | search for commissions by type | |
* * |
artist | search for commissions by name | |
* * |
artist who can offer multiple kinds of commissions | categorize the commissions | better analyse the commissions. |
* * |
artist who has similar customers | categorize them into groups | systematically review their feedback and apply the takeaways. |
* * |
artist who works traditionally | retain iterations of my work from the sketch phase to the final rendering | |
* * |
artist who creates non-commissioned works | determine potential customers who might be interested to purchase them | |
* * |
busy artist with several commissions ongoing | track the deadlines of each commission | ensure my work is delivered on time |
* * |
busy artist with several commissions ongoing | track my progress in each of them | |
* * |
artist keen to make my hobby a side hustle | determine the type of commissions that have proven lucrative | focus my efforts into these genres |
* * |
artist | update images of art | re-upload the image if I uploaded the wrong file |
* * |
artist | calculate my monthly income | |
* |
artist who may receive multiples of the same commission | duplicate my commissions | not have to manually enter the same information every time |
* |
long-time user | hide/archive old commissions | not be distracted by too much information |
* |
artist | store image references used when drawing the commission | |
* |
artist | clear all existing commissions | |
* |
artist | search for commissions by customers | |
* |
artist | search for commissions by multiple types(intersect) | |
* |
artist | search for commissions by multiple types(union) | |
* |
artist who works on multiple devices | transfer my application data from one device to the other |
Use cases
(For all use cases below, the System is ArtBuddy
and the Actor is the user
, unless specified otherwise)
Use case: View a Customer
MSS
- User requests to list customers.
- ArtBuddy shows a list of customers.
- User requests to open customer in the list.
-
ArtBuddy internally loads the list of commissions the customer made and the details and statistics of the customer.
Use case ends.
Extensions
-
1a. The customer list is empty.
Use case ends.
-
2a. The given index is invalid.
-
2a1. ArtBuddy shows an error message.
Use case ends.
-
Use case: Add a customer
MSS
- ArtBuddy shows a list of customers.
- User requests to add a customer and his or her details to the list.
-
ArtBuddy shows the updated list of customers.
Use case ends.
Extensions
-
2a. Necessary customer details not given.
-
2a1. ArtBuddy shows an error message.
Use case ends.
-
Use case: Edit a Customer
MSS
- ArtBuddy shows a list of customers.
- User requests to edit a customer in the list.
-
ArtBuddy edits the customer. ArtBuddy does not modify the commissions in the customer.
Use case ends.
Extensions
-
1a. The list is empty.
Use case ends.
-
2a. The given index is invalid.
-
2a1. ArtBuddy shows an error message.
Use case resumes at step 1.
-
Use case: Delete a Customer
MSS
- ArtBuddy shows a list of customers.
- User requests to delete a customer in the list.
-
ArtBuddy deletes the customer.
Use case ends.
Extensions
-
1a. The list is empty.
Use case ends.
-
2a. The given index is invalid.
-
2a1. ArtBuddy shows an error message.
Use case resumes at step 1.
-
Use case: Open a commission
MSS
- User enters a command to open a specific commission.
-
ArtBuddy shows the commission’s details.
Use case ends.
Extensions
- 1a. ArtBuddy detects an invalid command format.
-
1a1. ArtBuddy displays an error message informing User of the command format.
Use case ends.
-
- 1b. The given index is invalid.
-
1b1. ArtBuddy displays an error message.
Use case ends.
-
Use case: Add a commission
Preconditions: ArtBuddy currently has a customer opened.
MSS
- ArtBuddy shows the list of commissions from the opened customer.
- User requests to add a commission and its related details to the list.
-
ArtBuddy adds the commission and updates the list displayed.
Use case ends.
Extensions
-
2a. Necessary commission details not given.
-
2a1. ArtBuddy shows an error message.
Use case ends.
-
Use case: Edit a commission
MSS
- ArtBuddy shows the list of commissions.
- User requests to edit a specific commission in the list.
-
ArtBuddy edits the commission and updates the list displayed. ArtBuddy does not modify the iterations inside the commission.
Use case ends.
Extensions
-
1a. The commission list is empty.
Use case ends.
-
2a. The given index is invalid.
-
2a1. ArtBuddy shows an error message.
Use case ends.
-
Use case: Delete a commission
MSS
- ArtBuddy shows the list of commissions.
- User requests to delete a specific commission in the list.
-
ArtBuddy deletes the commission and updates the list displayed.
Use case ends.
Extensions
-
1a. The commission list is empty.
Use case ends.
-
2a. The given index is invalid.
-
2a1. ArtBuddy shows an error message.
Use case ends.
-
Use case: Add iteration to a commission
Preconditions: ArtBuddy currently has a commission opened.
Guarantees:
- An iteration, with an associated image, will be added to the specified commission only if its creation is successful
- The new iteration will not be created if the image provided is not valid (e.g. it does not exist, or it is not. of the correct image format).
MSS:
- User enters the command to add an iteration to the commission selected, specifying the image to use for the iteration using an absolute file path.
- ArtBuddy creates a new iteration for the commission, associated with the image specified.
-
ArtBuddy updates the GUI to also show the new iteration.
Use case ends.
Extensions:
- 2a. The specified file path the user specifies is invalid or does not exist.
-
2a1. ArtBuddy shows an error message, and notifies that a file does not exist.
Use case ends.
-
- 2b. The specified file under the file path is not a valid file type.
-
2b1. ArtBuddy shows an error message, and notifies that the filetype is invalid.
Use case ends.
-
Use case: Delete an iteration of a commission
Preconditions: ArtBuddy currently has a commission opened.
MSS:
- User enters a command to delete a specified iteration of the commission.
- ArtBuddy deletes the specified iteration and updates the GUI. Use case ends.
Extensions:
- 1a. The given index is invalid.
-
1a1. ArtBuddy shows an error message and asks the user to specify an iteration that exists.
Use case ends.
-
- 2a. The specified file path the user specifies is invalid or does not exist.
-
2a1. ArtBuddy shows an error message, and notifies that a file does not exist.
Use case ends.
-
- 2b. The specified file under the file path is not a valid file type.
-
2b1. ArtBuddy shows an error message, and notifies that the filetype is invalid.
Use case ends.
-
Use case: Delete an iteration of a commission
Preconditions: ArtBuddy currently has a commission opened.
MSS:
- User enters a command to delete a specified iteration of the commission.
- ArtBuddy deletes the specified iteration and updates the GUI. Use case ends.
Extensions:
- 1a. The given index is invalid.
-
1a1. ArtBuddy shows an error message.
Use case ends.
-
Use case: List all the customers
MSS:
- User enters a command to list all the customers.
- ArtBuddy updates the customer list to show all customers.
Use Case: Find customers by using filters and keywords
MSS:
- User enters a command with either tag filter or keyword search or both.
- ArtBuddy updates the customer list to show the customers who have the keywords given and passes tag filter.
Extensions:
- 1a. User does not provide keywords or tag filter.
-
1a1. ArtBuddy shows an error message.
Use case ends.
-
Use case: Sort customers by an options
MSS:
- User enters a command with a sort option.
- ArtBuddy updates the customer list to show the customers in sorted order by the given option.
Extensions:
- 1a. User does not provide a sort option.
-
1a1. ArtBuddy shows an error message.
Use case ends.
-
Use case: List commissions made by the customer
Preconditions: ArtBuddy currently has a commission opened.
MSS:
- User enters a command to list all commissions from the customer.
- ArtBuddy updates the commission list to show all commissions from the customer.
Use case: List all commissions made by all customers
MSS:
- User enters a command to list all commissions from all customers.
- ArtBuddy updates the commission list to show all commissions from all customers.
Use case: Find commissions by using filters and keywords
MSS:
- User enters a command with either tag filter or keyword search or both.
- ArtBuddy updates the commission list to show the commissions who have the keywords given and passes tag filter.
Extensions:
- 1a. User does not provide keywords or tag filter.
-
1a1. ArtBuddy shows an error message.
Use case ends.
-
Use case: View help
MSS:
- User enters command to show help.
- ArtBuddy shows a pop-up window that has link to ArtBuddy’s User Guide
Use case: Clear all customers
MSS:
- User enters command to clear all customers.
- ArtBuddy clears all customers and updates the GUI.
Use case: Exit the program
- User enters command to exit the program.
- ArtBuddy exits saving every change.
Non-Functional Requirements
- Should work on any mainstream OS as long as it has Java
11
or above installed. - A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
- The app should be designed for and used by a single user.
- The app data should be stored in a human-editable text file and not a DBMS.
- Images and other app assets should be stored locally and not in a remote server.
- The app should be well tested with a coverage of above 55% to allow bugs to be found more easily.
- The product should be usable on all standard screen resolutions above 1280x720.
- The product should be packaged within a single JAR file with a filesize of up to 100MB.
Glossary
- Mainstream OS: Windows, Linux, Unix, OS-X
- Customer: A contact detail. Contains information about the customer, and a list of commissions.
- Commission: An art piece requested by a customer that has been delivered or is in progress. Contains specifics about the commission and a list of iterations.
- Iteration: A single version of a commission. Contains an image and a text comment on the image.
- Tag: An additional field in customer or commission that can be used for tag filter feature.
Appendix: Instructions for manual testing
Given below are instructions to test the app manually.
Launch and shutdown
-
Initial launch
-
Download the jar file and copy into an empty folder
-
From the terminal,
cd
into that empty folder and runjava -jar artbuddy.jar
Expected: Shows the GUI with a set of sample customers, commissions and iterations. The window size may not be optimum.
-
-
Saving window preferences
-
Resize the window to an optimum size. Move the window to a different location. Close the window.
-
Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-
-
Shutdown
- Shutdown the application via closing the window or using the
exit
command.
- Shutdown the application via closing the window or using the
Commands
Customer-related commands
Note that you can run customer-related commands, even in the Commission view. That is a feature, not a bug.
1. addcus
Command
- Prerequisites: None.
- Test case:
addcus n/John Doe p/98765432 e/johnd@example.com t/tag
- Expected: New customer named John Doe appears on the customer list. Application switched to the Customer view. Details of new customer shown on the right pane.
- Test case:
addcus n/John Doe p/98765432 e/johnd@example.com t/tag
- Expected: Duplicate customer not added. Error message is displayed.
- Test case:
2. editcus
Command
- Prerequisites: There is at least one customer.
- Test case:
editcus 1 t/new tag
- Expected: The first customer should now only have one tag. Application switched to customer view. Edited customer’s details displayed on the right pane.
- Test case:
editcus 1
- No customer edited. Error details displayed.
- Test case:
editcus 0 t/new tag
- No customer edited. Error details displayed.
3. delcus
Command
- Deleting a customer while all customers are being shown
- Prerequisites: List all customers using the
list
command. Multiple customers in the list. - Test case:
delcus 1
- Expected: First contact is deleted from the list. Details of the deleted customer shown in the status message.
- Test case:
delcus 0
- Expected: No customer is deleted. Error details shown in the status message.
- Other incorrect delete commands to try:
delcus
,delcus x
,...
(where x is larger than the list size)
- Expected: Similar to previous.
- Prerequisites: List all customers using the
4. opencus
Command
- Prerequisites: At least one customer.
- Test case:
opencus 1
- Expected: Customer’s details shown on the right pane. If customer has any commissions, they can be seen with
listcom
.
- Expected: Customer’s details shown on the right pane. If customer has any commissions, they can be seen with
- Test case:
opencus
- Expected: No customer is selected. Error details in the status message.
- Test case:
Commission-related commands
Note that you can run commission-related commands, even in the Customer view. That is a feature, not a bug.
5. addcom
Command
- Prerequisites:
- There are customers.
- a customer should be selected (i.e. in the Customer view, you should see a customer on the right pane.)
If not fulfilled, run the
opencus
command, e.gopencus 1
.
- Test case:
addcom n/Tokyo Ghoul Kaneki f/50 d/2022-10-10 s/False p/Unfamiliar, I will need to do up a reference board first. t/digital t/neon
- Expected: Commission added to customer’s commission list. Application switches to the commission view. New commission details displayed on the right pane.
- Test case:
addcom n/Tokyo Ghoul Kaneki f/50 d/2022-10-10 s/False p/commission with the same name
- Expected: Commission is not added. Error message displayed.
6. editcom
Command
- Prerequisites:
- There are commissions in the displayed commission list.
- Test case:
editcom 1 t/tag
- Expected: Commission is edited. Application switches to Commission view. Edited commission’s details displayed on the right pane.
- Test case:
editcom 0
- Expected: No commission is edited. Error message displayed.
7. delcom
Command
- Prerequisites:
- There are commissions in the displayed commission list.
- Test case:
delcom 1
- Expected: Commission is deleted. Application switches to Commission view. If deleted commission was the selected commission, selected commission is reset on the right pane.
- Test case:
delcom 0
- Expected: No commission is deleted. Error message displayed.
8. opencom
Command
- Prerequisites:
- There are commissions in the displayed commission list.
- Test case:
opencom 1
- Expected: Application switches to Commission view. Selected commission’s details displayed on right pane.
- Test case:
opencom 0
- Expected: No commission is selected. Error message displayed.
Iteration-related commands
Note that you can run iteration-related commands, even in the Customer view. That is a feature, not a bug.
9. additer
Command
additer
command. You can refer to the User
Guide for more information.
- Prerequisites:
- A commission is selected. If not fulfilled, use the
opencom
command first.
- A commission is selected. If not fulfilled, use the
- Test case:
additer d/2022-10-10 n/Changed the colour scheme. p/{YOUR OWN FILE PATH HERE} f/Updated colour scheme is much better.
- Expected: A new iteration is created. You can see it in the right pane of the Commission’s view, at the bottom of the iteration’s list.
- Test case:
additer d/2022-10-10 n/Changed the colour scheme. p/{YOUR OWN FILE PATH HERE} f/Updated colour scheme is much better.
- Expected: Duplicate iteration not created. Error details displayed.
10. edititer
Command
- Prerequisites:
- A commission is selected. If not fulfilled, use the
opencom
command first. - The selected commission has at least one iteration.
- A commission is selected. If not fulfilled, use the
- Test case:
edititer 1 f/feedback changed
- Expected: Feedback of first iteration changed.
- Test case:
edititer 0
- Expected: No iteration edited. Error details displayed.
11. deliter
Command
- Prerequisites:
- A commission is selected. If not fulfilled, use the
opencom
command first. - The selected commission has at least one iteration.
- A commission is selected. If not fulfilled, use the
- Test case:
deliter 1
- Expected: Iteration deleted.
- Test case:
deliter 0
- Expected: No iteration deleted. Error details displayed.
Filtering / Sorting commands
12. list
Command
- Prerequisites: None.
- Test case:
list
- Expected: Switched to the Customer view. Customer list shows all customers.
13. find
Command
- Prerequisites: Technically, none. However, it is better to have some customers, so you can see the results of this command.
- Test case:
find k/Alex
- Expected: Switched to customer view. Filtered customer list shows all customers with
Alex
in their name.
- Expected: Switched to customer view. Filtered customer list shows all customers with
14. sortcus
Command
- Prerequisites: Technically, none. However, it is better to have some customers, so you can see the results of this command.
- Test case:
sortcus n/-
- Expected: Switched to Customer view. Customer list sorted in descending order of name.
- Test case:
sortcus n/+
- Expected: Switched to Customer view. Customer list sorted in ascending order of name.
15. listcom
Command
- Prerequisites: None.
- Test case:
listcom
- Expected: If a customer is selected, show all of customer’s commissions. Otherwise, show all commissions.
16. allcom
Command
- Prerequisites: None.
- Test case:
allcom
- Expected: Switched to Commission view. Commission List shows all commissions.
17. findcom
Command
- Prerequisites: Similar to
find
, technically, none. However, having some commissions will make it easier to see the results of this command. - Test case:
findcom k/1
- Expected: Switched to Commission view. All commissions with
1
in their name are displayed.
- Expected: Switched to Commission view. All commissions with
Saving data
-
Dealing with missing/corrupted data files
- Prerequisites:
- There is a data file. By default, it should be at
data/artbuddy.json
- There is a data file. By default, it should be at
- Remove the starting
{
, then launch ArtBuddy. - ArtBuddy’s customer and commission list will all be empty. The corrupted data file will be overwritten when new customers are added to ArtBuddy.
- To restart the application with sample data, delete the corrupted json file and re-run the application.
- Prerequisites:
Appendix: Effort
A significant volume of effort was expended to develop ArtBuddy from the original AB3.
This is due to AB3 dealing primarily with only one entity Person while ArtBuddy deals with three entities, Customer
,
Commission
and Iteration
.
Major changes:
- Adding two entirely new entity types,
Commission
andIteration
- Refactoring
Customer
andCommission
to use the Builder Pattern to support optional arguments - Supporting Images for
Iteration
- Creating CRUD commands for the two completely new models,
Commission
andIteration
- Designing
sort
command forCustomer
with many options for the user - Implementing
find
commands for bothCustomer
andCommission
with added tag filtering functionality - Redesigning the GUI
Challenges faced:
Revamping the GUI
Amongst these changes, the most challenging change must be updating the GUI.
Firstly, ArtBuddy’s three entities are very closely linked, with Commission
s belonging to a Customer
and
Iteration
s belonging to a Commission
. As a result, a lot of effort was expended to ensure the UI can properly
observe the models and filtered list. This is mostly facilitated by ArtBuddy’s custom ObservableObject
class.
A lot of listeners also had to be added in many parts of Model
and Ui
to ensure changes are properly propagated.
Secondly, ArtBuddy’s GUI has changed significantly from the original AB3 GUI. Multiple new components have been added, including tabs and split panes, pie charts for statistics, and even pop up windows and image drag and drop as an alternate way of adding customers, commissions and iterations. There are also a lot of CSS changes to make the product look more appealing to the user.
Creating new entities
Commission
and Iteration
are new entities and had to be written from scratch and integrated properly into all of
AB3’s components, such as Ui
, Model
, Storage
without breaking existing abstractions. The design had to clearly
thought out (e.g. which classes should help store the model and what methods are necessary) for easier implementation
of commands.
Implementing Images
Images for Iterations are a novel feature for ArtBuddy. There were many complications to consider:
- What if the file path is invalid?
- What if the file is not an image?
- What if the file is an image but not supported by JavaFx?
- What if the image file name is the same as another image?
- Images can have different dimensions. How should this be rendered in the GUI?
As a result, the implementation for this had to keep evolving in ArtBuddy, from a naive file copy to a more robust
implementation, a SimpleImageStorage
class using classes such as ImageIO
and BufferedImage
.