wrappers = new ArrayDeque<>();
+ /**
+ * Setter for UICompositor parent/root element.
+ *
+ * @param parent - Root element
+ * @return Builder - self
+ */
public Builder parent(Pane parent) {
this.parent = parent;
return this;
}
+ /**
+ * Method for streching a node and positioning within.
+ *
+ *
+ * Works for HBox and VBox instances.
+ *
+ * @param position - Position of inner nodes.
+ * @return builder - self.
+ */
public Builder growWithAlignment(Pos position) {
Pane root = getRoot();
if (root instanceof HBox) {
@@ -49,27 +84,55 @@ public Builder growWithAlignment(Pos position) {
return this;
}
+ /**
+ * Method for obtaining newest layout node on the stack.
+ *
+ * @return newest element on the stack.
+ */
private Pane getRoot() {
return wrappers.isEmpty() ? parent : wrappers.peek();
}
+ /**
+ * Method for adding content to newest stack element.
+ *
+ * @param child - Node/content
+ * @return bulder - self.
+ */
public Builder addContent(Parent child) {
Pane root = getRoot();
root.getChildren().add(child);
return this;
}
+ /**
+ * Method for adding multiple contents to newest stack element.
+ *
+ * @param children - array of nodes/content.
+ * @return builder - self.
+ */
public Builder addAllContent(Parent... children) {
Pane root = getRoot();
root.getChildren().addAll(List.of(children));
return this;
}
+ /**
+ * Method for adding a layer to the stack.
+ *
+ * @param wrapper - Pane type.
+ * @return builder - self.
+ */
public Builder wrap(Pane wrapper) {
wrappers.push(wrapper);
return this;
}
+ /**
+ * Method for adding newest stack element to previous on stack element.
+ *
+ * @return builder - self.
+ */
public Builder unwrap() {
Pane current = wrappers.pop();
@@ -81,11 +144,26 @@ public Builder unwrap() {
return this;
}
+ /**
+ * Method for changing newest stack element properties.
+ *
+ * @param handle - Functional interface with reference to newest stack element.
+ * @return builder - self.
+ */
public Builder properties(Consumer handle) {
handle.accept(getRoot());
return this;
}
+ /**
+ * Method for adding filler to newest stack element.
+ *
+ *
+ * Creates a filler for layered stack elements type HBox, VBox.
+ *
+ *
+ * @return builder = self.
+ */
public Builder filler() {
Pane root = getRoot();
@@ -100,6 +178,11 @@ public Builder filler() {
return this;
}
+ /**
+ * Method for applying the builder method.
+ *
+ * @return instance of created UICompositor.
+ */
public UICompositor build() {
return new UICompositor(this);
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/ui/UIFactory.java b/src/main/java/edu/ntnu/idi/idatt/view/components/ui/UIFactory.java
index 365580f..06ba4c8 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/components/ui/UIFactory.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/components/ui/UIFactory.java
@@ -1,5 +1,6 @@
package edu.ntnu.idi.idatt.view.components.ui;
+import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
@@ -11,6 +12,8 @@
import edu.ntnu.idi.idatt.view.components.primitives.ActionEventHandler;
import edu.ntnu.idi.idatt.view.util.CssUtils;
import edu.ntnu.idi.idatt.view.util.ResourceUtils;
+import javafx.beans.binding.Bindings;
+import javafx.beans.property.SimpleStringProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Parent;
@@ -19,15 +22,51 @@
import javafx.scene.control.MenuButton;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.HBox;
+import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
+/**
+ * Factory class for creating UI elements.
+ *
+ *
+ * Simplifies the repetative work to create
+ * equal layouts across multiple views.
+ *
+ *
+ * @see AbstractViewUI
+ */
public class UIFactory {
- public static Parent createHeader(String placeholder, Consumer onSearchQuery) {
- return createDefaultHeader(placeholder, onSearchQuery);
+ /**
+ * Wrapper for creating simple header.
+ *
+ *
+ * Creates a simple header containing a searchbar.
+ *
+ *
+ * @param placeholder - Placeholder for searchbar.
+ * @param searchQuery - Functional interface of searchbar input property.
+ * @return header element.
+ */
+ public static Parent createHeader(String placeholder, Consumer searchQuery) {
+ return createDefaultHeader(placeholder, searchQuery);
}
- public static Parent createHeader(String placeholder, Consumer onSearchQuery, List sortItems,
+ /**
+ * Wrapper for creating extended header.
+ *
+ *
+ * Creates a header with searchbar with sorting ability.
+ *
+ *
+ * @param placeholder - Placeholder for searchbar.
+ * @param searchQuery - Functional interface of searchbar input property.
+ * @param sortItems - List of available sorting labels.
+ * @param sortHandlers - List of functional interfaces to react to the items.
+ * @return header element.
+ */
+ public static Parent createHeader(String placeholder, Consumer searchQuery,
+ List sortItems,
ActionEventHandler... sortHandlers) {
if (sortItems.size() != sortHandlers.length) {
@@ -36,7 +75,7 @@ public static Parent createHeader(String placeholder, Consumer onSearchQ
}
MenuButton menu = new MenuButton("Sort by..");
- HBox.setMargin(menu, new Insets(20));
+ menu.getStyleClass().add("menu-button");
sortItems.forEach(item -> {
MenuItem m = new MenuItem(item);
@@ -44,10 +83,24 @@ public static Parent createHeader(String placeholder, Consumer onSearchQ
menu.getItems().add(m);
});
- return createDefaultHeader(placeholder, onSearchQuery, menu);
+ return createDefaultHeader(placeholder, searchQuery, menu);
}
- private static Parent createDefaultHeader(String placeholder, Consumer onSearchQuery, Parent... addons) {
+ /**
+ * Method for creating all headers.
+ *
+ *
+ * This method is used for creating all headers through the public wrappers.
+ *
+ *
+ * @param placeholder - Placeholder for searchbar.
+ * @param searchQuery - Functional interface of searchbar input property.
+ * @param addons - Parent objects to add to the left site header
+ * @return header element.
+ */
+ private static Parent createDefaultHeader(String placeholder, Consumer searchQuery,
+ Parent... addons) {
+
SearchBarComponent bar = new SearchBarComponent(placeholder);
HBox.setMargin(bar, new Insets(20));
@@ -55,27 +108,66 @@ private static Parent createDefaultHeader(String placeholder, Consumer o
UICompositor header = new UICompositor.Builder()
.parent(new HBox())
.growWithAlignment(Pos.CENTER)
+ .properties(parent -> parent.setPadding(new Insets(0, 10, 0, 10)))
.addAllContent(addons)
.filler()
+ .filler()
.addContent(bar)
.filler()
+ .filler()
+ .filler()
.build();
- bar.onSearchQuery(() -> onSearchQuery.accept(bar.getQuery())); // Remake?
+ searchQuery.accept(bar.getQuery());
return header.makeUI();
}
+ /**
+ * Wrapper for creating navigation with title.
+ *
+ *
+ * Creates a navigation with a title.
+ *
+ *
+ * @param title - Title string.
+ * @param buttonLables - List of button names.
+ * @param handlers - Array of functional interfaces for button clicks.
+ * @return navigation element.
+ */
public static Parent createNavigation(String title, List buttonLables, ActionEventHandler... handlers) {
Label titleLabel = new Label(title);
return createDefaultNavigation(titleLabel, buttonLables, handlers);
}
+ /**
+ * Wrapper for creating navigation with title label.
+ *
+ *
+ * Creates a navigation with a title label.
+ *
+ *
+ * @param titleLabel - Label title object.
+ * @param buttonLables - List of button names.
+ * @param handlers - Array of functional interfaces for button clicks.
+ * @return navigation element.
+ */
public static Parent createNavigation(Label titleLabel, List buttonLables,
ActionEventHandler... handlers) {
return createDefaultNavigation(titleLabel, buttonLables, handlers);
}
+ /**
+ * Method for creating all navigations.
+ *
+ * This method creates all navigations through the public wrappers.
+ *
+ *
+ * @param titleLabel - Label title object.
+ * @param buttonLables - List of button names.
+ * @param handlers - Array of functional interfaces for button clicks.
+ * @return navigation element.
+ */
private static Parent createDefaultNavigation(Label titleLabel, List buttonLables,
ActionEventHandler... handlers) {
if (buttonLables.size() != handlers.length) {
@@ -90,65 +182,93 @@ private static Parent createDefaultNavigation(Label titleLabel, List but
buttons.add(new Button(buttonLabel));
}
buttons.forEach(b -> {
- CssUtils.apply(b, CssUtils.MED_TEXT_16);
b.setOnAction((e) -> handlers[buttons.indexOf(b)].handle());
});
UICompositor.Builder navigationBuilder = new UICompositor.Builder()
- .parent(new VBox())
+ .parent(new VBox(10))
.growWithAlignment(Pos.CENTER)
+ .properties(nav -> nav.setPadding(new Insets(40)))
.addContent(titleLabel);
buttons.forEach(b -> navigationBuilder.addContent(b));
- navigationBuilder.filler();
+ navigationBuilder
+ .filler();
if (!SceneFactory.isFinal()) {
- Button previous = new Button("Previous");
+ Button previous = new Button("Previous Page");
previous.setOnAction((e) -> SceneFactory.goBack());
navigationBuilder.addContent(previous);
}
+ Button progress = new Button("Advance To Next Week");
+ progress.setOnAction((e) -> {
+ UserSession.getInstance().getExchange().advance();
+ UserSession.getInstance().updateGameState();
+ SceneFactory.reloadCurrent();
+ });
+
+ navigationBuilder.addContent(progress);
+
+ // Styles and properties of childs
+ navigationBuilder.properties(nav -> nav.getChildren()
+ .filtered(c -> !(c instanceof Label))
+ .forEach(c -> ((Region) c).setMaxWidth(Double.MAX_VALUE)));
+ navigationBuilder.properties(nav -> nav.getChildren()
+ .filtered(c -> c instanceof Button)
+ .forEach(c -> c.getStyleClass().add("button-outlined")));
+
UICompositor navigation = navigationBuilder.build();
return navigation.makeUI();
}
+ /**
+ * Method for creating menu element.
+ *
+ *
+ * Creates a menu with clickable buttons.
+ *
+ *
+ * @param title - Title of the menu.
+ * @param buttonLables - List of button names.
+ * @param handlers - Array of functional interfaces for button clicks.
+ * @return menu element.
+ */
public static Parent createMenu(String title, List buttonLables, ActionEventHandler... handlers) {
if (buttonLables.size() != handlers.length) {
System.out.println("Failed to build menu!");
}
- IconComponent menuIcon = new IconComponent(ResourceUtils.MENU_ICON, title, 60);
- CssUtils.apply(menuIcon, CssUtils.BIG_TEXT_32);
+ Label titleLabel = new Label(title);
+ CssUtils.apply(titleLabel, CssUtils.BIG_TEXT_32);
ArrayList buttons = new ArrayList<>();
for (String buttonLabel : buttonLables) {
buttons.add(new Button(buttonLabel));
}
buttons.forEach(b -> {
- CssUtils.apply(b, CssUtils.MED_TEXT_16);
b.setOnAction((e) -> handlers[buttons.indexOf(b)].handle());
});
UICompositor.Builder menuBuilder = new UICompositor.Builder()
- .parent(new VBox())
+ .parent(new VBox(10))
.growWithAlignment(Pos.CENTER)
- .addContent(menuIcon);
+ .properties(nav -> nav.setPadding(new Insets(40)))
+ .addContent(titleLabel);
buttons.forEach(b -> menuBuilder.addContent(b));
- menuBuilder.filler();
-
- Button progress = new Button("Advance to next week");
- progress.setOnAction((e) -> {
- UserSession.getInstance().getExchange().advance();
- UserSession.getInstance().updateGameState();
- SceneFactory.reloadCurrent();
- });
-
- menuBuilder.addContent(progress);
+ menuBuilder
+ .filler()
+ .properties(nav -> nav.getChildren()
+ .filtered(c -> !(c instanceof Label))
+ .forEach((c -> ((Region) c).setMaxWidth(Double.MAX_VALUE))));
+ menuBuilder.properties(nav -> nav.getChildren()
+ .filtered(c -> c instanceof Button)
+ .forEach(c -> c.getStyleClass().add("button-outlined")));
UICompositor menu = menuBuilder.build();
@@ -156,17 +276,44 @@ public static Parent createMenu(String title, List buttonLables, ActionE
}
+ /**
+ * Method for creating toolbar.
+ *
+ *
+ * Creates a toolbar with UserSession value displays and event handlers.
+ *
+ *
+ * @see UserSession
+ *
+ * @param menuHandle - Functional interface to menu button click.
+ * @param quitHandle - Functional interface to exit button click.
+ * @return toolbar element.
+ */
public static Parent createToolbar(ActionEventHandler menuHandle, ActionEventHandler quitHandle) {
+ // Initializing formatter locally.
+ NumberFormat formatter = NumberFormat.getNumberInstance();
+ formatter.setMaximumFractionDigits(2);
+
Label balance = new Label();
balance.textProperty().bind(
- UserSession.getInstance().moneyProperty().asString("Balance: %.2f $"));
+ Bindings.createStringBinding(
+ () -> String.format("Balance: %s $", formatter.format(UserSession.getInstance().moneyProperty().get())),
+ UserSession.getInstance().moneyProperty()));
+
Label week = new Label();
week.textProperty().bind(
UserSession.getInstance().weekProperty().asString("Week: %d"));
- Label playerStatus = new Label("Status:" + UserSession.getInstance().getPlayer().getStatus());
+
+ Label playerStatus = new Label();
+ playerStatus.textProperty().bind(Bindings.format("Status: %s",
+ UserSession.getInstance().statusProperty()));
+
Label playerNetWorth = new Label();
playerNetWorth.textProperty().bind(
- UserSession.getInstance().netWorthProperty().asString("Net Worth: %.2f $"));
+ Bindings.createStringBinding(
+ () -> String.format("Net Worth: %s $",
+ formatter.format(UserSession.getInstance().netWorthProperty().get())),
+ UserSession.getInstance().netWorthProperty()));
CssUtils.apply(balance, CssUtils.MED_TEXT_16);
CssUtils.apply(week, CssUtils.MED_TEXT_16);
@@ -179,16 +326,17 @@ public static Parent createToolbar(ActionEventHandler menuHandle, ActionEventHan
UICompositor toolbar = new UICompositor.Builder()
.parent(new HBox())
.growWithAlignment(Pos.CENTER)
- .wrap(new VBox())
+ .properties(parent -> parent.setPadding(new Insets(5)))
+ .wrap(new VBox(5))
.properties(wrapper -> ((VBox) wrapper).setAlignment(Pos.CENTER))
.addAllContent(balance, week)
.unwrap()
.filler()
- .wrap(new VBox())
+ .wrap(new VBox(5))
.properties(wrapper -> ((VBox) wrapper).setAlignment(Pos.CENTER))
.addAllContent(playerStatus, playerNetWorth)
.unwrap()
- .wrap(new HBox())
+ .wrap(new HBox(5))
.properties(wrapper -> ((HBox) wrapper).setAlignment(Pos.CENTER))
.addAllContent(userIcon, quitIcon)
.unwrap()
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/entry/StartController.java b/src/main/java/edu/ntnu/idi/idatt/view/entry/StartController.java
index 595a1c2..84a9c5e 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/entry/StartController.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/entry/StartController.java
@@ -16,14 +16,25 @@
import edu.ntnu.idi.idatt.view.components.AbstractController;
import javafx.stage.FileChooser;
+/**
+ * Class for Start MVC Controller.
+ */
public class StartController extends AbstractController {
private File csv;
+ /**
+ * Constructor for StartController.
+ *
+ * @param model - StartModel instance.
+ */
public StartController(StartModel model) {
super(model);
}
+ /**
+ * Method to obtain a user specified CSV file.
+ */
public void obtainCSVFile() {
csv = new FileChooser().showOpenDialog(null);
if (csv != null) {
@@ -31,6 +42,14 @@ public void obtainCSVFile() {
}
}
+ /**
+ * Method for initializing the game.
+ *
+ *
+ * Handles initial logic and fills the UserSession
+ * with the new instance.
+ *
+ */
public void initializeGame() {
model.getError().set(" "); // Empty buffers
@@ -52,6 +71,12 @@ public void initializeGame() {
model.isNewGame().set(true);
}
+ if (model.isFirstNewGame()) {
+ model.getError().set("No player with this name found. Create new player.");
+ model.setFirstNewGame(false);
+ return;
+ }
+
if (model.getBalance().get() == null) {
model.getError().set("Balance field can't be empty");
return;
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/entry/StartModel.java b/src/main/java/edu/ntnu/idi/idatt/view/entry/StartModel.java
index 089262c..93bb8d5 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/entry/StartModel.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/entry/StartModel.java
@@ -6,6 +6,9 @@
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
+/**
+ * Model class for Start MVC.
+ */
public class StartModel implements Model {
private final StringProperty name = new SimpleStringProperty();
@@ -14,28 +17,90 @@ public class StartModel implements Model {
private final StringProperty fileName = new SimpleStringProperty();
private final BooleanProperty newGame = new SimpleBooleanProperty();
+ private boolean firstNewGame = false;
private final BooleanProperty predefinedCSV = new SimpleBooleanProperty(true);
+ /**
+ * Constructor for StartModel.
+ *
+ * Creates a listener that checks if user was not found in the persistent
+ * storage.
+ *
+ */
+ public StartModel() {
+ newGame.addListener((obs) -> {
+ firstNewGame = true;
+ });
+ }
+
+ /**
+ * Getter for name propery.
+ *
+ * @return StringProperty;
+ */
public StringProperty getName() {
return name;
}
+ /**
+ * Getter for balance property.
+ *
+ * @return StringProperty;
+ */
public StringProperty getBalance() {
return balance;
}
+ /**
+ * Getter for error property.
+ *
+ * @return StringProperty;
+ */
public StringProperty getError() {
return error;
}
+ /**
+ * Getter for FileName property.
+ *
+ * @return StringProperty;
+ */
public StringProperty getFileName() {
return fileName;
}
+ /**
+ * Getter for newGame property.
+ *
+ * @return BooleanProperty;
+ */
public BooleanProperty isNewGame() {
return newGame;
}
+ /**
+ * Getter for first game status.
+ *
+ * @return boolean;
+ */
+ public boolean isFirstNewGame() {
+ return firstNewGame;
+ }
+
+ /**
+ * Setter for first game status.
+ *
+ * @param val - boolean.
+ */
+ public void setFirstNewGame(boolean val) {
+ firstNewGame = val;
+ }
+
+ /**
+ * Getter for predefinedCSV property.
+ *
+ * @return BooleanProperty;
+ */
public BooleanProperty isPredefinedCSV() {
return predefinedCSV;
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/entry/StartView.java b/src/main/java/edu/ntnu/idi/idatt/view/entry/StartView.java
index 0c7bc3c..ece4e5a 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/entry/StartView.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/entry/StartView.java
@@ -16,6 +16,9 @@
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
+/**
+ * View class for StartView MVC.
+ */
public class StartView extends AbstractView {
// Globlal variables for model implementation
@@ -31,11 +34,20 @@ public class StartView extends AbstractView {
private Button csvButton;
private Button startButton;
+ /**
+ * Constructor for StartView.
+ */
public StartView() {
super(new StackPane());
this.getInstance().getStyleClass().add("dark");
}
+ /**
+ * Overriden method for createContent()
+ *
+ * @see AbstractView;
+ * @return root node.
+ */
@Override
public Parent createContent() {
VBox root = new VBox();
@@ -98,7 +110,7 @@ public Parent createContent() {
VBox.setMargin(importCsvWrapper, new Insets(0.0, 0.0, 0.0, 50.0));
// Start game button and error log
- startButton = new Button("Start Game");
+ startButton = new Button("Proceed");
startButton.getStyleClass().add("button");
startButton.setMaxWidth(200);
VBox.setMargin(startButton, new Insets(40.0));
@@ -121,6 +133,12 @@ public Parent createContent() {
return root;
}
+ /**
+ * Setter for StartModel.
+ *
+ * Binds observable properties and model data.
+ *
+ */
public void setModel(StartModel model) {
this.nameField.textProperty().bindBidirectional(model.getName());
this.balanceField.textProperty().bindBidirectional(model.getBalance());
@@ -133,6 +151,12 @@ public void setModel(StartModel model) {
this.importCsvWrapper.visibleProperty().bind(csvPredefinedCheckBox.selectedProperty().not());
}
+ /**
+ * Setter for StartController.
+ *
+ * Responds to actions and events for interactibility.
+ *
+ */
public void setController(StartController controller) {
this.csvButton.setOnAction(e -> controller.obtainCSVFile());
this.startButton.setOnAction(e -> controller.initializeGame());
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/exchange/ExchangeController.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/exchange/ExchangeController.java
index dd8f981..cd317d1 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/exchange/ExchangeController.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/exchange/ExchangeController.java
@@ -17,10 +17,21 @@
import javafx.scene.paint.Color;
import javafx.util.Duration;
+/**
+ * Controller class for Exchange MVC.
+ */
public class ExchangeController extends AbstractController {
+ /**
+ * SortAction Enum
+ *
+ *
+ * Defines the different sorting actions available.
+ *
+ */
public enum SortAction {
NONE,
+ NEWS,
GAINERS,
LOSERS
}
@@ -28,13 +39,41 @@ public enum SortAction {
private UserSession session = UserSession.getInstance();
private ArrayList stocksSorted = new ArrayList<>();
+ /**
+ * Constructor for ExchangeController.
+ *
+ * Loads initial stocks for the exchange view.
+ *
+ *
+ * @param model - ExchangeModel reference.
+ */
public ExchangeController(ExchangeModel model) {
super(model);
List initialStocksLoad = session.getExchange().getStocks();
stocksSorted.addAll(initialStocksLoad);
setStocksModel(initialStocksLoad);
+
+ initController();
+ }
+
+ /**
+ * Method for initializing controller.
+ *
+ * Activates listener to searchbar query.
+ *
+ */
+ public void initController() {
+ model.searchQueryProperty().addListener((obs) -> handleSearchQuery());
}
+ /**
+ * Method for setting new stocks to the exchange.
+ *
+ * Turns stocks into StockComponents.
+ *
+ *
+ * @param stockList - List of stocks to set to the model list.
+ */
public void setStocksModel(List stockList) {
model.getStockList().clear();
for (Stock stock : stockList) {
@@ -49,6 +88,11 @@ public void setStocksModel(List stockList) {
}
}
+ /**
+ * Method that applies glow effect to StockComponent with new news.
+ *
+ * @param component - The chosen StockComponent.
+ */
public void applyNewspaperGlow(StockComponent component) {
DropShadow glow = new DropShadow(7, Color.WHITE);
@@ -65,19 +109,29 @@ public void applyNewspaperGlow(StockComponent component) {
timeline.play();
}
- public void handleSearchQuery(String query) {
- if (query == null || query.isBlank()) {
+ /**
+ * Method to handle searchbar query.
+ *
+ */
+ public void handleSearchQuery() {
+ if (model.searchQueryProperty().get() == null || model.searchQueryProperty().get().isBlank()) {
setStocksModel(stocksSorted); // Get back to "no search"
return;
}
List stocksFound = stocksSorted.stream()
- .filter(stock -> stock.toString().toLowerCase().contains(query.toLowerCase())).toList();
+ .filter(stock -> stock.toString().toLowerCase().contains(model.searchQueryProperty().get().toLowerCase()))
+ .toList();
setStocksModel(stocksFound);
}
+ /**
+ * Method for sorting stocks.
+ *
+ * @param action - Instance of chosen SortAction enum.
+ */
public void sortStocksBy(SortAction action) {
stocksSorted.clear();
@@ -88,8 +142,14 @@ public void sortStocksBy(SortAction action) {
break;
}
+ case NEWS: {
+ stocksSorted.addAll(session.getExchange().getStocks()
+ .stream().filter(s -> s.getNewspaper().hasNewNews()).toList());
+ break;
+ }
+
case GAINERS: {
- stocksSorted.addAll(session.getExchange().getGainers(Integer.MAX_VALUE)); // TODO: fix?
+ stocksSorted.addAll(session.getExchange().getGainers(Integer.MAX_VALUE));
break;
}
@@ -104,6 +164,11 @@ public void sortStocksBy(SortAction action) {
}
+ /**
+ * Method for redirecting view based on stock symbol.
+ *
+ * @param symbol - Stock symbol.
+ */
public void redirectView(String symbol) {
SceneManager.switchTo(SceneFactory.createStockView(symbol));
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/exchange/ExchangeModel.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/exchange/ExchangeModel.java
index 4495ea9..f7bf431 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/exchange/ExchangeModel.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/exchange/ExchangeModel.java
@@ -2,15 +2,34 @@
import edu.ntnu.idi.idatt.view.components.Model;
import edu.ntnu.idi.idatt.view.components.elements.StockComponent;
+import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
+/**
+ * Model class for the Exchange MVC.
+ */
public class ExchangeModel implements Model {
private final ObservableList stockList = FXCollections.observableArrayList();
+ private final SimpleStringProperty searchQueryProperty = new SimpleStringProperty();
+ /**
+ * Getter for the stock list.
+ *
+ * @return ObservableList;
+ */
public ObservableList getStockList() {
return stockList;
}
+ /**
+ * Getter for search query property.
+ *
+ * @return SimpleStringProperty;
+ */
+ public SimpleStringProperty searchQueryProperty() {
+ return searchQueryProperty;
+ }
+
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/exchange/ExchangeView.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/exchange/ExchangeView.java
index 8476959..8e961e8 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/exchange/ExchangeView.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/exchange/ExchangeView.java
@@ -3,13 +3,13 @@
import java.util.List;
import java.util.function.Consumer;
-import edu.ntnu.idi.idatt.session.UserSession;
import edu.ntnu.idi.idatt.view.SceneFactory;
import edu.ntnu.idi.idatt.view.SceneManager;
import edu.ntnu.idi.idatt.view.components.AbstractViewUI;
import edu.ntnu.idi.idatt.view.components.ui.UIFactory;
import edu.ntnu.idi.idatt.view.primary.exchange.ExchangeController.SortAction;
import javafx.beans.binding.Bindings;
+import javafx.beans.property.SimpleStringProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Parent;
@@ -17,12 +17,20 @@
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
+/**
+ * View class for Exchange MVC.
+ */
public class ExchangeView extends AbstractViewUI {
- Consumer searchQueryHandler;
- Consumer sortHandle;
+ private SimpleStringProperty searchQueryProperty;
+ private Consumer sortHandle;
private VBox root;
+ /**
+ * Override of createContent() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createContent() {
root = new VBox();
@@ -42,47 +50,85 @@ public Parent createContent() {
return wrapper;
}
+ /**
+ * Override of the createNavigation() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createNavigation() {
return UIFactory.createNavigation(
- UserSession.getInstance().getExchange().getName(),
+ "Exchange",
List.of());
}
+ /**
+ * Override of createHeader() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createHeader() {
- return UIFactory.createHeader("Search for stocks",
- query -> searchQueryHandler.accept(query),
+ return UIFactory.createHeader("Search for stocks..",
+ queryProperty -> searchQueryProperty = queryProperty,
List.of(
"None",
+ "New news",
"Gainers (week)",
"Losers (week)"),
() -> sortHandle.accept(SortAction.NONE),
+ () -> sortHandle.accept(SortAction.NEWS),
() -> sortHandle.accept(SortAction.GAINERS),
() -> sortHandle.accept(SortAction.LOSERS));
}
+ /**
+ * Override of the createToolbar() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createToolbar() {
return UIFactory.createToolbar(() -> this.toggleMenu(),
() -> SceneManager.switchTo(SceneFactory.createStartView()));
}
+ /**
+ * Override of the createMenu() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createMenu() {
return UIFactory.createMenu("Account",
- List.of(" • Portfolio", " • Transactions"),
+ List.of("Portfolio", "Transactions"),
() -> SceneManager.switchTo(SceneFactory.createPortfolioView()),
() -> SceneManager.switchTo(SceneFactory.createTransactionView()));
}
+ /**
+ * Setter for the ExchangeModel.
+ *
+ * Connects view to the model data.
+ *
+ *
+ * @param model - ExchangeModel instance.
+ */
public void setModel(ExchangeModel model) {
Bindings.bindContent(root.getChildren(), model.getStockList());
+ model.searchQueryProperty().bind(searchQueryProperty);
}
+ /**
+ * Setter for the ExchangeController.
+ *
+ * Handles events of view nodes for interactibility
+ *
+ *
+ * @param controller - ExchangeController instance.
+ */
public void setController(ExchangeController controller) {
- searchQueryHandler = (query) -> controller.handleSearchQuery(query);
sortHandle = (sortAction) -> controller.sortStocksBy(sortAction);
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/finish/FinishController.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/finish/FinishController.java
new file mode 100644
index 0000000..4ad3014
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/finish/FinishController.java
@@ -0,0 +1,163 @@
+package edu.ntnu.idi.idatt.view.primary.finish;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+
+import edu.ntnu.idi.idatt.model.portfolio.Share;
+import edu.ntnu.idi.idatt.session.UserSession;
+import edu.ntnu.idi.idatt.view.components.AbstractController;
+import edu.ntnu.idi.idatt.view.util.CssUtils;
+import javafx.scene.Parent;
+
+/**
+ * Controller class of Finish MVC.
+ */
+public class FinishController extends AbstractController {
+
+ private UserSession session = UserSession.getInstance();
+
+ /**
+ * Constructor for FinishController.
+ *
+ * Initializes finalized game state.
+ *
+ */
+ public FinishController(FinishModel model) {
+ super(model);
+ makeFinishedGameState();
+ }
+
+ /**
+ * Method for creating a finalized gamestate.
+ *
+ *
+ * Sells all holdings and updates the game state a final time.
+ *
+ */
+ public void makeFinishedGameState() {
+ // Sell all shares
+
+ // Copy shares (Avoid ConcurrentModificationException)
+ ArrayList holdings = new ArrayList<>(session.getPlayer().getPortfolio().getShares());
+
+ // Sell
+ holdings.forEach(share -> session.getExchange().sell(share, session.getPlayer()));
+
+ // Update gamestate
+ session.updateGameState();
+
+ }
+
+ /**
+ * Method for getting formatted week.
+ *
+ * @return Week string.
+ */
+ public String getWeek() {
+ return String.format("Week: %d", session.getExchange().getWeek());
+ }
+
+ /**
+ * Method for getting formatted transaction amount.
+ *
+ * @return transaction amount string.
+ */
+ public String getTransactionAmount() {
+ return String.format("Transactions made: %d",
+ session.getPlayer().getTransactionArchive().getTransactions().size());
+ }
+
+ /**
+ * Method for getting formatted player status.
+ *
+ * @return player status string.
+ */
+ public String getPlayerStatus() {
+ return String.format("Player status: %s",
+ session.getPlayer().getStatus());
+ }
+
+ /**
+ * Method for getting formatted player name.
+ *
+ * @return player name string.
+ */
+ public String getPlayerName() {
+ return String.format("Player name: %s", session.getPlayer().getName());
+ }
+
+ /**
+ * Method for getting formatted total net worth.
+ *
+ * @return total net worth string.
+ */
+ public String getTotalNetWorth() {
+ return String.format("Total net worth: %.2f $",
+ session.getPlayer().getMoney());
+ }
+
+ /**
+ * Method for calculating total profits.
+ *
+ * @return BigDecimal profits;
+ */
+ private BigDecimal calculateProfits() {
+ BigDecimal profit = session.getPlayer().getMoney().subtract(
+ session.getPlayer().getStartingMoney());
+ return profit;
+ }
+
+ /**
+ * Method for calculating total return on investements.
+ *
+ * @return BigDecimal return of investements;
+ */
+ private BigDecimal calculateROI() {
+ BigDecimal profit = session.getPlayer().getMoney().subtract(
+ session.getPlayer().getStartingMoney());
+ BigDecimal profitPercent = profit.divide(session.getPlayer().getStartingMoney()).setScale(2, RoundingMode.HALF_UP);
+
+ BigDecimal returnOfInvestement = profitPercent.multiply(new BigDecimal("100"));
+
+ return returnOfInvestement;
+ }
+
+ /**
+ * Method for getting formatted total profits.
+ *
+ * @return total profits string.
+ */
+ public String getProfits() {
+ return String.format("Total profits: %.2f $",
+ calculateProfits());
+ }
+
+ /**
+ * Method for getting formatted return of investement.
+ *
+ * @return return of investement string.
+ */
+ public String getROI() {
+ return String.format("Return of investement: %.2f %%", calculateROI());
+ }
+
+ /**
+ * Method for applying color to profit label.
+ *
+ * @param profitsLabel - Profit label.
+ */
+ public void setProfitsColor(Parent profitsLabel) {
+ CssUtils.apply(profitsLabel, CssUtils.generateValueColors(calculateProfits()));
+ }
+
+ /**
+ * Method for applying color to return of investement label.
+ *
+ * @param roiLabel - return of investement label.
+ */
+ public void setRoiColor(Parent roiLabel) {
+ CssUtils.apply(roiLabel, CssUtils.generateValueColors(calculateROI()));
+ }
+
+}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/finish/FinishModel.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/finish/FinishModel.java
new file mode 100644
index 0000000..0b958cd
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/finish/FinishModel.java
@@ -0,0 +1,14 @@
+package edu.ntnu.idi.idatt.view.primary.finish;
+
+import edu.ntnu.idi.idatt.view.components.Model;
+
+/**
+ * Model class for Finish MVC.
+ *
+ *
+ * No contents, just to suit the MVC model creation.
+ *
+ */
+public class FinishModel implements Model {
+
+}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/finish/FinishView.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/finish/FinishView.java
new file mode 100644
index 0000000..1fef67c
--- /dev/null
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/finish/FinishView.java
@@ -0,0 +1,118 @@
+package edu.ntnu.idi.idatt.view.primary.finish;
+
+import java.util.List;
+
+import edu.ntnu.idi.idatt.view.SceneFactory;
+import edu.ntnu.idi.idatt.view.SceneManager;
+import edu.ntnu.idi.idatt.view.components.AbstractView;
+import edu.ntnu.idi.idatt.view.components.ui.UICompositor;
+import edu.ntnu.idi.idatt.view.util.CssUtils;
+import javafx.application.Platform;
+import javafx.geometry.Pos;
+import javafx.scene.Parent;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Region;
+import javafx.scene.layout.StackPane;
+import javafx.scene.layout.VBox;
+
+/**
+ * View class of Finish MVC.
+ */
+public class FinishView extends AbstractView {
+
+ /**
+ * Constructor for FinishView.
+ */
+ public FinishView() {
+ StackPane root = new StackPane();
+ super(root);
+ root.getStyleClass().add("dark");
+ }
+
+ Label playerName;
+ Label playerStatus;
+ Label weeksPassed;
+ Label transactionsAmount;
+ Label totalNetWorth;
+ Label totalProfits;
+ Label returnOfInvestement;
+
+ Button newGame;
+ Button exit;
+
+ /**
+ * Override of the createContent() method.
+ *
+ * @see AbstractView
+ */
+ @Override
+ public Parent createContent() {
+
+ Label title = new Label("Finished game! - Summary");
+ CssUtils.apply(title, CssUtils.BIG_TEXT_32);
+
+ playerName = new Label();
+ playerStatus = new Label();
+ weeksPassed = new Label();
+ transactionsAmount = new Label();
+ totalNetWorth = new Label();
+ totalProfits = new Label();
+ returnOfInvestement = new Label();
+
+ List labels = List.of(playerName, playerStatus, new Label(" "), weeksPassed, transactionsAmount,
+ totalNetWorth, totalProfits,
+ returnOfInvestement);
+
+ labels.forEach(l -> CssUtils.apply(l, CssUtils.MED_TEXT_16));
+
+ newGame = new Button("New Game");
+ exit = new Button("Quit");
+
+ newGame.getStyleClass().add("button");
+ exit.getStyleClass().add("button");
+
+ UICompositor.Builder finishUIBuilder = new UICompositor.Builder()
+ .parent(new VBox())
+ .growWithAlignment(Pos.CENTER)
+ .addContent(title);
+
+ labels.forEach(l -> finishUIBuilder.addContent(l));
+
+ finishUIBuilder
+ .wrap(new HBox(10))
+ .growWithAlignment(Pos.CENTER)
+ .addAllContent(newGame, exit)
+ .properties(p -> p.getChildren().forEach(c -> ((Region) c).setPrefWidth(200)))
+ .unwrap();
+
+ return finishUIBuilder.build().makeUI();
+
+ }
+
+ /**
+ * Method for setting the FinishController.
+ *
+ * Handles events and actions of the view.
+ *
+ *
+ * @param controller - FinishController instance.
+ */
+ public void setController(FinishController controller) {
+ playerName.setText(controller.getPlayerName());
+ playerStatus.setText(controller.getPlayerStatus());
+ weeksPassed.setText(controller.getWeek());
+ transactionsAmount.setText(controller.getTransactionAmount());
+ totalNetWorth.setText(controller.getTotalNetWorth());
+ totalProfits.setText(controller.getProfits());
+ returnOfInvestement.setText(controller.getROI());
+
+ controller.setProfitsColor(totalProfits);
+ controller.setRoiColor(returnOfInvestement);
+
+ newGame.setOnAction((e) -> SceneManager.switchTo(SceneFactory.createStartView()));
+ exit.setOnAction((e) -> Platform.exit());
+ }
+
+}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/newspaper/NewspaperController.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/newspaper/NewspaperController.java
index 23904da..8b9069b 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/newspaper/NewspaperController.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/newspaper/NewspaperController.java
@@ -7,12 +7,21 @@
import java.util.ArrayList;
+/**
+ * Controller class for Newspaper MVC.
+ */
public class NewspaperController extends AbstractController {
private final ArrayList loadedNewsList = new ArrayList<>();
private Stock stock;
+ /**
+ * Constructor for NewspaperController.
+ *
+ * @param model - NewspaperModel instance.
+ * @param stock - Current instance of the stock to create newspaper for.
+ */
public NewspaperController(NewspaperModel model, Stock stock) {
super(model);
this.stock = stock;
@@ -21,6 +30,11 @@ public NewspaperController(NewspaperModel model, Stock stock) {
model.getNewsList().setAll(loadedNewsList);
}
+ /**
+ * Getter for stock toString.
+ *
+ * @return String;
+ */
public String getStock() {
return stock.toString();
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/newspaper/NewspaperModel.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/newspaper/NewspaperModel.java
index 23821fa..e5499be 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/newspaper/NewspaperModel.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/newspaper/NewspaperModel.java
@@ -5,9 +5,17 @@
import javafx.collections.ObservableList;
import javafx.scene.control.Label;
+/**
+ * Model class of Newspaper MVC.
+ */
public class NewspaperModel implements Model {
private final ObservableList newsList = FXCollections.observableArrayList();
+ /**
+ * Getter for newsList.
+ *
+ * @return ObservableList
+ */
public ObservableList getNewsList() {
return newsList;
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/newspaper/NewspaperView.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/newspaper/NewspaperView.java
index e341f5c..b5ae773 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/newspaper/NewspaperView.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/newspaper/NewspaperView.java
@@ -17,10 +17,18 @@
import java.util.List;
+/**
+ * View class of Newspaper MVC.
+ */
public class NewspaperView extends AbstractViewUI {
private VBox root;
private Label title;
+ /**
+ * Override of createContent() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createContent() {
@@ -49,34 +57,75 @@ public Parent createContent() {
}
+ /**
+ * Override of the createNavigation() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createNavigation() {
- return UIFactory.createNavigation(" Newspaper", List.of());
+ return UIFactory.createNavigation(" Newspaper",
+ List.of("Home"),
+ () -> SceneManager.switchTo(SceneFactory.createExchangeView(true)));
}
+ /**
+ * Override of the createHeader() method.
+ *
+ * Leaving empty, since it's not used.
+ *
+ *
+ * @see AbstractViewUI.
+ */
@Override
public Parent createHeader() {
return new HBox();
}
+ /**
+ * Override of the createtoolbar() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createToolbar() {
return UIFactory.createToolbar(() -> this.toggleMenu(),
() -> SceneManager.switchTo(SceneFactory.createStartView()));
}
+ /**
+ * Override of the createMenu() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createMenu() {
return UIFactory.createMenu("Account",
- List.of(" • Portfolio", " • Transactions"),
+ List.of("Portfolio", "Transactions"),
() -> SceneManager.switchTo(SceneFactory.createPortfolioView()),
() -> SceneManager.switchTo(SceneFactory.createTransactionView()));
}
+ /**
+ * Setter for NewspaperModel.
+ *
+ * Binds model data together with the view.
+ *
+ *
+ * @param model - NewspaperModel instance.
+ */
public void setModel(NewspaperModel model) {
Bindings.bindContent(root.getChildren(), model.getNewsList());
}
+ /**
+ * Setter for NewspaperController.
+ *
+ * Controls events and actions from the view.
+ *
+ *
+ * @param controller - NewspaperController instance.
+ */
public void setController(NewspaperController controller) {
title.setText(String.format("Newspaper - %s", controller.getStock()));
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioController.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioController.java
index 0254c2a..f72cc55 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioController.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioController.java
@@ -2,20 +2,34 @@
import edu.ntnu.idi.idatt.model.portfolio.Portfolio;
import edu.ntnu.idi.idatt.model.portfolio.Share;
+import edu.ntnu.idi.idatt.model.transaction.Sale;
import edu.ntnu.idi.idatt.service.transaction.SaleCalculator;
import edu.ntnu.idi.idatt.session.UserSession;
+import edu.ntnu.idi.idatt.view.SceneFactory;
+import edu.ntnu.idi.idatt.view.SceneManager;
import edu.ntnu.idi.idatt.view.components.AbstractController;
+import edu.ntnu.idi.idatt.view.components.elements.RecieptComponent;
import edu.ntnu.idi.idatt.view.components.elements.ShareComponent;
import edu.ntnu.idi.idatt.view.components.ui.UIAlert;
import edu.ntnu.idi.idatt.view.util.CssUtils;
+import javafx.scene.effect.GaussianBlur;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
+/**
+ * Constructor class of Portfolio MVC.
+ */
public class PortfolioController extends AbstractController {
+ /**
+ * SortAction enum.
+ *
+ * Enum for handeling sorting operations.
+ *
+ */
public enum SortAction {
OLDEST,
NEWEST,
@@ -26,6 +40,15 @@ public enum SortAction {
private final ArrayList sharesSorted = new ArrayList<>();
private UserSession session = UserSession.getInstance();
+ /**
+ * Constructor for PortfolioController.
+ *
+ * Loads initial shares to the portfolio.
+ *
+ *
+ * @param model - Reference to the PortfolioModel instance.
+ * @see PortfolioModel
+ */
public PortfolioController(PortfolioModel model) {
super(model);
List initialSharesLoad = session.getPlayer().getPortfolio().getShares();
@@ -35,21 +58,46 @@ public PortfolioController(PortfolioModel model) {
initController();
}
+ /**
+ * Method for setting new shares to the model list.
+ *
+ *
+ * Converts shares into ShareComponents.
+ *
+ *
+ * @param shareList - List of shares to be set.
+ */
public void setShareModel(List shareList) {
model.getShareList().clear();
for (Share share : shareList) {
ShareComponent shareComponent = new ShareComponent(share);
shareComponent.onShareSellButton((sellShare) -> holdingSale(sellShare));
+ shareComponent.onShareClick((stockSymbol) -> SceneManager.switchTo(SceneFactory.createStockView(stockSymbol)));
model.getShareList().add(shareComponent);
}
}
+ /**
+ * Method for initializing controller dependencies.
+ *
+ * Sets up initial model values and activates listener.
+ *
+ */
public void initController() {
setupPlayerInfo();
-
+ model.searchQueryProperty().addListener((obs) -> handleSearchQuery());
}
+ /**
+ * Method for attemting Share sale.
+ *
+ *
+ * Displays alert, and updates gamestate on sucess.
+ *
+ *
+ * @param share - chosen sell share.
+ */
public void holdingSale(Share share) {
UIAlert sellConfirmation = new UIAlert("Confirmation required",
@@ -63,13 +111,62 @@ public void holdingSale(Share share) {
return;
}
- session.getExchange().sell(share, session.getPlayer());
+ Sale sale = (Sale) session.getExchange().sell(share, session.getPlayer());
session.updateGameState();
+ showReciept(sale);
setupPlayerInfo(); // Reload player information section
sortSharesBy(SortAction.OLDEST); // Reset loaded shares.
}
+ /**
+ * Method for showing transaction reciept.
+ *
+ * @param sale - Transaction completed.
+ */
+ public void showReciept(Sale sale) {
+ GaussianBlur blur = new GaussianBlur(15);
+ model.instanceEffects().set(blur);
+
+ RecieptComponent reciept = new RecieptComponent(sale);
+ reciept.onExitButton(() -> {
+ model.instanceEffects().set(null);
+ model.instanceChildren().remove(reciept);
+ });
+
+ model.instanceChildren().add(reciept);
+ }
+
+ /**
+ * Method for finishing the game.
+ *
+ * Displays alert and switches view.
+ *
+ */
+ public void eventFinishGame() {
+
+ UIAlert askFinish = new UIAlert(
+ "Confirmation required.",
+ "Do you wish to finish the game?",
+ "This action is not reversable. A player summary " +
+ "of the playthrough will be shown, followed with account deletion.");
+
+ boolean status = askFinish.displayAwaitResponse();
+
+ if (!status) {
+ return;
+ }
+
+ SceneManager.switchTo(SceneFactory.createFinishView());
+
+ }
+
+ /**
+ * Method for setting up initial portfolio information.
+ *
+ * Fills the model properties with user portfolio information.
+ *
+ */
public void setupPlayerInfo() {
Portfolio portfolio = session.getPlayer().getPortfolio();
@@ -90,19 +187,62 @@ public void setupPlayerInfo() {
model.playerInfoModel().getTotalSharesOwned().set(ownedShares);
}
- public void handleSearchQuery(String query) {
- if (query == null || query.isBlank()) {
+ /**
+ * Method for handeling searchbar search.
+ *
+ *
+ * Sets share list model to found after name.
+ *
+ *
+ */
+ public void handleSearchQuery() {
+ if (model.searchQueryProperty().get() == null || model.searchQueryProperty().get().isBlank()) {
+ setShareModel(sharesSorted); // Get back to "no search"
+ return;
+ }
+
+ List sharesFound = sharesSorted.stream()
+ .filter(share -> share.getStock().toString().toLowerCase()
+ .contains(model.searchQueryProperty().get().toLowerCase()))
+ .toList();
+
+ setShareModel(sharesFound);
+
+ }
+
+ /**
+ * Overloaded method for handeling searchbar search.
+ *
+ *
+ * Sets share list model to found after name.
+ *
+ *
+ * @param initialSearch - initial search input.
+ *
+ */
+ public void handleSearchQuery(String initialSearch) {
+ if (initialSearch == null || initialSearch.isBlank()) {
setShareModel(sharesSorted); // Get back to "no search"
return;
}
List sharesFound = sharesSorted.stream()
- .filter(share -> share.getStock().toString().toLowerCase().contains(query.toLowerCase())).toList();
+ .filter(share -> share.getStock().toString().toLowerCase()
+ .contains(initialSearch.toLowerCase()))
+ .toList();
setShareModel(sharesFound);
}
+ /**
+ * Method for sorting shares.
+ *
+ * Searches after the available SortAction given.
+ *
+ *
+ * @param action - SortAction instance.
+ */
public void sortSharesBy(SortAction action) {
sharesSorted.clear();
sharesSorted.addAll(session.getPlayer().getPortfolio().getShares());
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioModel.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioModel.java
index 36f0dd3..1ea8088 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioModel.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioModel.java
@@ -3,20 +3,68 @@
import edu.ntnu.idi.idatt.view.components.Model;
import edu.ntnu.idi.idatt.view.components.elements.ShareComponent;
import edu.ntnu.idi.idatt.view.primary.portfolio.viewmodel.PlayerInfoModel;
+import javafx.beans.property.SimpleObjectProperty;
+import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
+import javafx.scene.Node;
+import javafx.scene.effect.Effect;
+/**
+ * Model class of the Portfolio MVC.
+ */
public class PortfolioModel implements Model {
private final ObservableList shareList = FXCollections.observableArrayList();
+ private final SimpleStringProperty searchQueryProperty = new SimpleStringProperty();
private final PlayerInfoModel playerInfoModel = new PlayerInfoModel();
+ /**
+ * Getter for the shareList property.
+ *
+ * @return ObservableList;
+ */
public ObservableList getShareList() {
return shareList;
}
+ /**
+ * Getter for search query property.
+ *
+ * @return SimpleStringProperty;
+ */
+ public SimpleStringProperty searchQueryProperty() {
+ return searchQueryProperty;
+ }
+
+ /**
+ * Getter for the playerInfoModel.
+ *
+ * @return PlayerInfoModel;
+ */
public PlayerInfoModel playerInfoModel() {
return playerInfoModel;
}
+ private final SimpleObjectProperty instanceEffects = new SimpleObjectProperty<>();
+ private final ObservableList instanceChildren = FXCollections.observableArrayList();
+
+ /**
+ * Getter for the view's root instance effects.
+ *
+ * @return SimpleObjectProperty;
+ */
+ public SimpleObjectProperty instanceEffects() {
+ return instanceEffects;
+ }
+
+ /**
+ * Getter for the view's root instance children.
+ *
+ * @return SimpleObjectProperty;
+ */
+ public ObservableList instanceChildren() {
+ return instanceChildren;
+ }
+
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioView.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioView.java
index f2c1ba1..132dc30 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioView.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioView.java
@@ -8,6 +8,7 @@
import edu.ntnu.idi.idatt.view.primary.portfolio.sections.PlayerInfoSection;
import edu.ntnu.idi.idatt.view.primary.portfolio.viewmodel.PlayerInfoModel;
import javafx.beans.binding.Bindings;
+import javafx.beans.property.SimpleStringProperty;
import javafx.geometry.Insets;
import javafx.scene.Parent;
import javafx.scene.control.ScrollPane;
@@ -16,14 +17,22 @@
import java.util.List;
import java.util.function.Consumer;
+/**
+ * View class of the Portfolio MVC.
+ */
public class PortfolioView extends AbstractViewUI {
- Consumer searchQueryHandler;
- Consumer sortHandle;
+ private SimpleStringProperty searchQueryProperty;
+ private Consumer sortHandle;
private VBox shareList;
private PlayerInfoSection playerInfoSection;
+ /**
+ * Override of createContent() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createContent() {
BorderPane root = new BorderPane();
@@ -42,17 +51,27 @@ public Parent createContent() {
return root;
}
+ /**
+ * Override of the createNavigation() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createNavigation() {
return UIFactory.createNavigation("Portfolio",
- List.of(" • Title"),
- () -> System.out.println("Newspaper clicked"));
+ List.of("Home"),
+ () -> SceneManager.switchTo(SceneFactory.createExchangeView(true)));
}
+ /**
+ * Override of the createHeader() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createHeader() {
return UIFactory.createHeader("Search after holdings..",
- query -> searchQueryHandler.accept(query),
+ queryProperty -> searchQueryProperty = queryProperty,
List.of(
"Oldest first",
"Newest first",
@@ -64,27 +83,57 @@ public Parent createHeader() {
() -> sortHandle.accept(SortAction.LOSS));
}
+ /**
+ * Override of the createToolbar() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createToolbar() {
return UIFactory.createToolbar(() -> this.toggleMenu(),
() -> SceneManager.switchTo(SceneFactory.createStartView()));
}
+ /**
+ * Override of the createMenu() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createMenu() {
return UIFactory.createMenu("Account",
- List.of(" • Portfolio", " • Transactions"),
+ List.of("Portfolio", "Transactions"),
() -> {
},
() -> SceneManager.switchTo(SceneFactory.createTransactionView()));
}
+ /**
+ * Setter for the PortfolioModel.
+ *
+ * Binds model data with the view nodes.
+ *
+ *
+ * @param model - PortfolioModel instance.
+ */
public void setModel(PortfolioModel model) {
Bindings.bindContent(shareList.getChildren(), model.getShareList());
+ model.searchQueryProperty().bind(searchQueryProperty);
setPlayerInfoSectionModel(model.playerInfoModel());
+
+ this.getInstance().getChildren().forEach(c -> c.effectProperty().bind(model.instanceEffects()));
+ Bindings.bindContentBidirectional(model.instanceChildren(), this.getInstance().getChildren());
}
+ /**
+ * Setter for PlayerInfoModel.
+ *
+ * Binds PlayerInfoModel data with the PlayerInfoSection nodes.
+ *
+ *
+ * @param model - PlayerInfoModel instance.
+ */
public void setPlayerInfoSectionModel(PlayerInfoModel model) {
playerInfoSection.getTitle().textProperty().bind(model.getTitle());
playerInfoSection.getNetWorth().textProperty().bind(model.getNetWorth());
@@ -96,9 +145,17 @@ public void setPlayerInfoSectionModel(PlayerInfoModel model) {
playerInfoSection.getTotalSharesOwned().textProperty().bind(model.getTotalSharesOwned());
}
+ /**
+ * Setter for PortfolioController.
+ *
+ * Handles events and action of view nodes for interactibility
+ *
+ *
+ * @param controller - PortfolioController instance.
+ */
public void setController(PortfolioController controller) {
- searchQueryHandler = (query) -> controller.handleSearchQuery(query);
sortHandle = (sortAction) -> controller.sortSharesBy(sortAction);
+ playerInfoSection.finishButtonClicked(() -> controller.eventFinishGame());
}
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/sections/PlayerInfoSection.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/sections/PlayerInfoSection.java
index a40b840..2968661 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/sections/PlayerInfoSection.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/sections/PlayerInfoSection.java
@@ -3,14 +3,24 @@
import java.util.List;
import edu.ntnu.idi.idatt.view.components.elements.TextValueComponent;
+import edu.ntnu.idi.idatt.view.components.primitives.ActionEventHandler;
import edu.ntnu.idi.idatt.view.components.ui.UICompositor;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
+import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
+/**
+ * Section class of Portfolio MVC.
+ *
+ * This is a component of the PortfolioView.
+ *
+ *
+ * @see PortfolioView
+ */
public class PlayerInfoSection extends VBox {
Label title = new Label();
@@ -18,7 +28,11 @@ public class PlayerInfoSection extends VBox {
TextValueComponent netWorthTotalChange = new TextValueComponent("Total portfolio net worth change: ");
Label playerStatus = new Label();
Label totalSharesOwned = new Label();
+ Button finishGameButton;
+ /**
+ * Constructor for PlayerInfoSection
+ */
public PlayerInfoSection() {
title.getStyleClass().add("portfolio-box-title");
@@ -26,6 +40,14 @@ public PlayerInfoSection() {
List labels = List.of(netWorth, playerStatus, totalSharesOwned);
labels.forEach(l -> l.getStyleClass().add("portfolio-box-text"));
+ // Override
+ netWorthTotalChange.getStyleClass().clear();
+ netWorthTotalChange.getStyleClass().add("portfolio-box-text");
+
+ finishGameButton = new Button("Finish game");
+ finishGameButton.getStyleClass().add("button");
+ finishGameButton.setMaxWidth(Double.MAX_VALUE);
+
new UICompositor.Builder()
.parent(this)
.properties((parent) -> {
@@ -45,31 +67,65 @@ public PlayerInfoSection() {
.filler()
.wrap(new VBox())
.growWithAlignment(Pos.BOTTOM_CENTER)
- .addAllContent(playerStatus, totalSharesOwned)
+ .addAllContent(playerStatus, totalSharesOwned, finishGameButton)
.unwrap()
.unwrap()
.build();
}
+ /**
+ * Getter for title.
+ *
+ * @return Label;
+ */
public Label getTitle() {
return title;
}
+ /**
+ * Getter for net worth.
+ *
+ * @return Label;
+ */
public Label getNetWorth() {
return netWorth;
}
+ /**
+ * Getter for net worth total change.
+ *
+ * @return TextValueComponent;
+ */
public TextValueComponent getNetWorthTotalChange() {
return netWorthTotalChange;
}
+ /**
+ * Getter for player status.
+ *
+ * @return Label;
+ */
public Label getPlayerStatus() {
return playerStatus;
}
+ /**
+ * Getter for total shares owned.
+ *
+ * @return Label;
+ */
public Label getTotalSharesOwned() {
return totalSharesOwned;
}
+ /**
+ * Method for redirecting finish button clicked.
+ *
+ * @param handler - Functional interface.
+ */
+ public void finishButtonClicked(ActionEventHandler handler) {
+ finishGameButton.setOnAction((e) -> handler.handle());
+ }
+
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/viewmodel/PlayerInfoModel.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/viewmodel/PlayerInfoModel.java
index 6afc3e3..fd5202d 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/viewmodel/PlayerInfoModel.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/viewmodel/PlayerInfoModel.java
@@ -2,6 +2,14 @@
import javafx.beans.property.SimpleStringProperty;
+/**
+ * ViewModel class of PlayerInfo.
+ *
+ * This is a component of the PortfolioModel.
+ *
+ *
+ * @see PortfolioModel
+ */
public class PlayerInfoModel {
private final SimpleStringProperty title = new SimpleStringProperty();
@@ -13,26 +21,56 @@ public class PlayerInfoModel {
private final SimpleStringProperty playerStatus = new SimpleStringProperty();
private final SimpleStringProperty totalSharesOwned = new SimpleStringProperty();
+ /**
+ * Getter for title property.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getTitle() {
return title;
}
+ /**
+ * Getter for netWorth property.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getNetWorth() {
return netWorth;
}
+ /**
+ * Getter for netWorthTotalChange property.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getNetWorthTotalChange() {
return netWorthTotalChange;
}
+ /**
+ * Getter for netWorthTotalChangeColor property.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getNetWorthTotalChangeColor() {
return netWorthTotalChangeColor;
}
+ /**
+ * Getter for playerStatus property.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getPlayerStatus() {
return playerStatus;
}
+ /**
+ * Getter for totalSharesOwned property.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getTotalSharesOwned() {
return totalSharesOwned;
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/StockController.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/StockController.java
index fbda060..cfd7b42 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/StockController.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/StockController.java
@@ -5,18 +5,25 @@
import edu.ntnu.idi.idatt.model.market.Stock;
import edu.ntnu.idi.idatt.model.portfolio.Share;
+import edu.ntnu.idi.idatt.model.transaction.Purchase;
import edu.ntnu.idi.idatt.service.transaction.PurchaseCalculator;
import edu.ntnu.idi.idatt.session.UserSession;
-import edu.ntnu.idi.idatt.storage.SessionManager;
+import edu.ntnu.idi.idatt.view.SceneFactory;
+import edu.ntnu.idi.idatt.view.SceneManager;
import edu.ntnu.idi.idatt.view.components.AbstractController;
+import edu.ntnu.idi.idatt.view.components.elements.RecieptComponent;
import edu.ntnu.idi.idatt.view.components.ui.UIAlert;
import edu.ntnu.idi.idatt.view.util.CssUtils;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
+import javafx.scene.effect.GaussianBlur;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
+/**
+ * Controller class of Stock MVC.
+ */
public class StockController extends AbstractController {
private UserSession session = UserSession.getInstance();
@@ -26,6 +33,12 @@ public class StockController extends AbstractController {
private Share share;
private PurchaseCalculator purchaseCalculator;
+ /**
+ * Constructor for StockController.
+ *
+ * @param model - Reference to the StockModel instance.
+ * @param stock - Destined stock to create the context for.
+ */
public StockController(StockModel model, Stock stock) {
super(model);
formatter.setMaximumFractionDigits(3);
@@ -34,6 +47,12 @@ public StockController(StockModel model, Stock stock) {
initController();
}
+ /**
+ * Method for initializing controller methods.
+ *
+ * Loads initial model fields with stock information.
+ *
+ */
private void initController() {
renderGraph();
setCurrentPrice();
@@ -45,10 +64,21 @@ private void initController() {
initHooks();
}
+ /**
+ * Method for obtaining stock symbol.
+ *
+ * @return String;
+ */
public String getSymbol() {
return this.stock.getSymbol();
}
+ /**
+ * Method for rendering stock price graph.
+ *
+ * Creates and fills the graph context with current stock values.
+ *
+ */
public void renderGraph() {
NumberAxis xAxis = new NumberAxis();
NumberAxis yAxis = new NumberAxis();
@@ -72,6 +102,9 @@ public void renderGraph() {
model.getGraphNodes().setAll(lineChart);
}
+ /**
+ * Method for resetting model fields.
+ */
private void resetDisplayBuffers() {
model.tradeModel().getBuyPrice().set("0 $");
model.tradeModel().getBuyCost().set("0 $");
@@ -80,11 +113,24 @@ private void resetDisplayBuffers() {
model.tradeModel().getResultMessageColorProperty().set(CssUtils.RED);
}
+ /**
+ * Method for updating live transaction information.
+ *
+ * Creates a listener for the purchase input field.
+ *
+ */
private void initHooks() {
resetDisplayBuffers();
model.tradeModel().getBuyInputField().addListener((obervable, oldVal, newVal) -> displayBuyInfo(newVal));
}
+ /**
+ * Method for handeling buy attempt.
+ *
+ * Executes on Buy button clicked, and attempts to buy the stock.
+ * On success, updates the game state.
+ *
+ */
public void buyButtonClicked() {
if (share == null || purchaseCalculator == null) {
resetDisplayBuffers(); // Flush after color change and new press.
@@ -92,8 +138,8 @@ public void buyButtonClicked() {
return;
}
- BigDecimal purchase = session.getPlayer().getMoney().subtract(purchaseCalculator.calculateTotal());
- if (purchase.compareTo(BigDecimal.ZERO) <= 0) {
+ BigDecimal purchaseCost = session.getPlayer().getMoney().subtract(purchaseCalculator.calculateTotal());
+ if (purchaseCost.compareTo(BigDecimal.ZERO) <= 0) {
// Flush after color change and new press, while still calculating everything.
model.tradeModel().getResultMessageColorProperty().set(CssUtils.RED);
model.tradeModel().getResultMessage().set("Balance too low.");
@@ -113,14 +159,51 @@ public void buyButtonClicked() {
return;
}
- session.getExchange().buy(share.getStock().getSymbol(), share.getQuantity(), session.getPlayer());
+ Purchase purchase = (Purchase) session.getExchange().buy(
+ share.getStock().getSymbol(),
+ share.getQuantity(),
+ session.getPlayer());
this.setOwnedAmount();
this.setTotalProfits();
model.tradeModel().getResultMessageColorProperty().set(CssUtils.GREEN);
model.tradeModel().getResultMessage().set("Purchase completed!");
session.updateGameState();
+ showReciept(purchase);
}
+ /**
+ * Method to execute on portfolio button clicked.
+ *
+ * Navigates to portfolio with this stock as deafult search.
+ *
+ */
+ public void portfolioButtonClicked() {
+ SceneManager.switchTo(SceneFactory.createPortfolioView(getSymbol()));
+ }
+
+ /**
+ * Method for showing transaction reciept.
+ *
+ * @param purchase - Transaction performed.
+ */
+ public void showReciept(Purchase purchase) {
+ GaussianBlur blur = new GaussianBlur(15);
+ model.instanceEffects().set(blur);
+
+ RecieptComponent reciept = new RecieptComponent(purchase);
+ reciept.onExitButton(() -> {
+ model.instanceEffects().set(null);
+ model.instanceChildren().remove(reciept);
+ });
+
+ model.instanceChildren().add(reciept);
+ }
+
+ /**
+ * Method for displaying buy info based on view's input amount.
+ *
+ * @param amountString - Amount from input field.
+ */
private void displayBuyInfo(String amountString) {
resetDisplayBuffers(); // Reset buffers
share = null;
@@ -157,10 +240,22 @@ private void displayBuyInfo(String amountString) {
model.tradeModel().getTotalPrice().set(total);
}
+ /**
+ * Setter for current price.
+ *
+ * Sets model property to this value.
+ *
+ */
public void setCurrentPrice() {
model.priceInfoModel().getStockPrice().set(String.format("%.2f $", this.stock.getSalesPrice()));
}
+ /**
+ * Setter for latest change percent.
+ *
+ * Sets model property to this value.
+ *
+ */
public void setLatestChange() {
BigDecimal change = this.stock.getLatestPriceChange();
BigDecimal changePercent = this.stock.getLatestPriceChangePercent();
@@ -171,6 +266,12 @@ public void setLatestChange() {
model.priceInfoModel().getLatestChangeColorProperty().set(CssUtils.generateValueColors(change.doubleValue()));
}
+ /**
+ * Setter for all time score.
+ *
+ * Sets model property to this value.
+ *
+ */
public void setAllTimeScore() {
BigDecimal highest = this.stock.getHighestPrice();
BigDecimal lowest = this.stock.getLowestPrice();
@@ -180,6 +281,12 @@ public void setAllTimeScore() {
model.priceInfoModel().getAllTimeScore().set(format);
}
+ /**
+ * Setter for owned stock amount.
+ *
+ * Sets model property to this value.
+ *
+ */
public void setOwnedAmount() {
BigDecimal ownedAmount = session.getPlayer().getPortfolio().getOwnedAmount(
this.stock.getSymbol());
@@ -190,6 +297,12 @@ public void setOwnedAmount() {
model.priceInfoModel().getOwnedAmount().set(format);
}
+ /**
+ * Setter for total profits.
+ *
+ * Sets model property to this value.
+ *
+ */
public void setTotalProfits() {
BigDecimal profit = session.getPlayer().getPortfolio().getProfitFromStock(
this.stock.getSymbol());
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/StockModel.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/StockModel.java
index 6890812..40b1330 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/StockModel.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/StockModel.java
@@ -3,9 +3,11 @@
import edu.ntnu.idi.idatt.view.components.Model;
import edu.ntnu.idi.idatt.view.primary.stock.viewmodel.PriceInfoModel;
import edu.ntnu.idi.idatt.view.primary.stock.viewmodel.TradeModel;
+import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Node;
+import javafx.scene.effect.Effect;
public class StockModel implements Model {
@@ -18,16 +20,52 @@ public class StockModel implements Model {
// Trade properties
private final TradeModel tradeModel = new TradeModel();
+ private final SimpleObjectProperty instanceEffects = new SimpleObjectProperty<>();
+ private final ObservableList instanceChildren = FXCollections.observableArrayList();
+
+ /**
+ * Getter for graphNodes observable array list.
+ *
+ * @return ObservableList;
+ */
public ObservableList getGraphNodes() {
return this.graphNodes;
}
+ /**
+ * Getter for priceInfoModel.
+ *
+ * @return PriceInfoModel;
+ */
public PriceInfoModel priceInfoModel() {
return priceInfoModel;
}
+ /**
+ * Getter for tradeModel.
+ *
+ * @return TradeModel;
+ */
public TradeModel tradeModel() {
return tradeModel;
}
+ /**
+ * Getter for view's root instance effect property.
+ *
+ * @return SimpleObjectProperty;
+ */
+ public SimpleObjectProperty instanceEffects() {
+ return instanceEffects;
+ }
+
+ /**
+ * Getter for view's root instance children property.
+ *
+ * @return ObservableList;
+ */
+ public ObservableList instanceChildren() {
+ return instanceChildren;
+ }
+
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/StockView.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/StockView.java
index 1ce0871..989ea7c 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/StockView.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/StockView.java
@@ -20,6 +20,9 @@
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
+/**
+ * View class of Stock MVC.
+ */
public class StockView extends AbstractViewUI {
private HBox graphContainer;
@@ -32,6 +35,11 @@ public class StockView extends AbstractViewUI {
// Trade menu
private TradeSection tradeSection;
+ /**
+ * Override of createContent() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createContent() {
VBox root = new VBox();
@@ -58,33 +66,64 @@ public Parent createContent() {
return root;
}
+ /**
+ * Override of createNavigation() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createNavigation() {
return UIFactory.createNavigation(title = new Label(),
- List.of(" • Newspaper"),
+ List.of(
+ "Home",
+ "Newspaper"),
+ () -> SceneManager.switchTo(SceneFactory.createExchangeView(true)),
() -> SceneManager.switchTo(SceneFactory.createNewspaperView(stockSymbol)));
}
+ /**
+ * Override of createHeader() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createHeader() {
return new HBox();
}
+ /**
+ * Override of createToolbar() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createToolbar() {
return UIFactory.createToolbar(() -> this.toggleMenu(),
() -> SceneManager.switchTo(SceneFactory.createStartView()));
}
+ /**
+ * Override of createMenu() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createMenu() {
return UIFactory.createMenu("Account",
- List.of(" • Portfolio", " • Transactions"),
+ List.of("Portfolio", "Transactions"),
() -> SceneManager.switchTo(SceneFactory.createPortfolioView()),
() -> SceneManager.switchTo(SceneFactory.createTransactionView()));
}
+ /**
+ * Setter for StockModel.
+ *
+ * Binds view with model information.
+ *
+ *
+ * @param model - StockModel instance.
+ */
public void setModel(StockModel model) {
// Graph
Bindings.bindContent(graphContainer.getChildren(), model.getGraphNodes());
@@ -95,8 +134,18 @@ public void setModel(StockModel model) {
// Trade section bindings
setTradeSectionModel(model.tradeModel());
+ this.getInstance().getChildren().forEach(c -> c.effectProperty().bind(model.instanceEffects()));
+ Bindings.bindContentBidirectional(model.instanceChildren(), this.getInstance().getChildren());
}
+ /**
+ * Setter for PriceInfoModel.
+ *
+ * Binds PriceInfoSection nodes together with PriceInfoModel fields.
+ *
+ *
+ * @param model - PriceInfoModel instance.
+ */
public void setPriceInfoSectionModel(PriceInfoModel model) {
priceInfoSection.getStockPrice().valueProperty().bind(model.getStockPrice());
@@ -111,6 +160,14 @@ public void setPriceInfoSectionModel(PriceInfoModel model) {
priceInfoSection.getTotalProfits().colorProperty().bind(model.getTotalProfitsColorProperty());
}
+ /**
+ * Setter for TradeModel.
+ *
+ * Binds TradeSection nodes together with TradeModel fields.
+ *
+ *
+ * @param model - TradeModel instance.
+ */
public void setTradeSectionModel(TradeModel model) {
tradeSection.getBuyInputField().textProperty().bindBidirectional(model.getBuyInputField());
tradeSection.getBuyPrice().valueProperty().bind(model.getBuyPrice());
@@ -121,10 +178,17 @@ public void setTradeSectionModel(TradeModel model) {
tradeSection.getResultMessage().colorProperty().bind(model.getResultMessageColorProperty());
}
+ /**
+ * Setter for Stockcontroller.
+ *
+ * Handles the view's events and actions for interactability
+ *
+ */
public void setController(StockController controller) {
title.setText(controller.getSymbol());
stockSymbol = controller.getSymbol();
tradeSection.getBuyButton().setOnAction((e) -> controller.buyButtonClicked());
+ tradeSection.getPortfolioButton().setOnAction((e) -> controller.portfolioButtonClicked());
}
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/sections/PriceInfoSection.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/sections/PriceInfoSection.java
index d375fde..1ef62ff 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/sections/PriceInfoSection.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/sections/PriceInfoSection.java
@@ -3,6 +3,12 @@
import edu.ntnu.idi.idatt.view.components.elements.TextValueComponent;
import javafx.scene.layout.VBox;
+/**
+ * View model of Stock MVC.
+ *
+ * This is a component of the Stock View.
+ *
+ */
public class PriceInfoSection extends VBox {
TextValueComponent stockPrice = new TextValueComponent("Current price: ");
@@ -11,26 +17,57 @@ public class PriceInfoSection extends VBox {
TextValueComponent ownedAmount = new TextValueComponent("Owned amount: ");
TextValueComponent totalProfits = new TextValueComponent("Total profits: ");
+ /**
+ * Constructor of PriceInfoSection
+ *
+ * Sets all components to itself.
+ *
+ */
public PriceInfoSection() {
this.getChildren().addAll(stockPrice, latestChange, allTimeScore, ownedAmount, totalProfits);
}
+ /**
+ * Getter for stockPrice.
+ *
+ * @return TextValueComponent;
+ */
public TextValueComponent getStockPrice() {
return stockPrice;
}
+ /**
+ * Getter for latestChange.
+ *
+ * @return TextValueComponent;
+ */
public TextValueComponent getLatestChange() {
return latestChange;
}
+ /**
+ * Getter for allTimeScore.
+ *
+ * @return TextValueComponent;
+ */
public TextValueComponent getAllTimeScore() {
return allTimeScore;
}
+ /**
+ * Getter for ownedAmount.
+ *
+ * @return TextValueComponent;
+ */
public TextValueComponent getOwnedAmount() {
return ownedAmount;
}
+ /**
+ * Getter for totalProfits.
+ *
+ * @return TextValueComponent;
+ */
public TextValueComponent getTotalProfits() {
return totalProfits;
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/sections/TradeSection.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/sections/TradeSection.java
index 19a599d..5cd3117 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/sections/TradeSection.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/sections/TradeSection.java
@@ -7,55 +7,108 @@
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
+/**
+ * View class of the Stock MVC.
+ *
+ * This is a component of the Stock View.
+ *
+ */
public class TradeSection extends VBox {
Button buyButton = new Button("Buy");
- Button portfolioButton = new Button("Sell in portfolio...");
+ Button portfolioButton = new Button("Sell in Portfolio");
TextField buyInputField = new TextField();
TextValueComponent buyPrice = new TextValueComponent("Price: ");
TextValueComponent buyCost = new TextValueComponent("Taxes & Comission: ");
TextValueComponent totalPrice = new TextValueComponent("Total: ");
TextValueComponent resultMessage = new TextValueComponent("");
+ /**
+ * Constructor of TradeSection.
+ *
+ * Sets the nodes to itself and styles them.
+ *
+ */
public TradeSection() {
HBox wrapper = new HBox();
wrapper.setSpacing(20.0);
wrapper.getChildren().addAll(buyButton, portfolioButton);
+ wrapper.setPadding(new Insets(10, 0, 10, 0));
// Detailing
+
+ buyButton.getStyleClass().add("button-outlined");
+ portfolioButton.getStyleClass().add("button-outlined");
+
buyInputField.setPromptText("Amount of stocks...");
+ buyInputField.getStyleClass().add("searchbar-field");
- this.setPadding(new Insets(20));
- this.setMaxWidth(400);
+ this.setPadding(new Insets(0, 20, 0, 20));
+ this.setMaxWidth(305);
this.getChildren().addAll(wrapper, buyInputField, buyPrice, buyCost, totalPrice, resultMessage);
}
+ /**
+ * Getter for buyButton.
+ *
+ * @return Button;
+ */
public Button getBuyButton() {
return buyButton;
}
+ /**
+ * Getter for portfolioButton.
+ *
+ * @return Button;
+ */
public Button getPortfolioButton() {
return portfolioButton;
}
+ /**
+ * Getter for buyInputField.
+ *
+ * @return TextField;
+ */
public TextField getBuyInputField() {
return buyInputField;
}
+ /**
+ * Getter for buyPrice;
+ *
+ * @return TextValueComponent;
+ */
public TextValueComponent getBuyPrice() {
return buyPrice;
}
+ /**
+ * Getter for buyCost.
+ *
+ * @return TextValueComponent;
+ */
public TextValueComponent getBuyCost() {
return buyCost;
}
+ /**
+ * Getter for totalPrice.
+ *
+ * @return TextValueComponent.
+ */
public TextValueComponent getTotalPrice() {
return totalPrice;
}
+ /**
+ * Getter for resultMessage.
+ *
+ * @return TextValueComponent;
+ */
public TextValueComponent getResultMessage() {
return resultMessage;
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/viewmodel/PriceInfoModel.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/viewmodel/PriceInfoModel.java
index 67c4599..7a32687 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/viewmodel/PriceInfoModel.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/viewmodel/PriceInfoModel.java
@@ -2,6 +2,12 @@
import javafx.beans.property.SimpleStringProperty;
+/**
+ * ViewModel class of the Stock MVC.
+ *
+ * This is a component of the Stock Model.
+ *
+ */
public class PriceInfoModel {
private final SimpleStringProperty stockPrice = new SimpleStringProperty();
@@ -15,30 +21,65 @@ public class PriceInfoModel {
private final SimpleStringProperty totalProfits = new SimpleStringProperty();
private final SimpleStringProperty totalProfitsColorProperty = new SimpleStringProperty();
+ /**
+ * Getter for stockPrice property.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getStockPrice() {
return stockPrice;
}
+ /**
+ * Getter for latestChange property.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getLatestChange() {
return latestChange;
}
+ /**
+ * Getter for latestChangeColorProperty.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getLatestChangeColorProperty() {
return latestChangeColorProperty;
}
+ /**
+ * Getter for allTimeScore property.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getAllTimeScore() {
return allTimeScore;
}
+ /**
+ * Getter for ownedAmount property.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getOwnedAmount() {
return ownedAmount;
}
+ /**
+ * Getter for totalProfits property.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getTotalProfits() {
return totalProfits;
}
+ /**
+ * Getter for totalProfitsColorProperty.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getTotalProfitsColorProperty() {
return totalProfitsColorProperty;
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/viewmodel/TradeModel.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/viewmodel/TradeModel.java
index 4c55bf7..f8d2050 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/viewmodel/TradeModel.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/viewmodel/TradeModel.java
@@ -2,6 +2,12 @@
import javafx.beans.property.SimpleStringProperty;
+/**
+ * ViewModel class of PortfolioMVC.
+ *
+ * This is a component of PortfolioModel.
+ *
+ */
public class TradeModel {
private final SimpleStringProperty buyInputField = new SimpleStringProperty();
@@ -11,26 +17,56 @@ public class TradeModel {
private final SimpleStringProperty buyCost = new SimpleStringProperty();
private final SimpleStringProperty totalPrice = new SimpleStringProperty();
+ /**
+ * Getter for buyInputField property.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getBuyInputField() {
return buyInputField;
}
+ /**
+ * Getter for resultMessage property.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getResultMessage() {
return resultMessage;
}
+ /**
+ * Getter for resultMessageColorProperty.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getResultMessageColorProperty() {
return resultMessageColorProperty;
}
+ /**
+ * Getter for buyPrice property.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getBuyPrice() {
return buyPrice;
}
+ /**
+ * Getter for buyCost property.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getBuyCost() {
return buyCost;
}
+ /**
+ * Getter for totalPrice property.
+ *
+ * @return SimpleStringProperty;
+ */
public SimpleStringProperty getTotalPrice() {
return totalPrice;
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionController.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionController.java
index b7ee8c6..d9bbee1 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionController.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionController.java
@@ -12,8 +12,17 @@
import edu.ntnu.idi.idatt.view.components.AbstractController;
import edu.ntnu.idi.idatt.view.components.elements.TransactionComponent;
+/**
+ * Controller class of the Transaction MVC.
+ */
public class TransactionController extends AbstractController {
+ /**
+ * SortAction enum.
+ *
+ * Defines the possible sort methods.
+ *
+ */
public enum SortAction {
NONE,
NEWEST_DESCENDING,
@@ -27,13 +36,41 @@ public enum SortAction {
private UserSession session = UserSession.getInstance();
private ArrayList transactionsSorted = new ArrayList<>();
+ /**
+ * Constructor of TransactionController.
+ *
+ * Loads initial transactions to the model's observable list.
+ *
+ *
+ * @param model - Reference to the TransactionModel instance.
+ */
public TransactionController(TransactionModel model) {
super(model);
List initialTransactionLoad = session.getPlayer().getTransactionArchive().getTransactions();
transactionsSorted.addAll(initialTransactionLoad);
setTransactionModel(initialTransactionLoad);
+
+ initController();
+ }
+
+ /**
+ * Method for initializing controller.
+ *
+ * Activates listener to searchbar query.
+ *
+ */
+ public void initController() {
+ model.searchQueryProperty().addListener((obs) -> handleSearchQuery());
}
+ /**
+ * Setter for the transactions in the model.
+ *
+ * Converts Transaction into TransactionComponent.
+ *
+ *
+ * @param list - List of transactions to be set.
+ */
public void setTransactionModel(List list) {
model.getTransactionList().clear();
for (Transaction transaction : list) {
@@ -41,19 +78,36 @@ public void setTransactionModel(List list) {
}
}
- public void handleSearchQuery(String query) {
- if (query == null || query.isBlank()) {
+ /**
+ * Method for handeling the searchbar.
+ *
+ * Sets transaction in the model based on query.
+ *
+ *
+ * @param query - Searchbar input.
+ */
+ public void handleSearchQuery() {
+ if (model.searchQueryProperty().get() == null || model.searchQueryProperty().get().isBlank()) {
setTransactionModel(transactionsSorted);
return;
}
List transactionsFound = transactionsSorted.stream()
- .filter(transaction -> transaction.getShare().getStock().toString().toLowerCase().contains(query.toLowerCase()))
+ .filter(transaction -> transaction.getShare().getStock().toString().toLowerCase()
+ .contains(model.searchQueryProperty().get().toLowerCase()))
.toList();
setTransactionModel(transactionsFound);
}
+ /**
+ * Method for sorting transactions.
+ *
+ * Sort transactions after defined sorting methods.
+ *
+ *
+ * @param action - Instance of SortAction enum.
+ */
public void sortTransactionsBy(SortAction action) {
int currentWeek = session.getExchange().getWeek();
transactionsSorted.clear(); // Clear buffers
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionModel.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionModel.java
index 6622bf5..8780c28 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionModel.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionModel.java
@@ -2,15 +2,34 @@
import edu.ntnu.idi.idatt.view.components.Model;
import edu.ntnu.idi.idatt.view.components.elements.TransactionComponent;
+import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
+/**
+ * Model class of the Transaction MVC.
+ */
public class TransactionModel implements Model {
private final ObservableList transactionList = FXCollections.observableArrayList();
+ private final SimpleStringProperty searchQueryProperty = new SimpleStringProperty();
+ /**
+ * Getter for the transactionList.
+ *
+ * @return ObservableList;
+ */
public ObservableList getTransactionList() {
return transactionList;
}
+ /**
+ * Getter for search query property.
+ *
+ * @return SimpleStringProperty;
+ */
+ public SimpleStringProperty searchQueryProperty() {
+ return searchQueryProperty;
+ }
+
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionView.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionView.java
index 4903f74..07a7d8c 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionView.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionView.java
@@ -9,6 +9,7 @@
import edu.ntnu.idi.idatt.view.components.ui.UIFactory;
import edu.ntnu.idi.idatt.view.primary.transactions.TransactionController.SortAction;
import javafx.beans.binding.Bindings;
+import javafx.beans.property.SimpleStringProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Parent;
@@ -16,12 +17,20 @@
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
+/**
+ * View class of the Transaction MVC.
+ */
public class TransactionView extends AbstractViewUI {
- HBox root;
- Consumer searchQueryHandler;
- Consumer sortHandle;
+ private HBox root;
+ private SimpleStringProperty searchQueryProperty;
+ private Consumer sortHandle;
+ /**
+ * Override of createContent() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createContent() {
root = new HBox();
@@ -40,15 +49,27 @@ public Parent createContent() {
return wrapper;
}
+ /**
+ * Override of the createNavigation() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createNavigation() {
- return UIFactory.createNavigation("Transactions", List.of());
+ return UIFactory.createNavigation("Archive",
+ List.of("Home"),
+ () -> SceneManager.switchTo(SceneFactory.createExchangeView(true)));
}
+ /**
+ * Override of the createHeader() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createHeader() {
- return UIFactory.createHeader("Search for transactions...",
- (query) -> searchQueryHandler.accept(query),
+ return UIFactory.createHeader("Search for transactions..",
+ (queryProperty) -> searchQueryProperty = queryProperty,
List.of(
"None",
"Oldest first",
@@ -66,27 +87,53 @@ public Parent createHeader() {
() -> sortHandle.accept(SortAction.LOSS));
}
+ /**
+ * Override of the createToolbar() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createToolbar() {
return UIFactory.createToolbar(() -> this.toggleMenu(),
() -> SceneManager.switchTo(SceneFactory.createStartView()));
}
+ /**
+ * Override of the createMenu() method.
+ *
+ * @see AbstractViewUI
+ */
@Override
public Parent createMenu() {
return UIFactory.createMenu("Account",
- List.of(" • Portfolio", " • Transactions"),
+ List.of("Portfolio", "Transactions"),
() -> SceneManager.switchTo(SceneFactory.createPortfolioView()),
() -> SceneManager.switchTo(SceneFactory.createTransactionView()));
}
+ /**
+ * Setter for TransactionModel.
+ *
+ * Binds view's data together with models fields.
+ *
+ *
+ * @param model - TransactionModel instance.
+ */
public void setModel(TransactionModel model) {
Bindings.bindContent(root.getChildren(), model.getTransactionList());
+ model.searchQueryProperty().bind(searchQueryProperty);
}
+ /**
+ * Setter for TransactionController.
+ *
+ * Handles view's events and action for interactability.
+ *
+ *
+ * @param controller - TransactionController instance.
+ */
public void setController(TransactionController controller) {
- searchQueryHandler = (query) -> controller.handleSearchQuery(query);
sortHandle = (sortAction) -> controller.sortTransactionsBy(sortAction);
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/util/CssUtils.java b/src/main/java/edu/ntnu/idi/idatt/view/util/CssUtils.java
index 4615da6..737d34f 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/util/CssUtils.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/util/CssUtils.java
@@ -4,27 +4,67 @@
import javafx.scene.Parent;
+/**
+ * Utility CSS class.
+ *
+ *
+ * Creates static access to widely CSS tools and
+ * styles to simplify CSS appliance.
+ *
+ */
public class CssUtils {
public static final String BIG_TEXT_32 = "big-text-32";
public static final String MED_TEXT_16 = "med-text-16";
+ public static final String MED_TEXT_24 = "med-text-24";
public static final String SMALL_TEXT_12 = "small-text-12";
public static final String RED = "red";
public static final String GREEN = "green";
+ public static final String GRAY = "gray";
+ /**
+ * Method for applying a css styling.
+ *
+ * @param parent - Parent object to apply for.
+ * @param cssClass - String of css class.
+ */
public static void apply(Parent parent, String cssClass) {
parent.getStyleClass().add(cssClass);
}
+ /**
+ * Method for setting one css styling.
+ *
+ * @param parent - Parent object to apply for.
+ * @param cssClass - String of css class.
+ */
public static void set(Parent parent, String cssClass) {
parent.getStyleClass().clear();
parent.getStyleClass().add(cssClass);
}
+ /**
+ * Method for generating colors based on value.
+ *
+ *
+ * Returns red or green if a value is below or over/equal zero correspondingly.
+ *
+ *
+ * @param value - BigDecimal value.
+ */
public static String generateValueColors(BigDecimal value) {
return value.compareTo(BigDecimal.ZERO) >= 0 ? GREEN : RED;
}
+ /**
+ * Method for generating colors based on value.
+ *
+ *
+ * Returns red or green if a value is below or over/equal zero correspondingly.
+ *
+ *
+ * @param value - double value.
+ */
public static String generateValueColors(double value) {
return value >= 0 ? GREEN : RED;
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/util/ResourceUtils.java b/src/main/java/edu/ntnu/idi/idatt/view/util/ResourceUtils.java
index d40bfce..718dbee 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/util/ResourceUtils.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/util/ResourceUtils.java
@@ -2,10 +2,16 @@
import javafx.scene.image.Image;
+/**
+ * Utility resource class.
+ *
+ *
+ * Creates static instances of components
+ * used often throughout diverse JavaFX classes.
+ *
+ */
public class ResourceUtils {
public static final Image MENU_ICON = new Image(ResourceUtils.class.getResource("/icons/user.png").toExternalForm());
- public static final Image SEARCH_ICON = new Image(
- ResourceUtils.class.getResource("/icons/search.png").toExternalForm());
public static final Image QUIT_ICON = new Image(ResourceUtils.class.getResource("/icons/quit.png").toExternalForm());
}
diff --git a/src/main/resources/icons/portfolio.png b/src/main/resources/icons/portfolio.png
deleted file mode 100644
index 2f33093..0000000
Binary files a/src/main/resources/icons/portfolio.png and /dev/null differ
diff --git a/src/main/resources/icons/quit.png b/src/main/resources/icons/quit.png
index f577227..5359419 100644
Binary files a/src/main/resources/icons/quit.png and b/src/main/resources/icons/quit.png differ
diff --git a/src/main/resources/icons/search.png b/src/main/resources/icons/search.png
deleted file mode 100644
index a206015..0000000
Binary files a/src/main/resources/icons/search.png and /dev/null differ
diff --git a/src/main/resources/icons/user.png b/src/main/resources/icons/user.png
index 0534bdd..63f5db1 100644
Binary files a/src/main/resources/icons/user.png and b/src/main/resources/icons/user.png differ
diff --git a/src/main/resources/stocks.csv b/src/main/resources/stocks.csv
index f9b7ff5..d9cec61 100644
--- a/src/main/resources/stocks.csv
+++ b/src/main/resources/stocks.csv
@@ -1,7 +1,506 @@
+# S&P 500 Companies by Market Cap
# Ticker,Name,Price
-AMD,Advanced Micro Devices,202.68
-MSI,Micro-Star International,92.80
-INTC,Intel,45.58
-NVDA,Nvidia,182.65
-EQNR,Equinor,32.43
+NVDA,Nvidia,191.27
+AAPL,Apple Inc.,276.43
+MSFT,Microsoft,404.68
+AMZN,Amazon,204.62
+GOOGL,Alphabet Inc. (Class A),311.20
+GOOG,Alphabet Inc. (Class C),311.62
+META,Meta Platforms,669.41
+AVGO,Broadcom,343.35
+TSLA,Tesla Inc.,426.52
+BRK.B,Berkshire Hathaway,501.05
+WMT,Walmart,128.75
+LLY,Lilly (Eli),1014.43
+JPM,JPMorgan Chase,311.14
+XOM,ExxonMobil,155.28
+V,Visa Inc.,329.54
+JNJ,Johnson & Johnson,240.70
+MA,Mastercard,539.52
+MU,Micron Technology,411.25
+ORCL,Oracle Corporation,157.08
+COST,Costco,979.71
+BAC,Bank of America,54.06
+ABBV,AbbVie,220.17
+HD,Home Depot (The),389.46
+PG,Procter & Gamble,159.45
+CVX,Chevron Corporation,185.66
+CAT,Caterpillar Inc.,773.53
+AMD,Advanced Micro Devices,213.00
+CSCO,Cisco,85.82
+KO,Coca-Cola Company (The),78.51
+NFLX,Netflix,79.94
+GE,GE Aerospace,314.37
+PLTR,Palantir Technologies,135.59
+LRCX,Lam Research,236.60
+MRK,Merck & Co.,118.79
+PM,Philip Morris International,185.99
+GS,Goldman Sachs,949.29
+MS,Morgan Stanley,176.86
+WFC,Wells Fargo,89.07
+AMAT,Applied Materials,342.19
+RTX,RTX Corporation,197.56
+IBM,IBM,273.86
+UNH,UnitedHealth Group,278.79
+AXP,American Express,355.18
+INTC,Intel,47.85
+TMUS,T-Mobile US,207.62
+PEP,PepsiCo,168.71
+MCD,McDonald's,323.50
+GEV,GE Vernova,822.50
+LIN,Linde plc,466.04
+C,Citigroup,117.93
+TXN,Texas Instruments,226.34
+VZ,Verizon,48.55
+T,AT&T,28.21
+TMO,Thermo Fisher Scientific,525.00
+AMGN,Amgen,364.77
+ABT,Abbott Laboratories,112.97
+KLAC,KLA Corporation,1492.27
+GILD,Gilead Sciences,155.71
+DIS,Walt Disney Company (The),108.30
+NEE,NextEra Energy,91.19
+BA,Boeing,236.98
+ANET,Arista Networks,141.06
+APH,Amphenol,144.60
+ISRG,Intuitive Surgical,496.14
+CRM,Salesforce,184.94
+SCHW,Charles Schwab Corporation,95.50
+BLK,BlackRock,1083.35
+TJX,TJX Companies,150.56
+DE,Deere & Company,610.03
+ADI,Analog Devices,336.71
+LOW,Lowe's,286.57
+PFE,Pfizer,27.77
+UNP,Union Pacific Corporation,261.95
+DHR,Danaher Corporation,219.80
+APP,AppLovin Corporation,459.27
+HON,Honeywell,243.56
+ETN,Eaton Corporation,394.94
+QCOM,Qualcomm,141.90
+UBER,Uber,70.72
+LMT,Lockheed Martin,630.54
+WELL,Welltower,208.65
+ACN,Accenture,230.79
+BKNG,Booking Holdings,4322.85
+SYK,Stryker Corporation,362.53
+COP,ConocoPhillips,110.75
+NEM,Newmont,123.89
+COF,Capital One,214.93
+PLD,Prologis,140.35
+MDT,Medtronic,100.87
+CB,Chubb Limited,328.82
+PH,Parker Hannifin,998.24
+PGR,Progressive Corporation,209.33
+BMY,Bristol Myers Squibb,60.18
+HCA,HCA Healthcare,531.83
+SPGI,S&P Global,396.65
+CMCSA,Comcast,32.53
+VRTX,Vertex Pharmaceuticals,459.93
+MCK,McKesson Corporation,944.20
+PANW,Palo Alto Networks,165.49
+GLW,Corning Inc.,134.16
+SBUX,Starbucks,99.03
+INTU,Intuit,401.05
+MO,Altria,65.72
+BSX,Boston Scientific,73.76
+CME,CME Group,303.44
+NOW,ServiceNow,101.55
+ADBE,Adobe Inc.,258.39
+TT,Trane Technologies,473.75
+CRWD,CrowdStrike,414.94
+BX,Blackstone Inc.,133.29
+UPS,United Parcel Service,119.93
+SO,Southern Company,90.86
+CEG,Constellation Energy,274.37
+DUK,Duke Energy,124.86
+CVS,CVS Health,76.36
+MAR,Marriott International,360.71
+NOC,Northrop Grumman,680.45
+PNC,PNC Financial Services,237.28
+WM,Waste Management,234.67
+GD,General Dynamics,348.79
+WDC,Western Digital,277.26
+KKR,KKR,105.28
+HWM,Howmet Aerospace,233.13
+FCX,Freeport-McMoRan,65.30
+NKE,Nike Inc.,62.43
+USB,U.S. Bancorp,59.25
+MMM,3M,173.46
+SHW,Sherwin-Williams,364.16
+RCL,Royal Caribbean Group,331.76
+SNDK,Sandisk Corporation,607.86
+STX,Seagate Technology,409.41
+EMR,Emerson Electric,156.30
+ADP,Automatic Data Processing,217.59
+WMB,Williams Companies,71.48
+ICE,Intercontinental Exchange,153.60
+FDX,FedEx,368.49
+ITW,Illinois Tool Works,298.50
+JCI,Johnson Controls,140.75
+CRH,CRH plc,127.89
+ECL,Ecolab,301.35
+EQIX,Equinix,863.66
+BK,BNY Mellon,122.83
+MRSH,Marsh & McLennan Companies Inc.,174.09
+AMT,American Tower,179.46
+CMI,Cummins,601.45
+SNPS,Synopsys,433.56
+REGN,Regeneron Pharmaceuticals,780.09
+DELL,Dell Technologies,124.37
+CDNS,Cadence Design Systems,298.74
+CTAS,Cintas,201.10
+ORLY,O'Reilly Auto Parts,93.87
+MNST,Monster Beverage,80.88
+MDLZ,Mondelez International,61.45
+PWR,Quanta Services,523.69
+CI,Cigna,292.46
+CSX,CSX Corporation,41.30
+CL,Colgate-Palmolive,95.04
+SLB,Schlumberger,51.14
+HLT,Hilton Worldwide,327.38
+DASH,DoorDash,175.41
+TDG,TransDigm Group,1325.26
+MCO,Moody's Corporation,415.20
+APO,Apollo Global Management,127.53
+ELV,Elevance Health,329.59
+ABNB,Airbnb,119.56
+GM,General Motors,79.78
+NSC,Norfolk Southern Railway,316.73
+COR,Cencora,365.43
+MSI,Motorola Solutions,423.10
+KMI,Kinder Morgan,31.64
+RSG,Republic Services,226.72
+HOOD,Robinhood Markets Inc.,77.55
+WBD,Warner Bros. Discovery,28.01
+TFC,Truist Financial,54.42
+PCAR,Paccar,129.93
+AON,Aon,314.02
+TEL,TE Connectivity,227.16
+APD,Air Products,293.38
+AEP,American Electric Power,122.18
+FTNT,Fortinet,87.72
+TRV,Travelers Companies (The),299.75
+PSX,Phillips 66,161.13
+LHX,L3Harris,341.14
+EOG,EOG Resources,117.39
+SPG,Simon Property Group,195.66
+NXPI,NXP Semiconductors,249.26
+ROST,Ross Stores,192.31
+VLO,Valero Energy,203.89
+AZO,AutoZone,3733.09
+MPC,Marathon Petroleum,207.85
+BKR,Baker Hughes,61.16
+AFL,Aflac,116.20
+DLR,Digital Realty,174.16
+SRE,Sempra,90.83
+O,Realty Income,64.39
+MPWR,Monolithic Power Systems,1197.55
+GWW,W. W. Grainger,1202.13
+ZTS,Zoetis,128.19
+CARR,Carrier Global,66.80
+D,Dominion Energy,64.61
+F,Ford Motor Company,13.78
+URI,United Rentals,870.17
+AME,Ametek,236.33
+VST,Vistra Corp.,160.43
+FAST,Fastenal,47.14
+ALL,Allstate,205.91
+OKE,ONEOK,85.03
+AJG,Arthur J. Gallagher & Co.,207.61
+CAH,Cardinal Health,225.15
+CVNA,Carvana Co.,365.94
+IDXX,Idexx Laboratories,647.63
+MET,MetLife,78.87
+TGT,Target Corporation,114.12
+PSA,Public Storage,293.33
+BDX,Becton Dickinson,179.62
+CTVA,Corteva,75.48
+TER,Teradyne,323.92
+EA,Electronic Arts,201.72
+ADSK,Autodesk,232.93
+FITB,Fifth Third Bancorp,54.59
+CMG,Chipotle Mexican Grill,37.35
+FANG,Diamondback Energy,168.93
+TRGP,Targa Resources,222.03
+FIX,Comfort Systems USA Inc.,1345.62
+DHI,D. R. Horton,163.35
+HSY,Hershey Company (The),231.46
+OXY,Occidental Petroleum,47.34
+DAL,Delta Air Lines,71.16
+ROK,Rockwell Automation,413.43
+NDAQ,Nasdaq Inc.,81.05
+XEL,Xcel Energy,77.79
+EW,Edwards Lifesciences,78.67
+CCL,Carnival,32.80
+CBRE,CBRE Group,151.76
+ETR,Entergy,100.79
+EXC,Exelon,44.57
+AMP,Ameriprise Financial,489.27
+NUE,Nucor,194.78
+DDOG,Datadog,126.70
+YUM,Yum! Brands,160.35
+MCHP,Microchip Technology,80.90
+WAB,Wabtec,255.15
+KR,Kroger,68.68
+AIG,American International Group,79.36
+VMC,Vulcan Materials Company,321.01
+CIEN,Ciena Corporation,301.11
+SYY,Sysco,88.04
+PEG,Public Service Enterprise Group,83.85
+COIN,Coinbase Global,152.61
+ODFL,Old Dominion,195.74
+KEYS,Keysight Technologies,237.88
+KDP,Keurig Dr Pepper,29.84
+VTR,Ventas,85.29
+MLM,Martin Marietta Materials,663.38
+GRMN,Garmin,206.52
+ED,Consolidated Edison,109.36
+HIG,Hartford (The),142.02
+LVS,Las Vegas Sands,57.75
+CPRT,Copart,39.73
+EL,Estée Lauder Companies (The),106.09
+IR,Ingersoll Rand,96.98
+WDAY,Workday Inc.,145.19
+MSCI,MSCI,519.16
+TTWO,Take-Two Interactive,204.25
+RMD,ResMed,259.29
+EBAY,eBay,82.95
+PCG,PG&E Corporation,17.02
+CCI,Crown Castle,85.66
+PYPL,PayPal,40.26
+PRU,Prudential Financial,105.34
+WEC,WEC Energy Group,113.19
+UAL,United Airlines Holdings,113.50
+STT,State Street Corporation,131.37
+HBAN,Huntington Bancshares,18.02
+A,Agilent Technologies,128.22
+GEHC,GE HealthCare,79.29
+MTB,M&T Bank,235.06
+EME,EMCOR Group Inc.,803.53
+ACGL,Arch Capital Group,98.49
+KMB,Kimberly-Clark,107.35
+ROP,Roper Technologies,333.96
+EQT,EQT Corporation,56.73
+KVUE,Kenvue,18.44
+LYV,Live Nation Entertainment,150.60
+OTIS,Otis Worldwide,89.85
+AXON,Axon Enterprise,436.36
+NRG,NRG Energy,160.11
+CTSH,Cognizant,71.22
+IBKR,Interactive Brokers Group,76.54
+PAYX,Paychex,94.49
+FISV,Fiserv Inc.,62.72
+ADM,Archer Daniels Midland,69.24
+XYZ,Block Inc.,53.87
+FICO,Fair Isaac,1369.86
+DG,Dollar General,147.49
+DOV,Dover Corporation,232.52
+ROL,Rollins Inc.,65.74
+HPE,Hewlett Packard Enterprise,23.62
+RJF,Raymond James Financial,159.60
+TPR,Tapestry Inc.,154.43
+VICI,Vici Properties,29.18
+TDY,Teledyne Technologies,657.92
+XYL,Xylem Inc.,126.71
+CHTR,Charter Communications,241.08
+ARES,Ares Management Corporation,137.90
+ULTA,Ulta Beauty,684.25
+STLD,Steel Dynamics,206.43
+EXR,Extra Space Storage,142.02
+LEN,Lennar,120.76
+IQV,IQVIA,175.80
+IRM,Iron Mountain,99.67
+KHC,Kraft Heinz,24.88
+PPG,PPG Industries,130.53
+HAL,Halliburton,34.84
+ATO,Atmos Energy,175.22
+DTE,DTE Energy,139.17
+TSCO,Tractor Supply,54.53
+EXPE,Expedia Group,235.08
+CFG,Citizens Financial Group,66.87
+AEE,Ameren,106.08
+TPL,Texas Pacific Land Corporation,416.14
+CBOE,Cboe Global Markets,271.99
+ON,ON Semiconductor,70.68
+MTD,Mettler Toledo,1391.33
+STZ,Constellation Brands,163.02
+BIIB,Biogen,191.29
+DVN,Devon Energy,44.78
+FE,FirstEnergy,47.94
+JBL,Jabil,260.92
+NTRS,Northern Trust,147.45
+HUBB,Hubbell Incorporated,513.63
+WTW,Willis Towers Watson,282.86
+WRB,W. R. Berkley Corporation,71.20
+RF,Regions Financial Corporation,30.86
+PHM,PulteGroup,139.04
+CNP,CenterPoint Energy,40.91
+PPL,PPL Corporation,35.97
+DXCM,Dexcom,68.19
+SW,Smurfit WestRock,50.23
+ES,Eversource Energy,69.77
+GIS,General Mills,48.40
+EIX,Edison International,66.94
+IP,International Paper,48.64
+WSM,Williams-Sonoma,214.52
+CINF,Cincinnati Financial,164.11
+LUV,Southwest Airlines,51.66
+AVB,AvalonBay Communities,179.80
+SYF,Synchrony Financial,72.95
+FIS,Fidelity National Information Services,48.73
+KEY,KeyCorp,22.67
+DLTR,Dollar Tree,125.35
+EQR,Equity Residential,65.09
+EXE,Expand Energy,103.09
+DRI,Darden Restaurants,212.58
+FSLR,First Solar,227.60
+DOW,Dow Inc.,33.98
+CPAY,Corpay,346.25
+AWK,American Water Works,123.54
+CHD,Church & Dwight,100.17
+LH,LabCorp,289.08
+VRSK,Verisk Analytics,171.87
+Q,Qnity Electronics,114.06
+CTRA,Coterra,31.48
+STE,Steris,243.09
+EFX,Equifax,197.29
+VLTO,Veralto,95.33
+BG,Bunge Global,121.39
+DGX,Quest Diagnostics,209.53
+CHRW,C.H. Robinson,196.77
+AMCR,Amcor,49.62
+TSN,Tyson Foods,64.52
+L,Loews Corporation,110.15
+CMS,CMS Energy,74.16
+BRO,Brown & Brown,67.07
+LDOS,Leidos,174.83
+PKG,Packaging Corporation of America,244.06
+JBHT,J.B. Hunt,231.62
+OMC,Omnicom Group,69.53
+EXPD,Expeditors International,163.06
+RL,Ralph Lauren Corporation,359.55
+NVR,NVR Inc.,8082.38
+DD,DuPont,51.29
+HUM,Humana,176.34
+NI,NiSource,44.78
+NTAP,NetApp,105.69
+GPC,Genuine Parts Company,149.43
+LULU,Lululemon Athletica,176.88
+ALB,Albemarle Corporation,176.03
+TROW,T. Rowe Price,94.24
+PFG,Principal Financial Group,92.86
+CSGP,CoStar Group,48.09
+GPN,Global Payments,72.67
+SBAC,SBA Communications,190.43
+SNA,Snap-on,383.21
+CNC,Centene Corporation,40.26
+VRSN,Verisign,215.66
+WAT,Waters Corporation,331.52
+IFF,International Flavors & Fragrances,76.65
+BR,Broadridge Financial Solutions,167.88
+WY,Weyerhaeuser,27.09
+INCY,Incyte,99.35
+LII,Lennox International,553.57
+LYB,LyondellBasell,59.29
+SMCI,Supermicro,31.69
+MKC,McCormick & Company,70.30
+ZBH,Zimmer Biomet,95.21
+PTC,PTC Inc.,155.52
+FTV,Fortive,58.93
+VTRS,Viatris,16.02
+EVRG,Evergy,78.94
+BALL,Ball Corporation,67.29
+HPQ,HP Inc.,19.63
+WST,West Pharmaceutical Services,247.87
+PODD,Insulet Corporation,253.09
+APTV,Aptiv,83.64
+CDW,CDW,135.32
+LNT,Alliant Energy,68.17
+TXT,Textron,96.68
+ESS,Essex Property Trust,262.76
+HOLX,Hologic,75.11
+J,Jacobs Solutions,142.70
+INVH,Invitation Homes,27.16
+TKO,TKO Group Holdings,210.88
+NDSN,Nordson Corporation,295.64
+DECK,Deckers Brands,115.15
+PNR,Pentair,99.79
+COO,Cooper Companies (The),82.84
+MAA,Mid-America Apartment Communities,136.74
+FFIV,F5 Inc.,282.22
+MAS,Masco,76.24
+IEX,IDEX Corporation,211.28
+MRNA,Moderna,40.21
+TRMB,Trimble Inc.,65.06
+ALLE,Allegion,179.40
+HII,Huntington Ingalls Industries,392.15
+CLX,Clorox,125.65
+CF,CF Industries,97.23
+GEN,Gen Digital,24.64
+AVY,Avery Dennison,192.77
+KIM,Kimco Realty,21.96
+HAS,Hasbro,105.26
+ERIE,Erie Indemnity,279.84
+TYL,Tyler Technologies,339.51
+UHS,Universal Health Services,231.22
+BEN,Franklin Resources,27.64
+ALGN,Align Technology,197.24
+SOLV,Solventum,81.25
+BBY,Best Buy,66.84
+REG,Regency Centers,76.49
+SWK,Stanley Black & Decker,90.31
+BF.B,Brown–Forman,30.11
+BLDR,Builders FirstSource,125.44
+HST,Host Hotels & Resorts,19.98
+AKAM,Akamai Technologies,95.00
+EG,Everest Group,331.67
+UDR,UDR Inc.,39.84
+TTD,The Trade Desk Inc.,27.19
+HRL,Hormel Foods,23.79
+DPZ,Domino's,385.50
+ZBRA,Zebra Technologies,250.71
+GNRC,Generac,214.94
+FOX,Fox Corporation (Class B),56.02
+FOXA,Fox Corporation (Class A),61.76
+GDDY,GoDaddy,91.44
+PSKY,Paramount Skydance Corp,10.96
+WYNN,Wynn Resorts,115.18
+JKHY,Jack Henry & Associates,165.63
+CPT,Camden Property Trust,111.66
+DOC,Healthpeak Properties,16.95
+SJM,J.M. Smucker Company (The),109.98
+IVZ,Invesco,26.42
+AES,AES Corporation,16.45
+IT,Gartner,160.21
+GL,Globe Life,144.35
+BAX,Baxter International,22.30
+PNW,Pinnacle West,95.57
+RVTY,Revvity,100.89
+AOS,A. O. Smith,80.03
+AIZ,Assurant,216.77
+TAP,Molson Coors Beverage Company,52.98
+NCLH,Norwegian Cruise Line Holdings,22.76
+POOL,Pool Corporation,270.70
+EPAM,EPAM Systems,180.79
+APA,APA Corporation,28.11
+TECH,Bio-Techne,63.46
+MOS,Mosaic Company (The),31.21
+BXP,BXP Inc.,61.61
+DVA,DaVita,144.55
+SWKS,Skyworks Solutions,63.62
+HSIC,Henry Schein,81.21
+CAG,Conagra Brands,19.95
+MGM,MGM Resorts,36.39
+ARE,Alexandria Real Estate Equities,53.92
+FRT,Federal Realty Investment Trust,107.14
+CPB,Campbell Soup Company,29.16
+NWSA,News Corp (Class A),23.30
+CRL,Charles River Laboratories,164.83
+MTCH,Match Group,31.27
+FDS,FactSet,193.29
+LW,Lamb Weston,50.33
+PAYC,Paycom,117.68
+MOH,Molina Healthcare,122.46
+NWS,News Corp (Class B),26.91
diff --git a/src/main/resources/themes/default.css b/src/main/resources/themes/default.css
index c64bfcd..4c7c21b 100644
--- a/src/main/resources/themes/default.css
+++ b/src/main/resources/themes/default.css
@@ -26,6 +26,12 @@
-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.3), 10, 0.5, 0, 5);
}
+.med-text-24{
+ -fx-font-size: 24px;
+ -fx-font-weight: 700;
+ -fx-text-fill: #EEEEEE;
+}
+
.med-text-16{
-fx-font-size: 16px;
-fx-font-weight: 700;
@@ -61,6 +67,10 @@
-fx-text-fill: #00FF00;
}
+.gray {
+ -fx-background-color: #404950;
+}
+
/* =======================
BUTTON STYLE
======================= */
@@ -80,6 +90,33 @@
-fx-translate-y: 1;
}
+.button-outlined {
+ -fx-font-size: 16px;
+ -fx-text-fill: white;
+ -fx-background-color: transparent;
+ -fx-border-radius: 20;
+ -fx-border-width: 2;
+ -fx-padding: 10 20 10 20;
+ -fx-cursor: hand;
+ -fx-border-color: white;
+ -fx-effect: dropshadow(gaussian, rgba(0,0,0,0.3), 6, 0.3, 0, 2);
+}
+
+.menu-button {
+ -fx-background-color: white;
+ -fx-background-radius: 8;
+ -fx-border-radius: 8;
+
+ -fx-text-fill: black;
+
+ -fx-padding: 4 10 4 10;
+
+ -fx-font-size: 12px;
+ -fx-font-weight: 500;
+
+ -fx-cursor: hand;
+}
+
.icon {
-fx-border-radius: 20;
-fx-padding: 5;
@@ -90,18 +127,6 @@
-fx-background-color: #3B8C6E;
}
-.rowBox {
- -fx-background-color: #404950;
- -fx-alignment: center;
-}
-
-.searchbar {
- -fx-background-color: #FFFFFF;
- -fx-background-radius: 20;
- -fx-border-radius: 20;
- -fx-effect: dropshadow(gaussian, rgba(0,0,0,0.3), 6, 0.3, 0, 2);
-}
-
.searchbar-field {
-fx-font-size: 16px;
-fx-text-fill: black;
@@ -111,22 +136,3 @@
-fx-cursor: hand;
}
-.newspaper-title {
- -fx-font-size: 56px;
- -fx-font-weight: 700;
- -fx-text-fill: #000000;
- -fx-padding: 30px;
- -fx-effect: dropshadow(gaussian, rgba(0,0,0,0.3), 10, 0.5, 0, 5);
-}
-
-.newspaper-med-text{
- -fx-font-size: 22px;
- -fx-font-weight: 700;
- -fx-text-fill: #000000;
-}
-
-.newspaper-article{
- -fx-background-color: #EEEEEE;
-}
-
-
diff --git a/src/test/java/edu/ntnu/idi/idatt/model/ExchangeTest.java b/src/test/java/edu/ntnu/idi/idatt/model/ExchangeTest.java
index af14b62..3ef88e6 100644
--- a/src/test/java/edu/ntnu/idi/idatt/model/ExchangeTest.java
+++ b/src/test/java/edu/ntnu/idi/idatt/model/ExchangeTest.java
@@ -2,16 +2,12 @@
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.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
-import java.io.InputStream;
import java.math.BigDecimal;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
@@ -43,7 +39,7 @@ class ExchangeTest {
private Player player;
@BeforeEach
- public void PT_setup() throws IOException {
+ public void setup() throws IOException {
Stock AAPL = new Stock("AAPL", "Apple Inc", List.of(new BigDecimal("30")));
Stock NVDA = new Stock("NVDA", "NVIDIA", List.of(new BigDecimal("182.81")));
@@ -57,7 +53,7 @@ public void PT_setup() throws IOException {
}
@Test
- void PTConstructor() {
+ void constructor_shouldCreateExchange() {
assertEquals("TestExchange", exchange.getName());
assertEquals(1, exchange.getWeek());
}
@@ -72,7 +68,7 @@ void PTConstructor() {
*/
@Test
- void PTFindStock() {
+ void findStocks_shouldFindLoadedStocks() {
assertTrue(exchange.hasStock("AAPL"));
assertTrue(stocks.contains(exchange.getStock("AAPL")));
@@ -91,7 +87,7 @@ void PTFindStock() {
*
*/
@Test
- void PTBuy() {
+ void buy_shouldFulfillTransaction() {
Transaction transaction = exchange.buy("AAPL", new BigDecimal("1"), player);
assertEquals(transaction, player.getTransactionArchive().getTransactions(1).getLast());
@@ -110,7 +106,7 @@ void PTBuy() {
*
*/
@Test
- void PTSell() {
+ void sell_shouldFulfillTransaction() {
// Player has to have a share to sell it.
exchange.buy("AAPL", new BigDecimal("1"), player);
exchange.getStock("AAPL").addNewSalesPrice(new BigDecimal("40")); // Simulate increase of AAPL stock price
@@ -123,15 +119,17 @@ void PTSell() {
}
@Test
- void PTAdvance() {
- // TODO: do
+ void advance_shouldIncrementWeek() {
+ int week = exchange.getWeek();
+ exchange.advance();
+ assertNotEquals(week, exchange.getWeek());
}
/**
* Test for obtaining the gainers and loosers.
*/
@Test
- void PTgetGainers_Losers() {
+ void getGainers_Loosers_shouldReturnStocks() {
// Simulate price change
stocks.get(0).addNewSalesPrice(new BigDecimal("4333"));
stocks.get(1).addNewSalesPrice(new BigDecimal("10"));
@@ -154,7 +152,7 @@ void PTgetGainers_Losers() {
*
*/
@Test
- void NTFindStock() {
+ void hasStock_NoMatchShouldThrowException() {
assertFalse(exchange.hasStock("Test"));
assertThrows(IllegalArgumentException.class, () -> exchange.getStock("thiswillnotwork"));
diff --git a/src/test/java/edu/ntnu/idi/idatt/model/enums/NewspaperEnumTest.java b/src/test/java/edu/ntnu/idi/idatt/model/enums/NewspaperEnumTest.java
new file mode 100644
index 0000000..874629d
--- /dev/null
+++ b/src/test/java/edu/ntnu/idi/idatt/model/enums/NewspaperEnumTest.java
@@ -0,0 +1,39 @@
+package edu.ntnu.idi.idatt.model.enums;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+public class NewspaperEnumTest {
+
+ @Test
+ void testGetTitle() {
+ NewspaperEnum event = NewspaperEnum.FRAUD;
+
+ assertEquals("Fraud investigation!", event.getTitle());
+ }
+
+ @Test
+ void testGetDescription() {
+ NewspaperEnum event = NewspaperEnum.FRAUD;
+
+ assertEquals(
+ "The company's CEO is under investigation for potential fraud!",
+ event.getDescription());
+ }
+
+ @Test
+ void testGetTrend() {
+ NewspaperEnum event = NewspaperEnum.FRAUD;
+
+ assertEquals(-0.05, event.getTrend());
+ }
+
+ @Test
+ void testGetVolatility() {
+ NewspaperEnum event = NewspaperEnum.FRAUD;
+
+ assertEquals(0.12, event.getVolatility());
+ }
+
+}
diff --git a/src/test/java/edu/ntnu/idi/idatt/model/market/NewspaperTest.java b/src/test/java/edu/ntnu/idi/idatt/model/market/NewspaperTest.java
new file mode 100644
index 0000000..1bdd5f1
--- /dev/null
+++ b/src/test/java/edu/ntnu/idi/idatt/model/market/NewspaperTest.java
@@ -0,0 +1,102 @@
+package edu.ntnu.idi.idatt.model.market;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.List;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import edu.ntnu.idi.idatt.model.enums.NewspaperEnum;
+
+public class NewspaperTest {
+
+ private Newspaper newspaper;
+
+ @BeforeEach
+ void setup() {
+ newspaper = new Newspaper();
+ }
+
+ @Test
+ void testNewsInitiallyContainsNoneEvent() {
+ List news = newspaper.getNews();
+
+ assertEquals(1, news.size());
+ assertEquals(NewspaperEnum.NONE_EVENT, news.getFirst());
+ }
+
+ @Test
+ void testMakeNewsAddsNewsEntry() {
+ int before = newspaper.getNews().size();
+
+ newspaper.makeNews();
+
+ int after = newspaper.getNews().size();
+
+ assertEquals(before + 1, after);
+ }
+
+ @Test
+ void testMakeNewsNeverReturnsNull() {
+ NewspaperEnum event = newspaper.makeNews();
+
+ assertNotNull(event);
+ }
+
+ @Test
+ void testHasNewNewsReturnsFalseWhenLastIsNoneEvent() {
+ newspaper.getNews().add(NewspaperEnum.NONE_EVENT);
+
+ assertFalse(newspaper.hasNewNews());
+ }
+
+ @Test
+ void testHasNewNewsReturnsTrueWhenLastIsRealEvent() {
+ newspaper.getNews().add(NewspaperEnum.DISASTER);
+
+ assertTrue(newspaper.hasNewNews());
+ }
+
+ @Test
+ void testGetNewsReturnsSameListReference() {
+ List news = newspaper.getNews();
+
+ assertNotNull(news);
+ assertEquals(newspaper.getNews(), news);
+ }
+
+ @Test
+ void testGetNewsStringsEmptyWhenOnlyNoneEvents() {
+ newspaper.getNews().clear();
+ newspaper.getNews().add(NewspaperEnum.NONE_EVENT);
+ newspaper.getNews().add(NewspaperEnum.NONE_EVENT);
+
+ List strings = newspaper.getNewsStrings();
+
+ assertTrue(strings.isEmpty());
+ }
+
+ @Test
+ void testGetNewsStringsFormatsCorrectly() {
+ newspaper.getNews().clear();
+
+ newspaper.getNews().add(NewspaperEnum.NONE_EVENT); // Week 1
+ newspaper.getNews().add(NewspaperEnum.DISASTER); // Week 2
+
+ List strings = newspaper.getNewsStrings();
+
+ assertEquals(1, strings.size());
+
+ String expected = String.format(
+ "Week: %d - %s [%s]",
+ 2,
+ NewspaperEnum.DISASTER.getTitle(),
+ NewspaperEnum.DISASTER.getDescription());
+
+ assertEquals(expected, strings.getFirst());
+ }
+}
diff --git a/src/test/java/edu/ntnu/idi/idatt/model/market/StockTest.java b/src/test/java/edu/ntnu/idi/idatt/model/market/StockTest.java
index 5b27600..0e8af44 100644
--- a/src/test/java/edu/ntnu/idi/idatt/model/market/StockTest.java
+++ b/src/test/java/edu/ntnu/idi/idatt/model/market/StockTest.java
@@ -1,8 +1,11 @@
package edu.ntnu.idi.idatt.model.market;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
@@ -14,7 +17,7 @@ public class StockTest {
private List prices;
@BeforeEach
- public void PT_setup() {
+ public void setup() {
prices = List.of(new BigDecimal("46.2"),
new BigDecimal("40.0"),
new BigDecimal("39.5"),
@@ -25,14 +28,14 @@ public void PT_setup() {
}
@Test
- void constructorTest() {
+ void constructor_shouldCreateStock() {
assertEquals("AAPL", stock.getSymbol());
assertEquals("Apple Inc.", stock.getCompany());
assertEquals(new BigDecimal("43.4"), stock.getSalesPrice());
}
@Test
- void PTgetPrices() {
+ void getHistoricalPrices_shouldReturnStockPrices() {
assertEquals(prices, stock.getHistoricalPrices());
assertEquals(new BigDecimal("39.5"), stock.getLowestPrice());
assertEquals(new BigDecimal("51.2"), stock.getHighestPrice());
@@ -40,7 +43,7 @@ void PTgetPrices() {
}
@Test
- void NTgetLatestPriceChange() {
+ void latestPriceChange_shouldBeNull() {
Stock noPrice = new Stock("NVDA", "Nvidia", List.of());
Stock onePrice = new Stock("TSLA", "Tesla Inc.", List.of(
BigDecimal.TEN));
@@ -50,11 +53,70 @@ void NTgetLatestPriceChange() {
}
@Test
- void addNewSalesPriceTest() {
+ void addNewSalesPrice_shouldAddNewPrice() {
BigDecimal value = new BigDecimal("15.6");
stock.addNewSalesPrice(value);
assertEquals(value, stock.getSalesPrice());
}
+ @Test
+ void getNewspaper() {
+
+ assertNotNull(stock.getNewspaper());
+ }
+
+ @Test
+ void advancePrice() {
+
+ BigDecimal previousPrice = stock.getSalesPrice();
+
+ stock.advancePrice();
+
+ BigDecimal newPrice = stock.getSalesPrice();
+
+ assertNotEquals(previousPrice, newPrice);
+ assertEquals(2, newPrice.scale());
+ }
+
+ @Test
+ void advancePrice_AddsNewPriceToHistory() {
+
+ int previousSize = stock.getHistoricalPrices().size();
+
+ stock.advancePrice();
+
+ assertEquals(previousSize + 1, stock.getHistoricalPrices().size());
+ }
+
+ @Test
+ void getLatestPriceChangePercent() {
+
+ BigDecimal expected = stock.getLatestPriceChange().multiply(new BigDecimal("100"))
+ .divide(new BigDecimal("51.2"), 2, RoundingMode.HALF_UP);
+
+ assertEquals(expected, stock.getLatestPriceChangePercent());
+ }
+
+ @Test
+ void getLatestPriceChangePercentNoPrices() {
+
+ Stock emptyStock = new Stock(
+ "MSFT",
+ "Microsoft",
+ List.of());
+
+ assertEquals(
+ BigDecimal.ZERO,
+ emptyStock.getLatestPriceChangePercent());
+ }
+
+ @Test
+ void stockToString() {
+
+ assertEquals(
+ "Apple Inc. (AAPL)",
+ stock.toString());
+ }
+
}
diff --git a/src/test/java/edu/ntnu/idi/idatt/model/player/PlayerTest.java b/src/test/java/edu/ntnu/idi/idatt/model/player/PlayerTest.java
index 16bbb95..32aa2d0 100644
--- a/src/test/java/edu/ntnu/idi/idatt/model/player/PlayerTest.java
+++ b/src/test/java/edu/ntnu/idi/idatt/model/player/PlayerTest.java
@@ -18,14 +18,14 @@ class PlayerTest {
private Player player;
@BeforeEach
- public void PT_setup() {
+ public void setup() {
player = new Player("TestPlayer", new BigDecimal("500"));
}
@Test
- void PTConstructor() {
+ void constructor_shouldCreatePlayer() {
assertEquals("TestPlayer", player.getName());
assertEquals(new BigDecimal("500"), player.getMoney());
assertNotNull(player.getPortfolio());
@@ -33,7 +33,7 @@ void PTConstructor() {
}
@Test
- void PTaddMoney() {
+ void addMoney_shouldAddMoney() {
player.addMoney(new BigDecimal("200"));
assertEquals(new BigDecimal("700"), player.getMoney());
@@ -41,13 +41,18 @@ void PTaddMoney() {
}
@Test
- void PTwithdrawMoney() {
+ void getStartingMoney() {
+ assertEquals(new BigDecimal("500"), player.getStartingMoney());
+ }
+
+ @Test
+ void withdrawMoney_shouldSubtractMoney() {
player.withdrawMoney(new BigDecimal("200"));
assertEquals(new BigDecimal("300"), player.getMoney());
}
@Test
- void PTgetNetWorth() {
+ void getNetWorth_shouldReturnTotalNetWorth() {
assertEquals(player.getNetWorth(), new BigDecimal("500"));
// Add to player portfolio
@@ -61,7 +66,7 @@ void PTgetNetWorth() {
}
@Test
- void PTgetStatus() {
+ void getStatus_shouldCalculateCorrectStatuses() {
assertEquals("Novice", player.getStatus());
// Simulate progress
diff --git a/src/test/java/edu/ntnu/idi/idatt/model/portfolio/PortfolioTest.java b/src/test/java/edu/ntnu/idi/idatt/model/portfolio/PortfolioTest.java
index 743963f..872b55e 100644
--- a/src/test/java/edu/ntnu/idi/idatt/model/portfolio/PortfolioTest.java
+++ b/src/test/java/edu/ntnu/idi/idatt/model/portfolio/PortfolioTest.java
@@ -6,6 +6,7 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
@@ -21,7 +22,7 @@ public class PortfolioTest {
private Portfolio portfolio;
@BeforeEach
- public void PT_setup() {
+ public void setup() {
// stock instance and parameters
List prices = List.of(new BigDecimal("46.2"),
new BigDecimal("40.0"));
@@ -36,20 +37,30 @@ public void PT_setup() {
}
@Test
- void PTaddShare() {
+ void addShare_shouldAddToPortfolio() {
assertTrue(portfolio.addShare(share));
assertEquals(List.of(share), portfolio.getShares());
}
- void addDefaultShare() { // Since PTaddShare test works, we will use this to initialize
+ void addDefaultShare() { // Since test over works, we will use this to initialize
// the rest of the tests under.
portfolio.addShare(share);
}
@Test
- void PTgetSharesBySymbol() {
+ void getShares() {
+
+ addDefaultShare();
+
+ assertEquals(
+ List.of(share),
+ portfolio.getShares());
+ }
+
+ @Test
+ void getSharesBySymbol_shouldReturnShares() {
addDefaultShare();
assertEquals(List.of(), portfolio.getShares("SYMBL"));
@@ -58,7 +69,7 @@ void PTgetSharesBySymbol() {
}
@Test
- void PTremoveShare() {
+ void removeShareBySymbol_shouldRemoveShare() {
addDefaultShare();
assertTrue(portfolio.removeShare(share));
@@ -67,7 +78,7 @@ void PTremoveShare() {
}
@Test
- void PTContains() {
+ void testContainsShare() {
assertFalse(portfolio.contains(share));
portfolio.addShare(share);
@@ -76,16 +87,23 @@ void PTContains() {
}
@Test
- void NTremoveShare() {
+ void removeShareBySymbol_shouldThrowException() {
Share exception = new Share(stock, new BigDecimal("2.3"), stock.getSalesPrice());
assertThrows(IllegalArgumentException.class, () -> portfolio.removeShare(exception));
}
- /**
- * Positive test for finding net value of the players shares.
- */
@Test
- void PTgetNetWorth() {
+ void removeShares_shouldClearPortfolio() {
+
+ addDefaultShare();
+
+ portfolio.removeShares();
+
+ assertTrue(portfolio.getShares().isEmpty());
+ }
+
+ @Test
+ void getNetWorth_shouldReturnNetWorth() {
Share share1 = new Share(stock, new BigDecimal("1"), new BigDecimal("135.8"));
Share share2 = new Share(stock, new BigDecimal("2"), new BigDecimal("254"));
portfolio.addShare(share1);
@@ -94,4 +112,123 @@ void PTgetNetWorth() {
portfolio.getNetWorth());
}
+ @Test
+ void getNetWorthEmptyPortfolio() {
+
+ assertEquals(
+ BigDecimal.ZERO,
+ portfolio.getNetWorth());
+ }
+
+ @Test
+ void getOwnedAmountBySymbol() {
+
+ addDefaultShare();
+
+ assertEquals(
+ new BigDecimal("3.3"),
+ portfolio.getOwnedAmount("AAPL"));
+ }
+
+ @Test
+ void getOwnedAmountBySymbolNoMatch() {
+
+ assertEquals(
+ BigDecimal.ZERO,
+ portfolio.getOwnedAmount("MSFT"));
+ }
+
+ @Test
+ void getOwnedAmount() {
+
+ addDefaultShare();
+
+ assertEquals(
+ new BigDecimal("3.3"),
+ portfolio.getOwnedAmount());
+ }
+
+ @Test
+ void getProfitFromStock() {
+
+ addDefaultShare();
+
+ BigDecimal expected = share.getProfit();
+
+ assertEquals(
+ expected,
+ portfolio.getProfitFromStock("AAPL"));
+ }
+
+ @Test
+ void getProfitFromStockNoMatch() {
+
+ assertEquals(
+ BigDecimal.ZERO,
+ portfolio.getProfitFromStock("MSFT"));
+ }
+
+ @Test
+ void getProfitFromPortfolio() {
+
+ addDefaultShare();
+
+ BigDecimal expected = share.getProfit();
+
+ assertEquals(
+ expected,
+ portfolio.getProfitFromStock());
+ }
+
+ @Test
+ void getChangeFromStock_shouldReturnCorrectPercentageChange() {
+
+ addDefaultShare();
+
+ BigDecimal profit = portfolio.getProfitFromStock("AAPL");
+
+ BigDecimal totalCost = share.getTotalPurchasePrice();
+
+ BigDecimal expected = profit
+ .divide(totalCost, 2, java.math.RoundingMode.HALF_UP)
+ .multiply(BigDecimal.valueOf(100));
+
+ assertEquals(
+ expected,
+ portfolio.getChangeFromStock("AAPL"));
+ }
+
+ @Test
+ void getChangeFromStock_shouldReturnZeroWhenNoSharesExist() {
+
+ assertEquals(
+ BigDecimal.ZERO,
+ portfolio.getChangeFromStock("MSFT"));
+ }
+
+ @Test
+ void getChangeFromStock_shouldReturnTotalFromPortfolioChange() {
+
+ addDefaultShare();
+
+ BigDecimal profit = portfolio.getProfitFromStock();
+
+ BigDecimal totalCost = share.getTotalPurchasePrice();
+
+ BigDecimal expected = profit
+ .divide(totalCost, 2, RoundingMode.HALF_UP)
+ .multiply(new BigDecimal("100"));
+
+ assertEquals(
+ expected,
+ portfolio.getChangeFromStock());
+ }
+
+ @Test
+ void getChangeFromStock_emptyPortfolio() {
+
+ assertEquals(BigDecimal.ZERO, portfolio.getChangeFromStock());
+
+ }
+
}
diff --git a/src/test/java/edu/ntnu/idi/idatt/model/portfolio/ShareTest.java b/src/test/java/edu/ntnu/idi/idatt/model/portfolio/ShareTest.java
index cefea8b..b0d261a 100644
--- a/src/test/java/edu/ntnu/idi/idatt/model/portfolio/ShareTest.java
+++ b/src/test/java/edu/ntnu/idi/idatt/model/portfolio/ShareTest.java
@@ -16,7 +16,7 @@ public class ShareTest {
private Stock stock;
@BeforeEach
- public void PT_setup() {
+ public void setup() {
List prices = List.of(new BigDecimal("46.2"),
new BigDecimal("40.0"));
stock = new Stock("AAPL", "Apple Inc.", prices);
@@ -36,4 +36,104 @@ void constructorTest() {
}
+ @Test
+ void testGetTotalPurchasePrice() {
+ BigDecimal expected = new BigDecimal("132.00");
+
+ assertEquals(0,
+ expected.compareTo(share.getTotalPurchasePrice()));
+ }
+
+ @Test
+ void testGetProfit() {
+
+ /*
+ * Current stock price = 40.0
+ * Purchase price = 40.0
+ * Quantity = 3.3
+ *
+ * Gross = 132.0
+ * Purchase total = 132.0
+ * Profit = 0
+ */
+
+ BigDecimal expected = BigDecimal.ZERO;
+
+ assertEquals(0,
+ expected.compareTo(share.getProfit()));
+ }
+
+ @Test
+ void testGetProfitPercent() {
+
+ /*
+ * Profit is 0, therefore percentage should also be 0
+ */
+
+ BigDecimal expected = BigDecimal.ZERO;
+
+ assertEquals(0,
+ expected.compareTo(share.getProfitPercent()));
+ }
+
+ @Test
+ void testGetProfitPositive() {
+
+ /*
+ * Simulate stock price increase
+ * Latest price becomes 50.0
+ */
+
+ Stock increasedStock = new Stock(
+ "AAPL",
+ "Apple Inc.",
+ List.of(
+ new BigDecimal("40.0"),
+ new BigDecimal("50.0")));
+
+ Share profitableShare = new Share(
+ increasedStock,
+ new BigDecimal("2"),
+ new BigDecimal("40.0"));
+
+ /*
+ * Gross = 50 * 2 = 100
+ * Purchase total = 40 * 2 = 80
+ * Profit = 20
+ */
+
+ BigDecimal expected = new BigDecimal("20.0");
+
+ assertEquals(0,
+ expected.compareTo(profitableShare.getProfit()));
+ }
+
+ @Test
+ void testGetProfitPercentPositive() {
+
+ Stock increasedStock = new Stock(
+ "AAPL",
+ "Apple Inc.",
+ List.of(
+ new BigDecimal("40.0"),
+ new BigDecimal("50.0")));
+
+ Share profitableShare = new Share(
+ increasedStock,
+ new BigDecimal("2"),
+ new BigDecimal("40.0"));
+
+ /*
+ * Profit = 20
+ * Purchase total = 80
+ *
+ * 20 / 80 * 100 = 25.00
+ */
+
+ BigDecimal expected = new BigDecimal("25.00");
+
+ assertEquals(0,
+ expected.compareTo(profitableShare.getProfitPercent()));
+ }
+
}
diff --git a/src/test/java/edu/ntnu/idi/idatt/model/transaction/PurchaseTest.java b/src/test/java/edu/ntnu/idi/idatt/model/transaction/PurchaseTest.java
index caf44c1..eab98aa 100644
--- a/src/test/java/edu/ntnu/idi/idatt/model/transaction/PurchaseTest.java
+++ b/src/test/java/edu/ntnu/idi/idatt/model/transaction/PurchaseTest.java
@@ -37,7 +37,7 @@ class PurchaseTest {
private Purchase purchase;
@BeforeEach
- public void PT_setup() {
+ public void setup() {
// stock instance and parameters
List prices = List.of(new BigDecimal("46.2"),
new BigDecimal("40.0"));
diff --git a/src/test/java/edu/ntnu/idi/idatt/model/transaction/SaleTest.java b/src/test/java/edu/ntnu/idi/idatt/model/transaction/SaleTest.java
index 1bd944e..ac360aa 100644
--- a/src/test/java/edu/ntnu/idi/idatt/model/transaction/SaleTest.java
+++ b/src/test/java/edu/ntnu/idi/idatt/model/transaction/SaleTest.java
@@ -39,7 +39,7 @@ class SaleTest {
private Sale sale;
@BeforeEach
- public void PT_setup() {
+ public void setup() {
// stock instance and parameters
List prices = List.of(new BigDecimal("46.2"),
new BigDecimal("40.0"));
@@ -65,7 +65,7 @@ public void PT_setup() {
* it will singlehandedly validate the methods of this class.
*/
@Test
- void PTconstructorTest() {
+ void constructorTest() {
assertEquals(share, sale.getShare());
assertEquals(1, sale.getWeek());
diff --git a/src/test/java/edu/ntnu/idi/idatt/model/transaction/TransactionArchiveTest.java b/src/test/java/edu/ntnu/idi/idatt/model/transaction/TransactionArchiveTest.java
index 32739ae..6550d87 100644
--- a/src/test/java/edu/ntnu/idi/idatt/model/transaction/TransactionArchiveTest.java
+++ b/src/test/java/edu/ntnu/idi/idatt/model/transaction/TransactionArchiveTest.java
@@ -19,7 +19,7 @@ class TransactionArchiveTest {
TransactionArchive transactionArchive;
@BeforeEach
- public void getDefaultValues() {
+ public void setup() {
Stock AAPL = new Stock("AAPL", "Apple Inc.", List.of(new BigDecimal("32")));
Stock NVDA = new Stock("NVDA", "NVIDIA", List.of(new BigDecimal("182.81")));
@@ -44,7 +44,7 @@ public void getDefaultValues() {
}
@Test
- void PTaddTransactions() {
+ void addTransaction_shouldAddToArchive() {
TransactionArchive archive = new TransactionArchive();
assertTrue(archive.add(transactions.get(0)));
@@ -55,7 +55,7 @@ void PTaddTransactions() {
}
@Test
- void PTisEmpty() {
+ void isEmpty_shouldBeTrue() {
TransactionArchive archive = new TransactionArchive();
@@ -76,7 +76,7 @@ void PTisEmpty() {
*/
@Test
- void PTgetTransactions() {
+ void getTransactionsProper() {
assertEquals(2, transactionArchive.getTransactions(1).size()); // First week all transactions
assertEquals(2, transactionArchive.getTransactions(2).size());
@@ -87,16 +87,31 @@ void PTgetTransactions() {
}
+ @Test
+ void getTransactions_shouldReturnArray() {
+ assertEquals(transactions, transactionArchive.getTransactions());
+ }
+
+ @Test
+ void getPurchases_allPurchases() {
+ assertEquals(List.of(transactions.get(0), transactions.get(1)), transactionArchive.getPurchases());
+ }
+
+ @Test
+ void getSales_allSales() {
+ assertEquals(List.of(transactions.get(2), transactions.get(3)), transactionArchive.getSales());
+ }
+
/**
* Tests for countDistinctWeeks().
*/
@Test
- void PTcountDistinctWeeks() {
+ void countDistinctWeeks() {
assertEquals(2, transactionArchive.countDistinctWeeks());
}
@Test
- void NTcountDistinctWeeks() {
+ void countDistinctWeeks_shouldBeZero() {
TransactionArchive tArchive = new TransactionArchive();
assertEquals(0, tArchive.countDistinctWeeks());
}
diff --git a/src/test/java/edu/ntnu/idi/idatt/service/transaction/PurchaseCalculatorTest.java b/src/test/java/edu/ntnu/idi/idatt/service/transaction/PurchaseCalculatorTest.java
index 7870ea4..69f2537 100644
--- a/src/test/java/edu/ntnu/idi/idatt/service/transaction/PurchaseCalculatorTest.java
+++ b/src/test/java/edu/ntnu/idi/idatt/service/transaction/PurchaseCalculatorTest.java
@@ -18,7 +18,7 @@ class PurchaseCalculatorTest {
private PurchaseCalculator purchaseCalculator;
@BeforeEach
- public void PT_setup() {
+ public void setup() {
// stock instance and parameters
List prices = List.of(new BigDecimal("46.2"),
new BigDecimal("40.0"));
@@ -39,7 +39,7 @@ public void PT_setup() {
* it will singlehandedly validate the methods of this class.
*/
@Test
- void PT_calculationTotal() {
+ void calculationTotalTest() {
BigDecimal expected = new BigDecimal("40.0")
.multiply(new BigDecimal("3.3"))
diff --git a/src/test/java/edu/ntnu/idi/idatt/service/transaction/SaleCalculatorTest.java b/src/test/java/edu/ntnu/idi/idatt/service/transaction/SaleCalculatorTest.java
index eacc8e2..e940b03 100644
--- a/src/test/java/edu/ntnu/idi/idatt/service/transaction/SaleCalculatorTest.java
+++ b/src/test/java/edu/ntnu/idi/idatt/service/transaction/SaleCalculatorTest.java
@@ -18,7 +18,7 @@ class SaleCalculatorTest {
private SaleCalculator saleCalculator;
@BeforeEach
- public void PT_setup() {
+ public void setup() {
// stock instance and parameters
List prices = List.of(new BigDecimal("46.2"),
new BigDecimal("40.0"));
@@ -41,7 +41,7 @@ public void PT_setup() {
* @see SaleCalculator
*/
@Test
- void PT_calculationTotal() {
+ void calculateAllTest() {
// For imitation, let's add a new weeks stock price.
stock.addNewSalesPrice(new BigDecimal("47.8"));
@@ -69,9 +69,11 @@ void PT_calculationTotal() {
.multiply(share.getQuantity()))
.multiply(new BigDecimal("0.3"));
- BigDecimal expected = gross.subtract(commision).subtract(tax);
- assertEquals(expected, saleCalculator.calculateTotal());
+ BigDecimal total = gross.subtract(commision).subtract(tax);
+ assertEquals(total, saleCalculator.calculateTotal());
+ BigDecimal profit = gross.subtract(share.getTotalPurchasePrice());
+ assertEquals(profit, saleCalculator.calculateProfit());
}
}
diff --git a/src/test/java/edu/ntnu/idi/idatt/storage/StockParserTest.java b/src/test/java/edu/ntnu/idi/idatt/storage/StockParserTest.java
deleted file mode 100644
index 570a2fa..0000000
--- a/src/test/java/edu/ntnu/idi/idatt/storage/StockParserTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package edu.ntnu.idi.idatt.storage;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-import java.util.List;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import edu.ntnu.idi.idatt.model.market.Stock;
-
-/**
- * Test class for ExchangeLoader
- *
- *
- * Tests the loading and saving of stock data.
- *
- */
-class StockParserTest {
-
- String file;
-
- @BeforeEach
- public void PT_setup() throws IOException {
-
- InputStream is = getClass()
- .getClassLoader()
- .getResourceAsStream("stocks.csv");
-
- Path tempFile = Files.createTempFile("stocks", ".csv");
- Files.copy(is, tempFile, StandardCopyOption.REPLACE_EXISTING);
-
- file = tempFile.toFile().toPath().toString();
-
- }
-
- /**
- * Positive test for loading/reading stocks
- */
- @Test
- void PT_load() {
- List stocks = null;
- try {
- stocks = StockParser.loadFromFile(file);
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- assertEquals(4, stocks.size());
-
- }
-
- /**
- * Negative tests reading stocks.
- */
- @Test
- void NT_IllegalArgumentException_Constructor() {
- assertThrows(IOException.class,
- () -> StockParser.loadFromFile("resources/notexistantfile.csv"));
- }
-
-}
diff --git a/src/test/resources/stocks.csv b/src/test/resources/stocks.csv
deleted file mode 100644
index 275ddb0..0000000
--- a/src/test/resources/stocks.csv
+++ /dev/null
@@ -1,7 +0,0 @@
-# Ticker,Name,Price
-AAPL,Apple Inc,32
-NVDA,NVIDIA,182.81
-TSLA,Tesla,417.44
-AMD,Advanced Micro Devices,207.32
-
-