Extracted some logic to the core Predictor.kt class

This commit is contained in:
Arty Bishop committed 2022-02-19 12:07:39 +00:00
1 parent b5da3d3ac4
commit 04c4ef25d2
3 files changed
+52 -59

No files matched your search

@@ -41,9 +41,16 @@ class PassesViewModel @Inject constructor(
init { init {
viewModelScope.launch { viewModelScope.launch {
predictor.passes.collect { passes -> predictor.calculatedPasses.collect { passes ->
passesProcessing?.cancelAndJoin() passesProcessing?.cancelAndJoin()
passesProcessing = viewModelScope.launch { tickPasses(passes) } passesProcessing = viewModelScope.launch {
while (isActive) {
val time = System.currentTimeMillis()
val newPasses = predictor.processPasses(passes, time)
_passes.postValue(DataState.Success(newPasses))
delay(1000)
}
}
} }
} }
} }
@@ -70,25 +77,4 @@ class PassesViewModel @Inject constructor(
settings.setHoursAhead(hoursAhead) settings.setHoursAhead(hoursAhead)
settings.setMinElevation(minElevation) settings.setMinElevation(minElevation)
} }
private suspend fun tickPasses(passes: List<SatPass>) = withContext(Dispatchers.Default) {
var currentPasses = passes
while (isActive) {
val timeNow = System.currentTimeMillis()
currentPasses.forEach { pass ->
if (!pass.isDeepSpace) {
val timeStart = pass.aosTime
if (timeNow > timeStart) {
val deltaNow = timeNow.minus(timeStart).toFloat()
val deltaTotal = pass.losTime.minus(timeStart).toFloat()
pass.progress = ((deltaNow / deltaTotal) * 100).toInt()
}
}
}
currentPasses = currentPasses.filter { it.progress < 100 }
val passesCopy = currentPasses.map { it.copy() }
_passes.postValue(DataState.Success(passesCopy))
delay(1000)
}
}
} }
@@ -54,7 +54,7 @@ class RadarViewModel @Inject constructor(
val orientation: LiveData<Triple<Float, Float, Float>> = _orientation val orientation: LiveData<Triple<Float, Float, Float>> = _orientation
fun getPass(catNum: Int, aosTime: Long) = liveData { fun getPass(catNum: Int, aosTime: Long) = liveData {
predictor.passes.collect { passes -> predictor.calculatedPasses.collect { passes ->
val pass = passes.find { it.catNum == catNum && it.aosTime == aosTime } val pass = passes.find { it.catNum == catNum && it.aosTime == aosTime }
pass?.let { satPass -> pass?.let { satPass ->
emit(satPass) emit(satPass)
@@ -105,21 +105,13 @@ class RadarViewModel @Inject constructor(
} }
} }
private fun processTransmitters(satPass: SatPass) { private fun processTransmitters(pass: SatPass) {
viewModelScope.launch { viewModelScope.launch {
val transmitters = dataRepository.getTransmitters(satPass.catNum) val transmitters = dataRepository.getTransmitters(pass.catNum)
while (isActive) { while (isActive) {
val satPos = predictor.getSatPos(satPass.satellite, stationPos, Date().time) val time = System.currentTimeMillis()
val copiedList = transmitters.map { it.copy() } val list = predictor.processRadios(pass.satellite, stationPos, transmitters, time)
copiedList.forEach { transmitter -> _transmitters.postValue(list)
transmitter.downlink?.let {
transmitter.downlink = satPos.getDownlinkFreq(it)
}
transmitter.uplink?.let {
transmitter.uplink = satPos.getUplinkFreq(it)
}
}
_transmitters.postValue(copiedList.map { it.copy() })
delay(1000) delay(1000)
} }
} }
@@ -17,6 +17,7 @@
*/ */
package com.rtbishop.look4sat.domain.predict package com.rtbishop.look4sat.domain.predict
import com.rtbishop.look4sat.domain.model.Transmitter
import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharedFlow
@@ -24,9 +25,8 @@ import kotlinx.coroutines.withContext
class Predictor(private val predictorDispatcher: CoroutineDispatcher) { class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
private val _passes = MutableSharedFlow<List<SatPass>>(replay = 1) private val _calculatedPasses = MutableSharedFlow<List<SatPass>>(replay = 1)
private var selectedSatIds = emptyList<Int>() val calculatedPasses: SharedFlow<List<SatPass>> = _calculatedPasses
val passes: SharedFlow<List<SatPass>> = _passes
suspend fun getSatPos(sat: Satellite, pos: GeoPos, time: Long): SatPos { suspend fun getSatPos(sat: Satellite, pos: GeoPos, time: Long): SatPos {
return withContext(predictorDispatcher) { sat.getPosition(pos, time) } return withContext(predictorDispatcher) { sat.getPosition(pos, time) }
@@ -44,40 +44,55 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
} }
} }
suspend fun triggerCalculation( suspend fun processRadios(sat: Satellite, pos: GeoPos, radios: List<Transmitter>, time: Long): List<Transmitter> {
satellites: List<Satellite>, return withContext(predictorDispatcher) {
pos: GeoPos, val satPos = sat.getPosition(pos, time)
time: Long, val copiedList = radios.map { it.copy() }
hoursAhead: Int = 8, copiedList.forEach { transmitter ->
minElevation: Double = 16.0 transmitter.downlink?.let {
) { transmitter.downlink = satPos.getDownlinkFreq(it)
if (satellites.isEmpty()) {
_passes.emit(emptyList())
} else {
val newCatNums = satellites.map { it.params.catnum }
if (selectedSatIds != newCatNums) {
forceCalculation(satellites, pos, time, hoursAhead, minElevation)
} }
transmitter.uplink?.let {
transmitter.uplink = satPos.getUplinkFreq(it)
}
}
copiedList.map { it.copy() }
}
}
suspend fun processPasses(passList: List<SatPass>, time: Long): List<SatPass> {
return withContext(predictorDispatcher) {
val copiedList = passList.map { it.copy() }
copiedList.forEach { pass ->
if (!pass.isDeepSpace) {
val timeStart = pass.aosTime
if (time > timeStart) {
val deltaNow = time.minus(timeStart).toFloat()
val deltaTotal = pass.losTime.minus(timeStart).toFloat()
pass.progress = ((deltaNow / deltaTotal) * 100).toInt()
}
}
}
copiedList.filter { it.progress < 100 }.map { it.copy() }
} }
} }
suspend fun forceCalculation( suspend fun forceCalculation(
satellites: List<Satellite>, satList: List<Satellite>,
pos: GeoPos, pos: GeoPos,
time: Long, time: Long,
hoursAhead: Int = 8, hoursAhead: Int = 8,
minElevation: Double = 16.0 minElevation: Double = 16.0
) { ) {
if (satellites.isEmpty()) { if (satList.isEmpty()) {
_passes.emit(emptyList()) _calculatedPasses.emit(emptyList())
} else { } else {
withContext(predictorDispatcher) { withContext(predictorDispatcher) {
val allPasses = mutableListOf<SatPass>() val allPasses = mutableListOf<SatPass>()
selectedSatIds = satellites.map { it.params.catnum } satList.forEach { satellite ->
satellites.forEach { satellite ->
allPasses.addAll(satellite.getPasses(pos, time, hoursAhead)) allPasses.addAll(satellite.getPasses(pos, time, hoursAhead))
} }
_passes.emit(allPasses.filter(time, hoursAhead, minElevation)) _calculatedPasses.emit(allPasses.filter(time, hoursAhead, minElevation))
} }
} }
} }