package controller; import static java.util.Objects.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javafx.animation.Animation; import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.ToggleButton; import javafx.scene.control.ToggleGroup; import javafx.util.Duration; import javafx.util.Pair; import model.Board; import model.Cloud; import model.EntityFactory; import model.Fire; import model.FireFighter; import model.FireFighterScenario; import model.MotorizedFireFighter; import model.Mountain; import model.Rockery; import model.Square; import util.Position; import view.Grid; import view.ViewElement; public class Controller { public static final int PERIOD_IN_MILLISECONDS = 50; @FXML public Button restartButton; @FXML public Button oneStepButton; @FXML public Label generationNumberLabel; @FXML private ToggleButton pauseToggleButton; @FXML private ToggleButton playToggleButton; @FXML private Grid<ViewElement> grid; private Timeline timeline; private Board<Square> board; @FXML private void initialize() { initializePlayAndPauseToggleButtons(); initializeTimeline(); } private void initializePlayAndPauseToggleButtons() { ToggleGroup toggleGroup = new PersistentToggleGroup(); toggleGroup.getToggles().addAll(playToggleButton, pauseToggleButton); pauseToggleButton.setSelected(true); } private void setModel(Board<Square> board) { this.board = requireNonNull(board, "board is null"); } private void updateBoard() { List<Position> updatedPositions = board.updateToNextGeneration(); List<Pair<Position, ViewElement>> updatedSquares = new ArrayList<>(); for (Position updatedPosition : updatedPositions) { Square squareState = board.getStates(updatedPosition); ViewElement viewElement = getViewElement(squareState); updatedSquares.add(new Pair<>(updatedPosition, viewElement)); } grid.repaint(updatedSquares); updateGenerationLabel(board.stepNumber()); } private void repaintGrid() { int columnCount = board.columnCount(); int rowCount = board.rowCount(); ViewElement[][] viewElements = new ViewElement[rowCount][columnCount]; for (int column = 0; column < columnCount; column++) for (int row = 0; row < rowCount; row++) viewElements[row][column] = getViewElement(board.getStates(new Position(row, column))); grid.repaint(viewElements); updateGenerationLabel(board.stepNumber()); } private ViewElement getViewElement(Square square) { return new ViewElement(square.getViewColor()); } private void initializeTimeline() { Duration duration = new Duration(Controller.PERIOD_IN_MILLISECONDS); EventHandler<ActionEvent> eventHandler = event -> updateBoard(); KeyFrame keyFrame = new KeyFrame(duration, eventHandler); timeline = new Timeline(keyFrame); timeline.setCycleCount(Animation.INDEFINITE); } public void play() { timeline.play(); } public void pause() { timeline.pause(); } public void pauseToggleButtonAction() { this.pause(); } public void playToggleButtonAction() { this.play(); } public void restartButtonAction() { this.pause(); board.reset(); pauseToggleButton.setSelected(true); repaintGrid(); } public void initialize(int squareWidth, int squareHeight, int columnCount, int rowCount, int initialFireCount, int initialFirefighterCount, int initialMotorizedFirefightersCount, int initialcloudCount, int initialmountaincount, int turnsForSpawningAirTanker) { grid.setDimensions(columnCount, rowCount, squareWidth, squareHeight); Board<Square> model = new FireFighterScenario(columnCount, rowCount); Map<EntityFactory, Integer> entityCounts = new HashMap<EntityFactory, Integer>(); entityCounts.put((pos, b) -> new Fire(pos), initialFireCount); entityCounts.put((pos, b) -> new FireFighter(pos,b), initialFirefighterCount); entityCounts.put((pos, b) -> new MotorizedFireFighter(pos, b), initialMotorizedFirefightersCount); entityCounts.put((pos, b) -> new Cloud(pos, b), initialcloudCount); entityCounts.put((pos, b) -> new Mountain(pos), initialmountaincount); entityCounts.put((pos, b) -> new Rockery(pos), 30); model.placeInitialEntities(entityCounts); this.setModel(model); repaintGrid(); } public void oneStepButtonAction() { this.pause(); updateBoard(); } private void updateGenerationLabel(int value) { generationNumberLabel.setText(Integer.toString(value)); } }