package seng302.Controllers; import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.ObservableList; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.input.MouseEvent; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.HBox; import javafx.scene.paint.Color; import javafx.scene.layout.GridPane; import javafx.util.Callback; import seng302.Constants; import seng302.Model.*; import java.net.URL; import java.util.ArrayList; import java.util.ResourceBundle; /** * Created by fwy13 on 15/03/2017. */ public class RaceController extends Controller{ @FXML AnchorPane canvasBase; ResizableRaceCanvas raceMap; @FXML GridPane startScreen; @FXML SplitPane ongoingRacePane; @FXML CheckBox showFPS; @FXML public CheckBox showAnno; @FXML Label timer; @FXML Label FPS; @FXML TableView boatInfoTable; @FXML TableColumn boatPlacingColumn; @FXML TableColumn boatTeamColumn; @FXML TableColumn boatMarkColumn; @FXML TableColumn boatSpeedColumn; /** * Updates the ResizableRaceCanvas (raceMap) with most recent data * * @param boats boats that are to be displayed in the race * @see ResizableRaceCanvas */ public void updateMap(ObservableList boats) { BoatInRace[] boatInRaces = new BoatInRace[boats.size()]; raceMap.setBoats(boats.toArray(boatInRaces)); raceMap.drawRaceMap(); } /** * Updates the array listened by the TableView (boatInfoTable) that displays the boat information. * * @param race Race to listen to. */ public void setInfoTable(Race race) { //boatInfoTable.getItems().clear(); boatInfoTable.setItems(race.getStartingBoats()); boatTeamColumn.setCellValueFactory(cellData -> cellData.getValue().getName()); boatSpeedColumn.setCellValueFactory(cellData -> cellData.getValue().getVelocityProp()); boatMarkColumn.setCellValueFactory(cellData -> cellData.getValue().getCurrentLegName()); boatPlacingColumn.setCellValueFactory(new Callback, ObservableValue>() { @Override public ObservableValue call(TableColumn.CellDataFeatures table) { return new ReadOnlyObjectWrapper(boatInfoTable.getItems().indexOf(table.getValue()) + 1); } }); } /** * Begins the race with a scale factor of 15 */ public void startRace1Min() { startRace(15); } /** * Begins the race with a scale factor of 3 */ public void startRace5Min() { startRace(3); } /** * Begins the race with a scale factor of 1 */ public void startRaceNoScaling() { startRace(1); } @Override public void initialize(URL location, ResourceBundle resources) { } /** * Initializes and runs the race, based on the user's chosen scale factor * Currently uses an example racecourse * * @param scaleFactor */ private void startRace(int scaleFactor) { BoatInRace[] boats = generateAC35Competitors(); raceMap = new ResizableRaceCanvas(); raceMap.setMouseTransparent(true); raceMap.widthProperty().bind(canvasBase.widthProperty()); raceMap.heightProperty().bind(canvasBase.heightProperty()); raceMap.setBoats(boats); raceMap.drawRaceMap(); raceMap.setVisible(true); canvasBase.getChildren().add(raceMap); startScreen.setVisible(false); ongoingRacePane.setVisible(true); ArrayList legs = generateBermudaCourseLegs(); ConstantVelocityRace race = new ConstantVelocityRace(boats, legs, this, scaleFactor); showFPS.setVisible(true); showFPS.selectedProperty().addListener(new ChangeListener() { public void changed(ObservableValue ov, Boolean old_val, Boolean new_val) { if (showFPS.isSelected()){ FPS.setVisible(true); } else { FPS.setVisible(false); } } }); showAnno.selectedProperty().addListener(new ChangeListener() { public void changed(ObservableValue ov, Boolean old_val, Boolean new_val) { raceMap.toggleAnno(); } }); new Thread((race)).start(); } /** * Function for the Bermuda Race. * @return legs in the Bermuda Race. */ private ArrayList generateBermudaCourseLegs() { ArrayList legs = new ArrayList<>(); Leg leg1 = new Leg("Start to Mark 1", Constants.startLineMarker1, Constants.mark1, 0); Leg leg2 = new Leg("Mark 1 to Leeward Gate", Constants.mark1, Constants.leewardGate1, 1); Leg leg3 = new Leg("Leeward Gate to Windward Gate", Constants.leewardGate1, Constants.windwardGate1, 2); Leg leg4 = new Leg("Windward Gate to Leeward Gate", Constants.windwardGate1, Constants.leewardGate1, 3); Leg leg5 = new Leg("Leeward Gate to Finish", Constants.leewardGate1, Constants.finishLineMarker1, 4); legs.add(leg1); legs.add(leg2); legs.add(leg3); legs.add(leg4); legs.add(leg5); return legs; } /** * Generates an example list of competitors (Official AC35 competitors) * @return List of official AC35 competing boats */ private BoatInRace[] generateAC35Competitors() { BoatInRace[] boats = new BoatInRace[6]; int i = 0; for (BoatInRace boat : Constants.OFFICIAL_AC35_COMPETITORS) { boat.setCurrentPosition(Constants.startLineMarker1); boats[i] = boat; i++; } return boats; } public void setTimer(String time) { timer.setText(time); } public void setFrames(String fps) { FPS.setText((fps)); } }