Skip to content

Commit

Permalink
Merge 86399e0 into 9989109
Browse files Browse the repository at this point in the history
  • Loading branch information
wallacelim committed Nov 8, 2019
2 parents 9989109 + 86399e0 commit c4e248d
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 67 deletions.
36 changes: 25 additions & 11 deletions src/main/java/seedu/address/logic/commands/ProjectCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE;

import java.util.List;
import java.util.Optional;

import javafx.collections.ObservableList;
import seedu.address.logic.commands.exceptions.CommandException;
Expand All @@ -29,8 +28,12 @@ public class ProjectCommand extends Command {
"There are no transactions in %s. It is impossible to cast a projection.";
public static final String MESSAGE_INSUFFICIENT_TRANSACTION_HISTORY =
"There are too few transactions. It is impossible to cast a projection.";
public static final String MESSAGE_PROJECTION_TOO_PROTRACTED =
"Projections should be a maximum of 2 years (730 days) from now";
public static final String SMALL_SAMPLE_SIZE =
"Projection is based on a small sample size, and may be limited in its accuracy";
public static final String PROTRACTED_PROJECTION =
"Projection is cast far into the future, and may be limited in its accuracy";
public static final String MESSAGE_USAGE = COMMAND_WORD + ": Project future balance based on past income/outflow.\n"
+ "Parameters: "
+ PREFIX_DATE + "DATE\n"
Expand All @@ -42,7 +45,8 @@ public class ProjectCommand extends Command {
"You are on track to meeting your budget of %s, with a surplus of %s!\n";
public static final String MESSAGE_BUDGET_CAUTION =
"You are likely to exceed your budget of %s, with a deficit of %s!\n";

public static final int REQUIRED_MAXIMUM_DAYS_TO_PROJECT = 730;
public static final int RECOMMENDED_MAXIMUM_DAYS_TO_PROJECT = 365;
public static final int RECOMMENDED_MINIMUM_TRANSACTIONS = 15;
public static final int REQUIRED_MINIMUM_TRANSACTIONS = 5;
private static final String MESSAGE_DUPLICATE = "A projection to %s already exists.";
Expand All @@ -59,14 +63,17 @@ public ProjectCommand(Date date) {
}

public ProjectCommand(Date date, Category category) {
this(date);
this.date = date;
this.category = category;
}

@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);

int daysFromNow = Math.abs(Date.daysBetween(Date.now(), this.date));
if (daysFromNow >= REQUIRED_MAXIMUM_DAYS_TO_PROJECT) {
throw new CommandException(MESSAGE_PROJECTION_TOO_PROTRACTED);
}
ObservableList<BankAccountOperation> transactionHistory =
model.getBankAccount().getSortedTransactionHistory(new DateComparator());

Expand All @@ -86,16 +93,23 @@ public CommandResult execute(Model model) throws CommandException {
model.add(this.projection);
model.commitUserState();

return transactionHistory.size() < RECOMMENDED_MINIMUM_TRANSACTIONS
? new CommandResult(String.format(MESSAGE_SUCCESS, projection.toString(),
projection.getAllBudgetForecastText()),
String.format(MESSAGE_WARNING, SMALL_SAMPLE_SIZE))
: new CommandResult(String.format(MESSAGE_SUCCESS, projection.toString(),
if (transactionHistory.size() < RECOMMENDED_MINIMUM_TRANSACTIONS
&& Math.abs(Date.daysBetween(Date.now(), this.date)) > RECOMMENDED_MAXIMUM_DAYS_TO_PROJECT) {
return new CommandResult(String.format(MESSAGE_SUCCESS, projection.toString(),
projection.getAllBudgetForecastText()),
String.format(MESSAGE_WARNING, SMALL_SAMPLE_SIZE),
String.format(MESSAGE_WARNING, PROTRACTED_PROJECTION));
} else if (transactionHistory.size() < RECOMMENDED_MINIMUM_TRANSACTIONS) {
return new CommandResult(String.format(MESSAGE_SUCCESS, projection.toString(),
projection.getAllBudgetForecastText()),
String.format(MESSAGE_WARNING, SMALL_SAMPLE_SIZE));
}
return new CommandResult(String.format(MESSAGE_SUCCESS, projection.toString(),
projection.getAllBudgetForecastText()));
}

Optional<Category> getCategory() {
return this.category == null ? Optional.empty() : Optional.of(this.category);
Category getCategory() {
return this.category;
}

/**
Expand Down
14 changes: 7 additions & 7 deletions src/main/java/seedu/address/model/projection/Projection.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import seedu.address.model.transaction.Amount;
import seedu.address.model.transaction.BankAccountOperation;
import seedu.address.model.transaction.Budget;
import seedu.address.model.transaction.UniqueBudgetList;
import seedu.address.model.util.Date;
import seedu.address.model.util.GradientDescent;

Expand All @@ -25,12 +26,11 @@ public class Projection {

private final ObservableList<BankAccountOperation> transactionHistory;
private final Date date;
private List<Budget> budgets = new ArrayList<>();
private ObservableList<Budget> budgets = new UniqueBudgetList().asUnmodifiableObservableList();
private List<Amount> budgetProjections = new ArrayList<>();
private List<Amount> budgetStartValues = new ArrayList<>();
private List<Amount> budgetThresholds = new ArrayList<>();
private Amount projection;
private Amount cumulativeBalance;
private GradientDescent projector;
private Category category;

Expand All @@ -43,7 +43,7 @@ public Projection(ObservableList<BankAccountOperation> transactionHistory, Date
}

public Projection(ObservableList<BankAccountOperation> transactionHistory, Date date,
List<Budget> budgets) {
ObservableList<Budget> budgets) {
this.transactionHistory = transactionHistory.sorted(new DateComparator());
this.date = date;
this.budgets = budgets;
Expand All @@ -52,10 +52,10 @@ public Projection(ObservableList<BankAccountOperation> transactionHistory, Date
}

public Projection(ObservableList<BankAccountOperation> transactionHistory, Date date,
List<Budget> budgets, Category category) {
ObservableList<Budget> budgets, Category category) {
this.transactionHistory = transactionHistory.sorted(new DateComparator());
this.date = date;
this.budgets = budgets;
this.budgets = budgets.sorted();
this.category = category;
this.project();
}
Expand All @@ -73,7 +73,7 @@ public Projection(ObservableList<BankAccountOperation> transactionHistory,
this.transactionHistory = transactionHistory.sorted(new DateComparator());
this.projection = amount;
this.date = date;
this.budgets = budgets;
this.budgets = budgets.sorted();
this.budgetProjections = new ArrayList<>();
this.category = category;
this.project();
Expand Down Expand Up @@ -105,7 +105,7 @@ GradientDescent getProjector() {
return this.projector;
}

public List<Budget> getBudgets() {
public ObservableList<Budget> getBudgets() {
return this.budgets;
}

Expand Down
7 changes: 6 additions & 1 deletion src/main/java/seedu/address/model/transaction/Budget.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/**
* Handles Budget of a BankAccount.
*/
public class Budget {
public class Budget implements Comparable<Budget> {
private Amount initialAmount;
private Amount amount;
private Date start = Date.now();
Expand Down Expand Up @@ -253,4 +253,9 @@ public String toString() {
public String toLabelText() {
return String.format("$%s by %s", this.getInitialBudget(), this.deadline.toString());
}

@Override
public int compareTo(Budget o) {
return o.getInitialBudget().compareTo(this.getInitialBudget());
}
}
36 changes: 31 additions & 5 deletions src/test/java/seedu/address/logic/commands/ProjectCommandTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package seedu.address.logic.commands;

import static java.util.Objects.requireNonNull;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static seedu.address.testutil.Assert.assertThrows;

import java.util.ArrayList;
Expand All @@ -13,14 +14,16 @@

import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.ReadOnlyBankAccount;
import seedu.address.model.category.Category;
import seedu.address.model.projection.Projection;
import seedu.address.model.stubs.BankAccountStub;
import seedu.address.model.stubs.ModelStub;
import seedu.address.model.transaction.BankAccountOperation;
import seedu.address.model.transaction.Transaction;
import seedu.address.model.transaction.UniqueTransactionList;
import seedu.address.model.util.Date;
import seedu.address.testutil.BankOperationBuilder;

import seedu.address.testutil.TypicalTransactions;


public class ProjectCommandTest {
Expand All @@ -30,7 +33,17 @@ public void constructor_nullTransaction_throwsNullPointerException() {
}

@Test
public void executeProjectCommand_oneTransaction_throwsCommandException() throws Exception {
public void executeProjectCommand_zeroTransactions_throwsCommandException() {
List<BankAccountOperation> transactions = new ArrayList<>();
ModelStubWithTransactions modelStub = new ModelStubWithTransactions(transactions);
Date date = new Date("12122019");

ProjectCommand projectCommand = new ProjectCommand(date);
assertThrows(CommandException.class, () -> projectCommand.execute(modelStub));
}

@Test
public void executeProjectCommand_oneTransaction_throwsCommandException() {
BankAccountOperation transaction = new BankOperationBuilder()
.withCategories("Food")
.withAmount("100")
Expand All @@ -45,6 +58,16 @@ public void executeProjectCommand_oneTransaction_throwsCommandException() throws
assertThrows(CommandException.class, () -> projectCommand.execute(modelStub));
}

@Test
public void executeProjectCommand_noCategory_categoryGeneralByDefault() {
List<BankAccountOperation> transactions = TypicalTransactions.getOneToTenTypicalTransactions(5);
ModelStubWithTransactions modelStub = new ModelStubWithTransactions(transactions);
Date date = new Date("12122019");

ProjectCommand projectCommand = new ProjectCommand(date);
assertEquals(projectCommand.getCategory(), Category.GENERAL);
}

/**
* A Model stub that contains a single transaction.
*/
Expand All @@ -64,7 +87,7 @@ public boolean has(BankAccountOperation transaction) {
}

/**
* A Model stub that contains 10 transactions.
* A Model stub that contains transactions.
*/
private class ModelStubWithTransactions extends ModelStub {
private ReadOnlyBankAccountStub readOnlyBankAccountStub;
Expand All @@ -78,15 +101,18 @@ private class ModelStubWithTransactions extends ModelStub {
public ReadOnlyBankAccount getBankAccount() {
return readOnlyBankAccountStub;
}

@Override
public boolean has(Projection projection) {
return false;
};
}

private class ReadOnlyBankAccountStub extends BankAccountStub {
private UniqueTransactionList transactions;

ReadOnlyBankAccountStub() {
this.transactions = new UniqueTransactionList();
}

void setTransactions(List<BankAccountOperation> transactions) {
this.transactions.setTransactions(transactions);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package seedu.address.model.projection;

public class ProjectionTest {


}
Loading

0 comments on commit c4e248d

Please sign in to comment.