Commit e220e082b538d95eae8e1c1c23879c90ff0bcde6

Authored by lsagona
1 parent dd1ce7fe83
Exists in master and in 1 other branch dev

graph binded to slider

removed useless start and stop button

Showing 8 changed files with 385 additions and 161 deletions Side-by-side Diff

build.gradle View file @ e220e08
... ... @@ -17,6 +17,7 @@
17 17 implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
18 18 implementation 'org.jfxtras:jmetro:8.6.9'
19 19 implementation 'org.slf4j:slf4j-api:1.7.30'
  20 + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9"
20 21 testCompile group: 'junit', name: 'junit', version: '4.12'
21 22 testCompile group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3'
22 23 compile group: 'ch.qos.logback', name: 'logback-core', version: '1.2.3'
src/main/kotlin/application/App.kt View file @ e220e08
... ... @@ -29,6 +29,7 @@
29 29 }
30 30  
31 31 private fun closeApplication() {
  32 +
32 33 Platform.exit()
33 34 exitProcess(0)
34 35 }
src/main/kotlin/application/controller/DataPanelController.kt View file @ e220e08
... ... @@ -7,6 +7,8 @@
7 7 import javafx.fxml.Initializable
8 8 import javafx.scene.control.ListCell
9 9 import javafx.scene.control.ListView
  10 +import kotlinx.coroutines.GlobalScope
  11 +import kotlinx.coroutines.launch
10 12 import org.charts.dataviewer.api.config.DataViewerConfiguration
11 13 import org.charts.dataviewer.api.data.PlotData
12 14 import org.charts.dataviewer.api.trace.ScatterTrace
13 15  
14 16  
15 17  
16 18  
... ... @@ -21,24 +23,43 @@
21 23 private var dataList: ObservableList<Pair<String, ArrayList<MessageData?>>> = FXCollections.observableArrayList()
22 24 private lateinit var timeData: ArrayList<MessageData?>
23 25  
  26 + private val latitude: ArrayList<MessageData?> = arrayListOf()
  27 + private val longitude: ArrayList<MessageData?> = arrayListOf()
  28 + private val speedOverGround: ArrayList<MessageData?> = arrayListOf()
  29 + private val courseOverGround: ArrayList<MessageData?> = arrayListOf()
  30 + private val heading: ArrayList<MessageData?> = arrayListOf()
  31 + private val vesselName: ArrayList<MessageData?> = arrayListOf()
  32 + private val imo: ArrayList<MessageData?> = arrayListOf()
  33 + private val callSign: ArrayList<MessageData?> = arrayListOf()
  34 + private val vesselType: ArrayList<MessageData?> = arrayListOf()
  35 + private val status: ArrayList<MessageData?> = arrayListOf()
  36 + private val length: ArrayList<MessageData?> = arrayListOf()
  37 + private val width: ArrayList<MessageData?> = arrayListOf()
  38 + private val draft: ArrayList<MessageData?> = arrayListOf()
  39 + private val cargo: ArrayList<MessageData?> = arrayListOf()
24 40  
  41 + private var selectedItem: Pair<String, ArrayList<MessageData?>>? = null
  42 +
25 43 @FXML
26 44 var dataListView = ListView<Pair<String, ArrayList<MessageData?>>>()
27 45  
28 46 @FXML
29 47 var dataViewer = JavaFxDataViewer()
30 48  
  49 + private val plotData = PlotData()
  50 + private val config = DataViewerConfiguration()
