From 37c5ebbf2e5a45000aa44bf8f1be558ad1765e84 Mon Sep 17 00:00:00 2001 From: Arty Bishop Date: Sun, 21 Mar 2021 20:22:29 +0000 Subject: [PATCH] Fragments and adapters refactoring --- .../rtbishop/look4sat/data/model/SatPass.kt | 4 +- .../look4sat/data/repository/PassesRepo.kt | 5 +- .../ui/entriesScreen/EntriesFragment.kt | 14 +-- .../look4sat/ui/passesScreen/PassesAdapter.kt | 87 +++++++++++-------- .../ui/passesScreen/PassesFragment.kt | 6 +- .../look4sat/ui/polarScreen/PolarFragment.kt | 54 ++++++------ .../look4sat/ui/polarScreen/PolarView.kt | 2 +- .../look4sat/ui/polarScreen/PolarViewModel.kt | 14 ++- .../look4sat/ui/polarScreen/TransAdapter.kt | 57 ++++++------ .../look4sat/utility/PassPredictor.kt | 27 ++---- 10 files changed, 142 insertions(+), 128 deletions(-) diff --git a/app/src/main/java/com/rtbishop/look4sat/data/model/SatPass.kt b/app/src/main/java/com/rtbishop/look4sat/data/model/SatPass.kt index 0e2e2f30..91bc8c6d 100644 --- a/app/src/main/java/com/rtbishop/look4sat/data/model/SatPass.kt +++ b/app/src/main/java/com/rtbishop/look4sat/data/model/SatPass.kt @@ -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 diff --git a/app/src/main/java/com/rtbishop/look4sat/data/repository/PassesRepo.kt b/app/src/main/java/com/rtbishop/look4sat/data/repository/PassesRepo.kt index d9772c4d..80d9df32 100644 --- a/app/src/main/java/com/rtbishop/look4sat/data/repository/PassesRepo.kt +++ b/app/src/main/java/com/rtbishop/look4sat/data/repository/PassesRepo.kt @@ -35,7 +35,8 @@ class PassesRepo @Inject constructor( private val prefsRepo: PrefsRepo, @DefaultDispatcher private val defaultDispatcher: CoroutineDispatcher ) { - private val _passes = MutableStateFlow>>(Result.InProgress) + private val _passes = + MutableStateFlow>>(Result.Success(mutableListOf())) val passes: StateFlow>> = _passes private var selectedSatellites = emptyList() @@ -61,7 +62,7 @@ class PassesRepo @Inject constructor( private fun getPasses(satellite: Satellite, refDate: Date): MutableList { 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 } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesFragment.kt index 47271812..9c1c31ef 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesFragment.kt @@ -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() } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesAdapter.kt b/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesAdapter.kt index 9ac7af06..fbfdefbf 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesAdapter.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesAdapter.kt @@ -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() { - 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 = mutableListOf() fun setList(list: MutableList) { @@ -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)) + } + } } } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesFragment.kt index da136fd6..54467456 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesFragment.kt @@ -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() + 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) diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarFragment.kt index 60ded8f2..66178746 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarFragment.kt @@ -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() diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarView.kt b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarView.kt index 5ddf4d1f..a9ad7889 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarView.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarView.kt @@ -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) } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarViewModel.kt index f4dc4f86..5de0141f 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarViewModel.kt @@ -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() } \ No newline at end of file diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/TransAdapter.kt b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/TransAdapter.kt index 3df37cfb..8045298b 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/TransAdapter.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/TransAdapter.kt @@ -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() { +class TransAdapter(private val pass: SatPass) : RecyclerView.Adapter() { - 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() fun setData(list: List) { @@ -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)) + } + } } } diff --git a/app/src/main/java/com/rtbishop/look4sat/utility/PassPredictor.kt b/app/src/main/java/com/rtbishop/look4sat/utility/PassPredictor.kt index e5609114..f8806904 100644 --- a/app/src/main/java/com/rtbishop/look4sat/utility/PassPredictor.kt +++ b/app/src/main/java/com/rtbishop/look4sat/utility/PassPredictor.kt @@ -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) } }