From 4d3930db89aca57fc07f8522aa3062dde2b871f4 Mon Sep 17 00:00:00 2001 From: Arty Bishop Date: Tue, 10 Dec 2019 09:46:06 +0000 Subject: [PATCH] Implemented satellite selection save and load between app launches. Some code move and cleanup. --- .../com/rtbishop/lookingsat/MainViewModel.kt | 120 +++++++++++------- .../com/rtbishop/lookingsat/ui/SkyFragment.kt | 42 +++--- app/src/main/res/values/strings.xml | 3 +- 3 files changed, 88 insertions(+), 77 deletions(-) diff --git a/app/src/main/java/com/rtbishop/lookingsat/MainViewModel.kt b/app/src/main/java/com/rtbishop/lookingsat/MainViewModel.kt index a0344475..a8bca96f 100644 --- a/app/src/main/java/com/rtbishop/lookingsat/MainViewModel.kt +++ b/app/src/main/java/com/rtbishop/lookingsat/MainViewModel.kt @@ -27,7 +27,6 @@ import java.io.ObjectOutputStream import java.util.* import javax.inject.Inject -@Suppress("UNCHECKED_CAST") class MainViewModel(application: Application) : AndroidViewModel(application) { private val defValueLoc = application.getString(R.string.def_gsp_loc) @@ -38,7 +37,8 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { private val keyAlt = application.getString(R.string.key_alt) private val keyHours = application.getString(R.string.key_hours_ahead) private val keyMinEl = application.getString(R.string.key_min_el) - private val tleFileName = application.getString(R.string.tle_file_name) + private val tleMainListFileName = application.getString(R.string.tle_main_list_file_name) + private val tleSelectionFileName = application.getString(R.string.tle_selection_file_name) private val app = application @Inject @@ -52,6 +52,10 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { (app as LookingSatApp).appComponent.inject(this) } + private var passPrefs = SatPassPrefs( + preferences.getString(keyHours, defValueHours)!!.toInt(), + preferences.getString(keyMinEl, defValueMinEl)!!.toDouble() + ) val debugMessage = MutableLiveData("") val gsp = MutableLiveData( GroundStationPosition( @@ -60,54 +64,9 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { preferences.getString(keyAlt, defValueLoc)!!.toDouble() ) ) - var satPassList = emptyList() var tleMainList = loadTwoLineElementFile() - var tleSelectedMap = mutableMapOf() - var passPrefs = SatPassPrefs( - preferences.getString(keyHours, defValueHours)!!.toInt(), - preferences.getString(keyMinEl, defValueMinEl)!!.toDouble() - ) - - private fun loadTwoLineElementFile(): List { - try { - val fileInput = app.openFileInput(tleFileName) - val objectInput = ObjectInputStream(fileInput) - val tleList = objectInput.readObject() - return tleList as List - } catch (e: FileNotFoundException) { - debugMessage.postValue("TLE file wasn't found") - } catch (e: IOException) { - debugMessage.postValue(e.toString()) - } - return emptyList() - } - - suspend fun getPasses() { - val passList = mutableListOf() - withContext(Dispatchers.Default) { - tleSelectedMap.forEach { (tle, value) -> - if (value) { - try { - val predictor = PassPredictor(tle, gsp.value) - val passes = predictor.getPasses(Date(), passPrefs.hoursAhead, true) - passes.forEach { passList.add(SatPass(tle, predictor, it)) } - } catch (exception: IllegalArgumentException) { - debugMessage.postValue("There was a problem with ${tle.name}") - } catch (exception: SatNotFoundException) { - debugMessage.postValue("${tle.name} shall not pass") - } - } - } - passList.retainAll { it.pass.maxEl >= passPrefs.maxEl } - passList.sortBy { it.pass.startTime } - } - satPassList = passList - } - - fun updateSelectedSatMap(mutableMap: MutableMap) { - tleSelectedMap = mutableMap - } + var selectionList = loadSelectionList() fun updateGsp() { val lat = preferences.getString(keyLat, defValueLoc)!!.toDouble() @@ -145,7 +104,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { try { val inputStream = repository.fetchTleStream() val tleList = TLE.importSat(inputStream).apply { sortBy { it.name } } - val fileOutStream = app.openFileOutput(tleFileName, Context.MODE_PRIVATE) + val fileOutStream = app.openFileOutput(tleMainListFileName, Context.MODE_PRIVATE) ObjectOutputStream(fileOutStream).apply { writeObject(tleList) flush() @@ -170,7 +129,70 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { } } + fun updateAndSaveSelectionList(list: MutableList) { + selectionList = list + try { + val fileOutputStream = app.openFileOutput(tleSelectionFileName, Context.MODE_PRIVATE) + ObjectOutputStream(fileOutputStream).apply { + writeObject(list) + flush() + close() + } + } catch (exception: IOException) { + debugMessage.postValue(exception.toString()) + } + } + + suspend fun getPasses() { + val passList = mutableListOf() + withContext(Dispatchers.Default) { + selectionList.forEach { indexOfSelection -> + val tle = tleMainList[indexOfSelection] + try { + val predictor = PassPredictor(tle, gsp.value) + val passes = predictor.getPasses(Date(), passPrefs.hoursAhead, true) + passes.forEach { passList.add(SatPass(tle, predictor, it)) } + } catch (exception: IllegalArgumentException) { + debugMessage.postValue("There was a problem with ${tle.name}") + } catch (exception: SatNotFoundException) { + debugMessage.postValue("${tle.name} shall not pass") + } + } + passList.retainAll { it.pass.maxEl >= passPrefs.maxEl } + passList.sortBy { it.pass.startTime } + } + satPassList = passList + } + suspend fun getTransmittersForSat(id: Int): List { return repository.getTransmittersForSat(id) } + + @Suppress("UNCHECKED_CAST") + private fun loadTwoLineElementFile(): List { + try { + val fileInputStream = app.openFileInput(tleMainListFileName) + val tleList = ObjectInputStream(fileInputStream).readObject() + return tleList as List + } catch (exception: FileNotFoundException) { + debugMessage.postValue("TLE file wasn't found") + } catch (exception: IOException) { + debugMessage.postValue(exception.toString()) + } + return emptyList() + } + + @Suppress("UNCHECKED_CAST") + private fun loadSelectionList(): MutableList { + try { + val fileInputStream = app.openFileInput(tleSelectionFileName) + val selectionList = ObjectInputStream(fileInputStream).readObject() + return selectionList as MutableList + } catch (exception: FileNotFoundException) { + debugMessage.postValue("Selection file wasn't found") + } catch (exception: IOException) { + debugMessage.postValue(exception.toString()) + } + return mutableListOf() + } } \ No newline at end of file diff --git a/app/src/main/java/com/rtbishop/lookingsat/ui/SkyFragment.kt b/app/src/main/java/com/rtbishop/lookingsat/ui/SkyFragment.kt index 1122c0da..c4226eef 100644 --- a/app/src/main/java/com/rtbishop/lookingsat/ui/SkyFragment.kt +++ b/app/src/main/java/com/rtbishop/lookingsat/ui/SkyFragment.kt @@ -75,46 +75,34 @@ class SkyFragment : Fragment() { } btnRefresh.setOnClickListener { calculatePasses() } - fab.setOnClickListener { showSelectSatDialog() } + fab.setOnClickListener { + showSelectSatDialog(viewModel.tleMainList, viewModel.selectionList) + } } - private fun showSelectSatDialog() { - val tleMainList = viewModel.tleMainList - val tleNameArray = arrayOfNulls(tleMainList.size) - val tleCheckedArray = BooleanArray(tleMainList.size) - val selectedSatMap = viewModel.tleSelectedMap - val currentSelectionMap = mutableMapOf() - - if (selectedSatMap.isEmpty()) { - tleMainList.withIndex().forEach { (position, tle) -> - tleNameArray[position] = tle.name - tleCheckedArray[position] = false - } - } else { - tleMainList.withIndex().forEach { (position, tle) -> - tleNameArray[position] = tle.name - tleCheckedArray[position] = selectedSatMap.getOrDefault(tle, false) - } + private fun showSelectSatDialog(tleMainList: List, selectionList: MutableList) { + val tleNameArray = arrayOfNulls(tleMainList.size).apply { + tleMainList.withIndex().forEach { (position, tle) -> this[position] = tle.name } + } + val tleCheckedArray = BooleanArray(tleMainList.size).apply { + selectionList.forEach { this[it] = true } } - val builder = AlertDialog.Builder(activity as MainActivity) builder.setTitle(getString(R.string.title_select_sat)) .setMultiChoiceItems(tleNameArray, tleCheckedArray) { _, which, isChecked -> - currentSelectionMap[tleMainList[which]] = isChecked + if (isChecked) selectionList.add(which) + else if (selectionList.contains(which)) selectionList.remove(which) } .setPositiveButton(getString(R.string.btn_ok)) { _, _ -> - for ((tle, value) in currentSelectionMap) { - selectedSatMap[tle] = value - viewModel.updateSelectedSatMap(selectedSatMap) - calculatePasses() - } + viewModel.updateAndSaveSelectionList(selectionList) + calculatePasses() } .setNegativeButton(getString(R.string.btn_cancel)) { dialog, _ -> dialog.cancel() } .setNeutralButton(getString(R.string.btn_clear)) { _, _ -> - selectedSatMap.clear() - viewModel.updateSelectedSatMap(selectedSatMap) + selectionList.clear() + viewModel.updateAndSaveSelectionList(selectionList) calculatePasses() } .create() diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index df9c7c79..b0b531b0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -62,7 +62,8 @@ hours_ahead min_elevation update_freq - tleFile.txt + tleFile.txt + tleSelection No Yes