Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/CS2103-AY1819S1-F10-2/main
Browse files Browse the repository at this point in the history
…into fix-ug-issues
  • Loading branch information
prokarius committed Nov 4, 2018
2 parents b63a674 + 9a7f184 commit 01b8393
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 120 deletions.
2 changes: 1 addition & 1 deletion docs/DeveloperGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ This is currently done by appending `-encrypt` to the password, and removing it
decrypting. For version 2.0, we plan to utilise existing libraries to encrypt and
decrypt our stored password.

// end::userconfirmation[]
// end::adminauthentication[]

=== Return a Loan feature

Expand Down
45 changes: 34 additions & 11 deletions docs/UserGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ Format: `listbikes`
Shows a list of all loans in the LoanBook. +
Format: `list`

=== \[Coming in v1.4\] Editing a bike: `editbike`
=== [Coming in v1.4] Editing a bike : `editbike`

To keep the system updated with any changes in the bicycles, this command allows details of a bicycle to be edited. +
Format: `edit BIKE_NAME [n/NEW_BIKE_NAME]`
Expand Down Expand Up @@ -147,26 +147,25 @@ We do not allow editing of the loan's start time or the return time because we w

=== Locating loans by keywords: `find`

Returns a loan based on parameters of LOAN_INDEX, PERSON_NAME or OBJECT_IDENTITY. +
Format: `find [i/LOAN_INDEX] [p/PERSON_NAME] [o/OBJECT_IDENTITY]`
Finds loans whose customers' names contain any of the given keywords. +
Format: find KEYWORD [MORE_KEYWORDS]

****
* The search is case insensitive. e.g `hans` will match `Hans`
* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans`
* Only the name is searched.
* Only full words will be matched e.g. `Han` will not match `Hans`
* Loans matching at least one keyword will be returned (i.e. `OR` search). e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang`
****

Examples:

* `search i/11037` +
Searches for the loan with LOAN_INDEX 11037
* `search p/James Tan` +
Searches for loans made by James Tan
* `search p/John Doe o/Bicycle-007` +
Searches for loans made by John Doe where the item loaned out is Bicycle-007
* `find John` +
Returns `john` and `John Doe`
* `find Betsy Tim John` +
Returns any loan having names `Betsy`, `Tim`, or `John`

=== \[Coming in v1.4\] Deleting the chosen bike from the loan book: `deletebike`
=== [Coming in v1.4] Deleting the chosen bike from the loan book : `deletebike`

Deletes a bike from the loan book. +
Format: `deletebike BIKE_NAME x/CURRENT_PASSWORD`
Expand Down Expand Up @@ -201,6 +200,7 @@ Examples:
* `delete i/11037 x/a12345` +
Deletes the loan with that has been indexed at position 11037.

// tag::setpass[]
=== Changing the password of the app: `setpass`

Change the current password of the app to `NEW_PASSWORD`. This ensures that critical commands such as `delete` and `reset` may be performed by authorized personnel only. +
Expand All @@ -215,6 +215,7 @@ Examples:

* `setpass a12345 n3wP4sS` +
Set the password of the app to `n3wP4sS`.
// end::setpass[]

=== Returning a loan: `return`

Expand Down Expand Up @@ -248,7 +249,29 @@ Examples:
* `return i/11037` +
Marks the loan with LOAN_INDEX 11037 as returned. Also automatically prints out the amount payable based on loan time and rate.

=== Hard reset the entire loan book: `reset`
// tag::searchcommand[]
=== Locating loans by date of loan: `search`

Returns all loans that was created between the range provided
Format: `search START_DATE END_DATE`

