Added various minor fixes, cleaned up classes

This commit is contained in:
Arty Bishop committed 2025-12-27 15:01:45 +00:00
1 parent 5a8108384f
commit fc0b995bac
35 files changed
+295 -310

No files matched your search

@@ -19,8 +19,6 @@ package com.rtbishop.look4sat.domain.model
sealed class DataState<out T> {
data class Success<out T>(val data: T) : DataState<T>()
data class Error(val resId: Int?) : DataState<Nothing>()
data class Exception(val message: String?) : DataState<Nothing>()
data object Handled : DataState<Nothing>()
data object Loading : DataState<Nothing>()
}
@@ -21,7 +21,7 @@ interface IDatabaseRepo {
suspend fun updateFromFile(uri: String)
suspend fun updateFromWeb()
suspend fun updateFromRemote()
suspend fun clearAllData()
}
@@ -19,9 +19,6 @@ package com.rtbishop.look4sat.domain.source
import java.io.InputStream
interface IDataSource {
interface IFileSource {
suspend fun getFileStream(uri: String): InputStream?
suspend fun getNetworkStream(url: String): InputStream?
}
@@ -22,7 +22,7 @@ import com.rtbishop.look4sat.domain.model.SatItem
import com.rtbishop.look4sat.domain.model.SatRadio
import com.rtbishop.look4sat.domain.predict.Satellite
interface ILocalStorage {
interface ILocalSource {
suspend fun getEntriesTotal(): Int
@@ -0,0 +1,24 @@
/*
* Look4Sat. Amateur radio satellite tracker and pass predictor.
* Copyright (C) 2019-2022 Arty Bishop (bishop.arty@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.rtbishop.look4sat.domain.source
import java.io.InputStream
interface IRemoteSource {
suspend fun getRemoteStream(url: String): InputStream?
}
@@ -1,3 +1,20 @@
/*
* Look4Sat. Amateur radio satellite tracker and pass predictor.
* Copyright (C) 2019-2022 Arty Bishop (bishop.arty@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.rtbishop.look4sat.domain.utility
import com.rtbishop.look4sat.domain.predict.DEG2RAD
@@ -19,43 +19,40 @@ package com.rtbishop.look4sat.domain.utility
import com.rtbishop.look4sat.domain.predict.GeoPos
object QthConverter {
fun qthToPosition(locator: String): GeoPos? {
val trimmedQth = locator.take(6)
if (!isValidLocator(trimmedQth)) return null
val lonFirst = (trimmedQth[0].uppercaseChar().code - 65) * 20
val latFirst = (trimmedQth[1].uppercaseChar().code - 65) * 10
val lonSecond = trimmedQth[2].toString().toInt() * 2
val latSecond = trimmedQth[3].toString().toInt()
val lonThird = (((trimmedQth[4].lowercaseChar().code - 97) / 12.0) + (1.0 / 24.0)) - 180
val latThird = (((trimmedQth[5].lowercaseChar().code - 97) / 24.0) + (1.0 / 48.0)) - 90
val longitude = (lonFirst + lonSecond + lonThird).round(4)
val latitude = (latFirst + latSecond + latThird).round(4)
return GeoPos(latitude, longitude)
}
fun positionToQth(latitude: Double, longitude: Double): String? {
if (!isValidPosition(latitude, longitude)) return null
val tempLon = if (longitude > 180.0) longitude - 180 else longitude
val upper = "ABCDEFGHIJKLMNOPQRSTUVWX"
val lower = "abcdefghijklmnopqrstuvwx"
val newLongitude = tempLon + 180
val newLatitude = latitude + 90
val lonFirst = upper[(newLongitude / 20).toInt()]
val latFirst = upper[(newLatitude / 10).toInt()]
val lonSecond = ((newLongitude / 2) % 10).toInt().toString()
val latSecond = (newLatitude % 10).toInt().toString()
val lonThird = lower[((newLongitude % 2) * 12).toInt()]
val latThird = lower[((newLatitude % 1) * 24).toInt()]
return "$lonFirst$latFirst$lonSecond$latSecond$lonThird$latThird"
}
private fun isValidPosition(lat: Double, lon: Double): Boolean {
return (lat >= -90.0 && lat <= 90.0) && (lon >= -180.0 && lon <= 360.0)
}
private fun isValidLocator(locator: String): Boolean {
return locator.matches("[a-xA-X][a-xA-X]\\d\\d[a-xA-X][a-xA-X]".toRegex())
}
fun qthToPosition(locator: String): GeoPos? {
val trimmedQth = locator.take(6)
if (!isValidLocator(trimmedQth)) return null
val lonFirst = (trimmedQth[0].uppercaseChar().code - 65) * 20
val latFirst = (trimmedQth[1].uppercaseChar().code - 65) * 10
val lonSecond = trimmedQth[2].toString().toInt() * 2
val latSecond = trimmedQth[3].toString().toInt()
val lonThird = (((trimmedQth[4].lowercaseChar().code - 97) / 12.0) + (1.0 / 24.0)) - 180
val latThird = (((trimmedQth[5].lowercaseChar().code - 97) / 24.0) + (1.0 / 48.0)) - 90
val longitude = (lonFirst + lonSecond + lonThird).round(4)
val latitude = (latFirst + latSecond + latThird).round(4)
return GeoPos(latitude, longitude)
}
fun positionToQth(latitude: Double, longitude: Double): String? {
if (!isValidPosition(latitude, longitude)) return null
val tempLon = if (longitude > 180.0) longitude - 180 else longitude
val upper = "ABCDEFGHIJKLMNOPQRSTUVWX"
val lower = "abcdefghijklmnopqrstuvwx"
val newLongitude = tempLon + 180
val newLatitude = latitude + 90
val lonFirst = upper[(newLongitude / 20).toInt()]
val latFirst = upper[(newLatitude / 10).toInt()]
val lonSecond = ((newLongitude / 2) % 10).toInt().toString()
val latSecond = (newLatitude % 10).toInt().toString()
val lonThird = lower[((newLongitude % 2) * 12).toInt()]
val latThird = lower[((newLatitude % 1) * 24).toInt()]
return "$lonFirst$latFirst$lonSecond$latSecond$lonThird$latThird"
}
private fun isValidPosition(lat: Double, lon: Double): Boolean {
return (lat >= -90.0 && lat <= 90.0) && (lon >= -180.0 && lon <= 360.0)
}
private fun isValidLocator(locator: String): Boolean {
return locator.matches("[a-xA-X][a-xA-X]\\d\\d[a-xA-X][a-xA-X]".toRegex())
}
@@ -17,37 +17,38 @@
*/
package com.rtbishop.look4sat.domain
import com.rtbishop.look4sat.domain.utility.QthConverter
import com.rtbishop.look4sat.domain.utility.positionToQth
import com.rtbishop.look4sat.domain.utility.qthToPosition
import org.junit.Test
class QthConverterTest {
@Test
fun `Given valid QTH returns correct POS`() {
var result = QthConverter.qthToPosition("io91VL39FX")
var result = qthToPosition("io91VL39FX")
assert(result?.latitude == 51.4792 && result.longitude == -0.2083)
result = QthConverter.qthToPosition("JN58TD")
result = qthToPosition("JN58TD")
assert(result?.latitude == 48.1458 && result.longitude == 11.6250)
result = QthConverter.qthToPosition("gf15vc")
result = qthToPosition("gf15vc")
assert(result?.latitude == -34.8958 && result.longitude == -56.2083)
}
@Test
fun `Given invalid QTH returns null`() {
assert(QthConverter.qthToPosition("ZZ00zz") == null)
assert(QthConverter.qthToPosition("JN58") == null)
assert(qthToPosition("ZZ00zz") == null)
assert(qthToPosition("JN58") == null)
}
@Test
fun `Given valid POS returns correct QTH`() {
assert(QthConverter.positionToQth(51.4878, -0.2146) == "IO91vl")
assert(QthConverter.positionToQth(48.1466, 11.6083) == "JN58td")
assert(QthConverter.positionToQth(-34.91, -56.2116) == "GF15vc")
assert(positionToQth(51.4878, -0.2146) == "IO91vl")
assert(positionToQth(48.1466, 11.6083) == "JN58td")
assert(positionToQth(-34.91, -56.2116) == "GF15vc")
}
@Test
fun `Given invalid POS returns null`() {
assert(QthConverter.positionToQth(91.0542, -170.1142) == null)
assert(QthConverter.positionToQth(89.0542, -240.1142) == null)
assert(positionToQth(91.0542, -170.1142) == null)
assert(positionToQth(89.0542, -240.1142) == null)
}
}