Skip to content

Commit

Permalink
Merge pull request #247 from shirsho-12/master
Browse files Browse the repository at this point in the history
Add PPP
  • Loading branch information
shirsho-12 authored Apr 10, 2023
2 parents 18a19a3 + 798a06d commit 4764ea7
Show file tree
Hide file tree
Showing 14 changed files with 1,387 additions and 454 deletions.
574 changes: 299 additions & 275 deletions docs/DeveloperGuide.md

Large diffs are not rendered by default.

338 changes: 172 additions & 166 deletions docs/UserGuide.md

Large diffs are not rendered by default.

66 changes: 53 additions & 13 deletions docs/team/shirsho-12.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,68 @@ title: Shirshajit's Project Portfolio Page

### Project: FastTrack

FastTrack is a desktop application used for _ _. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about __20__ kLoC.
FastTrack is an expense tracking app that helps computing students keep track of their expenses by providing a simple and convenient command-line interface. It is optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, FastTrack can get your expense management tasks done faster than traditional GUI apps.

Given below are my contributions to the project.

### Summary of Contributions

* **New Feature**: MAGIC to be added soon.
* What it does:
* Justification:
* Highlights:
* Credits:
- **New Feature**: `Recurring Expenses`: Created the recurring expense functionality

* **New Feature**:
- What it does: Creates recurring expenses for the user, i.e., expenses that occur at regular intervals. Theese expenses are automatically generated based on the user's input and current date. The user can also view all recurring expenses, delete recurring expenses, and mark recurring expenses as done.
- Justification: This feature improves the product significantly because a large number of users would prefer to track their recurring expenses. This feature also allows the user to save time by not having to manually create recurring expenses.
- Highlights: This enhancement affects existing commands and commands to be added in the future. It required an in-depth analysis of design alternatives. The implementation too was challenging as it required changes to existing commands and the logic to handle the recurring expenses.

**Enhancements implemented**: to be added soon
- **New Feature**: `Category` and `Expense` models: Created the main Category and Expense models.

**Contributions to the UG:** to be added soon
- What it does: The Category model is used to store the different categories of expenses that the user can add. The Expense model is used to store the different expenses that the user can add.
- Justification: This feature improves the product significantly because it allows the user to add expenses and categorize them. This feature also allows the user to save time by not having to manually create recurring expenses.
- Highlights: This enhancement affects existing commands and commands to be added in the future. It required an in-depth analysis of design alternatives. The implementation was challenging as it required changes to existing commands and the logic to handle the recurring expenses.

**Contributions to the DG:** to be added soon
- **Code Contributions**: [RepoSense link](https://nus-cs2103-ay2223s2.github.io/tp-dashboard/?search=shirsho-12&breakdown=true&sort=groupTitle&sortWithin=title&since=2023-02-17&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other)

**Contributions to team-based tasks:** to be added soon
- **Project Management**:
- Managed releases `v1.1` - `v1.4` (3 releases) on GitHub
- Managed issue creation and assignment, milestone creation, issue labelling, and issue closing
- Enforced coding standards and code quality
- Managed the project's [issue tracker](https://github.com/AY2223S2-CS2103T-W09-2/tp/issues)
- Managed the project's [pull requests](https://github.com/AY2223S2-CS2103T-W09-2/tp/pulls)
- Managed the project [repository](https://github.com/AY2223S2-CS2103T-W09-2/tp) with the help of Isaac,[@gitsac](https://github.com/gitsac/), and Nicholas, [@niceleejy](https://github.com/niceleejy/).

**Review/Mentoring Contributions:** to be added soon
**Enhancements implemented**:

**Contributions beyond team project:** to be added soon
- Implemented the recurring expense generation functionality
- Developed Expense Type enums for the different frequency types of recurring expenses
- Implemented functionality to strip out additional whitespace in user input

**Contributions to the UG:**

- Added documentation for the Category and Expense models
- Added documentation for the recurring expense functionality

**Contributions to the DG:**

- Created Activity Diagrams for all the commands
- Created UML Diagrams for the Category and Expense models, Commands, and the Parser
- Designed the architecture diagrams for the project

**Contributions to team-based tasks:**

- Managed the setting up of the project repository and test suite
- Created test cases for multiple commands, models, and storage
- Reviewed and merged multiple pull requests
- Redesigned the architecture of the Command classes to make it more extensible
- Fixed a number of bugs in the parser and storage classes
- Fixed test cases that were failing due to changes in the codebase
- Refactored the codebase to improve code quality

**Review/Mentoring Contributions:**

- Reviewed and provided feedback on multiple pull requests
- Reviewed and provided feedback on multiple issues
- Reviewed and provided feedback on multiple code quality issues

**Contributions beyond team project:**

- Reported bugs and suggestions for improvement for other team projects
- Participated in the discussion forum and helped other students with their queries
10 changes: 10 additions & 0 deletions src/main/java/fasttrack/logic/commands/SetBudgetCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,14 @@ public boolean equals(Object other) {
|| (other instanceof SetBudgetCommand // instanceof handles nulls
&& budget.equals(((SetBudgetCommand) other).budget));
}

@Override
public String toString() {
return "SetBudgetCommand{budget=" + budget + '}';
}

@Override
public int hashCode() {
return budget.hashCode();
}
}
5 changes: 5 additions & 0 deletions src/main/java/fasttrack/model/Budget.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,9 @@ public boolean equals(Object other) {
|| (other instanceof Budget // instanceof handles nulls
&& monthBudget == ((Budget) other).monthBudget);
}

@Override
public int hashCode() {
return Double.hashCode(monthBudget);
}
}
72 changes: 72 additions & 0 deletions src/test/java/fasttrack/logic/commands/SetBudgetCommandTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package fasttrack.logic.commands;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

