Implemented satellite selection save and load between app launches. Some code move and cleanup.

This commit is contained in:
Arty Bishop committed 2019-12-10 10:05:39 +00:00
1 parent 928ccd4991
commit 4d3930db89
3 files changed
+88 -77

No files matched your search

@@ -27,7 +27,6 @@ import java.io.ObjectOutputStream
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
@Suppress("UNCHECKED_CAST")
class MainViewModel(application: Application) : AndroidViewModel(application) { class MainViewModel(application: Application) : AndroidViewModel(application) {
private val defValueLoc = application.getString(R.string.def_gsp_loc) 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 keyAlt = application.getString(R.string.key_alt)
private val keyHours = application.getString(R.string.key_hours_ahead) private val keyHours = application.getString(R.string.key_hours_ahead)
private val keyMinEl = application.getString(R.string.key_min_el) 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 private val app = application
@Inject @Inject
@@ -52,6 +52,10 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
(app as LookingSatApp).appComponent.inject(this) (app as LookingSatApp).appComponent.inject(this)
} }
private var passPrefs = SatPassPrefs(
preferences.getString(keyHours, defValueHours)!!.toInt(),
preferences.getString(keyMinEl, defValueMinEl)!!.toDouble()
)
val debugMessage = MutableLiveData("") val debugMessage = MutableLiveData("")
val gsp = MutableLiveData<GroundStationPosition>( val gsp = MutableLiveData<GroundStationPosition>(
GroundStationPosition( GroundStationPosition(
@@ -60,54 +64,9 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
preferences.getString(keyAlt, defValueLoc)!!.toDouble() preferences.getString(keyAlt, defValueLoc)!!.toDouble()
) )
) )
var satPassList = emptyList<SatPass>() var satPassList = emptyList<SatPass>()
var tleMainList = loadTwoLineElementFile() var tleMainList = loadTwoLineElementFile()
var tleSelectedMap = mutableMapOf<TLE, Boolean>() var selectionList = loadSelectionList()
var passPrefs = SatPassPrefs(
preferences.getString(keyHours, defValueHours)!!.toInt(),
preferences.getString(keyMinEl, defValueMinEl)!!.toDouble()
)
private fun loadTwoLineElementFile(): List<TLE> {
try {
val fileInput = app.openFileInput(tleFileName)
val objectInput = ObjectInputStream(fileInput)
val tleList = objectInput.readObject()
return tleList as List<TLE>
} 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<SatPass>()
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<TLE, Boolean>) {
tleSelectedMap = mutableMap
}
fun updateGsp() { fun updateGsp() {
val lat = preferences.getString(keyLat, defValueLoc)!!.toDouble() val lat = preferences.getString(keyLat, defValueLoc)!!.toDouble()
@@ -145,7 +104,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
try { try {
val inputStream = repository.fetchTleStream() val inputStream = repository.fetchTleStream()
val tleList = TLE.importSat(inputStream).apply { sortBy { it.name } } 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 { ObjectOutputStream(fileOutStream).apply {
writeObject(tleList) writeObject(tleList)
flush() flush()
@@ -170,7 +129,70 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
} }
} }
fun updateAndSaveSelectionList(list: MutableList<Int>) {
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<SatPass>()
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<Transmitter> { suspend fun getTransmittersForSat(id: Int): List<Transmitter> {
return repository.getTransmittersForSat(id) return repository.getTransmittersForSat(id)
} }
@Suppress("UNCHECKED_CAST")
private fun loadTwoLineElementFile(): List<TLE> {
try {
val fileInputStream = app.openFileInput(tleMainListFileName)
val tleList = ObjectInputStream(fileInputStream).readObject()
return tleList as List<TLE>
} 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<Int> {
try {
val fileInputStream = app.openFileInput(tleSelectionFileName)
val selectionList = ObjectInputStream(fileInputStream).readObject()
return selectionList as MutableList<Int>
} catch (exception: FileNotFoundException) {
debugMessage.postValue("Selection file wasn't found")
} catch (exception: IOException) {
debugMessage.postValue(exception.toString())
}
return mutableListOf()
}
} }
@@ -75,46 +75,34 @@ class SkyFragment : Fragment() {
} }
btnRefresh.setOnClickListener { calculatePasses() } btnRefresh.setOnClickListener { calculatePasses() }
fab.setOnClickListener { showSelectSatDialog() } fab.setOnClickListener {
showSelectSatDialog(viewModel.tleMainList, viewModel.selectionList)
}
} }
private fun showSelectSatDialog() { private fun showSelectSatDialog(tleMainList: List<TLE>, selectionList: MutableList<Int>) {
val tleMainList = viewModel.tleMainList val tleNameArray = arrayOfNulls<String>(tleMainList.size).apply {
val tleNameArray = arrayOfNulls<String>(tleMainList.size) tleMainList.withIndex().forEach { (position, tle) -> this[position] = tle.name }
val tleCheckedArray = BooleanArray(tleMainList.size) }
val selectedSatMap = viewModel.tleSelectedMap val tleCheckedArray = BooleanArray(tleMainList.size).apply {
val currentSelectionMap = mutableMapOf<TLE, Boolean>() selectionList.forEach { this[it] = true }
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)
}
} }
val builder = AlertDialog.Builder(activity as MainActivity) val builder = AlertDialog.Builder(activity as MainActivity)
builder.setTitle(getString(R.string.title_select_sat)) builder.setTitle(getString(R.string.title_select_sat))
.setMultiChoiceItems(tleNameArray, tleCheckedArray) { _, which, isChecked -> .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)) { _, _ -> .setPositiveButton(getString(R.string.btn_ok)) { _, _ ->
for ((tle, value) in currentSelectionMap) { viewModel.updateAndSaveSelectionList(selectionList)
selectedSatMap[tle] = value calculatePasses()
viewModel.updateSelectedSatMap(selectedSatMap)
calculatePasses()
}
} }
.setNegativeButton(getString(R.string.btn_cancel)) { dialog, _ -> .setNegativeButton(getString(R.string.btn_cancel)) { dialog, _ ->
dialog.cancel() dialog.cancel()
} }
.setNeutralButton(getString(R.string.btn_clear)) { _, _ -> .setNeutralButton(getString(R.string.btn_clear)) { _, _ ->
selectedSatMap.clear() selectionList.clear()
viewModel.updateSelectedSatMap(selectedSatMap) viewModel.updateAndSaveSelectionList(selectionList)
calculatePasses() calculatePasses()
} }
.create() .create()
+2 -1
View File
@@ -62,7 +62,8 @@
<string name="key_hours_ahead">hours_ahead</string> <string name="key_hours_ahead">hours_ahead</string>
<string name="key_min_el">min_elevation</string> <string name="key_min_el">min_elevation</string>
<string name="key_update_freq">update_freq</string> <string name="key_update_freq">update_freq</string>
<string name="tle_file_name">tleFile.txt</string> <string name="tle_main_list_file_name">tleFile.txt</string>
<string name="tle_selection_file_name">tleSelection</string>
<string name="no">No</string> <string name="no">No</string>
<string name="yes">Yes</string> <string name="yes">Yes</string>