kopia lustrzana https://github.com/rt-bishop/Look4Sat
Integrated fixes from release v3.1.4 (leap year bug)
rodzic
f131d8a728
commit
19ea5ebc47
|
@ -3,20 +3,20 @@ name: Look4Sat CI
|
|||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
- v**
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout latest commit
|
||||
uses: actions/checkout@v3
|
||||
- name: Checkout Latest Commit
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup java environment
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '11'
|
||||
java-version: '17'
|
||||
|
||||
- name: Assemble APK and Bundle
|
||||
run: |
|
||||
|
@ -34,7 +34,7 @@ jobs:
|
|||
alias: ${{ secrets.KEY_ALIAS }}
|
||||
keyPassword: ${{ secrets.KEY_PASSWORD }}
|
||||
env:
|
||||
BUILD_TOOLS_VERSION: "33.0.0"
|
||||
BUILD_TOOLS_VERSION: "34.0.0"
|
||||
|
||||
- name: Sign Bundle
|
||||
uses: r0adkll/sign-android-release@v1
|
||||
|
@ -46,25 +46,25 @@ jobs:
|
|||
alias: ${{ secrets.KEY_ALIAS }}
|
||||
keyPassword: ${{ secrets.KEY_PASSWORD }}
|
||||
env:
|
||||
BUILD_TOOLS_VERSION: "33.0.0"
|
||||
BUILD_TOOLS_VERSION: "34.0.0"
|
||||
|
||||
- name: Rename APK
|
||||
- name: Rename APK and Bundle
|
||||
run: |
|
||||
mv ${{steps.sign_apk.outputs.signedReleaseFile}} app/build/outputs/apk/release/look4sat.apk
|
||||
mv ${{steps.sign_bundle.outputs.signedReleaseFile}} app/build/outputs/apk/release/look4sat.aab
|
||||
|
||||
- name: Deploy Bundle to Play Store
|
||||
uses: r0adkll/upload-google-play@v1.0.17
|
||||
uses: r0adkll/upload-google-play@v1
|
||||
with:
|
||||
serviceAccountJsonPlainText: ${{secrets.SERVICE_ACCOUNT_JSON}}
|
||||
packageName: com.rtbishop.look4sat
|
||||
releaseFiles: app/build/outputs/apk/release/look4sat.aab
|
||||
track: production
|
||||
mappingFile: app/build/outputs/mapping/release/mapping.txt
|
||||
whatsNewDirectory: fastlane/metadata/android/en-US/whatsnew
|
||||
releaseFiles: ${{steps.sign_bundle.outputs.signedReleaseFile}}
|
||||
|
||||
- name: Create release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
artifacts: app/build/outputs/apk/release/look4sat.apk
|
||||
artifacts: "app/build/outputs/apk/release/look4sat.apk,app/build/outputs/apk/release/look4sat.aab"
|
||||
bodyFile: fastlane/metadata/android/en-US/whatsnew/whatsnew-en-US
|
||||
token: ${{ secrets.RELEASE_TOKEN }}
|
||||
|
|
|
@ -5,18 +5,18 @@ plugins {
|
|||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(libs.versions.jvmToolchain.get().toInt())
|
||||
jvmToolchain(17)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.rtbishop.look4sat"
|
||||
compileSdk = libs.versions.compileSdk.get().toInt()
|
||||
compileSdk = 34
|
||||
defaultConfig {
|
||||
applicationId = "com.rtbishop.look4sat"
|
||||
minSdk = libs.versions.minSdk.get().toInt()
|
||||
targetSdk = libs.versions.targetSdk.get().toInt()
|
||||
versionCode = libs.versions.versionCode.get().toInt()
|
||||
versionName = libs.versions.versionName.get()
|
||||
minSdk = 26
|
||||
targetSdk = 34
|
||||
versionCode = 314
|
||||
versionName = "3.1.4"
|
||||
resourceConfigurations.addAll(listOf("en", "ru", "si", "zh-rCN", "anydpi"))
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
|
@ -44,9 +43,10 @@ import com.rtbishop.look4sat.domain.predict.OrbitalData
|
|||
import com.rtbishop.look4sat.domain.predict.OrbitalPass
|
||||
import com.rtbishop.look4sat.presentation.MainTheme
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
private val sdf = SimpleDateFormat("HH:mm:ss", Locale.ENGLISH)
|
||||
private val sdfTime = SimpleDateFormat("HH:mm:ss", Locale.ENGLISH)
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
|
@ -105,11 +105,10 @@ fun NextPassRow(pass: OrbitalPass) {
|
|||
.background(color = MaterialTheme.colorScheme.surface)
|
||||
.padding(start = 6.dp, top = 1.dp, end = 6.dp, bottom = 0.dp)
|
||||
) {
|
||||
val passSatId = stringResource(id = R.string.pass_satId, pass.catNum)
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(
|
||||
text = "Id:${pass.catNum} - ",
|
||||
modifier = Modifier.width(82.dp),
|
||||
textAlign = TextAlign.End,
|
||||
text = "$passSatId - ",
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
Text(
|
||||
|
@ -139,23 +138,33 @@ fun NextPassRow(pass: OrbitalPass) {
|
|||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.pass_aosAz, pass.aosAzimuth),
|
||||
text = sdfTime.format(Date(pass.aosTime)),
|
||||
textAlign = TextAlign.Start,
|
||||
fontSize = 15.sp,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.pass_altitude, pass.altitude),
|
||||
text = stringResource(id = R.string.pass_aosLos, pass.aosAzimuth.toInt(), pass.losAzimuth.toInt()),
|
||||
textAlign = TextAlign.Center,
|
||||
fontSize = 15.sp,
|
||||
modifier = Modifier.weight(2f)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.pass_losAz, pass.losAzimuth),
|
||||
textAlign = TextAlign.End,
|
||||
fontSize = 15.sp,
|
||||
modifier = Modifier.weight(1f)
|
||||
modifier = Modifier.weight(1.5f)
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.weight(1f),
|
||||
horizontalArrangement = Arrangement.End,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_altitude),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(16.dp)
|
||||
)
|
||||
Text(
|
||||
text = " ${pass.altitude} km",
|
||||
textAlign = TextAlign.Start,
|
||||
fontSize = 15.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,8 +53,8 @@ fun TypesDialog(items: List<String>, selected: String, dismiss: () -> Unit, sele
|
|||
.background(MaterialTheme.colorScheme.surface)
|
||||
.clickable { select(item) }) {
|
||||
Text(
|
||||
text = "$index - ",
|
||||
modifier = Modifier.padding(start = 12.dp),
|
||||
text = "$index).",
|
||||
modifier = Modifier.padding(start = 12.dp, end = 6.dp),
|
||||
fontWeight = FontWeight.Normal,
|
||||
color = MaterialTheme.colorScheme.secondary
|
||||
)
|
||||
|
|
|
@ -33,7 +33,6 @@ import androidx.compose.ui.res.painterResource
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
@ -188,6 +187,7 @@ private fun EntryPreview() {
|
|||
|
||||
@Composable
|
||||
private fun Entry(item: SatItem, onSelected: (Int, Boolean) -> Unit, modifier: Modifier) {
|
||||
val passSatId = stringResource(id = R.string.pass_satId, item.catnum)
|
||||
Surface(color = MaterialTheme.colorScheme.background,
|
||||
modifier = modifier.clickable { onSelected(item.catnum, item.isSelected) }) {
|
||||
Surface(modifier = Modifier.padding(bottom = 1.dp)) {
|
||||
|
@ -195,12 +195,10 @@ private fun Entry(item: SatItem, onSelected: (Int, Boolean) -> Unit, modifier: M
|
|||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.background(MaterialTheme.colorScheme.surface)
|
||||
.padding(start = 0.dp, top = 8.dp, end = 12.dp, bottom = 8.dp)
|
||||
.padding(start = 14.dp, top = 8.dp, end = 12.dp, bottom = 8.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "Id:${item.catnum} - ",
|
||||
modifier = Modifier.width(104.dp),
|
||||
textAlign = TextAlign.End,
|
||||
text = "$passSatId - ",
|
||||
color = MaterialTheme.colorScheme.secondary
|
||||
)
|
||||
Text(
|
||||
|
|
|
@ -144,7 +144,7 @@ fun PassesDialog(hours: Int, elev: Double, dismiss: () -> Unit, save: (Int, Doub
|
|||
Slider(
|
||||
value = hoursValue.intValue.toFloat(),
|
||||
onValueChange = { hoursValue.intValue = it.toInt() },
|
||||
valueRange = 1f..96f,
|
||||
valueRange = 1f..240f,
|
||||
colors = SliderDefaults.colors(inactiveTrackColor = MaterialTheme.colorScheme.onSurfaceVariant)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.ElevatedCard
|
||||
|
@ -49,7 +48,8 @@ import java.text.SimpleDateFormat
|
|||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
private val sdf = SimpleDateFormat("HH:mm:ss", Locale.ENGLISH)
|
||||
private val sdfDate = SimpleDateFormat("EEE, dd MMM", Locale.ENGLISH)
|
||||
private val sdfTime = SimpleDateFormat("HH:mm:ss", Locale.ENGLISH)
|
||||
|
||||
@Composable
|
||||
fun PassesScreen(uiState: PassesState, navToRadar: (Int, Long) -> Unit) {
|
||||
|
@ -107,7 +107,7 @@ private fun DeepSpacePassPreview() {
|
|||
"Satellite", 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 45000, 0.0
|
||||
)
|
||||
val satellite = DeepSpaceObject(data)
|
||||
val pass = OrbitalPass(1L, 0.0, 10L, 180.0, 850, 45.0, satellite, 0.5f)
|
||||
val pass = OrbitalPass(1L, 180.0, 10L, 360.0, 36650, 45.0, satellite, 0.5f)
|
||||
MainTheme { PassItem(pass = pass, { _, _ -> }) }
|
||||
}
|
||||
|
||||
|
@ -118,27 +118,26 @@ private fun NearEarthPassPreview() {
|
|||
"Satellite", 0.0, 15.0, 0.0, 0.0, 0.0, 0.0, 0.0, 45000, 0.0
|
||||
)
|
||||
val satellite = NearEarthObject(data)
|
||||
val pass = OrbitalPass(1L, 0.0, 10L, 180.0, 850, 45.0, satellite, 0.5f)
|
||||
val pass = OrbitalPass(1L, 180.0, 10L, 360.0, 36650, 45.0, satellite, 0.5f)
|
||||
MainTheme { PassItem(pass = pass, { _, _ -> }) }
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PassItem(pass: OrbitalPass, navToRadar: (Int, Long) -> Unit, modifier: Modifier = Modifier) {
|
||||
val passSatId = stringResource(id = R.string.pass_satId, pass.catNum)
|
||||
Surface(color = MaterialTheme.colorScheme.background, modifier = modifier) {
|
||||
Surface(modifier = Modifier
|
||||
.padding(bottom = 2.dp)
|
||||
.clickable { navToRadar(pass.catNum, pass.aosTime) }) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(1.dp),
|
||||
modifier = Modifier
|
||||
.background(color = MaterialTheme.colorScheme.surface)
|
||||
.padding(horizontal = 6.dp, vertical = 4.dp)
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(
|
||||
text = "Id:${pass.catNum} - ",
|
||||
modifier = Modifier.width(82.dp),
|
||||
textAlign = TextAlign.End,
|
||||
text = "$passSatId - ",
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
Text(
|
||||
|
@ -168,23 +167,37 @@ private fun PassItem(pass: OrbitalPass, navToRadar: (Int, Long) -> Unit, modifie
|
|||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.pass_aosAz, pass.aosAzimuth),
|
||||
text = sdfDate.format(Date(pass.aosTime)),
|
||||
textAlign = TextAlign.Start,
|
||||
fontSize = 15.sp,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.pass_altitude, pass.altitude),
|
||||
text = stringResource(
|
||||
id = R.string.pass_aosLos,
|
||||
pass.aosAzimuth.toInt(),
|
||||
pass.losAzimuth.toInt()
|
||||
),
|
||||
textAlign = TextAlign.Center,
|
||||
fontSize = 15.sp,
|
||||
modifier = Modifier.weight(2f)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.pass_losAz, pass.losAzimuth),
|
||||
textAlign = TextAlign.End,
|
||||
fontSize = 15.sp,
|
||||
modifier = Modifier.weight(1f)
|
||||
modifier = Modifier.weight(1.5f)
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.weight(1f),
|
||||
horizontalArrangement = Arrangement.End,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_altitude),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(16.dp)
|
||||
)
|
||||
Text(
|
||||
text = " ${pass.altitude} km",
|
||||
textAlign = TextAlign.Start,
|
||||
fontSize = 15.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
|
@ -192,7 +205,10 @@ private fun PassItem(pass: OrbitalPass, navToRadar: (Int, Long) -> Unit, modifie
|
|||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
val defaultTime = " - - : - - "
|
||||
Text(text = if (pass.isDeepSpace) defaultTime else sdf.format(Date(pass.aosTime)), fontSize = 15.sp)
|
||||
Text(
|
||||
text = if (pass.isDeepSpace) defaultTime else sdfTime.format(Date(pass.aosTime)),
|
||||
fontSize = 15.sp
|
||||
)
|
||||
LinearProgressIndicator(
|
||||
progress = { if (pass.isDeepSpace) 100f else pass.progress },
|
||||
modifier = modifier
|
||||
|
@ -200,7 +216,10 @@ private fun PassItem(pass: OrbitalPass, navToRadar: (Int, Long) -> Unit, modifie
|
|||
.padding(top = 2.dp),
|
||||
trackColor = MaterialTheme.colorScheme.inverseSurface
|
||||
)
|
||||
Text(text = if (pass.isDeepSpace) defaultTime else sdf.format(Date(pass.losTime)), fontSize = 15.sp)
|
||||
Text(
|
||||
text = if (pass.isDeepSpace) defaultTime else sdfTime.format(Date(pass.losTime)),
|
||||
fontSize = 15.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,8 +120,8 @@ class RadarViewModel(
|
|||
if (settingsRepo.getRotatorState()) {
|
||||
val server = settingsRepo.getRotatorAddress()
|
||||
val port = settingsRepo.getRotatorPort().toInt()
|
||||
val azimuth = orbitalPos.azimuth.toDegrees().round(1)
|
||||
val elevation = orbitalPos.elevation.toDegrees().round(1)
|
||||
val azimuth = orbitalPos.azimuth.toDegrees().round(2)
|
||||
val elevation = orbitalPos.elevation.toDegrees().round(2)
|
||||
networkReporter.reportRotation(server, port, azimuth, elevation)
|
||||
}
|
||||
radarData.value = RadarData(orbitalPass, orbitalPos, track)
|
||||
|
|
|
@ -133,14 +133,15 @@ private fun CardAbout(version: String, modifier: Modifier = Modifier) {
|
|||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
|
||||
) {
|
||||
Row(horizontalArrangement = Arrangement.Center) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_sputnik),
|
||||
tint = MaterialTheme.colorScheme.secondary,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(96.dp)
|
||||
.padding(top = 8.dp, end = 8.dp)
|
||||
modifier = Modifier.size(72.dp)
|
||||
)
|
||||
Column {
|
||||
Text(
|
||||
|
@ -436,8 +437,8 @@ private fun UpdateIndicator(isUpdating: Boolean, modifier: Modifier = Modifier)
|
|||
)
|
||||
} else {
|
||||
LinearProgressIndicator(
|
||||
progress = 0f,
|
||||
progress = { 0f },
|
||||
modifier = modifier.padding(start = 6.dp),
|
||||
trackColor = MaterialTheme.colorScheme.inverseSurface
|
||||
trackColor = MaterialTheme.colorScheme.inverseSurface,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -75,8 +75,9 @@
|
|||
<string name="passes_empty_db">No data to show. Please update the database via Settings menu.</string>
|
||||
|
||||
<string name="pass_satName">%s</string>
|
||||
<string name="pass_satId">Id:%d</string>
|
||||
<string name="pass_satId">Id:%05d</string>
|
||||
<string name="pass_aosAz">AOS - %.1f°</string>
|
||||
<string name="pass_aosLos" translatable="false">Az: %03d° -> Az: %03d°</string>
|
||||
<string name="pass_elevation">Elevation: %.1f°</string>
|
||||
<string name="pass_losAz">%.1f° - LOS</string>
|
||||
<string name="pass_altitude">Altitude: %d km</string>
|
||||
|
|
|
@ -5,14 +5,14 @@ plugins {
|
|||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(libs.versions.jvmToolchain.get().toInt())
|
||||
jvmToolchain(17)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.rtbishop.look4sat.data"
|
||||
compileSdk = libs.versions.compileSdk.get().toInt()
|
||||
compileSdk = 34
|
||||
defaultConfig {
|
||||
minSdk = libs.versions.minSdk.get().toInt()
|
||||
minSdk = 26
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,13 @@
|
|||
*/
|
||||
package com.rtbishop.look4sat.data.framework
|
||||
|
||||
import java.net.InetSocketAddress
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.channels.SocketChannel
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.cancelAndJoin
|
||||
import kotlinx.coroutines.launch
|
||||
import java.net.InetSocketAddress
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.channels.SocketChannel
|
||||
|
||||
class NetworkReporter(private val reporterScope: CoroutineScope) {
|
||||
|
||||
|
@ -56,7 +56,7 @@ class NetworkReporter(private val reporterScope: CoroutineScope) {
|
|||
if (rotationSocketChannel == null) {
|
||||
rotationSocketChannel = SocketChannel.open(InetSocketAddress(server, port))
|
||||
} else {
|
||||
val buffer = ByteBuffer.wrap("\\set_pos $azimuth $elevation\n".toByteArray())
|
||||
val buffer = ByteBuffer.wrap("\\P $azimuth $elevation\n".toByteArray())
|
||||
rotationSocketChannel?.write(buffer)
|
||||
}
|
||||
}.onFailure { error ->
|
||||
|
|
|
@ -74,6 +74,7 @@ class LocalSource(private val look4SatDao: Look4SatDao) : ILocalSource {
|
|||
}
|
||||
|
||||
override suspend fun insertRadios(radios: List<SatRadio>) {
|
||||
look4SatDao.deleteRadios()
|
||||
look4SatDao.insertRadios(radios.toFrameworkRadios())
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ plugins {
|
|||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(libs.versions.jvmToolchain.get().toInt())
|
||||
jvmToolchain(17)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.rtbishop.look4sat.domain.source
|
||||
|
||||
object Sources {
|
||||
const val radioDataUrl = "https://db.satnogs.org/api/transmitters/?format=json"
|
||||
const val radioDataUrl = "https://db.satnogs.org/api/transmitters/?format=json&status=active"
|
||||
val satelliteDataUrls = mapOf(
|
||||
"All" to "https://celestrak.org/NORAD/elements/gp.php?GROUP=active&FORMAT=csv",
|
||||
"Amsat" to "https://amsat.org/tle/current/nasabare.txt",
|
||||
|
|
|
@ -74,6 +74,10 @@ class DataParser(private val dispatcher: CoroutineDispatcher) {
|
|||
}
|
||||
}
|
||||
|
||||
fun isLeapYear(year: Int): Boolean {
|
||||
return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)
|
||||
}
|
||||
|
||||
private fun parseCSV(values: List<String>): OrbitalData? = try {
|
||||
val name = values[0]
|
||||
val year = values[2].substring(0, 4)
|
||||
|
@ -101,16 +105,6 @@ class DataParser(private val dispatcher: CoroutineDispatcher) {
|
|||
null
|
||||
}
|
||||
|
||||
private fun getDayOfYear(year: Int, month: Int, dayOfMonth: Int): Int {
|
||||
if (month == 1) return dayOfMonth
|
||||
val daysArray = arrayOf(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
|
||||
var dayOfYear = dayOfMonth
|
||||
// If leap year increment Feb days
|
||||
if (((year / 4 == 0) && (year / 100 != 0)) || (year / 400 == 0)) daysArray[1]++
|
||||
for (i in 0 until month - 1) dayOfYear += daysArray[i]
|
||||
return dayOfYear
|
||||
}
|
||||
|
||||
private fun parseTLE(tle: List<String>): OrbitalData? = try {
|
||||
val name: String = tle[0].trim()
|
||||
val epoch: Double = tle[1].substring(18, 32).toDouble()
|
||||
|
@ -145,4 +139,16 @@ class DataParser(private val dispatcher: CoroutineDispatcher) {
|
|||
println("JSON parsing exception: $exception")
|
||||
null
|
||||
}
|
||||
|
||||
private fun getDayOfYear(year: Int, month: Int, dayOfMonth: Int): Int {
|
||||
if (month == 1) return dayOfMonth
|
||||
val daysArray = arrayOf(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
|
||||
var dayOfYear = dayOfMonth
|
||||
// If leap year increment Feb days
|
||||
if (isLeapYear(year)) daysArray[1]++
|
||||
for (i in 0 until month - 1) {
|
||||
dayOfYear += daysArray[i]
|
||||
}
|
||||
return dayOfYear
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ class DataParserTest {
|
|||
private val validCSVStream = """
|
||||
OBJECT_NAME,OBJECT_ID,EPOCH,MEAN_MOTION,ECCENTRICITY,INCLINATION,RA_OF_ASC_NODE,ARG_OF_PERICENTER,MEAN_ANOMALY,EPHEMERIS_TYPE,CLASSIFICATION_TYPE,NORAD_CAT_ID,ELEMENT_SET_NO,REV_AT_EPOCH,BSTAR,MEAN_MOTION_DOT,MEAN_MOTION_DDOT
|
||||
ISS (ZARYA),1998-067A,2021-11-16T12:28:09.322176,15.48582035,.0004694,51.6447,309.4881,203.6966,299.8876,0,U,25544,999,31220,.31985E-4,.1288E-4,0
|
||||
ISS (ZARYA),1998-067A,2024-03-09T05:45:04.737024,15.49756209,.0005741,51.6418,90.7424,343.9724,92.8274,0,U,25544,999,44305,.25016E-3,.1373E-3,0
|
||||
""".trimIndent().byteInputStream()
|
||||
private val invalidCSVStream = """
|
||||
ISS (ZARYA),1998-067A,2021-11-16T12:28:09.322176,15.48582035,.0004694,51.6447,309.4881,203.6966,299.8876,0,U,25544,999,31220,.31985E-4,.1288E-4,0
|
||||
|
@ -40,6 +41,9 @@ class DataParserTest {
|
|||
ISS (ZARYA)
|
||||
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
|
||||
ISS (ZARYA)
|
||||
1 25544U 98067A 24069.23963816 .00013730 00000+0 25016-3 0 9999
|
||||
2 25544 51.6418 90.7424 0005741 343.9724 92.8274 15.49756209443058
|
||||
""".trimIndent().byteInputStream()
|
||||
private val invalidTLEStream = """
|
||||
1 25544U 98067A 21320.51955234 .00001288 00000+0 31985-4 0 9990
|
||||
|
@ -54,7 +58,9 @@ class DataParserTest {
|
|||
|
||||
@Test
|
||||
fun `Given valid CSV stream returns valid data`() = runTest(testDispatcher) {
|
||||
assert(dataParser.parseCSVStream(validCSVStream)[0].epoch == 21320.51955234)
|
||||
val parsedList = dataParser.parseCSVStream(validCSVStream)
|
||||
assert(parsedList[0].epoch == 21320.51955234)
|
||||
assert(parsedList[1].epoch == 24069.23963816)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -64,7 +70,9 @@ class DataParserTest {
|
|||
|
||||
@Test
|
||||
fun `Given valid TLE stream returns valid data`() = runTest(testDispatcher) {
|
||||
assert(dataParser.parseTLEStream(validTLEStream)[0].epoch == 21320.51955234)
|
||||
val parsedList = dataParser.parseTLEStream(validTLEStream)
|
||||
assert(parsedList[0].epoch == 21320.51955234)
|
||||
assert(parsedList[1].epoch == 24069.23963816)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -86,4 +94,12 @@ class DataParserTest {
|
|||
fun `Given valid data streams parsed results match`() = runTest(testDispatcher) {
|
||||
assert(dataParser.parseCSVStream(validCSVStream) == dataParser.parseTLEStream(validTLEStream))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Function isLeapYear returns correct data`() = runTest(testDispatcher) {
|
||||
val years = listOf(1900, 1984, 1994, 2016, 2022, 2024, 2042, 2048)
|
||||
val answers = listOf(false, true, false, true, false, true, false, true)
|
||||
val results = years.map { dataParser.isLeapYear(it) }
|
||||
assert(results == answers)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Aligned ROTCTL command with Gpredict #121
|
||||
Added ingoring inactive transmitters #125
|
||||
Fixed the satellite predictions bug #126
|
||||
Added date to a satellite pass ENG #127
|
|
@ -1 +1,4 @@
|
|||
Fixed the satellite data update bug #108
|
||||
Aligned ROTCTL command with Gpredict #121
|
||||
Added ingoring inactive transmitters #125
|
||||
Fixed the satellite predictions bug #126
|
||||
Added date to a satellite pass ENG #127
|
|
@ -3,23 +3,15 @@ android-gradle-plugin = "8.3.0"
|
|||
google-ksp = "1.9.22-1.0.17"
|
||||
kotlin = "1.9.22"
|
||||
|
||||
jvmToolchain = "17"
|
||||
|
||||
minSdk = "26"
|
||||
targetSdk = "34"
|
||||
compileSdk = "34"
|
||||
versionCode = "313"
|
||||
versionName = "3.1.3"
|
||||
|
||||
androidx-core-ktx = "1.12.0"
|
||||
androidx-core-splashscreen = "1.0.1"
|
||||
androidx-room = "2.6.1"
|
||||
|
||||
compose = "1.6.2"
|
||||
compose = "1.6.3"
|
||||
compose-activity = "1.8.2"
|
||||
compose-compiler = "1.5.10"
|
||||
compose-lifecycle = "2.7.0"
|
||||
compose-material3 = "1.2.0"
|
||||
compose-material3 = "1.2.1"
|
||||
compose-navigation = "2.7.7"
|
||||
|
||||
other-coroutines = "1.7.3"
|
||||
|
@ -28,7 +20,7 @@ other-okhttp = "4.12.0"
|
|||
other-osmdroid = "6.1.17"
|
||||
|
||||
test-junit4 = "4.13.2"
|
||||
test-mockk = "1.13.8"
|
||||
test-mockk = "1.13.9"
|
||||
|
||||
androidTest-junit = "1.1.5"
|
||||
androidTest-espresso = "3.5.1"
|
||||
|
|
Ładowanie…
Reference in New Issue