****
* Date format must be YYYY-MM-DD.
* The search is format sensitive sensitive. i.e. Date format must be strictly followed`.
* The search is determined on the date and time of loan created.
* Date provided must be valid. i.e. 2018-02-31 will return an error as it is not a valid date.
* The start date provided should be before end date. i.e. `search 2018-01-02 2018-01-01` will throw an error.
****

Examples:

* `search 2018-01-01 2018-01-01` +
Searches for loans with loan start date and time as 2018-01-01.
* `search 2018-01-01 2018-01-02` +
Searches for loans with loan start date and time between 2018-01-01 and 2018-01-02, inclusive.
// end::searchcommand[]

=== Hard reset the entire loan book : `reset`

Removes all the loans from the loan book and resets the LOAN_ID counter. +
Format: `reset`
Expand Down
59 changes: 26 additions & 33 deletions docs/team/weineng.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,44 @@
:stylesDir: ../stylesheets

== PROJECT: LoanBook
This portfolio page serves to showcases my contributions to the project, [https://github.com/CS2103-AY1819S1-F10-2/main[LoanBook]]. My resume and full portfolio can be found [https://weineng.io[here]].

---

== Overview
== Overview of Loanbook

AddressBook - Level 4 is a desktop address book application used for teaching Software Engineering principles. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC.

== Summary of contributions

* *Major enhancement*: added *the ability to undo/redo previous commands*
** What it does: allows the user to undo all previous commands one at a time. Preceding undo commands can be reversed by using the redo command.
** Justification: This feature improves the product significantly because a user can make mistakes in commands and the app should provide a convenient way to rectify them.
** Highlights: This enhancement affects existing commands and commands to be added in future. It required an in-depth analysis of design alternatives. The implementation too was challenging as it required changes to existing commands.
** Credits: _{mention here if you reused any code/ideas from elsewhere or if a third-party library is heavily used in the feature so that a reader can make a more accurate judgement of how much effort went into the feature}_
This section summarises the key contributions that I made to the project.

* *Minor enhancement*: added a history command that allows the user to navigate to previous commands using up/down keys.
* *Major enhancement*: added the ability to *set and change password to the application* and allow *searching for loans of specific dates*.
** What it does: Allow user to set password and change password for the app, so that critical comments that affects statistical integrity (Transaction summery & Tax-filing) cannot be performed by unauthorised personnel.
** Justification: This feature improves the product significantly because only authorized users are now able use the critical commands (E.g. `delete` command) to delete loans, which affects critical summery including tax-filling, revenue management.
** Highlights: This enhancement affects the security of the application and how existing commands and commands can leverage this in future release. It required an in-depth analysis of design alternatives. The implementation too was challenging as it required changes to existing commands.

* *Code contributed*: [https://github.com[Functional code]] [https://github.com[Test code]] _{give links to collated code files}_
* *Minor enhancement*:
*Create NRIC class and validate to ensure that only Singapore issued NRIC is provided.

* *Other contributions*:

** Project management:
*** Managed releases `v1.3` - `v1.5rc` (3 releases) on GitHub
*** Managed releases `v1.1` - `v1.4` (4 releases) on GitHub.
*** Added badges to show CI status, code quality and type of licence for the master branch [https://github.com/CS2103-AY1819S1-F10-2/main/pull/2[#2]][https://github.com/CS2103-AY1819S1-F10-2/main/pull/32[#32]]
** Enhancements to existing features:
*** Updated the GUI color scheme (Pull requests https://github.com[#33], https://github.com[#34])
*** Wrote additional tests for existing features to increase coverage from 88% to 92% (Pull requests https://github.com[#36], https://github.com[#38])
*** Improve data security by requiring a password before deletion.[https://github.com/CS2103-AY1819S1-F10-2/main/pull/96[#96]]
*** Add colour to tags [https://github.com/CS2103-AY1819S1-F10-2/main/pull/90[#90]]
** Documentation:
*** Did cosmetic tweaks to existing contents of the User Guide: https://github.com[#14]
*** Changed the gradle build script to display team name: [https://github.com/CS2103-AY1819S1-F10-2/main/pull/1[#1]]
** Community:
*** PRs reviewed (with non-trivial review comments): https://github.com[#12], https://github.com[#32], https://github.com[#19], https://github.com[#42]
*** Contributed to forum discussions (examples: https://github.com[1], https://github.com[2], https://github.com[3], https://github.com[4])
*** Reported bugs and suggestions for other teams in the class (examples: https://github.com[1], https://github.com[2], https://github.com[3])
*** Some parts of the history feature I added was adopted by several other class mates (https://github.com[1], https://github.com[2])
** Tools:
*** Integrated a third party library (Natty) to the project (https://github.com[#42])
*** Integrated a new Github plugin (CircleCI) to the team repo
*** PRs reviewed (with non-trivial review comments): [https://github.com/CS2103-AY1819S1-F10-2/main/pull/35[#35]], [https://github.com/CS2103-AY1819S1-F10-2/main/pull/24[#24]]
** Aesthetics:
*** Create application icon. [https://github.com/CS2103-AY1819S1-F10-2/main/pull/154[#154]

_{you can add/remove categories in the list above}_
** Tools:
*** Integrated TravisCI, AppVeyor, Coveralls, Codacy, and Netlify to the team repo [https://github.com/CS2103-AY1819S1-F10-2/main/pull/23[#23]]
*** Set up [https://cs2103-ay1819s1-f10-2.github.io/main/[team website]]
*** Set up slack notification and web hook for team.
**** This provides notification to developers on any updates to the repository.

== Contributions to the User Guide

Expand All @@ -50,23 +50,16 @@ _{you can add/remove categories in the list above}_
|_Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users._
|===

include::../UserGuide.adoc[tag=undoredo]
include::../UserGuide.adoc[tag=searchcommand]

include::../UserGuide.adoc[tag=dataencryption]
include::../UserGuide.adoc[tag=setpass]

== Contributions to the Developer Guide

|===
|_Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project._
|===

include::../DeveloperGuide.adoc[tag=undoredo]

include::../DeveloperGuide.adoc[tag=dataencryption]


== PROJECT: PowerPointLabs

---
include::../DeveloperGuide.adoc[tag=adminauthentication]

_{Optionally, you may include other projects in your portfolio.}_
//include::../DeveloperGuide.adoc[tag=dataencryption]
28 changes: 8 additions & 20 deletions src/main/java/loanbook/logic/parser/AddBikeCommandParser.java
Original file line number Diff line number Diff line change
@@ -1,33 +1,29 @@
package loanbook.logic.parser;

import static loanbook.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static loanbook.logic.parser.CliSyntax.PREFIX_NAME;

import java.util.stream.Stream;
import java.util.List;

import loanbook.logic.commands.AddBikeCommand;
import loanbook.logic.parser.exceptions.ParseException;
import loanbook.model.bike.Bike;
import loanbook.model.loan.Name;

/**
* Parses input arguments and creates a new AddBikeCommand object
* Parses input arguments and creates a new AddBikeCommand object.
*/
public class AddBikeCommandParser implements Parser<AddBikeCommand> {
public class AddBikeCommandParser extends ArgumentParser<AddBikeCommand> {

/**
* Parses the given {@code String} of arguments in the context of the AddBikeCommand
* and returns an AddBikeCommand object for execution.
* @throws ParseException if the user input does not conform the expected format
* @throws ParseException if the user input does not conform the expected format.
*/
public AddBikeCommand parse(String args) throws ParseException {
ArgumentMultimap argMultimap =
ArgumentTokenizer.tokenize(args, PREFIX_NAME);

if (!arePrefixesPresent(argMultimap, PREFIX_NAME)
|| !argMultimap.getPreamble().isEmpty()) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddBikeCommand.MESSAGE_USAGE));
}
ArgumentMultimap argMultimap = getArgumentMultimap(args,
List.of(PREFIX_NAME),
List.of(),
AddBikeCommand.MESSAGE_USAGE);

Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get());

Expand All @@ -36,12 +32,4 @@ public AddBikeCommand parse(String args) throws ParseException {
return new AddBikeCommand(bike);
}

/**
* Returns true if none of the prefixes contains empty {@code Optional} values in the given
* {@code ArgumentMultimap}.
*/
private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
}

}
41 changes: 8 additions & 33 deletions src/main/java/loanbook/logic/parser/AddCommandParser.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package loanbook.logic.parser;

import static loanbook.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static loanbook.logic.parser.CliSyntax.PREFIX_BIKE;
import static loanbook.logic.parser.CliSyntax.PREFIX_EMAIL;
import static loanbook.logic.parser.CliSyntax.PREFIX_LOANRATE;
Expand All @@ -9,8 +8,8 @@
import static loanbook.logic.parser.CliSyntax.PREFIX_PHONE;
import static loanbook.logic.parser.CliSyntax.PREFIX_TAG;

import java.util.List;
import java.util.Set;
import java.util.stream.Stream;

import loanbook.logic.commands.AddCommand;
import loanbook.logic.parser.exceptions.ParseException;
Expand All @@ -25,38 +24,22 @@
import loanbook.model.tag.Tag;

/**
* Parses input arguments and creates a new AddCommand object
* Parses input arguments and creates a new AddCommand object.
*/
public class AddCommandParser implements Parser<AddCommand> {
public class AddCommandParser extends ArgumentParser<AddCommand> {

public static final LoanId PLACEHOLDER_LOAN_ID = LoanId.fromInt(999999999);

/**
* Parses the given {@code String} of arguments in the context of the AddCommand
* and returns an AddCommand object for execution.
* @throws ParseException if the user input does not conform the expected format
* @throws ParseException if the user input does not conform the expected format.
*/
public AddCommand parse(String args) throws ParseException {
ArgumentMultimap argMultimap =
ArgumentTokenizer.tokenize(args,
PREFIX_NAME,
PREFIX_NRIC,
PREFIX_PHONE,
PREFIX_EMAIL,
PREFIX_BIKE,
PREFIX_LOANRATE,
PREFIX_TAG);

if (!arePrefixesPresent(argMultimap,
PREFIX_NAME,
PREFIX_NRIC,
PREFIX_PHONE,
PREFIX_EMAIL,
PREFIX_BIKE,
PREFIX_LOANRATE)
|| !argMultimap.getPreamble().isEmpty()) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
}
ArgumentMultimap argMultimap = getArgumentMultimap(args,
List.of(PREFIX_NAME, PREFIX_NRIC, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_BIKE, PREFIX_LOANRATE),
List.of(PREFIX_TAG),
AddCommand.MESSAGE_USAGE);

Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get());
Nric nric = ParserUtil.parseNric(argMultimap.getValue(PREFIX_NRIC).get());
Expand All @@ -71,12 +54,4 @@ public AddCommand parse(String args) throws ParseException {
return new AddCommand(loanWithPlaceholderId);
}

/**
* Returns true if none of the prefixes contains empty {@code Optional} values in the given
* {@code ArgumentMultimap}.
*/
private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
}

}
51 changes: 51 additions & 0 deletions src/main/java/loanbook/logic/parser/ArgumentParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package loanbook.logic.parser;

import static loanbook.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;

import java.util.ArrayList;
import java.util.List;

import loanbook.logic.commands.Command;
import loanbook.logic.parser.exceptions.ParseException;

/**
* Represents a Parser that parses a use input of only prefixed arguments
* for use by a {@code Command} of type {@code T}.
*/
public abstract class ArgumentParser<T extends Command> implements Parser<T> {

/**
* Generates an ArgumentMultimap from the given argument String and data specifications.
* @param argsString The String passed to the command, containing all the arguments.
* @param requiredArgs An array of Prefixes representing required data fields.
* @param optionalArgs An array of Prefixes representing optional data fields.
* @param msgUsage The message informing the user of the correct command usage.
* @return an ArgumentMultimap containing the data from {@code args}.
* @throws ParseException if the command does not have all required arguments, or has a pre-amble.
*/
protected ArgumentMultimap getArgumentMultimap(
String argsString,
List<Prefix> requiredArgs,
List<Prefix> optionalArgs,
String msgUsage) throws ParseException {

List<Prefix> allArgs = new ArrayList();
allArgs.addAll(requiredArgs);
allArgs.addAll(optionalArgs);
ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(argsString, allArgs);

if (!arePrefixesPresent(argMultimap, requiredArgs) || !argMultimap.getPreamble().isEmpty()) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, msgUsage));
}

return argMultimap;
}

/**
* Returns true if none of the prefixes contains empty {@code Optional} values in the given
* {@code ArgumentMultimap}.
*/
private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, List<Prefix> prefixes) {
return prefixes.stream().allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
}
}
Loading

0 comments on commit 01b8393

Please sign in to comment.