Skip to content

Commit

Permalink
Merge pull request #98 from einaskoi/per/clean
Browse files Browse the repository at this point in the history
add game states and fix bugs (when gametick was off)
  • Loading branch information
einaskoi authored May 13, 2026
2 parents f6887b1 + 2b58fb3 commit 18fa3be
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 167 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public record BankAppController(BankApp bankApp, Player player) implements AppCo
* @param player the player model
*/
public BankAppController {
nextTick();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,26 @@
import edu.ntnu.idi.idatt2003.gruppe42.View.Apps.StockApp;
import java.math.BigDecimal;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.ListCell;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;

/**
* Controller for the {@link StockApp}.
* Handles user interactions for buying and selling stocks,
* and updates the UI in real-time.
*/
public final class StockAppController implements AppController {

private final MarketController marketController;
private final StockApp stockApp;
private final Player player;
private Stock currentStock;

/**
* Constructs a new StockAppController.
Expand All @@ -34,67 +44,149 @@ public StockAppController(
this.marketController = marketController;
this.player = player;

stockApp.getStockList().getItems().addAll(
marketController.getExchange().getAllStocks()
);
stockApp.getStockList().getItems()
.addAll(marketController.getExchange().getAllStocks());

stockApp.getStockList().setCellFactory(lv -> createStockCell());

stockApp.getSearchField().textProperty().addListener(
(obs, old, newValue) -> {
if (stockApp.getCurrentStock() != null && !newValue.isEmpty()) {
stockApp.openSearchPage();
if (currentStock != null && !newValue.isEmpty()) {
navigateToSearch();
}
stockApp.getStockList().getItems().setAll(
marketController.getMarket(newValue)
);
stockApp.getStockList().getItems()
.setAll(marketController.getMarket(newValue));
});

stockApp.getQuantitySpinner().valueProperty().addListener(
(obs, old, newValue) -> {
if (stockApp.getCurrentStock() != null) {
if (currentStock != null) {
updateReceipt();
}
});

stockApp.getConfirmButton().setOnAction(event -> {
handleTransaction();
});
stockApp.getConfirmButton().setOnAction(e -> handleTransaction());
}

/**
* Navigates to the detail page for the given stock.
*
* @param stock the stock to view
*/
private void navigateToStock(final Stock stock) {
currentStock = stock;
stock.getStockGraph().setVisibility(true);
Platform.runLater(stock::updateStockGraph);
stockApp.showStockPage(stock);
updateReceipt();
}

/**
* Navigates back to the stock search page.
*/
private void navigateToSearch() {
if (currentStock != null) {
currentStock.getStockGraph().setVisibility(false);
}
currentStock = null;
stockApp.showSearchPage();
}

/**
* Creates a list cell for displaying a stock row.
*
* @return a configured list cell
*/
private ListCell<Stock> createStockCell() {
return new ListCell<>() {
private final HBox row = new HBox(15);
private final Label symbolLabel = new Label();
private final Label companyLabel = new Label();
private final Label priceLabel = new Label();
private final Label changeLabel = new Label();

{
row.setPadding(new Insets(10));
row.setAlignment(Pos.CENTER_LEFT);
row.getStyleClass().add("stock-list-item");

VBox names = new VBox(2, symbolLabel, companyLabel);
symbolLabel.getStyleClass().add("stock-symbol");
companyLabel.getStyleClass().add("stock-company");

Region spacer = new Region();
HBox.setHgrow(spacer, Priority.ALWAYS);

VBox priceInfo = new VBox(2, priceLabel, changeLabel);
priceInfo.setAlignment(Pos.CENTER_RIGHT);
priceLabel.getStyleClass().add("stock-price");
changeLabel.getStyleClass().add("stock-price-change");

row.getChildren().addAll(names, spacer, priceInfo);
row.setOnMouseClicked(e -> {
Stock stock = getItem();
if (stock != null) {
navigateToStock(stock);
}
});
}

@Override
protected void updateItem(final Stock stock, final boolean empty) {
super.updateItem(stock, empty);
if (empty || stock == null) {
setGraphic(null);
return;
}
symbolLabel.setText(stock.getSymbol());
companyLabel.setText(stock.getCompany());
priceLabel.setText("$" + String.format("%,.2f", stock.getSalesPrice()));

BigDecimal change = stock.getLatestPriceChange();
changeLabel.setText(
(change.compareTo(BigDecimal.ZERO) >= 0 ? "+" : "")
+ String.format("%,.2f", change)
);
changeLabel.getStyleClass()
.removeAll("stock-price-positive", "stock-price-negative");
changeLabel.getStyleClass().add(
change.compareTo(BigDecimal.ZERO) >= 0
? "stock-price-positive" : "stock-price-negative"
);
setGraphic(row);
}
};
}

/**
* Handles the buy or sell transaction based on the quantity spinner value.
* Handles the trade button action based on the spinner value.
*/
private void handleTransaction() {
Stock currentStock = stockApp.getCurrentStock();
if (currentStock == null) {
return;
}

int quantityValue = stockApp.getQuantitySpinner().getValue();
if (quantityValue == 0) {
int value = stockApp.getQuantitySpinner().getValue();
if (value == 0) {
return;
}

BigDecimal quantity = new BigDecimal(Math.abs(quantityValue));

if (quantityValue > 0) {
BigDecimal quantity = new BigDecimal(Math.abs(value));
if (value > 0) {
handleBuy(currentStock, quantity);
} else {
handleSell(currentStock, quantity);
}
}

/**
* Performs a buy transaction.
* Performs a buy transaction for the given stock.
*
* @param stock the stock to buy
* @param quantity the amount to buy
* @param quantity the quantity to buy
*/
private void handleBuy(final Stock stock, final BigDecimal quantity) {
try {
Transaction transaction = marketController.getExchange().buy(
stock.getSymbol(), quantity, player
);

Transaction transaction = marketController.getExchange()
.buy(stock.getSymbol(), quantity, player);
if (transaction != null) {
transaction.commit(player);
player.getPortfolio().addShare(transaction.getShare());
Expand All @@ -105,10 +197,10 @@ private void handleBuy(final Stock stock, final BigDecimal quantity) {
}

/**
* Performs a sell transaction.
* Performs a sell transaction for the given stock.
*
* @param stock the stock to sell
* @param quantity the amount to sell
* @param quantity the quantity to sell
*/
private void handleSell(final Stock stock, final BigDecimal quantity) {
player.getPortfolio().getShares().stream()
Expand All @@ -118,10 +210,8 @@ private void handleSell(final Stock stock, final BigDecimal quantity) {
if (existingShare.getQuantity().compareTo(quantity) < 0) {
return;
}

Transaction transaction = marketController.getExchange().sell(
existingShare, quantity, player
);
Transaction transaction = marketController.getExchange()
.sell(existingShare, quantity, player);
if (transaction != null) {
transaction.commit(player);
player.getPortfolio().removeShare(transaction.getShare());
Expand All @@ -130,10 +220,9 @@ private void handleSell(final Stock stock, final BigDecimal quantity) {
}

/**
* Updates the receipt in the stock app.
* Updates the receipt display based on the current stock and spinner value.
*/
private void updateReceipt() {
Stock currentStock = stockApp.getCurrentStock();
if (currentStock != null) {
Platform.runLater(() ->
stockApp.getReceipt().update(
Expand All @@ -146,17 +235,14 @@ private void updateReceipt() {

/**
* Updates the app state on each simulation tick.
* Refreshes the market data and updates UI components.
*/
@Override
public void nextTick() {
marketController.updateMarket();
Platform.runLater(() -> stockApp.getStockList().refresh());
Stock currentStockInView = stockApp.getCurrentStock();
if (currentStockInView != null) {
stockApp.updatePriceLabel(currentStockInView);
if (currentStock != null) {
stockApp.updatePriceLabel(currentStock);
updateReceipt();
// Graph is updated within marketController.updateMarket() if visible
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package edu.ntnu.idi.idatt2003.gruppe42.Controller;

import edu.ntnu.idi.idatt2003.gruppe42.Controller.AppControllers.AppController;
import edu.ntnu.idi.idatt2003.gruppe42.Model.GameState;
import edu.ntnu.idi.idatt2003.gruppe42.Model.Player;

import java.util.ArrayList;
Expand All @@ -15,6 +16,7 @@ public final class GameController {
private final Player player;
private final List<AppController> appControllers = new ArrayList<>();
private Timer timer;
private GameState gameState;

/**
* Constructs a new GameController.
Expand All @@ -34,6 +36,10 @@ public void addAppController(final AppController appController) {
appControllers.add(appController);
}

public void setGameState(GameState gameState) {
this.gameState = gameState;
}

/**
* Starts the game simulation timer.
*/
Expand All @@ -45,14 +51,24 @@ public void startGame() {
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {

if (isWeekend()) {
stopGame();
}

for (AppController controller : appControllers) {
controller.nextTick();

}
}
}, delay, period);

}

public boolean isWeekend() {
return !(gameState == GameState.WORKDAY);
}

/**
* Stops the game simulation timer.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package edu.ntnu.idi.idatt2003.gruppe42.Controller;

import edu.ntnu.idi.idatt2003.gruppe42.Controller.AppControllers.AppController;
import edu.ntnu.idi.idatt2003.gruppe42.Model.Day;
import edu.ntnu.idi.idatt2003.gruppe42.Model.GameState;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Random;
Expand All @@ -23,11 +25,12 @@ public class TimeAndWeatherController implements AppController {
private final Random random = new Random();
private final GameController gameController;

private static final String[] DAYS = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
private static final Day[] DAYS = {Day.SUN, Day.MON, Day.TUE, Day.WED, Day.THU, Day.FRI, Day.SAT};

public TimeAndWeatherController(GameController gameController) {
this.gameController = gameController;
updateWeather();
updateGameState();
}

@Override
Expand All @@ -37,14 +40,10 @@ public void nextTick() {
hour.set(0);
dayIndex.set((dayIndex.get() + 1) % 7);
updateWeather();
updateGameState();
} else {
hour.set(nextHour);
}

if (dayIndex.get() > 5) {
gameController.stopGame();

}
}

private void updateWeather() {
Expand Down Expand Up @@ -89,6 +88,17 @@ public String getTimeString() {
}

public String getDayOfWeekString() {
return DAYS[dayIndex.get()];
return DAYS[dayIndex.get()].toString();
}

public void updateGameState() {
if (dayIndex.equals(new SimpleIntegerProperty(6))) {
gameController.setGameState(GameState.RENTDAY);
return;
} else if (dayIndex.equals(new SimpleIntegerProperty(0))) {
gameController.setGameState(GameState.FREEDAY);
return;
}
gameController.setGameState(GameState.WORKDAY);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public DesktopViewController(

bankApp.setOnShareSelected(share -> {
popupsController.show(App.STOCK);
stockApp.openStockPage(share.getStock());
stockApp.showStockPage(share.getStock());
});

this.desktopView = new DesktopView(this);
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/edu/ntnu/idi/idatt2003/gruppe42/Model/Day.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package edu.ntnu.idi.idatt2003.gruppe42.Model;

public enum Day {
MON, TUE, WED, THU, FRI, SAT, SUN;
}
Loading

0 comments on commit 18fa3be

Please sign in to comment.