diff --git a/src/main/Resources/Style/Global.css b/src/main/Resources/Style/Global.css new file mode 100644 index 0000000..92c26b0 --- /dev/null +++ b/src/main/Resources/Style/Global.css @@ -0,0 +1,236 @@ +/* This is the CSS design used in the application */ + + +/* Root / Page background */ +.root { + + /* Colour pallette */ + dark-colour: rgb(28, 53, 45); + light-colour: rgb(249, 246, 243); + green-colour: rgb(166, 178, 139); + light-green-colour: rgba(166, 178, 139, 0.2); + red-colour: rgb(245, 201, 176); + dark-red-colour: rgb(53, 28, 32); + + + -fx-font-family: Verdana; + -fx-font-size: 13px; + -fx-background-color: green-colour; +} + +/* All labels */ +.label { + -fx-text-fill: dark-colour; + -fx-font-size: 13px; +} + +/* Title */ +.label.title-label { + -fx-font-size: 35px; + -fx-font-weight: bold; + -fx-padding: 0 0 12 0; +} + +/* Form row labels (setup scene) */ +.label.form-label { + -fx-font-size: 14px; +} + +/* Status bar label */ +.label.status-label { + -fx-font-size: 12px; + -fx-font-weight: bold; +} + +/* File name label */ +.label.file-label { + -fx-font-size: 12px; +} + +/* Card (centered white box in setup scene) */ +.card { + -fx-background-color: light-colour; + -fx-padding: 50 60 50 60; +} + +/* Content area (main game tab/panel background) */ +.content-area { + -fx-background-color: light-colour; + -fx-padding: 10; +} + +/* Top status bar */ +.top-bar { + -fx-background-color: light-green-colour; + -fx-padding: 8 12 8 12; +} + +/* Text fields */ +.text-field { + -fx-background-radius: 4; + -fx-padding: 7 10 7 10; + -fx-background-color: green-colour; + -fx-text-fill: dark-colour; + -fx-prompt-text-fill: dark-colour; + -fx-border-width: 0; +} + +/* Scroll panes (transparent so card shows through) */ +.scroll-pane { + -fx-background-color: transparent; + -fx-border-width: 0; +} + +.scroll-pane > .viewport { + -fx-background-color: transparent; +} + +/* Base button */ +.button { + -fx-font-size: 14px; + -fx-padding: 10 28 10 28; + -fx-background-radius: 4; + -fx-cursor: hand; + -fx-font-weight: bold; + -fx-border-style: solid; + -fx-border-width: 2px; + -fx-border-radius: 4; + -fx-background-color: dark-colour; + -fx-text-fill: light-colour; + -fx-border-color: dark-colour; +} + +.button:hover { + -fx-text-fill: dark-colour; + -fx-background-color: green-colour; +} + +/* Exit button */ +.exit-button { + -fx-background-color: dark-red-colour; + -fx-text-fill: light-colour; + -fx-border-color: dark-red-colour; +} + +.exit-button:hover { + -fx-background-color: red-colour; +} + +/* Browse button */ +.browse-button { + -fx-padding: 6 18 6 18; + -fx-font-size: 12px; +} + +/* Table view */ +.table-view { + -fx-background-color: light-colour; + -fx-border-color: dark-colour; + -fx-border-width: 1; +} + +.table-view .column-header-background { + -fx-background-color: green-colour; +} + +.table-view .column-header .label { + -fx-text-fill: dark-colour; + -fx-font-weight: bold; +} + +.table-view .table-row-cell { + -fx-background-color: light-colour; + -fx-border-color: transparent; +} + +.table-view .table-row-cell:odd { + -fx-background-color: light-green-colour; +} + +.table-view .table-row-cell:selected { + -fx-background-color: green-colour; +} + +.table-view .table-row-cell:selected .text { + -fx-fill: dark-colour; + -fx-font-weight: bold; +} + +/* Tab pane */ +.tab-pane { + -fx-background-color: light-colour; +} + +.tab-pane .tab-header-area { + -fx-background-color: green-colour; + -fx-padding: 4 0 0 4; +} + +.tab-pane .tab { + -fx-background-color: green-colour; + -fx-background-radius: 4 4 0 0; + -fx-padding: 5 16 5 16; +} + +.tab-pane .tab:selected { + -fx-background-color: light-colour; +} + +.tab-pane .tab .tab-label { + -fx-text-fill: dark-colour; + -fx-font-weight: bold; + -fx-font-size: 12px; +} + +.tab-pane .tab-content-area { + -fx-background-color: light-colour; + -fx-padding: 0; +} + +/* List view */ +.list-view { + -fx-background-color: light-colour; + -fx-border-color: green-colour; +} + +.list-view .list-cell { + -fx-background-color: light-colour; + -fx-text-fill: dark-colour; + -fx-padding: 6 8; +} + +.list-view .list-cell:odd { + -fx-background-color: green-colour; +} + +.list-view .list-cell:selected { + -fx-background-color: dark-colour; + -fx-text-fill: light-colour; +} + +/* ComboBox */ +.combo-box { + -fx-background-color: green-colour; + -fx-background-radius: 4; + -fx-text-fill: dark-colour; +} + +.combo-box .list-cell { + -fx-text-fill: dark-colour; + -fx-background-color: green-colour; +} + +.combo-box-popup .list-view .list-cell { + -fx-background-color: light-colour; + -fx-text-fill: dark-colour; +} + +.combo-box-popup .list-view .list-cell:selected { + -fx-background-color: green-colour; +} + +/* Separator */ +.separator .line { + -fx-border-color: dark-colour; + -fx-opacity: 0.4; +} diff --git a/src/main/java/View/GameSetupScene.java b/src/main/java/View/GameSetupScene.java index f6c8664..0ed8ded 100644 --- a/src/main/java/View/GameSetupScene.java +++ b/src/main/java/View/GameSetupScene.java @@ -1,12 +1,13 @@ package View; import javafx.geometry.Insets; +import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.*; -import javafx.scene.layout.VBox; -import javafx.scene.layout.HBox; +import javafx.scene.layout.*; import javafx.stage.FileChooser; import javafx.stage.Stage; + import Controller.StockFileHandler; import Model.Exchange; import Model.Stock; @@ -17,6 +18,7 @@ import java.util.function.Consumer; public class GameSetupScene { + private Scene scene; private Consumer onGameStart; private File selectedFile; @@ -28,114 +30,174 @@ public GameSetupScene(Consumer onGameStart) { } private Scene createScene() { - VBox root = new VBox(15); - root.setPadding(new Insets(20)); - root.setStyle("-fx-font-family: Arial; -fx-font-size: 12;"); - // title + // Card (centered cream box) + VBox card = new VBox(20); + card.getStyleClass().add("card"); + card.setMaxWidth(560); + card.setMinWidth(400); + + // Title Label titleLabel = new Label("Stock Trading Game"); - titleLabel.setStyle("-fx-font-size: 24; -fx-font-weight: bold;"); - root.getChildren().add(titleLabel); + titleLabel.getStyleClass().add("title-label"); + + // Spacer below title + Region titleSpacer = new Region(); + titleSpacer.setMinHeight(6); + + // Player name row + HBox nameBox = new HBox(16); + nameBox.setAlignment(Pos.CENTER_LEFT); + nameBox.setMaxWidth(Double.MAX_VALUE); + + Label nameLabel = new Label("Player:"); + nameLabel.setMinWidth(130); + nameLabel.getStyleClass().add("form-label"); - // player name - HBox nameBox = new HBox(10); - Label nameLabel = new Label("Player Name:"); - nameLabel.setMinWidth(120); TextField nameField = new TextField(); nameField.setPromptText("Enter your name"); + HBox.setHgrow(nameField, Priority.ALWAYS); + nameBox.getChildren().addAll(nameLabel, nameField); - // starting capital - HBox capitalBox = new HBox(10); - Label capitalLabel = new Label("Starting Capital:"); - capitalLabel.setMinWidth(120); + // Starting capital row + HBox capitalBox = new HBox(16); + capitalBox.setAlignment(Pos.CENTER_LEFT); + capitalBox.setMaxWidth(Double.MAX_VALUE); + + Label capitalLabel = new Label("Start Capital:"); + capitalLabel.setMinWidth(130); + capitalLabel.getStyleClass().add("form-label"); + TextField capitalField = new TextField(); - capitalField.setPromptText("Enter amount (e.g., 10000)"); + capitalField.setPromptText("e.g. 10000"); + HBox.setHgrow(capitalField, Priority.ALWAYS); + capitalBox.getChildren().addAll(capitalLabel, capitalField); - // file selection - HBox fileBox = new HBox(10); + // File selection row + HBox fileBox = new HBox(16); + fileBox.setAlignment(Pos.CENTER_LEFT); + fileBox.setMaxWidth(Double.MAX_VALUE); + Label fileSelectLabel = new Label("Stock Data File:"); - fileSelectLabel.setMinWidth(120); + fileSelectLabel.setMinWidth(130); + fileSelectLabel.getStyleClass().add("form-label"); + fileLabel = new Label("No file selected"); - fileLabel.setStyle("-fx-text-fill: #666666;"); + fileLabel.getStyleClass().add("file-label"); + HBox.setHgrow(fileLabel, Priority.ALWAYS); + Button browseButton = new Button("Browse"); + browseButton.getStyleClass().add("browse-button"); browseButton.setOnAction(e -> selectFile()); + fileBox.getChildren().addAll(fileSelectLabel, fileLabel, browseButton); - // button box - HBox buttonBox = new HBox(10); - buttonBox.setPadding(new Insets(20, 0, 0, 0)); - + // Spacer before buttons + Region buttonSpacer = new Region(); + buttonSpacer.setMinHeight(10); + + // Button row — buttons fill full card width equally + HBox buttonBox = new HBox(12); + buttonBox.setAlignment(Pos.CENTER_LEFT); + buttonBox.setMaxWidth(Double.MAX_VALUE); + Button startButton = new Button("Start Game"); - startButton.setStyle("-fx-font-size: 14; -fx-padding: 10 40 10 40;"); - startButton.setOnAction(e -> { - String name = nameField.getText().trim(); - String capitalStr = capitalField.getText().trim(); - - if (name.isEmpty()) { - showAlert("Validation Error", "Please enter a player name"); - return; - } - - if (capitalStr.isEmpty()) { - showAlert("Validation Error", "Please enter starting capital"); + startButton.getStyleClass().add("start-button"); + startButton.setMaxWidth(Double.MAX_VALUE); + startButton.setOnAction(e -> handleStart(nameField, capitalField)); + HBox.setHgrow(startButton, Priority.ALWAYS); + + Button exitButton = new Button("Exit"); + exitButton.getStyleClass().add("exit-button"); + exitButton.setMaxWidth(Double.MAX_VALUE); + exitButton.setOnAction(e -> System.exit(0)); + HBox.setHgrow(exitButton, Priority.ALWAYS); + + buttonBox.getChildren().addAll(startButton, exitButton); + + card.getChildren().addAll( + titleLabel, + titleSpacer, + nameBox, + capitalBox, + fileBox, + buttonSpacer, + buttonBox + ); + + // Center the card without stretching it vertically + VBox root = new VBox(card); + root.setAlignment(Pos.CENTER); + root.setFillWidth(false); + + Scene scene = new Scene(root, 800, 550); + scene.getStylesheets().add( + getClass().getResource("/Style/Global.css").toExternalForm() + ); + + return scene; + } + + private void handleStart(TextField nameField, TextField capitalField) { + String name = nameField.getText().trim(); + String capitalStr = capitalField.getText().trim(); + + if (name.isEmpty()) { + showAlert("Validation Error", "Please enter a player name"); + return; + } + + if (capitalStr.isEmpty()) { + showAlert("Validation Error", "Please enter starting capital"); + return; + } + + if (selectedFile == null) { + showAlert("Validation Error", "Please select a stock data file"); + return; + } + + try { + BigDecimal capital = new BigDecimal(capitalStr); + + if (capital.compareTo(BigDecimal.ZERO) <= 0) { + showAlert("Validation Error", "Starting capital must be greater than 0"); return; } - - if (selectedFile == null) { - showAlert("Validation Error", "Please select a stock data file"); + + StockFileHandler fileHandler = new StockFileHandler(); + List stocks = fileHandler.loadStocksFromFile(selectedFile.getAbsolutePath()); + + if (stocks.isEmpty()) { + showAlert("Error", "No stocks found in the selected file"); return; } - - try { - BigDecimal capital = new BigDecimal(capitalStr); - if (capital.compareTo(BigDecimal.ZERO) <= 0) { - showAlert("Validation Error", "Starting capital must be greater than 0"); - return; - } - - StockFileHandler fileHandler = new StockFileHandler(); - List stocks = fileHandler.loadStocksFromFile(selectedFile.getAbsolutePath()); - - if (stocks.isEmpty()) { - showAlert("Error", "No stocks found in the selected file"); - return; - } - - Exchange exchange = new Exchange("Main Exchange", stocks); - onGameStart.accept(new StartGameData(name, capital, exchange)); - } catch (NumberFormatException ex) { - showAlert("Validation Error", "Starting capital must be a valid number"); - } catch (Exception ex) { - showAlert("Error", "Failed to load file: " + ex.getMessage()); - } - }); - - Button exitButton = new Button("Exit"); - exitButton.setOnAction(e -> System.exit(0)); - buttonBox.getChildren().addAll(startButton, exitButton); - root.getChildren().addAll(nameBox, capitalBox, fileBox, buttonBox); + Exchange exchange = new Exchange("Main Exchange", stocks); + onGameStart.accept(new StartGameData(name, capital, exchange)); - ScrollPane scrollPane = new ScrollPane(root); - scrollPane.setFitToWidth(true); - return new Scene(scrollPane, 600, 400); + } catch (NumberFormatException ex) { + showAlert("Validation Error", "Starting capital must be a valid number"); + } catch (Exception ex) { + showAlert("Error", "Failed to load file: " + ex.getMessage()); + } } private void selectFile() { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle("Select Stock Data File"); fileChooser.getExtensionFilters().addAll( - new FileChooser.ExtensionFilter("CSV Files", "*.csv"), - new FileChooser.ExtensionFilter("All Files", "*.*") + new FileChooser.ExtensionFilter("CSV Files", "*.csv"), + new FileChooser.ExtensionFilter("All Files", "*.*") ); - + File file = fileChooser.showOpenDialog(new Stage()); + if (file != null) { selectedFile = file; fileLabel.setText(file.getName()); - fileLabel.setStyle("-fx-text-fill: #000000;"); } } diff --git a/src/main/java/View/MainGameScene.java b/src/main/java/View/MainGameScene.java index 5947dd2..8191208 100644 --- a/src/main/java/View/MainGameScene.java +++ b/src/main/java/View/MainGameScene.java @@ -1,6 +1,7 @@ package View; import javafx.geometry.Insets; +import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.layout.*; @@ -26,68 +27,80 @@ public MainGameScene(Exchange exchange, Player player, Runnable onExit) { } private Scene createScene() { - VBox root = new VBox(5); - root.setPadding(new Insets(10)); + VBox root = new VBox(0); // TOP STATUS BAR - HBox topBar = new HBox(15); - topBar.setPadding(new Insets(10)); - topBar.setStyle("-fx-background-color: #f0f0f0; -fx-border-color: #999;"); - + HBox topBar = new HBox(12); + topBar.getStyleClass().add("top-bar"); + topBar.setAlignment(Pos.CENTER_LEFT); + statusLabel = new Label(); + statusLabel.getStyleClass().add("status-label"); updateStatus(); - + + Separator sep = new Separator(javafx.geometry.Orientation.VERTICAL); + sep.setPrefHeight(20); + Button nextWeekBtn = new Button("Next week"); - nextWeekBtn.setStyle("-fx-font-size: 12; -fx-padding: 10 20; -fx-font-weight: bold;"); + nextWeekBtn.getStyleClass().addAll("action-button"); nextWeekBtn.setOnAction(e -> advance()); - + Button exitBtn = new Button("Exit"); + exitBtn.getStyleClass().add("exit-button"); exitBtn.setOnAction(e -> { if (confirm("Exit Game?", "Final Net Worth: $" + formatMoney(getNetWorth()))) { onExit.run(); } }); - - topBar.getChildren().addAll(statusLabel, new Separator(javafx.geometry.Orientation.VERTICAL), - nextWeekBtn, exitBtn); - root.getChildren().add(topBar); + + topBar.getChildren().addAll(statusLabel, sep, nextWeekBtn, exitBtn); // MAIN CONTENT TABS TabPane tabs = new TabPane(); tabs.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE); - tabs.getTabs().addAll( new Tab("Stocks", createStocksPanel()), new Tab("Portfolio", createPortfolioPanel()), new Tab("Trade", createTradePanel()), new Tab("History", createHistoryPanel()) ); - + VBox.setVgrow(tabs, Priority.ALWAYS); - root.getChildren().add(tabs); + root.getChildren().addAll(topBar, tabs); - return new Scene(root, 1000, 700); + Scene scene = new Scene(root, 1000, 700); + scene.getStylesheets().add( + getClass().getResource("/Style/Global.css").toExternalForm() + ); + return scene; } private VBox createStocksPanel() { VBox panel = new VBox(10); - panel.setPadding(new Insets(10)); - - HBox searchBox = new HBox(10); + panel.getStyleClass().add("content-area"); + + HBox searchBox = new HBox(8); + searchBox.setAlignment(Pos.CENTER_LEFT); + TextField search = new TextField(); search.setPromptText("Search symbol or company..."); + HBox.setHgrow(search, Priority.ALWAYS); + + Button searchBtn = new Button("Search"); + searchBtn.getStyleClass().add("action-button"); + ComboBox filter = new ComboBox<>(); filter.setItems(FXCollections.observableArrayList("All", "Gainers", "Losers")); filter.setValue("All"); - + TableView table = new TableView<>(); addStockColumns(table); - + Runnable loadStocks = () -> { List stocks; String filterVal = filter.getValue(); String searchVal = search.getText().trim(); - + if ("Gainers".equals(filterVal)) { stocks = exchange.getGainers(20); } else if ("Losers".equals(filterVal)) { @@ -95,21 +108,21 @@ private VBox createStocksPanel() { } else { stocks = exchange.findStocks(searchVal); } - + ObservableList data = FXCollections.observableArrayList(); for (Stock s : stocks) { data.add(new StockRow(s)); } table.setItems(data); }; - - Button searchBtn = new Button("Search"); + searchBtn.setOnAction(e -> loadStocks.run()); filter.setOnAction(e -> loadStocks.run()); - + search.setOnAction(e -> loadStocks.run()); + searchBox.getChildren().addAll(search, searchBtn, filter); loadStocks.run(); - + VBox.setVgrow(table, Priority.ALWAYS); panel.getChildren().addAll(searchBox, table); return panel; @@ -117,31 +130,34 @@ private VBox createStocksPanel() { private VBox createPortfolioPanel() { VBox panel = new VBox(10); - panel.setPadding(new Insets(10)); - + panel.getStyleClass().add("content-area"); + + Label heading = new Label("Holdings:"); + TableView table = new TableView<>(); addPortfolioColumns(table); updatePortfolio(table); - + Button refresh = new Button("Refresh"); + refresh.getStyleClass().add("action-button"); refresh.setOnAction(e -> updatePortfolio(table)); - + VBox.setVgrow(table, Priority.ALWAYS); - panel.getChildren().addAll(new Label("Holdings:"), table, refresh); + panel.getChildren().addAll(heading, table, refresh); return panel; } private VBox createTradePanel() { - VBox panel = new VBox(10); - panel.setPadding(new Insets(10)); - + VBox panel = new VBox(0); + panel.getStyleClass().add("content-area"); + TabPane tradeTabs = new TabPane(); tradeTabs.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE); tradeTabs.getTabs().addAll( new Tab("Buy", createBuyTab()), new Tab("Sell", createSellTab()) ); - + VBox.setVgrow(tradeTabs, Priority.ALWAYS); panel.getChildren().add(tradeTabs); return panel; @@ -149,20 +165,32 @@ private VBox createTradePanel() { private VBox createBuyTab() { VBox box = new VBox(10); - box.setPadding(new Insets(10)); - + box.getStyleClass().add("content-area"); + + Label heading = new Label("Buy Stocks:"); + + GridPane form = new GridPane(); + form.setHgap(10); + form.setVgap(10); + TextField stockField = new TextField(); - stockField.setPromptText("Stock symbol (e.g., AAPL)"); - + stockField.setPromptText("Stock symbol (e.g. AAPL)"); + TextField qtyField = new TextField(); qtyField.setPromptText("Quantity"); - + + form.add(new Label("Symbol:"), 0, 0); + form.add(stockField, 1, 0); + form.add(new Label("Quantity:"), 0, 1); + form.add(qtyField, 1, 1); + Label infoLabel = new Label(); - + stockField.textProperty().addListener((obs, old, val) -> updateBuyInfo(val, qtyField, infoLabel)); qtyField.textProperty().addListener((obs, old, val) -> updateBuyInfo(stockField.getText(), qtyField, infoLabel)); - + Button buyBtn = new Button("Buy"); + buyBtn.getStyleClass().add("action-button"); buyBtn.setOnAction(e -> { try { Stock s = exchange.getStock(stockField.getText().toUpperCase()); @@ -185,42 +213,40 @@ private VBox createBuyTab() { alert("Error", ex.getMessage()); } }); - - box.getChildren().addAll( - new Label("Buy Stocks:"), - stockField, qtyField, infoLabel, buyBtn - ); + + box.getChildren().addAll(heading, form, infoLabel, buyBtn); return box; } private VBox createSellTab() { VBox box = new VBox(10); - box.setPadding(new Insets(10)); - + box.getStyleClass().add("content-area"); + + Label heading = new Label("Your Holdings:"); + ListView holdingsList = new ListView<>(); + holdingsList.setPrefHeight(200); + VBox.setVgrow(holdingsList, Priority.ALWAYS); updateHoldingsList(holdingsList); - - TextField qtyField = new TextField(); - qtyField.setPromptText("Quantity to sell"); - + Label infoLabel = new Label(); - - Button sellBtn = new Button("Sell"); + + Button sellBtn = new Button("Sell Selected"); + sellBtn.getStyleClass().add("action-button"); sellBtn.setOnAction(e -> { String selected = holdingsList.getSelectionModel().getSelectedItem(); if (selected == null) { - alert("Error", "Select a holding"); + alert("Error", "Select a holding to sell"); return; } try { String symbol = selected.split(" ")[0]; List shares = player.getPortfolio().getShares(symbol); if (shares.isEmpty()) return; - + Transaction trans = exchange.sell(shares.get(0), player); if (trans != null && trans.isCommitted()) { showConfirmation("Sale successful", trans); - qtyField.clear(); updateHoldingsList(holdingsList); updateStatus(); } @@ -228,63 +254,66 @@ private VBox createSellTab() { alert("Error", ex.getMessage()); } }); - - holdingsList.setPrefHeight(200); - VBox.setVgrow(holdingsList, Priority.ALWAYS); - box.getChildren().addAll( - new Label("Your Holdings:"), - holdingsList, qtyField, infoLabel, sellBtn - ); + + box.getChildren().addAll(heading, holdingsList, infoLabel, sellBtn); return box; } private VBox createHistoryPanel() { VBox panel = new VBox(10); - panel.setPadding(new Insets(10)); - + panel.getStyleClass().add("content-area"); + ComboBox weekFilter = new ComboBox<>(); updateWeekCombo(weekFilter); - + TableView table = new TableView<>(); addHistoryColumns(table); updateHistory(table, null); - - weekFilter.setOnAction(e -> updateHistory(table, weekFilter.getValue() == 0 ? null : weekFilter.getValue())); - + + weekFilter.setOnAction(e -> updateHistory( + table, + weekFilter.getValue() == null || weekFilter.getValue() == 0 ? null : weekFilter.getValue() + )); + + HBox filterRow = new HBox(8); + filterRow.setAlignment(Pos.CENTER_LEFT); + filterRow.getChildren().addAll(new Label("Week:"), weekFilter); + VBox.setVgrow(table, Priority.ALWAYS); - panel.getChildren().addAll(new HBox(10, new Label("Week:"), weekFilter), table); + panel.getChildren().addAll(filterRow, table); return panel; } - // HELPER METHODS + // ---- Column helpers ---- + private void addStockColumns(TableView table) { table.getColumns().addAll( - createCol("Symbol", 80, "symbol"), - createCol("Company", 150, "company"), - createCol("Price", 80, "price"), - createCol("Change", 80, "change"), - createCol("High", 80, "high"), - createCol("Low", 80, "low") + createCol("Symbol", 90, "symbol"), + createCol("Company", 180, "company"), + createCol("Price", 90, "price"), + createCol("Change", 90, "change"), + createCol("High", 90, "high"), + createCol("Low", 90, "low") ); } private void addPortfolioColumns(TableView table) { table.getColumns().addAll( - createCol("Symbol", 80, "symbol"), - createCol("Qty", 60, "qty"), - createCol("Buy Price", 80, "buyPrice"), - createCol("Current Price", 100, "currentPrice"), - createCol("Gain/Loss", 80, "gainLoss") + createCol("Symbol", 90, "symbol"), + createCol("Qty", 70, "qty"), + createCol("Buy Price", 100, "buyPrice"), + createCol("Current Price", 120, "currentPrice"), + createCol("Gain/Loss", 100, "gainLoss") ); } private void addHistoryColumns(TableView table) { table.getColumns().addAll( - createCol("Week", 60, "week"), - createCol("Type", 60, "type"), - createCol("Symbol", 80, "symbol"), - createCol("Qty", 60, "qty"), - createCol("Total", 100, "total") + createCol("Week", 70, "week"), + createCol("Type", 70, "type"), + createCol("Symbol", 90, "symbol"), + createCol("Qty", 70, "qty"), + createCol("Total", 110, "total") ); } @@ -294,7 +323,9 @@ private TableColumn createCol(String header, int width, String pr col.setCellValueFactory(cellData -> { try { return new javafx.beans.property.SimpleStringProperty( - cellData.getValue().getClass().getMethod("get" + capitalize(property)).invoke(cellData.getValue()).toString() + cellData.getValue().getClass() + .getMethod("get" + capitalize(property)) + .invoke(cellData.getValue()).toString() ); } catch (Exception e) { return new javafx.beans.property.SimpleStringProperty(""); @@ -307,6 +338,8 @@ private String capitalize(String s) { return s.substring(0, 1).toUpperCase() + s.substring(1); } + // ---- Data updaters ---- + private void updatePortfolio(TableView table) { ObservableList data = FXCollections.observableArrayList(); for (Share s : player.getPortfolio().getShares()) { @@ -318,15 +351,18 @@ private void updatePortfolio(TableView table) { private void updateHoldingsList(ListView list) { ObservableList items = FXCollections.observableArrayList(); for (Share s : player.getPortfolio().getShares()) { - items.add(s.getStock().getSymbol() + " - " + formatMoney(s.getQuantity()) + " @ $" + formatMoney(s.getStock().getSalesPrice())); + items.add(s.getStock().getSymbol() + " - " + + formatMoney(s.getQuantity()) + " @ $" + + formatMoney(s.getStock().getSalesPrice())); } list.setItems(items); } private void updateHistory(TableView table, Integer week) { ObservableList data = FXCollections.observableArrayList(); - List trans = week == null ? player.getTransactionArchive().getAllTransactions() : - player.getTransactionArchive().getTransactions(week); + List trans = week == null + ? player.getTransactionArchive().getAllTransactions() + : player.getTransactionArchive().getTransactions(week); for (Transaction t : trans) { data.add(new HistoryRow(t)); } @@ -344,23 +380,27 @@ private void updateWeekCombo(ComboBox combo) { private void updateBuyInfo(String symbol, TextField qtyField, Label label) { try { - if (symbol.isEmpty()) return; + if (symbol == null || symbol.isEmpty()) return; Stock s = exchange.getStock(symbol.toUpperCase()); if (s == null) return; BigDecimal qty = new BigDecimal(qtyField.getText()); BigDecimal gross = s.getSalesPrice().multiply(qty); BigDecimal comm = gross.multiply(new BigDecimal("0.005")); - label.setText("Gross: $" + formatMoney(gross) + " | Commission: $" + formatMoney(comm) + - " | Total: $" + formatMoney(gross.add(comm))); + label.setText("Gross: $" + formatMoney(gross) + + " | Commission: $" + formatMoney(comm) + + " | Total: $" + formatMoney(gross.add(comm))); } catch (Exception e) { - // ignore + // ignore partial input } } private void updateStatus() { - statusLabel.setText("Player: " + player.getName() + " | Week: " + exchange.getWeek() + - " | Cash: $" + formatMoney(player.getMoney()) + - " | Net Worth: $" + formatMoney(getNetWorth())); + statusLabel.setText( + "Player: " + player.getName() + + " | Week: " + exchange.getWeek() + + " | Cash: $" + formatMoney(player.getMoney()) + + " | Net Worth: $" + formatMoney(getNetWorth()) + ); } private void advance() { @@ -391,6 +431,7 @@ private void showConfirmation(String title, Transaction t) { private void alert(String title, String msg) { Alert a = new Alert(Alert.AlertType.INFORMATION); a.setTitle(title); + a.setHeaderText(null); a.setContentText(msg); a.showAndWait(); } @@ -398,6 +439,7 @@ private void alert(String title, String msg) { private boolean confirm(String title, String msg) { Alert a = new Alert(Alert.AlertType.CONFIRMATION); a.setTitle(title); + a.setHeaderText(null); a.setContentText(msg); return a.showAndWait().get() == ButtonType.OK; } @@ -410,7 +452,8 @@ public Scene getScene() { return scene; } - // DATA CLASSES + // ---- Data row classes ---- + static class StockRow { Stock s; StockRow(Stock s) { this.s = s; } diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst index 9926576..e69de29 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -1,22 +0,0 @@ -Model\TransactionCalculator.class -Model\Portfolio.class -Model\Share.class -View\GameSetupScene.class -View\MainGameScene$TransactionInfo.class -Model\TransactionArchive.class -View\GameSetupScene$StartGameData.class -View\MainGameScene$StockInfo.class -View\Launcher.class -Model\Purchase.class -Model\Sale.class -Model\Exchange.class -Model\Transaction.class -View\MainGameScene$ShareInfo.class -Model\PurchaseCalculator.class -Model\SaleCalculator.class -Model\Stock.class -Model\Player.class -View\StockTradingGameApp.class -Controller\StockFileHandler.class -View\MainGameScene.class -View\MainGameScene$ShareListCell.class diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst index fc20747..8648fde 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -1,17 +1,17 @@ -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Controller\StockFileHandler.java -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Model\Exchange.java -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Model\Player.java -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Model\Portfolio.java -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Model\Purchase.java -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Model\PurchaseCalculator.java -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Model\Sale.java -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Model\SaleCalculator.java -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Model\Share.java -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Model\Stock.java -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Model\Transaction.java -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Model\TransactionArchive.java -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\Model\TransactionCalculator.java -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\View\GameSetupScene.java -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\View\Launcher.java -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\View\MainGameScene.java -C:\Users\elisa\Downloads\progdel1\Programmering2_mappe_v26\src\main\java\View\StockTradingGameApp.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/Controller/StockFileHandler.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/Model/Exchange.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/Model/Player.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/Model/Portfolio.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/Model/Purchase.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/Model/PurchaseCalculator.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/Model/Sale.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/Model/SaleCalculator.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/Model/Share.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/Model/Stock.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/Model/Transaction.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/Model/TransactionArchive.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/Model/TransactionCalculator.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/View/GameSetupScene.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/View/Launcher.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/View/MainGameScene.java +/Users/solveignatvig/Library/CloudStorage/Dropbox/NTNU/Dataingeniør/V2026/IDATT2003 Programmering 2/IDATT2003_Programmering2_mappe_v26/Programmering2_mappe_v26/src/main/java/View/StockTradingGameApp.java