31 51  
32 52 override fun initialize(location: URL?, resources: ResourceBundle?) {
33 53 setObservableSelectedVesselListener()
34 54 dataListView.items = dataList
35 55  
36 56  
37   - val plotData = PlotData()
38   - val config = DataViewerConfiguration()
  57 +
39 58 config.showLegend(true)
40 59 config.setLegendInsidePlot(false)
41 60  
  61 + setObservableCurrentTimeListener()
  62 +
42 63 dataListView.setCellFactory {
43 64 object : ListCell<Pair<String, ArrayList<MessageData?>>?>() {
44 65 override fun updateItem(item: Pair<String, ArrayList<MessageData?>>?, empty: Boolean) {
45 66  
46 67  
47 68  
48 69  
49 70  
50 71  
51 72  
52 73  
53 74  
54 75  
55 76  
56 77  
57 78  
58 79  
59 80  
60 81  
61 82  
62 83  
63 84  
64 85  
65 86  
66 87  
67 88  
68 89  
69 90  
70 91  
71 92  
72 93  
73 94  
74 95  
75 96  
76 97  
77 98  
78 99  
79 100  
80 101  
81 102  
82 103  
83 104  
84 105  
85 106  
86 107  
87 108  
88 109  
89 110  
90 111  
91 112  
92 113  
93 114  
94 115  
95 116  
96 117  
... ... @@ -53,224 +74,296 @@
53 74 }
54 75  
55 76 dataListView.selectionModel.selectedItemProperty().addListener { _, _, newValue ->
56   - if (newValue == null) {
57   - plotData.allTraces.clear()
58   - config.setxAxisTitle("")
59   - config.setyAxisTitle("")
60   - dataViewer.updateConfiguration(config)
  77 + selectedItem = newValue
  78 + plot(newValue)
  79 + }
61 80  
62   - dataViewer.resetPlot()
  81 + plotData.allTraces.clear()
  82 + config.setxAxisTitle("")
  83 + config.setyAxisTitle("")
  84 + config.plotTitle = ""
  85 + dataViewer.updateConfiguration(config)
  86 + dataViewer.updatePlot(plotData)
  87 + initDataList()
63 88  
64   - return@addListener
  89 +
  90 + }
  91 +
  92 + private fun plot() {
  93 + if (selectedItem != null) {
  94 + GlobalScope.launch {
  95 + plot(selectedItem)
65 96 }
  97 + }
  98 + }
66 99  
67   - val getValueVisitorX = GetValueVisitor()
68   - val getValueVisitorY = GetValueVisitor()
  100 + private fun plot(data: Pair<String, ArrayList<MessageData?>>?) {
  101 + if (data == null) {
  102 + plotData.allTraces.clear()
  103 + config.setxAxisTitle("")
  104 + config.setyAxisTitle("")
  105 + dataViewer.updateConfiguration(config)
69 106  
70   - val arrayListStringX = arrayListOf<String>()
71   - val arrayListDoubleX = arrayListOf<Double>()
72   - val arrayListStringY = arrayListOf<String>()
73   - val arrayListDoubleY = arrayListOf<Double>()
  107 + dataViewer.resetPlot()
74 108  
75   - for (x in 0 until newValue.second.size) {
76   - timeData[x]?.accept(getValueVisitorX)
77   - newValue.second[x]?.accept(getValueVisitorY)
  109 + return
  110 + }
78 111  
79   - if (getValueVisitorY.value.toDoubleOrNull() == null) {
80   - arrayListStringX.add(getValueVisitorX.value)
81   - arrayListStringY.add(getValueVisitorY.value)
82   - } else {
83   - arrayListStringX.add(getValueVisitorX.value)
84   - arrayListDoubleY.add(getValueVisitorY.value.toDouble())
85   - }
86   - }
  112 + val getValueVisitorX = GetValueVisitor()
  113 + val getValueVisitorY = GetValueVisitor()
87 114  
88   - val scatterTrace = ScatterTrace<Any>()
89   - scatterTrace.traceColour = TraceColour.RED
90   - scatterTrace.traceVisibility = TraceVisibility.TRUE
  115 + val arrayListStringX = arrayListOf<String>()
  116 +// val arrayListDoubleX = arrayListOf<Double>()
  117 + val arrayListStringY = arrayListOf<String>()
  118 + val arrayListDoubleY = arrayListOf<Double>()
91 119  
92   - val serieStringX: Array<String> = arrayListStringX.toTypedArray()
93   -// val serieDoubleX: Array<Double> = arrayListDoubleX.toTypedArray()
94   - val serieStringY: Array<String> = arrayListStringY.toTypedArray()
95   - val serieDoubleY: Array<Double> = arrayListDoubleY.toTypedArray()
  120 + for (x in 0 until timeData.size) {
  121 + timeData[x]?.accept(getValueVisitorX)
  122 + data.second[x]?.accept(getValueVisitorY)
96 123  
97 124 if (getValueVisitorY.value.toDoubleOrNull() == null) {
98   - scatterTrace.setxArray(serieStringX)
99   - scatterTrace.setyArray(serieStringY)
  125 + arrayListStringX.add(getValueVisitorX.value)
  126 + arrayListStringY.add(getValueVisitorY.value)
100 127 } else {
101   - scatterTrace.setxArray(serieStringX)
102   - scatterTrace.setyArray(serieDoubleY)
  128 + arrayListStringX.add(getValueVisitorX.value)
  129 + arrayListDoubleY.add(getValueVisitorY.value.toDouble())
103 130 }
  131 + }
104 132  
105   - config.plotTitle = ""
106   - config.setxAxisTitle("Time (s)")
107   - config.setyAxisTitle(newValue.first)
108   - dataViewer.resetPlot()
109   - plotData.allTraces.clear()
110   - plotData.addTrace(scatterTrace)
111   - dataViewer.updateConfiguration(config)
112   - dataViewer.updatePlot(plotData)
  133 + val scatterTrace = ScatterTrace<Any>()
  134 + scatterTrace.traceColour = TraceColour.RED
  135 + scatterTrace.traceVisibility = TraceVisibility.TRUE
113 136  
  137 + val serieStringX: Array<String> = arrayListStringX.toTypedArray()
  138 +// val serieDoubleX: Array<Double> = arrayListDoubleX.toTypedArray()
  139 + val serieStringY: Array<String> = arrayListStringY.toTypedArray()
  140 + val serieDoubleY: Array<Double> = arrayListDoubleY.toTypedArray()
  141 +
  142 + if (getValueVisitorY.value.toDoubleOrNull() == null) {
  143 + scatterTrace.setxArray(serieStringX)
  144 + scatterTrace.setyArray(serieStringY)
  145 + } else {
  146 + scatterTrace.setxArray(serieStringX)
  147 + scatterTrace.setyArray(serieDoubleY)
114 148 }
115 149  
116   - plotData.allTraces.clear()
117   - config.setxAxisTitle("")
118   - config.setyAxisTitle("")
119 150 config.plotTitle = ""
  151 + config.setxAxisTitle("Time (s)")
  152 + config.setyAxisTitle(data.first)
  153 + dataViewer.resetPlot()
  154 + plotData.allTraces.clear()
  155 + plotData.addTrace(scatterTrace)
120 156 dataViewer.updateConfiguration(config)
121 157 dataViewer.updatePlot(plotData)
122 158  
123 159 }
124 160  
  161 +
125 162 private fun setObservableSelectedVesselListener() {
126 163 observableSelectedVessel.listeners.add(this)
127 164 }
128 165  
129 166 private fun populateTime(vessel: Vessel): ArrayList<MessageData?> {
130   - val allTime: ArrayList<MessageData?> = vessel.getAllTime()
131   - allTime.sortBy { (it as Time).value }
132   -
133   - return allTime
  167 + return if (observableIsReplayState.value) {
  168 + vessel.getAllTimeBeforeSelectedTime()
  169 + } else {
  170 + vessel.getAllTime()
  171 + }
134 172 }
135 173  
136   - private fun populateLatitude(vessel: Vessel): ArrayList<MessageData?> {
137   - val allLatitude: ArrayList<MessageData?> = vessel.getAllLatitude()
138   - allLatitude.sortBy { (it as Latitude).value }
139 174  
140   - return allLatitude
  175 + private fun populateLatitude(vessel: Vessel): ArrayList<MessageData?> {
  176 + return if (observableIsReplayState.value) {
  177 + vessel.getAllLatitudeBeforeSelectedTime()
  178 + } else {
  179 + vessel.getAllLatitude()
  180 + }
141 181 }
142 182  
143 183 private fun populateLongitude(vessel: Vessel): ArrayList<MessageData?> {
144   - val allLongitude: ArrayList<MessageData?> = vessel.getAllLongitude()
145   - allLongitude.sortBy { (it as Longitude).value }
146   -
147   - return allLongitude
  184 + return if (observableIsReplayState.value) {
  185 + vessel.getAllLongitudeBeforeSelectedTime()
  186 + } else {
  187 + vessel.getAllLongitude()
  188 + }
148 189 }
149 190  
150 191 private fun populateSpeedOverGround(vessel: Vessel): ArrayList<MessageData?> {
151   - val allSpeedOverGround: ArrayList<MessageData?> = vessel.getAllSpeedOverGround()
152   - allSpeedOverGround.sortBy { (it as SpeedOverGround).value }
153   -
154   - return allSpeedOverGround
  192 + return if (observableIsReplayState.value) {
  193 + vessel.getAllSpeedOverGroundBeforeSelectedTime()
  194 + } else {
  195 + vessel.getAllSpeedOverGround()
  196 + }
155 197 }
156 198  
157 199 private fun populateCourseOverGround(vessel: Vessel): ArrayList<MessageData?> {
158   - val allCourseOverGround: ArrayList<MessageData?> = vessel.getAllCourseOverGround()
159   - allCourseOverGround.sortBy { (it as CourseOverGround).value }
160   -
161   - return allCourseOverGround
  200 + return if (observableIsReplayState.value) {
  201 + vessel.getAllCourseOverGroundBeforeSelectedTime()
  202 + } else {
  203 + vessel.getAllCourseOverGround()
  204 + }
162 205 }
163 206  
164 207 private fun populateHeading(vessel: Vessel): ArrayList<MessageData?> {
165   - val allHeading: ArrayList<MessageData?> = vessel.getAllHeading()
166   - allHeading.sortBy { (it as Heading).value }
167   -
168   - return allHeading
  208 + return if (observableIsReplayState.value) {
  209 + vessel.getAllHeadingBeforeSelectedTime()
  210 + } else {
  211 + vessel.getAllHeading()
  212 + }
169 213 }
170 214  
171 215 private fun populateVesselName(vessel: Vessel): ArrayList<MessageData?> {
172   - val allVesselName: ArrayList<MessageData?> = vessel.getAllVesselName()
173   - allVesselName.sortBy { (it as VesselName).value }
174   -
175   - return allVesselName
  216 + return if (observableIsReplayState.value) {
  217 + vessel.getAllVesselNameBeforeSelectedTime()
  218 + } else {
  219 + vessel.getAllVesselName()
  220 + }
176 221 }
177 222  
178 223 private fun populateIMO(vessel: Vessel): ArrayList<MessageData?> {
179   - val allIMO: ArrayList<MessageData?> = vessel.getAllIMO()
180   - allIMO.sortBy { (it as IMO).value }
181   -
182   - return allIMO
  224 + return if (observableIsReplayState.value) {
  225 + vessel.getAllIMOBeforeSelectedTime()
  226 + } else {
  227 + vessel.getAllIMO()
  228 + }
183 229 }
184 230  
185 231 private fun populateCallSign(vessel: Vessel): ArrayList<MessageData?> {
186   - val allCallSign: ArrayList<MessageData?> = vessel.getAllCallSign()
187   - allCallSign.sortBy { (it as CallSign).value }
188   -
189   - return allCallSign
  232 + return if (observableIsReplayState.value) {
  233 + vessel.getAllCallSignBeforeSelectedTime()
  234 + } else {
  235 + vessel.getAllCallSign()
  236 + }
190 237 }
191 238  
192 239 private fun populateVesselType(vessel: Vessel): ArrayList<MessageData?> {
193   - val allVesselType: ArrayList<MessageData?> = vessel.getAllVesselType()
194   - allVesselType.sortBy { (it as VesselType).value }
195   -
196   - return allVesselType
  240 + return if (observableIsReplayState.value) {
  241 + vessel.getAllVesselTypeBeforeSelectedTime()
  242 + } else {
  243 + vessel.getAllVesselType()
  244 + }
197 245 }
198 246  
199 247 private fun populateStatus(vessel: Vessel): ArrayList<MessageData?> {
200   - val allStatus: ArrayList<MessageData?> = vessel.getAllStatus()
201   - allStatus.sortBy { (it as Status).value }
202   -
203   - return allStatus
  248 + return if (observableIsReplayState.value) {
  249 + vessel.getAllStatusBeforeSelectedTime()
  250 + } else {
  251 + vessel.getAllStatus()
  252 + }
204 253 }
205 254  
206 255 private fun populateLength(vessel: Vessel): ArrayList<MessageData?> {
207   - val allLength: ArrayList<MessageData?> = vessel.getAllLength()
208   - allLength.sortBy { (it as Length).value }
209   -
210   - return allLength
  256 + return if (observableIsReplayState.value) {
  257 + vessel.getAllLengthBeforeSelectedTime()
  258 + } else {
  259 + vessel.getAllLength()
  260 + }
211 261 }
212 262  
213 263 private fun populateWidth(vessel: Vessel): ArrayList<MessageData?> {
214   - val allWidth: ArrayList<MessageData?> = vessel.getAllWidth()
215   - allWidth.sortBy { (it as Width).value }
216   -
217   - return allWidth
  264 + return if (observableIsReplayState.value) {
  265 + vessel.getAllWidthBeforeSelectedTime()
  266 + } else {
  267 + vessel.getAllWidth()
  268 + }
218 269 }
219 270  
220 271 private fun populateDraft(vessel: Vessel): ArrayList<MessageData?> {
221   - val allDraft: ArrayList<MessageData?> = vessel.getAllDraft()
222   - allDraft.sortBy { (it as Draft).value }
223   -
224   - return allDraft
  272 + return if (observableIsReplayState.value) {
  273 + vessel.getAllDraftBeforeSelectedTime()
  274 + } else {
  275 + vessel.getAllDraft()
  276 + }
225 277 }
226 278  
227 279 private fun populateCargo(vessel: Vessel): ArrayList<MessageData?> {
228   - val allCargo: ArrayList<MessageData?> = vessel.getAllCargo()
229   - allCargo.sortBy { (it as Cargo).value }
230   -
231   - return allCargo
  280 + return if (observableIsReplayState.value) {
  281 + vessel.getAllCargoBeforeSelectedTime()
  282 + } else {
  283 + vessel.getAllCargo()
  284 + }
232 285 }
233 286  
234   - private fun populateDataList(vessel: Vessel) {
  287 + private fun initDataList() {
235 288 val data = arrayListOf<Pair<String, ArrayList<MessageData?>>>()
236 289  
  290 + data.add(Pair("Latitude", latitude))
  291 + data.add(Pair("Longitude", longitude))
  292 + data.add(Pair("Speed Over Ground", speedOverGround))
  293 + data.add(Pair("Course Over Ground", courseOverGround))
  294 + data.add(Pair("Heading", heading))
  295 + data.add(Pair("Vessel Name", vesselName))
  296 + data.add(Pair("IMO", imo))
  297 + data.add(Pair("Call Sign", callSign))
  298 + data.add(Pair("Vessel Type", vesselType))
  299 + data.add(Pair("Status", status))
  300 + data.add(Pair("Length", length))
  301 + data.add(Pair("Width", width))
  302 + data.add(Pair("Draft", draft))
  303 + data.add(Pair("Cargo", cargo))
  304 +
  305 + dataList.addAll(data)
  306 + }
  307 +
  308 + private fun updateDataList(vessel: Vessel) {
237 309 timeData = populateTime(vessel)
238 310  
239   - data.add(Pair("Latitude", populateLatitude(vessel)))
  311 + latitude.clear()
  312 + latitude.addAll(populateLatitude(vessel))
240 313  
241   - data.add(Pair("Longitude", populateLongitude(vessel)))
  314 + longitude.clear()
  315 + longitude.addAll(populateLongitude(vessel))
242 316  
243   - data.add(Pair("Speed Over Ground", populateSpeedOverGround(vessel)))
  317 + speedOverGround.clear()
  318 + speedOverGround.addAll(populateSpeedOverGround(vessel))
244 319  
245   - data.add(Pair("Course Over Ground", populateCourseOverGround(vessel)))
  320 + courseOverGround.clear()
  321 + courseOverGround.addAll(populateCourseOverGround(vessel))
246 322  
247   - data.add(Pair("Heading", populateHeading(vessel)))
  323 + heading.clear()
  324 + heading.addAll(populateHeading(vessel))
248 325  
249   - data.add(Pair("Vessel Name", populateVesselName(vessel)))
  326 + vesselName.clear()
  327 + vesselName.addAll(populateVesselName(vessel))
250 328  
251   - data.add(Pair("IMO", populateIMO(vessel)))
  329 + imo.clear()
  330 + imo.addAll(populateIMO(vessel))
252 331  
253   - data.add(Pair("Call Sign", populateCallSign(vessel)))
  332 + callSign.clear()
  333 + callSign.addAll(populateCallSign(vessel))
254 334  
255   - data.add(Pair("Vessel Type", populateVesselType(vessel)))
  335 + vesselType.clear()
  336 + vesselType.addAll(populateVesselType(vessel))
256 337  
257   - data.add(Pair("Status", populateStatus(vessel)))
  338 + status.clear()
  339 + status.addAll(populateStatus(vessel))
258 340  
259   - data.add(Pair("Length", populateLength(vessel)))
  341 + length.clear()
  342 + length.addAll(populateLength(vessel))
260 343  
261   - data.add(Pair("Width", populateWidth(vessel)))
  344 + width.clear()
  345 + width.addAll(populateWidth(vessel))
262 346  
263   - data.add(Pair("Draft", populateDraft(vessel)))
  347 + draft.clear()
  348 + draft.addAll(populateDraft(vessel))
264 349  
265   - data.add(Pair("Cargo", populateCargo(vessel)))
  350 + cargo.clear()
  351 + cargo.addAll(populateCargo(vessel))
266 352  
267   - dataList.addAll(data)
268 353 }
269 354  
270   - override fun onValueChanged(newValue: Vessel) {
271   - dataList.clear()
272   - populateDataList(newValue)
  355 + private fun setObservableCurrentTimeListener() {
  356 + observableCurrentTime.listeners.add(object : CurrentTime {
  357 + override fun onValueChanged(newValue: Int) {
  358 + updateDataList(observableSelectedVessel.value)
  359 + plot()
  360 + }
  361 + })
  362 + }
273 363  
  364 + override fun onValueChanged(newValue: Vessel) {
  365 + updateDataList(newValue)
  366 + plot()
274 367 }
275 368  
276 369 }
src/main/kotlin/application/controller/MapPanelController.kt View file @ e220e08
... ... @@ -2,6 +2,7 @@
2 2  
3 3 import application.model.*
4 4 import application.model.MapState.*
  5 +import javafx.application.Platform
5 6 import javafx.fxml.FXML
6 7 import javafx.fxml.Initializable
7 8 import javafx.scene.layout.StackPane
8 9  
9 10  
10 11  
... ... @@ -53,34 +54,38 @@
53 54 }
54 55  
55 56 private fun updateMap() {
56   - if (observableIsReplayState.value) {
57   - when (observableMapState.state) {
58   - ALL_MESSAGES -> displayTimedAllMessageOnMap(mapView)
59   - CLUSTERED_MESSAGES -> displayTimedClusterMessageOnMap(mapView)
60   - HEAT_MAP -> displayTimedHeatMapOnMap(mapView)
  57 + Platform.runLater {
  58 + if (observableIsReplayState.value) {
  59 + when (observableMapState.state) {
  60 + ALL_MESSAGES -> displayTimedAllMessageOnMap(mapView)
  61 + CLUSTERED_MESSAGES -> displayTimedClusterMessageOnMap(mapView)
  62 + HEAT_MAP -> displayTimedHeatMapOnMap(mapView)
  63 + }
  64 + } else {
  65 + when (observableMapState.state) {
  66 + ALL_MESSAGES -> displayAllMessageOnMap(mapView)
  67 + CLUSTERED_MESSAGES -> displayClusterMessageOnMap(mapView)
  68 + HEAT_MAP -> displayHeatMapOnMap(mapView)
  69 + }
61 70 }
62   - } else {
63   - when (observableMapState.state) {
64   - ALL_MESSAGES -> displayAllMessageOnMap(mapView)
65   - CLUSTERED_MESSAGES -> displayClusterMessageOnMap(mapView)
66   - HEAT_MAP -> displayHeatMapOnMap(mapView)
67   - }
68 71 }
69 72 }
70 73  
71 74 private fun updateMap(selectedMMSI: String) {
72   - if (observableIsReplayState.value) {
73   - when (observableMapState.state) {
74   - ALL_MESSAGES -> displayTimedAllMessageOnMap(mapView, selectedMMSI)
75   - CLUSTERED_MESSAGES -> displayTimedClusterMessageOnMap(mapView, selectedMMSI)
76   - HEAT_MAP -> displayTimedHeatMapOnMap(mapView, selectedMMSI)
  75 + Platform.runLater {
  76 + if (observableIsReplayState.value) {
  77 + when (observableMapState.state) {
  78 + ALL_MESSAGES -> displayTimedAllMessageOnMap(mapView, selectedMMSI)
  79 + CLUSTERED_MESSAGES -> displayTimedClusterMessageOnMap(mapView, selectedMMSI)
  80 + HEAT_MAP -> displayTimedHeatMapOnMap(mapView, selectedMMSI)
  81 + }
  82 + } else {
  83 + when (observableMapState.state) {
  84 + ALL_MESSAGES -> displayAllMessageOnMap(mapView, selectedMMSI)
  85 + CLUSTERED_MESSAGES -> displayClusterMessageOnMap(mapView, selectedMMSI)
  86 + HEAT_MAP -> displayHeatMapOnMap(mapView, selectedMMSI)
  87 + }
77 88 }
78   - } else {
79   - when (observableMapState.state) {
80   - ALL_MESSAGES -> displayAllMessageOnMap(mapView, selectedMMSI)
81   - CLUSTERED_MESSAGES -> displayClusterMessageOnMap(mapView, selectedMMSI)
82   - HEAT_MAP -> displayHeatMapOnMap(mapView, selectedMMSI)
83   - }
84 89 }
85 90 }
86 91  
... ... @@ -93,7 +98,7 @@
93 98 }
94 99  
95 100 private fun setObservableIsReplayState() {
96   - observableIsReplayState.listeners.add(object: ReplayState {
  101 + observableIsReplayState.listeners.add(object : ReplayState {
97 102 override fun onValueChanged(newValue: Boolean) {
98 103 if (observableSelectedVessel.value.mmsi != null) {
99 104 updateMap(observableSelectedVessel.value.mmsi!!)
src/main/kotlin/application/controller/TimePanel.kt View file @ e220e08
... ... @@ -61,8 +61,10 @@
61 61 observableIsReplayState.listeners.add(object : ReplayState {
62 62 override fun onValueChanged(newValue: Boolean) {
63 63 if (observableIsReplayState.value) {
  64 + observableCurrentTime.value = timeSlider.value.toInt()
64 65 unableAllButton()
65 66 } else {
  67 + observableCurrentTime.value = Int.MAX_VALUE
66 68 disableAllButton()
67 69 }
68 70 }
src/main/kotlin/application/model/ObservableCurrentTime.kt View file @ e220e08
... ... @@ -7,7 +7,7 @@
7 7 val listeners: MutableList<CurrentTime> = mutableListOf()
8 8  
9 9 var value: Int by Delegates.observable(
10   - initialValue = 0,
  10 + initialValue = Int.MAX_VALUE,
11 11 onChange = { _, _, new ->
12 12 run {
13 13 listeners.forEach {
src/main/kotlin/application/model/Vessel.kt View file @ e220e08
... ... @@ -2,15 +2,145 @@
2 2  
3 3 import java.util.*
4 4  
5   -
6 5 class Vessel(val mmsi: String?) {
7 6 val messages: SortedMap<Long, Message> = sortedMapOf()
  7 + private val messageBeforeSelectedTime: Map<Long, Message>
  8 + get() {
  9 + return messages.filter { observableCurrentTime.value > it.key }
  10 + }
  11 +
8 12 var messageToDisplay: Message? = null
9 13 get() {
10 14 field =
11 15 messages.asSequence().map { it }.firstOrNull { observableCurrentTime.value < it.key }.let { it?.value }
12 16 return field
13 17 }
  18 +
  19 + fun getAllTimeBeforeSelectedTime(): ArrayList<MessageData?> {
  20 + val timeList = arrayListOf<MessageData?>()
  21 + messageBeforeSelectedTime.forEach {
  22 + timeList.add(it.value.time)
  23 + }
  24 +
  25 + return timeList
  26 + }
  27 +
  28 + fun getAllLatitudeBeforeSelectedTime(): ArrayList<MessageData?> {
  29 + val latitudeList = arrayListOf<MessageData?>()
  30 + messageBeforeSelectedTime.forEach {
  31 + latitudeList.add(it.value.latitude)
  32 + }
  33 +
  34 + return latitudeList
  35 + }
  36 +
  37 + fun getAllLongitudeBeforeSelectedTime(): ArrayList<MessageData?> {
  38 + val longitudeList = arrayListOf<MessageData?>()
  39 + messageBeforeSelectedTime.forEach {
  40 + longitudeList.add(it.value.longitude)
  41 + }
  42 +
  43 + return longitudeList
  44 + }
  45 +
  46 + fun getAllSpeedOverGroundBeforeSelectedTime(): ArrayList<MessageData?> {
  47 + val speedOverGroundList = arrayListOf<MessageData?>()
  48 + messageBeforeSelectedTime.forEach {
  49 + speedOverGroundList.add(it.value.speedOverGround)
  50 + }
  51 +
  52 + return speedOverGroundList
  53 + }
  54 +
  55 + fun getAllCourseOverGroundBeforeSelectedTime(): ArrayList<MessageData?> {
  56 + val res = arrayListOf<MessageData?>()
  57 + messageBeforeSelectedTime.forEach {
  58 + res.add(it.value.courseOverGround)
  59 + }
  60 +
  61 + return res
  62 + }
  63 +
  64 + fun getAllHeadingBeforeSelectedTime(): ArrayList<MessageData?> {
  65 + val res = arrayListOf<MessageData?>()
  66 + messageBeforeSelectedTime.forEach {
  67 + res.add(it.value.heading)
  68 + }
  69 +
  70 + return res
  71 + }
  72 +
  73 + fun getAllVesselNameBeforeSelectedTime(): ArrayList<MessageData?> {
  74 + val res = arrayListOf<MessageData?>()
  75 + messageBeforeSelectedTime.forEach {
  76 + res.add(it.value.vesselName)
  77 + }
  78 + return res
  79 + }
  80 +
  81 + fun getAllIMOBeforeSelectedTime(): ArrayList<MessageData?> {
  82 + val res = arrayListOf<MessageData?>()
  83 + messageBeforeSelectedTime.forEach {
  84 + res.add(it.value.imo)
  85 + }
  86 + return res
  87 + }
  88 +
  89 + fun getAllCallSignBeforeSelectedTime(): ArrayList<MessageData?> {
  90 + val res = arrayListOf<MessageData?>()
  91 + messageBeforeSelectedTime.forEach {
  92 + res.add(it.value.callSign)
  93 + }
  94 + return res
  95 + }
  96 +
  97 + fun getAllVesselTypeBeforeSelectedTime(): ArrayList<MessageData?> {
  98 + val res = arrayListOf<MessageData?>()
  99 + messageBeforeSelectedTime.forEach {
  100 + res.add(it.value.vesselType)
  101 + }
  102 + return res
  103 + }
  104 +
  105 + fun getAllStatusBeforeSelectedTime(): ArrayList<MessageData?> {
  106 + val res = arrayListOf<MessageData?>()
  107 + messageBeforeSelectedTime.forEach {
  108 + res.add(it.value.status)
  109 + }
  110 + return res
  111 + }
  112 +
  113 + fun getAllLengthBeforeSelectedTime(): ArrayList<MessageData?> {
  114 + val res = arrayListOf<MessageData?>()
  115 + messageBeforeSelectedTime.forEach {
  116 + res.add(it.value.length)
  117 + }
  118 + return res
  119 + }
  120 +
  121 + fun getAllWidthBeforeSelectedTime(): ArrayList<MessageData?> {
  122 + val res = arrayListOf<MessageData?>()
  123 + messageBeforeSelectedTime.forEach {
  124 + res.add(it.value.width)
  125 + }
  126 + return res
  127 + }
  128 +
  129 + fun getAllDraftBeforeSelectedTime(): ArrayList<MessageData?> {
  130 + val res = arrayListOf<MessageData?>()
  131 + messageBeforeSelectedTime.forEach {
  132 + res.add(it.value.draft)
  133 + }
  134 + return res
  135 + }
  136 +
  137 + fun getAllCargoBeforeSelectedTime(): ArrayList<MessageData?> {
  138 + val res = arrayListOf<MessageData?>()
  139 + messageBeforeSelectedTime.forEach {
  140 + res.add(it.value.cargo)
  141 + }
  142 + return res
  143 + }
14 144  
15 145 fun getAllTime(): ArrayList<MessageData?> {
16 146 val timeList = arrayListOf<MessageData?>()
src/main/resources/gui/timePanel.fxml View file @ e220e08
... ... @@ -6,15 +6,7 @@
6 6  
7 7 <HBox alignment="CENTER" prefHeight="65.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller.TimePanel">
8 8 <children>
9   - <Button fx:id="timePlay" alignment="CENTER" mnemonicParsing="false" text="Play">
10   - <HBox.margin>
11   - <Insets left="5.0" right="5.0" />
12   - </HBox.margin></Button>
13   - <Button fx:id="timeStop" mnemonicParsing="false" text="Stop">
14   - <HBox.margin>
15   - <Insets left="5.0" right="5.0" />
16   - </HBox.margin></Button>
17   - <Slider fx:id="timeSlider" prefHeight="14.0" prefWidth="475.0">
  9 + <Slider fx:id="timeSlider" prefHeight="14.0" prefWidth="538.0">
18 10 <HBox.margin>
19 11 <Insets left="5.0" right="5.0" />
20 12 </HBox.margin></Slider>