package application.controller import application.model.* import javafx.collections.FXCollections import javafx.collections.ObservableList import javafx.fxml.FXML import javafx.fxml.Initializable import javafx.scene.control.ListCell import javafx.scene.control.ListView import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import org.charts.dataviewer.api.config.DataViewerConfiguration import org.charts.dataviewer.api.data.PlotData import org.charts.dataviewer.api.trace.ScatterTrace import org.charts.dataviewer.javafx.JavaFxDataViewer import org.charts.dataviewer.utils.TraceColour import org.charts.dataviewer.utils.TraceVisibility import java.net.URL import java.util.* class DataPanelController : Initializable, SelectedVesselListener { private var dataList: ObservableList>> = FXCollections.observableArrayList() private lateinit var timeData: ArrayList private val latitude: ArrayList = arrayListOf() private val longitude: ArrayList = arrayListOf() private val speedOverGround: ArrayList = arrayListOf() private val courseOverGround: ArrayList = arrayListOf() private val heading: ArrayList = arrayListOf() private val vesselName: ArrayList = arrayListOf() private val imo: ArrayList = arrayListOf() private val callSign: ArrayList = arrayListOf() private val vesselType: ArrayList = arrayListOf() private val status: ArrayList = arrayListOf() private val length: ArrayList = arrayListOf() private val width: ArrayList = arrayListOf() private val draft: ArrayList = arrayListOf() private val cargo: ArrayList = arrayListOf() private var selectedItem: Pair>? = null @FXML var dataListView = ListView>>() @FXML var dataViewer = JavaFxDataViewer() private val plotData = PlotData() private val config = DataViewerConfiguration() override fun initialize(location: URL?, resources: ResourceBundle?) { setObservableSelectedVesselListener() dataListView.items = dataList config.showLegend(true) config.setLegendInsidePlot(false) setObservableCurrentTimeListener() dataListView.setCellFactory { object : ListCell>?>() { override fun updateItem(item: Pair>?, empty: Boolean) { super.updateItem(item, empty) text = if (empty) { null } else { item?.first } } } } dataListView.selectionModel.selectedItemProperty().addListener { _, _, newValue -> selectedItem = newValue plot(newValue) } plotData.allTraces.clear() config.setxAxisTitle("") config.setyAxisTitle("") config.plotTitle = "" dataViewer.updateConfiguration(config) dataViewer.updatePlot(plotData) initDataList() } private fun plot() { if (selectedItem != null) { GlobalScope.launch { plot(selectedItem) } } } private fun plot(data: Pair>?) { if (data == null) { plotData.allTraces.clear() config.setxAxisTitle("") config.setyAxisTitle("") dataViewer.updateConfiguration(config) dataViewer.resetPlot() return } val getValueVisitorX = GetValueVisitor() val getValueVisitorY = GetValueVisitor() val arrayListStringX = arrayListOf() // val arrayListDoubleX = arrayListOf() val arrayListStringY = arrayListOf() val arrayListDoubleY = arrayListOf() for (x in 0 until timeData.size) { timeData[x]?.accept(getValueVisitorX) data.second[x]?.accept(getValueVisitorY) if (getValueVisitorY.value.toDoubleOrNull() == null) { arrayListStringX.add(getValueVisitorX.value) arrayListStringY.add(getValueVisitorY.value) } else { arrayListStringX.add(getValueVisitorX.value) arrayListDoubleY.add(getValueVisitorY.value.toDouble()) } } val scatterTrace = ScatterTrace() scatterTrace.traceColour = TraceColour.RED scatterTrace.traceVisibility = TraceVisibility.TRUE val serieStringX: Array = arrayListStringX.toTypedArray() // val serieDoubleX: Array = arrayListDoubleX.toTypedArray() val serieStringY: Array = arrayListStringY.toTypedArray() val serieDoubleY: Array = arrayListDoubleY.toTypedArray() if (getValueVisitorY.value.toDoubleOrNull() == null) { scatterTrace.setxArray(serieStringX) scatterTrace.setyArray(serieStringY) } else { scatterTrace.setxArray(serieStringX) scatterTrace.setyArray(serieDoubleY) } config.plotTitle = "" config.setxAxisTitle("Time (s)") config.setyAxisTitle(data.first) dataViewer.resetPlot() plotData.allTraces.clear() plotData.addTrace(scatterTrace) dataViewer.updateConfiguration(config) dataViewer.updatePlot(plotData) } private fun setObservableSelectedVesselListener() { observableSelectedVessel.listeners.add(this) } private fun populateTime(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllTimeBeforeSelectedTime() } else { vessel.getAllTime() } } private fun populateLatitude(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllLatitudeBeforeSelectedTime() } else { vessel.getAllLatitude() } } private fun populateLongitude(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllLongitudeBeforeSelectedTime() } else { vessel.getAllLongitude() } } private fun populateSpeedOverGround(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllSpeedOverGroundBeforeSelectedTime() } else { vessel.getAllSpeedOverGround() } } private fun populateCourseOverGround(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllCourseOverGroundBeforeSelectedTime() } else { vessel.getAllCourseOverGround() } } private fun populateHeading(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllHeadingBeforeSelectedTime() } else { vessel.getAllHeading() } } private fun populateVesselName(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllVesselNameBeforeSelectedTime() } else { vessel.getAllVesselName() } } private fun populateIMO(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllIMOBeforeSelectedTime() } else { vessel.getAllIMO() } } private fun populateCallSign(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllCallSignBeforeSelectedTime() } else { vessel.getAllCallSign() } } private fun populateVesselType(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllVesselTypeBeforeSelectedTime() } else { vessel.getAllVesselType() } } private fun populateStatus(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllStatusBeforeSelectedTime() } else { vessel.getAllStatus() } } private fun populateLength(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllLengthBeforeSelectedTime() } else { vessel.getAllLength() } } private fun populateWidth(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllWidthBeforeSelectedTime() } else { vessel.getAllWidth() } } private fun populateDraft(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllDraftBeforeSelectedTime() } else { vessel.getAllDraft() } } private fun populateCargo(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllCargoBeforeSelectedTime() } else { vessel.getAllCargo() } } private fun initDataList() { val data = arrayListOf>>() data.add(Pair("Latitude", latitude)) data.add(Pair("Longitude", longitude)) data.add(Pair("Speed Over Ground", speedOverGround)) data.add(Pair("Course Over Ground", courseOverGround)) data.add(Pair("Heading", heading)) data.add(Pair("Vessel Name", vesselName)) data.add(Pair("IMO", imo)) data.add(Pair("Call Sign", callSign)) data.add(Pair("Vessel Type", vesselType)) data.add(Pair("Status", status)) data.add(Pair("Length", length)) data.add(Pair("Width", width)) data.add(Pair("Draft", draft)) data.add(Pair("Cargo", cargo)) dataList.addAll(data) } private fun updateDataList(vessel: Vessel) { timeData = populateTime(vessel) latitude.clear() latitude.addAll(populateLatitude(vessel)) longitude.clear() longitude.addAll(populateLongitude(vessel)) speedOverGround.clear() speedOverGround.addAll(populateSpeedOverGround(vessel)) courseOverGround.clear() courseOverGround.addAll(populateCourseOverGround(vessel)) heading.clear() heading.addAll(populateHeading(vessel)) vesselName.clear() vesselName.addAll(populateVesselName(vessel)) imo.clear() imo.addAll(populateIMO(vessel)) callSign.clear() callSign.addAll(populateCallSign(vessel)) vesselType.clear() vesselType.addAll(populateVesselType(vessel)) status.clear() status.addAll(populateStatus(vessel)) length.clear() length.addAll(populateLength(vessel)) width.clear() width.addAll(populateWidth(vessel)) draft.clear() draft.addAll(populateDraft(vessel)) cargo.clear() cargo.addAll(populateCargo(vessel)) } private fun setObservableCurrentTimeListener() { observableCurrentTime.listeners.add(object : CurrentTime { override fun onValueChanged(newValue: Int) { updateDataList(observableSelectedVessel.value) plot() } }) } override fun onValueChanged(newValue: Vessel) { updateDataList(newValue) plot() } }