text:
---
layout: page
title: Covigent - Developer Guide
---

1. [Preface](#1-preface)
1. [Setting Up](#2-setting-up)
1. [Design](#3-design)

    3.1  [Architecture: High Level View](#31-architecture-high-level-view)

    3.2  [UI Component](#32-ui-component)

    3.3  [Logic Component](#33-logic-component)

    3.4  [Model Component](#34-model-component)

    3.5  [Storage Component](#35-storage-component)

    3.6  [Commons Component](#36-commons-component)

 1. [Implementation](#4-implementation)

    4.1  [Patient Feature](#41-patient-feature)

          4.1.1 [Overview](#411-overview)

          4.1.2 [Implementation](#412-implementation)

          4.1.3 [Design Considerations](#413-design-considerations)

          4.1.4 [Create, Read, Update, Delete](#414-create-read-update-delete)

          4.1.5 [Search](#415-search)

    4.2  [Room Feature](#42-room-feature)

          4.2.1 [Overview](#421-overview)

          4.2.2 [Implementation](#422-implementation)

          4.2.3 [Design Considerations](#423-design-considerations)

          4.2.4 [Create, Read, Update](#424-create-read-update)

    4.3  [Task Feature](#43-task-feature)

          4.3.1 [Overview](#431-overview)

          4.3.2 [Implementation](#432-implementation)

          4.3.3 [Design Considerations](#433-design-considerations)

          4.3.4 [Create, Read, Update, Delete](#434-create-read-update-delete)

          4.3.5 [Search](#435-search)

    4.4  [Logging Feature](#44-logging-feature)

    4.5  [Configuration Feature](#45-configuration-feature)

 1. [Planned Features](#5-planned-features)

 1. [Documentation](#6-documentation)

 1. [Appendix](#7-appendix)

    A1. [Product Scope](#a1-product-scope)

    A2. [User Stories](#a2-user-stories)

    A3. [Use Cases](#a3-use-cases)

    A4. [Non-Functional Requirements](#a4-non-functional-requirements)

    A5. [Glossary](#a5-glossary)

    A6. [Instructions for Manual Testing](#a6-instructions-for-manual-testing)

--------------------------------------------------------------------------------------------------------------------
## 1. Preface

Covigent is a desktop management application that helps to keep track of the information of quarantined individuals and the tasks to be done by the staff of a small hotel that has been converted to a quarantine facility.

The Developer Guide for Covigent v1.4 is designed to illustrate and identify the high level architecture systems used to design and implement the Covigent application. The document contains an overall view of the system hierarchy, logical views of the system components, and a process view of the system’s communication. We hope that this Developer Guide serves you well in understanding and maintaining the Covigent application.

The link to the GitHub repository can be found [here](https://github.com/AY2021S1-CS2103T-W12-1/tp).

 _Written by: Yun Qing_

--------------------------------------------------------------------------------------------------------------------

## 2. Setting Up

Refer to the guide [_Setting up and getting started_](SettingUp.md).

--------------------------------------------------------------------------------------------------------------------

## 3. Design

This section describes some noteworthy details on how Covigent is designed.

### 3.1 Architecture: High Level View

    Figure 1. Architecture diagram of Covigent

The ***Architecture Diagram*** given above explains the high-level design of Covigent. Given below is a quick overview of each component.

:bulb: **Tip:** The `.puml` files used to create diagrams in this document can be found in the [diagrams](https://github.com/AY2021S1-CS2103T-W12-1/tp/tree/master/docs/diagrams/plantuml) folder. Refer to the [_PlantUML Tutorial_ at se-edu/guides](https://se-education.org/guides/tutorials/plantUml.html) to learn how to create and edit diagrams.

**`Main`** has two classes called [`Main`](https://github.com/AY2021S1-CS2103T-W12-1/tp/blob/master/src/main/java/seedu/address/Main.java) and [`MainApp`](https://github.com/AY2021S1-CS2103T-W12-1/tp/blob/master/src/main/java/seedu/address/MainApp.java). It is responsible for,
* At app launch: Initializes the components in the correct sequence, and connects them up with each other.
* At shut down: Shuts down the components and invokes cleanup methods where necessary.

[**`Commons`**](#36-commons-component) represents a collection of classes used by multiple other components.

The rest of the App consists of four components.

* [**`UI`**](#32-ui-component): The UI of the App.
* [**`Logic`**](#33-logic-component): The command executor.
* [**`Model`**](#34-model-component): Holds the data of the App in memory.
* [**`Storage`**](#35-storage-component): Reads data from, and writes data to, the hard disk.

Each of the four components,

* defines its *API* in an `interface` with the same name as the Component.
* exposes its functionality using a concrete `{Component Name}Manager` class (which implements the corresponding API `interface` mentioned in the previous point.

For example, the `Logic` component (see the class diagram given below) defines its API in the `Logic.java` interface and exposes its functionality using the `LogicManager.java` class which implements the `Logic` interface.

    Figure 2. Class diagram of Logic component

**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 `deletepatient Alex Yeoh`.

    Figure 3. Sequence diagram of deletepatient alex command

The sections below give more details of each component.

### 3.2 UI Component

The `UI` component displays information for the users based on user's input. The GUI to displayed is based on the return from logic.
It 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 [`MainWindow`](https://github.com/AY2021S1-CS2103T-W12-1/tp/blob/master/src/main/java/seedu/address/ui/MainWindow.java) is specified in [`MainWindow.fxml`](https://github.com/AY2021S1-CS2103T-W12-1/tp/blob/master/src/main/resources/view/MainWindow.fxml)

The `UI` component,
* Executes user commands using the `Logic` component.
* Consists of a `MainWindow` that is made up of many different parts that inherit from the abstract `UiPart` class.

The `MainWindow` is made up of
* A `PatientListPanel` that displays the list of patients. The layout is defined by `PatientCard` and `PatientDetailsPanel`.
* A `RoomListPanel` that displays the list of rooms. The layout is defined by `RoomCard` and `RoomDetailPanel`.
* A `RoomTaskListPanel` that displays the list of tasks. The layout is defined by `TaskCard`.
* A `HelpWindow` that displays the link to the help page.
* A `CommandBox` that displays the area for command input.
* A `ResultDisplay` that displays the robot response.
* A `StatusBarFooter` that displays the status bar footer.

Below is a class diagram for `Ui`

    Figure 4. Class diagram of Ui component

**API** :
[`Ui.java`](https://github.com/AY2021S1-CS2103T-W12-1/tp/blob/master/src/main/java/seedu/address/ui/Ui.java)

The `UI` component listens for changes to `Model` data so that the `UI` can be updated with the modified data.
Below shows the interaction with `Model`

    Figure 5. Structure of Ui component

_Written by: Wai Lok_

### 3.3 Logic Component

The `Logic` component is the "brains" of Covigent. While the `Ui` defines the GUI and `Model` defines in-memory data,
the `Logic` component does most of the heavy-lifting in terms of deciding what to change within the `Model` and what to
return to the `Ui`.

The diagram below shows the structure of the `Logic` component and how it interacts with its internal parts.

    Figure 6. Structure of the Logic Component

**API** :
[`Logic.java`](https://github.com/AY2021S1-CS2103T-W12-1/tp/blob/master/src/main/java/seedu/address/logic/Logic.java)

1. Once a user input is obtained from the GUI, `Logic` uses the `CovigentAppParser` class to parse the users' commands
and return a `Command` object.
1. The `Command` is executed by `LogicManager`.
1. Depending on the command input by the user, it may mutate the `Model`, such as adding a new patient, room or task.
1. The result of the command execution is encapsulated as a `CommandResult` that is returned to the `Ui`.
1. These `CommandResults` can instruct the `Ui` to perform certain actions, such as displaying help or error messages to the user.

Shown below is the Sequence Diagram within the `Logic` component for the API call: `execute("deletepatient alex")`.

    Figure 7. Interactions inside the Logic Component for the deletepatient alex Command

:information_source: **Note:** The lifeline for `DeletePatientCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.

_Written by: Ming De_

### 3.4 Model Component

The `Model` API acts as a facade that handles interaction between different kinds of data in Covigent. These data include user's preferences, patient records and room list. The `Model` API exposes the methods that allow the logic component to utilise to perform retrieving and updating of data.

The `Model` component,
  * stores a `UserPref` object that represents the user’s preferences.
  * stores a `PatientRecords` object that stores the data of all the patients.
  * stores a `RoomList` object that stores the data of all the rooms.
  * stores a `RoomTaskRecords` object that stores all the `RoomTaskAssociation` objects, which keep track of the room that a task belongs to.
  * exposes unmodifiable `ObservableList<Patient>`, `ObservableList<Room>` and `ObservableList<RoomTaskAssociation>` which can be observed. This means that the UI can be bound to the lists so that the UI automatically updates when data in the lists changes.
  * does not depend on any of the three components.

The concrete class `ModelManager` implements `Model` interface and manages the data for Covigent. `ModelManager` contains `UserPrefs`, `PatientRecords`, `RoomList` and `RoomTaskRecords`. These classes manage the data related to their specific features.

Below is a class diagram for `ModelManager`.

    Figure 7. Class Diagram for Model Component

**API** : [`Model.java`](https://github.com/AY2021S1-CS2103T-W12-1/tp/blob/master/src/main/java/seedu/address/model/Model.java)

The breakdown for each type of data in `ModelManager`, which include `PatientRecords`, `RoomList` and `RoomTaskRecords`, can be found below.

The `PatientRecords` class is in charge of maintaining the data of the patients and in ensuring the uniqueness of patients according to their names. Below is a class diagram for `PatientRecords`.

    Figure 8. Class Diagram for PatientRecords

:information_source: **Note:** The `PatientRecords` class implements the interface ReadOnlyList<Patient> but due to a limitation of PlantUML, the interface is reflected as simply `ReadOnlyList`.

The `RoomList` class is in charge of maintaining the data in the rooms and in ensuring the uniqueness of rooms according to the room numbers. As each room stores the data of the patient who resides in the room and the tasks meant for the room, it incorporates data from both `Patient` and `RoomTasks`. `RoomTasks` class is in charge of maintaining the data of the tasks in a room. The full details of `Patient` can be found in the previous class diagram for `PatientRecords` so it is no longer reflected in the class diagram for `RoomList`. The class diagram for `RoomList` is shown below.

    Figure 9. Class Diagram for RoomList

:information_source: **Note:** The `RoomList` class implements the interface ReadOnlyList <Room> and the `RoomTasks` class implements the interface ReadOnlyList<Task>. However, due to a limitation of PlantUML, the interface is reflected as simply `ReadOnlyList`.

The `RoomTaskRecords` class is in charge of maintaining the data regarding the association of a task in a room. The `RoomTaskAssociation` class acts as an association class that ties `Task` and `Room` together so that the `Task` object does not need to know of the details of `Room` and we are still able to identify the room number that `Task` belongs to and its index in `Room`. The class diagram for `RoomTaskRecords` is shown below.

    Figure 10. Class Diagram for RoomTaskRecords

:information_source: **Note:** The `RoomTaskRecords` class implements the interface ReadOnlyList <RoomTaskAssociation>. However, due to a limitation of PlantUML, the interface is reflected as simply `ReadOnlyList`.

 _Written by: Yun Qing_

### 3.5 Storage Component

    Figure 11. Structure of the Storage Component

**API** : [`Storage.java`](https://github.com/AY2021S1-CS2103T-W12-1/tp/blob/master/src/main/java/seedu/address/storage/Storage.java)

The `Storage` API handles the reading and writing of data in Json format, enabling Covigent to remember information stored by user even when the application is closed. The Storage API behaves like a façade by handling the storage classes and interfaces.

The `Storage` interface class diagram is shown below, and as it can be seen it inherits from specific storage interfaces.

The `Storage` component,
  *	Saves `UserPref` objects in Json format
  *	Reads `UserPred` objects in Json format
  *	Saves `RoomRecords` and `PatientRecords` data in json format
  *	Reads `RoomRecords` and `PatientRecords` data in json format

The information of the `Patient` and `Room` feature of Covigent is stored locally in the Json format. This is done by adapting the Patient and Room feature into JsonSerializablePatientRecords and JsonSerializableRoomRecords respectively.

The class diagram for StorageManager is shown below

    Figure 12. Structure of the StorageManager Component

The information of the `Patient` and `Room` feature of Covigent is stored locally in the Json format. This is done by adapting the Patient and Room feature into JsonSerializablePatientRecords and JsonSerializableRoomRecords respectively.

The class diagrams for the above stated adapted classes are shown below

     Figure 13. Structure of the JsonSerializableRoomRecords

      Figure 14. Structure of the JsonSerializablePatientRecords

 _Written by: Noorul Azlina_

### 3.6 Commons Component

Classes used by multiple components are in the `seedu.addressbook.commons` package.

--------------------------------------------------------------------------------------------------------------------

## 4. Implementation

This section describes some noteworthy details on how [Patient](#41-patient-feature), [Room](#42-room-feature) and [Task](#43-task-feature) features are implemented.

### 4.1 Patient Feature

#### 4.1.1 Overview

The patient feature in Covigent allows hotel staff to store important information about the individuals that are quarantined in the hotels. Some of these important dynamic information include temperature and comment regarding the patient. To fully understand the patient feature, it is important to learn about the [implementation](#412-implementation) and [design considerations](#413-design-considerations) of the patient object before looking at the possible [commands](#414-create-read-update-delete) that can operate on the patient object. A patient is meant to be allocated to a room in the facility, hence tying the patient feature with the room feature together.

#### 4.1.2 Implementation
A `Patient` object in Covigent contains the following attributes, which is also reflected in Figure 15:
1. Name
1. Temperature
1. PeriodOfStay
1. Age
1. Phone
1. Comment

Each of the attribute is a stand-alone class on its own.

      Figure 15. Class Diagram for Patient

#### 4.1.3 Design Considerations
**Aspect: Encapsulation of fields for `Patient` object**

* Option 1: Using primitive data types for `Temperature`, `Age` and `Comment` classes

Classes like `Temperature`, `Age` and `Comment` can be easily treated as primitive data types including double and string. However, this option goes against the spirit of OOP. Furthermore, it does not align to the original design of AddressBook3, which Covigent was morphed from, in which `Name` and `Phone` attributes were abstracted out as separate classes.

* Option 2: Encapsulate constituent patient attributes in their own classes

This option increases OOP and is aligned to the original design of AddressBook3. In addition, this design has proven itself to be extensible in the long run and allows for adjustments to `Patient` attributes easily. For example, when setting the valid temperature range as input for `Temperature`, only the `Temperature` class needs to change, which demonstrates the essence of the single responsibility principle. This allows for better understanding and maintenance of our code base in the future.

**Aspect: Decision on the uniqueness of `Patient` object**

* Option 1: Uniqueness is identified by name, age and phone

Originally, we intended to define two `Patient` to be equals if they have the same `Name`, `Age` and `Phone`. However, such a design will make it difficult for users of Covigent as they will have to key in all these fields when executing `EditPatientCommand` and `DeletePatientCommand` in order for Covigent to uniquely identify the `Patient` to manipulate.

* Option 2: Uniqueness is identified by name

Keeping in mind the ease of usage of Covigent for users, we chose to identify `Patient` uniquely by `Name` only. As such, when users need to manipulate the data of a `Patient`, all they need to input is the `Name`. Furthermore, we believes that since Covigent is used by small hotels, there is a very low chance of two patients having the same names.

##### Features related to Patient
Having looked at the design of `Patient`, we can now explore the possible features related to `Patient`. In particular, our commands support [create, read, update, delete](#414-create-read-update-delete) and [search](#415-search).

The features comprise of five commands namely,
* `AddPatientCommand` - Adding patients
* `ListPatientCommand` - Listing all the patients
* `EditPatientCommand` - Editing patients
* `DeletePatientCommand` - Deleting patients
* `SearchPatientCommand`- Searching for patients

_Written by Yun Qing_

#### 4.1.4 Create, Read, Update, Delete
In this section, we will cover the implementation of the manipulation of the `Patient` data. The commands that allow creating, reading, updating and deleting of `Patient` include `AddPatientCommand`, `ListPatientCommand`, `EditPatientCommand` and `DeletePatientCommand`.

As the `Patient` data are stored in `UniquePatientList`, which ensures the uniqueness of `Patient`, the actual manipulation of the `Patient` data is made in `UniquePatientList` class.

Some of the significant methods within `UniquePatientList` class that allows the manipulation of the `Patient` data are shown below:
* `UniquePatientList#add(Patient toAdd)` - Adds a `Patient` to `UniquePatientList`.
* `UniquePatientList#setPatient(Patient target, Patient editedPatient)` - Edits the attributes of `Patient`.
* `UniquePatientList#remove(Patient toRemove)` - Deletes a `Patient` from `UniquePatientList`.
* `UniquePatientList#asUnmodifiableObservableList()` - Returns an observable list of `Patient`
* `UniquePatientList#getPatientWithName(Name name)` - Returns the `Patient` with the given `Name` if the `Patient` object exists in `UniquePatientList`. Since `Name` is an identifier of a `Patient`, this method is used in `EditPatientCommand` and `DeletePatientCommand` to modify the `Patient` or check if the `Patient` to be deleted exists.

These methods in `UniquePatientList` class support the corresponding methods in the facade classes `PatientRecords` and `ModelManager`. In particular, the `Model` interface exposes the methods `Model#addPatient(Patient patient)`, `Model#setPatient(Patient target, Patient editedPatient)`, `Model#deletePatient(Patient target)`, `Model#getPatientWithName(Name name)` and `Model#getFilteredPatientList()`.

For brevity's sake, we will only illustrate the implementation of 2 specific commands - `AddPatientCommand` and `EditPatientCommand`.

**Implementation of AddPatientCommand**

The following is a detailed explanation of the operations that `AddPatientCommand` performs.

**Step 1.** The user executes `addpatient [input all attributes of Patient]` command to add a patient to Covigent. An `AddPatientCommandParser` object is created and the `AddPatientCommandParser#parse(String args)` method is called, which helps to parse the different attributes of `Patient`. The parse method returns a new `AddPatientCommand` object and the `AddPatientCommand` object stores the `Patient` to be added.

**Step 2.** The `Patient` to be added is then searched through `UniquePatientList#internalList`using the `Model#hasPatient(Patient patient)` method to check if the patient already exists. If the patient already exists, a `CommandException` object will be thrown with an error message.

**Step 3.** Through `Model#addPatient(Patient toAdd)`, the `Patient` will be added to `UniquePatientList`.

**Step 4.** A success message with the new patient details will be appended with the `AddPatientCommand#MESSAGE_SUCCESS` constant. A new `CommandResult` will be returned with the message.

The sequence diagram for a successful execution of `AddPatientCommand` can be found below.

      Figure 16. Sequence Diagram for AddPatientCommand

:information_source: **Note:** Due to space limitation in PlantUML diagram, the addpatient command example given in the sequence diagram only consists of two patient attributes, name and age.

_Written by Yun Qing_

**Implementation of EditPatientCommand**
The following is a detailed explanation of the operations that `EditPatientCommand` performs.

**Step 1.** The `EditPatientCommand#execute(Model model)` method is executed and it checks if the `Name` defined when instantiating
`EditPatientCommand(Name patientToBeEdited, EditPatientDescriptor editPatientDescriptor)` is valid. The `EditPatientDescriptor` holds
the edited information of the `Patient`.

**Step 2.** A new `Patient` with the updated values will be created and the patient is then searched through `UniquePatientList#internalList`
using the `Model#hasPatient(Patient patient)` method to check if the patient already exists. If the patient already exists,
`CommandException` will be thrown with an error message.

**Step 3.** The newly created `Patient` will replace the existing patient object through the `Model#setPatient(Patient target, Patient editedPatient)`
method.

**Step 4.** A success message with the edited patient will be appended with the `EditPatientCommand#MESSAGE_EDIT_PATIENT_SUCCESS` constant. A
new `CommandResult` will be returned with the message.

_Written by Ming De_

#### 4.1.5 Search

The following is a detailed explanation of the operations that `SearchPatientCommand` performs.

**Step 1.** The `SearchPatientCommand#execute(Model model)` method is executed and checks the `criteriaToSearch` via `confirmCriteria(SearchPatientDescriptor searchPatientDescriptor)`.
The `SearchPatientDescriptor` holds the `name` or `temperatureRange` of the Command.

**Step 2.** If the `criteriaToSearch` is `SearchCriteria.CRITERIA_NOT_FOUND`, `CommandException` will be thrown with an error message.

**Step 3.** If the `criteriaToSearch` is `SearchCriteria.CRITERIA_IS_NAME`, we update the `Model`'s `FilteredPatientList` Predicate via `updateNamePredicate(Model model, SearchPatientDescriptor searchPatientDescriptor)`
Then `findPatientWithName(SearchPatientDescriptor searchPatientDescriptor, List<Patient> patientList)` will go through `Model`'s `FilteredPatientList`, if no patient is found, `CommandException` will be thrown with an error message. If there is at least one patient found, a new `CommandResult` will be returned with the message.

**Step 4.** If the `criteriaToSearch` is `CRITERIA_IS_TEMPERATURE`, we update the `Model`'s `FilteredPatientList` Predicate via `updateTemperaturePredicate(Model model, SearchPatientDescriptor searchPatientDescriptor)`
Then `findPatientWithTemperature(SearchPatientDescriptor searchPatientDescriptor, List<Patient> patientList)` will go through `Model`'s `FilteredPatientList`, if no patient is found, `CommandException` will be thrown with an error message. If there is at least one patient found, a new `CommandResult` will be returned with the message.

**Step 5.** If the `criteriaToSearch` is `TOO_MANY_CRITERIA` A new `CommandResult` will be returned with the message.
method.

_Written by Wai Lok_

### 4.2 Room Feature

#### 4.2.1 Overview
The application is able to track the room details. It keep tracks of the whether a room is occupied and the patient inside the room if it is occupied.
It also keeps track of the tasks assigned to a specific room. Hence, there is a need to represent the Room List as a list of Rooms on which the application can perform read and update operations.

#### 4.2.2 Implementation

The class diagram for RoomList is shown below.

      Figure 17. Class diagram for RoomList

From the diagram above, the `RoomList` contains of one `UniqueRoomList`. This `UniqueRoomList` is a wrapper class around the `RoomList`
which contains an ObservableList of `Patient` and PriorityQueue of `Patient`. The `RoomList` can contain from about 1 to 500 rooms.

Each Room contains the following member attributes, all of which are non-nullable attributes:
1. **roomNumber**
This gives the room number of the Room object
2. **isOccupied**
This gives the information of whether the Room is occupied or not. If there is a `Patient` inside the `Room`, then the isOccupied is true, else false
3. **patient**
This gives the patient details and it is stored as an Optional object. If there is no `Patient`, then the Optional.empty() is assigned.
4. **tasks**
This gives all the tasks that are assigned to a specific room. The number of tasks assigned can be zero.

The proposed room feature is facilitated by `RoomList`. It extends `ReadOnlyRoomList` which reads the Room information Json file, stored internally as an `addressBookStateList` and `currentStatePointer`. Additionally, it implements the following operations:
* `RoomList#addRooms(int num)` — adds the number of which are said to add together and retains infromation previously stored in each room
* `RoomList#containsRoom(Room toCehck)` - checks whether the given room exists
* `RoomList#clearRoom(Name patientName)` - removes patient from the room
* `RoomList#setSingleRoom(Room target, Room editedRoom)` - sets the editedRoom to the target room

These operations are exposed in the `Model` interface as `Model#addRooms(int num)`, `Model#hasroom(Room room)`, `Model#clearRoom(Name patientName)` and `Model#setSingleRoom(Room target, Room editedRoom)` respectivley.

_Written by Noorul Azlina_

The GUI for room feature is based on a `ListView` that updates whenever the `RoomList` is updated and a `scroll pane` that
displays the details of the room. To ensure that the information displayed in the `scroll pane` is updated dynamically,
we employ the use of `Listeners` that listens for changes and notify the `scroll pane` to update.

_Written by: Ming De_

#### 4.2.3 Design Considerations
**Aspect: Decision on allowing `editRoomCommand` that allows changing of room number to remain**

* Option 1: Do not change the `editRoomCommand`
Allowing the users to change room numbers will give the user more power in customising the rooms. However, this option introduced a bug into the system
that could not be easily resolved unless we changed our entire implementation of `InitRoomCommand`.

* Option 2: Remove `editRoomCommand` ability to change room number and rename it to `AllocateRoomCommand`
Removing the `editRoomCommand` to change room number is much more time-efficient compared to changing the entire implementation of `InitRoomCommand`. We
also decided that there should be no reason that a user would need to change the room number. Renaming the method to `AllocateRoomCommand` would provide
more clarity for the method.

Ultimately, we decided on Option 2. This is because keeping `editRoomCommand` would lead to a large consumption of time to redesign the system. In order
to not stray from our schedule, we have to remove `editRoomCommand` to ensure that we can develop the other features on time.
Furthermore, to solve the bug that was introduced, we would have to store the count of the number of times `InitRoomCommand` was called. This would
cause us to store information in another `.json` file which is unnecessary. Therefore, we decided that the forgoing a
small function like this would be a better choice.

_Written by Ming De_

##### Feature related to Room

The features comprise of five commands namely,
* `InitRoomCommand` - Initializes the number of rooms in Covigent app.
* `ListRoomCommand` - Lists all the rooms in Covigent app.
* `AllocateRoomCommand` - Allocates a patient to a room.
* `SearchRoomCommand` - Searches for the room with the specified room number.
* `FindEmptyRoomCommand` - Finds an empty room with the lowest room number.

We will illustrate the progress of two of the above commands for simplicity.

#### 4.2.4 Create, Read, Update

**Implementation of InitRoomCommand**

The following is a detailed explanation of the operations that `InitRoomCommand` performs.

**Step 1.** The `InitRoomCommand#execute(Model model)` method is executed and it check if the `Integer`defined when instantiating
If it is a positive integer and the number of rooms is more than or equal to the existing number of occupied rooms, InitRoomCommand is valid.
The checking of the number of rooms is done by `Model#hasSpaceForRooms()`. If this is true then `Integer` is valid, else it is invalid.

**Step 2.** The stated number of rooms is then set to `Integer`, if `Integer` is greater than the existing number of rooms then excess rooms are added to the back of the
UniqueRoomList. If the number of rooms is less than the `Integer` and there are occupied rooms the information of patients in that room is transferred to an empty room
in the reduced number of rooms

**Step 4.** A success message with the `Intger` appended with the `InitRoomCommand#MESSAGE_SUCCESS` constant is displayed on the UI. A new `CommandResult`
returns this message.

The activity diagram below illustrates the `initRoom`.

      Figure 18. Activity diagram for initRoom

The Sequence Diagram for `initRooms` is shown below.

      Figure 19. Sequence diagram for initRoom

  _Written By: Noorul Azlina_

**Implementation of AllocateRoomCommand**

The following is a detailed explanation of the operations that `AllocateRoomCommand` performs.

**Step 1.** The `AllocateRoomCommand#execute(Model model)` method is executed and it checks if the `Integer` defined when instantiating
`AllocateRoomCommand(Integer roomNumberToAllocate, AllocateRoomDescriptor AllocateRoomDescriptor)` is valid. This is done using the `Model#getRoomWithRoomNumber` method
 where it is used to get an `Optional<Room>`. If `Optional<Room>` is empty, the `Integer` is not valid.
 The `AllocateRoomDescriptor` holds the information of the `Room` with the patient allocated.

**Step 2.** A new `Room` with the allocated patient will be created and the room is then searched through `RoomList#internalList`
using the `Model#hasRoom(Room room)` method to check if a room with the same room number exists. If it already exists,
`CommandException` will be thrown with an error message.

**Step 3.** The newly created `Room` will replace the existing room object through the `Model#setSingleRoom(Room target, Room editedRoom)`
method.

**Step 4.** A success message with the allocated room will be appended with the `AllocateRoomCommand#MESSAGE_ALLOCATE_ROOM_SUCCESS ` constant. A
new `CommandResult` will be returned with the message.

The activity diagram below illustrates `allocateRoomCommand`.

      Figure 20. Activity Diagram for AllocateRoomCommand

The sequence diagram for `AllocateRoomCommand` is shown below.

      Figure 21. Sequence Diagram for AllocateRoomCommand

_Written by Mingde_

### 4.3 Task Feature

#### 4.3.1 Overview
The task feature in Covigent allows hotel staff to manage and organize time-critical work related to a room in a quarantine facility.
Every room can be allocated any number of tasks, with each task keeping track of the description of the work and a due date by which
it should be completed.

It is important to note that Covigent handles tasks on a per-room basis. Tasks not specific to any room (e.g. tasks related to the operations
of the quarantine facility) are out of scope.

The task feature in Covigent includes the following:

* Adding a task to a room
* Displaying all tasks in the user interface
* Editing the description and due date of a task
* Removing a task from a room
* Filtering tasks based on a criterion and displays the filtered tasks in the user interface (currently on supports filtering by due date)

#### 4.3.2 Implementation
At a higher level, tasks share a composition type relationship with rooms. That is, if a room is deleted, all tasks in that room are similarly deleted.
We have implemented the task feature based on the class diagram in Figure 22.

      Figure 22. Class Diagram for Task

Each `Room` contains a `RoomTasks` class, which is a wrapper around `TaskList`.

Task-related operations that alter the tasks in a `Room` must be performed through that `Room`.
The API calls for these operations first proceed to `Room`, which redirects them to `RoomTasks`. To enforce this constraint, `RoomTasks` is not publicly exposed in the API for `Room`
(i.e. there is no getter for `RoomTasks` in `Room`).

`TaskList` emulates the other `List` classes in Covigent such as `UniquePatientList` and `UniqueRoomList`, exposing only an unmodifiable `ObservableList<Task>`.
This `ObservableList<Task>` is subsequently returned by `RoomTasks` in the `getReadOnlyList()` method to fulfill its contract with the `ReadOnlyList<Task>` interface.

#### 4.3.3 Design Considerations

**Aspect: Retrieving list of tasks from `Room`**

* Option 1: Supplying a getter for `RoomTasks` in `Room`

Having a `getRoomTasks()` method to retrieve all the tasks in `Room` greatly enhances convenience, especially when copying the information from one `Room` to another.
This is because we can use the constructor of `Room` in this manner: `Room copyOfRoom = new Room(..., originalRoom.getRoomTasks()))` (`...` refers to other attributes of `Room` that need to be passed into constructor).
It is a quick way to transfer tasks between `Room`.

However, this option is not optimal from a defensive programming perspective. Because a client can retrieve `RoomTasks` from `Room`, there is potential for abuse.
The `RoomTasks` object may be passed to some other classes that are not `Room`. Consequently, there is no guarantee that a client will not circumvent `Room` and call an operation that changes its tasks such as `addTask(Task)` directly from `RoomTasks`.
This destroys the abstraction barrier of `Room` as clients can modify the tasks in it via external means.

* Option 2: Add a `getReadOnlyTasks()` method in `Room` to retrieve an unmodifiable list of tasks from `RoomTasks`

We chose option 2 for Covigent as we thought it was the safer option. Since `RoomTasks` implements `ReadOnlyList<Task>`, `Room` can retrieve and expose it via a `getReadOnlyTasks()` method for clients to access the tasks.
This is more secure from a defensive programming perspective and respects the abstraction barrier. Without the getter for `RoomTasks`, clients are only allowed to change the tasks in `Room` via its API.
It ensures that the tasks in a `Room` are not modified without knowledge of `Room`, while providing the flexibility for clients to access the information in them.
An additional benefit of this option is that it obscures the fact that `Room` depends on `RoomTasks` for its task-related operations, thus strengthening the composition type relationship between tasks and rooms.

With option 2, the operation for copying tasks from one `Room` to another can be performed as such: `Room copyOfRoom = new Room(..., new RoomTasks(originalRoom.getReadOnlyTasks()))`.
It is probably better for the constructor of `Room` to take in `List<Task>` instead of `RoomTasks` to completely hide the existence of `RoomTasks` from clients.
This can be considered as part of the improvements to be made to Covigent in the future.

A downside of this option is that the implementor (future programmers of Covigent) must be aware of this design decision and avoid exposing `RoomTasks` through the public API of `Room`.
Moreover, there is a slight increase in complexity now that `RoomTasks` has to implement `ReadOnlyList<Task>`.

**Aspect: Storing a list of tasks in `Room`**

* Option 1: Using `List<Task>` in `Room`

This option is simple as it does not require any additional classes. However, `Room` has to handle all task-related operations, which violates the single-responsibility principle.
Conceptually, we consider `Room` to be a container for a patient and tasks. It should not contain implementations of methods related to patients and tasks.

* Option 2: Using `TaskList` in `Room`

While entirely possible to use `TaskList` to store the tasks in `Room` (see Figure 23), we cannot be certain that `TaskList` will not be used elsewhere in `Covigent` in the future.

      Figure 23. Class Diagram for Task using TaskList

For instance, suppose we want to support a list of tasks for specific patients (instead of rooms). It may not make much sense to use `TaskList` for both patients and rooms as they can have different behaviors.
Perhaps a maximum of 5 tasks can be assigned to each patient, while there is no limit to the number of tasks that can be assigned to each room.
Taking that into consideration, we decided to add a wrapper class.

* Option 3: Using an extra class in addition to `TaskList`

We chose option 3 and added a new class `RoomTasks` to `Room`. `RoomTasks` is a wrapper around `TaskList` to support room-specific behavior associated with tasks.
A simple example is how we can set a maximum number of tasks each `Room` can hold through `RoomTasks` without modifying `TaskList`. In that sense, option 3 respects the open-closed principle.

An alternative is to use a new class that extends from `TaskList`. This would improve polymorphism as methods that work with `TaskList` will also work with the new class.
However, Liskov substitution principle might be a concern. For instance, if `TaskList` allows an unlimited number of tasks to be stored but `RoomTasks` only allows 500, it would be a violation of Liskov substitution principle.
As such, we did not choose this alternative.

The disadvantage of using another class is the added complexity as API calls for task-related operations need to be routed from the new class to `TaskList`.

#### 4.3.4 Create, Read, Update, Delete
In this section, we will cover the implementation of the manipulation of `Task` data. The commands that allow the task-related operations of creating, reading, updating, and deleting of `Task` are `AddTaskCommand`, `ListTaskCommand`, `EditTaskCommand`, and `DeleteTaskCommand` respectively.

The actual manipulation of `Task` data is performed in the `TaskList` class. Some significant methods within `TaskList` that allows the manipulation of `Task` data are shown below:

* `TaskList#add(Task toAdd)` - Adds a `Task` to `TaskList`.
* `TaskList#setTask(Task target, Task editedTask)` - Replaces a `Task` in `TaskList` with the edited `Task`.
* `TaskList#remove(Task toRemove)` - Removes a `Task` from `TaskList`.
* `TaskList#asUnmodifiableObservableList()` - Returns a read-only list containing all `Task` in `TaskList`.
* `RoomTasks#getTaskWithTaskIndex(Index index)` - Returns the `Task` with the `Index` in the `TaskList`. This method is currently in `RoomTasks` but can be safely refactored into `TaskList`.

These methods in `TaskList` class support the corresponding methods in `RoomTasks`. For clients to perform these operations, `Room` exposes `addTask(Task task)`, `setTask(Task task, Task editedTask)`, and `deleteTask(Task task)` in its public API.
Calls to these APIs are redirected to `RoomTasks` and eventually `TaskList`.

Since the commands do not directly interact with `Room` but rather the `Model`, the `Model` interface has to expose `addTaskToRoom(Task task, Room room)`, `deleteTaskFromRoom(Task task, Room room)` and `setTaskToRoom(Task task, Task editedTask, Room room)`.

For brevity's sake, we will only illustrate the implementation of the most complex command, `EditTaskCommand`.

**Implementation of EditTaskCommand**

The following is an explanation of the operations that `EditTaskCommand` performs, with the higher level details (`LogicManager` and `CovigentAppParser`) omitted for simplicity.

**Step 1.** The user executes `edittask [room number] [task index] [other attributes to edit]` command to edit the description of a `Task` in a `Room`. An `EditTaskCommandParser` object is created and the `EditTaskCommandParser#parse(String args)` method is called, which helps to parse the different attributes of `Task`. The parse method returns a new `EditTaskCommand` object with the room number, task index, and a descriptor containing the updated values to replace the original.

**Step 2.** The `Room` is retrieved from the list of rooms in Covigent using the `Model#getRoomWithRoomNumber(int roomNumber)` method. If no such `Room` exists, a `CommandException` object will be thrown with an error message.

**Step 3.** The `Task` is retrieved from `RoomTasks` of `Room` using the `Model#getTaskFromRoomWithTaskIndex(Index taskIndex, Room room)` method. If no such `Task` exists, a `CommandException` object will be thrown with an error message.

**Step 4.** The `Task` is edited in `EditTaskCommand` and replaces the original `Task` the room with `Model#setTaskToRoom(Task target, Task editedTask, Room room)`.

**Step 5.** A success message with the new task details will be appended with the `EditTaskCommand#MESSAGE_SUCCESS` constant. A new `CommandResult` will be returned with the message.

The sequence diagram for `EditTaskCommand` can be found below.

      Figure 24. Sequence Diagram for EditTaskCommand

_Written by Yee Hong_

#### 4.3.5 Search

The following is a detailed explanation of the operations that `SearchTaskCommand` performs.

**Step 1.** The `SearchTaskCommand#execute(Model model)` method is executed and it gets information of `task` from each `room` in the `roomList`.

**Step 2.** If the `task` has a `duedate` before the `duedate` from user command, it is stored in `taskListWithDesirableResult`.

**Step 3.** If no `task` is found, `CommandException` will be thrown with an error message.

**Step 4.** If there is at least one task found, the `model`'s `filteredRoomTaskRecords` is updated with a `dueDatePredicate` using `updateTasksInFilteredRoomTaskRecords`.

**Step 5.** a new `CommandResult` will be returned with the message.

_Written by Wai Lok_

### 4.4 Logging Feature

We are using `java.util.logging` package for logging. The `LogsCenter` class is used to manage the logging levels and logging destinations.

* The logging level can be controlled using the `logLevel` setting in the configuration file (See [Section 4.5, "Configuration Features"](#45-configuration-feature))
* The `Logger` for a class can be obtained using `LogsCenter.getLogger(Class)` which will log messages according to the specified logging level
* Log messages are output through: `Console` and to a `.log` file

**Logging Levels**:
* `SEVERE` : Critical problem detected which may possibly cause the termination of the application
* `WARNING` : Can continue, but with caution
* `INFO` : Information showing the noteworthy actions by the App
* `FINE` : Details that is not usually noteworthy but may be useful in debugging e.g. print the actual list instead of just its size

_Written by Ming De_

### 4.5 Configuration Feature

Certain properties of the application can be controlled (e.g user prefs file location, logging level) through the configuration file (default: `config.json`).

--------------------------------------------------------------------------------------------------------------------

## 5. Planned Features

This section describes the features planned for the next iteration of Covigent.

### 5.1 Single Command to Create and Allocate Patient to Room

When the user wants to assign a patient to a room, she must run 2 commands: `addpatient` and `allocateroom`. The former creates a new `Patient` object in Covigent and the latter assigns that `Patient` to an empty room.
To improve the user's productivity, we can allow the user to specify a room number when executing `addpatient`. If the room and patient are valid, the patient is added to Covigent and assigned to the room in a single command.

Since these changes will add another layer of complexity, we plan to complete this feature in Covigent v1.5.

### 5.2 Search for Task by Description

The `searchtask` command allows searching for tasks only by due dates. A user with many tasks would most likely want to search for tasks by description.

In addition to modifying `SearchTaskCommand` and `SearchTaskCommandParser`, a new class `DescriptionPredicate` might have to be introduced to filter the tasks by description.
Considering these additional changes, we plan to complete this feature in Covigent v1.5.

### 5.3 Scroll to Modified Task in User Interface

Whenever a user adds or edits a `Patient` or `Room`, the Patients and Rooms tabs in the user interface scrolls to the entry corresponding to the most recent change.
This is useful as the user can immediately review the latest modification on the user interface. To accomplish this, `PatientListPanel` and `RoomListPanel` attach a listener to `ListView<Patient>` and `ListView<Room>` respectively to update the user interface when changes are detected.

Currently, when the user modifies a `Task`, the user interface does not scroll to the latest change. The reason is that the current implementation of the Tasks tab retrieves the room and task details from a `ListView<RoomTaskAssociation>`, as seen in `RoomTaskListPanel`.
The underlying list for `ListView<RoomTaskAssociation>`, found in `RoomTaskRecords` is altered each time there are changes to a room, including not only the tasks but also the room itself and the patient in it.
Hence, the list is unable to distinguish between modifications to tasks, to rooms, or to patients in rooms. Since we do not want the user interface for `Task` to scroll when there are changes to `Room` or `Patient`, we have disabled the listener for `ListView<RoomTaskAssociation>`.

Fixing this issue likely requires a significant overhaul of the implementation of the Tasks tab. We plan to complete this feature in Covigent v2.0.

_Written by Yee Hong_

--------------------------------------------------------------------------------------------------------------------

## 6. Documentation

* [Documentation guide](Documentation.md)
* [Testing guide](Testing.md)
* [Logging guide](Logging.md)
* [Configuration guide](Configuration.md)
* [DevOps guide](DevOps.md)

--------------------------------------------------------------------------------------------------------------------

## 7. Appendix

### A1. Product scope

**Target user profile**:
* Needs to manage a significant number of patients and their tasks
* Needs to manage a significant number of rooms
* Wants to keep track of patients and their tasks efficiently
* Wants to look up patients, rooms and tasks details quickly
* Prefers desktop apps over other types
* Prefers typing to mouse interactions
* Prefers all information to be available at one place
* Can type fast
* Is reasonably comfortable using Command Line Interface (CLI) apps

**Value proposition**:
* Covigent is a handy tool for quarantine facility managers to manage the rooms and patients in the quarantine facility with increased productivity.
* Covigent stores and retrieves information faster than a typical mouse/GUI driven app.

### A2. User stories

Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*`

| Priority | As a …                                    | I want to …                     | So that I can…                                                        |
| -------- | ------------------------------------------ | ------------------------------ | ---------------------------------------------------------------------- |
| `* * *`  | staff of a quarantine facility       | key in new patient information | keep track of the information of new patients in the facility |
| `* * *`  | staff of a quarantine facility       | edit patient information       | update his/her health status                                                                |
| `* * *` | staff of a quarantine facility | delete the records of patients who no longer resides in the facility | focus on information of existing patients residing in the facility|
| `* * *`  | staff of a quarantine facility       | view which rooms are empty     | allocate patients to them |
| `* * *`  | staff of a quarantine facility       | allocate patients to room     |keep track of which room they are living in|
| `* * *`  | staff of a quarantine facility | quickly find the room that a patient is staying in | locate the patient in the facility easily |
| `* * *`  | staff of a quarantine facility       | key in new task information    | keep track of the details of the tasks that I must complete                                  |
| `* *`  | staff of a quarantine facility | quickly find the room details of a given room number | track the patient and tasks in that room easily |
| `* *`    | staff of the quarantine facility     | indicate that I have completed the task in the room | let other staff know that they no longer have to handle them|
| `* *`    | staff of a quarantine facility | find out all the outstanding tasks left in each room |  serve the quarantined individuals better                                               |
| `* *` | staff of a quarantine facility | quickly search through patient information | find the patients that match my criteria|
| `* *` | staff of a quarantine facility | look at all the rooms| find out which rooms are occupied and which are not |
| `* *`| staff of a quarantine facility | initialise the number of rooms many times with previous information retained | define correct number of rooms if mistake is made I can correct it without having to tediously key in information again|
|`* * `| staff of a quarantine facility | find out an empty room | to allocate patient to that empty room easily without having to search through the rooms for an empty room |
| `* * `| careless staff of a quarantine facility | edit a task | to allow for me to easily change a mistake that I made while adding tasks |
| `* * `| forgetful staff of a quarantine facility | search a task | to allow for me to easily search for a task that end before a certain due date |

### A3. Use cases

(For all use cases below, the **System** is `Covigent` and the **Actor** is `Hotel Staff`, unless specified otherwise. In addition, due to limitation in Github markdown, for use cases which include another use case, there will be no underlining of text.)

**Use case: UC01 Add a patient**

**MSS**

1. Hotel Staff requests to add a patient into Covigent.
2. Covigent adds the patient.
3. Covigent shows the details of the newly added patient.

Use case ends.

**Extensions**
* 2a. Covigent realises that the patient name already exists.
    * 2a1. Covigent displays an error message.

Use case ends.

* 2b. Covigent realises that the patient information being entered does not conform to the system format.
    * 2b1. Covigent displays an error message.

Use case ends.

**Use case: UC02 Delete a patient**

**MSS**

1. Hotel Staff requests to delete a patient from Covigent.
2. Covigent deletes the patient and removes the patient from the room he/she is residing in.
3. Covigent shows the details of the deleted patient.

Use case ends.

**Extensions**
* 2a. Covigent realizes the patient does not exist.
    * 2a1. Covigent displays an error message.

Use case ends.

**Use case: UC03 Edit a patient**

**MSS**

1. Hotel Staff inputs the new information about the patient.
2. Covigent edits the patient information to the new information.
3. Covigent shows the details of the edited patient.

Use case ends.

**Extensions**
* 1a. Covigent realizes that no optional fields are input.
   * 1a1. Covigent displays an error message.

Use case ends.

**Use case: UC04 Search for a patient**

**MSS**

1. Hotel Staff requests to search patients with a criterion.
2. Covigent searches the patients with the input criteria.
3. Covigent shows the search results.

Use case ends.

**Extensions**
* 2a. Covigent realizes that no such patient is recorded
   * 2a1. Covigent displays an error message.

Use case ends.

**Use case: UC05 Allocate a patient to a room**

**MSS**

1. Hotel Staff adds a patient to Covigent (UC01).
2. Hotel Staff requests to allocate the patient to a specified room.
3. Covigent adds the patient to the specified room.

Use case ends.

**Extensions**
* 2a. Covigent realizes that the specified room does not exist.
    * 2a1. Covigent displays an error message.

Use case ends.

* 2b. Covigent realizes that the specified room is not empty.
   * 2b1. Covigent displays an error message.

Use case ends.

**Use case: UC06 List all rooms**

**MSS**

1. Hotel Staff requests to list all the rooms in quarantine facility.
2. Covigent lists all the rooms in the hotel and whether they are occupied or unoccupied.

Use case ends.

**Extensions**
* 1a. Covgient realizes that there are no rooms existing.
   * 1a1. Covigent displays an error message.

Use case ends.

**Use case: UC07 Find empty room**

**MSS**

1. Hotel Staff requests to search for an empty room to accommodate patient.
2. Covigent finds an empty room.
3. Covigent shows the room to Hotel Staff.

Use case ends.

**Extensions**
*  1a. Covigent realizes that there are no rooms.
    * 1a1. Covigent displays an error message.

Use case ends.

*  1b. Covigent realizes that there are no empty rooms.
    * 1b1. Covigent displays an error message.

Use case ends.

**Use case: UC08 Initialize rooms**

**MSS**

1. Hotel Staff requests to change number of rooms.
2. Hotel Staff inputs the number of rooms to change into.
3. Covigent changes the number of rooms in the system.
4. Covigent displays all the current rooms.

Use case ends.

**Extensions**
* 2a. Covigent realizes that the Hotel Staff inputs an invalid number.
   * 2a1. Covigent displays an error message.

Use case ends.

* 2b. Covigent realizes that the number of rooms input is less than number of occupied room
   * 2b1. Covigent displays an error message.

Use case ends.

**Use case: UC09 Search for a room**

**MSS**

1. Hotel Staff requests to search for a room with the given patient.
2. Hotel Staff inputs the name of the patient to find the corresponding room.
3. Covigent displays the room details that the patient resides in.

Use case ends.

**Extensions**
* 2a. Covigent realizes that the patient does not exists in the system.
    * 2a1. Covigent displays an error message.

Use case ends.

* 2b. Covigent realizes that the patient is not allocated to any room.
    * 2b1. Covigent displays an error message.

Use case ends.

**Use case: UC10 Add a task to a room**

**MSS**

1. Hotel Staff requests to add a task to a room.
2. Covigent adds the task to the room.

Use case ends.

**Extensions**
* 1a. Covigent realizes that the specified room does not exist.
    * 1a1. Covigent displays an error message.

Use case ends.

**Use case: UC11 Delete a task from a room**

**MSS**

1. Hotel Staff requests to delete a task from a room.
2. Covigent deletes the task from the room.

Use case ends.

**Extensions**
* 1a. Covigent realizes that the specified room does not exist.
     * 1a1. Covigent displays an error message.

 Use case ends.

 * 1b. Covigent realizes that the specified task does not exist.
     * 1b1. Covigent displays an error message.

 Use case ends.

**Use case: UC12 Edit a task in a room**

**MSS**

1. Hotel Staff inputs the new information about the task.
2. Covigent edits the task information to the new information.
3. Covigent shows the details of the edited task.

Use case ends.

**Extensions**
* 1a. Covigent realizes that no optional fields are input.
    * 1a1. Covigent displays an error message.

 Use case ends.

 * 1b. Covigent realizes that the specified room does not exist.
     * 1b1. Covigent displays an error message.

 Use case ends.

 * 1c. Covigent realizes that the specified task does not exist.
     * 1c1. Covigent displays an error message.

 Use case ends.

 * 1d. Covigent realizes that the new information for the task is the same as the original.
    * 1d1. Covigent displays an error message.

 Use case ends.

**Use case: UC13 Search Task**

**MSS**

1. Hotel Staff requests to search for a task before a specific date.
2. Hotel Staff inputs the specific date.
3. Covigent searches for tasks before the specific date.
4. Covigent displays the tasks before the specific date and success message.

Use case ends.

**Extensions**
* 2a. Covigent realizes that the format of the date is incorrect.
    * 2a1. Covigent displays an error message.

Use case ends.

* 3a. Covigent realizes that there is no task matching the criteria.
    * 3a1. Covigent displays an error message.

Use case ends.

### A4. Non-Functional Requirements

1. Should work on any _mainstream OS_ as long as it has Java `11` or above installed.
1. Should be able to hold up to 100 patients without a noticeable sluggishness in performance for typical usage.
1. 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.
1. Should work even without internet connection.
1. Should respond to commands within 3 seconds.

### A5. Glossary

* **Mainstream OS**: Windows, Linux, Unix, OS-X
* **Patient**: An individual residing in the quarantine facility
* **Task**: Task is to be completed by staff of the quarantine facility

## A6. Instructions for manual testing

Given below are instructions to test the app manually.

:information_source: **Note:** These instructions only provide a starting point for testers to work on;
testers are expected to do more *exploratory* testing.

### Launch and shutdown

1. **Initial Launch**

   1. Download the jar file and copy into an empty folder

   1. Double-click the jar file

   **Expected**: Shows the GUI with a set of sample patients.

1. **Saving Window Preferences**

   1. Resize the window to an optimum size. Move the window to a different location. Close the window.

   1. Re-launch the app by double-clicking the jar file.

   **Expected**: The most recent window size and location is retained.

1. **Storage**

   1. Launch the application and make a change that changes the state of the program, such as `addpatient` or `initroom`. Close the window.

   1. Re-launch the app by double-clicking the jar file.

   **Expected**: The app should re-launch into the same state as when it was closed.

### Adding a patient

1. **Adding a patient to Covigent**

   1. Prerequisites: User is viewing the patient tab.

   1. Test case: `addpatient n/John Doe t/37.0 d/20200101-20200114 p/91234567 a/22`

      **Expected**: Patient John Doe is added to the list. Details of the newly added patient is shown in the result box and the details panel.

   1. Test case: `addpatient n/John Doe`

      **Expected**: No patient is added. Error details shown in the result box.

   1. Other incorrect add patient commands to try: `addpatient n/John Doe t/37.0 d/20200101-20190114 p/91234567 a/22`

      **Expected**: Similar to previous.

### Saving data

1. **Dealing with missing data files**

   1. Run the app once and play around with the application. Once a change is made, the program will generate a data files in `./data/`.

   1. In `./data/`, delete `covigentapp.json` and `roomInformation.json`.

   1. Re-launch the app.

   **Expected**: Default Patient information should now be present in the Patient tab. No Rooms present in Room tab.

1. **Corrupted data files**

    1. Run the app once and play around with the application. Once a change is made, the program will generate a data files in `./data/`.

    1. In `./data/`, open `covigentapp.json`. On line 2, delete the `[`:

        ```
        1 {
        2   "patients" : [ {
        3 ...
       ```
       should become

       ```
       1 {
       2   "patients" : {
       3 ...
        ```
   1. Re-launch the app.

   **Expected**: Go to the Patient tab and the tab should not have any data. `covigentapp.json` still exists.


text:
storm-devenv
============

storm-devenv make it easy to construct storm cluster for development and QA.

# Prerequisites

* [Vagrant](https://www.vagrantup.com/)
* [Oracle VirtualBox](https://www.virtualbox.org/)
* [vagrant-aws](https://github.com/mitchellh/vagrant-aws)

Please install these software in advance.

# Setup

```
$ git clone git@github.com:Lewuathe/storm-devenv.git
```

Put your storm code on `site-cookbooks/storm/files/default` as tar format.
If you want to try official release package, you can find it [here](https://storm.apache.org/downloads.html)

```
$ wget http://www.apache.org/dyn/closer.cgi/storm/apache-storm-0.9.3/apache-storm-0.9.3.tar.gz
$ mv apache-storm-0.9.3.tar.gz site-cookbooks/files/default
```

# Launch cluster

```
$ cd storm-devenv
```

## With VirtualBox provider

```
$ export VAGRANT_CWD=./providers/virtualbox && vagrant up
```

## With AWS provider
You have to setup below configurations in environment variables first.

|key|value example|info|
|:---|:---|:---|
|AMI_ID|ami-1234abcd|Available AMI's ID|
|AWS_REGION|us-east-1|Region of EC2 instances|
|AWS_INSTANCE_TYPE|t2.micro|EC2 Instance type|
|AWS_VPC_SUBNET_ID|subnet-1234abcd|Avalable subnet ID|
|AWS_KEYPAIR_NAME|mykey-pair|Key pair name which you have|
|AWS_SECURITY_GROUPS|sg-1234abcd|Available security group|
|AWS_ACCESS_KEY_ID|abcdefg1234567|You AWS access key ID|
|AWS_SECRET_ACCESS_KEY|ABCDEFG1234567|Your AWS secret access key|
|AWS_PRIVATE_KEYPATH|/Users/yourname/.ssh/key.pem|The full path of your AWS key pair|

```
$ export VAGRANT_CWD=./providers/aws && vagrant up
```

# Submit Topology

Write your own storm.yaml file `~/.storm/storm.yaml`

```~/.storm/storm.yaml
nimbus.host: "<IP_ADDRESS>"
```

If you have launched on EC2, you have to setup this as EC2 nimbus public IP which can be found your AWS dashboard.

And submit your topology. You can read more detail [here](https://storm.apache.org/documentation/Running-topologies-on-a-production-cluster.html)
```
$ storm jar path/to/allmycode.jar org.me.MyTopology arg1 arg2 arg3
```

# Check UI

You can see your cluster UI on [http://<IP_ADDRESS>:8080](http://<IP_ADDRESS>:8080/index.html)

# License

MIT License. Please see the LICENSE file in details.

# Future works

* Make it easy to change storm version
* Separate storm cookbook as a distinct chef cookbook.

license: MIT

repository: Lewuathe/storm-devenv

branch_name: refs/heads/master

extension: md

gha_language: Ruby

license_type: permissive

repo_name: Lewuathe/storm-devenv


text:
# MiniPhone

A Ruby gem which plugs directly into Google's native C++
[libphonenumber](https://github.com/google/libphonenumber) for extremely
_fast_ and _robust_ phone number parsing, validation, and formatting. On
average, most methods are 70x to 80x faster than other Ruby phone number
libraries.

## Usage

### Checking if a phone number is valid

```ruby
MiniPhone.valid?('+14043841399')                     # true
MiniPhone.valid_for_country?('(404) 384-1399', 'US') # true
MiniPhone.valid_for_country?('(404) 384-1399', 'GB') # false
```

### Formatting a number

```ruby
MiniPhone.default_country = 'US'

phone_number = MiniPhone.parse('404-384-1399')

phone_number.e164                 # +14043841399
phone_number.national             #<PHONE_NUMBER>
phone_number.raw_national         #<PHONE_NUMBER>
phone_number.dasherized_national  #<PHONE_NUMBER>
phone_number.international        # +1<PHONE_NUMBER>
phone_number.rfc3966              # tel:+1-404-384-1384
```

### Checking if a phone number is possible

```ruby
phone_number = MiniPhone.parse('-12')

phone_number.possible? # false
```

### Getting the type of a phone number

```ruby
MiniPhone.parse('+12423570000').type # :mobile
MiniPhone.parse('+12423651234').type # :fixed_line
```

The possible types are directly mapped from [this
enum](https://github.com/google/libphonenumber/blob/4e9954edea7cf263532c5dd3861a801104c3f012/cpp/src/phonenumbers/phonenumberutil.h#L91):

```ruby
:fixed_line
:mobile
:fixed_line_or_mobile
:toll_free
:premium_rate
:shared_cost
:voip
:personal_number
:pager
:uan
:voicemail
:unknown
```

## Compatibility with PhoneLib

MiniPhone aims to be compatible with
[Phonelib](https://github.com/daddyz/phonelib). In many cases it can be a
drop in replacement. It has a smaller feature set, so it is not a
replacement for every use case. If there is a feature you need, open
an issue and we will try to support it.

## Benchmarks

On average, most methods are 40x to 50x faster than other libraries. To run
the benchmarks locally, execute: `bundle exec rake bench`

```
# Results from my Linux (5.10.6-arch1-10)

Comparison:
    Phonelib: valid?:      426.0 i/s
   MiniPhone: valid?:    34707.9 i/s - 81.47x faster

Comparison:
      Phonelib: e164:      580.3 i/s
     MiniPhone: e164:    43385.9 i/s - 74.76x faster
```

## Installation

1. Install libphonenumber

   ```sh
   brew install libphonenumber # mac
   ```

   ```sh
   apt-get install -y libphonenumber-dev # debian / ubuntu
   ```

2. Add this line to your application's Gemfile:

   ```ruby
   gem 'mini_phone'
   ```

3. And then execute:

   ```sh
   bundle install
   ```

   Or install it yourself as:

   ```sh
   gem install mini_phone
   ```

## Development

After checking out the repo, run `bin/setup` to install dependencies. Then,
run `rake spec` to run the tests. You can also run `bin/console` for an
interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run `bundle exec rake install`.
To release a new version, update the version number in `version.rb`, and then
run `bundle exec rake release`, which will create a git tag for the version,
push git commits and tags, and push the `.gem` file to
[rubygems.org](https://rubygems.org).

## Contributing

Bug reports and pull requests are welcome on GitHub at
https://github.com/ianks/mini_phone. This project is intended to be a
safe, welcoming space for collaboration, and contributors are expected to
adhere to the [code of
conduct](https://github.com/ianks/mini_phone/blob/master/CODE_OF_CONDUCT.md).

## License

The gem is available as open source under the terms of the [MIT
License](https://opensource.org/licenses/MIT).

## Code of Conduct

Everyone interacting in the MiniPhone project's codebases, issue trackers,
chat rooms and mailing lists is expected to follow the [code of
conduct](https://github.com/ianks/mini_phone/blob/master/CODE_OF_CONDUCT.md).


text:
---
title: Accessing Cells and Items
page_title: Accessing Cells and Items - RadTreeList
description: Check our Web Forms article about Accessing Cells and Items.
slug: treelist/items/accessing-cells-and-items
tags: accessing,cells,and,items
published: True
position: 1
---

# Accessing Cells and Items

There are various ways to access the different items of the RadTreeList control.The most important ones are shown below.

## Accessing TreeListDataItems and their values

You can access the RadTreeList data items either using the item events of the control(ItemCreated, ItemDataBound, ItemCommand) or by looping through its Items collection when it is available.

````C#
//e is the event argument object
if (e.Item is TreeListDataItem)
{
	TreeListDataItem item = e.Item as TreeListDataItem;
}
````
````VB.NET
If TypeOf e.Item Is TreeListDataItem Then
	Dim item As TreeListDataItem = CType(e.Item, TreeListDataItem)
End If
````

````C#
foreach (TreeListDataItem item in RadTreeList1.Items)
{
	//perform some action with the data item
}
````
````VB.NET
For Each item As TreeListDataItem In RadTreeList1.Items
	'perform some action with the data item
Next
````

Once you get hold of a certain data item, you can access its cells by using the **UniqueName**	property of the column that the cell belongs to.

````C#
TableCell cell = dataItem["ColumnUniqueName"]; //where dataItem is an object of type TreeListDataItem
````
````VB.NET
Dim cell As TableCell = dataItem("ColumnUniqueName") 'where dataItem is an object of type TreeListDataItem
````

With bound columns you can use the **Text**property to get the value of the cell.

````C#
string itemValue = cell.Text;
````
````VB.NET
Dim itemValue As String = cell.Text
````

For values in **TreeListTemplateColumns** you will need to find the control in the treelist cell (either using the **FindControl()** method or the	**Controls** collection of the cell) and extract its value.

````C#
string title = (dataItem["ColumnUniqueName"].FindControl("Label1") as Label).Text;
````
````VB.NET
Dim title As String = CType(dataItem("ColumnUniqueName").FindControl("Label1"), Label).Text
````

In case you want to access a checkbox in a TreeListCheckBoxColumn, you will be able to get hold of it through the	cell's **Controls** collection.

````C#
CheckBox chk = dataItem["Qualifies"].Controls[0] as CheckBox;
````
````VB.NET
Dim chk As CheckBox = CType(dataItem("Qualifies").Controls(0), CheckBox)
````

If you need to get hold of the expand/collapse button in the treelist data item you can do so by using FindControl()	having in mind that the button id is **"ExpandCollapseButton"**:

````C#
if (dataItem.FindControl("ExpandCollapseButton") != null)
{
	Button btn = dataItem.FindControl("ExpandCollapseButton") as Button;
}
````
````VB.NET
If Not dataItem.FindControl("ExpandCollapseButton") Is Nothing Then
	Dim btn As Button = CType(dataItem.FindControl("ExpandCollapseButton"), Button)
End If
````

## Accessing the TreeListHeaderItem

You can use the **ItemCreated** and **ItemDataBound** events Of RadTreeListto get hold of the header.

````C#
if (e.Item is TreeListHeaderItem)
{
	TreeListHeaderItem header = e.Item as TreeListHeaderItem;
	TableCell headerCell = header["ColumnUniqueName"] as TableCell;
}
````
````VB.NET
If TypeOf e.Item Is TreeListHeaderItem Then
	Dim header As TreeListHeaderItem = TryCast(e.Item, TreeListHeaderItem)

End If
````

Same as with the TreeListDataItem, you can access the separate cells by using the **UniqueName** of the column in question.

````C#
TableCell headerCell = header["ColumnUniqueName"] as TableCell;
````
````VB.NET
Dim headerCell As TableCell = CType(header("ColumnUniqueName"), TableCell)
````

## Accessing the TreeListPagerItem

You can use the same approach to get hold of the pager as for the header:

````C#
if (e.Item is TreeListPagerItem)
{
	TreeListPagerItem pager = e.Item as TreeListPagerItem;
	pager.PagerContentCell.BackColor = System.Drawing.Color.AliceBlue;
}
````
````VB.NET
If TypeOf e.Item Is TreeListPagerItem Then
	Dim pager As TreeListPagerItem = CType(e.Item, TreeListPagerItem)
	pager.PagerContentCell.BackColor = System.Drawing.Color.AliceBlue
End If
````

## Accessing the TreeListDetailTemplateItem

The **ItemCreated** and **ItemDataBound** events are the place where you can access the TreeListDetailTemplateItem as well.

````C#
if (e.Item is TreeListDetailTemplateItem)
{
	TreeListDetailTemplateItem detailItem = e.Item as TreeListDetailTemplateItem;
	Label lbl = detailItem.FindControl("Label1") as Label;
}
````
````VB.NET
If TypeOf e.Item Is TreeListDetailTemplateItem Then
	Dim detailItem As TreeListDetailTemplateItem = TryCast(e.Item, TreeListDetailTemplateItem)
End If
````

After that you can use the **FindControl()** method to get reference to the controls specified in the template.

````C#
Label lbl = detailItem.FindControl("Label1") as Label;
````
````VB.NET
Dim lbl As Label = CType(detailItem.FindControl("Label1"), Label)
````

## Accessing the TreeListNoRecordsItem

You can access the item rendered when the treelist is bound to an empty data source again the same way:

````C#
if (e.Item is TreeListNoRecordsItem)
{
	TreeListNoRecordsItem noRecordsItem = e.Item as TreeListNoRecordsItem;
}
````
````VB.NET
If TypeOf e.Item Is TreeListNoRecordsItem Then
	Dim detailItem As TreeListNoRecordsItem = TryCast(e.Item, TreeListNoRecordsItem)
End If
````

## Finding a TreeListDataItem by Key Value

**RadTreeList** provides a method to search for an existing item via the data key values of the underlying record. This method supports both key and parent key parameters.

````C#
protected void Button1_Click(object sender, EventArgs e)
{
		TreeListDataItem item = RadTreeList1.FindItemByKeyValue("RecordID", 3);
}
````
````VB.NET
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
	Dim item As TreeListDataItem = RadTreeList1.FindItemByKeyValue("RecordID", 3)
End Sub
````

If no items are found, the method returns null. In case there are multiple records matching the parameters, the method will return only the first item.

# See Also

 * [Overview]({%slug treelist/items/overview%})

repository: telerik/ajax-docs

gha_language: C#

repo_name: telerik/ajax-docs


text:
# Vagrant

## Introduction

[Vagrant](https://www.vagrantup.com) allows you to spin up local testing clusters in order to test Kubespray.

This can be useful to spin up local development clusters or to iterate on the development of Kubespray.

## Prerequisites

- Vagrant > 2.0
- A powerful computer (~2 GB of RAM for each node you want to virtualize)
- `vagrant-libvirt` if you want to add extra disks to nodes

## Quickstart

Create a Python virtualenv

```sh
python -m virtualenv /tmp/venv
```

Activate the Python virtualenv and download required dependencies

```sh
. /tmp/venv/bin/activate
pip install -r requirements.txt
```

Boot up the virtual machines

```sh
vagrant up --no-provision
```

Invoke Kubespray using Vagrant

```sh
vagrant provision
```

___Go grab a coffee___ (Kubespray might take several minutes)

Download the kubeconfig

```sh
vagrant ssh k8s-master-1 -- sudo cat /etc/kubernetes/admin.conf > /tmp/KUBECONFIG
export KUBECONFIG=/tmp/KUBECONFIG
```

Enjoy your multi-node cluster

```sh
$ kubectl get node
NAME           STATUS   ROLES    AGE     VERSION
k8s-master-1   Ready    master   10m     v1.15.3
k8s-master-2   Ready    master   7m37s   v1.15.3
k8s-master-3   Ready    master   7m44s   v1.15.3
k8s-worker-1   Ready    <none>   5m50s   v1.15.3
k8s-worker-2   Ready    <none>   5m50s   v1.15.3
```

```sh
$ kubectl -n kube-system get pod
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-869d84d46f-r7x65   1/1     Running   0          5m
calico-node-bftdq                          1/1     Running   0          5m24s
calico-node-h59rg                          1/1     Running   0          5m24s
calico-node-j6fg2                          1/1     Running   0          5m24s
calico-node-sj5dg                          1/1     Running   0          5m25s
calico-node-xfhf7                          1/1     Running   0          5m24s
coredns-74c9d4d795-kdk9r                   1/1     Running   0          3m56s
coredns-74c9d4d795-tqz7b                   1/1     Running   0          4m38s
dns-autoscaler-576b576b74-2dpl9            1/1     Running   0          4m33s
kube-apiserver-k8s-master-1                1/1     Running   0          5m23s
kube-apiserver-k8s-master-2                1/1     Running   0          5m20s
kube-apiserver-k8s-master-3                1/1     Running   0          5m22s
kube-controller-manager-k8s-master-1       1/1     Running   0          5m22s
kube-controller-manager-k8s-master-2       1/1     Running   0          5m21s
kube-controller-manager-k8s-master-3       1/1     Running   0          5m20s
kube-proxy-dkwvx                           1/1     Running   0          5m16s
kube-proxy-lgbx9                           1/1     Running   0          5m20s
kube-proxy-qvlrp                           1/1     Running   0          5m17s
kube-proxy-sjsb7                           1/1     Running   0          5m17s
kube-proxy-w772g                           1/1     Running   0          5m19s
kube-scheduler-k8s-master-1                1/1     Running   0          5m15s
kube-scheduler-k8s-master-2                1/1     Running   0          5m15s
kube-scheduler-k8s-master-3                1/1     Running   0          5m13s
kubernetes-dashboard-7c547b4c64-7q7kj      1/1     Running   0          4m28s
nginx-proxy-k8s-worker-1                   1/1     Running   0          5m13s
nginx-proxy-k8s-worker-2                   1/1     Running   0          5m14s
nodelocaldns-dk6dc                         1/1     Running   0          4m30s
nodelocaldns-dms7t                         1/1     Running   0          4m31s
nodelocaldns-h8282                         1/1     Running   0          4m31s
nodelocaldns-jqk8m                         1/1     Running   0          4m31s
nodelocaldns-pj8lh                         1/1     Running   0          4m30s
```

## How-tos

### Setting a variable

Open `Vagrantfile` and edit the `EXTRA_VARS` as follows

```ruby
EXTRA_VARS = {
  # String variable
  "variable_name" => "variable_value",
  # Number variable
  "variable_name" => 0,
  # Boolean variable
  "variable_name" => true,
  # Array variable
  "variable_name" => [ "first_element", "second_element" ],
  # Hash variable
  "variable_name" => {
    "hash_first_key" => "Hash value",
    "hash_second_key" => ["example","array"]
  }
}
```

### Altering the topology

Modify inside `Vagrantfile` the values of

- `NODE_MASTER_COUNT` number of master nodes
- `NODE_WORKER_COUNT` number of worker nodes
- `NODE_ETCD_COUNT` number of ___dedicated___ etcd nodes

Be aware that if `NODE_ETCD_COUNT` is equal to `0`, the master nodes will be used for hosting etcd

### Testing cluster scale-up / scale-down

[Change the cluster topology](#altering-the-topology) and then inside `Vagrantfile` replace

```ruby
PLAYBOOK = "cluster.yml"
```

with

```ruby
PLAYBOOK = "scale.yml"
```

then run `vagrant provison` and your cluster should be scaled

### Using a different OS

Modify inside `Vagrantfile` the values of

- `OS` the OS family (such as `debian`)
- `OS_VERSION` the OS release (such as `10`)

### Forwarding ports

Open `Vagrantfile` and edit the `FORWARD_PORTS` as follows

```ruby
FORWARD_PORTS = [
  { guest: 2375, host: 2375, host_ip: "<IP_ADDRESS>", protocol: "tcp" }
]
```

#### Explaination of port forwarding parameters

| Parameter | Explaination                  |
| :-------: | ----------------------------- |
|   guest   | Port number on the VM         |
|   host    | Port number on the host       |
|  host_ip  | IP Address to use on the host |
| protocol  | Protocol to use               |

#### Example output of port forwarding

```sh
Forwarding 2375 => 2375 on k8s-master-1
Forwarding 2376 => 2375 on k8s-master-2
Forwarding 2377 => 2375 on k8s-master-3
Forwarding 2378 => 2375 on k8s-worker-1
Forwarding 2379 => 2375 on k8s-worker-2
```

### Sharing folders

Open `Vagrantfile` and edit the `SYNCED_FOLDERS` as follows

```ruby
SYNCED_FOLDERS = [
  { from: "/tmp/cache", to: "/var/cache" }
]
```

#### Explaination of folder sharing parameters

| Parameter | Explaination     |
| :-------: | ---------------- |
|   from    | Source path      |
|    to     | Destination path |

#### Example output of folder sharing

```sh
Syncing folder /tmp/cache => /var/cache
```

### Adding additional disks

__This feature is only available using the `vagrant-libvirt` plugin__

Open `Vagrantfile` and change

- `NODE_EXTRA_DISK_COUNT` amount of extra disks available to each VM
- `NODE_EXTRA_DISK_SIZE` size in GB of each extra disk

#### Example lsblk output

`NODE_EXTRA_DISK_COUNT` was set to `2` and `NODE_EXTRA_DISK_SIZE` was set to `50`

```bash
vagrant@k8s-master-1:~$ lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
vda    254:0    0   50G  0 disk
`-vda1 254:1    0 18.6G  0 part /
vdb    254:16   0   50G  0 disk
vdc    254:32   0   50G  0 disk
```

`vdb` and `vdc` are our extra disks

### Reducing memory usage on Linux

To reduce memory usage on Linux you can use Kernel Samepage Merging that deduplicates common memory pages.

To enable it issue in a console

```sh
echo 1 | sudo tee /sys/kernel/mm/ksm/run
```

## Troubleshooting

### Machines are getting stuck at boot using the libvirt provider

This is usally due to the low amount of entropy available during the boot.

It can be fixed by adding the following line inside `~/.vagrant.d/Vagrantfile`

```ruby
Vagrant.configure("2") do |config|
  config.vm.provider :libvirt do |libvirt|
    libvirt.random :model => 'random' # Fix getting stuck at boot
  end
end
```

### Machine creation fails on Fedora using the libvirt provider

This is due to a change introduced in Fedora 30.

It can be fixed by adding the following line inside `~/.vagrant.d/Vagrantfile`

```ruby
Vagrant.configure("2") do |config|
  config.vm.provider :libvirt do |libvirt|
    # See https://fedoraproject.org/wiki/Changes/Vagrant_2.2_with_QEMU_Session
    libvirt.qemu_use_session = false
  end
end
```


text:
# Craftsy React Style Guide (WIP)

## Table of Contents

* [Component Setup](#component-setup)
  * [Component Naming](#component-naming)
  * [Method Organization](#method-organization)
  * [Formatting](#formatting)
  * [Component Attributes(Props)](#component-attributesprops)
    * [Passing Properties](#passing-properties)
    * [Assigning Properties](#assigning-properties)
* [JSX](#jsx)
  * [Conditional JSX](#conditional-jsx)
  * [List Iteration](#list-iteration)
* [Forms](#forms)

## Component Setup

### Component Naming

Components should be assigned to variables whose name will be the components name used throughout the application.
In JSX:
```
var Component = React.createClass({});
```
Compiles to:
```
var Component = React.createClass({displayName: "Component"});
```
___

This helps with modulatity in your application - Export/Require (Component.jsx example):
```
var Component = React.createClass({});
module.export = Component;
```
```
define([],function(){
  var Component = React.createClass({});
  return Component;
});
```

### Method Organization

Order component methods based on the order of their life-cycle methods:
```
var Component = React.createClass({
  propTypes: {},
  mixins : [],

  getInitialState: function() {},
  getDefaultProps: function() {},
  componentWillMount: function() {},
  componentWillReceiveProps: function() {},
  componentWillUnmount: function() {},

  // Begin custom methods
  _customHelperMethods: function() {},
  _customDerivedPropertiesMethods: function() {},

  _customEventMethods: function() {},

  _customRenderMethods: function() {},

  // End with render
  // Locate quickly and understand components internal elements and structure
  render: function() {}

})
```
___

Prefix custom functions with an underscore to distinguish between custom methods and methods which are part of React's API (example Component.jsx):
```
var Component = React.createClass({
  propTypes: {},

  getInitialState: function() {},
  componentWillReceiveProps: function() {},

  _computePrice : function() {},

  _onChange : function() {},

  _renderButtonGroup : function() {},

  render : function() {}
});

```

*Note:
Keep the render functions at the bottom of your component declarations. This way, you can always expect to find it in the same place.*

### Formatting

```
// Childless components should close themselves
<childless />

// Components with children should have closing tags
<with-children><child/></with-children>
```

### Component Attributes(Props)

##### Passing Properties

Always pass specifically need/required props and not all props to components/sub-components:

**bad**
```
<SubComponent {...this.props} />
```

**good**
```
<SubComponent theData={this.props.theData} />

<SubComponent {...this.props.theData} />
```

##### Assigning Properties
If there are multiple component attributes, display them on newlines and indent them instead of keeping them in-line:

**bad**
```
<Component attribute={...} anotherAttribute={...} attributeThree={...} attributeFour={...} attributeFive={...} attributeSix={...} attributeSeven={...}/>
```

**good**
```
<Component attribute={...}
        anotherAttribute={...}
        attributeThree={...}
        attributeFour={...}
        attributeFive={...}
        attributeSix={...}
        attributeSeven={...}
/>
```

___
Set propTypes for validation and self-documentation, required first:
```
propTypes: {
        arrayOfProps: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
        arrayProp: React.PropTypes.array,
        boolProp: React.PropTypes.bool,
        funcProp: React.PropTypes.func,
        numProp: React.PropTypes.number,
        objProp: React.PropTypes.object,
        stringProp: React.PropTypes.string
    }
```

Avoid using React.PropTypes.object and React.PropTypes.array if you can be more explicit:
```
propTypes: {
        message: React.PropTypes.instanceOf(Message),
        someView: React.PropTypes.shape({
                numProp: React.PropTypes.number.isRequired,
                funcProp: React.PropTypes.func
            }),
        optionalUnion: React.PropTypes.oneOfType([
                React.PropTypes.string,
                React.PropTypes.number
            ]).isRequired,
        arrayOfProps: React.PropTypes.arrayOf(React.PropTypes.shape({
                arrayProp: React.PropTypes.array,
                boolProp: React.PropTypes.bool,
            })),
        customProp: function(props, propName, componentName) {
          if (!/matchme/.test(props[propName])) {
            return new Error('Validation failed!');
          }
        }
    }
```

## JSX

Keep indenting consistent for JSX which contains nested elements across multiple lines, no matter how few elements are returned. Always use enclosing parens around JSX blocks. This helps preserve readability:

**bad**
```
return <div><ComponentOne /><ComponentTwo /></div>;
```

**good**
```
return (
    <div>
        <ComponentOne />
        <ComponentTwo />
    </div>
);
```
### Conditional JSX

Ternaries are fine as long as they fit on one line without scrolling:
```
{this.state.on ? ‘On’ : ‘Off’}

```
___

When an element returned by `render` depends on state, props, or other conditions, declare it in a var at the top of the render function:
either the element will be rendered, or it won't be.

```
var optionalElement;

if (this.props.condition) {
    optionalElement = (<div> … </div>);
}

return (
    <div>
        …
        {optionalElement}
        …
    </div>
);

```

It can be useful to keep a consistent suffix on these variables so they are easily identifiable:

```
optionalButtonElement, optionalFormElement, optionalTabElement
```
___

Do NOT use &&.

**bad**
```
return (
    <div>
        …
        {this.props.condition && (<div> … </div>)}
        …
    </div>
);

```

### List Iteration

Create lists inline with map calling a render method and ALWAYS assign a unique key:

```
_renderListItem: function(item) {
  // Keep the key as the first attribute so it's readily identifiable.
  return (<Component key={item.key} data={item.data} />);
},

render: function() {
  return (
      <div>
          {this.props.list.map(this._renderListItem)}
      </div>
  );
}
```

## Forms

Form elements can be written with an onChange handler to avoid having to register onChange on every field (within the same form):

```
<form onChange={this.inputHandler}>
  ...
    <input type="text" name="newDinosaurName" value={this.state.newDinosaurName} />
  ...
</form>
```
where the `inputHandler` looks like:
```
function(event) {
  actions.propagateValue({
    field : event.target.name,
    value : event.target.value
  });
}
```

## State vs. Props

Props are:

* never modified by the component itself (directly)
* set and modified by the parent

State should:

* be set by the component
* never set by an external source
* only be determined by props if a prop is explicitly an initial state i.e. ```<Foo initialCount=3/>```
* be kept as high up in the component hierarchy as reasonable
* never be duplicated or kept "in sync" between siblings

Derived properties should be moved into a component method.

Given this:
```
  propTypes: {
      myList: React.PropTypes.arrayOf(React.PropTypes.string).required
  },
  getInitialState: function() {
      return {
          title: 'WAT',
          filterString: ''
      }
  },
  ...
```
**bad**
```
  render: function() {
      return (
          <h1> { title.substr(0,20) } </h1>
          <ul>
            { this.props.myList.filter(function(item) { return item.matches(this.state.filterString); }).map(function(item) {
              <li>{ item }</li>
            })}
          </ul>
      );
  }
```
**good**
```
  _shortTitle: function() {
      return title.substr(0,20);
  },
  _filteredList: function() {
      return this.props.myList.filter(function(item) {
             return item.matches(this.state.filterString);
          });
  },
  render: function() {
      return (
          <h1>{ _shortTitle() }</h1>
          <ul>
            { this._filteredList().map(function(item) {
              <li>{ item }</li>
            })}
          </ul>
      );
  }
```

Derived properties can/should be memoized with an important caveat: Memoization is only practical with immutable objects and arrays. Immutability is recommended in general.

## Binding Event Handlers

When binding functions inside a collection, bind to the key instead of the data object itself. This helps keep logic out of the view.

React will currently override event handler binds to bind to this. This practice will stop in React 13, so you should explicitly bind to this from now on.

Don't use data- and dataset in event handlers/binds. It's terribly slow and non-reacty.

Avoid using the event object in event handlers unless you need something on the event object. If you need to call event.preventDefault(), use a prevent default wrapping utility function.

**bad**
```
  ...
  _doSomething: function(event) {
      event.preventDefault();
      var i = event.target.dataset.id;
      ...
  },
  render: function() {
      return this.props.sections.map(function(section, i) {(
        <a key={ i } href="#" onClick={ _doSomething } data-id="i">{ section.label }</a>
      )});
  }

```

**good**
```
  ...
  _preventDefault: function(handler) {
      return function(event) {
          event.preventDefault();
          handler.call(this, event);
      };
  },
  _doSomething: function(i) {
      ...
  },
  render: function() {
      return this.props.sections.map(function(section, i) {(
        <a key={ i } href="#" onClick={ preventDefault( _doSomething.bind(this, i) }>{ section.label }</a>
      )});
  }

```

Note: event.stopPropagation could be wrapped similarly. These wrapping functions should probably go into some mixin.

Don't use varargs in event handlers. The event object will get appended to arguments when bind is used.

## Mixins

Mixins provide additional functionality and help keep components DRY. However, they also "hide" code relevant to the component.

TODO:

## Credits

*Initially Forked from the [React Style Guide](https://github.com/DeepAnchor/react-style-guide). Thank you for starting DeepAnchor!*

* [React Style Guide, by David Chang](https://reactjsnews.com/react-style-guide-patterns-i-like/)
* [An opinionated guide to React.js best practices and conventions, by John Cobb](http://web-design-weekly.com/2015/01/29/opinionated-guide-react-js-best-practices-conventions/)
* [Khan React style guide](https://github.com/Khan/style-guides)
* [react guides](http://facebook.github.io/react/docs/getting-started.html)
* [Writing good react components](http://blog.whn.se/post/69621609605/writing-good-react-components)

repository: donabrams/react-style-guide

repo_name: donabrams/react-style-guide


text:
---
layout: post
title: Manchester, 6/19
---

Screening day and more! Things went very smoothly today. Grace, Olivia and I make a good team.

### Arrival inspection:

- Banjos very dirt, a few pseudo-clogged. Due to heavy use of Tet algae.
- HL-10 Ambient, which spawned, banjo overflowing but luckily lots was caught in an empty trio pour that was sitting adjacent to the catchment bucket

### Screened larvae (Olivia, Grace, and me).

- Mortality ranged dramatically between groups. Very high mortality in the following groups:
        - SN-6 Low 180um - lots of ciliates present
        - SN-10 Low 224um, 180um - lots of ciliates present
        - NF-10 Low 224um, 180um

![image](https://user-images.githubusercontent.com/17264765/27321862-c8a0c876-5550-11e7-98da-7c15dd4c6c4b.png)
![image](https://user-images.githubusercontent.com/17264765/27321876-db505298-5550-11e7-92f8-58fd8e23a022.png)

### Collected new larvae, counted, stocked, and sampled. Grace did the majority of this process today.
![6d0a3b25-93a2-4c00-ada2-d626b2cc58ca](https://user-images.githubusercontent.com/17264765/27321810-84fc8150-5550-11e7-83ac-40060a368d1d.png)

### Cleaned gigas (Olivia)

- Drained all three tanks, cleaned with vortex- LOTS of stringy stuff in the top tank w/o animals. I now am certain that the mucus is a result of the Reed’s paste, and not coming from the animals:
![file_009](https://user-images.githubusercontent.com/17264765/27322123-b1afc878-5551-11e7-839e-28e557465e43.jpeg)

- Rinsed gigas, checked for morts - there were none.
- Refilled tanks, then turned off flow and allowed header temp to increase.
- Grace adjusted flow for 1.2 L/Min on each side.
- Increased set point temp to 21degC.
- Fed with 490mL Reed’s paste
- Installed new pump (had been using small PSRF pump).

### Cleaned Broodstock (Olivia):

- First, recorded broodstock location on manifold
- [image here]
- Dumped all broodstock & larval catchment buckets, rinsed oysters, cleaned buckets with vortex.

### Larval experiment water change:

Katherine recommends having 5 replicates.
![image](https://user-images.githubusercontent.com/17264765/27322651-c19d93d0-5553-11e7-8913-43bbebdcfc6a.png)

I heeded her advice, and thus split my 3 reps into 5 via the following:
  * Math!:
    * Assuming 800 larvae in each tripour, total # larvae per treatment = 800*3 = 2,400
    * Larvae per rep for 5-reps = 2,400/5 = 480
    * larvae to remove from each tripour = 800-480 = 320. Split these up into 2 new silos = 160 larvae per new silo per triplicate
  * How this was done:
    * Set 2 new silos in FSW. Label with designated treatment group.
    * Working 1 silo at a time, transfer larvae to a tripour, fill to 200mL
      - mL needed per new silo = 800 larvae/200 mL = 4 larvae/mL, 160 larvae / l/mL = 40 mL
      - Plunge 20 times, pour 40mL into 2 falcon tubes. Add the contents into the two silos.
      - Repeat with other 2 triplicates.
      - Result:
          - 2 new silos will have 160*3 larvae = 480
          - Original silos will have 800-(2*160) = 480
  - New setup:
  ![file_000 4](https://user-images.githubusercontent.com/17264765/27322070-81823f1e-5551-11e7-8673-11e722adca8f.jpeg)

  - Changed water.
      - Filled a 5-gal bucket with 18L.
      - Harvested 450mL Tiso, CGW & counted density:

![1ca27f50-b20e-460c-9d61-ceb11e763dbc](https://user-images.githubusercontent.com/17264765/27321818-88addaf6-5550-11e7-80f3-3423ab96f26a.png)

  - Mimicking Katherine’s experiment, I will sample & image larvae on Thursday 6/22 (day 7), then also on 6/29 (day 14)
  - Reminder: I’m working with the 4 treatment groups in the South Sound (SN) population.

### current summary data:
![image](https://user-images.githubusercontent.com/17264765/27322333-991954c2-5552-11e7-8f2a-8544832018ff.png)
![image](https://user-images.githubusercontent.com/17264765/27321907-f2e70f82-5550-11e7-9e51-26d3081bd8d1.png)
![image](https://user-images.githubusercontent.com/17264765/27321921-ff8e711c-5550-11e7-8a21-6d599b4f69b9.png)
![image](https://user-images.githubusercontent.com/17264765/27321966-2d001434-5551-11e7-9809-f21a2df6683c.png)

### Downloaded Avtec Data from past 30 days:
Saved in my GitHub Repo.
![image](https://user-images.githubusercontent.com/17264765/27322431-0113d336-5553-11e7-83f2-775fb92de571.png)
![image](https://user-images.githubusercontent.com/17264765/27322458-0e309a0e-5553-11e7-8139-0532fac3cb5a.png)

repository: laurahspencer/LabNotebook

gha_language: CSS

gha_license_id: MIT

repo_name: laurahspencer/LabNotebook


text:
# chrome-network-dev :computer:

[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)

Chrome extension simplification for DevTools Network Tab, from a developer to developers.

> **No active releases.**

## Description

`chrome-network-dev` was built entirely based on [Chrome API](https://developer.chrome.com/extensions/api_index), especially [Debugger API](https://developer.chrome.com/extensions/debugger), since that is the only way to access DevTools data outside of DevTools console.

## Installation

On release, `chrome-network-dev` will be available on **Chrome Web Store**.

## Features

- [X] Draggable extension HTML div.
- [X] Method and URL for each request made.
- [X] Request details on clicking a request.
- [X] Pretty print on details.
- [ ] Loading icon waiting for response.
- [ ] Response details when response is received.
- [ ] Responsivity and styling.

repository: pedronogs/chrome-network-dev

repo_name: pedronogs/chrome-network-dev