Implemented satellite selection save and load between app launches. Some code move and cleanup.
This commit is contained in:
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 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>(
|
||||
GroundStationPosition(
|
||||
@@ -60,54 +64,9 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
|
||||
preferences.getString(keyAlt, defValueLoc)!!.toDouble()
|
||||
)
|
||||
)
|
||||
|
||||
var satPassList = emptyList<SatPass>()
|
||||
var tleMainList = loadTwoLineElementFile()
|
||||
var tleSelectedMap = mutableMapOf<TLE, Boolean>()
|
||||
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
|
||||
}
|
||||
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<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> {
|
||||
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() }
|
||||
fab.setOnClickListener { showSelectSatDialog() }
|
||||
fab.setOnClickListener {
|
||||
showSelectSatDialog(viewModel.tleMainList, viewModel.selectionList)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSelectSatDialog() {
|
||||
val tleMainList = viewModel.tleMainList
|
||||
val tleNameArray = arrayOfNulls<String>(tleMainList.size)
|
||||
val tleCheckedArray = BooleanArray(tleMainList.size)
|
||||
val selectedSatMap = viewModel.tleSelectedMap
|
||||
val currentSelectionMap = mutableMapOf<TLE, Boolean>()
|
||||
|
||||
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<TLE>, selectionList: MutableList<Int>) {
|
||||
val tleNameArray = arrayOfNulls<String>(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()
|
||||
|
||||
@@ -62,7 +62,8 @@
|
||||
<string name="key_hours_ahead">hours_ahead</string>
|
||||
<string name="key_min_el">min_elevation</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="yes">Yes</string>
|
||||
|
||||
Reference in new issue
Block a user