import fasttrack.model.Budget;
import fasttrack.model.Model;
import fasttrack.model.ModelManager;
import fasttrack.model.UserPrefs;
import fasttrack.testutil.TypicalCategories;

public class SetBudgetCommandTest {
private Budget budget = new Budget(1000);
private Budget differentBudget = new Budget(2000);
private Model model = new ModelManager(TypicalCategories.getTypicalExpenseTracker(),
new UserPrefs());

@Test
public void equals() {
SetBudgetCommand setBudgetCommand = new SetBudgetCommand(budget);
SetBudgetCommand setBudgetCommandCopy = new SetBudgetCommand(budget);
SetBudgetCommand setBudgetCommandDifferentBudget = new SetBudgetCommand(differentBudget);

// same object -> returns true
assertTrue(setBudgetCommand.equals(setBudgetCommand));

// same values -> returns true
assertTrue(setBudgetCommand.equals(setBudgetCommandCopy));

// null -> returns false
assertFalse(setBudgetCommand.equals(null));

// different budget -> returns false
assertFalse(setBudgetCommand.equals(setBudgetCommandDifferentBudget));
}

@Test
public void testHashCode() {
SetBudgetCommand setBudgetCommand = new SetBudgetCommand(budget);
SetBudgetCommand setBudgetCommandCopy = new SetBudgetCommand(budget);
SetBudgetCommand setBudgetCommandDifferentBudget = new SetBudgetCommand(differentBudget);

// same object -> returns same hashcode
assertEquals(setBudgetCommand.hashCode(), setBudgetCommand.hashCode());

// same values -> returns same hashcode
assertEquals(setBudgetCommand.hashCode(), setBudgetCommandCopy.hashCode());

// different budget -> returns different hashcode
assertNotEquals(setBudgetCommand.hashCode(), setBudgetCommandDifferentBudget.hashCode());
}

@Test
public void testToString() {
SetBudgetCommand setBudgetCommand = new SetBudgetCommand(budget);
assertEquals("SetBudgetCommand{budget=1000.0}", setBudgetCommand.toString());
}

@Test
public void execute_validBudget_success() {
SetBudgetCommand setBudgetCommand = new SetBudgetCommand(budget);
String expectedMessage = SetBudgetCommand.MESSAGE_SUCCESS + budget.toString();
Model expectedModel = new ModelManager(model.getExpenseTracker(), new UserPrefs());
CommandResult message = setBudgetCommand.execute(expectedModel);
assertEquals(expectedMessage, message.getFeedbackToUser());
}

}
105 changes: 105 additions & 0 deletions src/test/java/fasttrack/ui/CategoryCardTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package fasttrack.ui;

import static fasttrack.testutil.TypicalCategories.FOOD;
import static fasttrack.ui.JavaFxTestHelper.initJavaFxHelper;
import static fasttrack.ui.JavaFxTestHelper.setUpHeadlessMode;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.fail;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.opentest4j.AssertionFailedError;

import fasttrack.model.category.Category;
import javafx.application.Platform;
import javafx.scene.control.Label;


