diff --git a/.gitignore b/.gitignore index 5e59b862ba4..633c9b61726 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,5 @@ src/test/data/sandbox/ # MacOS custom attributes files created by Finder .DS_Store + +# Do not add docs folder \ No newline at end of file diff --git a/README.adoc b/README.adoc index e36efe534bb..e5ffb330991 100644 --- a/README.adoc +++ b/README.adoc @@ -1,8 +1,7 @@ = Address Book (Level 3) ifdef::env-github,env-browser[:relfileprefix: docs/] -https://travis-ci.org/se-edu/addressbook-level3[image:https://travis-ci.org/se-edu/addressbook-level3.svg?branch=master[Build Status]] -https://ci.appveyor.com/project/damithc/addressbook-level3[image:https://ci.appveyor.com/api/projects/status/3boko2x2vr5cc3w2?svg=true[Build status]] +https://travis-ci.org/se-edu/addressbook-level3[image:https://travis-ci.org/AY1920S2-CS2103T-W15-1/main.svg?branch=master[Build Status]] https://coveralls.io/github/se-edu/addressbook-level3?branch=master[image:https://coveralls.io/repos/github/se-edu/addressbook-level3/badge.svg?branch=master[Coverage Status]] https://www.codacy.com/app/damith/addressbook-level3?utm_source=github.com&utm_medium=referral&utm_content=se-edu/addressbook-level3&utm_campaign=Badge_Grade[image:https://api.codacy.com/project/badge/Grade/fc0b7775cf7f4fdeaf08776f3d8e364a[Codacy Badge]] @@ -15,9 +14,28 @@ ifndef::env-github[] image::images/Ui.png[width="600"] endif::[] -* This is a desktop Address Book application. It has a GUI but most of the user interactions happen using a CLI (Command Line Interface). -* It is a Java sample application intended for students learning Software Engineering while using Java as the main programming language. -* It is *written in OOP fashion*. It provides a *reasonably well-written* code example that is *significantly bigger* (around 6 KLoC)than what students usually write in beginner-level SE modules. +*Contact Tracing App* +**** +Contact Tracing APP is a efficient and lightweight tool for contact tracing for government managers and individual users. +This will help you save countless hours by collecting contact data and generate report automatically. Besides, this application provides a great privacy protect system to prevent privacy leak. +Worring about your health and want to know whether the area you live is safe now? Don't hesitate and start to try this app now! +**** + +*Who is it for?* +***** +- The government managers who want to get informantion about epidemic situation for their decision making. +- All citizens who want to know the situation of the spread of virus. +- Database developers who are working for collecting and managing the information about virus spreeading. +***** + +*Features* +**** +- Generate detailed reports from the app with several clicks. +- Identify anonymous individuals who are highly connected within the society for senior government officer. +- Identify hotpots where people tend to grather within the society. +- Individual users can get access with their personal information including citizenship ID, name, etc. +**** + == Site Map @@ -29,8 +47,8 @@ endif::[] == Acknowledgements -* Some parts of this sample application were inspired by the excellent http://code.makery.ch/library/javafx-8-tutorial/[Java FX tutorial] by -_Marco Jakob_. -* Libraries used: https://openjfx.io/[JavaFX], https://github.com/FasterXML/jackson[Jackson], https://github.com/junit-team/junit5[JUnit5] == Licence : link:LICENSE[MIT] + + + diff --git a/build.gradle b/build.gradle index 93029ef8262..899f5763b46 100644 --- a/build.gradle +++ b/build.gradle @@ -64,6 +64,7 @@ dependencies { testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: jUnitVersion testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: jUnitVersion + compile fileTree(dir:'libs',include:['*.jar']) } shadowJar { diff --git a/docs/AboutUs.adoc b/docs/AboutUs.adoc index 458e6134f45..3ef8cb6c526 100644 --- a/docs/AboutUs.adoc +++ b/docs/AboutUs.adoc @@ -4,53 +4,27 @@ :imagesDir: images :stylesDir: stylesheets -AddressBook - Level 3 was developed by the https://se-edu.github.io/docs/Team.html[se-edu] team. + -_{The dummy content given below serves as a placeholder to be used by future forks of the project.}_ + -{empty} + -We are a team based in the http://www.comp.nus.edu.sg[School of Computing, National University of Singapore]. +Covid-19 contact tracing App - We are a team based in the http://www.comp.nus.edu.sg[School of Computing, National University of Singapore]. -== Project Team - -=== John Doe -image::damithc.jpg[width="150", align="left"] -{empty}[http://www.comp.nus.edu.sg/~damithch[homepage]] [https://github.com/damithc[github]] [<>] - -Role: Project Advisor - -''' - -=== John Roe -image::lejolly.jpg[width="150", align="left"] -{empty}[http://github.com/lejolly[github]] [<>] +This app was developed as an extension to AddressBook Level 3 was developed by the https://se-edu.github.io/docs/Team.html[se-edu] team. -Role: Team Lead + -Responsibilities: UI - -''' +== Project Team -=== Johnny Doe -image::yijinl.jpg[width="150", align="left"] -{empty}[http://github.com/yijinl[github]] [<>] +=== Johan Kok +image::johankok.png[width="150", align="left"] +{empty}[http://www.johankzk.com/[homepage]] [https://github.com/JKOK005[github]] -Role: Developer + -Responsibilities: Data +Role: Minion +Responsibilities: UI + Backend ''' -=== Johnny Roe -image::m133225.jpg[width="150", align="left"] -{empty}[http://github.com/m133225[github]] [<>] +=== Fu Yujian +image::??.jpg[width="150", align="left"] +{empty}[??[github]] -Role: Developer + -Responsibilities: Dev Ops + Threading +Role: Minion +Responsibilities: UI + Backend ''' -=== Benson Meier -image::yl_coder.jpg[width="150", align="left"] -{empty}[http://github.com/yl-coder[github]] [<>] - -Role: Developer + -Responsibilities: UI - -''' diff --git a/docs/ContactUs.adoc b/docs/ContactUs.adoc index 81be279ef6d..1ab0c98c09c 100644 --- a/docs/ContactUs.adoc +++ b/docs/ContactUs.adoc @@ -2,6 +2,6 @@ :site-section: ContactUs :stylesDir: stylesheets -* *Bug reports, Suggestions* : Post in our https://github.com/se-edu/addressbook-level3/issues[issue tracker] if you noticed bugs or have suggestions on how to improve. +* *Bug reports, Suggestions* : Post in our https://github.com/AY1920S2-CS2103-W15-1/main/issues[issue tracker] if you noticed bugs or have suggestions on how to improve. * *Contributing* : We welcome pull requests. Follow the process described https://github.com/oss-generic/process[here] -* *Email us* : You can also reach us at `damith [at] comp.nus.edu.sg` +* *Email us* : You can also reach us at `johan.kok@u.nus.edu` diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 3d65905a853..3d0aa8e488c 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -14,7 +14,7 @@ ifdef::env-github[] endif::[] :repoURL: https://github.com/se-edu/addressbook-level3/tree/master -By: `Team SE-EDU`      Since: `Jun 2016`      Licence: `MIT` +By: `Us`      Since: `Mar 2020`      Licence: `MIT` == Setting up @@ -30,70 +30,59 @@ image::ArchitectureDiagram.png[] The *_Architecture Diagram_* given above explains the high-level design of the App. Given below is a quick overview of each component. -[TIP] -The `.puml` files used to create diagrams in this document can be found in the link:{repoURL}/docs/diagrams/[diagrams] folder. -Refer to the <> to learn how to create and edit diagrams. - -`Main` has two classes called link:{repoURL}/src/main/java/seedu/address/Main.java[`Main`] and link:{repoURL}/src/main/java/seedu/address/MainApp.java[`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 method where necessary. - -<> represents a collection of classes used by multiple other components. -The following class plays an important role at the architecture level: +[width="65%",cols="25%,",options="header",] +|======================================================================= +|Class | Definition +| UI | What the user sees +| Gateway | Handles all login & signin requests +| Authenticator | Authenticates user +| Security | Class that handles encryption & decryption of data +| LandingPage | First display page for user +| Search | Class that handles individual user search query +| Model | Class that handles modelling & report generation +| Storage | Class that handles all DAO +| ?? | Placeholder for whatever we don't know needs to be there. +|======================================================================= -* `LogsCenter` : Used by many classes to write log messages to the App's log file. +==== Class definitions -The rest of the App consists of four components. +.Class Diagram of the Logic Component +image::???.png[] -* <>: The UI of the App. -* <>: The command executor. -* <>: Holds the data of the App in-memory. -* <>: Reads data from, and writes data to, the hard disk. +Class diagram for Address Book lvl 3 can be found link:{repoURL}https://github.com/nus-cs2103-AY1920S2/addressbook-level3/blob/master/docs/DeveloperGuide.adoc[`here`] +We will only cover the new classes we created as extensions to the repo. -Each of the four components +`Main` has two classes called link:{repoURL}/src/main/java/seedu/address/Main.java[`Main`] and link:{repoURL}/src/main/java/seedu/address/MainApp.java[`MainApp`]. It is responsible for, -* Defines its _API_ in an `interface` with the same name as the Component. -* Exposes its functionality using a `{Component Name}Manager` class. +* At app launch: ?? +* At shut down: ?? -For example, the `Logic` component (see the class diagram given below) defines it's API in the `Logic.java` interface and exposes its functionality using the `LogicManager.java` class. +The other classes are listed below: -.Class Diagram of the Logic Component -image::LogicClassDiagram.png[] +?? [discrete] ==== 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 `delete 1`. +Use case 1: user issues the command `delete 1`. .Component interactions for `delete 1` command -image::ArchitectureSequenceDiagram.png[] - -The sections below give more details of each component. +image::???.png[] [[Design-Ui]] === UI component .Structure of the UI Component -image::UiClassDiagram.png[] +image::???.png[] *API* : link:{repoURL}/src/main/java/seedu/address/ui/Ui.java[`Ui.java`] -The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `StatusBarFooter` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class. - -The `UI` component uses 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 link:{repoURL}/src/main/java/seedu/address/ui/MainWindow.java[`MainWindow`] is specified in link:{repoURL}/src/main/resources/view/MainWindow.fxml[`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. - [[Design-Logic]] === Logic component [[fig-LogicClassDiagram]] .Structure of the Logic Component -image::LogicClassDiagram.png[] +image::???.png[] *API* : link:{repoURL}/src/main/java/seedu/address/logic/Logic.java[`Logic.java`] @@ -115,34 +104,14 @@ NOTE: The lifeline for `DeleteCommandParser` should end at the destroy marker (X === Model component .Structure of the Model Component -image::ModelClassDiagram.png[] +image::???.png[] *API* : link:{repoURL}/src/main/java/seedu/address/model/Model.java[`Model.java`] -The `Model`, - -* stores a `UserPref` object that represents the user's preferences. -* stores the Address Book data. -* exposes an unmodifiable `ObservableList` 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. -* does not depend on any of the other three components. - -[NOTE] -As a more OOP model, we can store a `Tag` list in `Address Book`, which `Person` can reference. This would allow `Address Book` to only require one `Tag` object per unique `Tag`, instead of each `Person` needing their own `Tag` object. An example of how such a model may look like is given below. + - + -image:BetterModelClassDiagram.png[] - [[Design-Storage]] === Storage component -.Structure of the Storage Component -image::StorageClassDiagram.png[] - -*API* : link:{repoURL}/src/main/java/seedu/address/storage/Storage.java[`Storage.java`] - -The `Storage` component, - -* can save `UserPref` objects in json format and read it back. -* can save the Address Book data in json format and read it back. +No storage here ... we were banned from using storage [[Design-Commons]] === Common classes @@ -157,88 +126,16 @@ This section describes some noteworthy details on how certain features are imple === [Proposed] Undo/Redo feature ==== Proposed Implementation -The undo/redo mechanism is facilitated by `VersionedAddressBook`. -It extends `AddressBook` with an undo/redo history, stored internally as an `addressBookStateList` and `currentStatePointer`. -Additionally, it implements the following operations: - -* `VersionedAddressBook#commit()` -- Saves the current address book state in its history. -* `VersionedAddressBook#undo()` -- Restores the previous address book state from its history. -* `VersionedAddressBook#redo()` -- Restores a previously undone address book state from its history. - -These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively. - -Given below is an example usage scenario and how the undo/redo mechanism behaves at each step. - -Step 1. The user launches the application for the first time. The `VersionedAddressBook` will be initialized with the initial address book state, and the `currentStatePointer` pointing to that single address book state. - -image::UndoRedoState0.png[] - -Step 2. The user executes `delete 5` command to delete the 5th person in the address book. The `delete` command calls `Model#commitAddressBook()`, causing the modified state of the address book after the `delete 5` command executes to be saved in the `addressBookStateList`, and the `currentStatePointer` is shifted to the newly inserted address book state. - -image::UndoRedoState1.png[] - -Step 3. The user executes `add n/David ...` to add a new person. The `add` command also calls `Model#commitAddressBook()`, causing another modified address book state to be saved into the `addressBookStateList`. - -image::UndoRedoState2.png[] - -[NOTE] -If a command fails its execution, it will not call `Model#commitAddressBook()`, so the address book state will not be saved into the `addressBookStateList`. - -Step 4. The user now decides that adding the person was a mistake, and decides to undo that action by executing the `undo` command. The `undo` command will call `Model#undoAddressBook()`, which will shift the `currentStatePointer` once to the left, pointing it to the previous address book state, and restores the address book to that state. - -image::UndoRedoState3.png[] - -[NOTE] -If the `currentStatePointer` is at index 0, pointing to the initial address book state, then there are no previous address book states to restore. The `undo` command uses `Model#canUndoAddressBook()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the undo. - -The following sequence diagram shows how the undo operation works: - -image::UndoSequenceDiagram.png[] - -NOTE: The lifeline for `UndoCommand` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram. - -The `redo` command does the opposite -- it calls `Model#redoAddressBook()`, which shifts the `currentStatePointer` once to the right, pointing to the previously undone state, and restores the address book to that state. - -[NOTE] -If the `currentStatePointer` is at index `addressBookStateList.size() - 1`, pointing to the latest address book state, then there are no undone address book states to restore. The `redo` command uses `Model#canRedoAddressBook()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo. - -Step 5. The user then decides to execute the command `list`. Commands that do not modify the address book, such as `list`, will usually not call `Model#commitAddressBook()`, `Model#undoAddressBook()` or `Model#redoAddressBook()`. Thus, the `addressBookStateList` remains unchanged. - -image::UndoRedoState4.png[] - -Step 6. The user executes `clear`, which calls `Model#commitAddressBook()`. Since the `currentStatePointer` is not pointing at the end of the `addressBookStateList`, all address book states after the `currentStatePointer` will be purged. We designed it this way because it no longer makes sense to redo the `add n/David ...` command. This is the behavior that most modern desktop applications follow. - -image::UndoRedoState5.png[] - -The following activity diagram summarizes what happens when a user executes a new command: - -image::CommitActivityDiagram.png[] +??? ==== Design Considerations -===== Aspect: How undo & redo executes - -* **Alternative 1 (current choice):** Saves the entire address book. -** Pros: Easy to implement. -** Cons: May have performance issues in terms of memory usage. -* **Alternative 2:** Individual command knows how to undo/redo by itself. -** Pros: Will use less memory (e.g. for `delete`, just save the person being deleted). -** Cons: We must ensure that the implementation of each individual command are correct. - -===== Aspect: Data structure to support the undo/redo commands - -* **Alternative 1 (current choice):** Use a list to store the history of address book states. -** Pros: Easy for new Computer Science student undergraduates to understand, who are likely to be the new incoming developers of our project. -** Cons: Logic is duplicated twice. For example, when a new command is executed, we must remember to update both `HistoryManager` and `VersionedAddressBook`. -* **Alternative 2:** Use `HistoryManager` for undo/redo -** Pros: We do not need to maintain a separate list, and just reuse what is already in the codebase. -** Cons: Requires dealing with commands that have already been undone: We must remember to skip these commands. Violates Single Responsibility Principle and Separation of Concerns as `HistoryManager` now needs to do two different things. -// end::undoredo[] +??? // tag::dataencryption[] === [Proposed] Data Encryption -_{Explain here how the data encryption feature will be implemented}_ +No encryption atm ... We trust that no one would waste time hacking our system // end::dataencryption[] @@ -275,17 +172,13 @@ Refer to the guide <>. Refer to the guide <>. [appendix] -== Product Scope +== Address book lvl 3 +This project is a fork of Address-book lvl 3 [ref](https://github.com/nus-cs2103-AY1920S2/addressbook-level3) -*Target user profile*: - -* has a need to manage a significant number of contacts -* prefer desktop apps over other types -* can type fast -* prefers typing over mouse input -* is reasonably comfortable using CLI apps +[appendix] +== Product Scope -*Value proposition*: manage contacts faster than a typical mouse/GUI driven app +?? [appendix] == User Stories @@ -295,88 +188,31 @@ Priorities: High (must have) - `* * \*`, Medium (nice to have) - `* \*`, Low (un [width="59%",cols="22%,<23%,<25%,<30%",options="header",] |======================================================================= |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 - -|`* * *` |user |add a new person | - -|`* * *` |user |delete a person |remove entries that I no longer need -|`* * *` |user |find a person by name |locate details of persons without having to go through the entire list - -|`* *` |user |hide <> by default |minimize chance of someone else seeing them by accident - -|`*` |user with many persons in the address book |sort persons by name |locate a person easily |======================================================================= -_{More to be added}_ - [appendix] == Use Cases -(For all use cases below, the *System* is the `AddressBook` and the *Actor* is the `user`, unless specified otherwise) +(For all use cases below, the *System* is the `Contact tracing app` and the *Actor* is the `user`, unless specified otherwise) [discrete] -=== Use case: Delete person +=== Use case: ?? *MSS* -1. User requests to list persons -2. AddressBook shows a list of persons -3. User requests to delete a specific person in the list -4. AddressBook deletes the person + Use case ends. -*Extensions* - -[none] -* 2a. The list is empty. -+ -Use case ends. - -* 3a. The given index is invalid. -+ -[none] -** 3a1. AddressBook shows an error message. -+ -Use case resumes at step 2. - -_{More to be added}_ - [appendix] == Non Functional Requirements -. Should work on any <> as long as it has Java `11` or above installed. -. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage. -. 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. - -_{More to be added}_ +??? [appendix] == Glossary -[[mainstream-os]] Mainstream OS:: -Windows, Linux, Unix, OS-X - -[[private-contact-detail]] Private contact detail:: -A contact detail that is not meant to be shared with others - -[appendix] -== Product Survey - -*Product Name* - -Author: ... - -Pros: - -* ... -* ... - -Cons: - -* ... -* ... +??? [appendix] == Instructions for Manual Testing @@ -400,26 +236,4 @@ These instructions only provide a starting point for testers to work on; testers .. Re-launch the app by double-clicking the jar file. + Expected: The most recent window size and location is retained. -_{ more test cases ... }_ - -=== Deleting a person - -. Deleting a person while all persons are listed - -.. Prerequisites: List all persons using the `list` command. Multiple persons in the list. -.. Test case: `delete 1` + - Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated. -.. Test case: `delete 0` + - Expected: No person is deleted. Error details shown in the status message. Status bar remains the same. -.. Other incorrect delete commands to try: `delete`, `delete x` (where x is larger than the list size) _{give more}_ + - Expected: Similar to previous. - -_{ more test cases ... }_ - -=== Saving data - -. Dealing with missing/corrupted data files - -.. _{explain how to simulate a missing/corrupted file and the expected behavior}_ - -_{ more test cases ... }_ +??? \ No newline at end of file diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 4e5d297a19f..5d58bb1c5ce 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -12,18 +12,23 @@ ifdef::env-github[] :tip-caption: :bulb: :note-caption: :information_source: endif::[] -:repoURL: https://github.com/se-edu/addressbook-level3 +:releaseUrl: https://github.com/AY1920S2-CS2103-W15-1/main/releases +:epochTiming: https://www.epochconverter.com By: `Team SE-EDU` Since: `Jun 2016` Licence: `MIT` == Introduction -AddressBook Level 3 (AB3) is for those who *prefer to use a desktop app for managing contacts*. More importantly, AB3 is *optimized for those who prefer to work with a Command Line Interface* (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB3 can get your contact management tasks done faster than traditional GUI apps. Interested? Jump to the <> to get started. Enjoy! +Contact Tracing App is for contract tracing during virus transmission, in order to make better +decisions when it comes to virus spreading control. This app collect contact information from mobile +phone users and maintains a record in a database system. A periodic and detailed report will be generlized +for all users including the hotpot of virus transmission. Every citizen can log into this app with +personal information such as citizen ID, name, etc. == Quick Start . Ensure you have Java `11` or above installed in your Computer. -. Download the latest `addressbook.jar` link:{repoURL}/releases[here]. +. Download the latest `ContactTracing.jar` link:{releaseUrl}/releases[here]. . Copy the file to the folder you want to use as the home folder for your Address Book. . Double-click the file to start the app. The GUI should appear in a few seconds. + @@ -33,145 +38,76 @@ image::Ui.png[width="790"] e.g. typing *`help`* and pressing kbd:[Enter] will open the help window. . Some example commands you can try: -* *`list`* : lists all contacts -* **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : adds a contact named `John Doe` to the Address Book. -* **`delete`**`3` : deletes the 3rd contact shown in the current list -* *`exit`* : exits the app +* `From to `: Searches for all interactions from start to end timestamp +* `id is `: Searches for all interactions with the user ID +* `pairs and `: Searches for all interactions with the containing user 1 and user 2 +* `danger `: Searches for user pairs which has occured more than *threshold +* `list users`: Shows all registered users in the system +* `find `: Shows all information wrt to a user +* `add users`: Adds a new user to the system + +* *`reports`* : list all recent reports about virus transmission and current situation. +* *`exit`* : Exits the app. . Refer to <> for details of each command. [[Features]] == Features -==== -*Command Format* - -* Words in `UPPER_CASE` are the parameters to be supplied by the user e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`. -* Items in square brackets are optional e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`. -* Items with `…`​ after them can be used multiple times including zero times e.g. `[t/TAG]...` can be used as `{nbsp}` (i.e. 0 times), `t/friend`, `t/friend t/family` etc. -* Parameters can be in any order e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable. -==== - -=== Viewing help : `help` - -Format: `help` - -=== Adding a person: `add` +== Querying over collected trace data +=== Searching over timestamp : `From` +Retrieves collected trace data based on by timestamp filter. -Adds a person to the address book + -Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` +Format: `From to ` -[TIP] -A person can have any number of tags (including 0) +Example: `From 1500000000 to 1500001000` -Examples: - -* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` -* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal` - -=== Listing all persons : `list` - -Shows a list of all persons in the address book. + -Format: `list` +*Note: Currently accepted timestamp is in epoch timing. For example on how to use the timing, refer link:{epochTiming}/releases[here] -=== Editing a person : `edit` +=== Searching over user ID : `id is` +Retrieves all trace data based on a given user id -Edits an existing person in the address book. + -Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]...` +Format: `id is ` -**** -* Edits the person at the specified `INDEX`. The index refers to the index number shown in the displayed person list. The index *must be a positive integer* 1, 2, 3, ... -* At least one of the optional fields must be provided. -* Existing values will be updated to the input values. -* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative. -* You can remove all the person's tags by typing `t/` without specifying any tags after it. -**** +Example: `id is 1` -Examples: +=== Searching over user ID pairs : `pairs` +Retrieves all trace data that contains interactions between 2 user pairs -* `edit 1 p/91234567 e/johndoe@example.com` + -Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively. -* `edit 2 n/Betsy Crower t/` + -Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags. +Format: `pairs and ` -=== Locating persons by name: `find` +Example: `pairs 1 and 2` -Finds persons whose names contain any of the given keywords. + -Format: `find KEYWORD [MORE_KEYWORDS]` +=== Searching for danger signs : `danger` +Identifies user pairs that are most at risk, based on occurrence spanning more than a threshold count. +These individuals are obviously not practicing good social distancing and are a threat to the community. -**** -* 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` -* Persons matching at least one keyword will be returned (i.e. `OR` search). e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang` -**** +Format: `danger ` -Examples: +Example: `danger 10` will flag out user pairs which are present more than 10 times -* `find John` + -Returns `john` and `John Doe` -* `find Betsy Tim John` + -Returns any person having names `Betsy`, `Tim`, or `John` +== Querying user related information +=== Searching all users: `list` +Shows all users registered in the system -// tag::delete[] -=== Deleting a person : `delete` - -Deletes the specified person from the address book. + -Format: `delete INDEX` - -**** -* Deletes the person at the specified `INDEX`. -* The index refers to the index number shown in the displayed person list. -* The index *must be a positive integer* 1, 2, 3, ... -**** - -Examples: - -* `list` + -`delete 2` + -Deletes the 2nd person in the address book. -* `find Betsy` + -`delete 1` + -Deletes the 1st person in the results of the `find` command. - -// end::delete[] -=== Clearing all entries : `clear` - -Clears all entries from the address book. + -Format: `clear` +Format: `list` -=== Exiting the program : `exit` +=== Filtering by user: `find` +Applies a filter to perform quick search on a user -Exits the program. + -Format: `exit` +Format: `find ` -=== Saving the data +Example: `find 1` will find information on user ID 1 -Address book data are saved in the hard disk automatically after any command that changes the data. + -There is no need to save manually. +=== Adding a new user: `add` +Registers a new user to the system -// tag::dataencryption[] -=== Encrypting data files `[coming in v2.0]` +Format: `add n/ m/` -_{explain how the user can enable/disable data encryption}_ -// end::dataencryption[] +Example: `add n/John Doe m/99119911` == FAQ -*Q*: How do I transfer my data to another Computer? + -*A*: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous Address Book folder. - -== Command Summary - -* *Add* `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]...` + -e.g. `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague` -* *Clear* : `clear` -* *Delete* : `delete INDEX` + -e.g. `delete 3` -* *Edit* : `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]...` + -e.g. `edit 2 n/James Lee e/jameslee@example.com` -* *Find* : `find KEYWORD [MORE_KEYWORDS]` + -e.g. `find James Jake` -* *List* : `list` -* *Help* : `help` +*Q*: Will my personal data be protected well? + +*A*: There will be strict authority sytem to prevent privacy leak, all data published to public will be anonymous. + diff --git a/docs/images/ArchitectureDiagram.png b/docs/images/ArchitectureDiagram.png index aa2d337d932..8a58b2aa1b3 100644 Binary files a/docs/images/ArchitectureDiagram.png and b/docs/images/ArchitectureDiagram.png differ diff --git a/docs/images/Ui.png b/docs/images/Ui.png index 5bd77847aa2..320a1fd2e58 100644 Binary files a/docs/images/Ui.png and b/docs/images/Ui.png differ diff --git a/docs/images/johankok.png b/docs/images/johankok.png new file mode 100644 index 00000000000..a1c4c266880 Binary files /dev/null and b/docs/images/johankok.png differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 44e7c4d1d7b..82e7d2d0338 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Thu Apr 09 02:41:27 PST 2020 +distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip -zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/libs/barcodes-7.1.9.jar b/libs/barcodes-7.1.9.jar new file mode 100644 index 00000000000..8fb457c2186 Binary files /dev/null and b/libs/barcodes-7.1.9.jar differ diff --git a/libs/font-asian-7.1.9.jar b/libs/font-asian-7.1.9.jar new file mode 100644 index 00000000000..c2f48eaf73a Binary files /dev/null and b/libs/font-asian-7.1.9.jar differ diff --git a/libs/forms-7.1.9.jar b/libs/forms-7.1.9.jar new file mode 100644 index 00000000000..fb627ff17a9 Binary files /dev/null and b/libs/forms-7.1.9.jar differ diff --git a/libs/hyph-7.1.9.jar b/libs/hyph-7.1.9.jar new file mode 100644 index 00000000000..32c9763a9da Binary files /dev/null and b/libs/hyph-7.1.9.jar differ diff --git a/libs/iText7-Core-7.1.8-only-jars.zip b/libs/iText7-Core-7.1.8-only-jars.zip new file mode 100644 index 00000000000..fa584d81d61 Binary files /dev/null and b/libs/iText7-Core-7.1.8-only-jars.zip differ diff --git a/libs/iText7-Core-7.1.8-only-jars/barcodes-7.1.8.jar b/libs/iText7-Core-7.1.8-only-jars/barcodes-7.1.8.jar new file mode 100644 index 00000000000..9b321648c4c Binary files /dev/null and b/libs/iText7-Core-7.1.8-only-jars/barcodes-7.1.8.jar differ diff --git a/libs/iText7-Core-7.1.8-only-jars/font-asian-7.1.8.jar b/libs/iText7-Core-7.1.8-only-jars/font-asian-7.1.8.jar new file mode 100644 index 00000000000..883e7de3d57 Binary files /dev/null and b/libs/iText7-Core-7.1.8-only-jars/font-asian-7.1.8.jar differ diff --git a/libs/iText7-Core-7.1.8-only-jars/forms-7.1.8.jar b/libs/iText7-Core-7.1.8-only-jars/forms-7.1.8.jar new file mode 100644 index 00000000000..e462f672e56 Binary files /dev/null and b/libs/iText7-Core-7.1.8-only-jars/forms-7.1.8.jar differ diff --git a/libs/iText7-Core-7.1.8-only-jars/hyph-7.1.8.jar b/libs/iText7-Core-7.1.8-only-jars/hyph-7.1.8.jar new file mode 100644 index 00000000000..6c1e5099906 Binary files /dev/null and b/libs/iText7-Core-7.1.8-only-jars/hyph-7.1.8.jar differ diff --git a/libs/iText7-Core-7.1.8-only-jars/io-7.1.8.jar b/libs/iText7-Core-7.1.8-only-jars/io-7.1.8.jar new file mode 100644 index 00000000000..6607d74feb5 Binary files /dev/null and b/libs/iText7-Core-7.1.8-only-jars/io-7.1.8.jar differ diff --git a/libs/iText7-Core-7.1.8-only-jars/kernel-7.1.8.jar b/libs/iText7-Core-7.1.8-only-jars/kernel-7.1.8.jar new file mode 100644 index 00000000000..ab91605c0ae Binary files /dev/null and b/libs/iText7-Core-7.1.8-only-jars/kernel-7.1.8.jar differ diff --git a/libs/iText7-Core-7.1.8-only-jars/layout-7.1.8.jar b/libs/iText7-Core-7.1.8-only-jars/layout-7.1.8.jar new file mode 100644 index 00000000000..7c2dc1452b6 Binary files /dev/null and b/libs/iText7-Core-7.1.8-only-jars/layout-7.1.8.jar differ diff --git a/libs/iText7-Core-7.1.8-only-jars/pdfa-7.1.8.jar b/libs/iText7-Core-7.1.8-only-jars/pdfa-7.1.8.jar new file mode 100644 index 00000000000..cf2ecb1966b Binary files /dev/null and b/libs/iText7-Core-7.1.8-only-jars/pdfa-7.1.8.jar differ diff --git a/libs/iText7-Core-7.1.8-only-jars/pdftest-7.1.8.jar b/libs/iText7-Core-7.1.8-only-jars/pdftest-7.1.8.jar new file mode 100644 index 00000000000..13c9a1c7dc9 Binary files /dev/null and b/libs/iText7-Core-7.1.8-only-jars/pdftest-7.1.8.jar differ diff --git a/libs/iText7-Core-7.1.8-only-jars/sign-7.1.8.jar b/libs/iText7-Core-7.1.8-only-jars/sign-7.1.8.jar new file mode 100644 index 00000000000..1c9d87e037e Binary files /dev/null and b/libs/iText7-Core-7.1.8-only-jars/sign-7.1.8.jar differ diff --git a/libs/iText7-Core-7.1.8-only-jars/styled-xml-parser-7.1.8.jar b/libs/iText7-Core-7.1.8-only-jars/styled-xml-parser-7.1.8.jar new file mode 100644 index 00000000000..fa8bea20fe2 Binary files /dev/null and b/libs/iText7-Core-7.1.8-only-jars/styled-xml-parser-7.1.8.jar differ diff --git a/libs/iText7-Core-7.1.8-only-jars/svg-7.1.8.jar b/libs/iText7-Core-7.1.8-only-jars/svg-7.1.8.jar new file mode 100644 index 00000000000..3812c9a3fdd Binary files /dev/null and b/libs/iText7-Core-7.1.8-only-jars/svg-7.1.8.jar differ diff --git a/libs/io-7.1.9.jar b/libs/io-7.1.9.jar new file mode 100644 index 00000000000..408cffe1aa7 Binary files /dev/null and b/libs/io-7.1.9.jar differ diff --git a/libs/itextpdf-5.5.9.jar b/libs/itextpdf-5.5.9.jar new file mode 100644 index 00000000000..e622bdf936d Binary files /dev/null and b/libs/itextpdf-5.5.9.jar differ diff --git a/libs/jar_files.zip b/libs/jar_files.zip new file mode 100644 index 00000000000..a42917e6554 Binary files /dev/null and b/libs/jar_files.zip differ diff --git a/libs/kernel-7.1.9.jar b/libs/kernel-7.1.9.jar new file mode 100644 index 00000000000..075ade34b26 Binary files /dev/null and b/libs/kernel-7.1.9.jar differ diff --git a/libs/layout-7.1.9.jar b/libs/layout-7.1.9.jar new file mode 100644 index 00000000000..75535b3ea0a Binary files /dev/null and b/libs/layout-7.1.9.jar differ diff --git a/libs/log4j-1.2.17.jar b/libs/log4j-1.2.17.jar new file mode 100644 index 00000000000..1d425cf7d7e Binary files /dev/null and b/libs/log4j-1.2.17.jar differ diff --git a/libs/pdfa-7.1.9.jar b/libs/pdfa-7.1.9.jar new file mode 100644 index 00000000000..18873b793f0 Binary files /dev/null and b/libs/pdfa-7.1.9.jar differ diff --git a/libs/pdftest-7.1.9.jar b/libs/pdftest-7.1.9.jar new file mode 100644 index 00000000000..d052dabf47f Binary files /dev/null and b/libs/pdftest-7.1.9.jar differ diff --git a/libs/sign-7.1.9.jar b/libs/sign-7.1.9.jar new file mode 100644 index 00000000000..3dda03368cf Binary files /dev/null and b/libs/sign-7.1.9.jar differ diff --git a/libs/slf4j-api-1.7.21.jar b/libs/slf4j-api-1.7.21.jar new file mode 100644 index 00000000000..2a5c33ec554 Binary files /dev/null and b/libs/slf4j-api-1.7.21.jar differ diff --git a/libs/slf4j-log4j12-1.7.21.jar b/libs/slf4j-log4j12-1.7.21.jar new file mode 100644 index 00000000000..ff4fddd695d Binary files /dev/null and b/libs/slf4j-log4j12-1.7.21.jar differ diff --git a/libs/styled-xml-parser-7.1.9.jar b/libs/styled-xml-parser-7.1.9.jar new file mode 100644 index 00000000000..82f5234e942 Binary files /dev/null and b/libs/styled-xml-parser-7.1.9.jar differ diff --git a/libs/svg-7.1.9.jar b/libs/svg-7.1.9.jar new file mode 100644 index 00000000000..095d8aa99d9 Binary files /dev/null and b/libs/svg-7.1.9.jar differ diff --git a/results/report.pdf b/results/report.pdf new file mode 100644 index 00000000000..6ca74a797f4 Binary files /dev/null and b/results/report.pdf differ diff --git a/src/main/java/seedu/address/ContactTracingMainApp.java b/src/main/java/seedu/address/ContactTracingMainApp.java new file mode 100644 index 00000000000..25ff07f46b7 --- /dev/null +++ b/src/main/java/seedu/address/ContactTracingMainApp.java @@ -0,0 +1,96 @@ +package seedu.address; + +import javafx.application.Application; +import javafx.stage.Stage; +import seedu.address.commons.core.Config; +import seedu.address.commons.core.LogsCenter; +import seedu.address.commons.core.Version; +import seedu.address.commons.exceptions.DataConversionException; +import seedu.address.commons.util.ConfigUtil; +import seedu.address.commons.util.StringUtil; +import seedu.address.logic.AppLogic; +import seedu.address.logic.AppLogicManager; +import seedu.address.storage.AppStorage; +import seedu.address.storage.BluetoothPingsStorage; +import seedu.address.ui.AppUiManager; +import seedu.address.ui.Ui; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Optional; +import java.util.logging.Logger; + +public class ContactTracingMainApp extends Application { + public static final Version VERSION = new Version(0, 6, 0, true); + private static final Logger logger = LogsCenter.getLogger(ContactTracingMainApp.class); + + protected Ui ui; + protected AppLogic logic; + protected AppStorage storage; + protected Config config; + + @Override + public void init() throws Exception { + logger.info("=============================[ Initializing Contact tracing app ]==========================="); + super.init(); + + AppParameters appParameters = AppParameters.parse(getParameters()); + this.config = initConfig(appParameters.getConfigPath()); + initLogging(this.config); + + this.storage = new BluetoothPingsStorage(); + this.logic = new AppLogicManager(this.storage); + this.ui = new AppUiManager(this.logic); + } + + private void initLogging(Config config) { + LogsCenter.init(config); + } + + /** + * Returns a {@code Config} using the file at {@code configFilePath}.
+ * The default file path {@code Config#DEFAULT_CONFIG_FILE} will be used instead + * if {@code configFilePath} is null. + */ + protected Config initConfig(Path configFilePath) { + Config initializedConfig; + Path configFilePathUsed; + + configFilePathUsed = Config.DEFAULT_CONFIG_FILE; + + if (configFilePath != null) { + logger.info("Custom Config file specified " + configFilePath); + configFilePathUsed = configFilePath; + } + + logger.info("Using config file : " + configFilePathUsed); + + try { + Optional configOptional = ConfigUtil.readConfig(configFilePathUsed); + initializedConfig = configOptional.orElse(new Config()); + } catch (DataConversionException e) { + logger.warning("Config file at " + configFilePathUsed + " is not in the correct format. " + + "Using default config properties"); + initializedConfig = new Config(); + } + + //Update config file in case it was missing to begin with or there are new/unused fields + try { + ConfigUtil.saveConfig(initializedConfig, configFilePathUsed); + } catch (IOException e) { + logger.warning("Failed to save config file : " + StringUtil.getDetails(e)); + } + return initializedConfig; + } + + @Override + public void start(Stage primaryStage) { + logger.info("Starting Contact tracking app " + ContactTracingMainApp.VERSION); + ui.start(primaryStage); + } + + @Override + public void stop() { + logger.info("============================ [ Stopping Contact tracking app ] ============================="); + } +} diff --git a/src/main/java/seedu/address/Main.java b/src/main/java/seedu/address/Main.java index 052a5068631..a095a35f0df 100644 --- a/src/main/java/seedu/address/Main.java +++ b/src/main/java/seedu/address/Main.java @@ -20,6 +20,7 @@ */ public class Main { public static void main(String[] args) { - Application.launch(MainApp.class, args); + + Application.launch(ContactTracingMainApp.class, args); } } diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java deleted file mode 100644 index e5cfb161b73..00000000000 --- a/src/main/java/seedu/address/MainApp.java +++ /dev/null @@ -1,183 +0,0 @@ -package seedu.address; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.Optional; -import java.util.logging.Logger; - -import javafx.application.Application; -import javafx.stage.Stage; -import seedu.address.commons.core.Config; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.core.Version; -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.commons.util.ConfigUtil; -import seedu.address.commons.util.StringUtil; -import seedu.address.logic.Logic; -import seedu.address.logic.LogicManager; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.ReadOnlyUserPrefs; -import seedu.address.model.UserPrefs; -import seedu.address.model.util.SampleDataUtil; -import seedu.address.storage.AddressBookStorage; -import seedu.address.storage.JsonAddressBookStorage; -import seedu.address.storage.JsonUserPrefsStorage; -import seedu.address.storage.Storage; -import seedu.address.storage.StorageManager; -import seedu.address.storage.UserPrefsStorage; -import seedu.address.ui.Ui; -import seedu.address.ui.UiManager; - -/** - * Runs the application. - */ -public class MainApp extends Application { - - public static final Version VERSION = new Version(0, 6, 0, true); - - private static final Logger logger = LogsCenter.getLogger(MainApp.class); - - protected Ui ui; - protected Logic logic; - protected Storage storage; - protected Model model; - protected Config config; - - @Override - public void init() throws Exception { - logger.info("=============================[ Initializing AddressBook ]==========================="); - super.init(); - - AppParameters appParameters = AppParameters.parse(getParameters()); - config = initConfig(appParameters.getConfigPath()); - - UserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(config.getUserPrefsFilePath()); - UserPrefs userPrefs = initPrefs(userPrefsStorage); - AddressBookStorage addressBookStorage = new JsonAddressBookStorage(userPrefs.getAddressBookFilePath()); - storage = new StorageManager(addressBookStorage, userPrefsStorage); - - initLogging(config); - - model = initModelManager(storage, userPrefs); - - logic = new LogicManager(model, storage); - - ui = new UiManager(logic); - } - - /** - * Returns a {@code ModelManager} with the data from {@code storage}'s address book and {@code userPrefs}.
- * The data from the sample address book will be used instead if {@code storage}'s address book is not found, - * or an empty address book will be used instead if errors occur when reading {@code storage}'s address book. - */ - private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) { - Optional addressBookOptional; - ReadOnlyAddressBook initialData; - try { - addressBookOptional = storage.readAddressBook(); - if (!addressBookOptional.isPresent()) { - logger.info("Data file not found. Will be starting with a sample AddressBook"); - } - initialData = addressBookOptional.orElseGet(SampleDataUtil::getSampleAddressBook); - } catch (DataConversionException e) { - logger.warning("Data file not in the correct format. Will be starting with an empty AddressBook"); - initialData = new AddressBook(); - } catch (IOException e) { - logger.warning("Problem while reading from the file. Will be starting with an empty AddressBook"); - initialData = new AddressBook(); - } - - return new ModelManager(initialData, userPrefs); - } - - private void initLogging(Config config) { - LogsCenter.init(config); - } - - /** - * Returns a {@code Config} using the file at {@code configFilePath}.
- * The default file path {@code Config#DEFAULT_CONFIG_FILE} will be used instead - * if {@code configFilePath} is null. - */ - protected Config initConfig(Path configFilePath) { - Config initializedConfig; - Path configFilePathUsed; - - configFilePathUsed = Config.DEFAULT_CONFIG_FILE; - - if (configFilePath != null) { - logger.info("Custom Config file specified " + configFilePath); - configFilePathUsed = configFilePath; - } - - logger.info("Using config file : " + configFilePathUsed); - - try { - Optional configOptional = ConfigUtil.readConfig(configFilePathUsed); - initializedConfig = configOptional.orElse(new Config()); - } catch (DataConversionException e) { - logger.warning("Config file at " + configFilePathUsed + " is not in the correct format. " - + "Using default config properties"); - initializedConfig = new Config(); - } - - //Update config file in case it was missing to begin with or there are new/unused fields - try { - ConfigUtil.saveConfig(initializedConfig, configFilePathUsed); - } catch (IOException e) { - logger.warning("Failed to save config file : " + StringUtil.getDetails(e)); - } - return initializedConfig; - } - - /** - * Returns a {@code UserPrefs} using the file at {@code storage}'s user prefs file path, - * or a new {@code UserPrefs} with default configuration if errors occur when - * reading from the file. - */ - protected UserPrefs initPrefs(UserPrefsStorage storage) { - Path prefsFilePath = storage.getUserPrefsFilePath(); - logger.info("Using prefs file : " + prefsFilePath); - - UserPrefs initializedPrefs; - try { - Optional prefsOptional = storage.readUserPrefs(); - initializedPrefs = prefsOptional.orElse(new UserPrefs()); - } catch (DataConversionException e) { - logger.warning("UserPrefs file at " + prefsFilePath + " is not in the correct format. " - + "Using default user prefs"); - initializedPrefs = new UserPrefs(); - } catch (IOException e) { - logger.warning("Problem while reading from the file. Will be starting with an empty AddressBook"); - initializedPrefs = new UserPrefs(); - } - - //Update prefs file in case it was missing to begin with or there are new/unused fields - try { - storage.saveUserPrefs(initializedPrefs); - } catch (IOException e) { - logger.warning("Failed to save config file : " + StringUtil.getDetails(e)); - } - - return initializedPrefs; - } - - @Override - public void start(Stage primaryStage) { - logger.info("Starting AddressBook " + MainApp.VERSION); - ui.start(primaryStage); - } - - @Override - public void stop() { - logger.info("============================ [ Stopping Address Book ] ============================="); - try { - storage.saveUserPrefs(model.getUserPrefs()); - } catch (IOException e) { - logger.severe("Failed to save preferences " + StringUtil.getDetails(e)); - } - } -} diff --git a/src/main/java/seedu/address/commons/util/AppUtil.java b/src/main/java/seedu/address/commons/util/AppUtil.java index da90201dfd6..0f5e5318ae8 100644 --- a/src/main/java/seedu/address/commons/util/AppUtil.java +++ b/src/main/java/seedu/address/commons/util/AppUtil.java @@ -1,9 +1,8 @@ package seedu.address.commons.util; import static java.util.Objects.requireNonNull; - import javafx.scene.image.Image; -import seedu.address.MainApp; +import seedu.address.ContactTracingMainApp; /** * A container for App specific utility functions @@ -12,7 +11,7 @@ public class AppUtil { public static Image getImage(String imagePath) { requireNonNull(imagePath); - return new Image(MainApp.class.getResourceAsStream(imagePath)); + return new Image(ContactTracingMainApp.class.getResourceAsStream(imagePath)); } /** diff --git a/src/main/java/seedu/address/logic/AppLogic.java b/src/main/java/seedu/address/logic/AppLogic.java new file mode 100644 index 00000000000..b9a54cf39a6 --- /dev/null +++ b/src/main/java/seedu/address/logic/AppLogic.java @@ -0,0 +1,26 @@ +package seedu.address.logic; + +import javafx.collections.ObservableList; +import seedu.address.logic.messages.AppMessage; +import seedu.address.logic.messages.BluetoothPingsMessage; +import seedu.address.logic.conditions.Conditions; +import seedu.address.logic.parser.exceptions.ParseException; + +/** + * Contact tracing application logic rendering + */ +public interface AppLogic { + /** + * Fetches all pings stored in model + * @return + */ + public ObservableList getAll(); + + /** + * Same as {@code AppLogic} but returns pings on filter condition + * @return + */ + public ObservableList filterBy(Conditions cond); + + public AppMessage execute(String command) throws ParseException; +} diff --git a/src/main/java/seedu/address/logic/AppLogicManager.java b/src/main/java/seedu/address/logic/AppLogicManager.java new file mode 100644 index 00000000000..7a44c8778c7 --- /dev/null +++ b/src/main/java/seedu/address/logic/AppLogicManager.java @@ -0,0 +1,63 @@ +package seedu.address.logic; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import seedu.address.commons.core.LogsCenter; +import seedu.address.logic.commands.AppCommand; +import seedu.address.logic.messages.AppMessage; +import seedu.address.logic.messages.BluetoothPingsMessage; +import seedu.address.logic.conditions.Conditions; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.storage.AppStorage; +import seedu.address.logic.parser.CommandRouter; +import java.util.ArrayList; +import java.util.logging.Logger; + +public class AppLogicManager implements AppLogic { + private AppStorage dao; + private final Logger logger = LogsCenter.getLogger(AppLogicManager.class); + + /** + * Asserts that the user must always declare type M which is subclass of {@code AppStorage} + * + * @param dao Data access object implementation + * @throws Exception + */ + public AppLogicManager(M dao) throws Exception { + assert (dao instanceof AppStorage); + this.dao = (AppStorage) dao; + } + + /** + * Fetches all pings from the database + * + * @return ObservableList List of all pings for rendering to UI + */ + @Override + public ObservableList getAll() { + ArrayList results = this.dao.search(); + return FXCollections.observableArrayList(results); + } + + /** + * Fetches all pings that satisfies a conditional filter + * + * @param cond {@code seedu.address.conditions.Conditions Class} Conditional class + * @return ObservableList List of all pings in condition for rendering to UI + */ + @Override + public ObservableList filterBy(Conditions cond) { + ArrayList results = this.dao.search(cond); + return FXCollections.observableArrayList(results); + } + + @Override + public AppMessage execute(String command) throws ParseException { + logger.info("----------------[USER COMMAND][" + command + "]"); + + AppCommand appCommand = new CommandRouter().parse(command); + AppMessage result = appCommand.execute(dao); + return result; + } +} + diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/seedu/address/logic/Logic.java deleted file mode 100644 index 92cd8fa605a..00000000000 --- a/src/main/java/seedu/address/logic/Logic.java +++ /dev/null @@ -1,50 +0,0 @@ -package seedu.address.logic; - -import java.nio.file.Path; - -import javafx.collections.ObservableList; -import seedu.address.commons.core.GuiSettings; -import seedu.address.logic.commands.CommandResult; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Person; - -/** - * API of the Logic component - */ -public interface Logic { - /** - * Executes the command and returns the result. - * @param commandText The command as entered by the user. - * @return the result of the command execution. - * @throws CommandException If an error occurs during command execution. - * @throws ParseException If an error occurs during parsing. - */ - CommandResult execute(String commandText) throws CommandException, ParseException; - - /** - * Returns the AddressBook. - * - * @see seedu.address.model.Model#getAddressBook() - */ - ReadOnlyAddressBook getAddressBook(); - - /** Returns an unmodifiable view of the filtered list of persons */ - ObservableList getFilteredPersonList(); - - /** - * Returns the user prefs' address book file path. - */ - Path getAddressBookFilePath(); - - /** - * Returns the user prefs' GUI settings. - */ - GuiSettings getGuiSettings(); - - /** - * Set the user prefs' GUI settings. - */ - void setGuiSettings(GuiSettings guiSettings); -} diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/seedu/address/logic/LogicManager.java deleted file mode 100644 index d47ce874b1a..00000000000 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ /dev/null @@ -1,78 +0,0 @@ -package seedu.address.logic; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.logging.Logger; - -import javafx.collections.ObservableList; -import seedu.address.commons.core.GuiSettings; -import seedu.address.commons.core.LogsCenter; -import seedu.address.logic.commands.Command; -import seedu.address.logic.commands.CommandResult; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.logic.parser.AddressBookParser; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.Model; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Person; -import seedu.address.storage.Storage; - -/** - * The main LogicManager of the app. - */ -public class LogicManager implements Logic { - public static final String FILE_OPS_ERROR_MESSAGE = "Could not save data to file: "; - private final Logger logger = LogsCenter.getLogger(LogicManager.class); - - private final Model model; - private final Storage storage; - private final AddressBookParser addressBookParser; - - public LogicManager(Model model, Storage storage) { - this.model = model; - this.storage = storage; - addressBookParser = new AddressBookParser(); - } - - @Override - public CommandResult execute(String commandText) throws CommandException, ParseException { - logger.info("----------------[USER COMMAND][" + commandText + "]"); - - CommandResult commandResult; - Command command = addressBookParser.parseCommand(commandText); - commandResult = command.execute(model); - - try { - storage.saveAddressBook(model.getAddressBook()); - } catch (IOException ioe) { - throw new CommandException(FILE_OPS_ERROR_MESSAGE + ioe, ioe); - } - - return commandResult; - } - - @Override - public ReadOnlyAddressBook getAddressBook() { - return model.getAddressBook(); - } - - @Override - public ObservableList getFilteredPersonList() { - return model.getFilteredPersonList(); - } - - @Override - public Path getAddressBookFilePath() { - return model.getAddressBookFilePath(); - } - - @Override - public GuiSettings getGuiSettings() { - return model.getGuiSettings(); - } - - @Override - public void setGuiSettings(GuiSettings guiSettings) { - model.setGuiSettings(guiSettings); - } -} diff --git a/src/main/java/seedu/address/logic/aggregators/Aggregators.java b/src/main/java/seedu/address/logic/aggregators/Aggregators.java new file mode 100644 index 00000000000..c2ea9557a51 --- /dev/null +++ b/src/main/java/seedu/address/logic/aggregators/Aggregators.java @@ -0,0 +1,7 @@ +package seedu.address.logic.aggregators; + +import java.util.ArrayList; + +public interface Aggregators { + public ArrayList collect(ArrayList initialList); +} diff --git a/src/main/java/seedu/address/logic/aggregators/GroupByIDPairsAggregators.java b/src/main/java/seedu/address/logic/aggregators/GroupByIDPairsAggregators.java new file mode 100644 index 00000000000..dd1fc9f74ea --- /dev/null +++ b/src/main/java/seedu/address/logic/aggregators/GroupByIDPairsAggregators.java @@ -0,0 +1,27 @@ +package seedu.address.logic.aggregators; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import seedu.address.model.bluetooth.BluetoothPings; +import seedu.address.model.bluetooth.BluetoothPingsSummary; + +public class GroupByIDPairsAggregators implements Aggregators { + @Override + public ArrayList collect(ArrayList initialList) { + ArrayList pingsSummary = new ArrayList(); + + Map, Long> collection = initialList.stream() + .collect(Collectors.groupingBy( + BluetoothPings::getUserIDs, + Collectors.counting() + )); + collection.forEach( + (userIdList, threshold) -> { + pingsSummary.add(new BluetoothPingsSummary(userIdList, threshold)); + }); + + return pingsSummary; + } +} diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java deleted file mode 100644 index 71656d7c5c8..00000000000 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ /dev/null @@ -1,67 +0,0 @@ -package seedu.address.logic.commands; - -import static java.util.Objects.requireNonNull; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; - -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; -import seedu.address.model.person.Person; - -/** - * Adds a person to the address book. - */ -public class AddCommand extends Command { - - public static final String COMMAND_WORD = "add"; - - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a person to the address book. " - + "Parameters: " - + PREFIX_NAME + "NAME " - + PREFIX_PHONE + "PHONE " - + PREFIX_EMAIL + "EMAIL " - + PREFIX_ADDRESS + "ADDRESS " - + "[" + PREFIX_TAG + "TAG]...\n" - + "Example: " + COMMAND_WORD + " " - + PREFIX_NAME + "John Doe " - + PREFIX_PHONE + "98765432 " - + PREFIX_EMAIL + "johnd@example.com " - + PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 " - + PREFIX_TAG + "friends " - + PREFIX_TAG + "owesMoney"; - - public static final String MESSAGE_SUCCESS = "New person added: %1$s"; - public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book"; - - private final Person toAdd; - - /** - * Creates an AddCommand to add the specified {@code Person} - */ - public AddCommand(Person person) { - requireNonNull(person); - toAdd = person; - } - - @Override - public CommandResult execute(Model model) throws CommandException { - requireNonNull(model); - - if (model.hasPerson(toAdd)) { - throw new CommandException(MESSAGE_DUPLICATE_PERSON); - } - - model.addPerson(toAdd); - return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd)); - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof AddCommand // instanceof handles nulls - && toAdd.equals(((AddCommand) other).toAdd)); - } -} diff --git a/src/main/java/seedu/address/logic/commands/AppCommand.java b/src/main/java/seedu/address/logic/commands/AppCommand.java new file mode 100644 index 00000000000..e5a830b9360 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/AppCommand.java @@ -0,0 +1,26 @@ +package seedu.address.logic.commands; + +import seedu.address.logic.messages.AppMessage; +import seedu.address.logic.messages.BluetoothPingsMessage; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.storage.AppStorage; + +public interface AppCommand { + + /** + * To validate that the arguments passed in are sound + * + * @param arguments String arguments + * @return AppCommand + * @throws ParseException Raise if arguments do not meet the condition + */ + public AppCommand validate(String arguments) throws ParseException; + + /** + * Command interface + * + * @param dao Data access object + * @return CommandResult + */ + public AppMessage execute(AppStorage dao); +} diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java deleted file mode 100644 index 9c86b1fa6e4..00000000000 --- a/src/main/java/seedu/address/logic/commands/ClearCommand.java +++ /dev/null @@ -1,23 +0,0 @@ -package seedu.address.logic.commands; - -import static java.util.Objects.requireNonNull; - -import seedu.address.model.AddressBook; -import seedu.address.model.Model; - -/** - * Clears the address book. - */ -public class ClearCommand extends Command { - - public static final String COMMAND_WORD = "clear"; - public static final String MESSAGE_SUCCESS = "Address book has been cleared!"; - - - @Override - public CommandResult execute(Model model) { - requireNonNull(model); - model.setAddressBook(new AddressBook()); - return new CommandResult(MESSAGE_SUCCESS); - } -} diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/seedu/address/logic/commands/Command.java deleted file mode 100644 index 64f18992160..00000000000 --- a/src/main/java/seedu/address/logic/commands/Command.java +++ /dev/null @@ -1,20 +0,0 @@ -package seedu.address.logic.commands; - -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; - -/** - * Represents a command with hidden internal logic and the ability to be executed. - */ -public abstract class Command { - - /** - * Executes the command and returns the result message. - * - * @param model {@code Model} which the command should operate on. - * @return feedback message of the operation result for display - * @throws CommandException If an error occurs during command execution. - */ - public abstract CommandResult execute(Model model) throws CommandException; - -} diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java deleted file mode 100644 index 02fd256acba..00000000000 --- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java +++ /dev/null @@ -1,53 +0,0 @@ -package seedu.address.logic.commands; - -import static java.util.Objects.requireNonNull; - -import java.util.List; - -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; -import seedu.address.model.person.Person; - -/** - * Deletes a person identified using it's displayed index from the address book. - */ -public class DeleteCommand extends Command { - - public static final String COMMAND_WORD = "delete"; - - public static final String MESSAGE_USAGE = COMMAND_WORD - + ": Deletes the person identified by the index number used in the displayed person list.\n" - + "Parameters: INDEX (must be a positive integer)\n" - + "Example: " + COMMAND_WORD + " 1"; - - public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s"; - - private final Index targetIndex; - - public DeleteCommand(Index targetIndex) { - this.targetIndex = targetIndex; - } - - @Override - public CommandResult execute(Model model) throws CommandException { - requireNonNull(model); - List lastShownList = model.getFilteredPersonList(); - - if (targetIndex.getZeroBased() >= lastShownList.size()) { - throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - Person personToDelete = lastShownList.get(targetIndex.getZeroBased()); - model.deletePerson(personToDelete); - return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, personToDelete)); - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof DeleteCommand // instanceof handles nulls - && targetIndex.equals(((DeleteCommand) other).targetIndex)); // state check - } -} diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java deleted file mode 100644 index 7e36114902f..00000000000 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ /dev/null @@ -1,226 +0,0 @@ -package seedu.address.logic.commands; - -import static java.util.Objects.requireNonNull; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; -import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; - -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; - -import seedu.address.commons.core.Messages; -import seedu.address.commons.core.index.Index; -import seedu.address.commons.util.CollectionUtil; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; - -/** - * Edits the details of an existing person in the address book. - */ -public class EditCommand extends Command { - - public static final String COMMAND_WORD = "edit"; - - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the person identified " - + "by the index number used in the displayed person list. " - + "Existing values will be overwritten by the input values.\n" - + "Parameters: INDEX (must be a positive integer) " - + "[" + PREFIX_NAME + "NAME] " - + "[" + PREFIX_PHONE + "PHONE] " - + "[" + PREFIX_EMAIL + "EMAIL] " - + "[" + PREFIX_ADDRESS + "ADDRESS] " - + "[" + PREFIX_TAG + "TAG]...\n" - + "Example: " + COMMAND_WORD + " 1 " - + PREFIX_PHONE + "91234567 " - + PREFIX_EMAIL + "johndoe@example.com"; - - public static final String MESSAGE_EDIT_PERSON_SUCCESS = "Edited Person: %1$s"; - public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided."; - public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book."; - - private final Index index; - private final EditPersonDescriptor editPersonDescriptor; - - /** - * @param index of the person in the filtered person list to edit - * @param editPersonDescriptor details to edit the person with - */ - public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) { - requireNonNull(index); - requireNonNull(editPersonDescriptor); - - this.index = index; - this.editPersonDescriptor = new EditPersonDescriptor(editPersonDescriptor); - } - - @Override - public CommandResult execute(Model model) throws CommandException { - requireNonNull(model); - List lastShownList = model.getFilteredPersonList(); - - if (index.getZeroBased() >= lastShownList.size()) { - throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - Person personToEdit = lastShownList.get(index.getZeroBased()); - Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor); - - if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) { - throw new CommandException(MESSAGE_DUPLICATE_PERSON); - } - - model.setPerson(personToEdit, editedPerson); - model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); - return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson)); - } - - /** - * Creates and returns a {@code Person} with the details of {@code personToEdit} - * edited with {@code editPersonDescriptor}. - */ - private static Person createEditedPerson(Person personToEdit, EditPersonDescriptor editPersonDescriptor) { - assert personToEdit != null; - - Name updatedName = editPersonDescriptor.getName().orElse(personToEdit.getName()); - Phone updatedPhone = editPersonDescriptor.getPhone().orElse(personToEdit.getPhone()); - Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail()); - Address updatedAddress = editPersonDescriptor.getAddress().orElse(personToEdit.getAddress()); - Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags()); - - return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags); - } - - @Override - public boolean equals(Object other) { - // short circuit if same object - if (other == this) { - return true; - } - - // instanceof handles nulls - if (!(other instanceof EditCommand)) { - return false; - } - - // state check - EditCommand e = (EditCommand) other; - return index.equals(e.index) - && editPersonDescriptor.equals(e.editPersonDescriptor); - } - - /** - * Stores the details to edit the person with. Each non-empty field value will replace the - * corresponding field value of the person. - */ - public static class EditPersonDescriptor { - private Name name; - private Phone phone; - private Email email; - private Address address; - private Set tags; - - public EditPersonDescriptor() {} - - /** - * Copy constructor. - * A defensive copy of {@code tags} is used internally. - */ - public EditPersonDescriptor(EditPersonDescriptor toCopy) { - setName(toCopy.name); - setPhone(toCopy.phone); - setEmail(toCopy.email); - setAddress(toCopy.address); - setTags(toCopy.tags); - } - - /** - * Returns true if at least one field is edited. - */ - public boolean isAnyFieldEdited() { - return CollectionUtil.isAnyNonNull(name, phone, email, address, tags); - } - - public void setName(Name name) { - this.name = name; - } - - public Optional getName() { - return Optional.ofNullable(name); - } - - public void setPhone(Phone phone) { - this.phone = phone; - } - - public Optional getPhone() { - return Optional.ofNullable(phone); - } - - public void setEmail(Email email) { - this.email = email; - } - - public Optional getEmail() { - return Optional.ofNullable(email); - } - - public void setAddress(Address address) { - this.address = address; - } - - public Optional
getAddress() { - return Optional.ofNullable(address); - } - - /** - * Sets {@code tags} to this object's {@code tags}. - * A defensive copy of {@code tags} is used internally. - */ - public void setTags(Set tags) { - this.tags = (tags != null) ? new HashSet<>(tags) : null; - } - - /** - * Returns an unmodifiable tag set, which throws {@code UnsupportedOperationException} - * if modification is attempted. - * Returns {@code Optional#empty()} if {@code tags} is null. - */ - public Optional> getTags() { - return (tags != null) ? Optional.of(Collections.unmodifiableSet(tags)) : Optional.empty(); - } - - @Override - public boolean equals(Object other) { - // short circuit if same object - if (other == this) { - return true; - } - - // instanceof handles nulls - if (!(other instanceof EditPersonDescriptor)) { - return false; - } - - // state check - EditPersonDescriptor e = (EditPersonDescriptor) other; - - return getName().equals(e.getName()) - && getPhone().equals(e.getPhone()) - && getEmail().equals(e.getEmail()) - && getAddress().equals(e.getAddress()) - && getTags().equals(e.getTags()); - } - } -} diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/seedu/address/logic/commands/ExitCommand.java deleted file mode 100644 index 3dd85a8ba90..00000000000 --- a/src/main/java/seedu/address/logic/commands/ExitCommand.java +++ /dev/null @@ -1,19 +0,0 @@ -package seedu.address.logic.commands; - -import seedu.address.model.Model; - -/** - * Terminates the program. - */ -public class ExitCommand extends Command { - - public static final String COMMAND_WORD = "exit"; - - public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting Address Book as requested ..."; - - @Override - public CommandResult execute(Model model) { - return new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, true); - } - -} diff --git a/src/main/java/seedu/address/logic/commands/FilterDangerCommand.java b/src/main/java/seedu/address/logic/commands/FilterDangerCommand.java new file mode 100644 index 00000000000..87cef00f47d --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/FilterDangerCommand.java @@ -0,0 +1,50 @@ +package seedu.address.logic.commands; + +import seedu.address.commons.core.LogsCenter; +import seedu.address.logic.aggregators.Aggregators; +import seedu.address.logic.aggregators.GroupByIDPairsAggregators; +import seedu.address.logic.conditions.Conditions; +import seedu.address.logic.conditions.DangerConditions; +import seedu.address.logic.messages.BluetoothSummaryMessage; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.bluetooth.BluetoothPings; +import seedu.address.model.bluetooth.BluetoothPingsSummary; +import seedu.address.storage.AppStorage; + +import java.util.ArrayList; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class FilterDangerCommand implements AppCommand { + private int THRESHOLD; + + public static final String COMMAND_WORD = "danger"; + private static final Pattern COMMAND_FORMAT = Pattern.compile("(?\\d+)"); + private final Logger logger = LogsCenter.getLogger(FilterDangerCommand.class); + + @Override + public AppCommand validate(String arguments) throws ParseException { + logger.info(String.format("Validating: %s", arguments)); + final Matcher matcher = COMMAND_FORMAT.matcher(arguments.trim()); + + if (!matcher.matches()) { + String error = String.format("Command %s invalid", arguments); + throw new ParseException(error); + } + + this.THRESHOLD = Integer.parseInt(matcher.group("threshold")); + return this; + } + + @Override + public BluetoothSummaryMessage execute(AppStorage dao) { + Conditions cond = new DangerConditions(this.THRESHOLD); + Aggregators agg = new GroupByIDPairsAggregators(); + ArrayList resp = dao.search(cond, agg); + BluetoothSummaryMessage result = new BluetoothSummaryMessage("Identified dangerous users", false); + result.setToDisplayList(resp); + return result; + } + +} diff --git a/src/main/java/seedu/address/logic/commands/FilterTimestampCommand.java b/src/main/java/seedu/address/logic/commands/FilterTimestampCommand.java new file mode 100644 index 00000000000..20d9e3b749d --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/FilterTimestampCommand.java @@ -0,0 +1,46 @@ +package seedu.address.logic.commands; + +import seedu.address.commons.core.LogsCenter; +import seedu.address.logic.conditions.Conditions; +import seedu.address.logic.conditions.TimestampConditions; +import seedu.address.logic.messages.BluetoothPingsMessage; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.storage.AppStorage; + +import java.util.ArrayList; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class FilterTimestampCommand implements AppCommand { + private static Long START_TIME; + private static Long END_TIME; + + public static final String COMMAND_WORD = "from"; + private static final Pattern COMMAND_FORMAT = Pattern.compile("(?\\d+) to (?\\d+)"); + private final Logger logger = LogsCenter.getLogger(FilterTimestampCommand.class); + + @Override + public FilterTimestampCommand validate(String arguments) throws ParseException { + logger.info(String.format("Validating: %s", arguments)); + final Matcher matcher = COMMAND_FORMAT.matcher(arguments.trim()); + + if (!matcher.matches()) { + String error = String.format("Command %s invalid", arguments); + throw new ParseException(error); + } + + this.START_TIME = Long.parseLong(matcher.group("start")); + this.END_TIME = Long.parseLong(matcher.group("end")); + return this; + } + + @Override + public BluetoothPingsMessage execute(AppStorage dao) { + Conditions cond = new TimestampConditions(this.START_TIME, this.END_TIME); + ArrayList resp = dao.search(cond); + BluetoothPingsMessage result = new BluetoothPingsMessage("Filtered by timestamp", false); + result.setToDisplayList(resp); + return result; + } +} diff --git a/src/main/java/seedu/address/logic/commands/FilterUserIDCommand.java b/src/main/java/seedu/address/logic/commands/FilterUserIDCommand.java new file mode 100644 index 00000000000..e0c883e2ef6 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/FilterUserIDCommand.java @@ -0,0 +1,44 @@ +package seedu.address.logic.commands; + +import seedu.address.commons.core.LogsCenter; +import seedu.address.logic.conditions.Conditions; +import seedu.address.logic.conditions.UserIDConditions; +import seedu.address.logic.messages.BluetoothPingsMessage; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.storage.AppStorage; + +import java.util.ArrayList; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class FilterUserIDCommand implements AppCommand { + private static int USER_ID; + public static final String COMMAND_WORD = "id"; + private static final Pattern COMMAND_FORMAT = Pattern.compile("is (?\\d+)"); + private final Logger logger = LogsCenter.getLogger(FilterUserIDCommand.class); + + @Override + public FilterUserIDCommand validate(String arguments) throws ParseException { + logger.info(String.format("Validating: %s", arguments)); + final Matcher matcher = COMMAND_FORMAT.matcher(arguments.trim()); + + if (!matcher.matches()) { + String error = String.format("Command %s invalid", arguments); + throw new ParseException(error); + } + + this.USER_ID = Integer.parseInt(matcher.group("userid")); + return this; + } + + @Override + public BluetoothPingsMessage execute(AppStorage dao) { + Conditions cond = new UserIDConditions(USER_ID); + ArrayList resp = dao.search(cond); + BluetoothPingsMessage result = new BluetoothPingsMessage("Identifying recods with User ID.", false); + result.setToDisplayList(resp); + return result; + } +} + diff --git a/src/main/java/seedu/address/logic/commands/FilterUserPairsCommand.java b/src/main/java/seedu/address/logic/commands/FilterUserPairsCommand.java new file mode 100644 index 00000000000..b73feca01d8 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/FilterUserPairsCommand.java @@ -0,0 +1,45 @@ +package seedu.address.logic.commands; + +import seedu.address.commons.core.LogsCenter; +import seedu.address.logic.conditions.Conditions; +import seedu.address.logic.conditions.UserPairsConditions; +import seedu.address.logic.messages.BluetoothPingsMessage; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.storage.AppStorage; + +import java.util.ArrayList; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class FilterUserPairsCommand implements AppCommand { + private int USER_A; + private int USER_B; + public static final String COMMAND_WORD = "pairs"; + private static final Pattern COMMAND_FORMAT = Pattern.compile("(?\\d+) and (?\\d+)"); + private final Logger logger = LogsCenter.getLogger(FilterUserPairsCommand.class); + + @Override + public FilterUserPairsCommand validate(String arguments) throws ParseException { + logger.info(String.format("Validating: %s", arguments)); + final Matcher matcher = COMMAND_FORMAT.matcher(arguments.trim()); + + if (!matcher.matches()) { + String error = String.format("Command %s invalid", arguments); + throw new ParseException(error); + } + + this.USER_A = Integer.parseInt(matcher.group("userA")); + this.USER_B = Integer.parseInt(matcher.group("userB")); + return this; + } + + @Override + public BluetoothPingsMessage execute(AppStorage dao) { + Conditions cond = new UserPairsConditions(USER_A, USER_B); + ArrayList resp = dao.search(cond); + BluetoothPingsMessage result = new BluetoothPingsMessage("Identifying recods with User Pairs.", false); + result.setToDisplayList(resp); + return result; + } +} diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java deleted file mode 100644 index d6b19b0a0de..00000000000 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ /dev/null @@ -1,42 +0,0 @@ -package seedu.address.logic.commands; - -import static java.util.Objects.requireNonNull; - -import seedu.address.commons.core.Messages; -import seedu.address.model.Model; -import seedu.address.model.person.NameContainsKeywordsPredicate; - -/** - * Finds and lists all persons in address book whose name contains any of the argument keywords. - * Keyword matching is case insensitive. - */ -public class FindCommand extends Command { - - public static final String COMMAND_WORD = "find"; - - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose names contain any of " - + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n" - + "Parameters: KEYWORD [MORE_KEYWORDS]...\n" - + "Example: " + COMMAND_WORD + " alice bob charlie"; - - private final NameContainsKeywordsPredicate predicate; - - public FindCommand(NameContainsKeywordsPredicate predicate) { - this.predicate = predicate; - } - - @Override - public CommandResult execute(Model model) { - requireNonNull(model); - model.updateFilteredPersonList(predicate); - return new CommandResult( - String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size())); - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof FindCommand // instanceof handles nulls - && predicate.equals(((FindCommand) other).predicate)); // state check - } -} diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/seedu/address/logic/commands/HelpCommand.java deleted file mode 100644 index bf824f91bd0..00000000000 --- a/src/main/java/seedu/address/logic/commands/HelpCommand.java +++ /dev/null @@ -1,21 +0,0 @@ -package seedu.address.logic.commands; - -import seedu.address.model.Model; - -/** - * Format full help instructions for every command for display. - */ -public class HelpCommand extends Command { - - public static final String COMMAND_WORD = "help"; - - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Shows program usage instructions.\n" - + "Example: " + COMMAND_WORD; - - public static final String SHOWING_HELP_MESSAGE = "Opened help window."; - - @Override - public CommandResult execute(Model model) { - return new CommandResult(SHOWING_HELP_MESSAGE, true, false); - } -} diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/ListCommand.java deleted file mode 100644 index 84be6ad2596..00000000000 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ /dev/null @@ -1,24 +0,0 @@ -package seedu.address.logic.commands; - -import static java.util.Objects.requireNonNull; -import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; - -import seedu.address.model.Model; - -/** - * Lists all persons in the address book to the user. - */ -public class ListCommand extends Command { - - public static final String COMMAND_WORD = "list"; - - public static final String MESSAGE_SUCCESS = "Listed all persons"; - - - @Override - public CommandResult execute(Model model) { - requireNonNull(model); - model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); - return new CommandResult(MESSAGE_SUCCESS); - } -} diff --git a/src/main/java/seedu/address/logic/commands/ReportGenerationCommand.java b/src/main/java/seedu/address/logic/commands/ReportGenerationCommand.java new file mode 100644 index 00000000000..821d7467d32 --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/ReportGenerationCommand.java @@ -0,0 +1,157 @@ +package seedu.address.logic.commands; + +import seedu.address.logic.aggregators.Aggregators; +import seedu.address.logic.aggregators.GroupByIDPairsAggregators; +import seedu.address.logic.conditions.*; +import seedu.address.logic.messages.BluetoothPingsMessage; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.bluetooth.BluetoothPings; +import seedu.address.model.bluetooth.BluetoothPingsSummary; +import seedu.address.report_generator.report_generator; +import seedu.address.storage.AppStorage; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ReportGenerationCommand implements AppCommand { + public static final String COMMAND_WORD = "report"; + public static String con_type = "None"; + public static int TARGET_ID; + public static long START_TIME; + public static long END_TIME; + public static int ID1; + public static int ID2; + public static int THRESHOLD; + public static final String CON_TYPE_ERROR = "Condition type not well defined"; + + + @Override + public ReportGenerationCommand validate(String arguments) throws ParseException { + System.out.println("In validate function, argument is " + arguments.trim()); + + if (arguments.trim().equals("all")) + { + System.out.println("Report all"); + con_type = "None"; + } + else + { + Pattern ID = Pattern.compile("id is (?\\d+)"); + Matcher m = ID.matcher(arguments.trim()); + if (m.matches()) + { + System.out.println("Report ID"); + this.TARGET_ID = Integer.parseInt(m.group("userid")); + this.con_type = "ID"; + } + else + { + Pattern Time = Pattern.compile("time from (?\\d+) to (?\\d+)"); + m = Time.matcher(arguments.trim()); + if (m.matches()) + { + System.out.println("Report Time"); + this.START_TIME = Long.parseLong(m.group("start")); + this.END_TIME = Long.parseLong(m.group("end")); + this.con_type = "Time"; + } + + else + { + Pattern pair = Pattern.compile("pairs (?\\d+) and (?\\d+)"); + m = pair.matcher(arguments.trim()); + + if (m.matches()) + { + System.out.println("Report ID pairs"); + this.ID1 = Integer.parseInt(m.group("userA")); + this.ID2 = Integer.parseInt(m.group("userB")); + this.con_type = "pairs"; + } + else + { + Pattern danger = Pattern.compile("danger (?\\d+)"); + m = danger.matcher(arguments.trim()); + + if (m.matches()) + { + System.out.println("Report Danger pairs"); + this.THRESHOLD = Integer.parseInt(m.group("threshold")); + this.con_type = "danger"; + } + else + { + + String error = String.format("Command %s invalid", arguments); + throw new ParseException(error); + } + } + } + } + } + + System.out.println(this.con_type + " " + this.TARGET_ID + " " + this.START_TIME + " " +this.END_TIME + " " + this.ID1 + " " + this.ID2 + " " + this.THRESHOLD); + + return this; + } + + @Override + public BluetoothPingsMessage execute(AppStorage dao) { + System.out.println("Now in execute function"); + ArrayList resp = new ArrayList(); + switch (this.con_type) + { + case "ID": + System.out.println("Search by ID"); + Conditions cond = new UserIDConditions(this.TARGET_ID); + resp = dao.search(cond); + System.out.println("The size of search result is"); + System.out.println(resp.size()); + break; + + case "Time": + System.out.println("Search by time"); + cond = new TimestampConditions(this.START_TIME, this.END_TIME); + resp = dao.search(cond); + System.out.println("The size of search result is"); + System.out.println(resp.size()); + break; + + case "pairs": + System.out.println(("Search by pair")); + cond = new UserPairsConditions(this.ID1, this.ID2); + resp = dao.search(cond); + + case "danger": + System.out.println("search by danger"); + cond = new DangerConditions(this.THRESHOLD); + Aggregators agg = new GroupByIDPairsAggregators(); + agg = new GroupByIDPairsAggregators(); + resp = dao.search(cond, agg); + + case "None": + System.out.println("Search all"); + resp = dao.search(); + System.out.println("The size of search result is"); + System.out.println(resp.size()); + break; + } + + + report_generator generator = new report_generator(); + System.out.println("Generating reports"); + try { + generator.GenerateReport(resp); + }catch (Exception e) + { + System.out.println("Write failed"); + } + + BluetoothPingsMessage result = new BluetoothPingsMessage("Saved report file to result folder.", false); + result.setToDisplayList(resp); + return result; + + } +} diff --git a/src/main/java/seedu/address/logic/conditions/Conditions.java b/src/main/java/seedu/address/logic/conditions/Conditions.java new file mode 100644 index 00000000000..e33d7c8d99c --- /dev/null +++ b/src/main/java/seedu/address/logic/conditions/Conditions.java @@ -0,0 +1,10 @@ +package seedu.address.logic.conditions; + +public interface Conditions { + + /** + * Given a class, enforce logic to see if certain properties of the class meets the condition + * This may be used in conjunction with filtering logic + */ + public Boolean satisfies(T objToTest); +} diff --git a/src/main/java/seedu/address/logic/conditions/DangerConditions.java b/src/main/java/seedu/address/logic/conditions/DangerConditions.java new file mode 100644 index 00000000000..2e9e9c63883 --- /dev/null +++ b/src/main/java/seedu/address/logic/conditions/DangerConditions.java @@ -0,0 +1,14 @@ +package seedu.address.logic.conditions; + +import seedu.address.model.bluetooth.BluetoothPingsSummary; + +public class DangerConditions implements Conditions { + private int THRESHOLD; + + public DangerConditions(int threshold) {this.THRESHOLD = threshold;} + + @Override + public Boolean satisfies(BluetoothPingsSummary objToTest) { + return objToTest.getCounts() >= this.THRESHOLD; + } +} diff --git a/src/main/java/seedu/address/logic/conditions/LiterallyNoConditions.java b/src/main/java/seedu/address/logic/conditions/LiterallyNoConditions.java new file mode 100644 index 00000000000..b6b65cac402 --- /dev/null +++ b/src/main/java/seedu/address/logic/conditions/LiterallyNoConditions.java @@ -0,0 +1,20 @@ +package seedu.address.logic.conditions; + +/** + * Literally no conditional filtering is being done here + * + * @param + */ +public class LiterallyNoConditions implements Conditions { + + /** + * Like I said. Literally no conditional filtering is being done here. + * + * @param objToTest + * @return Always True + */ + @Override + public Boolean satisfies(T objToTest) { + return true; + } +} diff --git a/src/main/java/seedu/address/logic/conditions/TimestampConditions.java b/src/main/java/seedu/address/logic/conditions/TimestampConditions.java new file mode 100644 index 00000000000..044a7c85ae2 --- /dev/null +++ b/src/main/java/seedu/address/logic/conditions/TimestampConditions.java @@ -0,0 +1,19 @@ +package seedu.address.logic.conditions; + +import seedu.address.model.bluetooth.BluetoothPings; + +public class TimestampConditions implements Conditions { + private Long start; + private Long end; + + public TimestampConditions(Long start, Long end) { + this.start = start; + this.end = end; + } + + @Override + public Boolean satisfies(BluetoothPings objToTest) { + Long timestamp = objToTest.getEpochTs(); + return this.start <= timestamp && timestamp <= this.end; + } +} diff --git a/src/main/java/seedu/address/logic/conditions/UserIDConditions.java b/src/main/java/seedu/address/logic/conditions/UserIDConditions.java new file mode 100644 index 00000000000..3ca011dc1e3 --- /dev/null +++ b/src/main/java/seedu/address/logic/conditions/UserIDConditions.java @@ -0,0 +1,16 @@ +package seedu.address.logic.conditions; + +import seedu.address.model.bluetooth.BluetoothPings; + +public class UserIDConditions implements Conditions { + private int userid; + + public UserIDConditions(int userid) { + this.userid = userid; + } + + @Override + public Boolean satisfies(BluetoothPings objToTest) { + return objToTest.getUserIDs().contains(this.userid); + } +} diff --git a/src/main/java/seedu/address/logic/conditions/UserPairsConditions.java b/src/main/java/seedu/address/logic/conditions/UserPairsConditions.java new file mode 100644 index 00000000000..2cf6e9c3d60 --- /dev/null +++ b/src/main/java/seedu/address/logic/conditions/UserPairsConditions.java @@ -0,0 +1,18 @@ +package seedu.address.logic.conditions; + +import seedu.address.model.bluetooth.BluetoothPings; + +public class UserPairsConditions implements Conditions { + private int USER_A; + private int USER_B; + + public UserPairsConditions(int USER_A, int USER_B) { + this.USER_A = USER_A; + this.USER_B = USER_B; + } + + @Override + public Boolean satisfies(BluetoothPings objToTest) { + return objToTest.getUserIDs().contains(this.USER_A) && objToTest.getUserIDs().contains(this.USER_B); + } +} diff --git a/src/main/java/seedu/address/logic/messages/AppMessage.java b/src/main/java/seedu/address/logic/messages/AppMessage.java new file mode 100644 index 00000000000..b0a33d683a1 --- /dev/null +++ b/src/main/java/seedu/address/logic/messages/AppMessage.java @@ -0,0 +1,12 @@ +package seedu.address.logic.messages; + +import javafx.collections.ObservableList; + +public abstract class AppMessage { + public String IDENTIFIER; + public abstract Boolean getRenderFlag(); + public abstract String getIdentifier(); + public abstract ObservableList getDisplayAsObservable(); + public abstract String getFeedbackToUser(); + public abstract boolean isExit(); +} diff --git a/src/main/java/seedu/address/logic/messages/BluetoothPingsMessage.java b/src/main/java/seedu/address/logic/messages/BluetoothPingsMessage.java new file mode 100644 index 00000000000..64d1fd62aa0 --- /dev/null +++ b/src/main/java/seedu/address/logic/messages/BluetoothPingsMessage.java @@ -0,0 +1,82 @@ +package seedu.address.logic.messages; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import seedu.address.model.bluetooth.BluetoothPings; + +import java.util.ArrayList; +import java.util.Objects; +import static java.util.Objects.requireNonNull; + +public class BluetoothPingsMessage extends AppMessage { + private final String feedbackToUser; + private ArrayList toDisplayList; + private Boolean RENDER_FLAG; + public final String IDENTIFIER = "BluetoothPings"; + + /** The application should exit. */ + private final boolean exit; + + /** + * Constructs a {@code CommandResult} with the specified fields. + */ + public BluetoothPingsMessage(String feedbackToUser, boolean exit) { + this.feedbackToUser = requireNonNull(feedbackToUser); + this.exit = exit; + this.RENDER_FLAG = false; + } + + /** + * Constructs a {@code CommandResult} with the specified {@code feedbackToUser}, + * and other fields set to their default value. + */ + public BluetoothPingsMessage(String feedbackToUser) { + this(feedbackToUser, false); + } + + public String getFeedbackToUser() { + return feedbackToUser; + } + + public Boolean getRenderFlag() { return this.RENDER_FLAG; } + + public String getIdentifier() { return this.IDENTIFIER; } + + public ObservableList getDisplayAsObservable() { return FXCollections.observableArrayList(this.toDisplayList); } + + /** + * A display list contains the necessary items needed to be rendered on the screen + * If this function is called, we set the RENDER_FLAG to true as signal that there is something to be displayed + * + * @param displayList List to be rendered on the screen + */ + public void setToDisplayList(ArrayList displayList) { + this.toDisplayList = displayList; + this.RENDER_FLAG = true; + } + + public boolean isExit() { + return exit; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof BluetoothPingsMessage)) { + return false; + } + + BluetoothPingsMessage otherCommandResult = (BluetoothPingsMessage) other; + return feedbackToUser.equals(otherCommandResult.feedbackToUser) + && exit == otherCommandResult.exit; + } + + @Override + public int hashCode() { + return Objects.hash(feedbackToUser, exit); + } +} diff --git a/src/main/java/seedu/address/logic/messages/BluetoothSummaryMessage.java b/src/main/java/seedu/address/logic/messages/BluetoothSummaryMessage.java new file mode 100644 index 00000000000..23d6ccf7204 --- /dev/null +++ b/src/main/java/seedu/address/logic/messages/BluetoothSummaryMessage.java @@ -0,0 +1,84 @@ +package seedu.address.logic.messages; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import seedu.address.model.bluetooth.BluetoothPingsSummary; + +import java.util.ArrayList; +import java.util.Objects; + +import static java.util.Objects.requireNonNull; + +public class BluetoothSummaryMessage extends AppMessage { + private final String feedbackToUser; + private ArrayList toDisplayList; + private Boolean RENDER_FLAG; + public final String IDENTIFIER = "BluetoothPingsSummary"; + + /** The application should exit. */ + private final boolean exit; + + /** + * Constructs a {@code CommandResult} with the specified fields. + */ + public BluetoothSummaryMessage(String feedbackToUser, boolean exit) { + this.feedbackToUser = requireNonNull(feedbackToUser); + this.exit = exit; + this.RENDER_FLAG = false; + } + + /** + * Constructs a {@code CommandResult} with the specified {@code feedbackToUser}, + * and other fields set to their default value. + */ + public BluetoothSummaryMessage(String feedbackToUser) { + this(feedbackToUser, false); + } + + public String getFeedbackToUser() { + return feedbackToUser; + } + + public Boolean getRenderFlag() { return this.RENDER_FLAG; } + + public String getIdentifier() { return this.IDENTIFIER; } + + public ObservableList getDisplayAsObservable() { return FXCollections.observableArrayList(this.toDisplayList); } + + /** + * A display list contains the necessary items needed to be rendered on the screen + * If this function is called, we set the RENDER_FLAG to true as signal that there is something to be displayed + * + * @param displayList List to be rendered on the screen + */ + public void setToDisplayList(ArrayList displayList) { + this.toDisplayList = displayList; + this.RENDER_FLAG = true; + } + + public boolean isExit() { + return exit; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof BluetoothPingsMessage)) { + return false; + } + + BluetoothSummaryMessage otherCommandResult = (BluetoothSummaryMessage) other; + return feedbackToUser.equals(otherCommandResult.feedbackToUser) + && exit == otherCommandResult.exit; + } + + @Override + public int hashCode() { + return Objects.hash(feedbackToUser, exit); + } + +} diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java deleted file mode 100644 index 3b8bfa035e8..00000000000 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ /dev/null @@ -1,60 +0,0 @@ -package seedu.address.logic.parser; - -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; - -import java.util.Set; -import java.util.stream.Stream; - -import seedu.address.logic.commands.AddCommand; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; - -/** - * Parses input arguments and creates a new AddCommand object - */ -public class AddCommandParser implements Parser { - - /** - * 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 - */ - public AddCommand parse(String args) throws ParseException { - ArgumentMultimap argMultimap = - ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); - - if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL) - || !argMultimap.getPreamble().isEmpty()) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); - } - - Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()); - Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()); - Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get()); - Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get()); - Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); - - Person person = new Person(name, phone, email, address, tagList); - - return new AddCommand(person); - } - - /** - * 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()); - } - -} diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java deleted file mode 100644 index 1e466792b46..00000000000 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ /dev/null @@ -1,76 +0,0 @@ -package seedu.address.logic.parser; - -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import seedu.address.logic.commands.AddCommand; -import seedu.address.logic.commands.ClearCommand; -import seedu.address.logic.commands.Command; -import seedu.address.logic.commands.DeleteCommand; -import seedu.address.logic.commands.EditCommand; -import seedu.address.logic.commands.ExitCommand; -import seedu.address.logic.commands.FindCommand; -import seedu.address.logic.commands.HelpCommand; -import seedu.address.logic.commands.ListCommand; -import seedu.address.logic.parser.exceptions.ParseException; - -/** - * Parses user input. - */ -public class AddressBookParser { - - /** - * Used for initial separation of command word and args. - */ - private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)"); - - /** - * Parses user input into command for execution. - * - * @param userInput full user input string - * @return the command based on the user input - * @throws ParseException if the user input does not conform the expected format - */ - public Command parseCommand(String userInput) throws ParseException { - final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim()); - if (!matcher.matches()) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE)); - } - - final String commandWord = matcher.group("commandWord"); - final String arguments = matcher.group("arguments"); - switch (commandWord) { - - case AddCommand.COMMAND_WORD: - return new AddCommandParser().parse(arguments); - - case EditCommand.COMMAND_WORD: - return new EditCommandParser().parse(arguments); - - case DeleteCommand.COMMAND_WORD: - return new DeleteCommandParser().parse(arguments); - - case ClearCommand.COMMAND_WORD: - return new ClearCommand(); - - case FindCommand.COMMAND_WORD: - return new FindCommandParser().parse(arguments); - - case ListCommand.COMMAND_WORD: - return new ListCommand(); - - case ExitCommand.COMMAND_WORD: - return new ExitCommand(); - - case HelpCommand.COMMAND_WORD: - return new HelpCommand(); - - default: - throw new ParseException(MESSAGE_UNKNOWN_COMMAND); - } - } - -} diff --git a/src/main/java/seedu/address/logic/parser/CommandRouter.java b/src/main/java/seedu/address/logic/parser/CommandRouter.java new file mode 100644 index 00000000000..fcdcefd44c2 --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/CommandRouter.java @@ -0,0 +1,48 @@ +package seedu.address.logic.parser; + +import seedu.address.logic.commands.*; +import seedu.address.logic.parser.exceptions.ParseException; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND; + +public class CommandRouter { + private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)"); + + public static final String COMMAND_WORD = "help"; + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Shows program usage instructions.\n" + + "Example: " + COMMAND_WORD; + + public AppCommand parse(String userInput) throws ParseException { + final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim()); + if (!matcher.matches()) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, this.MESSAGE_USAGE)); + } + + final String commandWord = matcher.group("commandWord"); + final String arguments = matcher.group("arguments"); + switch (commandWord) { + + case ReportGenerationCommand.COMMAND_WORD: + return new ReportGenerationCommand().validate((arguments)); + + case FilterTimestampCommand.COMMAND_WORD: + return new FilterTimestampCommand().validate(arguments); + + case FilterUserIDCommand.COMMAND_WORD: + return new FilterUserIDCommand().validate(arguments); + + case FilterUserPairsCommand.COMMAND_WORD: + return new FilterUserPairsCommand().validate(arguments); + + case FilterDangerCommand.COMMAND_WORD: + return new FilterDangerCommand().validate(arguments); + + default: + throw new ParseException(MESSAGE_UNKNOWN_COMMAND); + } + } +} diff --git a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java b/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java deleted file mode 100644 index 522b93081cc..00000000000 --- a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java +++ /dev/null @@ -1,29 +0,0 @@ -package seedu.address.logic.parser; - -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; - -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.DeleteCommand; -import seedu.address.logic.parser.exceptions.ParseException; - -/** - * Parses input arguments and creates a new DeleteCommand object - */ -public class DeleteCommandParser implements Parser { - - /** - * Parses the given {@code String} of arguments in the context of the DeleteCommand - * and returns a DeleteCommand object for execution. - * @throws ParseException if the user input does not conform the expected format - */ - public DeleteCommand parse(String args) throws ParseException { - try { - Index index = ParserUtil.parseIndex(args); - return new DeleteCommand(index); - } catch (ParseException pe) { - throw new ParseException( - String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE), pe); - } - } - -} diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/EditCommandParser.java deleted file mode 100644 index 845644b7dea..00000000000 --- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java +++ /dev/null @@ -1,82 +0,0 @@ -package seedu.address.logic.parser; - -import static java.util.Objects.requireNonNull; -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; - -import java.util.Collection; -import java.util.Collections; -import java.util.Optional; -import java.util.Set; - -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.EditCommand; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.tag.Tag; - -/** - * Parses input arguments and creates a new EditCommand object - */ -public class EditCommandParser implements Parser { - - /** - * Parses the given {@code String} of arguments in the context of the EditCommand - * and returns an EditCommand object for execution. - * @throws ParseException if the user input does not conform the expected format - */ - public EditCommand parse(String args) throws ParseException { - requireNonNull(args); - ArgumentMultimap argMultimap = - ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); - - Index index; - - try { - index = ParserUtil.parseIndex(argMultimap.getPreamble()); - } catch (ParseException pe) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE), pe); - } - - EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor(); - if (argMultimap.getValue(PREFIX_NAME).isPresent()) { - editPersonDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get())); - } - if (argMultimap.getValue(PREFIX_PHONE).isPresent()) { - editPersonDescriptor.setPhone(ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get())); - } - if (argMultimap.getValue(PREFIX_EMAIL).isPresent()) { - editPersonDescriptor.setEmail(ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get())); - } - if (argMultimap.getValue(PREFIX_ADDRESS).isPresent()) { - editPersonDescriptor.setAddress(ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get())); - } - parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags); - - if (!editPersonDescriptor.isAnyFieldEdited()) { - throw new ParseException(EditCommand.MESSAGE_NOT_EDITED); - } - - return new EditCommand(index, editPersonDescriptor); - } - - /** - * Parses {@code Collection tags} into a {@code Set} if {@code tags} is non-empty. - * If {@code tags} contain only one element which is an empty string, it will be parsed into a - * {@code Set} containing zero tags. - */ - private Optional> parseTagsForEdit(Collection tags) throws ParseException { - assert tags != null; - - if (tags.isEmpty()) { - return Optional.empty(); - } - Collection tagSet = tags.size() == 1 && tags.contains("") ? Collections.emptySet() : tags; - return Optional.of(ParserUtil.parseTags(tagSet)); - } - -} diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java deleted file mode 100644 index 4fb71f23103..00000000000 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ /dev/null @@ -1,33 +0,0 @@ -package seedu.address.logic.parser; - -import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; - -import java.util.Arrays; - -import seedu.address.logic.commands.FindCommand; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.NameContainsKeywordsPredicate; - -/** - * Parses input arguments and creates a new FindCommand object - */ -public class FindCommandParser implements Parser { - - /** - * Parses the given {@code String} of arguments in the context of the FindCommand - * and returns a FindCommand object for execution. - * @throws ParseException if the user input does not conform the expected format - */ - public FindCommand parse(String args) throws ParseException { - String trimmedArgs = args.trim(); - if (trimmedArgs.isEmpty()) { - throw new ParseException( - String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); - } - - String[] nameKeywords = trimmedArgs.split("\\s+"); - - return new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList(nameKeywords))); - } - -} diff --git a/src/main/java/seedu/address/logic/parser/Parser.java b/src/main/java/seedu/address/logic/parser/Parser.java deleted file mode 100644 index d6551ad8e3f..00000000000 --- a/src/main/java/seedu/address/logic/parser/Parser.java +++ /dev/null @@ -1,16 +0,0 @@ -package seedu.address.logic.parser; - -import seedu.address.logic.commands.Command; -import seedu.address.logic.parser.exceptions.ParseException; - -/** - * Represents a Parser that is able to parse user input into a {@code Command} of type {@code T}. - */ -public interface Parser { - - /** - * Parses {@code userInput} into a command and returns it. - * @throws ParseException if {@code userInput} does not conform the expected format - */ - T parse(String userInput) throws ParseException; -} diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java deleted file mode 100644 index b117acb9c55..00000000000 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ /dev/null @@ -1,124 +0,0 @@ -package seedu.address.logic.parser; - -import static java.util.Objects.requireNonNull; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -import seedu.address.commons.core.index.Index; -import seedu.address.commons.util.StringUtil; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; - -/** - * Contains utility methods used for parsing strings in the various *Parser classes. - */ -public class ParserUtil { - - public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer."; - - /** - * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be - * trimmed. - * @throws ParseException if the specified index is invalid (not non-zero unsigned integer). - */ - public static Index parseIndex(String oneBasedIndex) throws ParseException { - String trimmedIndex = oneBasedIndex.trim(); - if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) { - throw new ParseException(MESSAGE_INVALID_INDEX); - } - return Index.fromOneBased(Integer.parseInt(trimmedIndex)); - } - - /** - * Parses a {@code String name} into a {@code Name}. - * Leading and trailing whitespaces will be trimmed. - * - * @throws ParseException if the given {@code name} is invalid. - */ - public static Name parseName(String name) throws ParseException { - requireNonNull(name); - String trimmedName = name.trim(); - if (!Name.isValidName(trimmedName)) { - throw new ParseException(Name.MESSAGE_CONSTRAINTS); - } - return new Name(trimmedName); - } - - /** - * Parses a {@code String phone} into a {@code Phone}. - * Leading and trailing whitespaces will be trimmed. - * - * @throws ParseException if the given {@code phone} is invalid. - */ - public static Phone parsePhone(String phone) throws ParseException { - requireNonNull(phone); - String trimmedPhone = phone.trim(); - if (!Phone.isValidPhone(trimmedPhone)) { - throw new ParseException(Phone.MESSAGE_CONSTRAINTS); - } - return new Phone(trimmedPhone); - } - - /** - * Parses a {@code String address} into an {@code Address}. - * Leading and trailing whitespaces will be trimmed. - * - * @throws ParseException if the given {@code address} is invalid. - */ - public static Address parseAddress(String address) throws ParseException { - requireNonNull(address); - String trimmedAddress = address.trim(); - if (!Address.isValidAddress(trimmedAddress)) { - throw new ParseException(Address.MESSAGE_CONSTRAINTS); - } - return new Address(trimmedAddress); - } - - /** - * Parses a {@code String email} into an {@code Email}. - * Leading and trailing whitespaces will be trimmed. - * - * @throws ParseException if the given {@code email} is invalid. - */ - public static Email parseEmail(String email) throws ParseException { - requireNonNull(email); - String trimmedEmail = email.trim(); - if (!Email.isValidEmail(trimmedEmail)) { - throw new ParseException(Email.MESSAGE_CONSTRAINTS); - } - return new Email(trimmedEmail); - } - - /** - * Parses a {@code String tag} into a {@code Tag}. - * Leading and trailing whitespaces will be trimmed. - * - * @throws ParseException if the given {@code tag} is invalid. - */ - public static Tag parseTag(String tag) throws ParseException { - requireNonNull(tag); - String trimmedTag = tag.trim(); - if (!Tag.isValidTagName(trimmedTag)) { - throw new ParseException(Tag.MESSAGE_CONSTRAINTS); - } - return new Tag(trimmedTag); - } - - /** - * Parses {@code Collection tags} into a {@code Set}. - */ - public static Set parseTags(Collection tags) throws ParseException { - requireNonNull(tags); - final Set tagSet = new HashSet<>(); - for (String tagName : tags) { - tagSet.add(parseTag(tagName)); - } - return tagSet; - } -} diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java deleted file mode 100644 index 1a943a0781a..00000000000 --- a/src/main/java/seedu/address/model/AddressBook.java +++ /dev/null @@ -1,120 +0,0 @@ -package seedu.address.model; - -import static java.util.Objects.requireNonNull; - -import java.util.List; - -import javafx.collections.ObservableList; -import seedu.address.model.person.Person; -import seedu.address.model.person.UniquePersonList; - -/** - * Wraps all data at the address-book level - * Duplicates are not allowed (by .isSamePerson comparison) - */ -public class AddressBook implements ReadOnlyAddressBook { - - private final UniquePersonList persons; - - /* - * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication - * between constructors. See https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html - * - * Note that non-static init blocks are not recommended to use. There are other ways to avoid duplication - * among constructors. - */ - { - persons = new UniquePersonList(); - } - - public AddressBook() {} - - /** - * Creates an AddressBook using the Persons in the {@code toBeCopied} - */ - public AddressBook(ReadOnlyAddressBook toBeCopied) { - this(); - resetData(toBeCopied); - } - - //// list overwrite operations - - /** - * Replaces the contents of the person list with {@code persons}. - * {@code persons} must not contain duplicate persons. - */ - public void setPersons(List persons) { - this.persons.setPersons(persons); - } - - /** - * Resets the existing data of this {@code AddressBook} with {@code newData}. - */ - public void resetData(ReadOnlyAddressBook newData) { - requireNonNull(newData); - - setPersons(newData.getPersonList()); - } - - //// person-level operations - - /** - * Returns true if a person with the same identity as {@code person} exists in the address book. - */ - public boolean hasPerson(Person person) { - requireNonNull(person); - return persons.contains(person); - } - - /** - * Adds a person to the address book. - * The person must not already exist in the address book. - */ - public void addPerson(Person p) { - persons.add(p); - } - - /** - * Replaces the given person {@code target} in the list with {@code editedPerson}. - * {@code target} must exist in the address book. - * The person identity of {@code editedPerson} must not be the same as another existing person in the address book. - */ - public void setPerson(Person target, Person editedPerson) { - requireNonNull(editedPerson); - - persons.setPerson(target, editedPerson); - } - - /** - * Removes {@code key} from this {@code AddressBook}. - * {@code key} must exist in the address book. - */ - public void removePerson(Person key) { - persons.remove(key); - } - - //// util methods - - @Override - public String toString() { - return persons.asUnmodifiableObservableList().size() + " persons"; - // TODO: refine later - } - - @Override - public ObservableList getPersonList() { - return persons.asUnmodifiableObservableList(); - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof AddressBook // instanceof handles nulls - && persons.equals(((AddressBook) other).persons)); - } - - @Override - public int hashCode() { - return persons.hashCode(); - } -} diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java deleted file mode 100644 index d54df471c1f..00000000000 --- a/src/main/java/seedu/address/model/Model.java +++ /dev/null @@ -1,87 +0,0 @@ -package seedu.address.model; - -import java.nio.file.Path; -import java.util.function.Predicate; - -import javafx.collections.ObservableList; -import seedu.address.commons.core.GuiSettings; -import seedu.address.model.person.Person; - -/** - * The API of the Model component. - */ -public interface Model { - /** {@code Predicate} that always evaluate to true */ - Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true; - - /** - * Replaces user prefs data with the data in {@code userPrefs}. - */ - void setUserPrefs(ReadOnlyUserPrefs userPrefs); - - /** - * Returns the user prefs. - */ - ReadOnlyUserPrefs getUserPrefs(); - - /** - * Returns the user prefs' GUI settings. - */ - GuiSettings getGuiSettings(); - - /** - * Sets the user prefs' GUI settings. - */ - void setGuiSettings(GuiSettings guiSettings); - - /** - * Returns the user prefs' address book file path. - */ - Path getAddressBookFilePath(); - - /** - * Sets the user prefs' address book file path. - */ - void setAddressBookFilePath(Path addressBookFilePath); - - /** - * Replaces address book data with the data in {@code addressBook}. - */ - void setAddressBook(ReadOnlyAddressBook addressBook); - - /** Returns the AddressBook */ - ReadOnlyAddressBook getAddressBook(); - - /** - * Returns true if a person with the same identity as {@code person} exists in the address book. - */ - boolean hasPerson(Person person); - - /** - * Deletes the given person. - * The person must exist in the address book. - */ - void deletePerson(Person target); - - /** - * Adds the given person. - * {@code person} must not already exist in the address book. - */ - void addPerson(Person person); - - /** - * Replaces the given person {@code target} with {@code editedPerson}. - * {@code target} must exist in the address book. - * The person identity of {@code editedPerson} must not be the same as another existing person in the address book. - */ - void setPerson(Person target, Person editedPerson); - - /** Returns an unmodifiable view of the filtered person list */ - ObservableList getFilteredPersonList(); - - /** - * Updates the filter of the filtered person list to filter by the given {@code predicate}. - * @throws NullPointerException if {@code predicate} is null. - */ - void updateFilteredPersonList(Predicate predicate); -} diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java deleted file mode 100644 index 0650c954f5c..00000000000 --- a/src/main/java/seedu/address/model/ModelManager.java +++ /dev/null @@ -1,151 +0,0 @@ -package seedu.address.model; - -import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; - -import java.nio.file.Path; -import java.util.function.Predicate; -import java.util.logging.Logger; - -import javafx.collections.ObservableList; -import javafx.collections.transformation.FilteredList; -import seedu.address.commons.core.GuiSettings; -import seedu.address.commons.core.LogsCenter; -import seedu.address.model.person.Person; - -/** - * Represents the in-memory model of the address book data. - */ -public class ModelManager implements Model { - private static final Logger logger = LogsCenter.getLogger(ModelManager.class); - - private final AddressBook addressBook; - private final UserPrefs userPrefs; - private final FilteredList filteredPersons; - - /** - * Initializes a ModelManager with the given addressBook and userPrefs. - */ - public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs) { - super(); - requireAllNonNull(addressBook, userPrefs); - - logger.fine("Initializing with address book: " + addressBook + " and user prefs " + userPrefs); - - this.addressBook = new AddressBook(addressBook); - this.userPrefs = new UserPrefs(userPrefs); - filteredPersons = new FilteredList<>(this.addressBook.getPersonList()); - } - - public ModelManager() { - this(new AddressBook(), new UserPrefs()); - } - - //=========== UserPrefs ================================================================================== - - @Override - public void setUserPrefs(ReadOnlyUserPrefs userPrefs) { - requireNonNull(userPrefs); - this.userPrefs.resetData(userPrefs); - } - - @Override - public ReadOnlyUserPrefs getUserPrefs() { - return userPrefs; - } - - @Override - public GuiSettings getGuiSettings() { - return userPrefs.getGuiSettings(); - } - - @Override - public void setGuiSettings(GuiSettings guiSettings) { - requireNonNull(guiSettings); - userPrefs.setGuiSettings(guiSettings); - } - - @Override - public Path getAddressBookFilePath() { - return userPrefs.getAddressBookFilePath(); - } - - @Override - public void setAddressBookFilePath(Path addressBookFilePath) { - requireNonNull(addressBookFilePath); - userPrefs.setAddressBookFilePath(addressBookFilePath); - } - - //=========== AddressBook ================================================================================ - - @Override - public void setAddressBook(ReadOnlyAddressBook addressBook) { - this.addressBook.resetData(addressBook); - } - - @Override - public ReadOnlyAddressBook getAddressBook() { - return addressBook; - } - - @Override - public boolean hasPerson(Person person) { - requireNonNull(person); - return addressBook.hasPerson(person); - } - - @Override - public void deletePerson(Person target) { - addressBook.removePerson(target); - } - - @Override - public void addPerson(Person person) { - addressBook.addPerson(person); - updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); - } - - @Override - public void setPerson(Person target, Person editedPerson) { - requireAllNonNull(target, editedPerson); - - addressBook.setPerson(target, editedPerson); - } - - //=========== Filtered Person List Accessors ============================================================= - - /** - * Returns an unmodifiable view of the list of {@code Person} backed by the internal list of - * {@code versionedAddressBook} - */ - @Override - public ObservableList getFilteredPersonList() { - return filteredPersons; - } - - @Override - public void updateFilteredPersonList(Predicate predicate) { - requireNonNull(predicate); - filteredPersons.setPredicate(predicate); - } - - @Override - public boolean equals(Object obj) { - // short circuit if same object - if (obj == this) { - return true; - } - - // instanceof handles nulls - if (!(obj instanceof ModelManager)) { - return false; - } - - // state check - ModelManager other = (ModelManager) obj; - return addressBook.equals(other.addressBook) - && userPrefs.equals(other.userPrefs) - && filteredPersons.equals(other.filteredPersons); - } - -} diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java deleted file mode 100644 index 6ddc2cd9a29..00000000000 --- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java +++ /dev/null @@ -1,17 +0,0 @@ -package seedu.address.model; - -import javafx.collections.ObservableList; -import seedu.address.model.person.Person; - -/** - * Unmodifiable view of an address book - */ -public interface ReadOnlyAddressBook { - - /** - * Returns an unmodifiable view of the persons list. - * This list will not contain any duplicate persons. - */ - ObservableList getPersonList(); - -} diff --git a/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java b/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java deleted file mode 100644 index befd58a4c73..00000000000 --- a/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java +++ /dev/null @@ -1,16 +0,0 @@ -package seedu.address.model; - -import java.nio.file.Path; - -import seedu.address.commons.core.GuiSettings; - -/** - * Unmodifiable view of user prefs. - */ -public interface ReadOnlyUserPrefs { - - GuiSettings getGuiSettings(); - - Path getAddressBookFilePath(); - -} diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/seedu/address/model/UserPrefs.java deleted file mode 100644 index 25a5fd6eab9..00000000000 --- a/src/main/java/seedu/address/model/UserPrefs.java +++ /dev/null @@ -1,87 +0,0 @@ -package seedu.address.model; - -import static java.util.Objects.requireNonNull; - -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Objects; - -import seedu.address.commons.core.GuiSettings; - -/** - * Represents User's preferences. - */ -public class UserPrefs implements ReadOnlyUserPrefs { - - private GuiSettings guiSettings = new GuiSettings(); - private Path addressBookFilePath = Paths.get("data" , "addressbook.json"); - - /** - * Creates a {@code UserPrefs} with default values. - */ - public UserPrefs() {} - - /** - * Creates a {@code UserPrefs} with the prefs in {@code userPrefs}. - */ - public UserPrefs(ReadOnlyUserPrefs userPrefs) { - this(); - resetData(userPrefs); - } - - /** - * Resets the existing data of this {@code UserPrefs} with {@code newUserPrefs}. - */ - public void resetData(ReadOnlyUserPrefs newUserPrefs) { - requireNonNull(newUserPrefs); - setGuiSettings(newUserPrefs.getGuiSettings()); - setAddressBookFilePath(newUserPrefs.getAddressBookFilePath()); - } - - public GuiSettings getGuiSettings() { - return guiSettings; - } - - public void setGuiSettings(GuiSettings guiSettings) { - requireNonNull(guiSettings); - this.guiSettings = guiSettings; - } - - public Path getAddressBookFilePath() { - return addressBookFilePath; - } - - public void setAddressBookFilePath(Path addressBookFilePath) { - requireNonNull(addressBookFilePath); - this.addressBookFilePath = addressBookFilePath; - } - - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } - if (!(other instanceof UserPrefs)) { //this handles null as well. - return false; - } - - UserPrefs o = (UserPrefs) other; - - return guiSettings.equals(o.guiSettings) - && addressBookFilePath.equals(o.addressBookFilePath); - } - - @Override - public int hashCode() { - return Objects.hash(guiSettings, addressBookFilePath); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("Gui Settings : " + guiSettings); - sb.append("\nLocal data file location : " + addressBookFilePath); - return sb.toString(); - } - -} diff --git a/src/main/java/seedu/address/model/bluetooth/BluetoothPings.java b/src/main/java/seedu/address/model/bluetooth/BluetoothPings.java new file mode 100644 index 00000000000..f74b5d301f7 --- /dev/null +++ b/src/main/java/seedu/address/model/bluetooth/BluetoothPings.java @@ -0,0 +1,21 @@ +package seedu.address.model.bluetooth; + +import java.util.List; + +public class BluetoothPings { + private Long epochTs; + private List userIDs; + + public BluetoothPings(Long epochTs, List userPairs) { + this.epochTs = epochTs; + this.userIDs = userPairs; + } + + public List getUserIDs() { + return this.userIDs; + } + + public Long getEpochTs() { + return this.epochTs; + } +} diff --git a/src/main/java/seedu/address/model/bluetooth/BluetoothPingsSummary.java b/src/main/java/seedu/address/model/bluetooth/BluetoothPingsSummary.java new file mode 100644 index 00000000000..580b8d0f365 --- /dev/null +++ b/src/main/java/seedu/address/model/bluetooth/BluetoothPingsSummary.java @@ -0,0 +1,21 @@ +package seedu.address.model.bluetooth; + +import java.util.List; + +public class BluetoothPingsSummary { + private List userIDs; + private Long counts; + + public BluetoothPingsSummary(List userPairs, Long counts) { + this.userIDs = userPairs; + this.counts = counts; + } + + public List getUserIDs() { + return this.userIDs; + } + + public Long getCounts() { + return this.counts; + } +} diff --git a/src/main/java/seedu/address/model/bluetooth/Person.java b/src/main/java/seedu/address/model/bluetooth/Person.java new file mode 100644 index 00000000000..c1f949935a5 --- /dev/null +++ b/src/main/java/seedu/address/model/bluetooth/Person.java @@ -0,0 +1,25 @@ +package seedu.address.model.bluetooth; + +public class Person { + private String name; + private int age; + private int userID; + + public Person(String name, int age, int userID) { + this.name = name; + this.age = age; + this.userID = userID; + } + + public String getName() { + return this.name; + } + + public int getAge() { + return this.age; + } + + public int getUserID() { + return this.userID; + } +} diff --git a/src/main/java/seedu/address/model/bluetooth/Timestamps.java b/src/main/java/seedu/address/model/bluetooth/Timestamps.java new file mode 100644 index 00000000000..33f35eb794e --- /dev/null +++ b/src/main/java/seedu/address/model/bluetooth/Timestamps.java @@ -0,0 +1,60 @@ +package seedu.address.model.bluetooth; + +import seedu.address.model.bluetooth.formatter.DateFormatterInterface; +import seedu.address.model.bluetooth.formatter.SimpleDateFormatter; + +public class Timestamps { + private Long timestamp; + private DateFormatterInterface formatter; + + /** + * Creates a timestamp class initialized to an epoch timing + * Epoch timings are chosen by default and conversion to other timings / strings will use this value as ground truth + * + * @param epochTs Timestamp in unix epoch format + */ + public Timestamps(Long epochTs) { + this.timestamp = epochTs; + this.formatter = new SimpleDateFormatter(); + } + + /** + * Defines if the given timestamp is greater or equal to a relative value + * + * @param epochStart Lower limit value + * @return Is this timestamp greater or equal to the lower limit? + */ + public Boolean isGreaterOrEq(int epochStart) { + return this.timestamp >= epochStart; + } + + /** + * Defines if the given timestamp is smaller or equal to a relative value + * + * @param epochEnd Upper limit value + * @return Is this timestamp smaller or equal than the upper limit? + */ + public Boolean isSmallerOrEq(int epochEnd) { + return this.timestamp <= epochEnd; + } + + /** + * Defines if the given timestamp is within a bounded window of timing + * + * @param epochStart Start of the window + * @param epochEnd End of the window + * @return Is this timestamp bounded within the window? + */ + public Boolean isBound(int epochStart, int epochEnd){ + return this.isGreaterOrEq(epochStart) && this.isSmallerOrEq(epochEnd); + } + + /** + * Makes the timestamp nice looking cause people hate numbers + * + * @return Formatted timestamp string + */ + public String display() { + return this.formatter.format(this.timestamp); + } +} diff --git a/src/main/java/seedu/address/model/bluetooth/formatter/DateFormatterInterface.java b/src/main/java/seedu/address/model/bluetooth/formatter/DateFormatterInterface.java new file mode 100644 index 00000000000..6d9e2395bce --- /dev/null +++ b/src/main/java/seedu/address/model/bluetooth/formatter/DateFormatterInterface.java @@ -0,0 +1,5 @@ +package seedu.address.model.bluetooth.formatter; + +public interface DateFormatterInterface { + public String format(long epochTs); +} diff --git a/src/main/java/seedu/address/model/bluetooth/formatter/SimpleDateFormatter.java b/src/main/java/seedu/address/model/bluetooth/formatter/SimpleDateFormatter.java new file mode 100644 index 00000000000..5b7b4d34dde --- /dev/null +++ b/src/main/java/seedu/address/model/bluetooth/formatter/SimpleDateFormatter.java @@ -0,0 +1,16 @@ +package seedu.address.model.bluetooth.formatter; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +public class SimpleDateFormatter implements DateFormatterInterface { + @Override + public String format(long epochTs) { + Date date = new Date(epochTs); + SimpleDateFormat format = new SimpleDateFormat("dd/MM/yy", Locale.US); // IDK what I'm doing here. All I know is that I am converting the epoch timestamp to some timezone. + format.setTimeZone(TimeZone.getTimeZone("UTC")); + return format.format(date); + } +} diff --git a/src/main/java/seedu/address/model/person/Address.java b/src/main/java/seedu/address/model/person/Address.java deleted file mode 100644 index 60472ca22a0..00000000000 --- a/src/main/java/seedu/address/model/person/Address.java +++ /dev/null @@ -1,57 +0,0 @@ -package seedu.address.model.person; - -import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; - -/** - * Represents a Person's address in the address book. - * Guarantees: immutable; is valid as declared in {@link #isValidAddress(String)} - */ -public class Address { - - public static final String MESSAGE_CONSTRAINTS = "Addresses can take any values, and it should not be blank"; - - /* - * The first character of the address must not be a whitespace, - * otherwise " " (a blank string) becomes a valid input. - */ - public static final String VALIDATION_REGEX = "[^\\s].*"; - - public final String value; - - /** - * Constructs an {@code Address}. - * - * @param address A valid address. - */ - public Address(String address) { - requireNonNull(address); - checkArgument(isValidAddress(address), MESSAGE_CONSTRAINTS); - value = address; - } - - /** - * Returns true if a given string is a valid email. - */ - public static boolean isValidAddress(String test) { - return test.matches(VALIDATION_REGEX); - } - - @Override - public String toString() { - return value; - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof Address // instanceof handles nulls - && value.equals(((Address) other).value)); // state check - } - - @Override - public int hashCode() { - return value.hashCode(); - } - -} diff --git a/src/main/java/seedu/address/model/person/Email.java b/src/main/java/seedu/address/model/person/Email.java deleted file mode 100644 index a5bbe0b6a5f..00000000000 --- a/src/main/java/seedu/address/model/person/Email.java +++ /dev/null @@ -1,67 +0,0 @@ -package seedu.address.model.person; - -import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; - -/** - * Represents a Person's email in the address book. - * Guarantees: immutable; is valid as declared in {@link #isValidEmail(String)} - */ -public class Email { - - private static final String SPECIAL_CHARACTERS = "!#$%&'*+/=?`{|}~^.-"; - public static final String MESSAGE_CONSTRAINTS = "Emails should be of the format local-part@domain " - + "and adhere to the following constraints:\n" - + "1. The local-part should only contain alphanumeric characters and these special characters, excluding " - + "the parentheses, (" + SPECIAL_CHARACTERS + ") .\n" - + "2. This is followed by a '@' and then a domain name. " - + "The domain name must:\n" - + " - be at least 2 characters long\n" - + " - start and end with alphanumeric characters\n" - + " - consist of alphanumeric characters, a period or a hyphen for the characters in between, if any."; - // alphanumeric and special characters - private static final String LOCAL_PART_REGEX = "^[\\w" + SPECIAL_CHARACTERS + "]+"; - private static final String DOMAIN_FIRST_CHARACTER_REGEX = "[^\\W_]"; // alphanumeric characters except underscore - private static final String DOMAIN_MIDDLE_REGEX = "[a-zA-Z0-9.-]*"; // alphanumeric, period and hyphen - private static final String DOMAIN_LAST_CHARACTER_REGEX = "[^\\W_]$"; - public static final String VALIDATION_REGEX = LOCAL_PART_REGEX + "@" - + DOMAIN_FIRST_CHARACTER_REGEX + DOMAIN_MIDDLE_REGEX + DOMAIN_LAST_CHARACTER_REGEX; - - public final String value; - - /** - * Constructs an {@code Email}. - * - * @param email A valid email address. - */ - public Email(String email) { - requireNonNull(email); - checkArgument(isValidEmail(email), MESSAGE_CONSTRAINTS); - value = email; - } - - /** - * Returns if a given string is a valid email. - */ - public static boolean isValidEmail(String test) { - return test.matches(VALIDATION_REGEX); - } - - @Override - public String toString() { - return value; - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof Email // instanceof handles nulls - && value.equals(((Email) other).value)); // state check - } - - @Override - public int hashCode() { - return value.hashCode(); - } - -} diff --git a/src/main/java/seedu/address/model/person/Name.java b/src/main/java/seedu/address/model/person/Name.java deleted file mode 100644 index 79244d71cf7..00000000000 --- a/src/main/java/seedu/address/model/person/Name.java +++ /dev/null @@ -1,59 +0,0 @@ -package seedu.address.model.person; - -import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; - -/** - * Represents a Person's name in the address book. - * Guarantees: immutable; is valid as declared in {@link #isValidName(String)} - */ -public class Name { - - public static final String MESSAGE_CONSTRAINTS = - "Names should only contain alphanumeric characters and spaces, and it should not be blank"; - - /* - * The first character of the address must not be a whitespace, - * otherwise " " (a blank string) becomes a valid input. - */ - public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*"; - - public final String fullName; - - /** - * Constructs a {@code Name}. - * - * @param name A valid name. - */ - public Name(String name) { - requireNonNull(name); - checkArgument(isValidName(name), MESSAGE_CONSTRAINTS); - fullName = name; - } - - /** - * Returns true if a given string is a valid name. - */ - public static boolean isValidName(String test) { - return test.matches(VALIDATION_REGEX); - } - - - @Override - public String toString() { - return fullName; - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof Name // instanceof handles nulls - && fullName.equals(((Name) other).fullName)); // state check - } - - @Override - public int hashCode() { - return fullName.hashCode(); - } - -} diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java deleted file mode 100644 index c9b5868427c..00000000000 --- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java +++ /dev/null @@ -1,31 +0,0 @@ -package seedu.address.model.person; - -import java.util.List; -import java.util.function.Predicate; - -import seedu.address.commons.util.StringUtil; - -/** - * Tests that a {@code Person}'s {@code Name} matches any of the keywords given. - */ -public class NameContainsKeywordsPredicate implements Predicate { - private final List keywords; - - public NameContainsKeywordsPredicate(List keywords) { - this.keywords = keywords; - } - - @Override - public boolean test(Person person) { - return keywords.stream() - .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getName().fullName, keyword)); - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof NameContainsKeywordsPredicate // instanceof handles nulls - && keywords.equals(((NameContainsKeywordsPredicate) other).keywords)); // state check - } - -} diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java deleted file mode 100644 index 557a7a60cd5..00000000000 --- a/src/main/java/seedu/address/model/person/Person.java +++ /dev/null @@ -1,120 +0,0 @@ -package seedu.address.model.person; - -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -import seedu.address.model.tag.Tag; - -/** - * Represents a Person in the address book. - * Guarantees: details are present and not null, field values are validated, immutable. - */ -public class Person { - - // Identity fields - private final Name name; - private final Phone phone; - private final Email email; - - // Data fields - private final Address address; - private final Set tags = new HashSet<>(); - - /** - * Every field must be present and not null. - */ - public Person(Name name, Phone phone, Email email, Address address, Set tags) { - requireAllNonNull(name, phone, email, address, tags); - this.name = name; - this.phone = phone; - this.email = email; - this.address = address; - this.tags.addAll(tags); - } - - public Name getName() { - return name; - } - - public Phone getPhone() { - return phone; - } - - public Email getEmail() { - return email; - } - - public Address getAddress() { - return address; - } - - /** - * Returns an immutable tag set, which throws {@code UnsupportedOperationException} - * if modification is attempted. - */ - public Set getTags() { - return Collections.unmodifiableSet(tags); - } - - /** - * Returns true if both persons of the same name have at least one other identity field that is the same. - * This defines a weaker notion of equality between two persons. - */ - public boolean isSamePerson(Person otherPerson) { - if (otherPerson == this) { - return true; - } - - return otherPerson != null - && otherPerson.getName().equals(getName()) - && (otherPerson.getPhone().equals(getPhone()) || otherPerson.getEmail().equals(getEmail())); - } - - /** - * Returns true if both persons have the same identity and data fields. - * This defines a stronger notion of equality between two persons. - */ - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } - - if (!(other instanceof Person)) { - return false; - } - - Person otherPerson = (Person) other; - return otherPerson.getName().equals(getName()) - && otherPerson.getPhone().equals(getPhone()) - && otherPerson.getEmail().equals(getEmail()) - && otherPerson.getAddress().equals(getAddress()) - && otherPerson.getTags().equals(getTags()); - } - - @Override - public int hashCode() { - // use this method for custom fields hashing instead of implementing your own - return Objects.hash(name, phone, email, address, tags); - } - - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - builder.append(getName()) - .append(" Phone: ") - .append(getPhone()) - .append(" Email: ") - .append(getEmail()) - .append(" Address: ") - .append(getAddress()) - .append(" Tags: "); - getTags().forEach(builder::append); - return builder.toString(); - } - -} diff --git a/src/main/java/seedu/address/model/person/Phone.java b/src/main/java/seedu/address/model/person/Phone.java deleted file mode 100644 index 872c76b382f..00000000000 --- a/src/main/java/seedu/address/model/person/Phone.java +++ /dev/null @@ -1,53 +0,0 @@ -package seedu.address.model.person; - -import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; - -/** - * Represents a Person's phone number in the address book. - * Guarantees: immutable; is valid as declared in {@link #isValidPhone(String)} - */ -public class Phone { - - - public static final String MESSAGE_CONSTRAINTS = - "Phone numbers should only contain numbers, and it should be at least 3 digits long"; - public static final String VALIDATION_REGEX = "\\d{3,}"; - public final String value; - - /** - * Constructs a {@code Phone}. - * - * @param phone A valid phone number. - */ - public Phone(String phone) { - requireNonNull(phone); - checkArgument(isValidPhone(phone), MESSAGE_CONSTRAINTS); - value = phone; - } - - /** - * Returns true if a given string is a valid phone number. - */ - public static boolean isValidPhone(String test) { - return test.matches(VALIDATION_REGEX); - } - - @Override - public String toString() { - return value; - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof Phone // instanceof handles nulls - && value.equals(((Phone) other).value)); // state check - } - - @Override - public int hashCode() { - return value.hashCode(); - } - -} diff --git a/src/main/java/seedu/address/model/person/UniquePersonList.java b/src/main/java/seedu/address/model/person/UniquePersonList.java deleted file mode 100644 index 0fee4fe57e6..00000000000 --- a/src/main/java/seedu/address/model/person/UniquePersonList.java +++ /dev/null @@ -1,137 +0,0 @@ -package seedu.address.model.person; - -import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; - -import java.util.Iterator; -import java.util.List; - -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import seedu.address.model.person.exceptions.DuplicatePersonException; -import seedu.address.model.person.exceptions.PersonNotFoundException; - -/** - * A list of persons that enforces uniqueness between its elements and does not allow nulls. - * A person is considered unique by comparing using {@code Person#isSamePerson(Person)}. As such, adding and updating of - * persons uses Person#isSamePerson(Person) for equality so as to ensure that the person being added or updated is - * unique in terms of identity in the UniquePersonList. However, the removal of a person uses Person#equals(Object) so - * as to ensure that the person with exactly the same fields will be removed. - * - * Supports a minimal set of list operations. - * - * @see Person#isSamePerson(Person) - */ -public class UniquePersonList implements Iterable { - - private final ObservableList internalList = FXCollections.observableArrayList(); - private final ObservableList internalUnmodifiableList = - FXCollections.unmodifiableObservableList(internalList); - - /** - * Returns true if the list contains an equivalent person as the given argument. - */ - public boolean contains(Person toCheck) { - requireNonNull(toCheck); - return internalList.stream().anyMatch(toCheck::isSamePerson); - } - - /** - * Adds a person to the list. - * The person must not already exist in the list. - */ - public void add(Person toAdd) { - requireNonNull(toAdd); - if (contains(toAdd)) { - throw new DuplicatePersonException(); - } - internalList.add(toAdd); - } - - /** - * Replaces the person {@code target} in the list with {@code editedPerson}. - * {@code target} must exist in the list. - * The person identity of {@code editedPerson} must not be the same as another existing person in the list. - */ - public void setPerson(Person target, Person editedPerson) { - requireAllNonNull(target, editedPerson); - - int index = internalList.indexOf(target); - if (index == -1) { - throw new PersonNotFoundException(); - } - - if (!target.isSamePerson(editedPerson) && contains(editedPerson)) { - throw new DuplicatePersonException(); - } - - internalList.set(index, editedPerson); - } - - /** - * Removes the equivalent person from the list. - * The person must exist in the list. - */ - public void remove(Person toRemove) { - requireNonNull(toRemove); - if (!internalList.remove(toRemove)) { - throw new PersonNotFoundException(); - } - } - - public void setPersons(UniquePersonList replacement) { - requireNonNull(replacement); - internalList.setAll(replacement.internalList); - } - - /** - * Replaces the contents of this list with {@code persons}. - * {@code persons} must not contain duplicate persons. - */ - public void setPersons(List persons) { - requireAllNonNull(persons); - if (!personsAreUnique(persons)) { - throw new DuplicatePersonException(); - } - - internalList.setAll(persons); - } - - /** - * Returns the backing list as an unmodifiable {@code ObservableList}. - */ - public ObservableList asUnmodifiableObservableList() { - return internalUnmodifiableList; - } - - @Override - public Iterator iterator() { - return internalList.iterator(); - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof UniquePersonList // instanceof handles nulls - && internalList.equals(((UniquePersonList) other).internalList)); - } - - @Override - public int hashCode() { - return internalList.hashCode(); - } - - /** - * Returns true if {@code persons} contains only unique persons. - */ - private boolean personsAreUnique(List persons) { - for (int i = 0; i < persons.size() - 1; i++) { - for (int j = i + 1; j < persons.size(); j++) { - if (persons.get(i).isSamePerson(persons.get(j))) { - return false; - } - } - } - return true; - } -} diff --git a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java b/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java deleted file mode 100644 index d7290f59442..00000000000 --- a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java +++ /dev/null @@ -1,11 +0,0 @@ -package seedu.address.model.person.exceptions; - -/** - * Signals that the operation will result in duplicate Persons (Persons are considered duplicates if they have the same - * identity). - */ -public class DuplicatePersonException extends RuntimeException { - public DuplicatePersonException() { - super("Operation would result in duplicate persons"); - } -} diff --git a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java b/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java deleted file mode 100644 index fa764426ca7..00000000000 --- a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java +++ /dev/null @@ -1,6 +0,0 @@ -package seedu.address.model.person.exceptions; - -/** - * Signals that the operation is unable to find the specified person. - */ -public class PersonNotFoundException extends RuntimeException {} diff --git a/src/main/java/seedu/address/model/tag/Tag.java b/src/main/java/seedu/address/model/tag/Tag.java deleted file mode 100644 index b0ea7e7dad7..00000000000 --- a/src/main/java/seedu/address/model/tag/Tag.java +++ /dev/null @@ -1,54 +0,0 @@ -package seedu.address.model.tag; - -import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; - -/** - * Represents a Tag in the address book. - * Guarantees: immutable; name is valid as declared in {@link #isValidTagName(String)} - */ -public class Tag { - - public static final String MESSAGE_CONSTRAINTS = "Tags names should be alphanumeric"; - public static final String VALIDATION_REGEX = "\\p{Alnum}+"; - - public final String tagName; - - /** - * Constructs a {@code Tag}. - * - * @param tagName A valid tag name. - */ - public Tag(String tagName) { - requireNonNull(tagName); - checkArgument(isValidTagName(tagName), MESSAGE_CONSTRAINTS); - this.tagName = tagName; - } - - /** - * Returns true if a given string is a valid tag name. - */ - public static boolean isValidTagName(String test) { - return test.matches(VALIDATION_REGEX); - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof Tag // instanceof handles nulls - && tagName.equals(((Tag) other).tagName)); // state check - } - - @Override - public int hashCode() { - return tagName.hashCode(); - } - - /** - * Format state as text for viewing. - */ - public String toString() { - return '[' + tagName + ']'; - } - -} diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java deleted file mode 100644 index 1806da4facf..00000000000 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ /dev/null @@ -1,60 +0,0 @@ -package seedu.address.model.util; - -import java.util.Arrays; -import java.util.Set; -import java.util.stream.Collectors; - -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; - -/** - * Contains utility methods for populating {@code AddressBook} with sample data. - */ -public class SampleDataUtil { - public static Person[] getSamplePersons() { - return new Person[] { - new Person(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"), - new Address("Blk 30 Geylang Street 29, #06-40"), - getTagSet("friends")), - new Person(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"), - new Address("Blk 30 Lorong 3 Serangoon Gardens, #07-18"), - getTagSet("colleagues", "friends")), - new Person(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"), - new Address("Blk 11 Ang Mo Kio Street 74, #11-04"), - getTagSet("neighbours")), - new Person(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"), - new Address("Blk 436 Serangoon Gardens Street 26, #16-43"), - getTagSet("family")), - new Person(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"), - new Address("Blk 47 Tampines Street 20, #17-35"), - getTagSet("classmates")), - new Person(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"), - new Address("Blk 45 Aljunied Street 85, #11-31"), - getTagSet("colleagues")) - }; - } - - public static ReadOnlyAddressBook getSampleAddressBook() { - AddressBook sampleAb = new AddressBook(); - for (Person samplePerson : getSamplePersons()) { - sampleAb.addPerson(samplePerson); - } - return sampleAb; - } - - /** - * Returns a tag set containing the list of strings given. - */ - public static Set getTagSet(String... strings) { - return Arrays.stream(strings) - .map(Tag::new) - .collect(Collectors.toSet()); - } - -} diff --git a/src/main/java/seedu/address/report_generator/report_generator.java b/src/main/java/seedu/address/report_generator/report_generator.java new file mode 100644 index 00000000000..74f8fc73e5d --- /dev/null +++ b/src/main/java/seedu/address/report_generator/report_generator.java @@ -0,0 +1,90 @@ +package seedu.address.report_generator; + +import com.itextpdf.kernel.font.PdfFont; +import com.itextpdf.kernel.font.PdfFontFactory; +import com.itextpdf.kernel.geom.PageSize; +import com.itextpdf.kernel.pdf.PdfDocument; +import com.itextpdf.kernel.pdf.PdfWriter; +import com.itextpdf.layout.Document; +import com.itextpdf.layout.element.Paragraph; +import com.itextpdf.layout.element.Table; +import seedu.address.model.bluetooth.BluetoothPings; +import com.itextpdf.kernel.pdf.canvas.PdfCanvas; + + + +import java.io.File; +import java.io.IOException; +import java.util.*; + +public class report_generator { + public static final String DEST = "results/report.pdf"; + + public void GenerateReport(ArrayList resp) throws IOException + { + File file = new File(DEST); + file.getParentFile().mkdirs(); + new report_generator().createPdf(DEST, resp); + } + + public void createPdf(String dest, ArrayList resp) throws IOException + { + System.out.println("Creating PDF file"); + PdfWriter writer = new PdfWriter(dest); + + + PdfDocument pdf = new PdfDocument(writer); + + + Document document = new Document(pdf, PageSize.A4.rotate()); + + document.setMargins(20, 20, 20, 20); + + + float [] pointColumnWidths = {150F, 150F, 150F}; + + Table table = new Table(pointColumnWidths); + + + table.addCell("Time"); + table.addCell("ID1"); + table.addCell("ID2"); + + + System.out.println("Start inserting data"); + Set ID_set = new HashSet(); + + for(int i = 0; i < resp.size(); i++) + { + BluetoothPings instance = resp.get(i); + table.addCell(instance.getEpochTs()+""); + List epochTimes = instance.getUserIDs(); + table.addCell(epochTimes.get(0) + ""); + ID_set.add(epochTimes.get(0)+""); + table.addCell(epochTimes.get(1) + ""); + ID_set.add(epochTimes.get(1)+""); + } + + document.add(new Paragraph("CONTACT TRACING REPORT")); + document.add(new Paragraph("----------------------------------------------")); + Paragraph paragraph = new Paragraph("The total number of instances in this report is: " + resp.size()); + + document.add(paragraph); + + String text_string = "The ID included in this file are:"; + Iterator it = ID_set.iterator(); + while (it.hasNext()) + { + text_string = text_string + " " + it.next(); + } + + document.add(new Paragraph((text_string))); + document.add(new Paragraph("----------------------------------------------")); + + + document.add(table); + document.close(); + + } + +} diff --git a/src/main/java/seedu/address/router/UiRouter.java b/src/main/java/seedu/address/router/UiRouter.java new file mode 100644 index 00000000000..199fcdc869b --- /dev/null +++ b/src/main/java/seedu/address/router/UiRouter.java @@ -0,0 +1,11 @@ +package seedu.address.router; + +import javafx.stage.Stage; +import seedu.address.ui.Ui; + +public class UiRouter implements Ui { + @Override + public void start(Stage primaryStage) { + + } +} diff --git a/src/main/java/seedu/address/storage/AddressBookStorage.java b/src/main/java/seedu/address/storage/AddressBookStorage.java deleted file mode 100644 index 4599182b3f9..00000000000 --- a/src/main/java/seedu/address/storage/AddressBookStorage.java +++ /dev/null @@ -1,45 +0,0 @@ -package seedu.address.storage; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.Optional; - -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.ReadOnlyAddressBook; - -/** - * Represents a storage for {@link seedu.address.model.AddressBook}. - */ -public interface AddressBookStorage { - - /** - * Returns the file path of the data file. - */ - Path getAddressBookFilePath(); - - /** - * Returns AddressBook data as a {@link ReadOnlyAddressBook}. - * Returns {@code Optional.empty()} if storage file is not found. - * @throws DataConversionException if the data in storage is not in the expected format. - * @throws IOException if there was any problem when reading from the storage. - */ - Optional readAddressBook() throws DataConversionException, IOException; - - /** - * @see #getAddressBookFilePath() - */ - Optional readAddressBook(Path filePath) throws DataConversionException, IOException; - - /** - * Saves the given {@link ReadOnlyAddressBook} to the storage. - * @param addressBook cannot be null. - * @throws IOException if there was any problem writing to the file. - */ - void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException; - - /** - * @see #saveAddressBook(ReadOnlyAddressBook) - */ - void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException; - -} diff --git a/src/main/java/seedu/address/storage/AppStorage.java b/src/main/java/seedu/address/storage/AppStorage.java new file mode 100644 index 00000000000..6c2b2852ba2 --- /dev/null +++ b/src/main/java/seedu/address/storage/AppStorage.java @@ -0,0 +1,34 @@ +package seedu.address.storage; + +import seedu.address.logic.aggregators.Aggregators; +import seedu.address.logic.conditions.Conditions; + +import java.util.ArrayList; + +public interface AppStorage { + + public void create(T templateClass); + + public void delete(T templateClass); + + public void update(T oldTemplateClass, T newTemplateClass); + + /** + * Performs an aggregated search over records passed in to identify groups of records which satisfies a condition + * @param cond {@code Condition} interface + * agg Aggregation logic + * + * @return ArrayList Filtered results + */ + public ArrayList search(Conditions cond, Aggregators agg); + + /** + * Given a condition, return all valid objects + * @param cond {@code Condition} interface + * + * @return ArrayList Filtered results + */ + public ArrayList search(Conditions cond); + + public ArrayList search(); +} diff --git a/src/main/java/seedu/address/storage/BluetoothPingsStorage.java b/src/main/java/seedu/address/storage/BluetoothPingsStorage.java new file mode 100644 index 00000000000..fc8663e21ab --- /dev/null +++ b/src/main/java/seedu/address/storage/BluetoothPingsStorage.java @@ -0,0 +1,32 @@ +package seedu.address.storage; + +import seedu.address.model.bluetooth.BluetoothPings; + +import java.util.ArrayList; +import java.util.Arrays; + +public class BluetoothPingsStorage extends InMemoryStorage { + public BluetoothPingsStorage() { + super(); + this.init(); + } + + /** + * TODO: Would be nice if can read from JSON file to initialize fake data + * @return + */ + private ArrayList genFakeData() { + ArrayList fakePings = new ArrayList(); + fakePings.add(new BluetoothPings(15000000L, Arrays.asList(1, 2))); + fakePings.add(new BluetoothPings(15000100L, Arrays.asList(1, 2))); + fakePings.add(new BluetoothPings(15000200L, Arrays.asList(1, 2))); + fakePings.add(new BluetoothPings(15000300L, Arrays.asList(1, 2))); + fakePings.add(new BluetoothPings(15000400L, Arrays.asList(1, 2))); + fakePings.add(new BluetoothPings(15000500L, Arrays.asList(1, 2))); + return fakePings; + } + + public void init() { + this.fakeStorage = this.genFakeData(); + } +} diff --git a/src/main/java/seedu/address/storage/InMemoryStorage.java b/src/main/java/seedu/address/storage/InMemoryStorage.java new file mode 100644 index 00000000000..d5bb88e8003 --- /dev/null +++ b/src/main/java/seedu/address/storage/InMemoryStorage.java @@ -0,0 +1,57 @@ +package seedu.address.storage; + +import seedu.address.logic.aggregators.Aggregators; +import seedu.address.logic.conditions.Conditions; +import seedu.address.logic.conditions.LiterallyNoConditions; + +import java.util.ArrayList; +import java.util.stream.Collectors; + +/** + * Storage is maintained in memory + * All transactions are done via memory + * + * This does not work for large scale data but suffices for this project + * + * @param + */ +public abstract class InMemoryStorage implements AppStorage { + protected ArrayList fakeStorage; + + @Override + public void delete(T templateClass) { + // TODO: Write some code here + } + + @Override + public void create(T templateClass) { + // TODO: Write some code here + } + + @Override + public void update(T oldTemplateClass, T newTemplateClass) { + // TODO: write some code here + } + + @Override + public ArrayList search(Conditions cond, Aggregators agg) { + ArrayList collection = agg.collect(this.fakeStorage); + + return collection.stream() + .filter(each -> cond.satisfies(each)) + .collect(Collectors.toCollection(ArrayList::new)); + } + + @Override + public ArrayList search(Conditions cond) { + return this.fakeStorage.stream() + .filter(each -> cond.satisfies(each)) + .collect(Collectors.toCollection(ArrayList::new)); + } + + @Override + public ArrayList search() { + Conditions cond = new LiterallyNoConditions(); + return this.search(cond); + } +} diff --git a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java b/src/main/java/seedu/address/storage/JsonAdaptedPerson.java deleted file mode 100644 index a6321cec2ea..00000000000 --- a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java +++ /dev/null @@ -1,109 +0,0 @@ -package seedu.address.storage; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; - -/** - * Jackson-friendly version of {@link Person}. - */ -class JsonAdaptedPerson { - - public static final String MISSING_FIELD_MESSAGE_FORMAT = "Person's %s field is missing!"; - - private final String name; - private final String phone; - private final String email; - private final String address; - private final List tagged = new ArrayList<>(); - - /** - * Constructs a {@code JsonAdaptedPerson} with the given person details. - */ - @JsonCreator - public JsonAdaptedPerson(@JsonProperty("name") String name, @JsonProperty("phone") String phone, - @JsonProperty("email") String email, @JsonProperty("address") String address, - @JsonProperty("tagged") List tagged) { - this.name = name; - this.phone = phone; - this.email = email; - this.address = address; - if (tagged != null) { - this.tagged.addAll(tagged); - } - } - - /** - * Converts a given {@code Person} into this class for Jackson use. - */ - public JsonAdaptedPerson(Person source) { - name = source.getName().fullName; - phone = source.getPhone().value; - email = source.getEmail().value; - address = source.getAddress().value; - tagged.addAll(source.getTags().stream() - .map(JsonAdaptedTag::new) - .collect(Collectors.toList())); - } - - /** - * Converts this Jackson-friendly adapted person object into the model's {@code Person} object. - * - * @throws IllegalValueException if there were any data constraints violated in the adapted person. - */ - public Person toModelType() throws IllegalValueException { - final List personTags = new ArrayList<>(); - for (JsonAdaptedTag tag : tagged) { - personTags.add(tag.toModelType()); - } - - if (name == null) { - throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName())); - } - if (!Name.isValidName(name)) { - throw new IllegalValueException(Name.MESSAGE_CONSTRAINTS); - } - final Name modelName = new Name(name); - - if (phone == null) { - throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName())); - } - if (!Phone.isValidPhone(phone)) { - throw new IllegalValueException(Phone.MESSAGE_CONSTRAINTS); - } - final Phone modelPhone = new Phone(phone); - - if (email == null) { - throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName())); - } - if (!Email.isValidEmail(email)) { - throw new IllegalValueException(Email.MESSAGE_CONSTRAINTS); - } - final Email modelEmail = new Email(email); - - if (address == null) { - throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName())); - } - if (!Address.isValidAddress(address)) { - throw new IllegalValueException(Address.MESSAGE_CONSTRAINTS); - } - final Address modelAddress = new Address(address); - - final Set modelTags = new HashSet<>(personTags); - return new Person(modelName, modelPhone, modelEmail, modelAddress, modelTags); - } - -} diff --git a/src/main/java/seedu/address/storage/JsonAdaptedTag.java b/src/main/java/seedu/address/storage/JsonAdaptedTag.java deleted file mode 100644 index 0df22bdb754..00000000000 --- a/src/main/java/seedu/address/storage/JsonAdaptedTag.java +++ /dev/null @@ -1,48 +0,0 @@ -package seedu.address.storage; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; - -import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.model.tag.Tag; - -/** - * Jackson-friendly version of {@link Tag}. - */ -class JsonAdaptedTag { - - private final String tagName; - - /** - * Constructs a {@code JsonAdaptedTag} with the given {@code tagName}. - */ - @JsonCreator - public JsonAdaptedTag(String tagName) { - this.tagName = tagName; - } - - /** - * Converts a given {@code Tag} into this class for Jackson use. - */ - public JsonAdaptedTag(Tag source) { - tagName = source.tagName; - } - - @JsonValue - public String getTagName() { - return tagName; - } - - /** - * Converts this Jackson-friendly adapted tag object into the model's {@code Tag} object. - * - * @throws IllegalValueException if there were any data constraints violated in the adapted tag. - */ - public Tag toModelType() throws IllegalValueException { - if (!Tag.isValidTagName(tagName)) { - throw new IllegalValueException(Tag.MESSAGE_CONSTRAINTS); - } - return new Tag(tagName); - } - -} diff --git a/src/main/java/seedu/address/storage/JsonAddressBookStorage.java b/src/main/java/seedu/address/storage/JsonAddressBookStorage.java deleted file mode 100644 index dfab9daaa0d..00000000000 --- a/src/main/java/seedu/address/storage/JsonAddressBookStorage.java +++ /dev/null @@ -1,80 +0,0 @@ -package seedu.address.storage; - -import static java.util.Objects.requireNonNull; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.Optional; -import java.util.logging.Logger; - -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.commons.util.FileUtil; -import seedu.address.commons.util.JsonUtil; -import seedu.address.model.ReadOnlyAddressBook; - -/** - * A class to access AddressBook data stored as a json file on the hard disk. - */ -public class JsonAddressBookStorage implements AddressBookStorage { - - private static final Logger logger = LogsCenter.getLogger(JsonAddressBookStorage.class); - - private Path filePath; - - public JsonAddressBookStorage(Path filePath) { - this.filePath = filePath; - } - - public Path getAddressBookFilePath() { - return filePath; - } - - @Override - public Optional readAddressBook() throws DataConversionException { - return readAddressBook(filePath); - } - - /** - * Similar to {@link #readAddressBook()}. - * - * @param filePath location of the data. Cannot be null. - * @throws DataConversionException if the file is not in the correct format. - */ - public Optional readAddressBook(Path filePath) throws DataConversionException { - requireNonNull(filePath); - - Optional jsonAddressBook = JsonUtil.readJsonFile( - filePath, JsonSerializableAddressBook.class); - if (!jsonAddressBook.isPresent()) { - return Optional.empty(); - } - - try { - return Optional.of(jsonAddressBook.get().toModelType()); - } catch (IllegalValueException ive) { - logger.info("Illegal values found in " + filePath + ": " + ive.getMessage()); - throw new DataConversionException(ive); - } - } - - @Override - public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException { - saveAddressBook(addressBook, filePath); - } - - /** - * Similar to {@link #saveAddressBook(ReadOnlyAddressBook)}. - * - * @param filePath location of the data. Cannot be null. - */ - public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException { - requireNonNull(addressBook); - requireNonNull(filePath); - - FileUtil.createIfMissing(filePath); - JsonUtil.saveJsonFile(new JsonSerializableAddressBook(addressBook), filePath); - } - -} diff --git a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java deleted file mode 100644 index 5efd834091d..00000000000 --- a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java +++ /dev/null @@ -1,60 +0,0 @@ -package seedu.address.storage; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonRootName; - -import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Person; - -/** - * An Immutable AddressBook that is serializable to JSON format. - */ -@JsonRootName(value = "addressbook") -class JsonSerializableAddressBook { - - public static final String MESSAGE_DUPLICATE_PERSON = "Persons list contains duplicate person(s)."; - - private final List persons = new ArrayList<>(); - - /** - * Constructs a {@code JsonSerializableAddressBook} with the given persons. - */ - @JsonCreator - public JsonSerializableAddressBook(@JsonProperty("persons") List persons) { - this.persons.addAll(persons); - } - - /** - * Converts a given {@code ReadOnlyAddressBook} into this class for Jackson use. - * - * @param source future changes to this will not affect the created {@code JsonSerializableAddressBook}. - */ - public JsonSerializableAddressBook(ReadOnlyAddressBook source) { - persons.addAll(source.getPersonList().stream().map(JsonAdaptedPerson::new).collect(Collectors.toList())); - } - - /** - * Converts this address book into the model's {@code AddressBook} object. - * - * @throws IllegalValueException if there were any data constraints violated. - */ - public AddressBook toModelType() throws IllegalValueException { - AddressBook addressBook = new AddressBook(); - for (JsonAdaptedPerson jsonAdaptedPerson : persons) { - Person person = jsonAdaptedPerson.toModelType(); - if (addressBook.hasPerson(person)) { - throw new IllegalValueException(MESSAGE_DUPLICATE_PERSON); - } - addressBook.addPerson(person); - } - return addressBook; - } - -} diff --git a/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java b/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java deleted file mode 100644 index bc2bbad84aa..00000000000 --- a/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java +++ /dev/null @@ -1,47 +0,0 @@ -package seedu.address.storage; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.Optional; - -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.commons.util.JsonUtil; -import seedu.address.model.ReadOnlyUserPrefs; -import seedu.address.model.UserPrefs; - -/** - * A class to access UserPrefs stored in the hard disk as a json file - */ -public class JsonUserPrefsStorage implements UserPrefsStorage { - - private Path filePath; - - public JsonUserPrefsStorage(Path filePath) { - this.filePath = filePath; - } - - @Override - public Path getUserPrefsFilePath() { - return filePath; - } - - @Override - public Optional readUserPrefs() throws DataConversionException { - return readUserPrefs(filePath); - } - - /** - * Similar to {@link #readUserPrefs()} - * @param prefsFilePath location of the data. Cannot be null. - * @throws DataConversionException if the file format is not as expected. - */ - public Optional readUserPrefs(Path prefsFilePath) throws DataConversionException { - return JsonUtil.readJsonFile(prefsFilePath, UserPrefs.class); - } - - @Override - public void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException { - JsonUtil.saveJsonFile(userPrefs, filePath); - } - -} diff --git a/src/main/java/seedu/address/storage/Storage.java b/src/main/java/seedu/address/storage/Storage.java deleted file mode 100644 index beda8bd9f11..00000000000 --- a/src/main/java/seedu/address/storage/Storage.java +++ /dev/null @@ -1,32 +0,0 @@ -package seedu.address.storage; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.Optional; - -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.ReadOnlyUserPrefs; -import seedu.address.model.UserPrefs; - -/** - * API of the Storage component - */ -public interface Storage extends AddressBookStorage, UserPrefsStorage { - - @Override - Optional readUserPrefs() throws DataConversionException, IOException; - - @Override - void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException; - - @Override - Path getAddressBookFilePath(); - - @Override - Optional readAddressBook() throws DataConversionException, IOException; - - @Override - void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException; - -} diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/seedu/address/storage/StorageManager.java deleted file mode 100644 index e4f452b6cbf..00000000000 --- a/src/main/java/seedu/address/storage/StorageManager.java +++ /dev/null @@ -1,77 +0,0 @@ -package seedu.address.storage; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.Optional; -import java.util.logging.Logger; - -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.ReadOnlyUserPrefs; -import seedu.address.model.UserPrefs; - -/** - * Manages storage of AddressBook data in local storage. - */ -public class StorageManager implements Storage { - - private static final Logger logger = LogsCenter.getLogger(StorageManager.class); - private AddressBookStorage addressBookStorage; - private UserPrefsStorage userPrefsStorage; - - - public StorageManager(AddressBookStorage addressBookStorage, UserPrefsStorage userPrefsStorage) { - super(); - this.addressBookStorage = addressBookStorage; - this.userPrefsStorage = userPrefsStorage; - } - - // ================ UserPrefs methods ============================== - - @Override - public Path getUserPrefsFilePath() { - return userPrefsStorage.getUserPrefsFilePath(); - } - - @Override - public Optional readUserPrefs() throws DataConversionException, IOException { - return userPrefsStorage.readUserPrefs(); - } - - @Override - public void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException { - userPrefsStorage.saveUserPrefs(userPrefs); - } - - - // ================ AddressBook methods ============================== - - @Override - public Path getAddressBookFilePath() { - return addressBookStorage.getAddressBookFilePath(); - } - - @Override - public Optional readAddressBook() throws DataConversionException, IOException { - return readAddressBook(addressBookStorage.getAddressBookFilePath()); - } - - @Override - public Optional readAddressBook(Path filePath) throws DataConversionException, IOException { - logger.fine("Attempting to read data from file: " + filePath); - return addressBookStorage.readAddressBook(filePath); - } - - @Override - public void saveAddressBook(ReadOnlyAddressBook addressBook) throws IOException { - saveAddressBook(addressBook, addressBookStorage.getAddressBookFilePath()); - } - - @Override - public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) throws IOException { - logger.fine("Attempting to write to data file: " + filePath); - addressBookStorage.saveAddressBook(addressBook, filePath); - } - -} diff --git a/src/main/java/seedu/address/storage/UserPrefsStorage.java b/src/main/java/seedu/address/storage/UserPrefsStorage.java deleted file mode 100644 index 29eef178dbc..00000000000 --- a/src/main/java/seedu/address/storage/UserPrefsStorage.java +++ /dev/null @@ -1,36 +0,0 @@ -package seedu.address.storage; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.Optional; - -import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.ReadOnlyUserPrefs; -import seedu.address.model.UserPrefs; - -/** - * Represents a storage for {@link seedu.address.model.UserPrefs}. - */ -public interface UserPrefsStorage { - - /** - * Returns the file path of the UserPrefs data file. - */ - Path getUserPrefsFilePath(); - - /** - * Returns UserPrefs data from storage. - * Returns {@code Optional.empty()} if storage file is not found. - * @throws DataConversionException if the data in storage is not in the expected format. - * @throws IOException if there was any problem when reading from the storage. - */ - Optional readUserPrefs() throws DataConversionException, IOException; - - /** - * Saves the given {@link seedu.address.model.ReadOnlyUserPrefs} to the storage. - * @param userPrefs cannot be null. - * @throws IOException if there was any problem writing to the file. - */ - void saveUserPrefs(ReadOnlyUserPrefs userPrefs) throws IOException; - -} diff --git a/src/main/java/seedu/address/ui/CommandBox.java b/src/main/java/seedu/address/ui/AppCommandBox.java similarity index 68% rename from src/main/java/seedu/address/ui/CommandBox.java rename to src/main/java/seedu/address/ui/AppCommandBox.java index 7d76e691f52..801131b7fed 100644 --- a/src/main/java/seedu/address/ui/CommandBox.java +++ b/src/main/java/seedu/address/ui/AppCommandBox.java @@ -4,24 +4,19 @@ import javafx.fxml.FXML; import javafx.scene.control.TextField; import javafx.scene.layout.Region; -import seedu.address.logic.commands.CommandResult; -import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.logic.messages.AppMessage; import seedu.address.logic.parser.exceptions.ParseException; -/** - * The UI component that is responsible for receiving user command inputs. - */ -public class CommandBox extends UiPart { - +public class AppCommandBox extends UiPart { public static final String ERROR_STYLE_CLASS = "error"; private static final String FXML = "CommandBox.fxml"; - private final CommandExecutor commandExecutor; + private final AppCommandBox.CommandExecutor commandExecutor; - @FXML + @javafx.fxml.FXML private TextField commandTextField; - public CommandBox(CommandExecutor commandExecutor) { + public AppCommandBox(AppCommandBox.CommandExecutor commandExecutor) { super(FXML); this.commandExecutor = commandExecutor; // calls #setStyleToDefault() whenever there is a change to the text of the command box. @@ -32,13 +27,9 @@ public CommandBox(CommandExecutor commandExecutor) { * Handles the Enter button pressed event. */ @FXML - private void handleCommandEntered() { - try { - commandExecutor.execute(commandTextField.getText()); - commandTextField.setText(""); - } catch (CommandException | ParseException e) { - setStyleToIndicateCommandFailure(); - } + private void handleCommandEntered() throws ParseException { + commandExecutor.execute(commandTextField.getText()); + commandTextField.setText(""); } /** @@ -71,7 +62,6 @@ public interface CommandExecutor { * * @see seedu.address.logic.Logic#execute(String) */ - CommandResult execute(String commandText) throws CommandException, ParseException; + AppMessage execute(String commandText) throws ParseException; } - } diff --git a/src/main/java/seedu/address/ui/AppMainWindow.java b/src/main/java/seedu/address/ui/AppMainWindow.java new file mode 100644 index 00000000000..7e13affe91d --- /dev/null +++ b/src/main/java/seedu/address/ui/AppMainWindow.java @@ -0,0 +1,124 @@ +package seedu.address.ui; + +import java.util.logging.Logger; + +import javafx.fxml.FXML; +import javafx.scene.layout.StackPane; +import javafx.stage.Stage; +import seedu.address.commons.core.GuiSettings; +import seedu.address.commons.core.LogsCenter; +import seedu.address.logic.AppLogic; +import seedu.address.logic.messages.AppMessage; +import seedu.address.logic.messages.BluetoothPingsMessage; +import seedu.address.logic.parser.exceptions.ParseException; + +/** + * The Main Window. Provides the basic application layout containing + * a menu bar and space where other JavaFX elements can be placed. + */ +public class AppMainWindow extends UiPart { + + private static final String FXML = "AppMainWindow.fxml"; + + private final Logger logger = LogsCenter.getLogger(getClass()); + + private Stage primaryStage; + private AppLogic logic; + private BluetoothPingPanel bluetoothPingPanel; + private BluetoothPingSummaryPanel bluetoothPingSummaryPanel; + private ResultDisplay resultDisplay; + + @FXML + private StackPane commandBoxPlaceholder; + + @FXML + private StackPane resultDisplayPlaceholder; + + @FXML + private StackPane bluetoothPingPanelPlaceholder; + + private void renderToPanel() { + this.bluetoothPingPanelPlaceholder.getChildren().clear(); + + } + + public AppMainWindow(Stage primaryStage, AppLogic logic) { + super(FXML, primaryStage); + + // Set dependencies + this.primaryStage = primaryStage; + this.logic = logic; + } + + public Stage getPrimaryStage() { + return primaryStage; + } + + public void renderToDisplay(AppMessage commandResult) { + if (commandResult.getRenderFlag()) { + this.bluetoothPingPanelPlaceholder.getChildren().clear(); + if (commandResult.getIdentifier().equals("BluetoothPings")){ + this.bluetoothPingPanel = new BluetoothPingPanel(commandResult.getDisplayAsObservable()); + this.bluetoothPingPanelPlaceholder.getChildren().add(this.bluetoothPingPanel.getRoot()); + } + else if (commandResult.getIdentifier().equals("BluetoothPingsSummary")) { + this.bluetoothPingSummaryPanel = new BluetoothPingSummaryPanel(commandResult.getDisplayAsObservable()); + this.bluetoothPingPanelPlaceholder.getChildren().add(this.bluetoothPingSummaryPanel.getRoot()); + } + else if (commandResult.getIdentifier().equals("UserList")) { + + } + } + } + + /** + * Fills up all the placeholders of this window. + */ + void fillInnerParts() { + this.bluetoothPingPanel = new BluetoothPingPanel(logic.getAll()); + this.bluetoothPingPanelPlaceholder.getChildren().add(this.bluetoothPingPanel.getRoot()); + + this.resultDisplay = new ResultDisplay(); + resultDisplayPlaceholder.getChildren().add(this.resultDisplay.getRoot()); + + AppCommandBox commandBox = new AppCommandBox(this::executeCommand); + this.commandBoxPlaceholder.getChildren().add(commandBox.getRoot()); + } + + void show() { + primaryStage.show(); + } + + /** + * Closes the application. + */ + @FXML + private void handleExit() { + GuiSettings guiSettings = new GuiSettings(primaryStage.getWidth(), primaryStage.getHeight(), + (int) primaryStage.getX(), (int) primaryStage.getY()); + primaryStage.hide(); + } + + /** + * Executes the command and returns the result. + * + * @see seedu.address.logic.Logic#execute(String) + */ + private AppMessage executeCommand(String commandText) throws ParseException { + try { + AppMessage commandResult = logic.execute(commandText); + logger.info("Result: " + commandResult.getFeedbackToUser()); + resultDisplay.setFeedbackToUser(commandResult.getFeedbackToUser()); + this.renderToDisplay(commandResult); + + if (commandResult.isExit()) { + handleExit(); + } + return commandResult; + } catch (ParseException e) { + logger.warning("Invalid command: " + commandText); + resultDisplay.setFeedbackToUser(e.getMessage()); + throw e; + } + } +} diff --git a/src/main/java/seedu/address/ui/UiManager.java b/src/main/java/seedu/address/ui/AppUiManager.java similarity index 81% rename from src/main/java/seedu/address/ui/UiManager.java rename to src/main/java/seedu/address/ui/AppUiManager.java index 876621d79b9..cf5afd0a856 100644 --- a/src/main/java/seedu/address/ui/UiManager.java +++ b/src/main/java/seedu/address/ui/AppUiManager.java @@ -1,31 +1,25 @@ package seedu.address.ui; -import java.util.logging.Logger; - import javafx.application.Platform; import javafx.scene.control.Alert; -import javafx.scene.control.Alert.AlertType; import javafx.scene.image.Image; import javafx.stage.Stage; -import seedu.address.MainApp; import seedu.address.commons.core.LogsCenter; import seedu.address.commons.util.StringUtil; -import seedu.address.logic.Logic; - -/** - * The manager of the UI component. - */ -public class UiManager implements Ui { +import seedu.address.logic.AppLogic; +import seedu.address.ContactTracingMainApp; +import java.util.logging.Logger; +public class AppUiManager implements Ui { public static final String ALERT_DIALOG_PANE_FIELD_ID = "alertDialogPane"; - private static final Logger logger = LogsCenter.getLogger(UiManager.class); + private static final Logger logger = LogsCenter.getLogger(AppUiManager.class); private static final String ICON_APPLICATION = "/images/address_book_32.png"; - private Logic logic; - private MainWindow mainWindow; + private AppLogic logic; + private AppMainWindow mainWindow; - public UiManager(Logic logic) { + public AppUiManager(AppLogic logic) { super(); this.logic = logic; } @@ -38,7 +32,7 @@ public void start(Stage primaryStage) { primaryStage.getIcons().add(getImage(ICON_APPLICATION)); try { - mainWindow = new MainWindow(primaryStage, logic); + mainWindow = new AppMainWindow(primaryStage, logic); mainWindow.show(); //This should be called before creating other UI parts mainWindow.fillInnerParts(); @@ -49,7 +43,7 @@ public void start(Stage primaryStage) { } private Image getImage(String imagePath) { - return new Image(MainApp.class.getResourceAsStream(imagePath)); + return new Image(ContactTracingMainApp.class.getResourceAsStream(imagePath)); } void showAlertDialogAndWait(Alert.AlertType type, String title, String headerText, String contentText) { @@ -60,7 +54,7 @@ void showAlertDialogAndWait(Alert.AlertType type, String title, String headerTex * Shows an alert dialog on {@code owner} with the given parameters. * This method only returns after the user has closed the alert dialog. */ - private static void showAlertDialogAndWait(Stage owner, AlertType type, String title, String headerText, + private static void showAlertDialogAndWait(Stage owner, Alert.AlertType type, String title, String headerText, String contentText) { final Alert alert = new Alert(type); alert.getDialogPane().getStylesheets().add("view/DarkTheme.css"); @@ -82,5 +76,4 @@ private void showFatalErrorDialogAndShutdown(String title, Throwable e) { Platform.exit(); System.exit(1); } - } diff --git a/src/main/java/seedu/address/ui/BluetoothPingCard.java b/src/main/java/seedu/address/ui/BluetoothPingCard.java new file mode 100644 index 00000000000..4ee1438e812 --- /dev/null +++ b/src/main/java/seedu/address/ui/BluetoothPingCard.java @@ -0,0 +1,29 @@ +package seedu.address.ui; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.layout.Region; +import seedu.address.model.bluetooth.BluetoothPings; + +public class BluetoothPingCard extends UiPart { + + private static final String FXML = "BluetoothPingCard.fxml"; + + public final BluetoothPings bluetoothPings; + + @FXML + private Label contacts; + + @FXML + private Label timestamp; + + public BluetoothPingCard(BluetoothPings bluetoothPings, int displayedIndex) { + super(FXML); + this.bluetoothPings = bluetoothPings; + contacts.setText(bluetoothPings.getUserIDs().toString()); + timestamp.setText(bluetoothPings.getEpochTs().toString()); + } + + @Override + public boolean equals(Object other) {return true;} +} diff --git a/src/main/java/seedu/address/ui/BluetoothPingPanel.java b/src/main/java/seedu/address/ui/BluetoothPingPanel.java new file mode 100644 index 00000000000..73041a1cfbf --- /dev/null +++ b/src/main/java/seedu/address/ui/BluetoothPingPanel.java @@ -0,0 +1,39 @@ +package seedu.address.ui; + +import java.util.logging.Logger; + +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.scene.layout.Region; +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; +import seedu.address.commons.core.LogsCenter; +import seedu.address.model.bluetooth.BluetoothPings; + +public class BluetoothPingPanel extends UiPart { + private static final String FXML = "BluetoothPingPanel.fxml"; + private final Logger logger = LogsCenter.getLogger(BluetoothPingPanel.class); + + @FXML + private ListView bluetoothPingsListView; + + public BluetoothPingPanel(ObservableList bluetoothPingsList) { + super(FXML); + bluetoothPingsListView.setItems(bluetoothPingsList); + bluetoothPingsListView.setCellFactory(listView -> new BluetoothPingsListViewCell()); + } + + class BluetoothPingsListViewCell extends ListCell { + @Override + protected void updateItem(BluetoothPings bluetoothPings, boolean empty) { + super.updateItem(bluetoothPings, empty); + + if (empty || bluetoothPings == null) { + setGraphic(null); + setText(null); + } else { + setGraphic(new BluetoothPingCard(bluetoothPings, getIndex() +1).getRoot()); + } + } + } +} diff --git a/src/main/java/seedu/address/ui/BluetoothPingSummaryCard.java b/src/main/java/seedu/address/ui/BluetoothPingSummaryCard.java new file mode 100644 index 00000000000..9a6b41beb88 --- /dev/null +++ b/src/main/java/seedu/address/ui/BluetoothPingSummaryCard.java @@ -0,0 +1,29 @@ +package seedu.address.ui; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.layout.Region; +import seedu.address.model.bluetooth.BluetoothPingsSummary; + +public class BluetoothPingSummaryCard extends UiPart { + + private static final String FXML="BluetoothPingSummaryCard.fxml"; + + public final BluetoothPingsSummary bluetoothPings; + + @FXML + private Label contacts; + + @FXML + private Label occurrence; + + public BluetoothPingSummaryCard(BluetoothPingsSummary bluetoothPingSummary,int displayedIndex){ + super(FXML); + this.bluetoothPings = bluetoothPingSummary; + contacts.setText(bluetoothPingSummary.getUserIDs().toString()); + occurrence.setText(bluetoothPingSummary.getCounts().toString()); + } + + @Override + public boolean equals(Object other){return true;} +} diff --git a/src/main/java/seedu/address/ui/BluetoothPingSummaryPanel.java b/src/main/java/seedu/address/ui/BluetoothPingSummaryPanel.java new file mode 100644 index 00000000000..5e119a7a1cc --- /dev/null +++ b/src/main/java/seedu/address/ui/BluetoothPingSummaryPanel.java @@ -0,0 +1,39 @@ +package seedu.address.ui; + +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; +import javafx.scene.layout.Region; +import seedu.address.commons.core.LogsCenter; +import seedu.address.model.bluetooth.BluetoothPingsSummary; + +import java.util.logging.Logger; + +public class BluetoothPingSummaryPanel extends UiPart { + private static final String FXML = "BluetoothPingPanel.fxml"; + private final Logger logger = LogsCenter.getLogger(BluetoothPingSummaryPanel.class); + + @javafx.fxml.FXML + private ListView bluetoothPingsListView; + + public BluetoothPingSummaryPanel(ObservableList bluetoothPingSummaryList) { + super(FXML); + bluetoothPingsListView.setItems(bluetoothPingSummaryList); + bluetoothPingsListView.setCellFactory(listView -> new BluetoothPingSummaryPanel.BluetoothPingsListViewCell()); + } + + class BluetoothPingsListViewCell extends ListCell { + @Override + protected void updateItem(BluetoothPingsSummary bluetoothPingsSummary, boolean empty) { + super.updateItem(bluetoothPingsSummary, empty); + + if (empty || bluetoothPingsSummary == null) { + setGraphic(null); + setText(null); + } else { + setGraphic(new BluetoothPingSummaryCard(bluetoothPingsSummary, getIndex() +1).getRoot()); + } + } + } +} diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java deleted file mode 100644 index 90bbf11de97..00000000000 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ /dev/null @@ -1,193 +0,0 @@ -package seedu.address.ui; - -import java.util.logging.Logger; - -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.scene.control.MenuItem; -import javafx.scene.control.TextInputControl; -import javafx.scene.input.KeyCombination; -import javafx.scene.input.KeyEvent; -import javafx.scene.layout.StackPane; -import javafx.stage.Stage; -import seedu.address.commons.core.GuiSettings; -import seedu.address.commons.core.LogsCenter; -import seedu.address.logic.Logic; -import seedu.address.logic.commands.CommandResult; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.logic.parser.exceptions.ParseException; - -/** - * The Main Window. Provides the basic application layout containing - * a menu bar and space where other JavaFX elements can be placed. - */ -public class MainWindow extends UiPart { - - private static final String FXML = "MainWindow.fxml"; - - private final Logger logger = LogsCenter.getLogger(getClass()); - - private Stage primaryStage; - private Logic logic; - - // Independent Ui parts residing in this Ui container - private PersonListPanel personListPanel; - private ResultDisplay resultDisplay; - private HelpWindow helpWindow; - - @FXML - private StackPane commandBoxPlaceholder; - - @FXML - private MenuItem helpMenuItem; - - @FXML - private StackPane personListPanelPlaceholder; - - @FXML - private StackPane resultDisplayPlaceholder; - - @FXML - private StackPane statusbarPlaceholder; - - public MainWindow(Stage primaryStage, Logic logic) { - super(FXML, primaryStage); - - // Set dependencies - this.primaryStage = primaryStage; - this.logic = logic; - - // Configure the UI - setWindowDefaultSize(logic.getGuiSettings()); - - setAccelerators(); - - helpWindow = new HelpWindow(); - } - - public Stage getPrimaryStage() { - return primaryStage; - } - - private void setAccelerators() { - setAccelerator(helpMenuItem, KeyCombination.valueOf("F1")); - } - - /** - * Sets the accelerator of a MenuItem. - * @param keyCombination the KeyCombination value of the accelerator - */ - private void setAccelerator(MenuItem menuItem, KeyCombination keyCombination) { - menuItem.setAccelerator(keyCombination); - - /* - * TODO: the code below can be removed once the bug reported here - * https://bugs.openjdk.java.net/browse/JDK-8131666 - * is fixed in later version of SDK. - * - * According to the bug report, TextInputControl (TextField, TextArea) will - * consume function-key events. Because CommandBox contains a TextField, and - * ResultDisplay contains a TextArea, thus some accelerators (e.g F1) will - * not work when the focus is in them because the key event is consumed by - * the TextInputControl(s). - * - * For now, we add following event filter to capture such key events and open - * help window purposely so to support accelerators even when focus is - * in CommandBox or ResultDisplay. - */ - getRoot().addEventFilter(KeyEvent.KEY_PRESSED, event -> { - if (event.getTarget() instanceof TextInputControl && keyCombination.match(event)) { - menuItem.getOnAction().handle(new ActionEvent()); - event.consume(); - } - }); - } - - /** - * Fills up all the placeholders of this window. - */ - void fillInnerParts() { - personListPanel = new PersonListPanel(logic.getFilteredPersonList()); - personListPanelPlaceholder.getChildren().add(personListPanel.getRoot()); - - resultDisplay = new ResultDisplay(); - resultDisplayPlaceholder.getChildren().add(resultDisplay.getRoot()); - - StatusBarFooter statusBarFooter = new StatusBarFooter(logic.getAddressBookFilePath()); - statusbarPlaceholder.getChildren().add(statusBarFooter.getRoot()); - - CommandBox commandBox = new CommandBox(this::executeCommand); - commandBoxPlaceholder.getChildren().add(commandBox.getRoot()); - } - - /** - * Sets the default size based on {@code guiSettings}. - */ - private void setWindowDefaultSize(GuiSettings guiSettings) { - primaryStage.setHeight(guiSettings.getWindowHeight()); - primaryStage.setWidth(guiSettings.getWindowWidth()); - if (guiSettings.getWindowCoordinates() != null) { - primaryStage.setX(guiSettings.getWindowCoordinates().getX()); - primaryStage.setY(guiSettings.getWindowCoordinates().getY()); - } - } - - /** - * Opens the help window or focuses on it if it's already opened. - */ - @FXML - public void handleHelp() { - if (!helpWindow.isShowing()) { - helpWindow.show(); - } else { - helpWindow.focus(); - } - } - - void show() { - primaryStage.show(); - } - - /** - * Closes the application. - */ - @FXML - private void handleExit() { - GuiSettings guiSettings = new GuiSettings(primaryStage.getWidth(), primaryStage.getHeight(), - (int) primaryStage.getX(), (int) primaryStage.getY()); - logic.setGuiSettings(guiSettings); - helpWindow.hide(); - primaryStage.hide(); - } - - public PersonListPanel getPersonListPanel() { - return personListPanel; - } - - /** - * Executes the command and returns the result. - * - * @see seedu.address.logic.Logic#execute(String) - */ - private CommandResult executeCommand(String commandText) throws CommandException, ParseException { - try { - CommandResult commandResult = logic.execute(commandText); - logger.info("Result: " + commandResult.getFeedbackToUser()); - resultDisplay.setFeedbackToUser(commandResult.getFeedbackToUser()); - - if (commandResult.isShowHelp()) { - handleHelp(); - } - - if (commandResult.isExit()) { - handleExit(); - } - - return commandResult; - } catch (CommandException | ParseException e) { - logger.info("Invalid command: " + commandText); - resultDisplay.setFeedbackToUser(e.getMessage()); - throw e; - } - } -} diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java deleted file mode 100644 index 0684b088868..00000000000 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ /dev/null @@ -1,74 +0,0 @@ -package seedu.address.ui; - -import java.util.Comparator; - -import javafx.fxml.FXML; -import javafx.scene.control.Label; -import javafx.scene.layout.FlowPane; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Region; -import seedu.address.model.person.Person; - -/** - * An UI component that displays information of a {@code Person}. - */ -public class PersonCard extends UiPart { - - private static final String FXML = "PersonListCard.fxml"; - - /** - * Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX. - * As a consequence, UI elements' variable names cannot be set to such keywords - * or an exception will be thrown by JavaFX during runtime. - * - * @see The issue on AddressBook level 4 - */ - - public final Person person; - - @FXML - private HBox cardPane; - @FXML - private Label name; - @FXML - private Label id; - @FXML - private Label phone; - @FXML - private Label address; - @FXML - private Label email; - @FXML - private FlowPane tags; - - public PersonCard(Person person, int displayedIndex) { - super(FXML); - this.person = person; - id.setText(displayedIndex + ". "); - name.setText(person.getName().fullName); - phone.setText(person.getPhone().value); - address.setText(person.getAddress().value); - email.setText(person.getEmail().value); - person.getTags().stream() - .sorted(Comparator.comparing(tag -> tag.tagName)) - .forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); - } - - @Override - public boolean equals(Object other) { - // short circuit if same object - if (other == this) { - return true; - } - - // instanceof handles nulls - if (!(other instanceof PersonCard)) { - return false; - } - - // state check - PersonCard card = (PersonCard) other; - return id.getText().equals(card.id.getText()) - && person.equals(card.person); - } -} diff --git a/src/main/java/seedu/address/ui/PersonListPanel.java b/src/main/java/seedu/address/ui/PersonListPanel.java deleted file mode 100644 index 1328917096e..00000000000 --- a/src/main/java/seedu/address/ui/PersonListPanel.java +++ /dev/null @@ -1,46 +0,0 @@ -package seedu.address.ui; - -import java.util.logging.Logger; - -import javafx.collections.ObservableList; -import javafx.fxml.FXML; -import javafx.scene.control.ListCell; -import javafx.scene.control.ListView; -import javafx.scene.layout.Region; -import seedu.address.commons.core.LogsCenter; -import seedu.address.model.person.Person; - -/** - * Panel containing the list of persons. - */ -public class PersonListPanel extends UiPart { - private static final String FXML = "PersonListPanel.fxml"; - private final Logger logger = LogsCenter.getLogger(PersonListPanel.class); - - @FXML - private ListView personListView; - - public PersonListPanel(ObservableList personList) { - super(FXML); - personListView.setItems(personList); - personListView.setCellFactory(listView -> new PersonListViewCell()); - } - - /** - * Custom {@code ListCell} that displays the graphics of a {@code Person} using a {@code PersonCard}. - */ - class PersonListViewCell extends ListCell { - @Override - protected void updateItem(Person person, boolean empty) { - super.updateItem(person, empty); - - if (empty || person == null) { - setGraphic(null); - setText(null); - } else { - setGraphic(new PersonCard(person, getIndex() + 1).getRoot()); - } - } - } - -} diff --git a/src/main/java/seedu/address/ui/UiPart.java b/src/main/java/seedu/address/ui/UiPart.java index fc820e01a9c..4f43333c5f4 100644 --- a/src/main/java/seedu/address/ui/UiPart.java +++ b/src/main/java/seedu/address/ui/UiPart.java @@ -4,9 +4,8 @@ import java.io.IOException; import java.net.URL; - import javafx.fxml.FXMLLoader; -import seedu.address.MainApp; +import seedu.address.ContactTracingMainApp; /** * Represents a distinct part of the UI. e.g. Windows, dialogs, panels, status bars, etc. @@ -81,7 +80,7 @@ private void loadFxmlFile(URL location, T root) { private static URL getFxmlFileUrl(String fxmlFileName) { requireNonNull(fxmlFileName); String fxmlFileNameWithFolder = FXML_FILE_FOLDER + fxmlFileName; - URL fxmlFileUrl = MainApp.class.getResource(fxmlFileNameWithFolder); + URL fxmlFileUrl = ContactTracingMainApp.class.getResource(fxmlFileNameWithFolder); return requireNonNull(fxmlFileUrl); } diff --git a/src/main/main.iml b/src/main/main.iml new file mode 100644 index 00000000000..161e1645a3c --- /dev/null +++ b/src/main/main.iml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/Externel Library/itextpdf/barcodes-7.1.9.jar b/src/main/resources/Externel Library/itextpdf/barcodes-7.1.9.jar new file mode 100644 index 00000000000..8fb457c2186 Binary files /dev/null and b/src/main/resources/Externel Library/itextpdf/barcodes-7.1.9.jar differ diff --git a/src/main/resources/Externel Library/itextpdf/font-asian-7.1.9.jar b/src/main/resources/Externel Library/itextpdf/font-asian-7.1.9.jar new file mode 100644 index 00000000000..c2f48eaf73a Binary files /dev/null and b/src/main/resources/Externel Library/itextpdf/font-asian-7.1.9.jar differ diff --git a/src/main/resources/Externel Library/itextpdf/forms-7.1.9.jar b/src/main/resources/Externel Library/itextpdf/forms-7.1.9.jar new file mode 100644 index 00000000000..fb627ff17a9 Binary files /dev/null and b/src/main/resources/Externel Library/itextpdf/forms-7.1.9.jar differ diff --git a/src/main/resources/Externel Library/itextpdf/hyph-7.1.9.jar b/src/main/resources/Externel Library/itextpdf/hyph-7.1.9.jar new file mode 100644 index 00000000000..32c9763a9da Binary files /dev/null and b/src/main/resources/Externel Library/itextpdf/hyph-7.1.9.jar differ diff --git a/src/main/resources/Externel Library/itextpdf/io-7.1.9.jar b/src/main/resources/Externel Library/itextpdf/io-7.1.9.jar new file mode 100644 index 00000000000..408cffe1aa7 Binary files /dev/null and b/src/main/resources/Externel Library/itextpdf/io-7.1.9.jar differ diff --git a/src/main/resources/Externel Library/itextpdf/kernel-7.1.9.jar b/src/main/resources/Externel Library/itextpdf/kernel-7.1.9.jar new file mode 100644 index 00000000000..075ade34b26 Binary files /dev/null and b/src/main/resources/Externel Library/itextpdf/kernel-7.1.9.jar differ diff --git a/src/main/resources/Externel Library/itextpdf/layout-7.1.9.jar b/src/main/resources/Externel Library/itextpdf/layout-7.1.9.jar new file mode 100644 index 00000000000..75535b3ea0a Binary files /dev/null and b/src/main/resources/Externel Library/itextpdf/layout-7.1.9.jar differ diff --git a/src/main/resources/Externel Library/itextpdf/log4j-1.2.17.jar b/src/main/resources/Externel Library/itextpdf/log4j-1.2.17.jar new file mode 100644 index 00000000000..1d425cf7d7e Binary files /dev/null and b/src/main/resources/Externel Library/itextpdf/log4j-1.2.17.jar differ diff --git a/src/main/resources/Externel Library/itextpdf/pdfa-7.1.9.jar b/src/main/resources/Externel Library/itextpdf/pdfa-7.1.9.jar new file mode 100644 index 00000000000..18873b793f0 Binary files /dev/null and b/src/main/resources/Externel Library/itextpdf/pdfa-7.1.9.jar differ diff --git a/src/main/resources/Externel Library/itextpdf/pdftest-7.1.9.jar b/src/main/resources/Externel Library/itextpdf/pdftest-7.1.9.jar new file mode 100644 index 00000000000..d052dabf47f Binary files /dev/null and b/src/main/resources/Externel Library/itextpdf/pdftest-7.1.9.jar differ diff --git a/src/main/resources/Externel Library/itextpdf/sign-7.1.9.jar b/src/main/resources/Externel Library/itextpdf/sign-7.1.9.jar new file mode 100644 index 00000000000..3dda03368cf Binary files /dev/null and b/src/main/resources/Externel Library/itextpdf/sign-7.1.9.jar differ diff --git a/src/main/resources/Externel Library/itextpdf/slf4j-api-1.7.21.jar b/src/main/resources/Externel Library/itextpdf/slf4j-api-1.7.21.jar new file mode 100644 index 00000000000..2a5c33ec554 Binary files /dev/null and b/src/main/resources/Externel Library/itextpdf/slf4j-api-1.7.21.jar differ diff --git a/src/main/resources/Externel Library/itextpdf/slf4j-log4j12-1.7.21.jar b/src/main/resources/Externel Library/itextpdf/slf4j-log4j12-1.7.21.jar new file mode 100644 index 00000000000..ff4fddd695d Binary files /dev/null and b/src/main/resources/Externel Library/itextpdf/slf4j-log4j12-1.7.21.jar differ diff --git a/src/main/resources/Externel Library/itextpdf/styled-xml-parser-7.1.9.jar b/src/main/resources/Externel Library/itextpdf/styled-xml-parser-7.1.9.jar new file mode 100644 index 00000000000..82f5234e942 Binary files /dev/null and b/src/main/resources/Externel Library/itextpdf/styled-xml-parser-7.1.9.jar differ diff --git a/src/main/resources/Externel Library/itextpdf/svg-7.1.9.jar b/src/main/resources/Externel Library/itextpdf/svg-7.1.9.jar new file mode 100644 index 00000000000..095d8aa99d9 Binary files /dev/null and b/src/main/resources/Externel Library/itextpdf/svg-7.1.9.jar differ diff --git a/src/main/resources/Externel Library/slf4j/log4j-1.2.17.jar b/src/main/resources/Externel Library/slf4j/log4j-1.2.17.jar new file mode 100644 index 00000000000..1d425cf7d7e Binary files /dev/null and b/src/main/resources/Externel Library/slf4j/log4j-1.2.17.jar differ diff --git a/src/main/resources/Externel Library/slf4j/slf4j-api-1.7.21.jar b/src/main/resources/Externel Library/slf4j/slf4j-api-1.7.21.jar new file mode 100644 index 00000000000..2a5c33ec554 Binary files /dev/null and b/src/main/resources/Externel Library/slf4j/slf4j-api-1.7.21.jar differ diff --git a/src/main/resources/Externel Library/slf4j/slf4j-log4j12-1.7.21.jar b/src/main/resources/Externel Library/slf4j/slf4j-log4j12-1.7.21.jar new file mode 100644 index 00000000000..ff4fddd695d Binary files /dev/null and b/src/main/resources/Externel Library/slf4j/slf4j-log4j12-1.7.21.jar differ diff --git a/src/main/resources/view/AppMainWindow.fxml b/src/main/resources/view/AppMainWindow.fxml new file mode 100644 index 00000000000..1e03ef0fd4d --- /dev/null +++ b/src/main/resources/view/AppMainWindow.fxml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/view/BluetoothPingCard.fxml b/src/main/resources/view/BluetoothPingCard.fxml new file mode 100644 index 00000000000..5bbd346bacb --- /dev/null +++ b/src/main/resources/view/BluetoothPingCard.fxml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/view/BluetoothPingPanel.fxml b/src/main/resources/view/BluetoothPingPanel.fxml new file mode 100644 index 00000000000..1ba48a8fb72 --- /dev/null +++ b/src/main/resources/view/BluetoothPingPanel.fxml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/main/resources/view/BluetoothPingSummaryCard.fxml b/src/main/resources/view/BluetoothPingSummaryCard.fxml new file mode 100644 index 00000000000..d80b681c0c7 --- /dev/null +++ b/src/main/resources/view/BluetoothPingSummaryCard.fxml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/seedu/address/logic/LogicManagerTest.java index ad923ac249a..77609bfd1d1 100644 --- a/src/test/java/seedu/address/logic/LogicManagerTest.java +++ b/src/test/java/seedu/address/logic/LogicManagerTest.java @@ -17,19 +17,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import seedu.address.logic.commands.AddCommand; -import seedu.address.logic.commands.CommandResult; -import seedu.address.logic.commands.ListCommand; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.UserPrefs; import seedu.address.model.person.Person; -import seedu.address.storage.JsonAddressBookStorage; -import seedu.address.storage.JsonUserPrefsStorage; -import seedu.address.storage.StorageManager; import seedu.address.testutil.PersonBuilder; public class LogicManagerTest { diff --git a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java index cb8714bb055..ec9ad5ce5d6 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java @@ -7,9 +7,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; import seedu.address.model.person.Person; import seedu.address.testutil.PersonBuilder; diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/seedu/address/logic/commands/AddCommandTest.java index 5865713d5dd..0daa882be5a 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/AddCommandTest.java @@ -16,10 +16,6 @@ import javafx.collections.ObservableList; import seedu.address.commons.core.GuiSettings; import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.ReadOnlyUserPrefs; import seedu.address.model.person.Person; import seedu.address.testutil.PersonBuilder; diff --git a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java b/src/test/java/seedu/address/logic/commands/ClearCommandTest.java index 80d9110c03a..2376f89f317 100644 --- a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ClearCommandTest.java @@ -5,11 +5,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; - public class ClearCommandTest { @Test diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java index 643a1d08069..ad49cf6e0e9 100644 --- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java +++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java @@ -15,8 +15,6 @@ import seedu.address.commons.core.index.Index; import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; import seedu.address.model.person.NameContainsKeywordsPredicate; import seedu.address.model.person.Person; import seedu.address.testutil.EditPersonDescriptorBuilder; diff --git a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java index 0f77d8295f6..172c9ccddb8 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java @@ -13,9 +13,6 @@ import seedu.address.commons.core.Messages; import seedu.address.commons.core.index.Index; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; import seedu.address.model.person.Person; /** diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java index 1c27530fa99..f0410709bcc 100644 --- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/EditCommandTest.java @@ -18,11 +18,6 @@ import seedu.address.commons.core.Messages; import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; import seedu.address.model.person.Person; import seedu.address.testutil.EditPersonDescriptorBuilder; import seedu.address.testutil.PersonBuilder; diff --git a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java b/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java index e0288792e72..5c988077a4d 100644 --- a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java +++ b/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java @@ -12,7 +12,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; import seedu.address.testutil.EditPersonDescriptorBuilder; public class EditPersonDescriptorTest { diff --git a/src/test/java/seedu/address/logic/commands/ExitCommandTest.java b/src/test/java/seedu/address/logic/commands/ExitCommandTest.java index 9533c473875..4c2f949041f 100644 --- a/src/test/java/seedu/address/logic/commands/ExitCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ExitCommandTest.java @@ -5,9 +5,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; - public class ExitCommandTest { private Model model = new ModelManager(); private Model expectedModel = new ModelManager(); diff --git a/src/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/seedu/address/logic/commands/FindCommandTest.java index 9b15db28bbb..956799bab0a 100644 --- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/FindCommandTest.java @@ -15,9 +15,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; import seedu.address.model.person.NameContainsKeywordsPredicate; /** diff --git a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java b/src/test/java/seedu/address/logic/commands/HelpCommandTest.java index 4904fc4352e..43e5b3c06bd 100644 --- a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/HelpCommandTest.java @@ -5,9 +5,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; - public class HelpCommandTest { private Model model = new ModelManager(); private Model expectedModel = new ModelManager(); diff --git a/src/test/java/seedu/address/logic/commands/ListCommandTest.java b/src/test/java/seedu/address/logic/commands/ListCommandTest.java index 435ff1f7275..600c3237618 100644 --- a/src/test/java/seedu/address/logic/commands/ListCommandTest.java +++ b/src/test/java/seedu/address/logic/commands/ListCommandTest.java @@ -8,10 +8,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; - /** * Contains integration tests (interaction with the Model) and unit tests for ListCommand. */ diff --git a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java index 5cf487d7ebb..646a9f483b3 100644 --- a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java @@ -31,7 +31,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.AddCommand; import seedu.address.model.person.Address; import seedu.address.model.person.Email; import seedu.address.model.person.Name; diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java index d9659205b57..22b68cc032a 100644 --- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java @@ -13,15 +13,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.AddCommand; -import seedu.address.logic.commands.ClearCommand; -import seedu.address.logic.commands.DeleteCommand; -import seedu.address.logic.commands.EditCommand; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.logic.commands.ExitCommand; -import seedu.address.logic.commands.FindCommand; -import seedu.address.logic.commands.HelpCommand; -import seedu.address.logic.commands.ListCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.NameContainsKeywordsPredicate; import seedu.address.model.person.Person; diff --git a/src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java b/src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java index e4c33515768..bf7336b7908 100644 --- a/src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java +++ b/src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java @@ -2,7 +2,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import seedu.address.logic.commands.Command; import seedu.address.logic.parser.exceptions.ParseException; /** diff --git a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java b/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java index 27eaec84450..a8281d3d99c 100644 --- a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java @@ -7,8 +7,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.DeleteCommand; - /** * As we are only doing white-box testing, our test cases do not cover path variations * outside of the DeleteCommand code. For example, inputs "1" and "1 abc" take the diff --git a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java index 2ff31522486..d81e08a5da1 100644 --- a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java @@ -34,8 +34,6 @@ import org.junit.jupiter.api.Test; import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.EditCommand; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; import seedu.address.model.person.Address; import seedu.address.model.person.Email; import seedu.address.model.person.Name; diff --git a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java index 70f4f0e79c4..530ba604565 100644 --- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java @@ -8,7 +8,6 @@ import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.FindCommand; import seedu.address.model.person.NameContainsKeywordsPredicate; public class FindCommandParserTest { diff --git a/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java b/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java index ac3c3af9566..cef9f1158c3 100644 --- a/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java +++ b/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java @@ -16,8 +16,6 @@ import org.junit.jupiter.api.io.TempDir; import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; public class JsonAddressBookStorageTest { private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "JsonAddressBookStorageTest"); diff --git a/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java b/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java index 188c9058d20..f4dfe86b936 100644 --- a/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java +++ b/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java @@ -10,7 +10,6 @@ import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.commons.util.JsonUtil; -import seedu.address.model.AddressBook; import seedu.address.testutil.TypicalPersons; public class JsonSerializableAddressBookTest { diff --git a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java b/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java index 16f33f4a6bb..8a019e8f554 100644 --- a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java +++ b/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java @@ -14,7 +14,6 @@ import seedu.address.commons.core.GuiSettings; import seedu.address.commons.exceptions.DataConversionException; -import seedu.address.model.UserPrefs; public class JsonUserPrefsStorageTest { diff --git a/src/test/java/seedu/address/storage/StorageManagerTest.java b/src/test/java/seedu/address/storage/StorageManagerTest.java index 99a16548970..0e337acda71 100644 --- a/src/test/java/seedu/address/storage/StorageManagerTest.java +++ b/src/test/java/seedu/address/storage/StorageManagerTest.java @@ -11,9 +11,6 @@ import org.junit.jupiter.api.io.TempDir; import seedu.address.commons.core.GuiSettings; -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.UserPrefs; public class StorageManagerTest { diff --git a/src/test/java/seedu/address/testutil/AddressBookBuilder.java b/src/test/java/seedu/address/testutil/AddressBookBuilder.java index d53799fd110..2bc9efdd76b 100644 --- a/src/test/java/seedu/address/testutil/AddressBookBuilder.java +++ b/src/test/java/seedu/address/testutil/AddressBookBuilder.java @@ -1,6 +1,5 @@ package seedu.address.testutil; -import seedu.address.model.AddressBook; import seedu.address.model.person.Person; /** diff --git a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java b/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java index 4584bd5044e..4c906e6ca71 100644 --- a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java +++ b/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java @@ -4,7 +4,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; import seedu.address.model.person.Address; import seedu.address.model.person.Email; import seedu.address.model.person.Name; diff --git a/src/test/java/seedu/address/testutil/PersonUtil.java b/src/test/java/seedu/address/testutil/PersonUtil.java index 90849945183..cb502d00d14 100644 --- a/src/test/java/seedu/address/testutil/PersonUtil.java +++ b/src/test/java/seedu/address/testutil/PersonUtil.java @@ -8,8 +8,6 @@ import java.util.Set; -import seedu.address.logic.commands.AddCommand; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; import seedu.address.model.person.Person; import seedu.address.model.tag.Tag; diff --git a/src/test/java/seedu/address/testutil/TestUtil.java b/src/test/java/seedu/address/testutil/TestUtil.java index 896d103eb0b..20582a6fdea 100644 --- a/src/test/java/seedu/address/testutil/TestUtil.java +++ b/src/test/java/seedu/address/testutil/TestUtil.java @@ -6,7 +6,6 @@ import java.nio.file.Paths; import seedu.address.commons.core.index.Index; -import seedu.address.model.Model; import seedu.address.model.person.Person; /** diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/seedu/address/testutil/TypicalPersons.java index fec76fb7129..4f2e532ae9b 100644 --- a/src/test/java/seedu/address/testutil/TypicalPersons.java +++ b/src/test/java/seedu/address/testutil/TypicalPersons.java @@ -15,7 +15,6 @@ import java.util.Arrays; import java.util.List; -import seedu.address.model.AddressBook; import seedu.address.model.person.Person; /** diff --git a/src/test/java/seedu/address/ui/UiPartTest.java b/src/test/java/seedu/address/ui/UiPartTest.java index 33d82d911b8..f2e4fa9ff69 100644 --- a/src/test/java/seedu/address/ui/UiPartTest.java +++ b/src/test/java/seedu/address/ui/UiPartTest.java @@ -11,7 +11,6 @@ import org.junit.jupiter.api.io.TempDir; import javafx.fxml.FXML; -import seedu.address.MainApp; public class UiPartTest { diff --git a/src/test/test.iml b/src/test/test.iml new file mode 100644 index 00000000000..bb46440c32d --- /dev/null +++ b/src/test/test.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file