mirror of
https://github.com/rt-bishop/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
Fragments and adapters refactoring
This commit is contained in:
1 parent
f04e54d59b
commit
37c5ebbf2e
10 files changed
+142
-128
No files matched your search
@@ -18,11 +18,11 @@
|
||||
package com.rtbishop.look4sat.data.model
|
||||
|
||||
import com.github.amsacode.predict4java.SatPassTime
|
||||
import com.github.amsacode.predict4java.TLE
|
||||
import com.github.amsacode.predict4java.Satellite
|
||||
import com.rtbishop.look4sat.utility.PassPredictor
|
||||
|
||||
class SatPass(
|
||||
val tle: TLE,
|
||||
val satellite: Satellite,
|
||||
val predictor: PassPredictor,
|
||||
val pass: SatPassTime,
|
||||
var progress: Int = 0
|
||||
|
||||
@@ -35,7 +35,8 @@ class PassesRepo @Inject constructor(
|
||||
private val prefsRepo: PrefsRepo,
|
||||
@DefaultDispatcher private val defaultDispatcher: CoroutineDispatcher
|
||||
) {
|
||||
private val _passes = MutableStateFlow<Result<MutableList<SatPass>>>(Result.InProgress)
|
||||
private val _passes =
|
||||
MutableStateFlow<Result<MutableList<SatPass>>>(Result.Success(mutableListOf()))
|
||||
val passes: StateFlow<Result<MutableList<SatPass>>> = _passes
|
||||
|
||||
private var selectedSatellites = emptyList<Satellite>()
|
||||
@@ -61,7 +62,7 @@ class PassesRepo @Inject constructor(
|
||||
private fun getPasses(satellite: Satellite, refDate: Date): MutableList<SatPass> {
|
||||
val predictor = satellite.getPredictor(prefsRepo.getStationPosition())
|
||||
val passes = predictor.getPasses(refDate, prefsRepo.getHoursAhead(), true)
|
||||
val passList = passes.map { SatPass(satellite.tle, predictor, it) }
|
||||
val passList = passes.map { SatPass(satellite, predictor, it) }
|
||||
return passList as MutableList<SatPass>
|
||||
}
|
||||
|
||||
|
||||
@@ -46,10 +46,8 @@ class EntriesFragment : Fragment(R.layout.fragment_entries), EntriesAdapter.Entr
|
||||
registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
|
||||
uri?.let { viewModel.importSatDataFromFile(uri) }
|
||||
}
|
||||
private val entriesAdapter = EntriesAdapter().apply {
|
||||
setEntriesClickListener(this@EntriesFragment)
|
||||
}
|
||||
private var binding: FragmentEntriesBinding? = null
|
||||
private var entriesAdapter: EntriesAdapter? = null
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
@@ -60,6 +58,9 @@ class EntriesFragment : Fragment(R.layout.fragment_entries), EntriesAdapter.Entr
|
||||
}
|
||||
|
||||
private fun setupComponents() {
|
||||
entriesAdapter = EntriesAdapter().apply {
|
||||
setEntriesClickListener(this@EntriesFragment)
|
||||
}
|
||||
binding?.apply {
|
||||
entriesRecycler.apply {
|
||||
setHasFixedSize(true)
|
||||
@@ -70,7 +71,7 @@ class EntriesFragment : Fragment(R.layout.fragment_entries), EntriesAdapter.Entr
|
||||
}
|
||||
importWeb.setOnClickListener { showImportFromWebDialog() }
|
||||
importFile.setOnClickListener { filePicker.launch("*/*") }
|
||||
selectAll.setOnClickListener { entriesAdapter.selectAllItems() }
|
||||
selectAll.setOnClickListener { entriesAdapter?.selectAllItems() }
|
||||
searchBar.addTextChangedListener { query -> filterByQuery(query) }
|
||||
searchBar.clearFocus()
|
||||
}
|
||||
@@ -83,7 +84,7 @@ class EntriesFragment : Fragment(R.layout.fragment_entries), EntriesAdapter.Entr
|
||||
if (result.data.isEmpty()) {
|
||||
setEmpty()
|
||||
} else {
|
||||
entriesAdapter.submitAllItems(result.data)
|
||||
entriesAdapter?.submitAllItems(result.data)
|
||||
setLoaded()
|
||||
}
|
||||
}
|
||||
@@ -134,7 +135,7 @@ class EntriesFragment : Fragment(R.layout.fragment_entries), EntriesAdapter.Entr
|
||||
}
|
||||
|
||||
private fun filterByQuery(it: Editable?) {
|
||||
entriesAdapter.filterItems(it.toString())
|
||||
entriesAdapter?.filterItems(it.toString())
|
||||
binding?.entriesRecycler?.scrollToPosition(0)
|
||||
}
|
||||
|
||||
@@ -147,6 +148,7 @@ class EntriesFragment : Fragment(R.layout.fragment_entries), EntriesAdapter.Entr
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
entriesAdapter = null
|
||||
binding = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
*/
|
||||
package com.rtbishop.look4sat.ui.passesScreen
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.os.bundleOf
|
||||
@@ -31,22 +30,9 @@ import com.rtbishop.look4sat.utility.navigateSafe
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class PassesAdapter(context: Context, private val shouldUseUTC: Boolean = false) :
|
||||
class PassesAdapter(private val shouldUseUTC: Boolean = false) :
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
private val currentDate = Date()
|
||||
private val satIdFormat = context.getString(R.string.pass_satId)
|
||||
private val azFormat = context.getString(R.string.pat_azimuth)
|
||||
private val altFormat = context.getString(R.string.pat_altitude)
|
||||
private val elevFormat = context.getString(R.string.pat_elevation)
|
||||
private val aosAzFormat = context.getString(R.string.pass_aosAz)
|
||||
private val maxElFormat = context.getString(R.string.pass_maxEl)
|
||||
private val losAzFormat = context.getString(R.string.pass_losAz)
|
||||
private val startTimeFormat = context.getString(R.string.pass_startTime)
|
||||
private val endTimeFormat = context.getString(R.string.pass_endTime)
|
||||
private val timeZoneUTC = TimeZone.getTimeZone("UTC")
|
||||
private val startFormat = SimpleDateFormat(startTimeFormat, Locale.getDefault())
|
||||
private val endFormat = SimpleDateFormat(endTimeFormat, Locale.getDefault())
|
||||
private var satPassList: MutableList<SatPass> = mutableListOf()
|
||||
|
||||
fun setList(list: MutableList<SatPass>) {
|
||||
@@ -55,11 +41,10 @@ class PassesAdapter(context: Context, private val shouldUseUTC: Boolean = false)
|
||||
}
|
||||
|
||||
fun tickPasses(timeNow: Long) {
|
||||
currentDate.time = timeNow
|
||||
val iterator = satPassList.listIterator()
|
||||
while (iterator.hasNext()) {
|
||||
val satPass = iterator.next()
|
||||
if (!satPass.tle.isDeepspace) {
|
||||
if (!satPass.satellite.tle.isDeepspace) {
|
||||
if (satPass.progress < 100) {
|
||||
val timeStart = satPass.pass.startTime.time
|
||||
if (timeNow > timeStart) {
|
||||
@@ -84,42 +69,49 @@ class PassesAdapter(context: Context, private val shouldUseUTC: Boolean = false)
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (satPassList[position].tle.isDeepspace) 1
|
||||
return if (satPassList[position].satellite.tle.isDeepspace) 1
|
||||
else 0
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return if (viewType == 0) {
|
||||
val bindingLeo = ItemPassLeoBinding
|
||||
.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
SatPassLeoHolder(bindingLeo)
|
||||
SatPassLeoHolder.from(parent)
|
||||
} else {
|
||||
val bindingGeo = ItemPassGeoBinding
|
||||
.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
SatPassGeoHolder(bindingGeo)
|
||||
SatPassGeoHolder.from(parent)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder.itemViewType == 0) {
|
||||
(holder as SatPassLeoHolder).bind(satPassList[position])
|
||||
(holder as SatPassLeoHolder).bind(satPassList[position], position, shouldUseUTC)
|
||||
} else {
|
||||
(holder as SatPassGeoHolder).bind(satPassList[position])
|
||||
(holder as SatPassGeoHolder).bind(satPassList[position], position)
|
||||
}
|
||||
}
|
||||
|
||||
inner class SatPassLeoHolder(private val binding: ItemPassLeoBinding) :
|
||||
class SatPassLeoHolder private constructor(private val binding: ItemPassLeoBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(satPass: SatPass) {
|
||||
val satPos = satPass.predictor.getSatPos(currentDate)
|
||||
private val satIdFormat = itemView.context.getString(R.string.pass_satId)
|
||||
private val altFormat = itemView.context.getString(R.string.pat_altitude)
|
||||
private val aosAzFormat = itemView.context.getString(R.string.pass_aosAz)
|
||||
private val maxElFormat = itemView.context.getString(R.string.pass_maxEl)
|
||||
private val losAzFormat = itemView.context.getString(R.string.pass_losAz)
|
||||
private val startTimeFormat = itemView.context.getString(R.string.pass_startTime)
|
||||
private val endTimeFormat = itemView.context.getString(R.string.pass_endTime)
|
||||
private val timeZoneUTC = TimeZone.getTimeZone("UTC")
|
||||
private val startFormat = SimpleDateFormat(startTimeFormat, Locale.getDefault())
|
||||
private val endFormat = SimpleDateFormat(endTimeFormat, Locale.getDefault())
|
||||
|
||||
fun bind(satPass: SatPass, position: Int, shouldUseUTC: Boolean) {
|
||||
val satPos = satPass.predictor.getSatPos(Date())
|
||||
binding.apply {
|
||||
if (shouldUseUTC) {
|
||||
startFormat.timeZone = timeZoneUTC
|
||||
endFormat.timeZone = timeZoneUTC
|
||||
}
|
||||
passLeoSatName.text = satPass.tle.name
|
||||
passLeoSatId.text = String.format(satIdFormat, satPass.tle.catnum)
|
||||
passLeoSatName.text = satPass.satellite.tle.name
|
||||
passLeoSatId.text = String.format(satIdFormat, satPass.satellite.tle.catnum)
|
||||
passLeoAosAz.text = String.format(aosAzFormat, satPass.pass.aosAzimuth)
|
||||
passLeoMaxEl.text = String.format(maxElFormat, satPass.pass.maxEl)
|
||||
passLeoLosAz.text = String.format(losAzFormat, satPass.pass.losAzimuth)
|
||||
@@ -131,30 +123,49 @@ class PassesAdapter(context: Context, private val shouldUseUTC: Boolean = false)
|
||||
|
||||
itemView.setOnClickListener {
|
||||
if (satPass.progress < 100) {
|
||||
val bundle = bundleOf("index" to satPassList.indexOf(satPass))
|
||||
val bundle = bundleOf("index" to position)
|
||||
itemView.findNavController().navigateSafe(R.id.action_passes_to_polar, bundle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun from(parent: ViewGroup): SatPassLeoHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
return SatPassLeoHolder(ItemPassLeoBinding.inflate(inflater, parent, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class SatPassGeoHolder(private val binding: ItemPassGeoBinding) :
|
||||
class SatPassGeoHolder private constructor(private val binding: ItemPassGeoBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(satPass: SatPass) {
|
||||
val satPos = satPass.predictor.getSatPos(currentDate)
|
||||
private val satIdFormat = itemView.context.getString(R.string.pass_satId)
|
||||
private val azFormat = itemView.context.getString(R.string.pat_azimuth)
|
||||
private val altFormat = itemView.context.getString(R.string.pat_altitude)
|
||||
private val elevFormat = itemView.context.getString(R.string.pat_elevation)
|
||||
|
||||
fun bind(satPass: SatPass, position: Int) {
|
||||
val satPos = satPass.predictor.getSatPos(Date())
|
||||
binding.apply {
|
||||
passGeoSatName.text = satPass.tle.name
|
||||
passGeoSatId.text = String.format(satIdFormat, satPass.tle.catnum)
|
||||
passGeoSatName.text = satPass.satellite.tle.name
|
||||
passGeoSatId.text = String.format(satIdFormat, satPass.satellite.tle.catnum)
|
||||
passGeoAz.text = String.format(azFormat, Math.toDegrees(satPos.azimuth))
|
||||
passGeoAlt.text = String.format(altFormat, satPos.altitude)
|
||||
passGeoEl.text = String.format(elevFormat, Math.toDegrees(satPos.elevation))
|
||||
}
|
||||
|
||||
itemView.setOnClickListener {
|
||||
val bundle = bundleOf("index" to satPassList.indexOf(satPass))
|
||||
val bundle = bundleOf("index" to position)
|
||||
itemView.findNavController().navigateSafe(R.id.action_passes_to_polar, bundle)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun from(parent: ViewGroup): SatPassGeoHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
return SatPassGeoHolder(ItemPassGeoBinding.inflate(inflater, parent, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,10 +37,10 @@ import java.util.*
|
||||
@AndroidEntryPoint
|
||||
class PassesFragment : Fragment(R.layout.fragment_passes) {
|
||||
|
||||
private var binding: FragmentPassesBinding? = null
|
||||
private var passesAdapter: PassesAdapter? = null
|
||||
private val viewModel: PassesViewModel by viewModels()
|
||||
private var passes = mutableListOf<SatPass>()
|
||||
private var binding: FragmentPassesBinding? = null
|
||||
private var passesAdapter: PassesAdapter? = null
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
@@ -84,7 +84,7 @@ class PassesFragment : Fragment(R.layout.fragment_passes) {
|
||||
}
|
||||
|
||||
private fun setupComponents() {
|
||||
passesAdapter = PassesAdapter(requireContext(), viewModel.shouldUseUTC())
|
||||
passesAdapter = PassesAdapter(viewModel.shouldUseUTC())
|
||||
binding?.apply {
|
||||
passesRecycler.apply {
|
||||
setHasFixedSize(true)
|
||||
|
||||
@@ -32,23 +32,18 @@ import androidx.recyclerview.widget.SimpleItemAnimator
|
||||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.data.model.Result
|
||||
import com.rtbishop.look4sat.data.model.SatPass
|
||||
import com.rtbishop.look4sat.data.repository.PrefsRepo
|
||||
import com.rtbishop.look4sat.databinding.FragmentPolarBinding
|
||||
import com.rtbishop.look4sat.utility.RecyclerDivider
|
||||
import com.rtbishop.look4sat.utility.formatForTimer
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.round
|
||||
|
||||
@FlowPreview
|
||||
@AndroidEntryPoint
|
||||
class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener {
|
||||
|
||||
@Inject
|
||||
lateinit var prefsRepo: PrefsRepo
|
||||
|
||||
private lateinit var transmitterAdapter: TransAdapter
|
||||
private lateinit var binding: FragmentPolarBinding
|
||||
private lateinit var satPass: SatPass
|
||||
@@ -61,13 +56,13 @@ class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding = FragmentPolarBinding.bind(view)
|
||||
sensorManager = requireContext().getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||
magneticDeclination = prefsRepo.getMagDeclination()
|
||||
magneticDeclination = viewModel.getMagDeclination()
|
||||
observePasses()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (prefsRepo.shouldUseCompass()) {
|
||||
if (viewModel.shouldUseCompass()) {
|
||||
sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR).also { sensor ->
|
||||
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_UI)
|
||||
}
|
||||
@@ -76,7 +71,7 @@ class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener {
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
if (prefsRepo.shouldUseCompass()) {
|
||||
if (viewModel.shouldUseCompass()) {
|
||||
sensorManager.unregisterListener(this)
|
||||
}
|
||||
}
|
||||
@@ -98,7 +93,7 @@ class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener {
|
||||
}
|
||||
|
||||
private fun observePasses() {
|
||||
viewModel.passes.observe(viewLifecycleOwner, { result ->
|
||||
viewModel.getPasses().observe(viewLifecycleOwner, { result ->
|
||||
if (result is Result.Success) {
|
||||
satPass = result.data[requireArguments().getInt("index")]
|
||||
polarView = PolarView(requireContext()).apply { setPass(satPass) }
|
||||
@@ -109,26 +104,27 @@ class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener {
|
||||
}
|
||||
|
||||
private fun observeTransmitters() {
|
||||
viewModel.getTransmittersForSat(satPass.tle.catnum).observe(viewLifecycleOwner, { list ->
|
||||
transmitterAdapter = TransAdapter(requireContext(), satPass)
|
||||
if (list.isNotEmpty()) {
|
||||
transmitterAdapter.setData(list)
|
||||
binding.recycler.apply {
|
||||
setHasFixedSize(true)
|
||||
adapter = transmitterAdapter
|
||||
isVerticalScrollBarEnabled = false
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
(itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
|
||||
addItemDecoration(RecyclerDivider(R.drawable.rec_divider_dark))
|
||||
visibility = View.VISIBLE
|
||||
viewModel.getTransmittersForSat(satPass.satellite.tle.catnum)
|
||||
.observe(viewLifecycleOwner, { list ->
|
||||
transmitterAdapter = TransAdapter(satPass)
|
||||
if (list.isNotEmpty()) {
|
||||
transmitterAdapter.setData(list)
|
||||
binding.recycler.apply {
|
||||
setHasFixedSize(true)
|
||||
adapter = transmitterAdapter
|
||||
isVerticalScrollBarEnabled = false
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
(itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
|
||||
addItemDecoration(RecyclerDivider(R.drawable.rec_divider_dark))
|
||||
visibility = View.VISIBLE
|
||||
}
|
||||
binding.noTransMsg.visibility = View.INVISIBLE
|
||||
} else {
|
||||
binding.recycler.visibility = View.INVISIBLE
|
||||
binding.noTransMsg.visibility = View.VISIBLE
|
||||
}
|
||||
binding.noTransMsg.visibility = View.INVISIBLE
|
||||
} else {
|
||||
binding.recycler.visibility = View.INVISIBLE
|
||||
binding.noTransMsg.visibility = View.VISIBLE
|
||||
}
|
||||
observeTimer()
|
||||
})
|
||||
observeTimer()
|
||||
})
|
||||
}
|
||||
|
||||
private fun observeTimer() {
|
||||
@@ -151,7 +147,7 @@ class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener {
|
||||
binding.distance.text = String.format(polarRng, satPos.range)
|
||||
binding.altitude.text = String.format(polarAlt, satPos.altitude)
|
||||
|
||||
if (!satPass.tle.isDeepspace) {
|
||||
if (!satPass.satellite.tle.isDeepspace) {
|
||||
if (dateNow.before(satPass.pass.startTime)) {
|
||||
val millisBeforeStart = satPass.pass.startTime.time.minus(timeNow)
|
||||
binding.polarTimer.text = millisBeforeStart.formatForTimer()
|
||||
|
||||
@@ -72,7 +72,7 @@ class PolarView(context: Context) : View(context) {
|
||||
canvas.translate(polarCenter, polarCenter)
|
||||
drawRadarView(canvas)
|
||||
drawRadarText(canvas)
|
||||
if (!satPass.tle.isDeepspace) drawPassTrajectory(canvas, satPass)
|
||||
if (!satPass.satellite.tle.isDeepspace) drawPassTrajectory(canvas, satPass)
|
||||
drawSatellite(canvas, satPass)
|
||||
}
|
||||
|
||||
|
||||
@@ -30,12 +30,10 @@ import javax.inject.Inject
|
||||
@HiltViewModel
|
||||
class PolarViewModel @Inject constructor(
|
||||
private val prefsRepo: PrefsRepo,
|
||||
passesRepo: PassesRepo,
|
||||
private val passesRepo: PassesRepo,
|
||||
private val satelliteRepo: SatelliteRepo
|
||||
) : ViewModel() {
|
||||
|
||||
val passes = passesRepo.passes.asLiveData()
|
||||
|
||||
fun getAppTimer() = liveData {
|
||||
while (true) {
|
||||
emit(System.currentTimeMillis())
|
||||
@@ -43,5 +41,15 @@ class PolarViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun getPasses() = passesRepo.passes.asLiveData()
|
||||
|
||||
fun shouldUseCompass(): Boolean {
|
||||
return prefsRepo.shouldUseCompass()
|
||||
}
|
||||
|
||||
fun getMagDeclination(): Float {
|
||||
return prefsRepo.getMagDeclination()
|
||||
}
|
||||
|
||||
fun getTransmittersForSat(satId: Int) = satelliteRepo.getSatTransmitters(satId).asLiveData()
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
*/
|
||||
package com.rtbishop.look4sat.ui.polarScreen
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@@ -25,19 +24,12 @@ import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.data.model.SatPass
|
||||
import com.rtbishop.look4sat.data.model.SatTrans
|
||||
import com.rtbishop.look4sat.databinding.ItemTransBinding
|
||||
import com.rtbishop.look4sat.utility.PassPredictor
|
||||
import com.rtbishop.look4sat.utility.getDopplerFreq
|
||||
import java.util.*
|
||||
|
||||
class TransAdapter(context: Context, private val satPass: SatPass) :
|
||||
RecyclerView.Adapter<TransAdapter.TransHolder>() {
|
||||
class TransAdapter(private val pass: SatPass) : RecyclerView.Adapter<TransAdapter.TransHolder>() {
|
||||
|
||||
private val divider = 1000000f
|
||||
private val strNo = context.getString(R.string.btn_no)
|
||||
private val strYes = context.getString(R.string.btn_yes)
|
||||
private val mode = context.getString(R.string.trans_mode)
|
||||
private val formatLink = context.getString(R.string.trans_link_low)
|
||||
private val formatLinkNull = context.getString(R.string.trans_no_link)
|
||||
private val isInverted = context.getString(R.string.trans_inverted)
|
||||
private val predictor = satPass.predictor
|
||||
private var transmittersList = emptyList<SatTrans>()
|
||||
|
||||
fun setData(list: List<SatTrans>) {
|
||||
@@ -46,7 +38,7 @@ class TransAdapter(context: Context, private val satPass: SatPass) :
|
||||
}
|
||||
|
||||
fun tickTransmitters() {
|
||||
if (!satPass.tle.isDeepspace) {
|
||||
if (!pass.satellite.tle.isDeepspace) {
|
||||
val iterator = transmittersList.listIterator()
|
||||
while (iterator.hasNext()) {
|
||||
val trans = iterator.next()
|
||||
@@ -61,23 +53,29 @@ class TransAdapter(context: Context, private val satPass: SatPass) :
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TransHolder {
|
||||
val binding = ItemTransBinding
|
||||
.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return TransHolder(binding)
|
||||
return TransHolder.from(parent)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: TransHolder, position: Int) {
|
||||
holder.bind(transmittersList[position])
|
||||
holder.bind(transmittersList[position], pass)
|
||||
}
|
||||
|
||||
inner class TransHolder(private val binding: ItemTransBinding) :
|
||||
class TransHolder private constructor(private val binding: ItemTransBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(satTrans: SatTrans) {
|
||||
private val divider = 1000000f
|
||||
private val strNo = itemView.context.getString(R.string.btn_no)
|
||||
private val strYes = itemView.context.getString(R.string.btn_yes)
|
||||
private val mode = itemView.context.getString(R.string.trans_mode)
|
||||
private val formatLink = itemView.context.getString(R.string.trans_link_low)
|
||||
private val formatLinkNull = itemView.context.getString(R.string.trans_no_link)
|
||||
private val isInverted = itemView.context.getString(R.string.trans_inverted)
|
||||
|
||||
fun bind(satTrans: SatTrans, satPass: SatPass) {
|
||||
binding.description.text = satTrans.description
|
||||
|
||||
if (satPass.tle.isDeepspace) setRegularFreq(satTrans)
|
||||
else setDopplerFreq(satTrans)
|
||||
if (satPass.satellite.tle.isDeepspace) setRegularFreq(satTrans)
|
||||
else setDopplerFreq(satTrans, satPass.predictor)
|
||||
|
||||
if (satTrans.mode != null) binding.mode.text = String.format(mode, satTrans.mode)
|
||||
else binding.mode.text = String.format(mode, strNo)
|
||||
@@ -98,18 +96,27 @@ class TransAdapter(context: Context, private val satPass: SatPass) :
|
||||
} else binding.uplink.text = formatLinkNull
|
||||
}
|
||||
|
||||
private fun setDopplerFreq(satTrans: SatTrans) {
|
||||
private fun setDopplerFreq(satTrans: SatTrans, predictor: PassPredictor) {
|
||||
val dateNow = Date()
|
||||
|
||||
if (satTrans.downlinkLow != null) {
|
||||
val downFreq = predictor.getDownlinkFreq(satTrans.downlinkLow, dateNow) / divider
|
||||
binding.downlink.text = String.format(Locale.ENGLISH, formatLink, downFreq)
|
||||
val rangeRate = predictor.getSatPos(dateNow).rangeRate
|
||||
val freq = satTrans.downlinkLow.getDopplerFreq(rangeRate, true) / divider
|
||||
binding.downlink.text = String.format(Locale.ENGLISH, formatLink, freq)
|
||||
} else binding.downlink.text = formatLinkNull
|
||||
|
||||
if (satTrans.uplinkLow != null) {
|
||||
val upFreq = predictor.getUplinkFreq(satTrans.uplinkLow, dateNow) / divider
|
||||
binding.uplink.text = String.format(Locale.ENGLISH, formatLink, upFreq)
|
||||
val rangeRate = predictor.getSatPos(dateNow).rangeRate
|
||||
val freq = satTrans.uplinkLow.getDopplerFreq(rangeRate, false) / divider
|
||||
binding.uplink.text = String.format(Locale.ENGLISH, formatLink, freq)
|
||||
} else binding.uplink.text = formatLinkNull
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun from(parent: ViewGroup): TransHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
return TransHolder(ItemTransBinding.inflate(inflater, parent, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,19 +24,9 @@ import com.github.amsacode.predict4java.Satellite
|
||||
import java.util.*
|
||||
|
||||
class PassPredictor(private val satellite: Satellite, private val qth: GroundStationPosition) {
|
||||
private val oneQuarterOrbitMin = (24.0 * 60.0 / satellite.tle.meanmo / 4.0).toInt()
|
||||
private val speedOfLight = 2.99792458E8
|
||||
|
||||
fun getDownlinkFreq(freq: Long, date: Date): Long {
|
||||
val rangeRate = getSatPos(date).rangeRate
|
||||
return (freq.toDouble() * (speedOfLight - rangeRate * 1000.0) / speedOfLight).toLong()
|
||||
}
|
||||
|
||||
fun getUplinkFreq(freq: Long, date: Date): Long {
|
||||
val rangeRate = getSatPos(date).rangeRate
|
||||
return (freq.toDouble() * (speedOfLight + rangeRate * 1000.0) / speedOfLight).toLong()
|
||||
}
|
||||
|
||||
private val oneQuarterOrbitMin = (24.0 * 60.0 / satellite.tle.meanmo / 4.0).toInt()
|
||||
|
||||
fun getSatPos(date: Date): SatPos {
|
||||
return satellite.getPosition(qth, date)
|
||||
}
|
||||
@@ -81,10 +71,9 @@ class PassPredictor(private val satellite: Satellite, private val qth: GroundSta
|
||||
val satPos = getSatPos(refDate)
|
||||
val startDate = Date(refDate.time - 24 * 60L * 60L * 1000L)
|
||||
val endDate = Date(refDate.time + 24 * 60L * 60L * 1000L)
|
||||
val aosAzimuth = (satPos.azimuth / (2.0 * Math.PI) * 360.0).toInt()
|
||||
val losAzimuth = (satPos.azimuth / (2.0 * Math.PI) * 360.0).toInt()
|
||||
val maxEl = satPos.elevation / (2.0 * Math.PI) * 360.0
|
||||
return SatPassTime(startDate, endDate, "pole", aosAzimuth, losAzimuth, maxEl)
|
||||
val azimuth = Math.toDegrees(satPos.azimuth).toInt()
|
||||
val maxEl = Math.toDegrees(satPos.elevation)
|
||||
return SatPassTime(startDate, endDate, "pole", azimuth, azimuth, maxEl)
|
||||
}
|
||||
|
||||
private fun nextNearEarthPass(refDate: Date, windBack: Boolean = false): SatPassTime {
|
||||
@@ -127,7 +116,7 @@ class PassPredictor(private val satellite: Satellite, private val qth: GroundSta
|
||||
} while (satPos.elevation < 0.0)
|
||||
|
||||
val startDate = satPos.time
|
||||
val aosAzimuth = (satPos.azimuth / (2.0 * Math.PI) * 360.0).toInt()
|
||||
val aosAzimuth = Math.toDegrees(satPos.azimuth).toInt()
|
||||
|
||||
// find when sat goes below
|
||||
do {
|
||||
@@ -147,8 +136,8 @@ class PassPredictor(private val satellite: Satellite, private val qth: GroundSta
|
||||
} while (satPos.elevation > 0.0)
|
||||
|
||||
val endDate = satPos.time
|
||||
val losAzimuth = (satPos.azimuth / (2.0 * Math.PI) * 360.0).toInt()
|
||||
val maxEl = maxElevation / (2.0 * Math.PI) * 360.0
|
||||
val losAzimuth = Math.toDegrees(satPos.azimuth).toInt()
|
||||
val maxEl = Math.toDegrees(maxElevation)
|
||||
return SatPassTime(startDate, endDate, "pole", aosAzimuth, losAzimuth, maxEl)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user