public class CategoryCardTest {

private Category category;
private int displayedIndex;
private int associatedExpenseCount;

@BeforeEach
public void setUp() throws InterruptedException {
if (System.getProperty("os.name").toLowerCase().contains("linux")) {
return;
}
category = FOOD;
displayedIndex = 1;
associatedExpenseCount = 3;
}

@BeforeAll
static void initJfx() throws InterruptedException {
if (System.getProperty("os.name").toLowerCase().contains("linux")) {
return;
}
setUpHeadlessMode();
initJavaFxHelper();
}

@Test
public void testCategoryCard_validData_success() {
if (System.getProperty("os.name").toLowerCase().contains("linux")) {
return;
}
CategoryCard categoryCard = new CategoryCard(category, displayedIndex, associatedExpenseCount);
CompletableFuture<Void> future = new CompletableFuture<>();
Platform.runLater(() -> {
try {
// Test that the category name label is set correctly
Label categoryNameLabel = (Label) categoryCard.getRoot().lookup("#categoryName");
assertEquals("Food", categoryNameLabel.getText());

// Test that the index label is set correctly
Label indexLabel = (Label) categoryCard.getRoot().lookup("#id");
assertEquals("1. ", indexLabel.getText());

// Test that the expense count label is set correctly
Label expenseCountLabel = (Label) categoryCard.getRoot().lookup("#expenseCount");
assertEquals("3", expenseCountLabel.getText());
future.complete(null);
} catch (AssertionFailedError e) {
future.completeExceptionally(e);
}
});
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
fail("Assertion error thrown in Platform.runLater thread: " + e.getMessage());
}
}

@Test
public void testEquals_validCategoryCard_success() {
if (System.getProperty("os.name").toLowerCase().contains("linux")) {
return;
}
CategoryCard categoryCard1 = new CategoryCard(category, displayedIndex, associatedExpenseCount);
CategoryCard categoryCard2 = new CategoryCard(category, displayedIndex + 1, associatedExpenseCount - 1);
CategoryCard categoryCard3 = new CategoryCard(category, displayedIndex + 1, associatedExpenseCount - 1);
CompletableFuture<Void> future = new CompletableFuture<>();
Platform.runLater(() -> {
try {
assertEquals(categoryCard1, categoryCard1);
assertNotEquals(categoryCard1, categoryCard2);
assertEquals(categoryCard2, categoryCard3);
future.complete(null);
} catch (AssertionFailedError e) {
future.completeExceptionally(e);
}
});
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
fail("Assertion error thrown in Platform.runLater thread: " + e.getMessage());
}
}
}
101 changes: 101 additions & 0 deletions src/test/java/fasttrack/ui/CategoryListPanelTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package fasttrack.ui;

import static fasttrack.testutil.TypicalCategories.FOOD;
import static fasttrack.testutil.TypicalCategories.TECH;
import static fasttrack.testutil.TypicalExpenses.APPLE;
import static fasttrack.testutil.TypicalExpenses.CHERRY;
import static fasttrack.ui.JavaFxTestHelper.initJavaFxHelper;
import static fasttrack.ui.JavaFxTestHelper.setUpHeadlessMode;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.opentest4j.AssertionFailedError;

import fasttrack.model.category.Category;
import fasttrack.model.expense.Expense;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ListView;


public class CategoryListPanelTest {

private CategoryListPanel categoryListPanel;
private ObservableList<Category> categories;
private ObservableList<Expense> expenses;

@BeforeEach
public void setUp() {
if (System.getProperty("os.name").toLowerCase().contains("linux")) {
return;
}
categories = FXCollections.observableArrayList(FOOD, TECH);
expenses = FXCollections.observableArrayList(APPLE, CHERRY);
}

@BeforeAll
static void initJfx() throws InterruptedException {
if (System.getProperty("os.name").toLowerCase().contains("linux")) {
return;
}
setUpHeadlessMode();
initJavaFxHelper();
}


@Test
public void categoryListView_validCategories_countEqual() {
if (System.getProperty("os.name").toLowerCase().contains("linux")) {
return;
}
CompletableFuture<Void> future = new CompletableFuture<>();
categoryListPanel = new CategoryListPanel(categories, expenses);
Platform.runLater(() -> {
try {
// Test that the number of categories is correct
ListView<?> categoryListView = (ListView<?>) categoryListPanel.getRoot().lookup("#categoryListView");
assertEquals(categories.size(), categoryListView.getItems().size());
future.complete(null);
} catch (AssertionFailedError e) {
future.completeExceptionally(e);
}
});
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
fail("Assertion error thrown in Platform.runLater thread: " + e.getMessage());
}
}

@Test
public void categoryListView_emptyList_countZero() {
if (System.getProperty("os.name").toLowerCase().contains("linux")) {
return;
}
categories = FXCollections.observableArrayList();
expenses = FXCollections.observableArrayList();
CompletableFuture<Void> future = new CompletableFuture<>();
categoryListPanel = new CategoryListPanel(categories, expenses);
Platform.runLater(() -> {
try {
ListView<?> categoryListView = (ListView<?>) categoryListPanel.getRoot().lookup("#categoryListView");
assertEquals(0, categoryListView.getItems().size());
future.complete(null);
} catch (AssertionFailedError e) {
future.completeExceptionally(e);
}
});
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
fail("Assertion error thrown in Platform.runLater thread: " + e.getMessage());
}
}
}
Loading

0 comments on commit 4764ea7

Please sign in to comment.