Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • team13/tdat1006
  • eivindrt/tdat1006
  • alexholt/idatt1002
  • elinang/idatt1002
  • surya/idatt1002
  • kjellit/idata-1002-demo-project
  • eskillr/idatt1002
  • G1-06/idatt-1002-2022-1-06
  • emillaa/idatt1002
  • andreksv/idatt-1002-2023-9
  • melane/idatt-1002-2023-5
  • ramtinfs/idatt1002
  • surya/idatx1005
  • itatt1005_2024_group15/purchase-planner
  • systemutvikling-gruppe-19/idatt-1005-2024-group-19
15 results
Show changes
Showing
with 2732 additions and 0 deletions
package no.ntnu.idatt1002.demo.controller;
import java.io.IOException;
import java.time.LocalDate;
import java.util.Optional;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.chart.PieChart.Data;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ComboBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Modality;
import javafx.stage.Stage;
import no.ntnu.idatt1002.demo.data.Budget.FileHandlingBudget;
import no.ntnu.idatt1002.demo.data.Budget.FileHandlingBudgetArchive;
import no.ntnu.idatt1002.demo.data.Budget.FileHandlingSelectedBudget;
import no.ntnu.idatt1002.demo.data.Budget.GeneralBudget;
import no.ntnu.idatt1002.demo.data.Economics.Expense;
import no.ntnu.idatt1002.demo.data.Economics.ExpenseCategory;
import no.ntnu.idatt1002.demo.data.Economics.ExpenseRegister;
import no.ntnu.idatt1002.demo.data.Economics.FileHandling;
import no.ntnu.idatt1002.demo.data.Economics.Income;
import no.ntnu.idatt1002.demo.data.Economics.IncomeCategory;
import no.ntnu.idatt1002.demo.data.Economics.IncomeRegister;
/**
* Class for representing an overview of the income and expenses of the users budget.
* Displays information in tables and pie charts. It is possible to add, edit and delete
* income and expenses. The difference of the expense and income sum contribute to
* the monthly budget progress.
* @author Harry Linrui Xu
* @since 30.03.2023
*/
public class IncomeExpenseController extends FinanceController {
private final static String sumText = "Sum: ";
@FXML
private TableColumn<Expense, Double> expAmountCol;
@FXML
private TableColumn<Expense, ExpenseCategory> expCategoryCol;
@FXML
private TableColumn<Expense, String> expDateCol;
@FXML
private TableColumn<Expense, String> expDescriptionCol;
@FXML
private TableColumn<Expense, Boolean> expRecurringCol;
@FXML
private TableColumn<Income, Double> inAmountCol;
@FXML
private TableColumn<Income, IncomeCategory> inCategoryCol;
@FXML
private TableColumn<Income, String> inDateCol;
@FXML
private TableColumn<Income, String> inDescriptionCol;
@FXML
private TableColumn<Income, Boolean> inRecurringCol;
@FXML
private TableView<Expense> expenseTableView;
@FXML
private TableView<Income> incomeTableView;
@FXML
private Label inSum;
@FXML
private Label expSum;
@FXML
private MenuItem addExpense;
@FXML
private MenuItem addIncome;
@FXML
private DatePicker date;
@FXML
private Label daysLeftLbl;
@FXML
private ComboBox<?> filter;
@FXML
private Button returnToMainMenuBtn;
@FXML
private Button returnBtn;
@FXML
private Button continueBtn;
@FXML
private Label title;
@FXML
private Label errorMsg;
@FXML
private MenuItem editIncomeMenu;
@FXML
private MenuItem deleteIncomeMenu;
@FXML
private MenuItem editExpenseMenu;
@FXML
private MenuItem deleteExpenseMenu;
private IncomeRegister incomeRegister;
private ExpenseRegister expenseRegister;
private GeneralBudget generalBudget;
private ObservableList<Income> income;
private ObservableList<Expense> expenses;
@FXML
private PieChart expensePieChart;
@FXML
private PieChart incomePieChart;
@FXML
public void initialize() {
System.out.println("Start of initialize");
//Initialize columns
setColumns();
try {
//Initialize registers and tableview
incomeRegister = loadIncomeDataFromFile(
"budgets/" + FileHandlingSelectedBudget.readSelectedBudget() + "/Income");
expenseRegister = loadExpenseDataFromFile(
"budgets/" + FileHandlingSelectedBudget.readSelectedBudget() + "/Expense");
} catch(IOException ioe) {
showErrorDialogBox("File reading error", "Could not read register", "");
}
income = FXCollections.observableArrayList(incomeRegister.getItems());
incomeTableView.setItems(income);
expenses = FXCollections.observableArrayList(expenseRegister.getItems());
expenseTableView.setItems(expenses);
//Setting pie chart values to correspond with the registers
incomePieChart.setLegendSide(Side.RIGHT);
incomePieChart.setLabelLineLength(10);
expensePieChart.setLegendSide(Side.RIGHT);
expensePieChart.setLabelLineLength(10);
refreshPieChart();
formatDatePicker();
//Initialize sum field under the tableview
inSum.setText(sumText + String.valueOf(incomeRegister.getTotalSum()));
expSum.setText(sumText + String.valueOf(expenseRegister.getTotalSum()));
}
private void setColumns() {
inDateCol.setCellValueFactory(new PropertyValueFactory<>("date"));
inAmountCol.setCellValueFactory(new PropertyValueFactory<>("amount"));
inCategoryCol.setCellValueFactory(new PropertyValueFactory<>("category"));
inDescriptionCol.setCellValueFactory(new PropertyValueFactory<>("description"));
inRecurringCol.setCellValueFactory(new PropertyValueFactory<>("recurring"));
expDateCol.setCellValueFactory(new PropertyValueFactory<>("date"));
expAmountCol.setCellValueFactory(new PropertyValueFactory<>("amount"));
expCategoryCol.setCellValueFactory(new PropertyValueFactory<>("category"));
expDescriptionCol.setCellValueFactory(new PropertyValueFactory<>("description"));
expRecurringCol.setCellValueFactory(new PropertyValueFactory<>("recurring"));
}
public ObservableList<PieChart.Data> createExpensePieChart() {
return FXCollections.observableArrayList(
new Data("Food", expenseRegister.getExpenseByCategory(ExpenseCategory.FOOD).getTotalSum()),
new Data("Books", expenseRegister.getExpenseByCategory(ExpenseCategory.BOOKS).getTotalSum()),
new Data("Clothes", expenseRegister.getExpenseByCategory(ExpenseCategory.CLOTHES).getTotalSum()),
new Data("Other", expenseRegister.getExpenseByCategory(ExpenseCategory.OTHER).getTotalSum())
);
}
private ObservableList<PieChart.Data> createIncomePieChart() {
return FXCollections.observableArrayList(
new Data("Gift", incomeRegister.getIncomeByCategory(IncomeCategory.GIFT).getTotalSum()),
new Data("Salary", incomeRegister.getIncomeByCategory(IncomeCategory.SALARY).getTotalSum()),
new Data("Loans", incomeRegister.getIncomeByCategory(IncomeCategory.STUDENT_LOAN).getTotalSum())
);
}
/**
* Method for disabling the date picker, yet having its opacity at max.
*/
@Override
public void formatDatePicker() {
date.setValue(LocalDate.now());
date.setDisable(true);
date.setStyle("-fx-opacity: 1");
date.getEditor().setStyle("-fx-opacity: 1");
}
/**
* Method for handling the adding of new entries in the tableview.
* @param event A button click on the add button.
*/
@Override
public void handleAddBtn(javafx.event.ActionEvent event) {
int sizeBf = (expenseRegister.getItems().size() + incomeRegister.getItems().size());
if (event.getSource() == addIncome) {
handleAddIncome();
} else if (event.getSource() == addExpense){
handleAddExpense();
}
int sizeAf = (expenseRegister.getItems().size() + incomeRegister.getItems().size());
if (sizeAf != sizeBf) {
refreshTableView();
}
}
/**
* Method for handling the editing of a chosen entry in the tableview.
*
* @param event A button click on the edit button.
*/
@Override
public void handleEditBtn(javafx.event.ActionEvent event) {
Income chosenIncome = incomeTableView.getSelectionModel().getSelectedItem();
Expense chosenExpense = expenseTableView.getSelectionModel().getSelectedItem();
boolean isEditIncome = event.getSource() == editIncomeMenu;
boolean isDeleteIncome = event.getSource() == deleteIncomeMenu;
boolean isEditExpense = event.getSource() == editExpenseMenu;
boolean isDeleteExpense = event.getSource() == deleteExpenseMenu;
if (isEditIncome) {
handleEditIncome(chosenIncome);
} else if (isDeleteIncome) {
handleDeleteIncome(chosenIncome);
} else if (isEditExpense) {
handleEditExpense(chosenExpense);
} else if (isDeleteExpense) {
handleDeleteExpense(chosenExpense);
} else return;
//Updates the tableview and pie chart using the register
refreshTableView();
}
/**
* Deletes an entry from the tableview, if an entry has been selected. The method brings up a
* popup window, asking for confirmation for deleting the entry.
*
* @param event A button click on the delete button
*/
@Override
public void handleDeleteBtn(javafx.event.ActionEvent event) {
handleEditBtn(event);
}
/**
* Method for synching the register with the tableview. The observable list to which the tableview
* is set, is being refilled with all the entries in the register, keeping it updated with new
* changes.
*/
@Override
public void refreshTableView() {
this.income.setAll(incomeRegister.getItems());
this.inSum.setText("Sum: " + String.valueOf(incomeRegister.getTotalSum()));
this.expenses.setAll(expenseRegister.getItems());
this.expSum.setText("Sum: " + String.valueOf(expenseRegister.getTotalSum()));
}
@Override
public void refreshPieChart() {
this.incomePieChart.setData(createIncomePieChart());
this.expensePieChart.setData(createExpensePieChart());
}
@FXML
private void handleAddIncome() {
//Instantiate FXML loader and loads the popup for adding income
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/AddIncome.fxml"));
Income newIncome;
String dialogTitle = "Add income";
// Load the FXML file for your dialog box
Dialog<Income> dialog = new Dialog<>();
dialog.initModality(Modality.APPLICATION_MODAL);
try {
// Set the Dialog's content to the loaded FXML file
dialog.getDialogPane().setContent(loader.load());
} catch (IOException e) {
showErrorDialogBox("Loading", "Error in loading dialog box", "Could not load"
+ "the AddIncome window");
}
// Get the controller for the loaded FXML file
AddIncomeController dialogController = loader.getController();
//Sets the title of the dialog box
dialog.setTitle(dialogTitle);
// Show the Dialog and wait for the user to close it
dialog.showAndWait();
//Get the newly created income from the dialog pane
newIncome = dialogController.getNewIncome();
//Adds the new item to the register
if (newIncome != null) {
incomeRegister.addItem(newIncome);
incomePieChart.setData(createIncomePieChart());
}
}
@FXML
private void handleAddExpense() {
//Instantiate FXML loader and loads the popup for adding expense
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/AddExpense.fxml"));
Expense newExpense;
String dialogTitle = "Add expense";
Dialog<Expense> dialog = new Dialog<>();
dialog.initModality(Modality.APPLICATION_MODAL);
try {
// Set the Dialog's content to the loaded FXML file
dialog.getDialogPane().setContent(loader.load());
} catch (IOException e) {
showErrorDialogBox("Loading", "Error in loading dialog box", "Could not load"
+ "the AddExpense window");
}
// Get the controller for the loaded FXML file
AddExpenseController dialogController = loader.getController();
dialog.setTitle(dialogTitle);
// Show the Dialog and wait for the user to close it
dialog.showAndWait();
//Get the newly created expense from the dialog pane
newExpense = dialogController.getNewExpense();
//Adds the new item to the register
if (newExpense != null) {
expenseRegister.addItem(newExpense);
expensePieChart.setData(createExpensePieChart());
}
}
@FXML
private void handleEditIncome(Income chosenIncome) {
//Create copy of chosenIncome before changes
//Instantiate FXML loader and loads the popup for adding income
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/AddIncome.fxml"));
String dialogTitle = "Edit income";
// Load the FXML file for your dialog box
Dialog<Income> dialog = new Dialog<>();
dialog.initModality(Modality.APPLICATION_MODAL);
try {
// Set the Dialog's content to the loaded FXML file
dialog.getDialogPane().setContent(loader.load());
} catch (IOException e) {
showErrorDialogBox("Loading", "Error in loading dialog box", "Could not load"
+ "the EditIncome window");
}
// Get the controller for the loaded FXML file
AddIncomeController dialogController = loader.getController();
//Binds the selected item to another item which is defined in the ItemController
dialogController.setIncome(chosenIncome);
dialog.setTitle(dialogTitle);
// Show the Dialog and wait for the user to close it
dialog.showAndWait();
incomePieChart.setData(createIncomePieChart());
}
@FXML
private void handleEditExpense(Expense chosenExpense) {
//Instantiate FXML loader and loads the popup for adding expense
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/AddExpense.fxml"));
String dialogTitle = "Edit expense";
// Load the FXML file for your dialog box
Dialog<Expense> dialog = new Dialog<>();
dialog.initModality(Modality.APPLICATION_MODAL);
try {
// Set the Dialog's content to the loaded FXML file
dialog.getDialogPane().setContent(loader.load());
} catch (IOException e) {
showErrorDialogBox("Loading", "Error in loading dialog box", "Could not"
+ "load the EditExpense window");
}
// Get the controller for the loaded FXML file
AddExpenseController dialogController = loader.getController();
//Binds the selected item to another item which is defined in the ItemController
dialogController.setExpense(chosenExpense);
dialog.setTitle(dialogTitle);
// Show the Dialog and wait for the user to close it
dialog.showAndWait();
this.expensePieChart.setData(createExpensePieChart());
}
@FXML
private void handleDeleteIncome(Income chosenIncome) {
String title = "Confirm Delete" ;
String header = "Delete Confirmation";
String content = "Are you sure you would like to delete the selected income?";
Optional<ButtonType> isConfirmed = showConfirmationDialog(title, header, content);
if (isConfirmed.isPresent() && isConfirmed.get() == ButtonType.OK) {
incomeRegister.removeItem(chosenIncome);
}
this.incomePieChart.setData(createIncomePieChart());
}
@FXML
private void handleDeleteExpense(Expense chosenExpense) {
String title = "Confirm Delete" ;
String header = "Delete Confirmation";
String content = "Are you sure you would like to delete the selected expense?";
Optional<ButtonType> isConfirmed = showConfirmationDialog(title, header, content);
if (isConfirmed.isPresent() && isConfirmed.get() == ButtonType.OK) {
expenseRegister.removeItem(chosenExpense);
}
this.expensePieChart.setData(createExpensePieChart());
}
/**
* Saves the changes made to the tableview by writing the information to a file.
* @throws IOException If an error occurs while writing to the file.
*/
@Override
public void saveDataToFile() throws IOException {
FileHandling.writeItemRegisterToFile(incomeRegister,
"budgets/" + FileHandlingSelectedBudget.readSelectedBudget() + "/Income");
FileHandling.writeItemRegisterToFile(expenseRegister,
"budgets/" + FileHandlingSelectedBudget.readSelectedBudget() + "/Expense");
}
public void saveDisposableIncomeToFile() throws IOException {
String disposableIncomeAsString = String.valueOf(incomeRegister.getTotalSum() - expenseRegister.getTotalSum());
FileHandlingBudget.writeMaxAmountToFile(
"budgets/" + FileHandlingSelectedBudget.readSelectedBudget() + "/Budget", disposableIncomeAsString);
}
/**
* Switches scenes back to main menu, by loading a new FXML file and setting the scene to this location.
* @param event A button click on the return to main menu button
*/
@FXML
public void switchScene(javafx.event.ActionEvent event) {
try {
FXMLLoader loader = new FXMLLoader();
if (event.getSource() == returnToMainMenuBtn) {
saveDataToFile();
loader.setLocation(getClass().getResource("/view/MainMenuNew.fxml"));
} else if (event.getSource() == continueBtn) {
loader.setLocation(getClass().getResource("/view/newBudgetBudgert.fxml"));
saveDisposableIncomeToFile();
} else if (event.getSource() == returnBtn) {
loader.setLocation(getClass().getResource("/view/FirstMenu.fxml"));
FileHandlingBudgetArchive.deleteBudgetDirectory(FileHandlingSelectedBudget.readSelectedBudget());
FileHandlingSelectedBudget.clearSelectedBudget();
}
Parent root = loader.load();
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
} catch(IOException ioe) {
ioe.printStackTrace();
showErrorDialogBox("Loading error", "Error in loading", "Could not save"
+ "to file");
}
}
}
package no.ntnu.idatt1002.demo.controller;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import no.ntnu.idatt1002.demo.data.recipes.RecipeIngredient;
import java.net.URL;
import java.util.ResourceBundle;
public class IngredientTileController implements Initializable {
@FXML
private Label text;
@FXML
private Pane ingredientPane;
public void setData(RecipeIngredient ingredient) {
StringBuilder sb = new StringBuilder();
sb.append("# ").append(ingredient.getFoodType().label.substring(0,1).toUpperCase())
.append(ingredient.getFoodType().label.substring(1));
sb.append(" ").append(ingredient.getAmount()).append(" ").append(ingredient.getUnit().label);
text.setText(String.valueOf(sb));
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
}
}
package no.ntnu.idatt1002.demo.controller;
import java.io.IOException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Screen;
import javafx.stage.Stage;
import no.ntnu.idatt1002.demo.data.Budget.BudgetItem;
import no.ntnu.idatt1002.demo.data.Budget.FileHandlingBudget;
import no.ntnu.idatt1002.demo.data.Budget.FileHandlingSelectedBudget;
import no.ntnu.idatt1002.demo.data.Budget.GeneralBudget;
import no.ntnu.idatt1002.demo.data.Economics.ExpenseCategory;
import no.ntnu.idatt1002.demo.data.Economics.ExpenseRegister;
import no.ntnu.idatt1002.demo.data.Economics.FileHandling;
import no.ntnu.idatt1002.demo.data.Economics.IncomeRegister;
import no.ntnu.idatt1002.demo.data.Economics.Overview;
import no.ntnu.idatt1002.demo.data.recipes.Recipe;
public class MainMenu {
@FXML
private Label balanceLbl;
@FXML
private ProgressBar bookBar;
@FXML
private Label bookLbl;
@FXML
private Button budgetBtn;
@FXML
private ProgressBar clothesBar;
@FXML
private Label clothesLbl;
@FXML
private DatePicker date;
@FXML
private Button expenseBtn;
@FXML
private ProgressBar foodBar;
@FXML
private Button foodBtn;
@FXML
private Label foodLbl;
@FXML
private Button incomeBtn;
@FXML
private ProgressBar mainBar;
@FXML
private ProgressBar otherBar;
@FXML
private Label otherLbl;
@FXML
private Button returnBtn;
@FXML
private Label title;
@FXML
private Label usageLbl;
@FXML
private AnchorPane root;
@FXML
private Label daysLeftLbl;
@FXML
private VBox miniBarScroll;
GeneralBudget generalBudget;
ExpenseRegister expenseRegister;
IncomeRegister incomeRegister;
Overview overview;
@FXML
public void initialize() {
//Initialize all registers + overview
try {
incomeRegister = loadIncomeDataFromFile(
"budgets/" + FileHandlingSelectedBudget.readSelectedBudget() + "/Income");
expenseRegister = loadExpenseDataFromFile(
"budgets/" + FileHandlingSelectedBudget.readSelectedBudget() + "/Expense");
generalBudget = loadBudgetDataFromFile(
"budgets/" + FileHandlingSelectedBudget.readSelectedBudget() + "/Budget");
} catch (IOException ioe) {
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Could not load register data");
alert.setHeaderText("Could not load register data");
alert.setContentText("There was an error loading in the registers");
alert.showAndWait();
}
overview = new Overview(incomeRegister, expenseRegister, generalBudget);
mainBar.setStyle("-fx-accent: rgb(48,215,106);");
refreshProgressBars();
refreshLabels();
//Set progress when opening scene
double maxAmount = generalBudget.getMaxAmount();
double expenseSum = expenseRegister.getTotalSum();
//Displaying month
title.setText("BUDGET " + (LocalDate.now().getMonth()));
double balance = maxAmount - expenseSum;
//Set balance
balanceLbl.setText("Balance: " + (balance));
//Displaying how much of the monthly budget has been spent.
usageLbl.setText("Used " + expenseSum + " out of " + generalBudget.getMaxAmount());
if (balance < 0) {
balanceLbl.setTextFill(Color.RED);
}
//Make calendar uneditable
formatDatePicker();
daysLeftLbl.setText("Days left: 31");
//date.restrict
}
private void refreshLabels() {
}
/**
* Sets the progress of the progress bars to their most updated data.
*/
private void refreshProgressBars() {
mainBar.setProgress(expenseRegister.getTotalSum()/generalBudget.getMaxAmount());
if (mainBar.getProgress() >= 1) {
mainBar.setStyle("-fx-accent: #fa5959;");
}
ArrayList<BudgetItem> budgets = generalBudget.getBudgetItems().stream()
.filter(budget -> budget.getBudgetAmount() > 0)
.collect(Collectors.toCollection(ArrayList::new));
for(BudgetItem bi : budgets) {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/BudgetBar.fxml"));
try {
HBox hBox = loader.load();
BudgetBarController budgetBarController = loader.getController();
double leftovers = overview.getBudgetItemMinusExpense(bi.getBudgetCategory());
budgetBarController.setData(bi, leftovers);
miniBarScroll.getChildren().add(hBox);
}catch (IOException e) {
throw new RuntimeException(e);
}
}
}
/**
* Method that either reads data from a file with which it fills an income register, if older changes exist, or instantiates an income register if the file is empty.
* @param fileDestination The name of the file that is being read from.
* @return An object of type IncomeRegister.
* @throws IOException If an error occurs while reading from the file.
*/
public IncomeRegister loadIncomeDataFromFile(String fileDestination) throws IOException {
//Instantiate incomeRegister
if (FileHandling.isEmpty(fileDestination)) {
incomeRegister = new IncomeRegister();
} else { //Load previous income register
try {
incomeRegister = FileHandling.readIncomeRegisterFromFile(fileDestination);
} catch (IOException e) {
e.printStackTrace();
}
}
return incomeRegister;
}
/**
* Method that either reads data from a file with which it fills an expense register, if older changes exist, or instantiates an expense register if the file is empty.
* @param fileDestination The name of the file that is being read from.
* @return An object of type IncomeRegister.
* @throws IOException If an error occurs while reading from the file.
*/
public ExpenseRegister loadExpenseDataFromFile(String fileDestination) throws IOException {
//Instantiate expense register
if (FileHandling.isEmpty(fileDestination)) {
expenseRegister = new ExpenseRegister();
} else {
try {
expenseRegister = FileHandling.readExpenseRegisterFromFile(fileDestination);
} catch (IOException e) {
e.printStackTrace();
}
}
return expenseRegister;
}
/**
* Method that either reads data from a file with which it fills a budget register, if this is an old budget, or instantiates a budget register if this is a new budget.
* @param fileDestination The name of the file that is being read from.
* @return An object of type GeneralBudget.
* @throws IOException If an error occurs while reading from the file.
*/
public GeneralBudget loadBudgetDataFromFile(String fileDestination) throws IOException {
//Instantiate new budget
if (FileHandlingBudget.isEmpty(fileDestination)) {
System.out.println("hey");
generalBudget = new GeneralBudget(1000);
} else { //Load previous budget
try {
generalBudget = FileHandlingBudget.readGeneralBudgetFromFile(fileDestination);
} catch (IOException e) {
e.printStackTrace();
}
}
return generalBudget;
}
/**
* Method for disabling the date picker, yet having its opacity at max.
*/
private void formatDatePicker() {
date.setValue(LocalDate.now());
date.setDisable(true);
date.setStyle("-fx-opacity: 1");
date.getEditor().setStyle("-fx-opacity: 1");
}
@FXML
private void switchScene(ActionEvent event) throws IOException {
FXMLLoader loader = new FXMLLoader();
if (event.getSource() == foodBtn) {
loader.setLocation(getClass().getResource("/view/SuggestRecipes.fxml"));
} else if (event.getSource() == expenseBtn) {
loader.setLocation(getClass().getResource("/view/IncomeAndExpenses.fxml"));
} else if (event.getSource() == incomeBtn) {
loader.setLocation(getClass().getResource("/view/IncomeAndExpenses.fxml"));
} else if (event.getSource() == budgetBtn) {
loader.setLocation(getClass().getResource("/view/BudgetNewest.fxml"));
} else if (event.getSource() == returnBtn) {
loader.setLocation(getClass().getResource("/view/FirstMenu.fxml"));
}
Parent root = loader.load();
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
Scene scene = new Scene(root);
stage.setScene(scene);
//Centralize the new screen
Rectangle2D primScreenBounds = Screen.getPrimary().getVisualBounds();
stage.setX((primScreenBounds.getWidth() - stage.getWidth()) / 2);
stage.setY((primScreenBounds.getHeight() - stage.getHeight()) / 2);
stage.setResizable(false);
stage.show();
}
}
package no.ntnu.idatt1002.demo.controller;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import no.ntnu.idatt1002.demo.data.recipes.*;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class RecipeController implements Initializable {
@FXML
private Label recipeName;
@FXML
private Text instructions;
@FXML
private Button goBackBtn;
@FXML
private VBox ingredientList;
@FXML
private ObservableList<RecipeIngredient> ingredients;
@FXML
private Pane ingredientPane;
@FXML
private Button allRecipesBtn;
private Recipe recipe;
public void setData(Recipe recipeOfInterest) {
recipe = recipeOfInterest;
recipeName.setText(recipe.getName());
instructions.setText(recipe.getInstructions());
ingredients = FXCollections.observableArrayList(recipe.getIngredientList());
setIngredientTiles();
}
private void setIngredientTiles() {
for(RecipeIngredient ri : ingredients) {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/IngredientTile.fxml"));
try {
Pane pane = loader.load();
IngredientTileController ingredientTileController = loader.getController(); //Todo: is null
ingredientTileController.setData(ri);
ingredientList.getChildren().add(pane);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@FXML
private void goBack(ActionEvent event) throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/SuggestRecipes.fxml"));
Parent root = loader.load();
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
@FXML
private void toAllRecipes(ActionEvent event) throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/AllRecipes.fxml"));
Parent root = loader.load();
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
// ingredients = FXCollections.observableArrayList(recipe.getIngredientList());
}
}
package no.ntnu.idatt1002.demo.controller;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import no.ntnu.idatt1002.demo.data.recipes.FileHandler;
import no.ntnu.idatt1002.demo.data.recipes.Recipe;
import no.ntnu.idatt1002.demo.data.recipes.RecipeRegister;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class RecipeTileController implements Initializable {
@FXML
private Button nameTag;
@FXML
private Label missingTag;
@FXML
private VBox recipeTile;
private RecipeRegister recipeRegister;
@FXML
private void tileClick(ActionEvent event) throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/Recipe.fxml"));
String recipeName = this.nameTag.getText();
Recipe recipeOfInterest = recipeRegister.getRecipe(recipeName);
Parent root = loader.load();
RecipeController recipeController = loader.getController();
recipeController.setData(recipeOfInterest);
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public void setData(Recipe recipe) {
nameTag.setText(recipe.getName());
missingTag.setText(Integer.toString(recipe.getMissingIngredients()));
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
recipeRegister = FileHandler.readRecipeRegister("Recipes");
nameTag.setWrapText(true);
}
}
package no.ntnu.idatt1002.demo.controller;
import java.io.IOException;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Dialog;
import javafx.stage.Modality;
import javafx.stage.Screen;
import javafx.stage.Stage;
import no.ntnu.idatt1002.demo.data.Budget.FileHandlingBudget;
import no.ntnu.idatt1002.demo.data.Budget.FileHandlingSelectedBudget;
import no.ntnu.idatt1002.demo.data.Economics.Income;
public class SceneController {
@FXML
public void initialize() {
}
/**
* Brings up popup window to name budget
* @throws IOException
*/
@FXML
public void switchIncome(ActionEvent event) throws IOException {
//Bring up popup X
//Let user fill in. When OK is pressed, show confirmation dialog as the name cannot be changed X
//Create maybe a folder, and Create three new files, using the budgetName + the dateMonth as the ID //
//Overwrite a "currentFile" file with the fileName
//Then switch scene to the expense vs income
//Instantiate FXML loader and loads the popup for adding expense
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/CreateBudget.fxml"));
String budgetName;
String dialogTitle = "Create budget";
Dialog<String> dialog = new Dialog<>();
dialog.initModality(Modality.APPLICATION_MODAL);
try {
// Set the Dialog's content to the loaded FXML file
dialog.getDialogPane().setContent(loader.load());
} catch (IOException e) {
showErrorDialogBox("Loading", "Error in loading dialog box", "Could not load"
+ "the AddExpense window");
}
// Get the controller for the loaded FXML file
CreateBudgetController createBudgetController = new CreateBudgetController();
// Show the Dialog and wait for the user to close it
dialog.setTitle(dialogTitle);
dialog.showAndWait();
try {
if (FileHandlingSelectedBudget.readSelectedBudget() != null) {
switchNext(event);
}
} catch (IOException ioe) {
showErrorDialogBox("", "", "");
}
}
private void switchNext(ActionEvent event) throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(SceneController.class.getResource("/view/dualList.fxml"));
Parent root = loader.load();
Stage stage = (Stage)((Node)event.getSource()).getScene().getWindow();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
private void showErrorDialogBox(String title, String header, String content) {
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle(title);
alert.setHeaderText(header);
alert.setContentText(content);
alert.showAndWait();
}
public void switchMainMenu(ActionEvent event) throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(SceneController.class.getResource("/view/SelectBudget.fxml"));
String dialogTitle = "Select budget";
// Load the FXML file for your dialog box
Dialog<Income> dialog = new Dialog<>();
try {
// Set the Dialog's content to the loaded FXML file
dialog.getDialogPane().setContent(loader.load());
} catch (IOException e) {
showErrorDialogBox("Loading error", "Error in loading dialog box", "Could not load"
+ "the AddIncome window");
}
//Sets the title of the dialog box
dialog.setTitle(dialogTitle);
// Show the Dialog and wait for the user to close it
dialog.showAndWait();
try {
if (FileHandlingSelectedBudget.readSelectedBudget() != null) {
switchChosenBudget(event);
}
} catch(IOException ioe) {
showErrorDialogBox("Loading error", "Could not switch to main menu", "");
}
}
private void switchChosenBudget(ActionEvent event) throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(SceneController.class.getResource("/view/MainMenuNew.fxml"));
Parent root = loader.load();
Stage stage = (Stage)((Node)event.getSource()).getScene().getWindow();
Scene scene = new Scene(root);
stage.setScene(scene);
//Centralize the new screen
Rectangle2D primScreenBounds = Screen.getPrimary().getVisualBounds();
stage.setX((primScreenBounds.getWidth() - stage.getWidth()) / 2);
stage.setY((primScreenBounds.getHeight() - stage.getHeight()) / 2);
stage.show();
}
public void closeButton(ActionEvent actionEvent) {
final Node source = (Node) actionEvent.getSource();
final Stage stage = (Stage) source.getScene().getWindow();
stage.close();
}
}
package no.ntnu.idatt1002.demo.controller;
import java.io.IOException;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.input.MouseButton;
import javafx.stage.Stage;
import no.ntnu.idatt1002.demo.data.Budget.BudgetRegister;
import no.ntnu.idatt1002.demo.data.Budget.FileHandlingBudget;
import no.ntnu.idatt1002.demo.data.Budget.FileHandlingBudgetArchive;
import no.ntnu.idatt1002.demo.data.Budget.FileHandlingSelectedBudget;
public class SelectBudgetController {
@FXML
Button okBtn;
@FXML
private Label errorMsg;
@FXML
private ListView<String> budgetListView;
private BudgetRegister budgetRegister;
private ObservableList<String> budgetList;
@FXML
public void initialize() throws IOException {
okBtn.addEventFilter(
ActionEvent.ACTION, event -> {
if (budgetListView.getSelectionModel().getSelectedItem() == null) {
errorMsg.setOpacity(1);
event.consume();
}
});
try {
if (FileHandlingBudgetArchive.isBudgetRegisterEmpty()) {
budgetRegister = new BudgetRegister();
} else {
budgetRegister = FileHandlingBudgetArchive.readBudgetArchive("");
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
System.out.println("budget register is: " + budgetRegister);
budgetList = FXCollections.observableList(budgetRegister.getBudgetNames());
budgetListView.setItems(budgetList);
budgetListView.setOnMouseClicked(mouseEvent-> {
if(mouseEvent.getButton().equals(MouseButton.PRIMARY)){
if(mouseEvent.getClickCount() == 2){
System.out.println("Double clicked");
}
}
});
}
@FXML
public void selectBudget(ActionEvent event) throws IOException {
String name = budgetListView.getSelectionModel().getSelectedItem();
System.out.println(name);
FileHandlingSelectedBudget.updateSelectedBudget(name);
final Node source = (Node) event.getSource();
((Stage) source.getScene().getWindow()).close();
}
@FXML
public void exitWindow(ActionEvent event) throws IOException {
FileHandlingSelectedBudget.clearSelectedBudget();
final Node source = (Node) event.getSource();
((Stage) source.getScene().getWindow()).close();
}
}
package no.ntnu.idatt1002.demo.controller;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import no.ntnu.idatt1002.demo.data.recipes.*;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Optional;
import java.util.ResourceBundle;
public class SuggestRecipesController implements Initializable {
IngredientsAtHand ingredientsAtHand;
RecipeRegister recipeRegister;
@FXML
private Button showAllBtn;
@FXML
private Button goBackBtn;
@FXML
private ListView<String> fridgeList;
@FXML
private GridPane recipeGrid;
@FXML
private Label missingList;
private ObservableList<String> fridge;
private final ArrayList<VBox> currentRecipeTiles = new ArrayList<>(4);
@FXML
private void addIngredient() throws IOException {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/AddIngredient.fxml"));
DialogPane addIngredientPane = loader.load();
Dialog<ButtonType> dialog = new Dialog<>();
dialog.setDialogPane(addIngredientPane);
dialog.setTitle("Add ingredient to fridge");
Optional<ButtonType> clickedButton = dialog.showAndWait();
if (clickedButton.isPresent() && clickedButton.get() == ButtonType.CLOSE) {
readIngredientsAtHand();
setRecipeTiles();
}
}
@FXML
private void removeFromFridge() throws IOException {
String toRemove = fridgeList.getSelectionModel().getSelectedItem();
if(toRemove != null) {
ingredientsAtHand.removeIngredient(FoodItem.valueOf(toRemove.replace(" ", "_").toUpperCase()));
storeIngredientsAtHand();
setRecipeTiles();
}
}
private void setRecipeTiles() {
int NUMBER_OF_TILES = 4;
ArrayList<Recipe> recipes = recipeRegister.pickBestFits(NUMBER_OF_TILES, ingredientsAtHand);
int i = 0;
int j = 0;
int counter = 0;
for (Recipe r : recipes) {
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/view/RecipeTile.fxml"));
if (i > 1) {
j++;
i = 0;
}
try {
VBox vBox = loader.load();
RecipeTileController recipeTileController = loader.getController();
recipeTileController.setData(r);
if (currentRecipeTiles.size() < recipes.size()) {
currentRecipeTiles.add(vBox);
} else {
recipeGrid.getChildren().remove(currentRecipeTiles.get(counter));
currentRecipeTiles.set(counter, vBox);
}
setHoverEffect(vBox, r);
recipeGrid.add(vBox, i, j);
} catch (IOException e) {
throw new RuntimeException(e);
}
i++;
counter++;
}
}
private void setHoverEffect(VBox vBox, Recipe recipe) {
vBox.setOnMouseEntered(event -> {
if(recipe.getMissingIngredients()==0) {
missingList.setText("");
missingList.setVisible(false);
} else {
missingList.setText("Missing: " + String.join(", ", recipe.getMissingList()));
missingList.setVisible(true);
}
});
vBox.setOnMouseExited(event -> {
missingList.setText("");
missingList.setVisible(false);
});
}
@FXML
private void switchScene(ActionEvent event) throws IOException {
FXMLLoader loader = new FXMLLoader();
if (event.getSource() == showAllBtn) {
loader.setLocation(getClass().getResource("/view/AllRecipes.fxml"));
} else if (event.getSource() == goBackBtn) {
loader.setLocation(getClass().getResource("/view/MainMenuNew.fxml"));
}
Parent root = loader.load();
Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow();
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setResizable(false);
stage.show();
}
public void readIngredientsAtHand() {
ingredientsAtHand = FileHandler.readIngredientsAtHand("Fridge");
if (ingredientsAtHand == null) {
ingredientsAtHand = new IngredientsAtHand();
}
fridge = FXCollections.observableArrayList(ingredientsAtHand.getIngredientsAtHand().stream().map(foodItem -> foodItem.label).toList());
fridgeList.setItems(fridge.sorted());
}
public void storeIngredientsAtHand() throws IOException {
FileHandler.writeIngredientsAtHand(ingredientsAtHand, "Fridge");
fridge = FXCollections.observableArrayList(ingredientsAtHand.getIngredientsAtHand().stream().map(foodItem -> foodItem.label).toList());
fridgeList.setItems(fridge.sorted());
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
readIngredientsAtHand();
recipeRegister = FileHandler.readRecipeRegister("Recipes");
if(recipeRegister == null) {
recipeRegister = new RecipeRegister();
}
//ObservableList<Recipe> recipes = FXCollections.observableArrayList(recipeRegister.getRecipes());
missingList.setVisible(false);
setRecipeTiles();
}
}
package no.ntnu.idatt1002.demo.data.Budget;
import javafx.beans.property.*;
import no.ntnu.idatt1002.demo.data.Economics.ExpenseCategory;
import java.util.Objects;
/**
* This class represents a budgetItem
*
* @author Adele
*/
public class BudgetItem {
private DoubleProperty budgetAmount;
private ObjectProperty<ExpenseCategory> budgetCategory;
private StringProperty budgetDescription;
/**
* The constructor of a new Budgetitem.
*
* @throws IllegalArgumentException if the budgetAmount is less than zero.
* @param budgetAmount The amount of budget as a double
* @param description A description of the budget as a String
* @param category A category from ExpenseCategory
*
*/
public BudgetItem(double budgetAmount, String description, ExpenseCategory category){
if(budgetAmount < 0) {
throw new IllegalArgumentException("The amount of the budget item must be more than zero");
}
this.budgetAmount = new SimpleDoubleProperty(budgetAmount);
this.budgetDescription = new SimpleStringProperty(description);
this.budgetCategory = new SimpleObjectProperty<>(category);
}
/**
* This method gets the BudgetAmount.
*
* @return the budgetAmount as a double
*
*/
public double getBudgetAmount() {
return budgetAmount.get();
}
public DoubleProperty getAmountProperty(){ return budgetAmount;}
public void setBudgetAmount(double amount){
this.budgetAmount.set(amount);
}
/**
* This method gets the category.
*
* @return the category as one of the categories in ExpenseCategory
*
*/
public ExpenseCategory getBudgetCategory() {
return budgetCategory.get();
}
public ObjectProperty<ExpenseCategory> getCategoryProperty(){ return budgetCategory; }
public void setBudgetCategory(ExpenseCategory category){
this.budgetCategory.set(category);
}
/**
* This method gets the description.
*
* @return the description as a String
*
*/
public String getBudgetDescription() {
return budgetDescription.get();
}
public StringProperty getDescriptionProperty(){ return budgetDescription; }
public void setBudgetDescription(String description){
this.budgetDescription.set(description);
}
@Override
public String toString() {
return "budgetAmount=" + getBudgetAmount() +
"\nbudgetCategory=" + getBudgetCategory() +
"\nbudgetDescription=" + getBudgetDescription();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BudgetItem that)) return false;
return Objects.equals(budgetAmount.get(), that.budgetAmount.get()) && Objects.equals(budgetCategory.get(), that.budgetCategory.get()) && Objects.equals(budgetDescription.get(), that.budgetDescription.get());
}
@Override
public int hashCode() {
return Objects.hash(budgetAmount, budgetCategory, budgetDescription);
}
}
package no.ntnu.idatt1002.demo.data.Budget;
import java.util.ArrayList;
import java.util.List;
public class BudgetRegister {
private final List<String> budgetNames;
public BudgetRegister() {
budgetNames = new ArrayList<>();
}
public List<String> getBudgetNames() {
return this.budgetNames;
}
public void addBudgetName(String name) {
if (name == null) throw new IllegalArgumentException("Name cannot be null");
if (name.isBlank()) throw new IllegalArgumentException("Name cannot be blank");
//if(budgetNames.contains(name)) throw new IllegalArgumentException("Duplicate entry");
budgetNames.add(name);
}
public void removeBudgetName(String name) {
if (name == null) throw new IllegalArgumentException("Name cannot be null");
if (name.isBlank()) throw new IllegalArgumentException("Name cannot be blank");
budgetNames.add(name);
}
@Override
public String toString() {
StringBuilder namesToString = new StringBuilder();
budgetNames.forEach(name -> namesToString.append(name).append("\n"));
return namesToString.toString();
}
}
package no.ntnu.idatt1002.demo.data.Budget;
import no.ntnu.idatt1002.demo.data.Economics.*;
import java.io.*;
/**
* FileHandling is a class for writing and reading
* Budgets to and from a file.
*
* @author andreas
*/
public class FileHandlingBudget {
private static final String filePath = "src/main/resources/budgets/Budget/";
private static final String fileType = ".budget";
private static final String path = "src/main/resources/";
private static final String type = ".register";
private static final String maxAmount = "maxAmount=";
private static final String budgetAmount = "budgetAmount=";
private static final String budgetCategory = "budgetCategory=";
private static final String budgetDescription = "budgetDescription=";
public static String id = "";
/**
* Method for writing (adding) a budget to a file.
*
* @param generalBudget the budget you want to write to a file.
* @param fileTitle the name of the file you want to check
* @throws IOException if an input or output exception occurred.
*/
public static void writeGeneralBudgetToFile(String fileTitle, GeneralBudget generalBudget) throws IOException {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(path + fileTitle + fileType))) {
//try (BufferedWriter bw = new BufferedWriter(new FileWriter(filePath + fileTitle + fileType))) {
bw.write(generalBudget.toString());
} catch (IOException ex) {
ex.printStackTrace();
throw new IOException("Error writing to file: " + fileTitle);
}
}
/**
* Method for checking if a .budget file is empty.
*
* @param fileTitle the name of the file you want to check
* @return true or false depending on if file is empty.
* @throws IOException if an input or output exception occurred.
*/
public static boolean isEmpty(String fileTitle) throws IOException {
/*try (BufferedReader br = new BufferedReader(new FileReader(filePath + fileTitle + fileType))) {
return br.readLine() == null;
}*/
try (BufferedReader br = new BufferedReader(new FileReader(path + fileTitle + fileType))) {
System.out.println("Trying budget isEmpty in: " + path + FileHandlingSelectedBudget.readSelectedBudget() + "/" + fileTitle + fileType);
return br.readLine() == null;
}
}
/**
* Method for checking if a .budget file is new (no categories)
* or old (has budget categories)
* @param fileTitle The name of the file
* @return True, if the budget is new. Else, returns false
* @throws IOException
*/
public static boolean isNewBudget(String fileTitle) throws IOException {
try (BufferedReader br = new BufferedReader(
new FileReader(path + fileTitle + fileType))) {
//new FileReader(filePath + fileTitle + fileType))) {
for (int i = 0; i < 2; ++i) {
br.readLine();
}
if (br.readLine() == null) {
System.out.println("Is new budget - no max amount");
return true;
}
}
System.out.println("Is 'old' budget - has max amount");
return false;
}
public static void writeMaxAmountToFile(String fileDestination, String maxAmount) throws IOException {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(path
+ fileDestination + fileType))) {
bw.write("maxAmount=" + maxAmount);
System.out.println("Max amount is...");
} catch (IOException ex) {
throw new IOException("Error writing to file: " + fileDestination);
}
}
/**
* Method for reading (getting) a Budget from a file.
*
* @param fileTitle the name of the file you want to read from.
* @return the GeneralBudget from the file.
* @throws IOException if an input or output exception occurred.
*/
public static GeneralBudget readGeneralBudgetFromFile(String fileTitle) throws IOException {
GeneralBudget generalBudget = null;
double maxAmount = 0;
double budgetAmount = 0;
ExpenseCategory expenseCategory = null;
String budgetDescription = null;
try (BufferedReader br = new BufferedReader(new FileReader(path + fileTitle + fileType))) {
String line;
String nextLine = br.readLine();
while ((line = nextLine) != null) {
nextLine = br.readLine();
if (line.startsWith(FileHandlingBudget.maxAmount)) {
maxAmount = Double.parseDouble(line.replace(FileHandlingBudget.maxAmount,""));
} else if (line.startsWith(FileHandlingBudget.budgetAmount)) {
budgetAmount = Double.parseDouble(line.replace(FileHandlingBudget.budgetAmount,""));
} else if (line.startsWith(FileHandlingBudget.budgetCategory)) {
line = line.replace(FileHandlingBudget.budgetCategory, "");
expenseCategory = switch (line) {
case "FOOD" -> ExpenseCategory.FOOD;
case "CLOTHES" -> ExpenseCategory.CLOTHES;
case "BOOKS" -> ExpenseCategory.BOOKS;
default -> ExpenseCategory.OTHER;
};
} else if (line.startsWith(FileHandlingBudget.budgetDescription)) {
budgetDescription = line.replace(FileHandlingBudget.budgetDescription,"");
}
if (line.isEmpty() || (nextLine == null)) {
if(generalBudget == null){
generalBudget = new GeneralBudget(maxAmount);
} else{
generalBudget.addToBudget(budgetAmount,budgetDescription,expenseCategory);
}
}
}
}
return generalBudget;
}
}
package no.ntnu.idatt1002.demo.data.Budget;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
//Disable next i dualList før income har blitt lagt til. Kanksje filter som prevneter negativ max amount (if balance < 1)
//MÅTE Å FIKSE TESTER PÅ: LA SELECTEDBUDGET.CURRENT VÆRE EN PARAMETER I METODENE
//Disable next i newBudgetbert til maxamount har blitt burkt opp
//Sette label til total balance i dualList
//HVIS CONTINUE I BUDGET PRESSES, SHOWCONFIRMATION
//VIKTIG_ BALANCE LABEL ER RØD PÅ GRØNN BAKGRUNN!!!
//Binde label to total balance i budget window (newBUdgetBert)
//Popup for edit og delete button
//La next button save dataene i to nye filer for persisterign i tilfelle "back" trykkes i newBudgetbudget
//confirmation for når returnBtn som returner til start. "Are you sure you want to go back. Changes will not be saved"
// FIKSE TRY CATCHES I ALLE METODENE!!!!!!!!!!
//tester for nye klasserr
//resize fordi tabellkolonner er for små, fontsize, font
//set all windows unresizable
//Bytte oversikt på dualList til Monthly ....
//System.out.println(System.getProperty("user.dir") + path); =
//C:\Users\xulr0\IdeaProjects\skoleProsjekter\idatt1002\idatt1002_2023_9src/main/resources/
//(System.getProperty("user.dir") + "/" + path) =
//(path) =
//(src/main/resources)
public class FileHandlingBudgetArchive {
private static final String filePath = "src/main/resources/budgets/";
private static final String fileType = ".archive";
public static void writeBudgetRegisterToArchive(BudgetRegister budgetNames) throws IOException {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(filePath + "Archive" + fileType))) {
bw.write(budgetNames.toString());
} catch (IOException ioe) {
ioe.printStackTrace();
throw new IOException("Could not write to file: Archive", ioe);
}
}
public static boolean isBudgetRegisterEmpty() throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(filePath
+ "Archive" + fileType))) {
return br.readLine() == null;
}
}
public static BudgetRegister readBudgetArchive(String fileTitle) throws IOException {
BudgetRegister budgetRegister = null;
String budgetName;
String line;
try (BufferedReader br = new BufferedReader(
new FileReader(filePath + "Archive" + fileType))) {
String nextLine = br.readLine();
while ((line = nextLine) != null) {
System.out.println(line);
nextLine = br.readLine();
budgetName = line;
if (budgetRegister == null) {
budgetRegister = new BudgetRegister();
}
budgetRegister.addBudgetName(budgetName);
}
}
return budgetRegister;
}
public static void writeSavingsToFile() {
}
public static boolean deleteBudgetDirectory(String budgetID) {
File targetDirectory = new File(filePath + budgetID);
System.out.println("Deleting directory:" + targetDirectory.getPath());
String[]entries = targetDirectory.list();
assert entries != null;
for(String file : entries){
File currentFile = new File(targetDirectory.getPath(),file);
System.out.println("Deleting file:" + currentFile.delete());
}
return targetDirectory.delete();
}
}
package no.ntnu.idatt1002.demo.data.Budget;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FileHandlingSelectedBudget {
private static final String filePath = "src/main/resources/budgets/";
private static final String selectedBudgetFileType = ".current";
private static final String registerFileType = ".register";
private static final String budgetFileType = ".budget";
private static final String slash = "/";
public static String readSelectedBudget() throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(filePath + "SelectedBudget" +
selectedBudgetFileType))) {
return br.readLine();
} catch (IOException ioException) {
throw new IOException("File: SelectedBudget.current does not exist", ioException);
}
}
public static void updateSelectedBudget(String budgetName) throws IOException {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(filePath + "SelectedBudget" +
selectedBudgetFileType))) {
bw.write(budgetName);
System.out.println("Current file is: " + budgetName);
} catch (IOException ex) {
throw new IOException("Error writing to file: " + "SelectedBudget.current");
}
}
public static void clearSelectedBudget() throws IOException {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(filePath + "SelectedBudget" +
selectedBudgetFileType))) {
bw.write("");
System.out.println("Current file is: ");
} catch (IOException ex) {
throw new IOException("Error writing to file: " + "SelectedBudget.current");
}
}
public static boolean isSelectedBudgetEmpty(String fileTitle) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(filePath
+ "SelectedBudget" + selectedBudgetFileType))) {
return br.readLine() == null;
}
}
public static boolean createBudgetDirectory(String budgetId) {
System.out.println("Directory: " + filePath + budgetId);
File f = new File(filePath + budgetId);
return f.mkdir();
}
public static void createNewIncomeFile(String budgetId, String incomeFileTitle) throws IOException {
System.out.println("Income filepath: " + filePath + budgetId + "/" + incomeFileTitle + registerFileType);
File incomeFile = new File(filePath + budgetId + "/" + incomeFileTitle + registerFileType);
incomeFile.createNewFile();
}
public static void createNewExpenseFile(String budgetId, String expenseFileTitle) throws IOException {
System.out.println("Expense filePath: " + filePath + budgetId + "/" + expenseFileTitle + registerFileType);
File expenseFile = new File(filePath + budgetId + "/" + expenseFileTitle + registerFileType);
expenseFile.createNewFile();
}
public static void createNewBudgetFile(String budgetId, String budgetFileTitle) throws IOException {
System.out.println("Budget filePath: " + filePath + budgetId + "/" + budgetFileTitle + budgetFileType);
File budgetFile = new File(filePath + budgetId + "/" + budgetFileTitle + budgetFileType);
budgetFile.createNewFile();
}
}
package no.ntnu.idatt1002.demo.data.Budget;
import java.util.Arrays;
import no.ntnu.idatt1002.demo.data.Economics.ExpenseCategory;
import java.time.LocalDate;
import java.time.Month;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Class that represents GeneralBudget.
*
* @author Adele
*/
public class GeneralBudget {
/**
* The period the budget is going to last for.
* Is always the amount of days left in the current month.
*/
private final int budgetPeriod = getDaysLeftOfBudgetPeriod();
/**
* A List of BudgetItems.
*/
private final List<BudgetItem> budgetItems;
/**
* The max amount of the budget.
*/
private final double maxAmount;
/**
* The savings of budget.
*/
private final Savings savings;
public GeneralBudget(List<BudgetItem> budgetItems, double maxAmount, Savings savings) {
if (maxAmount < 0) {
throw new IllegalArgumentException("The max amount of the budget cant be less than zero");
} else {
this.maxAmount = maxAmount;
this.budgetItems = budgetItems;
this.savings = savings;
}
}
/**
* Class constructor.
*
* @param budgetItems a List of BudgetItems.
* @param maxAmount the max amount of the budget.
*
*/
public GeneralBudget(List<BudgetItem> budgetItems, double maxAmount) {
if (maxAmount < 0) {
throw new IllegalArgumentException("The max amount of the budget cant be less than zero");
} else {
this.maxAmount = maxAmount;
this.budgetItems = budgetItems;
this.savings = new Savings();
}
}
/**
* Class constructor that creates an empty
* ArrayList for storing BudgetItems
*
* @param maxAmount the max amount of the budget.
*/
public GeneralBudget(double maxAmount) {
if (maxAmount < 0) {
throw new IllegalArgumentException("The max amount of the budget cant be less than zero");
} else {
this.maxAmount = maxAmount;
this.budgetItems = new ArrayList<>();
this.savings = new Savings();
}
}
/**
* This method returns the amount of days the budget will last for.
*
* @return amount of days the budget lasts.
*
*/
public int getBudgetPeriod() {
return budgetPeriod;
}
/**
* Method for getting the maxAmount of the GeneralBudget
* @return the GeneralBudget´s
*/
public double getMaxAmount() {
return maxAmount;
}
/**
* Method for getting budgetItems
*
* @return an ArrayList of every BudgetItem
* @throws if budgetItems is empty
*/
public List<BudgetItem> getBudgetItems() throws IllegalArgumentException {
return budgetItems;
}
/**
* Method for getting Savings
*
* @return savings of Budget.
*/
public Savings getSavings() {
return savings;
}
/**
* Method for getting a Specific BudgetItem
* from budgetItems
* @param expenseCategory the ExpenseCategory of the BudgetItem you want to get
* @throws IllegalArgumentException if there is no BudgetItem with the given ExpenseCategory
* @return the BudgetItem with the expenseCategory
*/
public BudgetItem getBudgetItem(ExpenseCategory expenseCategory) throws IllegalArgumentException{
for(BudgetItem budgetItem1 : budgetItems){
if (budgetItem1.getBudgetCategory().equals(expenseCategory)) {
return budgetItem1;
}
}
throw new IllegalArgumentException("No BudgetItem for this ExpenseCategory");
}
/**
* This method returns the amount of days left in the budget period as a long.
*
* @return the amount of days left in the budget period
*
*/
public int getDaysLeftOfBudgetPeriod() {
Month thisMonth = LocalDate.now().getMonth();
int dayOfTheMonth = LocalDate.now().getDayOfMonth();
return thisMonth.maxLength() - dayOfTheMonth;
}
/**
* This method adds a budgetItem to the list of budgetItems in the generalBudget
*
* @param budgetItem the budgetItem you want to add
*
*/
public void addToBudgetBudgetItem(BudgetItem budgetItem) {
if (totalSum() + budgetItem.getBudgetAmount() > maxAmount) {
throw new IllegalArgumentException("Amount to be added goes over the max value of the budget");
}
if (!hasBudgetCategory(budgetItem.getBudgetCategory())) {
budgetItems.add(budgetItem);
} else {
throw new IllegalArgumentException("There is already a budget with this category");
}
}
/**
* This method takes in a double budgetAmount, String description
* and a String category to create and add a BudgetItem to budgetItems
*
* @param budgetAmount The amount of budget as a double
* @param description A description of the budget as a String
* @param category A category from ExpenseCategory
*/
public void addToBudget(double budgetAmount, String description, ExpenseCategory category) {
if ((totalSumAndSavings() + budgetAmount) > maxAmount) {
throw new IllegalArgumentException("Amount to be added goes over the max value of the budget");
}
if (!hasBudgetCategory(category)) {
System.out.println(category.label);
budgetItems.add(new BudgetItem(budgetAmount, description, category));
} else {
System.out.println("Failing: " + category.label); //TODO: When adding budgets, this fails at 'other' even if an 'other' budget was not set.
throw new IllegalArgumentException("There is already a budget with this category");
}
}
/**
* This method checks if the list in the generalBudget already contains a budgetItem with a specified category.
*
* @param category A category from ExpenseCategory
* @return True if the list contains a budgetItem with this category and false if it does not
*
*/
public boolean hasBudgetCategory(ExpenseCategory category) {
return budgetItems.stream().anyMatch(budgetItem -> budgetItem.getBudgetCategory().equals(category));
}
/**
* Method that gets the chosen budget categories. Returns the chosen categories in a list.
* @return A list of the chosen budget categories.
*/
public List<ExpenseCategory> getChosenBudgetCategories() {
return Arrays.stream(ExpenseCategory.values()).toList().
stream().filter(this::hasBudgetCategory).toList();
}
/**
* This method checks if there are unused categories in the budget.
* @return True, if the list contains unused categories. Else returns false.
*/
private boolean hasUnusedCategories() {
return budgetItems.size() != ExpenseCategory.values().length;
}
/**
* Method that adds the remaining, unused categories to the budget list.
* Useful, as unused categories can be automatically added without user input.
*/
public void addUnusedCategories() {
if (hasUnusedCategories()) {
Arrays.stream(ExpenseCategory.values()).
filter(category -> !hasBudgetCategory(category)).
forEach(category -> budgetItems.add(new BudgetItem(0, "", category)));
}
}
/**
* This method returns the totalSum of all budgetItems in the generalBudget
*
* @return the sum of the budgetsItems as a double
*
*/
public double totalSum() {
double sum = 0;
for (BudgetItem budgetItem : budgetItems) {
sum += budgetItem.getBudgetAmount();
}
return sum;
}
/**
* This method deletes a budgetItem from the list in the GeneralBudget.
*
* @param category A category from ExpenseCategory
*
*/
public void deleteItemFromBudget(ExpenseCategory category) {
budgetItems.removeIf(item -> item.getBudgetCategory() == category);
}
/**
* Method returns totalSum of budgetItems and totalSum of savings.
*
* @return totalSum of budgetItems and totalSum of savings.
*/
public double totalSumAndSavings() {
return totalSum() + savings.getTotalSavings();
}
/**
* Assign an amount to savings.
* The amount plus other assigned amounts cannot be more than the maxAmount.
*
* @param amount the amount you want to assign to savings.
* @throws IllegalArgumentException if amount plus totalSumAndSavings is more than maxAmount
*/
public void addToSavings(double amount) {
if((totalSumAndSavings() + amount) > maxAmount) {
throw new IllegalArgumentException("Amount to be added goes over the max value of the budget");
}
savings.addToSavings(amount);
}
@Override
public String toString() {
StringBuilder budgetItemsString = new StringBuilder();
for(BudgetItem budgetItem : budgetItems){
budgetItemsString.append(budgetItem+"\n\n");
}
if(budgetItemsString.isEmpty()) {
return "maxAmount="+getMaxAmount()+"\n\n";
} else {
return "maxAmount="+getMaxAmount()+"\n\n"+budgetItemsString;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof GeneralBudget that)) return false;
return budgetPeriod == that.budgetPeriod && Double.compare(that.maxAmount, maxAmount) == 0 && Objects.equals(budgetItems, that.budgetItems);
}
@Override
public int hashCode() {
return Objects.hash(budgetPeriod, budgetItems, maxAmount);
}
/**
* Check if there is a BudgetItem for
* a specific category
*
* @param category the category you want to check
* @return true or false depending on if there is a BudgetItem for category
*/
/**
public boolean hasBudgetCategory(ExpenseCategory category){
for (BudgetItem item : listOfItems) {
if (item.getCategory() == category) {
return true;
}
}
return false;
}
*/
}
package no.ntnu.idatt1002.demo.data.Budget;
import javafx.scene.control.ProgressBar;
public class MMBI {
private ProgressBar progressBar;
private BudgetItem budgetItem;
public MMBI(BudgetItem item, ProgressBar bar){
this.budgetItem = item;
this.progressBar = bar;
}
public BudgetItem getBudgetItem(){
return budgetItem;
}
public void setBudgetItem(BudgetItem item){
this.budgetItem = item;
}
public ProgressBar getBar(){
return progressBar;
}
public void setProgressBar(ProgressBar bar){
this.progressBar = bar;
}
}
package no.ntnu.idatt1002.demo.data.Budget;
import java.util.ArrayList;
import java.util.List;
/**
* Savings is a class that has an amount
* that is given to it, which can further can be
* given to different savingsGoals.
*/
public class Savings {
/**
* List of SavingsGoals
*/
private final List<SavingsGoal> savingsGoals;
/**
* An amount not used on any SavingsGoal.
*/
private double amount;
/**
* Class constructor that sets
* savingsGoals to an empty ArrayList and
* amount to zero.
*/
public Savings() {
this.savingsGoals = new ArrayList<>();
this.amount = 0;
}
/**
* Class constructor that sets
* savingsGoals to an empty ArrayList and
* amount to a given double.
*
* @param amount the double you want to assign amount
*/
public Savings(double amount) {
this.savingsGoals = new ArrayList<>();
this.amount = amount;
}
/**
* Class constructor that sets
* savingsGoals to a given ArrayList and
* amount to zero.
*
* @param savingsGoals the ArrayList you want to assign savingsGoals
*/
public Savings(ArrayList<SavingsGoal> savingsGoals) {
this.savingsGoals = savingsGoals;
this.amount = 0;
}
/**
* Class constructor that sets
* savingsGoals to a given ArrayList and
* amount to a given double.
*
* @param savingsGoals the ArrayList you want to assign savingsGoals
* @param amount
*/
public Savings(ArrayList<SavingsGoal> savingsGoals, double amount) {
this.savingsGoals = savingsGoals;
this.amount = amount;
}
/**
* Get List of SavingsGoals.
*
* @return List of SavingsGoals
*/
public List<SavingsGoal> getSavingsGoals() {
return savingsGoals;
}
/**
* Get the amount.
*
* @return savings amount
*/
public double getAmount() {
return amount;
}
/**
* Get the total amount invested into SavingsGoals
* and the amount that is unused.
*
* @return amount invested into SavingsGoals and amount not used.
*/
public double getTotalSavings() {
double totalSavings = 0;
for(SavingsGoal savingsGoal : savingsGoals) {
totalSavings += savingsGoal.getAmountInvested();
}
totalSavings += getAmount();
return totalSavings;
}
/**
* Get a specific SavingsGoal from
* savingsGoals
*
* @param savingsGoal the SavingsGoal you want to get
* @throws IllegalArgumentException if the SavingsGoal is not in the List
* @return the SavingsGoal you wanted to find if it exists
*/
public SavingsGoal getSavingsGoal(SavingsGoal savingsGoal) {
for(SavingsGoal aSavingsGoal : savingsGoals) {
if(savingsGoal == aSavingsGoal) {
return aSavingsGoal;
}
}
throw new IllegalArgumentException("The SavingsGoal is not in the List");
}
/**
* Method to check if savingsGoals
* contains a specific SavingsGoal
*
* @param savingsGoal the SavingsGoal you want to check.
* @return boolean depending on if savingsGoals contains the savingsGoal.
*/
public boolean hasSavingsGoal(SavingsGoal savingsGoal) {
return savingsGoals.contains(savingsGoal);
}
/**
* A List of all SavingsGoal that are achieved.
* A SavingsGoal is achieved if its amount is zero.
*
* @return List of achieved SavingsGoal
*/
public List<SavingsGoal> getAchievedSavingsGoal() {
List<SavingsGoal> achievedSavingsGoals = new ArrayList<>();
for(SavingsGoal aSavingsGoal : savingsGoals) {
if(aSavingsGoal.isAchieved()) {
achievedSavingsGoals.add(aSavingsGoal);
}
}
return achievedSavingsGoals;
}
/**
* Method for adding an amount to a
* SavingsGoal.
*
* @param amount the amount you want to add
* @param savingsGoal the SavingsGoal you want to add to
* @throws IllegalArgumentException if the amount is higher than the Savings amount.
* @throws IllegalArgumentException if SavingsGoal is not in savingsGoal.
*/
public void addToSavingsGoal(int amount, SavingsGoal savingsGoal) {
if(amount > this.amount) {
throw new IllegalArgumentException("The amount cannot be higher than the Savings amount");
}
if(!hasSavingsGoal(savingsGoal)) {
throw new IllegalArgumentException("The SavingsGoal is not in savingsGoals");
}
getSavingsGoal(savingsGoal).addAmountInvested(amount);
this.amount -= amount;
}
/**
* Add an amount to Savings
*
* @param amount the amount you want to add.
*/
public void addToSavings(double amount) {
this.amount += amount;
}
/**
* Add a SavingsGoal to Savings.
*
* @param savingsGoal the SavingsGoal you want to add.
* @throws IllegalArgumentException if the SavingsGoal already exists in the Savings.
*/
public void addSavingsGoal(SavingsGoal savingsGoal) {
if(savingsGoals.contains(savingsGoal)) {
throw new IllegalArgumentException("SavingsGoal already in Savings");
} else {
savingsGoals.add(savingsGoal);
}
}
}
\ No newline at end of file
package no.ntnu.idatt1002.demo.data.Budget;
/**
* SavingsGoal is a specific goal that you are
* saving towards, for example a car or holiday.
*/
public class SavingsGoal {
/**
* A description of what the SavingsGoal is for.
*/
private String description;
/**
* The monetary amount invested into the SavingsGoal
*/
private double amountInvested;
/**
* The monetary amount needed to achieve the SavingsGoal
*/
private double amountGoal;
/**
* Boolean to check if the SavingsGoal has been achieved.
* SavingsGoal has been achieved when amount is zero.
*/
private boolean achieved = false;
/**
* The class constructor for a SavingsGoal.
*
* @param description a String the explains what the SavingsGoal is for.
* @param amountInvested the monetary amount invested into the SavingsGoal.
* @param amountGoal the monetary amount needed to achieve the SavingsGoal.
*/
public SavingsGoal(String description, double amountInvested, double amountGoal) throws IllegalArgumentException{
this.description = description;
if(amountGoal < 0) {
amountGoal = 0;
}
if(amountInvested < 0) {
amountInvested = 0;
}
this.amountGoal = amountGoal;
this.amountInvested = amountInvested;
achieved = amountInvested >= amountGoal;
}
/**
* The class constructor for a SavingsGoal,
* amountInvested is set to zero.
*
* @param description a String the explains what the SavingsGoal is for.
* @param amountGoal the monetary amount needed to achieve the SavingsGoal.
*/
public SavingsGoal(String description, double amountGoal) {
this.description = description;
if(amountGoal < 0) {
amountGoal = 0;
}
this.amountGoal = amountGoal;
this.amountInvested = 0;
}
/**
* Getting the description of the SavingsGoal
* @return the SavingsGoal´s description.
*/
public String getDescription() {
return description;
}
/**
* Getting the amount needed to achieve the SavingsGoal
* @return the SavingsGoal´s needed amount.
*/
public double getAmountGoal() {
return amountGoal;
}
/**
* Getting the amount invested into the SavingsGoal.
* @return the SavingsGoal´s amount invested.
*/
public double getAmountInvested() {
return amountInvested;
}
/**
* Check if the SavingsGoal is achieved.
*
* @return boolean
*/
public boolean isAchieved() {
return achieved;
}
/**
* Setting the description of the SavingsGoal.
*
* @param description the new description you want to use.
*/
public void setDescription(String description) {
this.description = description;
}
/**
* Setting the amountGoal of the SavingsGoal.
*
* @param amount the new amount you want to use.
*/
public void setAmountGoal(double amount) throws IllegalArgumentException{
if(amount < 0) {
this.amountGoal = 0;
} else {
this.amountGoal = amount;
}
achieved = amountInvested >= amountGoal;
}
/**
* Adding an amount to the amountInvested of the SavingsGoal.
*
* @param amount the amount you want to add.
*/
public void addAmountInvested(double amount) throws IllegalArgumentException{
this.amountInvested += amount;
achieved = amountInvested >= amountGoal;
}
}
package no.ntnu.idatt1002.demo.data.Economics;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import java.time.LocalDate;
import java.util.Objects;
public class Expense extends Item{
private ObjectProperty<ExpenseCategory> category;
/**
* This constructor uses the super constructor to set the fields for 'amount' and 'recurring' and then sets the
* category. A IllegalArgumentException from this constructor if the category is left blank. The description
* field is left to the default blank string.
*
* @param amount The amount of the current Expense object as a double.
* @param recurring True if the current Expense repeats at regular intervals.
* @param category The category to which the Expense belongs to, provided as a value of ExpenseCategory.
* @param date The date of the Expense at format "dd.mm.yy".
*/
public Expense(double amount, boolean recurring, ExpenseCategory category, LocalDate date) {
super(amount, recurring, date);
if(category == null) {
throw new IllegalArgumentException("The income must belong to a category.");
}
this.category = new SimpleObjectProperty<>(category);
}
/**
* This constructor uses the super constructor to set the fields for 'amount', 'description' and 'recurring'
* and then sets the category. A IllegalArgumentException from this constructor if the category is left blank.
* @param description A description of the Expense as a String.
* @param amount The amount of the current Expense object as a double.
* @param recurring True if the current income repeats at regular intervals.
* @param category The category to which the Expense belongs to, provided as a value of ExpenseCategory
* @param date The date of the Expense at format "dd.mm.yy".
*/
public Expense(String description, double amount, boolean recurring, ExpenseCategory category, LocalDate date) {
super(description, amount, recurring, date);
if(category == null) {
throw new IllegalArgumentException("The income must belong to a category.");
}
this.category = new SimpleObjectProperty<>(category);
}
public ObjectProperty<ExpenseCategory> expenseCategoryObjectProperty() {
return this.category;
}
/**
* The method returns the category to which the Expense belongs as a value of the ExpenseCategory enum class.
* @return The category the Expense belongs to as a value of the ExpenseCategory enum class.
*/
public ExpenseCategory getCategory() {
return category.get();
}
/**
* The method sets the category of an expense to a value of the ExpenseCategory enum class.
* @param expenseCategory The category to which the expense belongs as a value of the ExpenseCategory enum.
*/
public void setCategory(ExpenseCategory expenseCategory) {
if(expenseCategory == null) {
throw new IllegalArgumentException("The income must belong to a category.");
}
this.category.set(expenseCategory);
}
/**
* Returns a String that represents the Expense.
* Also includes the ExpenseCategory
* @return The Expense as a String
*/
@Override
public String toString() {
return super.toString()+"category="+category.get()+"\n\n";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Expense expense)) return false;
if (!super.equals(o)) return false;
return category.get() == expense.category.get();
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), category);
}
}
package no.ntnu.idatt1002.demo.data.Economics;
public enum ExpenseCategory {
FOOD("food"),
CLOTHES("clothes"),
BOOKS("books"),
OTHER("other");
public final String label;
ExpenseCategory(String label) {
this.label = label;
}
}
package no.ntnu.idatt1002.demo.data.Economics;
import java.time.YearMonth;
import java.util.List;
import java.util.stream.Collectors;
/**
* ExpenseRegister is a class for
* storing Expenses. Subclass of
* ItemRegister.
*
* @author andreas
*/
public class ExpenseRegister extends ItemRegister<Expense> {
/**
* Class constructor that creates an empty List for storing Expense.
*/
public ExpenseRegister() {
super();
}
/**
* Class constructor that takes in a List of Expense as argument.
*
* @param expenses the List of Expense you want to register.
*/
public ExpenseRegister(List<Expense> expenses){
super(expenses);
}
/**
* Method for getting every Expense
* in a given ExpenseCategory.
*
* @param category the ExpenseCategory you want to get every Expense of.
* @return a new ExpenseRegister of every Expense with category.
*/
public ExpenseRegister getExpenseByCategory(ExpenseCategory category){
return new ExpenseRegister(this.items.stream().filter(expense -> expense.getCategory().compareTo( category) == 0).toList());
}
/**
* Get the Expenses that are registered with a date corresponding to the given month and year.
* @param yearMonth month and year for which to withdraw Expenses.
* @return list of Expenses for a certain month and year.
*/
public ExpenseRegister getExpenseByMonth(YearMonth yearMonth) {
return new ExpenseRegister(items.stream()
.filter(income -> YearMonth.from(income.getDate()).equals(yearMonth))
.collect(Collectors.toList()));
}
/**
* Get the Expenses that are recurring.
*
* @return a new ExpenseRegister of recurring Expenses.
*/
public ExpenseRegister getRecurringExpense(){
return new ExpenseRegister(items.stream()
.filter(Item::isRecurring).toList());
}
}