kopia lustrzana https://github.com/rt-bishop/Look4Sat
Added GeoConverter.kt and various minor fixes
rodzic
3efff32dbb
commit
6a2a4f9f9e
|
@ -9,6 +9,7 @@
|
|||
android:name=".MainApplication"
|
||||
android:allowBackup="false"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
|
@ -16,7 +17,7 @@
|
|||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.Look4Sat.Main"
|
||||
tools:targetApi="31">
|
||||
tools:targetApi="33">
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
|
|
|
@ -11,7 +11,6 @@ import com.rtbishop.look4sat.data.database.MainDatabase
|
|||
import com.rtbishop.look4sat.data.framework.BluetoothReporter
|
||||
import com.rtbishop.look4sat.data.framework.NetworkReporter
|
||||
import com.rtbishop.look4sat.data.framework.SettingsRepo
|
||||
import com.rtbishop.look4sat.data.repository.DataParser
|
||||
import com.rtbishop.look4sat.data.repository.DatabaseRepo
|
||||
import com.rtbishop.look4sat.data.repository.SatelliteRepo
|
||||
import com.rtbishop.look4sat.data.repository.SelectionRepo
|
||||
|
@ -22,20 +21,25 @@ import com.rtbishop.look4sat.domain.repository.IDatabaseRepo
|
|||
import com.rtbishop.look4sat.domain.repository.ISatelliteRepo
|
||||
import com.rtbishop.look4sat.domain.repository.ISelectionRepo
|
||||
import com.rtbishop.look4sat.domain.repository.ISettingsRepo
|
||||
import com.rtbishop.look4sat.domain.source.IDataSource
|
||||
import com.rtbishop.look4sat.domain.source.ISensorSource
|
||||
import com.rtbishop.look4sat.domain.utility.DataParser
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import okhttp3.Cache
|
||||
import okhttp3.OkHttpClient
|
||||
import org.osmdroid.config.Configuration
|
||||
|
||||
class MainContainer(private val context: Context) {
|
||||
|
||||
private val database = Room.databaseBuilder(context, MainDatabase::class.java, "Look4SatDb")
|
||||
.addMigrations(MIGRATION_1_2).fallbackToDestructiveMigration().build()
|
||||
private val database =
|
||||
Room.databaseBuilder(context, MainDatabase::class.java, "Look4SatDb").addMigrations(MIGRATION_1_2)
|
||||
.fallbackToDestructiveMigration().build()
|
||||
private val localStorage = LocalStorage(database.storageDao())
|
||||
private val mainHandler = CoroutineExceptionHandler { _, error -> println("Look4Sat: $error") }
|
||||
private val remoteSource = provideRemoteSource()
|
||||
val mainScope = CoroutineScope(SupervisorJob() + Dispatchers.Default + mainHandler)
|
||||
val settingsRepo = provideSettingsRepo()
|
||||
val databaseRepo = provideDatabaseRepo()
|
||||
|
@ -57,11 +61,15 @@ class MainContainer(private val context: Context) {
|
|||
return SensorSource(sensorManager, sensor)
|
||||
}
|
||||
|
||||
private fun provideRemoteSource(): IDataSource {
|
||||
val cache = Cache(context.cacheDir, 1000 * 1000 * 10L)
|
||||
val httpClient = OkHttpClient.Builder().cache(cache).build()
|
||||
return DataSource(context.contentResolver, httpClient, Dispatchers.IO)
|
||||
}
|
||||
|
||||
private fun provideDatabaseRepo(): IDatabaseRepo {
|
||||
val httpClient = OkHttpClient.Builder().build()
|
||||
val dataParser = DataParser(Dispatchers.Default)
|
||||
val dataSource = DataSource(context.contentResolver, httpClient, Dispatchers.IO)
|
||||
return DatabaseRepo(Dispatchers.Default, dataParser, dataSource, localStorage, settingsRepo)
|
||||
return DatabaseRepo(Dispatchers.Default, dataParser, remoteSource, localStorage, settingsRepo)
|
||||
}
|
||||
|
||||
private fun provideSatelliteRepo(): ISatelliteRepo {
|
||||
|
|
|
@ -24,6 +24,7 @@ import com.rtbishop.look4sat.domain.repository.IDatabaseRepo
|
|||
import com.rtbishop.look4sat.domain.repository.ISettingsRepo
|
||||
import com.rtbishop.look4sat.domain.source.IDataSource
|
||||
import com.rtbishop.look4sat.domain.source.ILocalStorage
|
||||
import com.rtbishop.look4sat.domain.utility.DataParser
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package com.rtbishop.look4sat.data
|
||||
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
|
||||
class ExampleUnitTest {
|
||||
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
Assert.assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ kotlin {
|
|||
|
||||
dependencies {
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
|
||||
implementation("org.json:json:20230618")
|
||||
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
testImplementation("io.mockk:mockk:1.13.5")
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* 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.data.repository
|
||||
package com.rtbishop.look4sat.domain.utility
|
||||
|
||||
import com.rtbishop.look4sat.domain.model.SatRadio
|
||||
import com.rtbishop.look4sat.domain.predict.OrbitalData
|
|
@ -17,8 +17,6 @@
|
|||
*/
|
||||
package com.rtbishop.look4sat.domain.utility
|
||||
|
||||
import com.rtbishop.look4sat.domain.predict.DEG2RAD
|
||||
import com.rtbishop.look4sat.domain.predict.RAD2DEG
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
fun Long.toTimerString(): String {
|
||||
|
@ -41,10 +39,6 @@ fun Double.round(decimals: Int): Double {
|
|||
return kotlin.math.round(this * multiplier) / multiplier
|
||||
}
|
||||
|
||||
fun Double.toDegrees(): Double = this * RAD2DEG
|
||||
|
||||
fun Double.toRadians(): Double = this * DEG2RAD
|
||||
|
||||
//fun String.getHash(type: String = "SHA-256"): String {
|
||||
// val hexChars = "0123456789ABCDEF"
|
||||
// val bytes = MessageDigest.getInstance(type).digest(this.toByteArray())
|
||||
|
@ -63,12 +57,12 @@ fun Double.toRadians(): Double = this * DEG2RAD
|
|||
// return pattern.matcher(this).matches()
|
||||
//}
|
||||
|
||||
fun String.isValidIPv4(): Boolean {
|
||||
val ip4 = "^((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])(\\.(?!\$)|\$)){4}\$"
|
||||
return this.matches(ip4.toRegex())
|
||||
}
|
||||
//fun String.isValidIPv4(): Boolean {
|
||||
// val ip4 = "^((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])(\\.(?!\$)|\$)){4}\$"
|
||||
// return this.matches(ip4.toRegex())
|
||||
//}
|
||||
|
||||
fun String.isValidPort(): Boolean {
|
||||
val port = "([1-9]|[1-9]\\d{1,3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])"
|
||||
return this.matches(port.toRegex()) && this.toInt() in 1024..65535
|
||||
}
|
||||
//fun String.isValidPort(): Boolean {
|
||||
// val port = "([1-9]|[1-9]\\d{1,3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])"
|
||||
// return this.matches(port.toRegex()) && this.toInt() in 1024..65535
|
||||
//}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package com.rtbishop.look4sat.domain.utility
|
||||
|
||||
import com.rtbishop.look4sat.domain.predict.DEG2RAD
|
||||
import com.rtbishop.look4sat.domain.predict.PI
|
||||
import com.rtbishop.look4sat.domain.predict.RAD2DEG
|
||||
import kotlin.math.ln
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.sin
|
||||
|
||||
private const val MIN_LATITUDE = -85.05112877980658
|
||||
private const val MAX_LATITUDE = 85.05112877980658
|
||||
private const val MIN_LONGITUDE = -180.0
|
||||
private const val MAX_LONGITUDE = 180.0
|
||||
|
||||
fun Double.toDegrees(): Double = this * RAD2DEG
|
||||
|
||||
fun Double.toRadians(): Double = this * DEG2RAD
|
||||
|
||||
fun Double.latToY01(): Double {
|
||||
val sinus = sin(clipLat(this) * PI / MAX_LONGITUDE)
|
||||
return 0.5 - ln((1 + sinus) / (1 - sinus)) / (4 * PI)
|
||||
}
|
||||
|
||||
fun Double.lonToX01(): Double {
|
||||
return (clipLon(this) - MIN_LONGITUDE) / (MAX_LONGITUDE - MIN_LONGITUDE)
|
||||
}
|
||||
|
||||
//fun Double.y01ToLat(): Double {
|
||||
// return 90 - 360 * atan(exp((this - 0.5) * 2 * PI)) / PI
|
||||
//}
|
||||
|
||||
//fun Double.x01ToLon(): Double {
|
||||
// return MIN_LONGITUDE + (MAX_LONGITUDE - MIN_LONGITUDE) * this
|
||||
//}
|
||||
|
||||
private fun clipLat(latitude: Double): Double {
|
||||
return clip(latitude, MIN_LATITUDE, MAX_LATITUDE)
|
||||
}
|
||||
|
||||
private fun clipLon(longitude: Double): Double {
|
||||
var result = longitude
|
||||
while (result < MIN_LONGITUDE) result += 360.0
|
||||
while (result > MAX_LONGITUDE) result -= 360.0
|
||||
return clip(result, MIN_LONGITUDE, MAX_LONGITUDE)
|
||||
}
|
||||
|
||||
private fun clip(currentValue: Double, minValue: Double, maxValue: Double): Double {
|
||||
return min(max(currentValue, minValue), maxValue)
|
||||
}
|
|
@ -15,9 +15,9 @@
|
|||
* 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.data
|
||||
package com.rtbishop.look4sat.domain
|
||||
|
||||
import com.rtbishop.look4sat.data.repository.DataParser
|
||||
import com.rtbishop.look4sat.domain.utility.DataParser
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.runTest
|
||||
|
@ -49,12 +49,12 @@ class DataParserTest {
|
|||
1 25544U 98067A 21320.51955234 .00001288 00000+0 31985-4 0 9990
|
||||
2 25544 51.6447 309.4881 0004694 203.6966 299.8876 15.48582035312205
|
||||
""".trimIndent().byteInputStream()
|
||||
// private val validJSONStream = """
|
||||
// [{"uuid":"UzPz4gcsNBPKPKAFPmer7g","description":"Upper side band (drifting)","alive":true,"type":"Transmitter","uplink_low":null,"uplink_high":null,"uplink_drift":null,"downlink_low":136658500,"downlink_high":null,"downlink_drift":null,"mode":"USB","mode_id":9,"uplink_mode":null,"invert":false,"baud":null,"sat_id":"SCHX-0895-2361-9925-0309","norad_cat_id":965,"status":"active","updated":"2019-04-18T05:39:53.343316Z","citation":"CITATION NEEDED - https://xkcd.com/285/","service":"Unknown","coordination":"","coordination_url":""}]
|
||||
// """.trimIndent().byteInputStream()
|
||||
// private val invalidJSONStream = """
|
||||
// [{"description":"Upper side band (drifting)","alive":true,"type":"Transmitter","uplink_low":null,"uplink_high":null,"uplink_drift":null,"downlink_low":136658500,"downlink_high":null,"downlink_drift":null,"mode":"USB","mode_id":9,"uplink_mode":null,"invert":false,"baud":null,"sat_id":"SCHX-0895-2361-9925-0309","norad_cat_id":965,"status":"active","updated":"2019-04-18T05:39:53.343316Z","citation":"CITATION NEEDED - https://xkcd.com/285/","service":"Unknown","coordination":"","coordination_url":""}]
|
||||
// """.trimIndent().byteInputStream()
|
||||
private val validJSONStream = """
|
||||
[{"uuid":"UzPz4gcsNBPKPKAFPmer7g","description":"Upper side band (drifting)","alive":true,"type":"Transmitter","uplink_low":null,"uplink_high":null,"uplink_drift":null,"downlink_low":136658500,"downlink_high":null,"downlink_drift":null,"mode":"USB","mode_id":9,"uplink_mode":null,"invert":false,"baud":null,"sat_id":"SCHX-0895-2361-9925-0309","norad_cat_id":965,"status":"active","updated":"2019-04-18T05:39:53.343316Z","citation":"CITATION NEEDED - https://xkcd.com/285/","service":"Unknown","coordination":"","coordination_url":""}]
|
||||
""".trimIndent().byteInputStream()
|
||||
private val invalidJSONStream = """
|
||||
[{"description":"Upper side band (drifting)","alive":true,"type":"Transmitter","uplink_low":null,"uplink_high":null,"uplink_drift":null,"downlink_low":136658500,"downlink_high":null,"downlink_drift":null,"mode":"USB","mode_id":9,"uplink_mode":null,"invert":false,"baud":null,"sat_id":"SCHX-0895-2361-9925-0309","norad_cat_id":965,"status":"active","updated":"2019-04-18T05:39:53.343316Z","citation":"CITATION NEEDED - https://xkcd.com/285/","service":"Unknown","coordination":"","coordination_url":""}]
|
||||
""".trimIndent().byteInputStream()
|
||||
|
||||
@Test
|
||||
fun `Given valid CSV stream returns valid data`() = runTest(testDispatcher) {
|
||||
|
@ -87,15 +87,15 @@ class DataParserTest {
|
|||
assert(csvResult == tleResult)
|
||||
}
|
||||
|
||||
// @Test
|
||||
// fun `Given valid JSON stream returns valid data`() = runTest(testDispatcher) {
|
||||
// val parsedList = dataParser.parseJSONStream(validJSONStream)
|
||||
// assert(parsedList[0].downlink == 136658500L)
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// fun `Given invalid JSON stream returns empty list`() = runTest(testDispatcher) {
|
||||
// val parsedList = dataParser.parseJSONStream(invalidJSONStream)
|
||||
// assert(parsedList.isEmpty())
|
||||
// }
|
||||
@Test
|
||||
fun `Given valid JSON stream returns valid data`() = runTest(testDispatcher) {
|
||||
val parsedList = dataParser.parseJSONStream(validJSONStream)
|
||||
assert(parsedList[0].downlink == 136658500L)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Given invalid JSON stream returns empty list`() = runTest(testDispatcher) {
|
||||
val parsedList = dataParser.parseJSONStream(invalidJSONStream)
|
||||
assert(parsedList.isEmpty())
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue