This is Wang Shiyao’s Project Portfolio Page - highlighting his contributions to his CS2103T Software Engineering Project.
LiBerry
Overview
In the spirit of spreading education, literacy and a sense of community to the world (and completing our software engineering project), my team has developed Liberry - a desktop software for managing community and private libraries. The target users are mainly librarians in under-developed communities who cannot afford commercial versions of such software.
LiBerry can execute the basic functions of library management:
-
Addition and deletion of books in the catalog
-
Registering Borrowers and editing their particulars
-
Loan, return, renew and pay fine functions
-
Searching through books in the catalog by filters
As part of the requirements of the project, we were given the source code for a common AddressBook application and were tasked to morph it to something else that is useful. We were also limited to designing software that takes in the majority of user input through a Command Line Interface (CLI), though displays information through a Graphical User Interface (GUI).
This is what the GUI looks like:
My role was to:
-
configure the basic AddressBook software to accommodate Json-type storage for a catalog, a record of borrowers, and a record of loans
-
design the Find Command to execute given a set of parameters - such as searching by title, genre, loan status etc
-
Add a Clear Command to clear user searches
-
design the GUI in terms of color schemes
-
create the Toggle UI Command to allow users to switch the GUI between 'light mode' and 'dark mode' themes
-
Create sample data for testing
Summary of Contributions
Major enhancement - Finding by various parameters
Allows the user to filter the catalog by various parameters
What it does
-
Searches books in catalog and displays them on the screen through filtering by:
-
title
-
author
-
serial number
-
genres
-
loan status (available / loaned / overdue)
-
-
sets the number of books to display on the screen
Justification
As a librarian who is keeping charge of book and loan records, the ability to find books and their loan statuses fast is necessary.
Highlights
This enhancement was decently demanding as it required a way to test every book on whether it met the query requirements. It showcases my ability to play with functional programming and Streams in Java. As the predicate used has multiple possible combinations, extensive tests were written to ensure that it worked the way it should.
Minor enhancement - Switching GUI themes
Allows the user to toggle the GUI between 'light mode' and 'dark mode'.
Justification
As a librarian who may work after the sun has set, this command helps to switch the GUI into a more eye-friendly mode when using the software.
Highlights
This feature was rather challenging as it required a decent amount of CSS knowledge and the ability to manipulate JavaFx elements.
Other contributions
Project management
-
Managed the release of
v1.4-alpha
on GitHub. This is the final version of our software at Alpha release for final pre-release testing. The improvements made tov1.3
are:-
Feature: Undo and Redo
-
Feature: Toggle UI theme
-
GUI theme update
-
Additional sample data on startup
-
Bug fixes
-
Enhancements to existing features
Done through the following pull requests:
Documentation
Done through the following pull requests:
Community
-
Left a DG review on another group’s PR as a group
-
Posted a tip in the module forum (as a group) on making a code coverage check shortcut
-
Left a User Stories review on another group’s PR as a group
-
Tested another team’s PR and submitted bugs during Practical Exam Dry Run.
Contributions to the User Guide
Given below are sections I have contributed to in the User Guide. They showcase my ability to write documentation targeting end-users. The official User Guide is linked here. |
User Guide: Find Command
The following segment shows my description of the find
command which I have implemented in LiBerry.
Locating books by title: find
Shows all relevant books found.
Format: find [NUMBER] { [t/TITLE] [a/AUTHOR] [g/GENRE]… [sn/BOOK_SN] [-overdue] [-loaned] [-available] }
Format: find [NUMBER] { [t/TITLE] [a/AUTHOR] [g/GENRE]… [sn/BOOK_SN] [-overdue] [-loaned] [-available] [-rated] [-popular] [-new] }
- Coming in v2.0
Inputs for g/GENRE is automatically capitalized.
|
t/TITLE and a/AUTHOR are matched by partial spellings. Search t/phil if you forgot how to spell 'Philosopher'!
|
Examples:
-
find t/Animal Farm a/George Orwell
Searches for the book titled “Animal Farm” by the author “George Orwell”. -
find 3 g/mystery g/children -available
Searches for children mystery books that are not on loan and show the first 3 entries.
User Guide: Command Summary
The following segment shows my summary of all the commands in LiBerry. I made this so that users can have an overview of all the commands and be able to find the relevant one quickly without having to go through the entire User Guide.
This section contains the summary of LiBerry’s commands.
Commands applicable to both Normal and Serve mode:
-
Help :
help
-
Find a book :
find [NUMBER] { [t/TITLE] [a/AUTHOR] [g/GENRE]… [sn/BOOK_SN]] [-overdue] [-loaned] [-available] }
e.g.find t/Animal Farm a/George Orwell
,find 3 g/mystery g/children -available
[-rated] [-popular] [-new]
- Coming in v2.0 -
View book info :
info INDEX
-
Clear results :
clear
-
Add a book :
add t/TITLE a/AUTHOR sn/BOOK_SN [g/GENRE]… `
e.g. `add t/Harry Botter and the Baby’s Potty a/Reali Jolking sn/B02010 g/children -
Delete a book :
delete INDEX
ordelete sn/BOOK_SN
-
Register a borrower :
register n/NAME p/PHONE_NUMBER e/EMAIL
e.g.register n/matt p/83938249 e/matt@damon.com
-
Unregister a borrower :
unregister id/BORROWER_ID
-
Undo :
undo
-
Redo :
redo
-
Set user settings:
set [lp/LOAN_PERIOD] [rp/RENEW_PERIOD] [fi/FINE_INCREMENT] [mr/MAX_RENEWS]
-
Toggle UI theme:
toggleui
-
Rate a book :
rate INDEX r/RATING
- Coming in v2.0 -
Exit :
exit
-
Enter Serve mode :
serve id/BORROWER_ID
e.g.serve id/K0001
Commands applicable to Serve mode only:
-
Exit serve mode :
done
-
Edit a borrower’s particulars :
edit { [n/NAME] [p/PHONE_NUMBER] [e/email] }
e.g.edit p/91234567 e/jane@austen.com
-
Loan book :
loan sn/BOOK_SN
e.g.loan sn/B00201
-
Return book(s) :
return INDEX
orreturn -all
-
Renew book(s) :
renew INDEX
orrenew -all
-
Pay fines :
pay $AMOUNT
-
Reserve book :
reserve INDEX
orreserve sn/BOOK_SN
- Coming in v2.0
Contributions to the Developer Guide
Given below are sections I have contributed to in the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project. The official Developer Guide is linked here |
Book Finding is the main feature that I have implemented in LiBerry. The following is an extract from the Developer Guide that describes and explains the feature.
Book finding feature
The command for finding a book in the catalog is as follows:
find [NUMBER] { [t/TITLE] [a/AUTHOR] [g/GENRE]… [sn/BOOK_SN]] [-overdue] [-loaned] [-available] }
Details of Implementation
ModelManager contains a FilteredList
of Books
(filteredBooks
), which is used to display books on the LiBerry GUI. Book finding works by
starting converting the command string in to a BookPredicate
object, then updating filteredBooks
with that predicate.
The parsing of the command string to create the required BookPredicate
object is done with the help of the ArgumentTokenizer
object.
ArgumentTokenizer
tokenizes the command string to generate an
ArgumentMultimap
, which is internally a HashMap of predicate values paired to prefix keys. The FindCommandParser
then extracts all the values from the ArgumentMultimap
prefix by prefix and building the predicate through functions
such as setTitle()
, setGenres()
setLoanStatus
etc.
The diagram below shows a simplified command generation sequence of a 'find t/Animal Farm a/George' command, starting from the CatalogParser
The BookPredicate
class stores in its fields the specific values to match. Default values are mostly null, which will indicate that
there is no need to filter for that field. Below is an example.
The figure above shows what happens when we are trying to filter for books with title 'harry' and 'Potter' that are loaned out, showing up to 5 books only. Notice that the rest of the fields in the object are null.
Design Considerations
Aspect: Ensuring only 1 Loan Status Flag
In order for LiBerry to display only books that are loaned, available or overdue, flags are used. All flags have
the prefix -
, and the ArgumentTokenizer
is able to detect this. However, a user can technically enter more than 1
of such loan status flags eg. -loaned -available
. This is not meaningful, as there can be multiple interpretations of
this statement. The user could be looking for both types of books (which will show every book), or books that are both
loaned and available (which will show none). To prevent such meaningless confusion, there is a need for only 1 such
flag to be accepted in the BookPredicate
.
-
Alternative 1: Hard code a priority for loan status flags and accept the highest one when generating
BookPredicate
*-
Pros: Easy to implement, since Flags are implemented as
Enums
. -
Cons: Can be confusing to the reader as it is not clear why an unintended display is shown / why a certain priority exists.
-
-
Alternative 2 (Currently Used): Raise an exception whenever there are more than 1 loan status flags
-
Pros: Helps user clarify misconception of using more than 1 loan status flag
-
Cons: Slightly more complicated code where the flags obtained from
ArgumentMultimap
has to be counted, checked and selected.
-
Alternative 2 was chosen in the end as it conformed with the norms of directly informing the user of his mistake through the use of exceptions and error messages.
Aspect: Limiting the Number of Books to Display
As users generally do not want to be flooded with information when using the find command, a display limit [NUMBER]
is used. Users
can ask for a limited number of books to display. However, the FilteredList
JavaFx class that is used to implement the list of
filtered books does not have an API that sets a hard limit on the number of books to show. A work-around has to be made.
-
Alternative 1: Create an new class that extends the JavaFx
FilteredList
class that has a function that caps the number of items in the innerObservableList
.-
Pros: Does not require a change in other parts of the code. Interface is simple and elegant.
-
Cons: Hard to implement. Need to know the ins and outs of
FilteredList
andObservableList
.
-
-
Alternative 2 (Currently Used): Create a counter variable in
BookPredicate
that decrements after every passed test-
Pros: Easy to implement.
-
Cons: Not the cleanest and most developer friendly way of implementation.
-
Alternative 2 was chosen instead as the extension of FilteredList
would take too much time for the implementation of such a simple feature.
The cons of this choice will be compensated for in source code documentation to explain to developers how it works.
End of PPP
Thank you for reading this Portfolio Page. If you have any suggestions for LiBerry, for this page, or for me in general, contact me at wangshiyao@u.nus.edu!
Special thanks to my team for making this project a success!