diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index b06f8efd..9a5a9c50 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -4,10 +4,15 @@ on:
push:
tags:
- v**
+ workflow_dispatch:
+ inputs:
+ tag_name:
+ description: 'Release tag name (e.g. v4.4.3)'
+ required: false
+ default: ''
env:
- TAG_NAME: ${{ github.ref_name }}
- GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
+ TAG_NAME: ${{ github.event.inputs.tag_name || github.ref_name }}
jobs:
release:
@@ -16,66 +21,40 @@ jobs:
contents: write
steps:
- name: Checkout Repository
- uses: actions/checkout@v7
+ uses: actions/checkout@v4
- name: Setup Java
- uses: actions/setup-java@v5
+ uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
- name: Setup Gradle
- uses: gradle/actions/setup-gradle@v6
+ uses: gradle/actions/setup-gradle@v4
- - name: Assemble Artifacts
- run: ./gradlew assembleRelease bundleRelease
+ - name: Assemble APK
+ run: ./gradlew assembleRelease
- name: Sign APK
run: |
echo "${{ secrets.KEY_STORE }}" | base64 -d > keystore.jks
APK=$(find app/build/outputs/apk/release -name "*.apk" | head -1)
+ VERSION=${TAG_NAME#v}
+ SIGNED_APK="app/build/outputs/apk/release/Look4Sat-Pro-${VERSION}.apk"
BUILD_TOOLS=$(ls -d ${ANDROID_HOME}/build-tools/*/ | sort -V | tail -1)
${BUILD_TOOLS}apksigner sign \
--ks keystore.jks \
--ks-pass pass:${{ secrets.KEY_STORE_PASSWORD }} \
--ks-key-alias ${{ secrets.KEY_ALIAS }} \
--key-pass pass:${{ secrets.KEY_PASSWORD }} \
- --out app/build/outputs/apk/release/look4sat.apk \
+ --out "$SIGNED_APK" \
"$APK"
rm keystore.jks
-
- - name: Sign Bundle
- run: |
- echo "${{ secrets.KEY_STORE }}" | base64 -d > keystore.jks
- AAB=$(find app/build/outputs/bundle/release -name "*.aab" | head -1)
- jarsigner -verbose -sigalg SHA256withRSA -digestalg SHA-256 \
- -keystore keystore.jks \
- -storepass ${{ secrets.KEY_STORE_PASSWORD }} \
- -keypass ${{ secrets.KEY_PASSWORD }} \
- "$AAB" ${{ secrets.KEY_ALIAS }}
- rm keystore.jks
-
- - name: Setup Ruby
- uses: ruby/setup-ruby@v1
- with:
- ruby-version: '3.4'
-
- - name: Deploy Bundle to Google Play
- run: |
- gem install multi_json
- gem install fastlane --no-document
- AAB=$(find app/build/outputs/bundle/release -name "*.aab" | head -1)
- echo '${{ secrets.SERVICE_ACCOUNT_JSON }}' > service_account.json
- fastlane supply \
- --aab "$AAB" \
- --json_key service_account.json \
- --package_name com.rtbishop.look4sat \
- --track production \
- --skip_upload_images true \
- --skip_upload_screenshots true \
- rm service_account.json
+ echo "SIGNED_APK=$SIGNED_APK" >> "$GITHUB_ENV"
- name: Create Release
+ env:
+ GH_TOKEN: ${{ github.token }}
run: |
gh release create $TAG_NAME --title=$TAG_NAME --generate-notes
- gh release upload $TAG_NAME app/build/outputs/apk/release/look4sat.apk
+ gh release upload $TAG_NAME "$SIGNED_APK"
diff --git a/.gitignore b/.gitignore
index a3196c82..07d4b106 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,8 +39,7 @@ captures/
.idea/
# Keystore files
-# Uncomment the following line if you do not want to check your keystore files in.
-#*.jks
+*.jks
/*.properties
/keystore.properties
/app/keystore.jks
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 1199060a..9d1381c3 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,3 +1,36 @@
+import java.util.Properties
+
plugins {
alias(libs.plugins.convention.applicationPlugin)
}
+
+// Load signing config from keystore.properties (gitignored, never commit credentials)
+val keystoreProperties = Properties().apply {
+ val propsFile = rootProject.file("keystore.properties")
+ if (propsFile.exists()) propsFile.inputStream().use { load(it) }
+}
+
+android {
+ // CW 解码 native 库仅 armeabi-v7a(照搬 Morse Expert 1.15): 全 ABI 打包会在
+ // arm64 设备 loadLibrary 失败, 强制 32 位兼容(用户设备为 32 位软件)
+ defaultConfig {
+ ndk {
+ abiFilters += listOf("armeabi-v7a")
+ }
+ }
+ signingConfigs {
+ if (keystoreProperties["storeFile"] != null) {
+ create("release") {
+ storeFile = rootProject.file(keystoreProperties["storeFile"] as String)
+ storePassword = keystoreProperties["storePassword"] as String
+ keyAlias = keystoreProperties["keyAlias"] as String
+ keyPassword = keystoreProperties["keyPassword"] as String
+ }
+ }
+ }
+ buildTypes {
+ release {
+ signingConfig = signingConfigs.findByName("release")
+ }
+ }
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 25895b98..a57d1d1c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -43,7 +43,7 @@
+ android:value="com.rtbishop.look4sat.bg7nta" />
diff --git a/app/src/main/java/com/rtbishop/look4sat/MainScreen.kt b/app/src/main/java/com/rtbishop/look4sat/MainScreen.kt
index c549f558..009e0ac2 100644
--- a/app/src/main/java/com/rtbishop/look4sat/MainScreen.kt
+++ b/app/src/main/java/com/rtbishop/look4sat/MainScreen.kt
@@ -17,16 +17,23 @@
*/
package com.rtbishop.look4sat
+import androidx.activity.compose.BackHandler
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.RepeatMode
+import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
+import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
+import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
+import androidx.compose.animation.shrinkVertically
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.togetherWith
@@ -53,6 +60,9 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -80,11 +90,15 @@ import com.rtbishop.look4sat.core.presentation.RadarDestination
import com.rtbishop.look4sat.core.presentation.Screen
import com.rtbishop.look4sat.core.presentation.hasEnoughHeight
import com.rtbishop.look4sat.core.presentation.hasEnoughWidth
+import com.rtbishop.look4sat.feature.cw.CwDecodeScreen
import com.rtbishop.look4sat.feature.map.MapDestination
import com.rtbishop.look4sat.feature.mutual.MutualScreen
import com.rtbishop.look4sat.feature.mutual.MutualViewModel
import com.rtbishop.look4sat.feature.passes.PassesDestination
import com.rtbishop.look4sat.feature.radar.RadarDestination
+import com.rtbishop.look4sat.feature.radar.WavelogLogScreen
+import com.rtbishop.look4sat.feature.status.SatStatusScreen
+import com.rtbishop.look4sat.feature.roaming.RoamingScreen
import com.rtbishop.look4sat.feature.satellites.SatellitesDestination
import com.rtbishop.look4sat.feature.settings.SettingsDestination
@@ -130,12 +144,35 @@ fun MainScreen(navigateToRadar: () -> Unit = {}) {
val currentKey = backStack.lastOrNull()
val navigateBack: () -> Unit = { backStack.removeLastOrNull() }
val fadeTransition = fadeIn(animationSpec = tween(350)) togetherWith fadeOut(animationSpec = tween(350))
- val navItems = listOf(Screen.Satellites, Screen.Passes, Screen.Radar, Screen.Mutual, Screen.Map, Screen.Settings)
-
val context = LocalContext.current
val container = (context.applicationContext as IContainerProvider).getMainContainer()
val trackingState by container.radioTrackingService.state.collectAsStateWithLifecycle()
val otherSettings by container.settingsRepo.otherSettings.collectAsStateWithLifecycle()
+ // UI 设置: 按 screenOrder 排序(空 = 默认顺序), 再按 hiddenScreens 过滤(设置页固定保留)
+ val allNavItems = listOf(Screen.Satellites, Screen.Passes, Screen.Radar, Screen.Mutual, Screen.Roaming, Screen.CwDecode, Screen.WavelogLog, Screen.AmSat, Screen.Map, Screen.Settings)
+ .sortedBy { screen ->
+ // 未知(新页面如 CwDecode 不在旧持久化顺序里): 用默认顺序位置(漫游↔地图), 再兜底最后
+ val idx = otherSettings.screenOrder.indexOf(screen.screenId)
+ if (idx != -1) idx
+ else com.rtbishop.look4sat.core.presentation.defaultScreenOrder.indexOf(screen.screenId).let {
+ if (it != -1) it else Int.MAX_VALUE
+ }
+ }
+ .filter { it.screenId !in otherSettings.hiddenScreens || it is Screen.Settings }
+ // 4.5.1 折叠菜单: 主菜单(底部栏 5 槽) + 更多菜单(溢出页面)
+ // 老用户迁移: 已持久化的 subMenuOrder 不含新页面 WavelogLog → 追加到子菜单尾部
+ val subOrder = (otherSettings.subMenuOrder.ifEmpty { com.rtbishop.look4sat.core.presentation.defaultSubMenuOrder })
+ .let { list -> if ("WavelogLog" in list) list else list + "WavelogLog" }
+ .let { list -> if ("AMSAT" in list) list else list + "AMSAT" }
+ val mainNavItems = remember(allNavItems, subOrder) {
+ allNavItems.filter { it.screenId !in subOrder }.take(5)
+ }
+ val moreNavItems = remember(allNavItems, subOrder) {
+ subOrder.mapNotNull { id -> allNavItems.find { it.screenId == id } }
+ }
+ var moreExpanded by remember { mutableStateOf(false) }
+ // 更多菜单打开时拦截返回: 先关菜单
+ BackHandler(enabled = moreExpanded) { moreExpanded = false }
// Activity-scoped so the mutual query results survive navigation to Radar and back
val mutualViewModel: MutualViewModel = viewModel(
viewModelStoreOwner = context as ViewModelStoreOwner,
@@ -150,12 +187,15 @@ fun MainScreen(navigateToRadar: () -> Unit = {}) {
) {
NavigationSuiteScaffold(
navigationSuiteItems = {
- navItems.forEach { screen ->
+ mainNavItems.forEach { screen ->
val isSelected = when (currentKey) {
is Screen.Satellites -> screen is Screen.Satellites
is Screen.Passes -> screen is Screen.Passes
is Screen.Radar -> screen is Screen.Radar
is Screen.Mutual -> screen is Screen.Mutual
+ is Screen.CwDecode -> screen is Screen.CwDecode
+ is Screen.WavelogLog -> screen is Screen.WavelogLog
+ is Screen.AmSat -> screen is Screen.AmSat
is Screen.Map -> screen is Screen.Map
is Screen.Settings -> screen is Screen.Settings
else -> false
@@ -166,11 +206,26 @@ fun MainScreen(navigateToRadar: () -> Unit = {}) {
selected = isSelected,
onClick = {
if (isSelected) return@item
+ moreExpanded = false
while (backStack.size > 1) backStack.removeAt(backStack.size - 1)
if (screen !is Screen.Passes) backStack.add(screen)
}
)
}
+ // 更多菜单按钮(固定第 6 槽, 子菜单非空才显示)
+ if (moreNavItems.isNotEmpty()) {
+ item(
+ icon = {
+ Icon(
+ painterResource(com.rtbishop.look4sat.R.drawable.ic_more),
+ stringResource(com.rtbishop.look4sat.core.presentation.R.string.nav_more)
+ )
+ },
+ label = { Text(stringResource(com.rtbishop.look4sat.core.presentation.R.string.nav_more)) },
+ selected = moreExpanded,
+ onClick = { moreExpanded = !moreExpanded }
+ )
+ }
},
navigationSuiteColors = NavigationSuiteDefaults.colors(
navigationRailContainerColor = MaterialTheme.colorScheme.surfaceContainer
@@ -181,103 +236,137 @@ fun MainScreen(navigateToRadar: () -> Unit = {}) {
else -> NavigationSuiteType.ShortNavigationBarMedium
}
) {
- Column {
- NavDisplay(
- backStack = backStack,
- modifier = Modifier.weight(1f),
- onBack = navigateBack,
- transitionSpec = { fadeTransition },
- popTransitionSpec = { fadeTransition },
- predictivePopTransitionSpec = { fadeTransition },
- entryDecorators = listOf(
- // Required for saving Compose state per entry
- rememberSaveableStateHolderNavEntryDecorator(),
- // Required for ViewModel scoping per entry
- rememberViewModelStoreNavEntryDecorator()
- ),
- entryProvider = entryProvider {
- entry {
- SatellitesDestination(navigateUp = navigateBack)
- }
- entry {
- PassesDestination { catNum, aosTime ->
- container.setMutualPassData(MutualPassData())
- container.satelliteRepo.selectPass(catNum, aosTime)
- backStack.add(Screen.Radar)
-// navigateToRadar()
+ Box {
+ Column(modifier = Modifier.fillMaxSize()) {
+ NavDisplay(
+ backStack = backStack,
+ modifier = Modifier.weight(1f).fillMaxWidth(),
+ onBack = navigateBack,
+ transitionSpec = { fadeTransition },
+ popTransitionSpec = { fadeTransition },
+ predictivePopTransitionSpec = { fadeTransition },
+ entryDecorators = listOf(
+ // Required for saving Compose state per entry
+ rememberSaveableStateHolderNavEntryDecorator(),
+ // Required for ViewModel scoping per entry
+ rememberViewModelStoreNavEntryDecorator()
+ ),
+ entryProvider = entryProvider {
+ entry {
+ SatellitesDestination(navigateUp = navigateBack)
}
- }
- entry {
- RadarDestination(navigateUp = navigateBack)
- }
- entry {
- MapDestination()
- }
- entry {
- MutualScreen(
- viewModel = mutualViewModel,
- navigateUp = navigateBack,
- navigateToRadar = { catNum, aosTime, pass ->
- container.setMutualPassData(pass ?: MutualPassData())
+ entry {
+ PassesDestination { catNum, aosTime ->
+ container.setMutualPassData(MutualPassData())
container.satelliteRepo.selectPass(catNum, aosTime)
backStack.add(Screen.Radar)
- }
- )
- }
- entry {
- SettingsDestination()
- }
- }
- )
- // Radio tracking status banner
- if (trackingState.isActive) {
- val infiniteTransition = rememberInfiniteTransition(label = "trackingPulse")
- val alpha by infiniteTransition.animateFloat(
- initialValue = 1f, targetValue = 0.4f,
- animationSpec = infiniteRepeatable(
- animation = tween(1000, easing = LinearEasing),
- repeatMode = RepeatMode.Reverse
- ), label = "pulseAlpha"
- )
- Row(
- verticalAlignment = Alignment.CenterVertically,
- modifier = Modifier
- .fillMaxWidth()
- .background(MaterialTheme.colorScheme.primaryContainer)
- .clickable {
- val pass = trackingState.currentPass
- if (pass != null) {
- container.setMutualPassData(MutualPassData())
- container.satelliteRepo.selectPass(pass.catNum, pass.aosTime)
- backStack.add(Screen.Radar)
+ // navigateToRadar()
}
}
- .padding(horizontal = 12.dp, vertical = 6.dp)
- ) {
- Box(
+ entry {
+ RadarDestination(navigateUp = navigateBack)
+ }
+ entry {
+ MapDestination()
+ }
+ entry {
+ MutualScreen(
+ viewModel = mutualViewModel,
+ navigateUp = navigateBack,
+ navigateToRadar = { catNum, aosTime, pass ->
+ container.setMutualPassData(pass ?: MutualPassData())
+ container.satelliteRepo.selectPass(catNum, aosTime)
+ backStack.add(Screen.Radar)
+ }
+ )
+ }
+ entry {
+ RoamingScreen()
+ }
+ entry {
+ CwDecodeScreen()
+ }
+ entry {
+ SatStatusScreen(container = container)
+ }
+ entry {
+ WavelogLogScreen(queue = container.wavelogQueue)
+ }
+ entry {
+ SettingsDestination()
+ }
+ }
+ )
+ // Radio tracking status banner
+ if (trackingState.isActive) {
+ val infiniteTransition = rememberInfiniteTransition(label = "trackingPulse")
+ val alpha by infiniteTransition.animateFloat(
+ initialValue = 1f, targetValue = 0.4f,
+ animationSpec = infiniteRepeatable(
+ animation = tween(1000, easing = LinearEasing),
+ repeatMode = RepeatMode.Reverse
+ ), label = "pulseAlpha"
+ )
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
- .size(8.dp)
- .clip(CircleShape)
- .background(Color(0xFF4CAF50).copy(alpha = alpha))
- )
- Spacer(modifier = Modifier.width(8.dp))
- Text(
- text = "Tracking: ${trackingState.currentPass?.name ?: ""}",
- fontSize = 13.sp,
- fontWeight = FontWeight.Medium,
- color = MaterialTheme.colorScheme.onPrimaryContainer,
- modifier = Modifier.weight(1f)
- )
- val txOk = if (trackingState.txConnected) "TX" else ""
- val rxOk = if (trackingState.rxConnected) "RX" else ""
- Text(
- text = listOf(txOk, rxOk).filter { it.isNotBlank() }.joinToString("/"),
- fontSize = 12.sp,
- color = MaterialTheme.colorScheme.onPrimaryContainer
- )
+ .fillMaxWidth()
+ .background(MaterialTheme.colorScheme.primaryContainer)
+ .clickable {
+ val pass = trackingState.currentPass
+ if (pass != null) {
+ container.setMutualPassData(MutualPassData())
+ container.satelliteRepo.selectPass(pass.catNum, pass.aosTime)
+ backStack.add(Screen.Radar)
+ }
+ }
+ .padding(horizontal = 12.dp, vertical = 6.dp)
+ ) {
+ Box(
+ modifier = Modifier
+ .size(8.dp)
+ .clip(CircleShape)
+ .background(Color(0xFF4CAF50).copy(alpha = alpha))
+ )
+ Spacer(modifier = Modifier.width(8.dp))
+ Text(
+ text = stringResource(com.rtbishop.look4sat.core.presentation.R.string.tracking_status, trackingState.currentPass?.name ?: ""),
+ fontSize = 13.sp,
+ fontWeight = FontWeight.Medium,
+ color = MaterialTheme.colorScheme.onPrimaryContainer,
+ modifier = Modifier.weight(1f)
+ )
+ val txOk = if (trackingState.txConnected) "TX" else ""
+ val rxOk = if (trackingState.rxConnected) "RX" else ""
+ Text(
+ text = listOf(txOk, rxOk).filter { it.isNotBlank() }.joinToString("/"),
+ fontSize = 12.sp,
+ color = MaterialTheme.colorScheme.onPrimaryContainer
+ )
+ }
}
}
+ // 更多菜单弹出面板(覆盖在内容上, 底部栏上方; spring 弹跳)
+ AnimatedVisibility(
+ visible = moreExpanded,
+ modifier = Modifier.fillMaxSize(),
+ enter = expandVertically(
+ animationSpec = spring(dampingRatio = Spring.DampingRatioMediumBouncy)
+ ) + fadeIn(),
+ exit = shrinkVertically() + fadeOut()
+ ) {
+ MoreMenuPopup(
+ items = moreNavItems,
+ currentKey = currentKey,
+ onDismiss = { moreExpanded = false },
+ onSelect = { screen ->
+ moreExpanded = false
+ while (backStack.size > 1) backStack.removeAt(backStack.size - 1)
+ if (screen !is Screen.Passes) backStack.add(screen)
+ }
+ )
+ }
}
}
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/rtbishop/look4sat/MoreMenuPopup.kt b/app/src/main/java/com/rtbishop/look4sat/MoreMenuPopup.kt
new file mode 100644
index 00000000..8b90d581
--- /dev/null
+++ b/app/src/main/java/com/rtbishop/look4sat/MoreMenuPopup.kt
@@ -0,0 +1,106 @@
+/*
+ * MoreMenuPopup.kt — 底部导航「更多」二级菜单弹出面板(4.5.1)。
+ *
+ * 覆盖在内容区上(底部栏上方, 右对齐), 竖排菜单项(图标+文本+箭头),
+ * 当前页高亮; 点击遮罩关闭, 点击项跳转。弹出/收起动画由调用处
+ * (MainScreen 的 AnimatedVisibility + spring)驱动。
+ */
+package com.rtbishop.look4sat
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+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.shape.RoundedCornerShape
+import androidx.compose.material3.Card
+import androidx.compose.material3.CardDefaults
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.navigation3.runtime.NavKey
+import com.rtbishop.look4sat.core.presentation.Screen
+
+@Composable
+fun MoreMenuPopup(
+ items: List,
+ currentKey: NavKey?,
+ onDismiss: () -> Unit,
+ onSelect: (Screen) -> Unit
+) {
+ Box(
+ modifier = Modifier
+ .fillMaxSize()
+ .background(MaterialTheme.colorScheme.scrim.copy(alpha = 0.35f))
+ .clickable(onClick = onDismiss)
+ ) {
+ Card(
+ modifier = Modifier
+ .align(Alignment.BottomEnd)
+ .padding(12.dp),
+ shape = RoundedCornerShape(12.dp),
+ colors = CardDefaults.cardColors(
+ containerColor = MaterialTheme.colorScheme.surfaceContainerHigh
+ )
+ ) {
+ Column(modifier = Modifier.padding(vertical = 4.dp)) {
+ items.forEach { screen ->
+ val isSelected = when (currentKey) {
+ is Screen.Satellites -> screen is Screen.Satellites
+ is Screen.Passes -> screen is Screen.Passes
+ is Screen.Radar -> screen is Screen.Radar
+ is Screen.Mutual -> screen is Screen.Mutual
+ is Screen.CwDecode -> screen is Screen.CwDecode
+ is Screen.WavelogLog -> screen is Screen.WavelogLog
+ is Screen.Map -> screen is Screen.Map
+ is Screen.Settings -> screen is Screen.Settings
+ else -> false
+ }
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier
+ .fillMaxWidth()
+ .clickable { onSelect(screen) }
+ .padding(horizontal = 16.dp, vertical = 12.dp)
+ ) {
+ Icon(
+ painter = painterResource(screen.iconResId),
+ contentDescription = stringResource(screen.titleResId),
+ tint = if (isSelected) MaterialTheme.colorScheme.primary
+ else MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.size(20.dp)
+ )
+ Spacer(modifier = Modifier.width(12.dp))
+ Text(
+ text = stringResource(screen.titleResId),
+ fontSize = 14.sp,
+ fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal,
+ color = if (isSelected) MaterialTheme.colorScheme.primary
+ else MaterialTheme.colorScheme.onSurface,
+ modifier = Modifier.weight(1f)
+ )
+ Text(
+ text = "›",
+ fontSize = 16.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant
+ )
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/src/main/res/drawable/ic_more.xml b/app/src/main/res/drawable/ic_more.xml
new file mode 100644
index 00000000..3ca18a0a
--- /dev/null
+++ b/app/src/main/res/drawable/ic_more.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/build-logic/convention/src/main/java/com/rtbishop/look4sat/convention/ApplicationPlugin.kt b/build-logic/convention/src/main/java/com/rtbishop/look4sat/convention/ApplicationPlugin.kt
index db09bc5f..e91f4ed1 100644
--- a/build-logic/convention/src/main/java/com/rtbishop/look4sat/convention/ApplicationPlugin.kt
+++ b/build-logic/convention/src/main/java/com/rtbishop/look4sat/convention/ApplicationPlugin.kt
@@ -31,12 +31,15 @@ internal class ApplicationPlugin : Plugin {
implementation(project(":core:data"))
implementation(project(":core:domain"))
implementation(project(":core:presentation"))
+ implementation(project(":feature:cw"))
implementation(project(":feature:map"))
implementation(project(":feature:mutual"))
implementation(project(":feature:passes"))
implementation(project(":feature:radar"))
+ implementation(project(":feature:roaming"))
implementation(project(":feature:satellites"))
implementation(project(":feature:settings"))
+ implementation(project(":feature:status"))
implementation(libs.androidx.core.splashscreen)
implementation(libs.compose.material3.adaptive)
implementation(libs.compose.navigation3)
diff --git a/build-logic/convention/src/main/java/com/rtbishop/look4sat/convention/PluginSetupUtils.kt b/build-logic/convention/src/main/java/com/rtbishop/look4sat/convention/PluginSetupUtils.kt
index 334a9308..6126a2d0 100644
--- a/build-logic/convention/src/main/java/com/rtbishop/look4sat/convention/PluginSetupUtils.kt
+++ b/build-logic/convention/src/main/java/com/rtbishop/look4sat/convention/PluginSetupUtils.kt
@@ -57,7 +57,7 @@ internal fun Project.setupAndroidApp() {
namespace = libs.versions.packageName.get()
compileSdk = libs.versions.compileSdk.get().toInt()
defaultConfig {
- applicationId = libs.versions.packageName.get()
+ applicationId = libs.versions.applicationId.get()
minSdk = libs.versions.minSdk.get().toInt()
versionCode = libs.versions.appVersionCode.get().toInt()
versionName = libs.versions.appVersionName.get()
diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/injection/MainContainer.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/injection/MainContainer.kt
index ab4e95cf..ac93635d 100644
--- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/injection/MainContainer.kt
+++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/injection/MainContainer.kt
@@ -29,6 +29,7 @@ import com.rtbishop.look4sat.core.data.framework.Ft817Controller
import com.rtbishop.look4sat.core.data.framework.Ic705Controller
import com.rtbishop.look4sat.core.data.framework.NetworkReporter
import com.rtbishop.look4sat.core.data.framework.RadioTrackingService
+import com.rtbishop.look4sat.core.data.repository.AmSatRepository
import com.rtbishop.look4sat.core.data.repository.DatabaseRepo
import com.rtbishop.look4sat.core.data.repository.SatelliteRepo
import com.rtbishop.look4sat.core.data.repository.SelectionRepo
@@ -40,6 +41,9 @@ import com.rtbishop.look4sat.core.data.usecase.AddToCalendar
import com.rtbishop.look4sat.core.data.usecase.AudioCapture
import com.rtbishop.look4sat.core.data.usecase.SaveImage
import com.rtbishop.look4sat.core.data.usecase.ShowToast
+import com.rtbishop.look4sat.core.domain.wavelog.IWavelogQueueStore
+import com.rtbishop.look4sat.core.domain.wavelog.WavelogQueue
+import com.rtbishop.look4sat.core.domain.wavelog.WavelogUploader
import com.rtbishop.look4sat.core.domain.model.RadioControlSettings
import com.rtbishop.look4sat.core.domain.repository.IDatabaseRepo
import com.rtbishop.look4sat.core.domain.repository.IMainContainer
@@ -70,12 +74,14 @@ import okhttp3.OkHttpClient
class MainContainer(private val context: Context) : IMainContainer {
private val localSource = provideLocalSource()
+ private val remoteSource by lazy { provideRemoteSource() }
private val mainHandler = CoroutineExceptionHandler { _, error -> println("MainHandler: $error") }
override val appScope = CoroutineScope(SupervisorJob() + Dispatchers.Default + mainHandler)
override val settingsRepo = provideSettingsRepo()
override val selectionRepo = provideSelectionRepo()
override val satelliteRepo = provideSatelliteRepo()
override val databaseRepo = provideDatabaseRepo()
+ override val amSatRepo = AmSatRepository(remoteSource)
override val radioTrackingService: IRadioTrackingService by lazy {
val manager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
RadioTrackingService(appScope, manager, satelliteRepo, settingsRepo)
@@ -96,6 +102,16 @@ class MainContainer(private val context: Context) : IMainContainer {
override fun provideSaveImage(): ISaveImage = SaveImage(context)
+ // WaveLog 日志(4.5.2): 本地队列 + 上传器(共享实例)
+ override val wavelogQueue: WavelogQueue by lazy {
+ val prefs = context.getSharedPreferences("wavelog", Context.MODE_PRIVATE)
+ WavelogQueue(object : IWavelogQueueStore {
+ override fun load(): String = prefs.getString("wavelog_queue", "[]") ?: "[]"
+ override fun save(json: String) = prefs.edit().putString("wavelog_queue", json).apply()
+ })
+ }
+ override fun provideWavelogUploader(): WavelogUploader = WavelogUploader(settingsRepo, wavelogQueue)
+
override fun provideBluetoothReporter(): IReporter {
val manager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
val rc = settingsRepo.rcSettings.value
@@ -149,7 +165,6 @@ class MainContainer(private val context: Context) : IMainContainer {
private fun provideDatabaseRepo(): IDatabaseRepo {
val dbDispatcher = Dispatchers.Default
val dataParser = DataParser(dbDispatcher)
- val remoteSource = provideRemoteSource()
return DatabaseRepo(dbDispatcher, dataParser, localSource, remoteSource, settingsRepo)
}
@@ -160,7 +175,14 @@ class MainContainer(private val context: Context) : IMainContainer {
}
private fun provideRemoteSource(): IRemoteSource {
- return RemoteSource(Dispatchers.IO, context.contentResolver, OkHttpClient.Builder().build())
+ return RemoteSource(
+ Dispatchers.IO, context.contentResolver,
+ OkHttpClient.Builder()
+ .connectTimeout(15, java.util.concurrent.TimeUnit.SECONDS)
+ .readTimeout(20, java.util.concurrent.TimeUnit.SECONDS)
+ .writeTimeout(20, java.util.concurrent.TimeUnit.SECONDS)
+ .build()
+ )
}
private fun provideSatelliteRepo(): ISatelliteRepo {
@@ -176,6 +198,6 @@ class MainContainer(private val context: Context) : IMainContainer {
val appPrefsFileName = "${context.packageName}_preferences"
val appPreferences = context.getSharedPreferences(appPrefsFileName, Context.MODE_PRIVATE)
val appVersionName = context.packageManager.getPackageInfo(context.packageName, 0).versionName ?: "4.0.4"
- return SettingsRepo(manager, appPreferences, appVersionName)
+ return SettingsRepo(context, manager, appPreferences, appVersionName)
}
}
diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/AmSatRepository.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/AmSatRepository.kt
new file mode 100644
index 00000000..b992bfe5
--- /dev/null
+++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/AmSatRepository.kt
@@ -0,0 +1,21 @@
+package com.rtbishop.look4sat.core.data.repository
+
+import com.rtbishop.look4sat.core.data.source.AmSatParser
+import com.rtbishop.look4sat.core.domain.model.SatStatusPage
+import com.rtbishop.look4sat.core.domain.repository.IAmSatRepository
+import com.rtbishop.look4sat.core.domain.source.IRemoteSource
+
+/** AMSAT 状态仓库: 抓 HTML → 解析 → SatStatusPage */
+class AmSatRepository(private val remoteSource: IRemoteSource) : IAmSatRepository {
+
+ override suspend fun fetchStatus(): SatStatusPage? {
+ val html = remoteSource.getStatusHtml() ?: return null
+ if (html.isBlank()) return null
+ return try {
+ AmSatParser.parse(html, System.currentTimeMillis())
+ } catch (exception: Exception) {
+ println("AmSatRepository parse exception: $exception")
+ null
+ }
+ }
+}
diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/DatabaseRepo.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/DatabaseRepo.kt
index 8decc7a6..9fa00f97 100644
--- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/DatabaseRepo.kt
+++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/DatabaseRepo.kt
@@ -69,23 +69,33 @@ class DatabaseRepo(
val dataSourcesSettings = settingsRepo.dataSourcesSettings.value
val tleUrls = buildMap {
putAll(Sources.satelliteDataUrls)
- if (dataSourcesSettings.useCustomTLE) put(customSourceType, dataSourcesSettings.tleUrl)
+ // 开关开且 URL 非空 -> All 用自定义 URL;否则用默认 URL(在线更新默认源)
+ put("All", if (dataSourcesSettings.useCustomTLE && dataSourcesSettings.tleUrl.isNotBlank())
+ dataSourcesSettings.tleUrl else Sources.defaultTleUrl)
}.filterValues { it.isNotBlank() }
val radioUrls = buildMap {
putAll(Sources.transceiversDataUrls)
- if (dataSourcesSettings.useCustomTransceivers) put(customSourceType, dataSourcesSettings.transceiversUrl)
+ put("SatNOGS", if (dataSourcesSettings.useCustomTransceivers && dataSourcesSettings.transceiversUrl.isNotBlank())
+ dataSourcesSettings.transceiversUrl else Sources.defaultTransceiversUrl)
}.filterValues { it.isNotBlank() }
// launch all network requests concurrently
val tleJobs = tleUrls.values.map { url -> async { url to remoteSource.getNetworkStream(url) } }
val radioJobs = radioUrls.values.map { url -> async { url to remoteSource.getNetworkStream(url) } }
+ // 统计成功源数: 0 成功视为更新失败(不刷时间戳, 抛异常让 UI 提示)
+ val tleResults = tleJobs.awaitAll()
+ val radioResults = radioJobs.awaitAll()
+ val successCount = tleResults.count { it.second != null } + radioResults.count { it.second != null }
+ if (successCount == 0) {
+ throw java.io.IOException("All data sources failed to download")
+ }
// parse fetched data concurrently and associate with types
- val importedEntries = tleJobs.awaitAll().flatMap { (url, stream) ->
+ val importedEntries = tleResults.flatMap { (url, stream) ->
val type = tleUrls.entries.find { it.value == url }?.key ?: customSourceType
stream?.let { parseSatelliteStream(url, unwrapIfZipped(url, it)) }.orEmpty().also { entries ->
settingsRepo.setSatelliteTypeIds(type, entries.map { it.catnum })
}
}
- val importedRadios = radioJobs.awaitAll().flatMap { (url, stream) ->
+ val importedRadios = radioResults.flatMap { (url, stream) ->
stream?.let { dataParser.parseJSONStream(unwrapIfZipped(url, it)) }.orEmpty()
}
// insert parsed data into the database
diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/SatelliteRepo.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/SatelliteRepo.kt
index 6c9c0c01..c5d1c143 100644
--- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/SatelliteRepo.kt
+++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/SatelliteRepo.kt
@@ -95,14 +95,8 @@ class SatelliteRepo(
}
}
- override suspend fun getRadios(
- sat: OrbitalObject,
- pos: GeoPos,
- radios: List,
- time: Long
- ): List {
+ override suspend fun getRadios(satPos: OrbitalPos, radios: List): List {
return withContext(dispatcher) {
- val satPos = sat.getPosition(pos, time)
radios.map { transmitter ->
transmitter.copy(
downlinkLow = transmitter.downlinkLow?.let { satPos.getDownlinkFreq(it) },
@@ -242,13 +236,16 @@ class SatelliteRepo(
if (elevation > maxElevation) maxElevation = elevation
} while (elevation < 0.0)
- // refine AOS to ~500ms precision
- calendarTimeMillis -= 60L * 1000L
- do {
- calendarTimeMillis += 500L
- elevation = sat.getElevation(pos, calendarTimeMillis)
- if (elevation > maxElevation) maxElevation = elevation
- } while (elevation < 0.0)
+ // refine AOS to ~500ms precision via binary search.
+ // Elevation is monotonic across the horizon crossing, so binary search
+ // finds the crossing in ~8 SGP4 calls instead of up to 120 linear steps.
+ var aosLo = calendarTimeMillis - 60L * 1000L // elevation < 0 (below horizon)
+ var aosHi = calendarTimeMillis // elevation >= 0 (above horizon)
+ while (aosHi - aosLo > 500L) {
+ val mid = (aosLo + aosHi) / 2
+ if (sat.getElevation(pos, mid) < 0.0) aosLo = mid else aosHi = mid
+ }
+ calendarTimeMillis = aosHi
// Get full position for AOS data (azimuth, altitude)
val aosPos = sat.getFullPosition(pos, calendarTimeMillis)
@@ -262,13 +259,14 @@ class SatelliteRepo(
if (elevation > maxElevation) maxElevation = elevation
} while (elevation > 0.0)
- // refine LOS to ~500ms precision
- calendarTimeMillis -= 30L * 1000L
- do {
- calendarTimeMillis += 500L
- elevation = sat.getElevation(pos, calendarTimeMillis)
- if (elevation > maxElevation) maxElevation = elevation
- } while (elevation > 0.0)
+ // refine LOS to ~500ms precision via binary search (same monotonic argument)
+ var losLo = calendarTimeMillis - 30L * 1000L // elevation > 0 (above horizon)
+ var losHi = calendarTimeMillis // elevation <= 0 (below horizon)
+ while (losHi - losLo > 500L) {
+ val mid = (losLo + losHi) / 2
+ if (sat.getElevation(pos, mid) > 0.0) losLo = mid else losHi = mid
+ }
+ calendarTimeMillis = losHi
// Get full position for LOS data (azimuth, altitude)
val losPos = sat.getFullPosition(pos, calendarTimeMillis)
diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/SettingsRepo.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/SettingsRepo.kt
index ccc34102..5d85007b 100644
--- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/SettingsRepo.kt
+++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/SettingsRepo.kt
@@ -29,6 +29,7 @@ import com.rtbishop.look4sat.core.domain.model.OtherSettings
import com.rtbishop.look4sat.core.domain.model.PassesSettings
import com.rtbishop.look4sat.core.domain.model.RCSettings
import com.rtbishop.look4sat.core.domain.model.RadioControlSettings
+import com.rtbishop.look4sat.core.domain.source.Sources
import com.rtbishop.look4sat.core.domain.predict.GeoPos
import com.rtbishop.look4sat.core.domain.repository.ISettingsRepo
import com.rtbishop.look4sat.core.domain.utility.positionToQth
@@ -39,6 +40,7 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
class SettingsRepo(
+ private val context: android.content.Context,
private val locationManager: LocationManager,
private val preferences: SharedPreferences,
override val appVersionName: String
@@ -76,6 +78,8 @@ class SettingsRepo(
private val keyStateOfUtc = "stateOfUtc"
private val keyStateOfLightTheme = "stateOfLightTheme"
private val keyStateOfNightMode = "stateOfNightMode"
+ private val keyHiddenScreens = "hiddenScreens"
+ private val keyScreenOrder = "screenOrder"
private val keyStationAltitude = "stationAltitude"
private val keyStationLatitude = "stationLatitude"
private val keyStationLongitude = "stationLongitude"
@@ -91,6 +95,11 @@ class SettingsRepo(
private val keyUseCustomTransceivers = "useCustomTransceivers"
private val keyTleUrl = "tleUrl"
private val keyTransceiversUrl = "transceiversUrl"
+ private val keySubMenuOrder = "subMenuOrder"
+ private val keyWavelogUrl = "wavelogUrl"
+ private val keyWavelogApiKey = "wavelogApiKey"
+ private val keyWavelogStationId = "wavelogStationId"
+ private val keyWavelogAutoUpload = "wavelogAutoUpload"
private val separatorComma = ","
//region # Satellites selection settings
@@ -178,23 +187,41 @@ class SettingsRepo(
return true
}
- override fun setStationPosition(): Boolean {
- if (!LocationManagerCompat.isLocationEnabled(locationManager)) return false
- try {
- val hasGps = LocationManagerCompat.hasProvider(locationManager, providerGps)
- val hasNet = LocationManagerCompat.hasProvider(locationManager, providerNet)
- val provider = if (hasGps) providerGps else if (hasNet) providerNet else providerDef
- val location = locationManager.getLastKnownLocation(providerDef)
- if (location == null || System.currentTimeMillis() - location.time > 600_000L) {
- println("Requesting location for $provider provider")
- locationManager.requestLocationUpdates(provider, 0L, 0f, this)
- } else {
- setStationPosition(location.latitude, location.longitude, location.altitude)
- }
- } catch (exception: SecurityException) {
- println("No permissions were given - $exception")
+ /** GPS 定位: 一次性 getCurrentLocation(GPS 优先, 15 秒超时), 拿到位置才返回 true */
+ override suspend fun setStationPosition(): Boolean {
+ // 权限前置: 无定位权限直接失败(不吞异常)
+ if (androidx.core.content.ContextCompat.checkSelfPermission(
+ context, android.Manifest.permission.ACCESS_FINE_LOCATION
+ ) != android.content.pm.PackageManager.PERMISSION_GRANTED
+ ) {
+ println("GPS: no fine location permission")
+ return false
+ }
+ if (!LocationManagerCompat.isLocationEnabled(locationManager)) return false
+ return kotlinx.coroutines.suspendCancellableCoroutine { cont ->
+ val signal = android.os.CancellationSignal()
+ val handler = android.os.Handler(android.os.Looper.getMainLooper())
+ val executor = java.util.concurrent.Executor { handler.post(it) }
+ // 15 秒超时
+ val timeout = handler.postDelayed({
+ signal.cancel()
+ if (cont.isActive) cont.resume(false) { }
+ }, 15_000L)
+ val listener = androidx.core.util.Consumer { location ->
+ handler.removeCallbacksAndMessages(null)
+ setStationPosition(location.latitude, location.longitude, location.altitude)
+ if (cont.isActive) cont.resume(true) { }
+ }
+ val hasGps = LocationManagerCompat.hasProvider(locationManager, providerGps)
+ val provider = if (hasGps) providerGps else providerNet
+ try {
+ LocationManagerCompat.getCurrentLocation(locationManager, provider, signal, executor, listener)
+ } catch (exception: SecurityException) {
+ handler.removeCallbacksAndMessages(null)
+ if (cont.isActive) cont.resume(false) { }
+ }
+ cont.invokeOnCancellation { signal.cancel(); handler.removeCallbacksAndMessages(null) }
}
- return true
}
override fun setStationPosition(locator: String): Boolean {
@@ -213,8 +240,8 @@ class SettingsRepo(
}
private fun setStationPosition(latitude: Double, longitude: Double, altitude: Double, locator: String) {
- val newLat = latitude.round(4)
- val newLon = longitude.round(4)
+ val newLat = latitude.round(5)
+ val newLon = longitude.round(5)
val newAlt = altitude.round(1)
val timestamp = System.currentTimeMillis()
println("Received new Position($newLat, $newLon, $newAlt) & Locator $locator")
@@ -356,6 +383,13 @@ class SettingsRepo(
putString(keySstvMode, new.sstvMode)
putLong(keyLowElevation, new.lowElevation.toRawBits())
putLong(keyHighElevation, new.highElevation.toRawBits())
+ putStringSet(keyHiddenScreens, new.hiddenScreens.toSet())
+ putString(keyScreenOrder, new.screenOrder.joinToString(","))
+ putString(keySubMenuOrder, new.subMenuOrder.joinToString(","))
+ putString(keyWavelogUrl, new.wavelogUrl)
+ putString(keyWavelogApiKey, new.wavelogApiKey)
+ putString(keyWavelogStationId, new.wavelogStationId)
+ putBoolean(keyWavelogAutoUpload, new.wavelogAutoUpload)
}
new
}
@@ -371,8 +405,15 @@ class SettingsRepo(
shouldSeeWarning = preferences.getBoolean(keyShouldSeeWarning, true),
shouldSeeWhatsNew = preferences.getBoolean(keyShouldSeeWhatsNew, true),
sstvMode = preferences.getString(keySstvMode, null) ?: "Auto",
+ hiddenScreens = preferences.getStringSet(keyHiddenScreens, emptySet())?.toList() ?: emptyList(),
+ screenOrder = preferences.getString(keyScreenOrder, null)?.split(",")?.filter { it.isNotBlank() } ?: emptyList(),
+ subMenuOrder = preferences.getString(keySubMenuOrder, null)?.split(",")?.filter { it.isNotBlank() } ?: emptyList(),
lowElevation = Double.fromBits(preferences.getLong(keyLowElevation, 15.0.toRawBits())),
- highElevation = Double.fromBits(preferences.getLong(keyHighElevation, 45.0.toRawBits()))
+ highElevation = Double.fromBits(preferences.getLong(keyHighElevation, 45.0.toRawBits())),
+ wavelogUrl = preferences.getString(keyWavelogUrl, null) ?: "",
+ wavelogApiKey = preferences.getString(keyWavelogApiKey, null) ?: "",
+ wavelogStationId = preferences.getString(keyWavelogStationId, null) ?: "",
+ wavelogAutoUpload = preferences.getBoolean(keyWavelogAutoUpload, false)
)
//endregion
@@ -390,12 +431,20 @@ class SettingsRepo(
_dataSourcesSettings.value = settings
}
- private fun getDataSourcesSettings(): DataSourcesSettings = DataSourcesSettings(
- useCustomTLE = preferences.getBoolean(keyUseCustomTle, false),
- useCustomTransceivers = preferences.getBoolean(keyUseCustomTransceivers, false),
- tleUrl = preferences.getString(keyTleUrl, "https://example.com/tle.txt") ?: "",
- transceiversUrl = preferences.getString(keyTransceiversUrl, "https://example.com/radio.json") ?: ""
- )
+ private fun getDataSourcesSettings(): DataSourcesSettings {
+ // 4.4.8 修复: 旧版 example.com 占位 URL 视为未配置 -> 替换为真实默认 URL 且开关强制关闭,
+ // 否则在线更新的 All/SatNOGS 源会指向错误地址导致更新失败
+ val storedTleUrl = preferences.getString(keyTleUrl, Sources.defaultTleUrl) ?: Sources.defaultTleUrl
+ val storedTxUrl = preferences.getString(keyTransceiversUrl, Sources.defaultTransceiversUrl) ?: Sources.defaultTransceiversUrl
+ val tleUrl = if (storedTleUrl == "https://example.com/tle.txt") Sources.defaultTleUrl else storedTleUrl
+ val txUrl = if (storedTxUrl == "https://example.com/radio.json") Sources.defaultTransceiversUrl else storedTxUrl
+ return DataSourcesSettings(
+ useCustomTLE = preferences.getBoolean(keyUseCustomTle, false) && tleUrl != Sources.defaultTleUrl,
+ useCustomTransceivers = preferences.getBoolean(keyUseCustomTransceivers, false) && txUrl != Sources.defaultTransceiversUrl,
+ tleUrl = tleUrl,
+ transceiversUrl = txUrl
+ )
+ }
//endregion
//region # Radio control settings
diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/source/AmSatParser.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/source/AmSatParser.kt
new file mode 100644
index 00000000..f67ae677
--- /dev/null
+++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/source/AmSatParser.kt
@@ -0,0 +1,136 @@
+package com.rtbishop.look4sat.core.data.source
+
+import com.rtbishop.look4sat.core.domain.model.SatDay
+import com.rtbishop.look4sat.core.domain.model.SatReport
+import com.rtbishop.look4sat.core.domain.model.SatSlot
+import com.rtbishop.look4sat.core.domain.model.SatStatus
+import com.rtbishop.look4sat.core.domain.model.SatStatusPage
+import java.util.regex.Pattern
+
+/**
+ * AMSAT 卫星状态页解析器(https://amsat.org/status/)
+ *
+ * 页面结构(静态 HTML, 2026-08 实测):
+ * - 状态表: 内 48 行, 表头 = Name + 6 天(每个 colspan=12)
+ * 数据行 73 格: [0]=卫星名, [1..72] = 6 天 × 12 个 2 小时槽(新→旧)
+ * 每格 | 数字 | , 有报告时数字带
+ * docTips.show('id') 链接
+ * - 报告详情在页面内嵌 JS:
+ * tips.a885153 = new Array(5,5,120,'状态
呼号
网格
日期
时间段 UTC')
+ *
+ * 状态色: #648fff=活跃, #ffb000=仅遥测, #dc267f=未听到, #fe6100=矛盾
+ */
+object AmSatParser {
+
+ private val STATUS_COLORS = mapOf(
+ "#648fff" to 0xFF648FFF.toLong(),
+ "#ffb000" to 0xFFFFB000.toLong(),
+ "#dc267f" to 0xFFDC267F.toLong(),
+ "#fe6100" to 0xFFFE6100.toLong()
+ )
+ private val GRAY = 0xFFC0C0C0.toLong()
+
+ private val rowRe = Pattern.compile("(.*?)
", Pattern.DOTALL)
+ private val cellRe = Pattern.compile("(]*>.*?)", Pattern.DOTALL)
+ private val bgRe = Pattern.compile("bgcolor=\"?(#[0-9a-fA-F]{6}|C0C0C0)\"?")
+ private val linkRe = Pattern.compile("docTips\\.show\\('(a\\d+)'\\)")
+ private val tipRe = Pattern.compile(
+ "tips\\.(a\\d+)\\s*=\\s*new\\s+Array\\(\\s*\\d+,\\s*\\d+,\\s*\\d+,\\s*'([^']*)'"
+ )
+
+ /** 解析完整页面 */
+ fun parse(html: String, fetchedAtUtcMs: Long): SatStatusPage {
+ val reports = parseReports(html)
+ val statuses = parseStatusTable(html, reports)
+ return SatStatusPage(fetchedAtUtcMs, statuses, reports)
+ }
+
+ /** 提取全部报告(tips.* JS 数组) */
+ fun parseReports(html: String): Map {
+ val map = mutableMapOf()
+ val m = tipRe.matcher(html)
+ while (m.find()) {
+ val id = m.group(1)
+ val parts = m.group(2).split("
")
+ map[id] = SatReport(
+ id = id,
+ statusText = parts.getOrElse(0) { "" }.trim(),
+ call = parts.getOrElse(1) { "" }.trim(),
+ grid = parts.getOrElse(2) { "" }.trim(),
+ dateUtc = parts.getOrElse(3) { "" }.trim(),
+ timeUtc = parts.getOrElse(4) { "" }.trim()
+ )
+ }
+ return map
+ }
+
+ /** 解析状态表(48 行卫星) */
+ fun parseStatusTable(html: String, reports: Map): List {
+ val result = mutableListOf()
+ val tables = extractTables(html)
+ for (table in tables) {
+ val rows = rowRe.matcher(table)
+ val parsed = mutableListOf()
+ var rowIndex = 0
+ var dayHeaders: List = emptyList()
+ while (rows.find()) {
+ val rowHtml = rows.group(1)
+ val cells = cellRe.matcher(rowHtml)
+ val cellList = mutableListOf()
+ while (cells.find()) cellList.add(cells.group(1))
+ if (rowIndex == 0) {
+ // 表头: Name + 6 天(每个 colspan=12)
+ dayHeaders = cellList.drop(1).take(6).map { stripHtml(it) }
+ rowIndex++
+ continue
+ }
+ if (cellList.size < 7) { rowIndex++; continue }
+ val name = stripHtml(cellList[0])
+ if (name.isBlank()) { rowIndex++; continue }
+ val days = mutableListOf()
+ for (d in 0 until 6) {
+ val start = 1 + d * 12
+ val end = start + 12
+ val slots = (start until end).mapNotNull { i ->
+ cellList.getOrNull(i)?.let { cell ->
+ val bg = bgRe.matcher(cell)
+ val color = if (bg.find()) {
+ STATUS_COLORS[bg.group(1).lowercase()] ?: GRAY
+ } else GRAY
+ val link = linkRe.matcher(cell)
+ val ids = mutableListOf()
+ while (link.find()) ids.add(link.group(1))
+ val hasReport = ids.isNotEmpty()
+ val count = if (hasReport) {
+ stripHtml(cell).trim().toIntOrNull() ?: ids.size
+ } else 0
+ SatSlot(
+ statusColor = if (hasReport) color else GRAY,
+ count = count,
+ reportIds = ids
+ )
+ }
+ }
+ days.add(SatDay(dayHeaders.getOrElse(d) { "" }, slots))
+ }
+ parsed.add(SatStatus(name, days))
+ rowIndex++
+ }
+ if (parsed.isNotEmpty()) {
+ result.addAll(parsed)
+ break
+ }
+ }
+ return result
+ }
+
+ private fun extractTables(html: String): List {
+ val result = mutableListOf()
+ val m = Pattern.compile("", Pattern.DOTALL).matcher(html)
+ while (m.find()) result.add(m.group())
+ return result
+ }
+
+ private fun stripHtml(s: String): String =
+ s.replace(Regex("<[^>]+>"), "").trim()
+}
diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/source/RemoteSource.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/source/RemoteSource.kt
index 300e930d..b65cfb8e 100644
--- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/source/RemoteSource.kt
+++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/source/RemoteSource.kt
@@ -43,6 +43,22 @@ class RemoteSource(
}
}
+ override suspend fun getStatusHtml(): String? = withContext(dispatcher) {
+ try {
+ val request = Request.Builder()
+ .url("https://amsat.org/status/")
+ .header("User-Agent", "Mozilla/5.0 (Linux; Android 13) Look4Sat/4.5")
+ .build()
+ httpClient.newCall(request).execute().use { response ->
+ if (!response.isSuccessful) return@use null
+ response.body?.string()
+ }
+ } catch (exception: Exception) {
+ println("RemoteSource amsat status exception: $exception")
+ null
+ }
+ }
+
override suspend fun getNetworkStream(url: String): InputStream? = withContext(dispatcher) {
try {
val networkRequest = Request.Builder().url(url).build()
diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/usecase/ShowToast.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/usecase/ShowToast.kt
index b07b15ac..83f7e2ff 100644
--- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/usecase/ShowToast.kt
+++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/usecase/ShowToast.kt
@@ -25,4 +25,8 @@ class ShowToast(private val context: Context) : IShowToast {
override fun invoke(message: String) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
}
+
+ override fun invoke(resId: Int) {
+ invoke(context.getString(resId))
+ }
}
diff --git a/core/data/src/test/java/com/rtbishop/look4sat/core/data/repository/DatabaseRepoTest.kt b/core/data/src/test/java/com/rtbishop/look4sat/core/data/repository/DatabaseRepoTest.kt
index a14ede56..57d33998 100644
--- a/core/data/src/test/java/com/rtbishop/look4sat/core/data/repository/DatabaseRepoTest.kt
+++ b/core/data/src/test/java/com/rtbishop/look4sat/core/data/repository/DatabaseRepoTest.kt
@@ -102,7 +102,8 @@ class DatabaseRepoTest {
repository.updateFromRemote()
assertTrue(localSource.insertedEntries.any { it.catnum == 25544 })
- assertEquals(listOf(25544), settingsRepo.satelliteTypeIdsByType["Other"])
+ // 新语义: 开关开 + URL 非空 -> All 源用自定义 URL, 数据归入 All 类型
+ assertEquals(listOf(25544), settingsRepo.satelliteTypeIdsByType["All"])
}
private fun validCsvStream(): InputStream = """
diff --git a/core/domain/build.gradle.kts b/core/domain/build.gradle.kts
index 841c9857..dbc922ee 100644
--- a/core/domain/build.gradle.kts
+++ b/core/domain/build.gradle.kts
@@ -1,3 +1,8 @@
plugins {
alias(libs.plugins.convention.coreDomainPlugin)
}
+
+dependencies {
+ // 编译期使用 org.json(构造/解析 WaveLog API 请求体); 运行时用 Android 系统自带的 org.json
+ compileOnly("org.json:json:20240303")
+}
diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/model/SatStatus.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/model/SatStatus.kt
new file mode 100644
index 00000000..3b76516c
--- /dev/null
+++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/model/SatStatus.kt
@@ -0,0 +1,37 @@
+package com.rtbishop.look4sat.core.domain.model
+
+/** 单条卫星状态报告(AMSAT 网站 tooltip 数据) */
+data class SatReport(
+ val id: String, // 报告 ID(a885153)
+ val statusText: String, // Heard / Telemetry Only / Not Heard ...
+ val call: String, // 呼号
+ val grid: String, // 网格坐标(可为空)
+ val dateUtc: String, // 2026-08-04
+ val timeUtc: String // 2:46-:59 UTC
+)
+
+/** 单个 2 小时槽的状态 */
+data class SatSlot(
+ val statusColor: Long, // ARGB 状态色(-1 = 无报告)
+ val count: Int, // 报告数量(0 = 无)
+ val reportIds: List = emptyList() // 该槽报告 ID 列表
+)
+
+/** 卫星一天的状态(12 个 2 小时槽) */
+data class SatDay(
+ val dateLabel: String, // "Aug 4"
+ val slots: List // 12 槽(00-02 ... 22-24)
+)
+
+/** 单个卫星 6 天状态 */
+data class SatStatus(
+ val name: String, // "AO-123_[FM]"
+ val days: List // 6 天(新→旧)
+)
+
+/** 页面整体解析结果 */
+data class SatStatusPage(
+ val fetchedAtUtcMs: Long,
+ val statuses: List,
+ val reports: Map // id → 报告
+)
diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/model/Settings.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/model/Settings.kt
index ef830eb4..d8cbed65 100644
--- a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/model/Settings.kt
+++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/model/Settings.kt
@@ -62,7 +62,18 @@ data class OtherSettings(
val shouldSeeWhatsNew: Boolean,
val sstvMode: String = "Auto",
val lowElevation: Double = 15.0,
- val highElevation: Double = 45.0
+ val highElevation: Double = 45.0,
+ // UI 设置: 底部导航栏隐藏的页面(Screen simpleName 列表, 默认空 = 全部显示)
+ val hiddenScreens: List = emptyList(),
+ // UI 设置: 页面顺序(空 = 默认顺序: 卫星/过境/雷达/地图/设置)
+ val screenOrder: List = emptyList(),
+ // UI 设置: 更多菜单顺序(空 = 默认: 匹配/漫游/CW解码)
+ val subMenuOrder: List = emptyList(),
+ // WaveLog 日志系统(4.5.2): 服务器配置
+ val wavelogUrl: String = "",
+ val wavelogApiKey: String = "",
+ val wavelogStationId: String = "",
+ val wavelogAutoUpload: Boolean = false
)
data class DataSourcesSettings(
diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/IAmSatRepository.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/IAmSatRepository.kt
new file mode 100644
index 00000000..c8f11b1c
--- /dev/null
+++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/IAmSatRepository.kt
@@ -0,0 +1,9 @@
+package com.rtbishop.look4sat.core.domain.repository
+
+import com.rtbishop.look4sat.core.domain.model.SatStatusPage
+
+/** AMSAT 卫星状态数据源 */
+interface IAmSatRepository {
+ /** 抓取并解析 AMSAT 状态页; 失败返回 null */
+ suspend fun fetchStatus(): SatStatusPage?
+}
diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/IMainContainer.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/IMainContainer.kt
index 70de0f81..1268f581 100644
--- a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/IMainContainer.kt
+++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/IMainContainer.kt
@@ -30,6 +30,7 @@ interface IMainContainer {
val selectionRepo: ISelectionRepo
val satelliteRepo: ISatelliteRepo
val databaseRepo: IDatabaseRepo
+ val amSatRepo: IAmSatRepository
val radioTrackingService: IRadioTrackingService
val mutualPassData: StateFlow
fun setMutualPassData(data: MutualPassData)
@@ -42,6 +43,9 @@ interface IMainContainer {
fun provideRxRadioController(): IRadioController
fun provideAudioCapture(): IAudioCapture
fun provideSaveImage(): ISaveImage
+ // WaveLog 日志(4.5.2)
+ val wavelogQueue: com.rtbishop.look4sat.core.domain.wavelog.WavelogQueue
+ fun provideWavelogUploader(): com.rtbishop.look4sat.core.domain.wavelog.WavelogUploader
}
data class MutualPassData(
diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/ISatelliteRepo.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/ISatelliteRepo.kt
index 99d31474..e5cf947f 100644
--- a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/ISatelliteRepo.kt
+++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/ISatelliteRepo.kt
@@ -61,7 +61,7 @@ interface ISatelliteRepo {
suspend fun getTrack(sat: OrbitalObject, pos: GeoPos, start: Long, end: Long): List
/** Get Doppler-shifted radio frequencies for a satellite at the given time. */
- suspend fun getRadios(sat: OrbitalObject, pos: GeoPos, radios: List, time: Long): List
+ suspend fun getRadios(satPos: OrbitalPos, radios: List): List
/** Fetch radio transceivers for a satellite by its catalog number. */
suspend fun getRadiosWithId(id: Int): List
diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/ISettingsRepo.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/ISettingsRepo.kt
index 23b726e2..f2a5c3fe 100644
--- a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/ISettingsRepo.kt
+++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/repository/ISettingsRepo.kt
@@ -45,7 +45,8 @@ interface ISettingsRepo {
//region # Station position settings
val stationPosition: StateFlow
fun setStationPosition(latitude: Double, longitude: Double, altitude: Double): Boolean
- fun setStationPosition(): Boolean
+ /** GPS 定位(挂起): 拿到位置才返回 true; 权限缺失/超时/无信号返回 false */
+ suspend fun setStationPosition(): Boolean
fun setStationPosition(locator: String): Boolean
//endregion
diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/source/IRemoteSource.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/source/IRemoteSource.kt
index 1ba5d62d..8437c927 100644
--- a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/source/IRemoteSource.kt
+++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/source/IRemoteSource.kt
@@ -22,4 +22,7 @@ import java.io.InputStream
interface IRemoteSource {
suspend fun getFileStream(uri: String): InputStream?
suspend fun getNetworkStream(url: String): InputStream?
+
+ /** 抓取 AMSAT 状态页 HTML(带 UA, 返回 null = 失败) */
+ suspend fun getStatusHtml(): String?
}
diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/source/Sources.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/source/Sources.kt
index 17c91e34..ddc4a0de 100644
--- a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/source/Sources.kt
+++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/source/Sources.kt
@@ -18,6 +18,10 @@
package com.rtbishop.look4sat.core.domain.source
object Sources {
+ // 在线更新的默认 URL(用户可通过"自定义URL"对话框修改/重置)
+ val defaultTleUrl = "https://celestrak.org/NORAD/elements/gp.php?GROUP=active&FORMAT=csv"
+ val defaultTransceiversUrl = "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",
"Amateur" to "https://celestrak.org/NORAD/elements/gp.php?GROUP=amateur&FORMAT=csv",
diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/usecase/IShowToast.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/usecase/IShowToast.kt
index 1bb99c75..7c20324b 100644
--- a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/usecase/IShowToast.kt
+++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/usecase/IShowToast.kt
@@ -19,4 +19,7 @@ package com.rtbishop.look4sat.core.domain.usecase
interface IShowToast {
operator fun invoke(message: String)
+
+ /** 按资源 ID 显示(四语文案) */
+ operator fun invoke(resId: Int)
}
diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/utility/DopplerFrequencyCalculator.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/utility/DopplerFrequencyCalculator.kt
index f391907d..51c59129 100644
--- a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/utility/DopplerFrequencyCalculator.kt
+++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/utility/DopplerFrequencyCalculator.kt
@@ -1,4 +1,4 @@
-/*
+/*
* Look4Sat. Amateur radio satellite tracker and pass predictor.
* Copyright (C) 2019-2026 Arty Bishop and contributors.
*
@@ -11,6 +11,7 @@ package com.rtbishop.look4sat.core.domain.utility
import com.rtbishop.look4sat.core.domain.model.SatRadio
import com.rtbishop.look4sat.core.domain.predict.OrbitalPos
+import java.util.Locale
/**
* Computes Doppler-corrected reciprocal frequencies for linear transponders.
@@ -44,6 +45,9 @@ object DopplerFrequencyCalculator {
* Given a downlink frequency, compute the Doppler-corrected uplink frequency
* with an offset applied to the downlink (in Hz).
* Returns null if the transponder is not a linear passband type.
+ *
+ * The user-entered downlink frequency already includes the offset, so subtract
+ * it before mapping the downlink passband position back to the uplink.
*/
fun computeUplinkFromDownlinkWithOffset(
downlinkHz: Long,
@@ -52,7 +56,7 @@ object DopplerFrequencyCalculator {
offsetHz: Long
): Long? {
if (!isLinearTransponder(transponder)) return null
- val baseUplink = TransponderMapper.mapDownlinkToUplink(downlinkHz + offsetHz, transponder) ?: return null
+ val baseUplink = TransponderMapper.mapDownlinkToUplink(downlinkHz - offsetHz, transponder) ?: return null
return orbitalPos.getUplinkFreq(baseUplink)
}
@@ -95,4 +99,26 @@ object DopplerFrequencyCalculator {
return upLow != null && upHigh != null && downLow != null && downHigh != null
&& upLow != upHigh && downLow != downHigh
}
+
+ /**
+ * True for the radio entry that should drive the standalone Calculator page.
+ *
+ * A frequency range alone is not enough: some non-user-facing or drifting data entries
+ * can also have low/high frequencies. The calculator is meant for the named linear
+ * transponder entry, e.g. "Linear Transponder", "Linear Transp.", "SSB Transponder".
+ */
+ fun isNamedLinearTransponder(transponder: SatRadio): Boolean {
+ if (!isLinearTransponder(transponder)) return false
+
+ val info = transponder.info.lowercase(Locale.ENGLISH)
+ val modes = listOfNotNull(transponder.downlinkMode, transponder.uplinkMode)
+ .joinToString(separator = " ")
+ .lowercase(Locale.ENGLISH)
+ val hasLinearName = info.contains("linear")
+ val hasTransponderName = info.contains("transponder") || info.contains("transp") ||
+ info.contains("xponder") || info.contains("xpdr")
+ val hasLinearMode = listOf("ssb", "usb", "lsb", "cw").any { modes.contains(it) }
+
+ return (hasLinearName && hasTransponderName) || (hasTransponderName && hasLinearMode)
+ }
}
diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/utility/QthConverter.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/utility/QthConverter.kt
index 5055ab7f..afea0353 100644
--- a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/utility/QthConverter.kt
+++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/utility/QthConverter.kt
@@ -19,31 +19,78 @@ package com.rtbishop.look4sat.core.domain.utility
import com.rtbishop.look4sat.core.domain.predict.GeoPos
+/**
+ * Converts a Maidenhead locator (QTH grid square) to a GeoPos.
+ * Supports 6-char (3 pair), 8-char (4 pair) and 10-char (5 pair) locators.
+ * The returned position is the center of the finest cell encoded by the locator:
+ * - 6 char: 5' lon x 2.5' lat cell center
+ * - 8 char: 30" lon x 15" lat cell center
+ * - 10 char: 1.25" lon x 0.625" lat cell center
+ */
fun qthToPosition(locator: String): GeoPos? {
- val trimmedQth = locator.take(6)
+ val trimmedQth = locator.trim().uppercase()
if (!isValidLocator(trimmedQth)) return null
- val lonFirst = (trimmedQth[0].uppercaseChar().code - 65) * 20
- val latFirst = (trimmedQth[1].uppercaseChar().code - 65) * 10
+ val lonFirst = (trimmedQth[0].code - 65) * 20
+ val latFirst = (trimmedQth[1].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)
+ val lonThird = (trimmedQth[4].lowercaseChar().code - 97) / 12.0
+ val latThird = (trimmedQth[5].lowercaseChar().code - 97) / 24.0
+ var longitude = lonFirst + lonSecond + lonThird - 180
+ var latitude = latFirst + latSecond + latThird - 90
+ // 8-char extension: 4th pair, digits, 30" lon x 15" lat cells
+ if (trimmedQth.length >= 8) {
+ longitude += trimmedQth[6].toString().toInt() / 120.0
+ latitude += trimmedQth[7].toString().toInt() / 240.0
+ }
+ // 10-char extension: 5th pair, letters, 1.25" lon x 0.625" lat cells
+ if (trimmedQth.length >= 10) {
+ longitude += (trimmedQth[8].lowercaseChar().code - 97) / 2880.0
+ latitude += (trimmedQth[9].lowercaseChar().code - 97) / 5760.0
+ }
+ // Offset to the center of the finest encoded cell
+ when (trimmedQth.length) {
+ 8 -> {
+ longitude += 1.0 / 240.0
+ latitude += 1.0 / 480.0
+ }
+ 10 -> {
+ longitude += 1.0 / 5760.0
+ latitude += 1.0 / 11520.0
+ }
+ else -> {
+ longitude += 1.0 / 24.0
+ latitude += 1.0 / 48.0
+ }
+ }
+ return GeoPos(latitude.round(6), longitude.round(6))
}
-fun positionToQth(latitude: Double, longitude: Double): String? {
+/**
+ * Converts a GeoPos to a Maidenhead locator (QTH grid square).
+ * Default precision is 8 characters (4 pairs) giving 30" lon x 15" lat resolution,
+ * matching common 8-char grid square tools. Pass precision = 6 for the classic
+ * 5' x 2.5' resolution, or precision = 10 for the finest 1.25" x 0.625" resolution.
+ */
+fun positionToQth(latitude: Double, longitude: Double, precision: Int = 8): String? {
if (!isValidPosition(latitude, longitude)) return null
- val newLongitude = if (longitude > 180.0) longitude else longitude + 180
+ val newLongitude = longitude + 180
val newLatitude = latitude + 90
- val lonFirst = (65 + (newLongitude / 20)).toInt().toChar()
- val latFirst = (65 + (newLatitude / 10)).toInt().toChar()
- val lonSecond = ((newLongitude / 2) % 10).toInt()
+ val lonFirst = (65 + (newLongitude / 20).toInt().coerceIn(0, 17)).toChar()
+ val latFirst = (65 + (newLatitude / 10).toInt().coerceIn(0, 17)).toChar()
+ val lonSecond = ((newLongitude % 20) / 2).toInt()
val latSecond = (newLatitude % 10).toInt()
val lonThird = (65 + (newLongitude % 2) * 12).toInt().toChar().lowercaseChar()
val latThird = (65 + (newLatitude % 1) * 24).toInt().toChar().lowercaseChar()
- return "$lonFirst$latFirst$lonSecond$latSecond$lonThird$latThird"
+ val qth = "$lonFirst$latFirst$lonSecond$latSecond$lonThird$latThird"
+ if (precision < 8) return qth
+ val lonFourth = ((newLongitude % (1.0 / 12.0)) * 120).toInt()
+ val latFourth = ((newLatitude % (1.0 / 24.0)) * 240).toInt()
+ val qth8 = "$qth$lonFourth$latFourth"
+ if (precision < 10) return qth8
+ val lonFifth = (65 + (newLongitude % (1.0 / 120.0)) * 2880).toInt().toChar().lowercaseChar()
+ val latFifth = (65 + (newLatitude % (1.0 / 240.0)) * 5760).toInt().toChar().lowercaseChar()
+ return "$qth8$lonFifth$latFifth"
}
private fun isValidPosition(lat: Double, lon: Double): Boolean {
@@ -51,5 +98,49 @@ private fun isValidPosition(lat: Double, lon: Double): Boolean {
}
private fun isValidLocator(locator: String): Boolean {
- return locator.matches("[a-xA-X][a-xA-X]\\d\\d[a-xA-X][a-xA-X]".toRegex())
+ return locator.matches("[a-xA-X]{2}\\d{2}[a-xA-X]{2}(?:\\d{2}(?:[a-xA-X]{2})?)?".toRegex())
}
+
+/**
+ * Returns the 4-char field+square part of a locator, e.g. "OL42ih45" -> "OL42".
+ * A 4-char input is returned as-is when valid.
+ */
+fun qthToSquare(locator: String): String {
+ val upper = locator.trim().uppercase()
+ return when {
+ upper.length >= 4 && isValidLocator(upper) -> upper.take(4)
+ upper.length == 4 && upper.matches("[a-xA-X]{2}\\d{2}".toRegex()) -> upper
+ else -> "----"
+ }
+}
+
+/**
+ * Builds the 3x3 grid of 4-char squares surrounding [square] (e.g. "OL42").
+ * Row 0 = north (lat +1), col 0 = west (lon -1). Handles field/square carry
+ * at boundaries (e.g. "AA00" wraps to "RR99" at the south-west corner).
+ * Mirrors the neighbor logic decompiled from the QTH定位器 app.
+ */
+fun qthNeighbors(square: String): List {
+ if (square.length != 4) return emptyList()
+ val lonField = (square[0].uppercaseChar().code - 65).coerceIn(0, 17)
+ val latField = (square[1].uppercaseChar().code - 65).coerceIn(0, 17)
+ val lonSquare = square[2].digitToCharOrNull() ?: return emptyList()
+ val latSquare = square[3].digitToCharOrNull() ?: return emptyList()
+ val result = mutableListOf()
+ for (dLat in 1 downTo -1) { // north -> south
+ for (dLon in -1..1) { // west -> east
+ var lf = lonField
+ var tf = latField
+ var ls = lonSquare + dLon
+ var ts = latSquare + dLat
+ if (ls < 0) { lf -= 1; ls = 9 } else if (ls > 9) { lf += 1; ls = 0 }
+ if (ts < 0) { tf -= 1; ts = 9 } else if (ts > 9) { tf += 1; ts = 0 }
+ lf = (lf + 18) % 18
+ tf = (tf + 18) % 18
+ result += "${('A' + lf).toChar()}${('A' + tf).toChar()}$ls$ts"
+ }
+ }
+ return result
+}
+
+private fun Char.digitToCharOrNull(): Int? = digitToIntOrNull()
diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/wavelog/WaveLogApi.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/wavelog/WaveLogApi.kt
new file mode 100644
index 00000000..6b1d6c25
--- /dev/null
+++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/wavelog/WaveLogApi.kt
@@ -0,0 +1,266 @@
+/*
+ * WaveLogApi.kt — WaveLog 日志服务器 API 客户端(4.5.2 覆盖修复 2)。
+ *
+ * 同时支持 v1 与 v2(用户服务器实测只有 v1, v2 返回 404):
+ * v2: POST {base}/api/v2/qso (Authorization: Bearer + JSON 字段)
+ * v1: POST {base}/index.php/api/qso (key 在 JSON body + ADIF 字符串)
+ * 策略: 优先 v2, 404 自动降级 v1。
+ * 测试连接: v2 GET api/v2/token → 404 时 v1 POST api/get_contacts_adif。
+ * 站点网格: 仅 v2 有 GET api/v2/station/{id}; v1 无此端点 → 降级用用户 QTH。
+ */
+package com.rtbishop.look4sat.core.domain.wavelog
+
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import org.json.JSONObject
+import java.io.BufferedReader
+import java.io.InputStreamReader
+import java.io.OutputStreamWriter
+import java.net.HttpURLConnection
+import java.net.URL
+import java.util.Locale
+
+/** 站点信息(GET /api/v2/station/{id} 结果) */
+data class WavelogStation(
+ val id: Int,
+ val name: String,
+ val callsign: String,
+ val gridsquare: String
+)
+
+sealed class WavelogResult {
+ data class Success(val message: String) : WavelogResult()
+ data class Failure(val message: String) : WavelogResult()
+}
+
+object WaveLogApi {
+
+ private const val TIMEOUT_MS = 15000
+
+ /** 规范化服务器地址: 去尾斜杠/去尾部 index.php; 无协议前缀时补 https:// */
+ fun normalizeUrl(raw: String): String {
+ var u = raw.trim().trimEnd('/')
+ if (u.isBlank()) return ""
+ if (!u.startsWith("http://") && !u.startsWith("https://")) u = "https://$u"
+ if (u.endsWith("/index.php")) u = u.removeSuffix("/index.php")
+ return u
+ }
+
+ /** 测试连接: v2 GET api/v2/token → 404 时 v1 POST api/get_contacts_adif */
+ suspend fun testToken(url: String, apiKey: String, stationId: String = ""): WavelogResult = withContext(Dispatchers.IO) {
+ val base = normalizeUrl(url)
+ if (base.isBlank()) return@withContext WavelogResult.Failure("服务器地址为空")
+
+ // v2: GET /index.php/api/v2/token
+ val v2 = httpRequest("$base/index.php/api/v2/token", "GET", apiKey, null)
+ if (v2.first in 200..299) return@withContext WavelogResult.Success("连接成功 (API v2)")
+
+ // v1: POST /index.php/api/get_contacts_adif(key 在 body)
+ if (stationId.isNotBlank()) {
+ val body = JSONObject().apply {
+ put("key", apiKey)
+ put("station_id", stationId)
+ put("fetchfromid", 0)
+ }.toString()
+ val v1 = httpRequest("$base/index.php/api/get_contacts_adif", "POST", apiKey, body)
+ if (v1.first in 200..299) return@withContext WavelogResult.Success("连接成功 (API v1)")
+ if (v1.first == 401) return@withContext WavelogResult.Failure("API 密钥无效 (v1: 401)")
+ }
+ // 无 index.php 的 v1 尝试
+ val body = JSONObject().apply {
+ put("key", apiKey)
+ put("station_id", stationId)
+ put("fetchfromid", 0)
+ }.toString()
+ val v1b = httpRequest("$base/api/get_contacts_adif", "POST", apiKey, body)
+ if (v1b.first in 200..299) return@withContext WavelogResult.Success("连接成功 (API v1)")
+ if (v1b.first == 401) return@withContext WavelogResult.Failure("API 密钥无效 (v1: 401)")
+
+ WavelogResult.Failure("连接失败: v2 HTTP ${v2.first}, v1 HTTP ${v1b.first} — 请确认服务器地址/密钥正确")
+ }
+
+ /** 站点信息: 仅 v2; v1 无此端点返回 null 标记(网格检测降级用用户 QTH) */
+ suspend fun getStation(url: String, apiKey: String, stationId: String): WavelogResult = withContext(Dispatchers.IO) {
+ val base = normalizeUrl(url)
+ if (base.isBlank()) return@withContext WavelogResult.Failure("服务器地址为空")
+ val (code, resp) = httpRequest("$base/index.php/api/v2/station/$stationId", "GET", apiKey, null)
+ if (code in 200..299) {
+ return@withContext try {
+ val obj = JSONObject(resp)
+ val data = obj.optJSONObject("data") ?: obj
+ val station = WavelogStation(
+ id = data.optInt("id"),
+ name = data.optString("name"),
+ callsign = data.optString("callsign"),
+ gridsquare = data.optString("gridsquare")
+ )
+ WavelogResult.Success(JSONObject().apply {
+ put("id", station.id); put("name", station.name)
+ put("callsign", station.callsign); put("gridsquare", station.gridsquare)
+ }.toString())
+ } catch (e: Exception) {
+ WavelogResult.Failure("解析失败: ${e.message}")
+ }
+ }
+ // v1 无 station 端点 → 返回 Success 空(调用方降级用用户 QTH)
+ WavelogResult.Success("")
+ }
+
+ /** LoTW 认可的卫星名: 取括号前主名 + 大写(ISS 特判) */
+ fun normalizeSatName(raw: String): String {
+ val main = raw.substringBefore('(').trim()
+ .ifBlank { raw.trim() }
+ .uppercase(Locale.ENGLISH)
+ // ISS 特判: 主名是 ISS/ZARYA/ARISS 变体 → ISS(LoTW 认可名)
+ return when {
+ main == "ZARYA" || main.startsWith("ISS") -> "ISS"
+ main == "ARISS" -> "ISS"
+ else -> main
+ }
+ }
+
+ /** 创建 QSO: 优先 v2, 404 降级 v1(ADIF) */
+ suspend fun postQso(
+ url: String,
+ apiKey: String,
+ stationProfileId: String,
+ qso: WavelogQso,
+ gridsquare: String
+ ): WavelogResult = withContext(Dispatchers.IO) {
+ val base = normalizeUrl(url)
+ if (base.isBlank()) return@withContext WavelogResult.Failure("服务器地址为空")
+
+ val satName = normalizeSatName(qso.satName)
+
+ // v2: POST /index.php/api/v2/qso(JSON 字段)
+ val v2Body = JSONObject().apply {
+ put("station_profile_id", stationProfileId.toIntOrNull() ?: 0)
+ put("call", qso.call)
+ put("band", "SAT")
+ put("mode", qso.mode)
+ put("qso_date", utcDate(qso.timeUtcMs))
+ put("time_on", utcTime(qso.timeUtcMs))
+ put("freq", qso.freqTxHz)
+ put("freq_rx", qso.freqRxHz)
+ put("gridsquare", gridsquare)
+ put("sat_name", satName)
+ }
+ val (code, resp) = httpRequest("$base/index.php/api/v2/qso", "POST", apiKey, v2Body.toString())
+ if (code in 200..299) return@withContext WavelogResult.Success("已上传 (v2)")
+ if (code == 409) return@withContext WavelogResult.Success("重复(已存在)")
+
+ // v1: POST /index.php/api/qso(key 在 body + ADIF)
+ val v1Body = JSONObject().apply {
+ put("key", apiKey)
+ put("station_profile_id", stationProfileId)
+ put("type", "adif")
+ put("string", toAdif(qso, gridsquare, satName))
+ }
+ val (code1, resp1) = httpRequest("$base/index.php/api/qso", "POST", apiKey, v1Body.toString())
+ if (code1 in 200..299) return@withContext WavelogResult.Success("已上传 (v1)")
+
+ // 无 index.php 的 v1
+ val (code1b, resp1b) = httpRequest("$base/api/qso", "POST", apiKey, v1Body.toString())
+ if (code1b in 200..299) return@withContext WavelogResult.Success("已上传 (v1)")
+
+ WavelogResult.Failure("上传失败: v2 HTTP $code, v1 HTTP $code1 — ${shortError(resp1.ifBlank { resp1b })}")
+ }
+
+ /** v1 ADIF 字符串(频率 MHz, 长度=UTF-8 字节数, sat_name 已规范化) */
+ private fun toAdif(qso: WavelogQso, gridsquare: String, satName: String): String {
+ fun field(name: String, value: String): String {
+ val bytes = value.toByteArray(Charsets.UTF_8).size
+ return "<$name:$bytes>$value"
+ }
+ return buildString {
+ append(field("call", qso.call))
+ append(field("band", "SAT"))
+ append(field("mode", qso.mode))
+ append(field("freq", String.format(Locale.ENGLISH, "%.6f", qso.freqTxHz / 1_000_000.0)))
+ if (qso.freqRxHz > 0) {
+ append(field("freq_rx", String.format(Locale.ENGLISH, "%.6f", qso.freqRxHz / 1_000_000.0)))
+ }
+ append(field("qso_date", utcDateCompact(qso.timeUtcMs)))
+ append(field("time_on", utcTimeCompact(qso.timeUtcMs)))
+ if (gridsquare.isNotBlank()) append(field("gridsquare", gridsquare.take(4)))
+ if (satName.isNotBlank()) {
+ append(field("sat_name", satName))
+ append(field("prop_mode", "SAT"))
+ }
+ append("")
+ }
+ }
+
+ /** 通用 HTTP 请求(返回 code + body) */
+ private fun httpRequest(url: String, method: String, apiKey: String, jsonBody: String?): Pair {
+ return try {
+ val conn = URL(url).openConnection() as HttpURLConnection
+ conn.requestMethod = method
+ conn.connectTimeout = TIMEOUT_MS
+ conn.readTimeout = TIMEOUT_MS
+ if (apiKey.isNotBlank()) conn.setRequestProperty("Authorization", "Bearer $apiKey")
+ if (jsonBody != null) {
+ conn.doOutput = true
+ conn.setRequestProperty("Content-Type", "application/json")
+ conn.setRequestProperty("Accept", "application/json")
+ OutputStreamWriter(conn.outputStream, Charsets.UTF_8).use { it.write(jsonBody) }
+ }
+ val code = conn.responseCode
+ val stream = if (code in 200..299) conn.inputStream else conn.errorStream
+ val body = if (stream != null) {
+ BufferedReader(InputStreamReader(stream, Charsets.UTF_8)).use { it.readText() }
+ } else ""
+ code to body
+ } catch (e: Exception) {
+ -1 to (e.message ?: e.javaClass.simpleName)
+ }
+ }
+
+ private fun shortError(body: String): String {
+ if (body.startsWith("<")) return body.take(80) // HTML 错误页
+ return try {
+ val obj = JSONObject(body)
+ val err = obj.optJSONObject("error")
+ err?.optString("message")?.ifBlank { body.take(120) }
+ ?: obj.optString("reason").ifBlank { obj.optString("message").ifBlank { body.take(120) } }
+ } catch (_: Exception) {
+ body.take(120)
+ }
+ }
+
+ private fun utcDate(ms: Long): String {
+ val cal = java.util.Calendar.getInstance(java.util.TimeZone.getTimeZone("UTC"))
+ cal.timeInMillis = ms
+ return "%04d-%02d-%02d".format(
+ cal.get(java.util.Calendar.YEAR), cal.get(java.util.Calendar.MONTH) + 1,
+ cal.get(java.util.Calendar.DAY_OF_MONTH)
+ )
+ }
+
+ private fun utcTime(ms: Long): String {
+ val cal = java.util.Calendar.getInstance(java.util.TimeZone.getTimeZone("UTC"))
+ cal.timeInMillis = ms
+ return "%02d:%02d:%02d".format(
+ cal.get(java.util.Calendar.HOUR_OF_DAY), cal.get(java.util.Calendar.MINUTE),
+ cal.get(java.util.Calendar.SECOND)
+ )
+ }
+
+ private fun utcDateCompact(ms: Long): String {
+ val cal = java.util.Calendar.getInstance(java.util.TimeZone.getTimeZone("UTC"))
+ cal.timeInMillis = ms
+ return "%04d%02d%02d".format(
+ cal.get(java.util.Calendar.YEAR), cal.get(java.util.Calendar.MONTH) + 1,
+ cal.get(java.util.Calendar.DAY_OF_MONTH)
+ )
+ }
+
+ private fun utcTimeCompact(ms: Long): String {
+ val cal = java.util.Calendar.getInstance(java.util.TimeZone.getTimeZone("UTC"))
+ cal.timeInMillis = ms
+ return "%02d%02d%02d".format(
+ cal.get(java.util.Calendar.HOUR_OF_DAY), cal.get(java.util.Calendar.MINUTE),
+ cal.get(java.util.Calendar.SECOND)
+ )
+ }
+}
diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/wavelog/WavelogQueue.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/wavelog/WavelogQueue.kt
new file mode 100644
index 00000000..3e728c21
--- /dev/null
+++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/wavelog/WavelogQueue.kt
@@ -0,0 +1,100 @@
+/*
+ * WavelogQueue.kt — WaveLog 本地日志队列(4.5.2)。
+ *
+ * 纯 Kotlin(不依赖 Android): 存储走 IWavelogQueueStore 接口,
+ * 由 core/data 用 SharedPreferences 实现。
+ * 队列上限 500 条(超出丢最旧)。
+ */
+package com.rtbishop.look4sat.core.domain.wavelog
+
+import org.json.JSONArray
+import org.json.JSONObject
+
+/** 存储抽象(SharedPreferences 实现见 core/data) */
+interface IWavelogQueueStore {
+ fun load(): String
+ fun save(json: String)
+}
+
+/** 待上传的 QSO 条目(本地队列元素,与 POST /api/v2/qso 字段对应) */
+data class WavelogQso(
+ val id: String, // 本地唯一 id(UUID)
+ val timeUtcMs: Long, // 回车时刻 UTC 毫秒(本地显示 + 组装 qso_date/time_on)
+ val call: String,
+ val mode: String,
+ val freqTxHz: Long, // 上行(回车那一秒多普勒修正)
+ val freqRxHz: Long, // 下行
+ val satName: String,
+ val sessionId: String = "", // 场次 ID: 卫星名-AOS 时间戳(过境仰角 0 秒), 空=未分组(旧数据)
+ val uploaded: Boolean = false // 是否已成功上传(4.5.2 修复: 成功后保留标记, 表格打勾)
+)
+
+class WavelogQueue(private val store: IWavelogQueueStore) {
+
+ private val key = "wavelog_queue"
+
+ fun all(): List {
+ val raw = store.load()
+ return try {
+ val arr = JSONArray(raw)
+ (0 until arr.length()).map { i ->
+ val o = arr.getJSONObject(i)
+ WavelogQso(
+ id = o.getString("id"),
+ timeUtcMs = o.getLong("timeUtcMs"),
+ call = o.optString("call"),
+ mode = o.optString("mode"),
+ freqTxHz = o.optLong("freqTxHz"),
+ freqRxHz = o.optLong("freqRxHz"),
+ satName = o.optString("satName"),
+ sessionId = o.optString("sessionId"),
+ uploaded = o.optBoolean("uploaded", false)
+ )
+ }
+ } catch (_: Exception) { emptyList() }
+ }
+
+ @Synchronized
+ fun add(qso: WavelogQso) {
+ val list = all().toMutableList()
+ list.add(0, qso) // 最新在前
+ if (list.size > 500) list.removeAt(list.size - 1)
+ save(list)
+ }
+
+ @Synchronized
+ fun remove(id: String) {
+ save(all().filter { it.id != id })
+ }
+
+ @Synchronized
+ fun removeAll(ids: Set) {
+ save(all().filter { it.id !in ids })
+ }
+
+ /** 标记为已上传(保留在队列, 表格打勾) */
+ @Synchronized
+ fun markUploaded(id: String) {
+ save(all().map { if (it.id == id) it.copy(uploaded = true) else it })
+ }
+
+ /** 移除所有已上传条目(可选项, 保持队列精简) */
+ @Synchronized
+ fun removeUploaded() {
+ save(all().filter { !it.uploaded })
+ }
+
+ private fun save(list: List) {
+ val arr = JSONArray()
+ list.forEach { q ->
+ arr.put(JSONObject().apply {
+ put("id", q.id); put("timeUtcMs", q.timeUtcMs); put("call", q.call)
+ put("mode", q.mode); put("freqTxHz", q.freqTxHz)
+ put("freqRxHz", q.freqRxHz); put("satName", q.satName)
+ put("sessionId", q.sessionId)
+ put("uploaded", q.uploaded)
+ })
+ }
+ store.save(arr.toString())
+ }
+}
diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/wavelog/WavelogUploader.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/wavelog/WavelogUploader.kt
new file mode 100644
index 00000000..40599871
--- /dev/null
+++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/wavelog/WavelogUploader.kt
@@ -0,0 +1,91 @@
+/*
+ * WavelogUploader.kt — WaveLog 队列上传调度(4.5.2)。
+ *
+ * 手动/周期上传共用: 逐条网格检测(用户 QTH 前 4 位 vs 台站网格前 4 位)
+ * → POST /api/v2/qso → 成功移出队列。
+ * 网格不一致: 返回 NeedConfirm(由 UI 弹窗「忽略并上传/取消」),
+ * 确认后带 force=true 重试本批。
+ */
+package com.rtbishop.look4sat.core.domain.wavelog
+
+import com.rtbishop.look4sat.core.domain.repository.ISettingsRepo
+import org.json.JSONObject
+
+sealed class UploadOutcome {
+ data class NeedConfirm(val stationGrid: String, val userGrid: String) : UploadOutcome()
+ data class Done(
+ val successCount: Int,
+ val failedCount: Int,
+ val message: String,
+ val firstError: String = ""
+ ) : UploadOutcome()
+}
+
+class WavelogUploader(
+ private val settingsRepo: ISettingsRepo,
+ private val queue: WavelogQueue
+) {
+
+ // 台站网格缓存(每次上传前刷新; 失败用旧值)
+ private var cachedStationGrid: String? = null
+
+ /** 上传整个队列。force=true 跳过网格确认(用户已选「忽略并上传」) */
+ suspend fun uploadQueue(force: Boolean = false): UploadOutcome {
+ val settings = settingsRepo.otherSettings.value
+ val url = settings.wavelogUrl
+ val apiKey = settings.wavelogApiKey
+ val stationId = settings.wavelogStationId
+ if (url.isBlank() || apiKey.isBlank() || stationId.isBlank()) {
+ return UploadOutcome.Done(0, queue.all().size, "未配置 WaveLog 服务器")
+ }
+
+ // 1. 拉站点信息(拿台站网格); v1 无此端点时降级用用户 QTH
+ val stationGrid = getStationGrid(url, apiKey, stationId) ?: userQthGrid()
+ if (stationGrid.isNullOrBlank()) {
+ return UploadOutcome.Done(0, queue.all().size, "无法获取站点信息(检查站点 ID/密钥权限)")
+ }
+
+ // 2. 网格检测: 用户当前 QTH 前 4 位 vs 台站网格前 4 位(v1 降级时网格相同, 跳过)
+ if (!force) {
+ val userGrid = userQthGrid()
+ if (userGrid != null && stationGrid.take(4).lowercase() != userGrid.take(4).lowercase()) {
+ return UploadOutcome.NeedConfirm(stationGrid, userGrid)
+ }
+ }
+
+ // 3. 逐条上传(成功后标记 uploaded, 保留在本地供日志页打勾)
+ val entries = queue.all()
+ var ok = 0
+ var fail = 0
+ var firstError = ""
+ for (qso in entries) {
+ if (qso.uploaded) { ok++; continue }
+ val result = WaveLogApi.postQso(url, apiKey, stationId, qso, stationGrid)
+ if (result is WavelogResult.Success) {
+ ok++
+ queue.markUploaded(qso.id)
+ } else {
+ fail++
+ if (firstError.isBlank()) firstError = (result as? WavelogResult.Failure)?.message ?: ""
+ }
+ }
+ val message = if (fail == 0) "成功上传 $ok 条" else "成功 $ok 条, 失败 $fail 条(保留待重试)"
+ return UploadOutcome.Done(ok, fail, message, firstError)
+ }
+
+ private suspend fun getStationGrid(url: String, apiKey: String, stationId: String): String? {
+ val result = WaveLogApi.getStation(url, apiKey, stationId)
+ if (result is WavelogResult.Success) {
+ return try {
+ JSONObject(result.message).optString("gridsquare").takeIf { it.isNotBlank() }
+ ?: cachedStationGrid
+ } catch (_: Exception) { cachedStationGrid }
+ }
+ return cachedStationGrid
+ }
+
+ /** 用户当前 QTH 网格(前 4 位; 无 QTH 返回 null = 跳过检测) */
+ private fun userQthGrid(): String? {
+ return settingsRepo.stationPosition.value.qthLocator?.takeIf { it.length >= 4 }
+ }
+}
diff --git a/core/domain/src/test/java/com/rtbishop/look4sat/core/domain/DopplerFrequencyCalculatorTest.kt b/core/domain/src/test/java/com/rtbishop/look4sat/core/domain/DopplerFrequencyCalculatorTest.kt
index 9cbfdedd..709e54d1 100644
--- a/core/domain/src/test/java/com/rtbishop/look4sat/core/domain/DopplerFrequencyCalculatorTest.kt
+++ b/core/domain/src/test/java/com/rtbishop/look4sat/core/domain/DopplerFrequencyCalculatorTest.kt
@@ -13,12 +13,15 @@ class DopplerFrequencyCalculatorTest {
upHigh: Long = 145_500_000L,
downLow: Long = 435_000_000L,
downHigh: Long? = 435_500_000L,
- inverted: Boolean = false
+ inverted: Boolean = false,
+ info: String = "Linear Transponder",
+ downlinkMode: String? = "USB",
+ uplinkMode: String? = "LSB"
) = SatRadio(
- uuid = "linear", info = "Linear Transponder", isAlive = true,
+ uuid = "linear", info = info, isAlive = true,
downlinkLow = downLow, downlinkHigh = downHigh,
- downlinkMode = "USB", uplinkLow = upLow, uplinkHigh = upHigh,
- uplinkMode = "LSB", isInverted = inverted, catnum = 12345
+ downlinkMode = downlinkMode, uplinkLow = upLow, uplinkHigh = upHigh,
+ uplinkMode = uplinkMode, isInverted = inverted, catnum = 12345
)
private fun fmTransponder() = SatRadio(
@@ -48,6 +51,28 @@ class DopplerFrequencyCalculatorTest {
assertFalse(DopplerFrequencyCalculator.isLinearTransponder(xpdr))
}
+ @Test
+ fun isNamedLinearTransponder_returnsTrueForLinearTransponderName() {
+ assertTrue(DopplerFrequencyCalculator.isNamedLinearTransponder(linearTransponder()))
+ }
+
+ @Test
+ fun isNamedLinearTransponder_returnsTrueForSsbTransponderName() {
+ val xpdr = linearTransponder(info = "Mode V/U SSB Transponder", downlinkMode = "USB", uplinkMode = "LSB")
+ assertTrue(DopplerFrequencyCalculator.isNamedLinearTransponder(xpdr))
+ }
+
+ @Test
+ fun isNamedLinearTransponder_returnsFalseForRangeEntryWithoutTransponderName() {
+ val driftingRangeEntry = linearTransponder(info = "Upper side band (drifting)")
+ assertFalse(DopplerFrequencyCalculator.isNamedLinearTransponder(driftingRangeEntry))
+ }
+
+ @Test
+ fun isNamedLinearTransponder_returnsFalseForFmRepeater() {
+ assertFalse(DopplerFrequencyCalculator.isNamedLinearTransponder(fmTransponder()))
+ }
+
@Test
fun computeUplinkFromDownlink_linear_noDoppler() {
val xpdr = linearTransponder()
@@ -93,6 +118,53 @@ class DopplerFrequencyCalculatorTest {
assertNull(result)
}
+ @Test
+ fun computeDownlinkFromUplink_withPositiveOffset_addsOffsetToDownlink() {
+ val xpdr = linearTransponder()
+ val orbitalPos = pos(0.0)
+ val downlink = DopplerFrequencyCalculator.computeDownlinkFromUplinkWithOffset(
+ uplinkHz = 145_200_000L,
+ transponder = xpdr,
+ orbitalPos = orbitalPos,
+ offsetHz = 2_500L
+ )
+ assertEquals(435_202_500L, downlink)
+ }
+
+ @Test
+ fun computeUplinkFromDownlink_withPositiveOffset_subtractsOffsetBeforeMapping() {
+ val xpdr = linearTransponder()
+ val orbitalPos = pos(0.0)
+ val uplink = DopplerFrequencyCalculator.computeUplinkFromDownlinkWithOffset(
+ downlinkHz = 435_202_500L,
+ transponder = xpdr,
+ orbitalPos = orbitalPos,
+ offsetHz = 2_500L
+ )
+ assertEquals(145_200_000L, uplink)
+ }
+
+ @Test
+ fun computeOffsetRoundTrip_handlesNegativeOffset() {
+ val xpdr = linearTransponder()
+ val orbitalPos = pos(0.0)
+ val downlink = DopplerFrequencyCalculator.computeDownlinkFromUplinkWithOffset(
+ uplinkHz = 145_200_000L,
+ transponder = xpdr,
+ orbitalPos = orbitalPos,
+ offsetHz = -2_500L
+ )
+ assertEquals(435_197_500L, downlink)
+
+ val uplink = DopplerFrequencyCalculator.computeUplinkFromDownlinkWithOffset(
+ downlinkHz = downlink!!,
+ transponder = xpdr,
+ orbitalPos = orbitalPos,
+ offsetHz = -2_500L
+ )
+ assertEquals(145_200_000L, uplink)
+ }
+
@Test
fun computeUplinkFromDownlink_invertedTransponder() {
val xpdr = linearTransponder(inverted = true, downHigh = 435_500_000L)
diff --git a/core/domain/src/test/java/com/rtbishop/look4sat/core/domain/QthConverterTest.kt b/core/domain/src/test/java/com/rtbishop/look4sat/core/domain/QthConverterTest.kt
index 2348dd75..4b87942a 100644
--- a/core/domain/src/test/java/com/rtbishop/look4sat/core/domain/QthConverterTest.kt
+++ b/core/domain/src/test/java/com/rtbishop/look4sat/core/domain/QthConverterTest.kt
@@ -18,7 +18,9 @@
package com.rtbishop.look4sat.core.domain
import com.rtbishop.look4sat.core.domain.utility.positionToQth
+import com.rtbishop.look4sat.core.domain.utility.qthNeighbors
import com.rtbishop.look4sat.core.domain.utility.qthToPosition
+import com.rtbishop.look4sat.core.domain.utility.qthToSquare
import org.junit.Test
class QthConverterTest {
@@ -26,21 +28,36 @@ class QthConverterTest {
@Test
fun `Given valid QTH returns correct POS`() {
var result = qthToPosition("io91VL39FX")
- assert(result?.latitude == 51.4792 && result.longitude == -0.2083)
+ assert(result?.latitude == 51.499913 && result.longitude == -0.22309)
result = qthToPosition("gf15vc")
- assert(result?.latitude == -34.8958 && result.longitude == -56.2083)
+ assert(result?.latitude == -34.895833 && result.longitude == -56.208333)
+ // 8-char locators: finer 30" x 15" cell center
+ result = qthToPosition("io91vl47")
+ assert(result?.latitude == 51.489583 && result.longitude == -0.2125)
+ result = qthToPosition("jn58td25")
+ assert(result?.latitude == 48.147917 && result.longitude == 11.604167)
}
@Test
fun `Given invalid QTH returns null`() {
assert(qthToPosition("ZZ00zz") == null)
assert(qthToPosition("JN58") == null)
+ assert(qthToPosition("io9") == null)
+ assert(qthToPosition("IO91VL7") == null)
+ assert(qthToPosition("IO91VL4X") == null)
}
@Test
fun `Given valid POS returns correct QTH`() {
- assert(positionToQth(51.4878, -0.2146) == "IO91vl")
- assert(positionToQth(48.1466, 11.6083) == "JN58td")
+ // default precision is 8 chars
+ assert(positionToQth(51.4878, -0.2146) == "IO91vl47")
+ assert(positionToQth(48.1466, 11.6083) == "JN58td25")
+ // 6-char precision still available for backwards compatibility
+ assert(positionToQth(51.4878, -0.2146, 6) == "IO91vl")
+ assert(positionToQth(48.1466, 11.6083, 6) == "JN58td")
+ // 10-char precision
+ assert(positionToQth(51.4878, -0.2146, 10) == "IO91vl47fb")
+ assert(positionToQth(48.1466, 11.6083, 10) == "JN58td25xe")
}
@Test
@@ -48,4 +65,61 @@ class QthConverterTest {
assert(positionToQth(91.0542, -170.1142) == null)
assert(positionToQth(89.0542, -240.1142) == null)
}
+
+ @Test
+ fun `Given boundary POS stays in valid grid`() {
+ // antipodal / edge cases must not overflow the A-R / 0-9 / a-x alphabet
+ assert(positionToQth(-90.0, -180.0, 8) == "AA00aa00")
+ assert(positionToQth(90.0, 180.0, 8) == "RR00aa00")
+ assert(positionToQth(0.0, 0.0, 8) == "JJ00aa00")
+ // roundtrip stability: 8-char roundtrip is stable across a sample of positions
+ val positions = listOf(
+ Pair(51.4878, -0.2146), Pair(48.1466, 11.6083), Pair(-33.8688, 151.2093),
+ Pair(39.9042, 116.4074), Pair(35.6895, 139.6917), Pair(41.714, -72.727)
+ )
+ positions.forEach { (lat, lon) ->
+ val qth = positionToQth(lat, lon, 8)
+ val pos = qthToPosition(qth!!)
+ val qth2 = positionToQth(pos!!.latitude, pos.longitude, 8)
+ assert(qth == qth2) { "Roundtrip failed for ($lat, $lon): $qth -> $qth2" }
+ }
+ }
+
+ @Test
+ fun `Given square returns correct 3x3 neighbors`() {
+ // Reference grid from the QTH定位器 screenshot: OL42
+ val neighbors = qthNeighbors("OL42")
+ assert(neighbors == listOf(
+ "OL33", "OL43", "OL53",
+ "OL32", "OL42", "OL52",
+ "OL31", "OL41", "OL51"
+ )) { "OL42 grid mismatch: $neighbors" }
+ // Center cell must be the input itself
+ assert(neighbors[4] == "OL42")
+ // 9 cells, all distinct
+ assert(neighbors.size == 9 && neighbors.toSet().size == 9)
+ }
+
+ @Test
+ fun `Given boundary square wraps fields correctly`() {
+ // South-west corner: AA00 neighbors wrap to RR99 / RA90 etc.
+ val sw = qthNeighbors("AA00")
+ assert(sw.size == 9 && sw.toSet().size == 9)
+ assert(sw[0] == "RA91" && sw[4] == "AA00" && sw[6] == "RR99" && sw[8] == "AR19")
+ // North-east corner: RR99 wraps to AA00
+ val ne = qthNeighbors("RR99")
+ assert(ne.size == 9 && ne.toSet().size == 9)
+ assert(ne[0] == "RA80" && ne[4] == "RR99" && ne[8] == "AR08")
+ // Field boundary: IO91's east neighbors cross into J field
+ val london = qthNeighbors("IO91")
+ assert(london[2] == "JO02" && london[5] == "JO01")
+ }
+
+ @Test
+ fun `Given full locator returns square part`() {
+ assert(qthToSquare("OL42ih45") == "OL42")
+ assert(qthToSquare("io91VL39FX") == "IO91")
+ assert(qthToSquare("JN58") == "JN58")
+ assert(qthToSquare("garbage!!") == "----")
+ }
}
diff --git a/core/presentation/src/main/java/com/rtbishop/look4sat/core/presentation/Components.kt b/core/presentation/src/main/java/com/rtbishop/look4sat/core/presentation/Components.kt
index c299889e..8f250300 100644
--- a/core/presentation/src/main/java/com/rtbishop/look4sat/core/presentation/Components.kt
+++ b/core/presentation/src/main/java/com/rtbishop/look4sat/core/presentation/Components.kt
@@ -518,6 +518,5 @@ fun formatFrequency(frequencyHz: Long): String {
if (frequencyHz <= 0) return "---"
val mhz = frequencyHz / 1_000_000
val khz = (frequencyHz % 1_000_000) / 1_000
- val hz = frequencyHz % 1_000
- return String.format(Locale.ENGLISH, "%d.%03d.%03d", mhz, khz, hz)
+ return String.format(Locale.ENGLISH, "%d.%03d", mhz, khz)
}
diff --git a/core/presentation/src/main/java/com/rtbishop/look4sat/core/presentation/Navigation.kt b/core/presentation/src/main/java/com/rtbishop/look4sat/core/presentation/Navigation.kt
index 3c7672df..b44596b4 100644
--- a/core/presentation/src/main/java/com/rtbishop/look4sat/core/presentation/Navigation.kt
+++ b/core/presentation/src/main/java/com/rtbishop/look4sat/core/presentation/Navigation.kt
@@ -21,27 +21,45 @@ import androidx.navigation3.runtime.NavKey
import kotlinx.serialization.Serializable
@Serializable
-sealed class Screen(val iconResId: Int, val titleResId: Int) : NavKey {
+sealed class Screen(val iconResId: Int, val titleResId: Int, val screenId: String) : NavKey {
@Serializable
- data object Satellites : Screen(R.drawable.ic_satellites, R.string.nav_sat)
+ data object Satellites : Screen(R.drawable.ic_satellites, R.string.nav_sat, "Satellites")
@Serializable
- data object Passes : Screen(R.drawable.ic_passes, R.string.nav_pass)
+ data object Passes : Screen(R.drawable.ic_passes, R.string.nav_pass, "Passes")
@Serializable
- data object Radar : Screen(R.drawable.ic_radar, R.string.nav_radar)
+ data object Radar : Screen(R.drawable.ic_radar, R.string.nav_radar, "Radar")
@Serializable
- data object Map : Screen(R.drawable.ic_map, R.string.nav_map)
+ data object Map : Screen(R.drawable.ic_map, R.string.nav_map, "Map")
@Serializable
- data object Mutual : Screen(R.drawable.ic_match, R.string.nav_mutual)
+ data object Mutual : Screen(R.drawable.ic_match, R.string.nav_mutual, "Mutual")
@Serializable
- data object Settings : Screen(R.drawable.ic_settings, R.string.nav_prefs)
+ data object Roaming : Screen(R.drawable.ic_roaming, R.string.nav_roaming, "Roaming")
+
+ @Serializable
+ data object CwDecode : Screen(R.drawable.ic_cw, R.string.nav_cw, "CwDecode")
+
+ @Serializable
+ data object WavelogLog : Screen(R.drawable.ic_log, R.string.nav_log, "WavelogLog")
+
+ @Serializable
+ data object AmSat : Screen(R.drawable.ic_satellites, R.string.nav_amsat, "AMSAT")
+
+ @Serializable
+ data object Settings : Screen(R.drawable.ic_settings, R.string.nav_prefs, "Settings")
}
+// UI 设置: 默认主菜单页面顺序(底部栏 5 槽)
+val defaultScreenOrder = listOf("Satellites", "Passes", "Radar", "Map", "Settings")
+
+// UI 设置: 默认更多菜单顺序(进「更多」的页面)
+val defaultSubMenuOrder = listOf("Mutual", "Roaming", "CwDecode", "WavelogLog", "AMSAT")
+
@Serializable
data object RadarDestination : NavKey
@@ -70,4 +88,4 @@ class DeeplinkResolver(private val fallbackDestination: NavKey = Screen.Passes)
matchers.forEach { it.match(deeplink)?.let { match -> return match } }
return fallbackDestination
}
-}
+}
\ No newline at end of file
diff --git a/core/presentation/src/main/res/drawable/ic_cw.xml b/core/presentation/src/main/res/drawable/ic_cw.xml
new file mode 100644
index 00000000..133be500
--- /dev/null
+++ b/core/presentation/src/main/res/drawable/ic_cw.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/core/presentation/src/main/res/drawable/ic_log.xml b/core/presentation/src/main/res/drawable/ic_log.xml
new file mode 100644
index 00000000..74746c0a
--- /dev/null
+++ b/core/presentation/src/main/res/drawable/ic_log.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/core/presentation/src/main/res/drawable/ic_reset.xml b/core/presentation/src/main/res/drawable/ic_reset.xml
new file mode 100644
index 00000000..644d9601
--- /dev/null
+++ b/core/presentation/src/main/res/drawable/ic_reset.xml
@@ -0,0 +1,10 @@
+
+
+
+
diff --git a/core/presentation/src/main/res/drawable/ic_roaming.xml b/core/presentation/src/main/res/drawable/ic_roaming.xml
new file mode 100644
index 00000000..240fdaa4
--- /dev/null
+++ b/core/presentation/src/main/res/drawable/ic_roaming.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
diff --git a/core/presentation/src/main/res/values-id/strings.xml b/core/presentation/src/main/res/values-id/strings.xml
new file mode 100644
index 00000000..da6da14c
--- /dev/null
+++ b/core/presentation/src/main/res/values-id/strings.xml
@@ -0,0 +1,252 @@
+
+
+ Look4Sat Pro
+ Terima
+ Batal
+ Tidak ada data untuk ditampilkan
+ Satelit
+ Lintasan
+ Radar
+ Pasangan
+ Jelajah
+ Dekoder CW
+ Peta
+ Pengaturan
+ Lainnya
+ Log
+ AMSAT
+ Status Satelit AMSAT
+ Diperbarui:
+ Aktif
+ TLM/beacon
+ Tidak terdengar
+ Konflik
+ Name
+ Gagal memuat - periksa jaringan dan coba lagi
+ Tidak ada laporan untuk periode ini
+ Tutup
+
+ Jenis: %s
+ Pilih jenis satelit
+ Id - Nama
+ Bersihkan
+ Bersihkan semua
+ Pilih semua
+ Pastikan kata kunci pencarian Anda benar dan DB sudah diperbarui
+ Peringatan\!
+
+ Ada lebih dari 9000 satelit yang terdaftar di aplikasi ini.
+ Tidak masuk akal untuk melacak semuanya sekaligus.
+ \n\nSelalu coba persempit daftar hanya ke satelit yang
+ Anda minati melalui pencarian dan pemilih jenis.
+ Filter lintasan
+ Elevasi minimal
+ Waktu ke depan
+ Jendela AOS
+ Balik jendela AOS
+ DeepSpace (periode >225 mnt)
+ -- : -- : --
+ Pilih jenis modulasi
+ %05d
+ Elevasi: %.1f°
+ DeepSpace
+ Ketinggian: %d km
+ %03d° - %03d°
+
+ Pastikan filter Anda benar dan Anda sudah memilih satelit
+ Tidak ada lintasan satelit mendatang untuk ditampilkan
+ Selamat datang di Look4Sat\!
+
+ Pastikan Anda mengatur posisi melalui GPS, Lat/Lon atau QTH di Pengaturan.
+ \n\nPerbarui database setidaknya seminggu sekali untuk prediksi yang akurat.
+ Apa yang baru di Look4Sat
+
+ * BARU: Halaman status satelit AMSAT - tabel status langsung (warna resmi), jumlah laporan, laporan detail per satelit/hari
+ * Log dikelompokkan per lintasan satelit (sesi = satelit + waktu AOS), garis pemisah antar sesi
+ * GPS kini hanya menampilkan sukses saat posisi benar-benar didapat (timeout 15 dtk, cek izin)
+ * Pesan kegagalan jelas saat database satelit gagal diunduh
+ * Frekuensi log mengikuti panel Doppler secara real-time; visual hapus geser dipulihkan
+ * Perbaikan bahasa Indonesia (values-id)
+ Kembali
+ Beri tahu
+ Azimuth
+ %.1f°
+ Elevasi
+ %.1f°
+ Ketinggian
+ %.0f km
+ Jarak
+ %.0f km
+ Gerhana
+ Downlink
+ Uplink
+ %.4f
+ %.4f - %.4f
+ - - . - -
+ Satelit ini tidak memiliki transceiver
+ Tambah
+ Transceiver satelit:
+ Terbalik: %s
+ Mode: %s
+ Tidak
+ Ya
+ Terlihat
+ Kalkulator Frekuensi Doppler
+ Masukkan frekuensi TX (MHz)
+ Masukkan frekuensi RX (MHz)
+ Offset (kHz)
+ Untuk transponder linier, ketik satu frekuensi untuk melihat frekuensi lainnya
+ Dekoder CW
+ Mulai
+ Berhenti
+ Bersihkan
+ Sebelumnya
+ Berikutnya
+ © Kontributor OpenStreetMap
+ Azimuth: %.1f°
+ Elevasi: %.1f°
+ Ketinggian: %.0f km
+ Jarak: %.0f km
+ Lintang: %.1f°
+ Bujur: %.1f°
+ QTH: %s
+ Fase: %.1f°
+ Gerhana
+ Periode: %.0f mnt
+ Kecepatan: %.2f km/d
+ Visibilitas: %s
+ Terlihat
+ Look4Sat Pro v%s
+ https://play.google.com/store/apps/details?id=com.rtbishop.look4sat
+ Donasi
+ https://ko-fi.com/rt_bishop
+ F-Droid
+ https://f-droid.org/en/packages/com.rtbishop.look4sat/
+ GitHub
+ https://github.com/rt-bishop/Look4Sat/
+ GPLv3
+ https://www.gnu.org/licenses/gpl-3.0.html
+ Kebijakan Privasi
+ https://sites.google.com/view/look4sat-privacy-policy/home
+ Diperbarui: %s
+ d MMM yyyy - HH:mm:ss
+ Posisi stasiun
+ GPS
+ Tidak dapat mengambil lokasi - periksa izin dan sinyal GPS/jaringan
+ Input
+ Lokasi yang dimasukkan tidak valid
+ QTH
+ Lokator QTH tidak valid
+ Posisi berhasil diperbarui
+ Pengaturan posisi stasiun
+ Atur garis lintang stasiun Anda
+ Atur garis bujur stasiun Anda
+ Pengaturan lokator QTH
+ Atur posisi stasiun menggunakan lokator
+ Data satelit
+ Satelit: %s
+ Transceiver: %s
+ Perbarui
+ URL Kustom
+ Bersihkan
+ Data berhasil dibersihkan
+ Pembaruan berhasil diselesaikan
+ Pembaruan gagal - periksa jaringan Anda
+ Tidak ada satelit yang diimpor. Pilih file TLE/3LE (.txt) atau OMM (.csv) yang valid.
+ Tidak ada transceiver yang diimpor. Pilih file SatNOGS (.json) yang valid.
+ Sumber data kustom
+ URL TLE Kustom
+ URL transceiver kustom
+ URL (HTTPS)
+ Setel ulang ke URL bawaan
+ Keluaran data
+ Jaringan
+ Bluetooth
+ CAT
+ Kontrol Radio
+ Kontrol Radio CAT
+ Model Radio
+ Alamat BT Radio TX
+ Alamat BT Radio RX
+ Nama Radio TX
+ Nama Radio RX
+ Aktifkan Kontrol CAT
+ Keluaran data jaringan
+ Aktifkan keluaran rotator
+ IP:Port
+ Format
+ Aktifkan keluaran frekuensi
+ IP:Port
+ Format
+ Keluaran data Bluetooth
+ Aktifkan keluaran rotator
+ Id perangkat
+ Format data
+ Aktifkan keluaran frekuensi
+ Id perangkat
+ Format data
+ Periksa izin bluetooth Anda
+ Periksa izin jaringan Anda
+ Melacak: %s
+ Lintang: %s°
+ Bujur: %s°
+ QTH: %s
+ Hubungkan
+ Putuskan
+ Lacak
+ Berhenti
+ Server log WaveLog
+ Alamat server
+ Kunci API
+ ID stasiun
+ Unggah otomatis
+ Uji koneksi
+ Unggah sekarang
+ Log
+ Pilih transponder
+ Tanda panggil
+ Mode
+ Tersimpan ke log lokal
+ Konfigurasikan WaveLog di Pengaturan terlebih dahulu
+ Belum ada entri log
+ Grid QTH (%1$s) tidak cocok dengan grid stasiun (%2$s). Tetap unggah?
+ Abaikan dan unggah
+ Batal
+ Salin
+ Urungkan
+ Waktu
+ Frek.
+ Satelit
+ Panggilan
+ Terkirim
+ Pengaturan lainnya
+ Pengaturan UI
+ Urutan halaman
+ Menu utama (bilah bawah)
+ Menu lainnya
+ Pindah ke menu lainnya
+ Kembalikan ke menu utama
+ Tetap (tidak dapat dipindahkan)
+ Setel ulang urutan
+ Tampilkan waktu lintasan dalam UTC
+ Aktifkan pembaruan data otomatis
+ Aktifkan animasi sapuan radar
+ Gunakan sensor untuk memutar tampilan radar
+ Aktifkan filter mode malam merah
+ Sorotan elevasi
+ Rendah < %1$d°
+ Sedang %1$d–%2$d°
+ Tinggi > %1$d°
+ BG7NTA & penulis asli mengucapkan terima kasih
+
+ * Pengguna dan kontributor Look4Sat!
+ \n* David A. B. Johnson (predict4java)
+ \n* Dave Moten (predict4java)
+ \n* Alexandru Csete (Gpredict)
+ \n* Dr T.S. Kelso (Celestrak)
+ \n* Libre Space Foundation (SatNOGS)
+ \n* xdsopl dan kontributor Robot36!
+ \n* BA7OPF (fitur pencocokan lintasan)
+ \n* BG7NTA
+ Aplikasi ini hadir tanpa jaminan
+
diff --git a/core/presentation/src/main/res/values-in-rID/strings.xml b/core/presentation/src/main/res/values-in-rID/strings.xml
new file mode 100644
index 00000000..dd01248a
--- /dev/null
+++ b/core/presentation/src/main/res/values-in-rID/strings.xml
@@ -0,0 +1,252 @@
+
+
+ Look4Sat Pro
+ Terima
+ Batal
+ Tidak ada data untuk ditampilkan
+ Satelit
+ Lintasan
+ Radar
+ Pasangan
+ Jelajah
+ Dekoder CW
+ Peta
+ Pengaturan
+ Lainnya
+ Log
+ AMSAT
+ Status Satelit AMSAT
+ Diperbarui:
+ Aktif
+ TLM/beacon
+ Tidak terdengar
+ Konflik
+ Name
+ Gagal memuat - periksa jaringan dan coba lagi
+ Tidak ada laporan untuk periode ini
+ Tutup
+ Jenis: %s
+ Pilih jenis satelit
+ Id - Nama
+ Bersihkan
+ Bersihkan semua
+ Pilih semua
+ Pastikan kata kunci pencarian Anda benar dan DB sudah diperbarui
+ Peringatan\!
+
+ Ada lebih dari 9000 satelit yang terdaftar di aplikasi ini.
+ Tidak masuk akal untuk melacak semuanya sekaligus.
+ \n\nSelalu coba persempit daftar hanya ke satelit yang
+ Anda minati melalui pencarian dan pemilih jenis.
+ Filter lintasan
+ Elevasi minimal
+ Waktu ke depan
+ Jendela AOS
+ Balik jendela AOS
+ DeepSpace (periode >225 mnt)
+ -- : -- : --
+ Pilih jenis modulasi
+ %05d
+ Elevasi: %.1f°
+ DeepSpace
+ Ketinggian: %d km
+ %03d° - %03d°
+
+ Pastikan filter Anda benar dan Anda sudah memilih satelit
+ Tidak ada lintasan satelit mendatang untuk ditampilkan
+ Selamat datang di Look4Sat\!
+
+ Pastikan Anda mengatur posisi melalui GPS, Lat/Lon atau QTH di Pengaturan.
+ \n\nPerbarui database setidaknya seminggu sekali untuk prediksi yang akurat.
+ Apa yang baru di Look4Sat
+
+ * BARU: Halaman status satelit AMSAT - tabel status langsung (warna resmi), jumlah laporan, laporan detail per satelit/hari
+ * Log dikelompokkan per lintasan satelit (sesi = satelit + waktu AOS), garis pemisah antar sesi
+ * GPS kini hanya menampilkan sukses saat posisi benar-benar didapat (timeout 15 dtk, cek izin)
+ * Pesan kegagalan jelas saat database satelit gagal diunduh
+ * Frekuensi log mengikuti panel Doppler secara real-time; visual hapus geser dipulihkan
+ * Perbaikan bahasa Indonesia (values-id)
+ Kembali
+ Beri tahu
+ Azimuth
+ %.1f°
+ Elevasi
+ %.1f°
+ Ketinggian
+ %.0f km
+ Jarak
+ %.0f km
+ Gerhana
+ Downlink
+ Uplink
+ %.4f
+ %.4f - %.4f
+ - - . - -
+ Satelit ini tidak memiliki transceiver
+ Tambah
+ Transceiver satelit:
+ Terbalik: %s
+ Mode: %s
+ Tidak
+ Ya
+ Terlihat
+ Kalkulator Frekuensi Doppler
+ Masukkan frekuensi TX (MHz)
+ Masukkan frekuensi RX (MHz)
+ Offset (kHz)
+ Untuk transponder linier, ketik satu frekuensi untuk melihat frekuensi lainnya
+ Dekoder CW
+ Mulai
+ Berhenti
+ Bersihkan
+ Sebelumnya
+ Berikutnya
+ © Kontributor OpenStreetMap
+ Azimuth: %.1f°
+ Elevasi: %.1f°
+ Ketinggian: %.0f km
+ Jarak: %.0f km
+ Lintang: %.1f°
+ Bujur: %.1f°
+ QTH: %s
+ Fase: %.1f°
+ Gerhana
+ Periode: %.0f mnt
+ Kecepatan: %.2f km/d
+ Visibilitas: %s
+ Terlihat
+ Look4Sat Pro v%s
+ https://play.google.com/store/apps/details?id=com.rtbishop.look4sat
+ Donasi
+ https://ko-fi.com/rt_bishop
+ F-Droid
+ https://f-droid.org/en/packages/com.rtbishop.look4sat/
+ GitHub
+ https://github.com/rt-bishop/Look4Sat/
+ GPLv3
+ https://www.gnu.org/licenses/gpl-3.0.html
+ Kebijakan Privasi
+ https://sites.google.com/view/look4sat-privacy-policy/home
+ Diperbarui: %s
+ d MMM yyyy - HH:mm:ss
+ Posisi stasiun
+ GPS
+ Tidak dapat mengambil lokasi - periksa izin dan sinyal GPS/jaringan
+ Input
+ Lokasi yang dimasukkan tidak valid
+ QTH
+ Lokator QTH tidak valid
+ Posisi berhasil diperbarui
+ Pengaturan posisi stasiun
+ Atur garis lintang stasiun Anda
+ Atur garis bujur stasiun Anda
+ Pengaturan lokator QTH
+ Atur posisi stasiun menggunakan lokator
+ Data satelit
+ Satelit: %s
+ Transceiver: %s
+ Perbarui
+ URL Kustom
+ Bersihkan
+ Data berhasil dibersihkan
+ Pembaruan berhasil diselesaikan
+ Pembaruan gagal - periksa jaringan Anda
+ Tidak ada satelit yang diimpor. Pilih file TLE/3LE (.txt) atau OMM (.csv) yang valid.
+ Tidak ada transceiver yang diimpor. Pilih file SatNOGS (.json) yang valid.
+ Sumber data kustom
+ URL TLE Kustom
+ URL transceiver kustom
+ URL (HTTPS)
+ Setel ulang ke URL bawaan
+ Keluaran data
+ Jaringan
+ Bluetooth
+ CAT
+ Kontrol Radio
+ Kontrol Radio CAT
+ Model Radio
+ Alamat BT Radio TX
+ Alamat BT Radio RX
+ Nama Radio TX
+ Nama Radio RX
+ Aktifkan Kontrol CAT
+ Keluaran data jaringan
+ Aktifkan keluaran rotator
+ IP:Port
+ Format
+ Aktifkan keluaran frekuensi
+ IP:Port
+ Format
+ Keluaran data Bluetooth
+ Aktifkan keluaran rotator
+ Id perangkat
+ Format data
+ Aktifkan keluaran frekuensi
+ Id perangkat
+ Format data
+ Periksa izin bluetooth Anda
+ Periksa izin jaringan Anda
+ Melacak: %s
+ Lintang: %s°
+ Bujur: %s°
+ QTH: %s
+ Hubungkan
+ Putuskan
+ Lacak
+ Berhenti
+ Server log WaveLog
+ Alamat server
+ Kunci API
+ ID stasiun
+ Unggah otomatis
+ Uji koneksi
+ Unggah sekarang
+ Log
+ Pilih transponder
+ Tanda panggil
+ Mode
+ Tersimpan ke log lokal
+ Konfigurasikan WaveLog di Pengaturan terlebih dahulu
+ Belum ada entri log
+ Grid QTH (%1$s) tidak cocok dengan grid stasiun (%2$s). Tetap unggah?
+ Abaikan dan unggah
+ Batal
+ Salin
+ Urungkan
+ Waktu
+ Frek.
+ Satelit
+ Panggilan
+ Terkirim
+ Tidak dikelompokkan
+ Pengaturan lainnya
+ Pengaturan UI
+ Urutan halaman
+ Menu utama (bilah bawah)
+ Menu lainnya
+ Pindah ke menu lainnya
+ Kembalikan ke menu utama
+ Tetap (tidak dapat dipindahkan)
+ Setel ulang urutan
+ Tampilkan waktu lintasan dalam UTC
+ Aktifkan pembaruan data otomatis
+ Aktifkan animasi sapuan radar
+ Gunakan sensor untuk memutar tampilan radar
+ Aktifkan filter mode malam merah
+ Sorotan elevasi
+ Rendah < %1$d°
+ Sedang %1$d–%2$d°
+ Tinggi > %1$d°
+ BG7NTA & penulis asli mengucapkan terima kasih
+
+ * Pengguna dan kontributor Look4Sat!
+ \n* David A. B. Johnson (predict4java)
+ \n* Dave Moten (predict4java)
+ \n* Alexandru Csete (Gpredict)
+ \n* Dr T.S. Kelso (Celestrak)
+ \n* Libre Space Foundation (SatNOGS)
+ \n* xdsopl dan kontributor Robot36!
+ \n* BA7OPF (fitur pencocokan lintasan)
+ \n* BG7NTA
+ Aplikasi ini hadir tanpa jaminan
+
diff --git a/core/presentation/src/main/res/values-in/strings.xml b/core/presentation/src/main/res/values-in/strings.xml
new file mode 100644
index 00000000..dd01248a
--- /dev/null
+++ b/core/presentation/src/main/res/values-in/strings.xml
@@ -0,0 +1,252 @@
+
+
+ Look4Sat Pro
+ Terima
+ Batal
+ Tidak ada data untuk ditampilkan
+ Satelit
+ Lintasan
+ Radar
+ Pasangan
+ Jelajah
+ Dekoder CW
+ Peta
+ Pengaturan
+ Lainnya
+ Log
+ AMSAT
+ Status Satelit AMSAT
+ Diperbarui:
+ Aktif
+ TLM/beacon
+ Tidak terdengar
+ Konflik
+ Name
+ Gagal memuat - periksa jaringan dan coba lagi
+ Tidak ada laporan untuk periode ini
+ Tutup
+ Jenis: %s
+ Pilih jenis satelit
+ Id - Nama
+ Bersihkan
+ Bersihkan semua
+ Pilih semua
+ Pastikan kata kunci pencarian Anda benar dan DB sudah diperbarui
+ Peringatan\!
+
+ Ada lebih dari 9000 satelit yang terdaftar di aplikasi ini.
+ Tidak masuk akal untuk melacak semuanya sekaligus.
+ \n\nSelalu coba persempit daftar hanya ke satelit yang
+ Anda minati melalui pencarian dan pemilih jenis.
+ Filter lintasan
+ Elevasi minimal
+ Waktu ke depan
+ Jendela AOS
+ Balik jendela AOS
+ DeepSpace (periode >225 mnt)
+ -- : -- : --
+ Pilih jenis modulasi
+ %05d
+ Elevasi: %.1f°
+ DeepSpace
+ Ketinggian: %d km
+ %03d° - %03d°
+
+ Pastikan filter Anda benar dan Anda sudah memilih satelit
+ Tidak ada lintasan satelit mendatang untuk ditampilkan
+ Selamat datang di Look4Sat\!
+
+ Pastikan Anda mengatur posisi melalui GPS, Lat/Lon atau QTH di Pengaturan.
+ \n\nPerbarui database setidaknya seminggu sekali untuk prediksi yang akurat.
+ Apa yang baru di Look4Sat
+
+ * BARU: Halaman status satelit AMSAT - tabel status langsung (warna resmi), jumlah laporan, laporan detail per satelit/hari
+ * Log dikelompokkan per lintasan satelit (sesi = satelit + waktu AOS), garis pemisah antar sesi
+ * GPS kini hanya menampilkan sukses saat posisi benar-benar didapat (timeout 15 dtk, cek izin)
+ * Pesan kegagalan jelas saat database satelit gagal diunduh
+ * Frekuensi log mengikuti panel Doppler secara real-time; visual hapus geser dipulihkan
+ * Perbaikan bahasa Indonesia (values-id)
+ Kembali
+ Beri tahu
+ Azimuth
+ %.1f°
+ Elevasi
+ %.1f°
+ Ketinggian
+ %.0f km
+ Jarak
+ %.0f km
+ Gerhana
+ Downlink
+ Uplink
+ %.4f
+ %.4f - %.4f
+ - - . - -
+ Satelit ini tidak memiliki transceiver
+ Tambah
+ Transceiver satelit:
+ Terbalik: %s
+ Mode: %s
+ Tidak
+ Ya
+ Terlihat
+ Kalkulator Frekuensi Doppler
+ Masukkan frekuensi TX (MHz)
+ Masukkan frekuensi RX (MHz)
+ Offset (kHz)
+ Untuk transponder linier, ketik satu frekuensi untuk melihat frekuensi lainnya
+ Dekoder CW
+ Mulai
+ Berhenti
+ Bersihkan
+ Sebelumnya
+ Berikutnya
+ © Kontributor OpenStreetMap
+ Azimuth: %.1f°
+ Elevasi: %.1f°
+ Ketinggian: %.0f km
+ Jarak: %.0f km
+ Lintang: %.1f°
+ Bujur: %.1f°
+ QTH: %s
+ Fase: %.1f°
+ Gerhana
+ Periode: %.0f mnt
+ Kecepatan: %.2f km/d
+ Visibilitas: %s
+ Terlihat
+ Look4Sat Pro v%s
+ https://play.google.com/store/apps/details?id=com.rtbishop.look4sat
+ Donasi
+ https://ko-fi.com/rt_bishop
+ F-Droid
+ https://f-droid.org/en/packages/com.rtbishop.look4sat/
+ GitHub
+ https://github.com/rt-bishop/Look4Sat/
+ GPLv3
+ https://www.gnu.org/licenses/gpl-3.0.html
+ Kebijakan Privasi
+ https://sites.google.com/view/look4sat-privacy-policy/home
+ Diperbarui: %s
+ d MMM yyyy - HH:mm:ss
+ Posisi stasiun
+ GPS
+ Tidak dapat mengambil lokasi - periksa izin dan sinyal GPS/jaringan
+ Input
+ Lokasi yang dimasukkan tidak valid
+ QTH
+ Lokator QTH tidak valid
+ Posisi berhasil diperbarui
+ Pengaturan posisi stasiun
+ Atur garis lintang stasiun Anda
+ Atur garis bujur stasiun Anda
+ Pengaturan lokator QTH
+ Atur posisi stasiun menggunakan lokator
+ Data satelit
+ Satelit: %s
+ Transceiver: %s
+ Perbarui
+ URL Kustom
+ Bersihkan
+ Data berhasil dibersihkan
+ Pembaruan berhasil diselesaikan
+ Pembaruan gagal - periksa jaringan Anda
+ Tidak ada satelit yang diimpor. Pilih file TLE/3LE (.txt) atau OMM (.csv) yang valid.
+ Tidak ada transceiver yang diimpor. Pilih file SatNOGS (.json) yang valid.
+ Sumber data kustom
+ URL TLE Kustom
+ URL transceiver kustom
+ URL (HTTPS)
+ Setel ulang ke URL bawaan
+ Keluaran data
+ Jaringan
+ Bluetooth
+ CAT
+ Kontrol Radio
+ Kontrol Radio CAT
+ Model Radio
+ Alamat BT Radio TX
+ Alamat BT Radio RX
+ Nama Radio TX
+ Nama Radio RX
+ Aktifkan Kontrol CAT
+ Keluaran data jaringan
+ Aktifkan keluaran rotator
+ IP:Port
+ Format
+ Aktifkan keluaran frekuensi
+ IP:Port
+ Format
+ Keluaran data Bluetooth
+ Aktifkan keluaran rotator
+ Id perangkat
+ Format data
+ Aktifkan keluaran frekuensi
+ Id perangkat
+ Format data
+ Periksa izin bluetooth Anda
+ Periksa izin jaringan Anda
+ Melacak: %s
+ Lintang: %s°
+ Bujur: %s°
+ QTH: %s
+ Hubungkan
+ Putuskan
+ Lacak
+ Berhenti
+ Server log WaveLog
+ Alamat server
+ Kunci API
+ ID stasiun
+ Unggah otomatis
+ Uji koneksi
+ Unggah sekarang
+ Log
+ Pilih transponder
+ Tanda panggil
+ Mode
+ Tersimpan ke log lokal
+ Konfigurasikan WaveLog di Pengaturan terlebih dahulu
+ Belum ada entri log
+ Grid QTH (%1$s) tidak cocok dengan grid stasiun (%2$s). Tetap unggah?
+ Abaikan dan unggah
+ Batal
+ Salin
+ Urungkan
+ Waktu
+ Frek.
+ Satelit
+ Panggilan
+ Terkirim
+ Tidak dikelompokkan
+ Pengaturan lainnya
+ Pengaturan UI
+ Urutan halaman
+ Menu utama (bilah bawah)
+ Menu lainnya
+ Pindah ke menu lainnya
+ Kembalikan ke menu utama
+ Tetap (tidak dapat dipindahkan)
+ Setel ulang urutan
+ Tampilkan waktu lintasan dalam UTC
+ Aktifkan pembaruan data otomatis
+ Aktifkan animasi sapuan radar
+ Gunakan sensor untuk memutar tampilan radar
+ Aktifkan filter mode malam merah
+ Sorotan elevasi
+ Rendah < %1$d°
+ Sedang %1$d–%2$d°
+ Tinggi > %1$d°
+ BG7NTA & penulis asli mengucapkan terima kasih
+
+ * Pengguna dan kontributor Look4Sat!
+ \n* David A. B. Johnson (predict4java)
+ \n* Dave Moten (predict4java)
+ \n* Alexandru Csete (Gpredict)
+ \n* Dr T.S. Kelso (Celestrak)
+ \n* Libre Space Foundation (SatNOGS)
+ \n* xdsopl dan kontributor Robot36!
+ \n* BA7OPF (fitur pencocokan lintasan)
+ \n* BG7NTA
+ Aplikasi ini hadir tanpa jaminan
+
diff --git a/core/presentation/src/main/res/values-tr/strings.xml b/core/presentation/src/main/res/values-tr/strings.xml
index 7e65fb7b..6a924337 100644
--- a/core/presentation/src/main/res/values-tr/strings.xml
+++ b/core/presentation/src/main/res/values-tr/strings.xml
@@ -10,8 +10,22 @@
Uydular
Geçişler
Radar
+ CW Dekoder
Harita
Ayarlar
+ Daha Fazla
+ Günlük
+ AMSAT
+ AMSAT Uydu Durumu
+ Güncellendi:
+ Aktif
+ TLM/işaret
+ Duyulmadı
+ Çelişkili
+ Name
+ Yükleme başarısız - ağı kontrol edip tekrar deneyin
+ Bu dönem için rapor yok
+ Kapat
Uydu türü: %s
@@ -50,13 +64,13 @@
Ayarlar\'dan GPS, Enlem/Boylam veya QTH kullanarak konumunuzu belirlediğinizden emin olun.
\n\nDoğru tahminler alabilmek için veritabanını en az haftada bir güncelleyin.
What\'s new in Look4Sat
-
- * Switched to short-form commands in NetworkReporter, by theojalba
- \n* Added CAT radio control for full-duplex SAT operation, by jcmerg
- \n* Added normalized time for passes AOS/LOS, fixed refresh state bug
- \n* Added multiple performance tweaks, improved passes calculation
- \n* Fixed UTC pass time problem mentioned in issue #201
-
+
+ * YENİ: AMSAT uydu durum sayfası - canlı durum tablosu (resmi renkler), rapor sayıları, uydu/gün bazında detaylı raporlar
+ * Günlükler uydu geçişine göre gruplanır (oturum = uydu + AOS zamanı), oturumlar arasında ayırıcı çizgi
+ * GPS artık yalnızca gerçek konum alındığında başarı gösterir (15 sn zaman aşımı, izin kontrolü)
+ * Uydu veritabanı indirilemediğinde net hata mesajı gösterilir
+ * Günlük frekansları Doppler panelini gerçek zamanlı takip eder; kaydırarak silme görselleri düzeltildi
+ * Endonezya dili düzeltmesi (values-id)
Geri
@@ -103,7 +117,7 @@
Görünür
- Look4Sat v%s
+ Look4Sat Pro v%s
https://play.google.com/store/apps/details?id=com.rtbishop.look4sat
Bağış yap
https://ko-fi.com/rt_bishop
@@ -121,7 +135,7 @@
İstasyon konumu
GPS
- Konum izinlerinizi kontrol edin
+ Konum alınamıyor - izinleri ve GPS/ağ sinyalini kontrol edin
Manuel giriş
Geçersiz konum girildi
QTH
@@ -137,15 +151,17 @@
Uydular: %s
Transceiver\'lar: %s
Güncelle
- İçe aktar
+ Özel URL
Temizle
Veriler başarıyla temizlendi
Güncelleme başarıyla tamamlandı
+ Güncelleme başarısız - ağınızı kontrol edin
Özel veri kaynakları
Özel TLE URL
Özel transceiver URL
URL (HTTPS)
+ Varsayılan URL\'ye sıfırla
Veri aktarımı
Ağ
@@ -180,7 +196,48 @@
Bluetooth izninizi kontrol edin
Ağ izninizi kontrol edin
+ İzleniyor: %s
+ Enlem: %s°
+ Boylam: %s°
+ QTH: %s
+ Bağlan
+ Bağlantıyı Kes
+ Takip
+ Dur
+ WaveLog günlük sunucusu
+ Sunucu adresi
+ API anahtarı
+ İstasyon kimliği
+ Otomatik yükleme
+ Bağlantıyı test et
+ Şimdi yükle
+ Günlük
+ Transponder seç
+ Çağrı işareti
+ Mod
+ Yerel günlüğe kaydedildi
+ Önce Ayarlar\'da WaveLog\'u yapılandırın
+ Henüz günlük kaydı yok
+ QTH ızgarası (%1$s) istasyon ızgarasıyla (%2$s) eşleşmiyor. Yine de yüklensin mi?
+ Yoksay ve yükle
+ İptal
+ Kopyala
+ Geri al
+ Zaman
+ Frekans
+ Uydu
+ Çağrı
+ Gönderildi
+ Gruplanmamış
Diğer ayarlar
+ UI Ayarları
+ Sayfa sırası
+ Ana menü (alt çubuk)
+ Daha fazla menü
+ Daha fazla menüye taşı
+ Ana menüye geri taşı
+ Sabit (taşınamaz)
+ Sıralamayı sıfırla
Geçiş saatini UTC olarak göster
Otomatik veri güncellemeyi etkinleştir
Radar taramasını etkinleştir
@@ -192,14 +249,16 @@
Orta %1$d-%2$d°
Yüksek > %1$d°
- Teşekkürler
+ BG7NTA ve orijinal yazar teşekkür eder
• Look4Sat users and contributors!
\n• David A. B. Johnson (predict4java)
\n• Dave Moten (predict4java)
\n• Alexandru Csete (Gpredict)
\n• Dr T.S. Kelso (Celestrak)
- \n• Libre Space Foundation (SatNOGS)
+ \n• Libre Space Foundation (SatNOGS)
+ \n• BA7OPF (pass matching feature)
+ \n• BG7NTA
Bu uygulama herhangi bir garanti sunmaz
diff --git a/core/presentation/src/main/res/values-zh/strings.xml b/core/presentation/src/main/res/values-zh/strings.xml
index 220613c1..ae2b403d 100644
--- a/core/presentation/src/main/res/values-zh/strings.xml
+++ b/core/presentation/src/main/res/values-zh/strings.xml
@@ -10,8 +10,23 @@
过境
雷达
匹配
+ 漫游
+ CW解码
地图
设置
+ 更多
+ 日志
+ AMSAT
+ AMSAT 卫星状态
+ 更新:
+ 活跃
+ 仅遥测
+ 未听到
+ 矛盾
+ Name
+ 加载失败,请检查网络后重试
+ 该时段无报告
+ 关闭
类型:%s
@@ -38,6 +53,14 @@
没有即将过境的卫星
欢迎来到 Look4Sat\!
请务必在设置中通过GPS、经纬度或QTH定位您的位置\n建议至少每周更新一次数据库,以确保预测结果的准确性
+ Look4Sat Pro 更新内容
+
+ * 新增: AMSAT 卫星状态页 - 实时状态表格(官网配色)、报告数量、逐卫星/逐日详细报告
+ * 日志按场次分组(场次 = 卫星 + AOS 时间), 组间横线分隔
+ * GPS 真正定位成功才会提示成功(15 秒超时, 权限检查)
+ * 卫星数据库下载失败时有明确失败提示
+ * 日志频率实时跟随多普勒面板; 左滑删除视觉恢复
+ * 印尼语识别修复(values-id)
后退
@@ -94,7 +117,7 @@
站位
GPS 定位
- 检查您的位置权限
+ 无法获取位置,请检查定位权限和GPS/网络信号
输入位置
输入的位置无效
QTH 网格
@@ -110,10 +133,11 @@
卫星:%s
收发器:%s
在线更新
- 导入文件
+ 自定义URL
清空
数据清空成功
更新成功
+ 更新失败,请检查网络
未导入卫星。请选择有效的 TLE/3LE (.txt) 或 OMM (.csv) 文件。
未导入收发器。请选择有效的 SatNOGS (.json) 文件。
@@ -155,7 +179,48 @@
接收电台名称
启用 CAT 控制
+ 跟踪: %s
+ 纬度: %s°
+ 经度: %s°
+ QTH: %s
+ 连接
+ 断开
+ 跟踪
+ 停止
+ WaveLog 日志服务器
+ 服务器地址
+ API 密钥
+ 站点 ID
+ 自动上传
+ 测试连接
+ 手动上传
+ 日志
+ 选择转发器
+ 对方呼号
+ 模式
+ 已存入本地日志
+ 请先在设置中配置 WaveLog
+ 暂无日志记录
+ 当前 QTH 网格(%1$s)与站点网格(%2$s)不一致,仍要上传?
+ 忽略并上传
+ 取消
+ 复制
+ 撤销
+ 时间
+ 频率
+ 卫星
+ 呼号
+ 已传
+ 未分组
其他设置
+ UI设置
+ 页面顺序
+ 主菜单(底部栏)
+ 更多菜单
+ 移入更多菜单
+ 移回主菜单
+ 固定(不可移动)
+ 重置顺序
以 UTC 时间显示
启用卫星数据自动更新
启用雷达扫描动画
@@ -167,7 +232,7 @@
中 %1$d-%2$d°
高 > %1$d°
- 我要感谢:
+ BG7NTA 与原作者感谢:
• Look4Sat 所有用户及贡献者!
\n• David A. B. Johnson (predict4java)
@@ -175,7 +240,9 @@
\n• Alexandru Csete (Gpredict)
\n• Dr T.S. Kelso (Celestrak)
\n• Libre Space Foundation (SatNOGS)
- \n• xdsopl 和 Robot36 贡献者!
+ \n• xdsopl 和 Robot36 贡献者!
+ \n• BA7OPF(过境匹配功能)
+ \n• BG7NTA
该应用程序不提供任何保修.
diff --git a/core/presentation/src/main/res/values/strings.xml b/core/presentation/src/main/res/values/strings.xml
index d476eb45..d802234d 100644
--- a/core/presentation/src/main/res/values/strings.xml
+++ b/core/presentation/src/main/res/values/strings.xml
@@ -1,7 +1,7 @@
- Look4Sat
+ Look4Sat Pro
Accept
Cancel
No data to show
@@ -11,8 +11,23 @@
Passes
Radar
Match
+ Roaming
+ CW Decoder
Map
Settings
+ More
+ Log
+ AMSAT
+ AMSAT Satellite Status
+ Updated:
+ Active
+ TLM/Beacon
+ Not Heard
+ Conflicting
+ Name
+ Load failed - check network and retry
+ No reports for this period
+ Close
Type: %s
@@ -51,10 +66,13 @@
Make sure to set your position via GPS, Lat/Lon or QTH in Settings.
\n\nPlease update the database at least weekly to get accurate predictions.
What\'s new in Look4Sat
-
- * Added required tweaks to support Android 17 (API 37)
- \n\n* Added ACCESS_LOCAL_NETWORK permission check to support network data output
-
+
+ * NEW: AMSAT satellite status page - live status grid (official colors), report counts, detailed reports per satellite/day
+ * Log entries grouped by satellite pass (session ID = satellite + AOS time), divider lines between sessions
+ * GPS now only reports success when a real fix is acquired (15s timeout, permission check)
+ * Data update shows a clear failure message when the satellite database cannot be downloaded
+ * Log frequencies follow the Doppler panel in real time; swipe-to-delete visuals restored
+ * Indonesian locale fix (values-id)
Back
@@ -111,7 +129,7 @@
Visible
- Look4Sat v%s
+ Look4Sat Pro v%s
https://play.google.com/store/apps/details?id=com.rtbishop.look4sat
Donate
https://ko-fi.com/rt_bishop
@@ -129,7 +147,7 @@
Station position
GPS
- Check your location permissions
+ Unable to get location - check permission and GPS/network signal
Input
Invalid location entered
QTH
@@ -145,10 +163,11 @@
Satellites: %s
Transceivers: %s
Update
- Import
+ Custom URL
Clear
Data was cleared successfully
Update completed successfully
+ Update failed - check your network
No satellites imported. Select a valid TLE/3LE (.txt) or OMM (.csv) file.
No transceivers imported. Select a valid SatNOGS (.json) file.
@@ -156,6 +175,7 @@
Custom TLE URL
Custom transceivers URL
URL (HTTPS)
+ Reset to default URL
Data output
Network
@@ -190,7 +210,48 @@
Check your bluetooth permission
Check your network permission
+ Tracking: %s
+ Lat: %s°
+ Lon: %s°
+ Qth: %s
+ Connect
+ Disconnect
+ Track
+ Stop
+ WaveLog log server
+ Server address
+ API key
+ Station ID
+ Auto upload
+ Test connection
+ Upload now
+ Log
+ Select transponder
+ Callsign
+ Mode
+ Saved to local log
+ Configure WaveLog in Settings first
+ No log entries yet
+ QTH grid (%1$s) does not match station grid (%2$s). Upload anyway?
+ Ignore and upload
+ Cancel
+ Copy
+ Undo
+ Time
+ Freq
+ Satellite
+ Call
+ Sent
+ Ungrouped
Other settings
+ UI Settings
+ Page order
+ Main menu (bottom bar)
+ More menu
+ Move to more menu
+ Move back to main menu
+ Fixed (cannot be moved)
+ Reset order
Show pass time in UTC
Enable automatic data update
Enable radar sweep animation
@@ -202,7 +263,7 @@
Mid %1$d–%2$d°
High > %1$d°
- I would like to say thanks to
+ BG7NTA & the original author would like to thank
* Look4Sat users and contributors!
\n* David A. B. Johnson (predict4java)
@@ -211,6 +272,8 @@
\n* Dr T.S. Kelso (Celestrak)
\n* Libre Space Foundation (SatNOGS)
\n* xdsopl and Robot36 contributors!
+ \n* BA7OPF (pass matching feature)
+ \n* BG7NTA
The app comes with no warranty
diff --git a/feature/cw/build.gradle.kts b/feature/cw/build.gradle.kts
new file mode 100644
index 00000000..3a781ca9
--- /dev/null
+++ b/feature/cw/build.gradle.kts
@@ -0,0 +1,38 @@
+import com.android.build.api.dsl.LibraryExtension
+import com.android.build.api.variant.CanProduceConsumerProguardFiles
+
+plugins {
+ alias(libs.plugins.convention.featurePlugin)
+}
+
+android {
+ namespace = "com.rtbishop.look4sat.feature.cw"
+ compileOptions {
+ encoding = "UTF-8"
+ }
+ // 照搬 Morse Expert 1.15: native 解码器仅 armeabi-v7a
+ defaultConfig {
+ ndk {
+ abiFilters += listOf("armeabi-v7a")
+ }
+ }
+}
+
+// CW 类保持规则(JNI 按类名注册 + 照搬混淆类保逻辑), 由 app 的 R8 消费
+// AGP 9: consumer 规则走 variant 级 CanProduceConsumerProguardFiles
+androidComponents {
+ onVariants(selector().all()) { variant ->
+ (variant as? CanProduceConsumerProguardFiles)?.consumerProguardFiles?.add(
+ project.layout.projectDirectory.file("proguard-rules.pro")
+ )
+ }
+}
+
+dependencies {
+ implementation("androidx.constraintlayout:constraintlayout:2.2.1")
+}
+
+// 照搬的 Java 源码含中文注释, 强制 UTF-8 编译(compileOptions 在部分 AGP 版本不生效)
+tasks.withType().configureEach {
+ options.encoding = "UTF-8"
+}
diff --git a/feature/cw/proguard-rules.pro b/feature/cw/proguard-rules.pro
new file mode 100644
index 00000000..28fe39ab
--- /dev/null
+++ b/feature/cw/proguard-rules.pro
@@ -0,0 +1,31 @@
+# Look4Sat Pro — CW 解码模块(照搬 Morse Expert 1.15)混淆规则
+# 所有 CW 类保持原名: pas.* 通过 RegisterNatives 按类名注册 JNI(混淆即崩);
+# 其余为照搬的混淆名类(命名已无混淆意义, 保持以保逻辑完整)。
+
+# JNI 引擎(RegisterNatives 按类名/方法名查表)
+-keep class pas.** { *; }
+
+# 照搬的解码/UI 类(全部保持)
+-keep class com.ve3nea.morse_expert.** { *; }
+-keep class H2.** { *; }
+-keep class I2.b { *; }
+-keep class J2.** { *; }
+-keep class k3.** { *; }
+-keep class i3.** { *; }
+-keep class g3.** { *; }
+-keep class j3.** { *; }
+-keep class s.** { *; }
+-keep class d1.AbstractC1518b { *; }
+-keep class B0.b { *; }
+-keep class B.RunnableC0001b { *; }
+-keep class D.n { *; }
+-keep class E2.g { *; }
+-keep class F2.a { *; }
+-keep class I0.d { *; }
+-keep class K1.a { *; }
+-keep class j1.C1646n { *; }
+
+# sun.misc stub(Android 无此类, 仅编译期; 防止 R8 异常处理)
+-dontwarn sun.misc.**
+-keep class sun.misc.Unsafe { *; }
+-keep class sun.misc.Cleaner { *; }
diff --git a/feature/cw/src/main/java/B/RunnableC0001b.java b/feature/cw/src/main/java/B/RunnableC0001b.java
new file mode 100644
index 00000000..a5d5ea58
--- /dev/null
+++ b/feature/cw/src/main/java/B/RunnableC0001b.java
@@ -0,0 +1,63 @@
+package B;
+
+import android.text.SpannableStringBuilder;
+import com.ve3nea.morse_expert.DecodedTextView;
+import com.ve3nea.morse_expert.MainActivity;
+import H2.b;
+
+/**
+ * 照搬自 Morse Expert 1.15 B.RunnableC0001b, 类名保持混淆原名。
+ * R8 合并 Runnable 手术: 构造按 smali 真实签名 5 参 (Object,Object,int,int,boolean),
+ * 字段 = i(Object)/h(Object)/g(int)/f(int); run() 仅保留 case 4(f==2 对应 pswitch_4:
+ * 解码文本 UI 更新, H2.b 调用), 其余 case(权限/Intent/通知等库代码)已裁剪。
+ * 注: jadx 4 参构造为错误还原, 已按 smali 修正。
+ */
+public final class RunnableC0001b implements Runnable {
+ public final /* synthetic */ int f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public final int g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public final Object h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public final Object i;
+
+ public /* synthetic */ RunnableC0001b(Object obj, Object obj2, int i4, int i5, boolean z) {
+ this.i = obj;
+ this.h = obj2;
+ this.g = i4;
+ this.f = i5;
+ }
+
+ @Override // java.lang.Runnable
+ public final void run() {
+ if (this.f == 2) {
+ MainActivity mainActivity = ((b) this.i).f620p;
+ if (mainActivity != null) {
+ SpannableStringBuilder spannableStringBuilder = (SpannableStringBuilder) this.h;
+ int i5 = this.g;
+ DecodedTextView decodedTextView = (DecodedTextView) mainActivity.f11035D.f11888g;
+ if (!decodedTextView.f11032n && !decodedTextView.f11033o.get()) {
+ decodedTextView.beginBatchEdit();
+ try {
+ int length2 = decodedTextView.length();
+ int min = Math.min(length2, i5);
+ if (min > 0) {
+ decodedTextView.getEditableText().delete(length2 - min, length2);
+ }
+ decodedTextView.q(spannableStringBuilder);
+ decodedTextView.endBatchEdit();
+ return;
+ } catch (Throwable th) {
+ decodedTextView.endBatchEdit();
+ throw th;
+ }
+ }
+ return;
+ }
+ return;
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/B0/b.java b/feature/cw/src/main/java/B0/b.java
new file mode 100644
index 00000000..bbaba882
--- /dev/null
+++ b/feature/cw/src/main/java/B0/b.java
@@ -0,0 +1,61 @@
+package B0;
+
+import android.widget.TextView;
+import com.ve3nea.morse_expert.MainActivity;
+import com.ve3nea.morse_expert.ScaleView;
+import java.util.Locale;
+import d1.AbstractC1518b;
+
+/**
+ * 照搬自 Morse Expert 1.15 B0.b, 类名保持混淆原名。
+ * R8 合并 Runnable 手术: 构造按 smali 真实签名 (H2/b, String, [I) -> f=4;
+ * 只保留 case 4(状态栏更新: dBFS/Hz/dB/WPM + ScaleView 频率标记, H2.b 调用),
+ * 其余 case(WorkManager/动画等库代码)已裁剪。
+ * r3 = scaleView.getHeight()(smali 证实, jadx 寄存器未展开)。
+ */
+public final class b implements Runnable {
+ public final /* synthetic */ int f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public final Object g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public final Object h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public final Object i;
+
+ public b(H2.b bVar, String str, int[] iArr) {
+ this.f = 4;
+ this.g = bVar;
+ this.h = iArr;
+ this.i = str;
+ }
+
+ @Override // java.lang.Runnable
+ public final void run() {
+ if (this.f == 4) {
+ MainActivity mainActivity = ((H2.b) this.g).f621q;
+ if (mainActivity != null) {
+ String str2 = (String) this.i;
+ int[] iArr = (int[]) this.h;
+ String concat;
+ String format = String.format(Locale.US, " %3d dBFS", Integer.valueOf(iArr[0]));
+ if (iArr[5] == 0) {
+ concat = format.concat(" Idle ");
+ } else {
+ concat = format.concat(String.format(Locale.US, " %4d Hz %2d dB %2d WPM ", Integer.valueOf(iArr[1]), Integer.valueOf(iArr[2]), Integer.valueOf(iArr[3])));
+ }
+ ((TextView) mainActivity.f11035D.f11890i).setText(AbstractC1518b.e(concat, str2));
+ ScaleView scaleView = (ScaleView) mainActivity.f11035D.f11889h;
+ int i4 = iArr[1];
+ scaleView.f11041g = iArr[5];
+ // r3 = scaleView.getHeight()(smali 证实)
+ scaleView.f = (scaleView.getHeight() - 1) - Math.round(((Math.round(i4 * 0.128f) - H2.b.f606z) * scaleView.getHeight()) / H2.b.f603B);
+ scaleView.invalidate();
+ return;
+ }
+ return;
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/D/n.java b/feature/cw/src/main/java/D/n.java
new file mode 100644
index 00000000..ddb2a7e2
--- /dev/null
+++ b/feature/cw/src/main/java/D/n.java
@@ -0,0 +1,69 @@
+package D;
+
+import android.graphics.Bitmap;
+import android.opengl.GLES20;
+import android.opengl.GLUtils;
+import com.ve3nea.morse_expert.WaterfallSurfaceView;
+
+/**
+ * 照搬自 Morse Expert 1.15, 类名保持混淆原名。
+ * R8 合并 Runnable 手术: 只保留 case 1(瀑布图频谱->OpenGL 纹理, H2.b 调用),
+ * 其余 case(库/广告)已裁剪。
+ */
+public final /* synthetic */ class n implements Runnable {
+ public final /* synthetic */ int f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public final /* synthetic */ Object f224g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public final /* synthetic */ Object f225h;
+
+ public /* synthetic */ n(Object obj, int i4, Object obj2) {
+ this.f = i4;
+ this.f224g = obj;
+ this.f225h = obj2;
+ }
+
+ @Override // java.lang.Runnable
+ public final void run() {
+ int i4 = this.f;
+ Object obj = this.f225h;
+ Object obj2 = this.f224g;
+ if (i4 == 1) {
+ float[] fArr = (float[]) obj;
+ J2.b bVar = ((WaterfallSurfaceView) obj2).f;
+ Bitmap bitmap = bVar.f733h;
+ int width = bVar.f730d.getWidth();
+ double d4 = width;
+ double b4 = (bVar.b() + 4.0d) % d4;
+ double d5 = bVar.f737l - b4;
+ if (d5 > d4 / 2.0d) {
+ d5 -= d4;
+ } else if (d5 < (-width) / 2.0d) {
+ d5 += d4;
+ }
+ if (Math.abs(d5) > 8.0d) {
+ bVar.f737l = (int) Math.floor(b4);
+ } else {
+ bVar.f732g = (d5 * 1.0E-5d) + bVar.f732g;
+ }
+ int height = bitmap.getHeight() - 1;
+ for (int i5 = 0; i5 <= height; i5++) {
+ J2.a aVar = bVar.f734i;
+ int round = Math.round((fArr[i5] * 4.0f) + 30.0f);
+ aVar.getClass();
+ bitmap.setPixel(0, height - i5, aVar.f727a[Math.max(0, Math.min(255, round))]);
+ }
+ int i6 = bVar.f737l;
+ GLES20.glBindTexture(3553, bVar.f728a[0]);
+ J2.b.a();
+ GLUtils.texSubImage2D(3553, 0, i6, 0, bitmap);
+ J2.b.a();
+ int i7 = bVar.f737l + 1;
+ bVar.f737l = i7;
+ bVar.f737l = i7 % width;
+ return;
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/E2/g.java b/feature/cw/src/main/java/E2/g.java
new file mode 100644
index 00000000..5f836223
--- /dev/null
+++ b/feature/cw/src/main/java/E2/g.java
@@ -0,0 +1,44 @@
+package E2;
+
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import com.ve3nea.morse_expert.MainActivity;
+import com.ve3nea.morse_expert.ScaleView;
+
+/**
+ * 照搬自 Morse Expert 1.15 (com.ve3nea.morse_expert), 类名保持混淆原名。
+ * R8 合并类手术: 只保留 case 1(瀑布图触摸选频率=应用逻辑),
+ * 其余 case(广告 P4 / appcompat 焦点 / 弹窗)为库代码, 已裁剪。
+ */
+public final class g implements View.OnTouchListener {
+ public final /* synthetic */ int f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public final /* synthetic */ Object f411g;
+
+ public /* synthetic */ g(Object obj, int i4) {
+ this.f = i4;
+ this.f411g = obj;
+ }
+
+ @Override // android.view.View.OnTouchListener
+ public final boolean onTouch(View view, MotionEvent motionEvent) {
+ int i4 = this.f;
+ Object obj = this.f411g;
+ if (i4 == 1) {
+ MainActivity mainActivity = (MainActivity) obj;
+ if (motionEvent.getActionMasked() == 0 && mainActivity.f11037F != null) {
+ // smali 证实: p1 先被重赋值为 f11035D.h(ScaleView)再 getHeight;
+ // 公式 = round((f606z + ((scaleH-1-y)*f603B/scaleH)) / 0.128f)
+ ScaleView scaleView = (ScaleView) mainActivity.f11035D.f11889h;
+ float y3 = motionEvent.getY();
+ int round = Math.round((H2.b.f606z + ((((scaleView.getHeight() - 1) - y3) * H2.b.f603B) / scaleView.getHeight())) / 0.128f);
+ mainActivity.f11037F.f622r.set(round);
+ Log.i("Waterfall", String.format("Touch at %d Hz`", Integer.valueOf(round)));
+ }
+ return false;
+ }
+ return false;
+ }
+}
diff --git a/feature/cw/src/main/java/F2/a.java b/feature/cw/src/main/java/F2/a.java
new file mode 100644
index 00000000..6f2bc8b2
--- /dev/null
+++ b/feature/cw/src/main/java/F2/a.java
@@ -0,0 +1,53 @@
+package F2;
+
+import com.rtbishop.look4sat.feature.cw.R;
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuItem;
+import com.ve3nea.morse_expert.DecodedTextView;
+
+/* loaded from: classes.dex */
+public final class a implements ActionMode.Callback {
+
+ /* renamed from: a, reason: collision with root package name */
+ public final /* synthetic */ DecodedTextView f564a;
+
+ public a(DecodedTextView decodedTextView) {
+ this.f564a = decodedTextView;
+ }
+
+ @Override // android.view.ActionMode.Callback
+ public final boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
+ int itemId = menuItem.getItemId();
+ DecodedTextView decodedTextView = this.f564a;
+ if (itemId != 73) {
+ if (itemId != 74) {
+ return false;
+ }
+ decodedTextView.s();
+ return true;
+ }
+ decodedTextView.r();
+ actionMode.finish();
+ return true;
+ }
+
+ @Override // android.view.ActionMode.Callback
+ public final boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
+ this.f564a.f11032n = true;
+ // 原: if (menu.findItem(R.id.shareText) == null) 检查(shareText 为原 APK 资源, 简化后始终添加)
+ menu.add(0, 74, 0, "Share").setIcon(R.drawable.ic_baseline_share_24);
+ menu.add(0, 73, 0, "Save").setIcon(R.drawable.ic_baseline_save_24);
+ return true;
+ }
+
+ @Override // android.view.ActionMode.Callback
+ public final void onDestroyActionMode(ActionMode actionMode) {
+ this.f564a.f11032n = false;
+ }
+
+ @Override // android.view.ActionMode.Callback
+ public final boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
+ return false;
+ }
+}
diff --git a/feature/cw/src/main/java/H2/a.java b/feature/cw/src/main/java/H2/a.java
new file mode 100644
index 00000000..670423ad
--- /dev/null
+++ b/feature/cw/src/main/java/H2/a.java
@@ -0,0 +1,82 @@
+package H2;
+
+import android.media.AudioRecord;
+import android.util.Log;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/* loaded from: classes.dex */
+public final class a implements Runnable {
+ public final int f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public final AudioRecord f596g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public final ExecutorService f597h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public final AtomicBoolean f598i;
+
+ /* renamed from: j, reason: collision with root package name */
+ public final short[] f599j;
+
+ /* renamed from: k, reason: collision with root package name */
+ public final float[] f600k;
+
+ /* renamed from: l, reason: collision with root package name */
+ public b f601l;
+
+ public a() {
+ int minBufferSize = AudioRecord.getMinBufferSize(8000, 16, 2);
+ int i4 = b.f604C;
+ this.f = i4;
+ ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
+ this.f597h = newSingleThreadExecutor;
+ AtomicBoolean atomicBoolean = new AtomicBoolean(false);
+ this.f598i = atomicBoolean;
+ this.f599j = new short[i4];
+ this.f600k = new float[i4];
+ AudioRecord audioRecord = new AudioRecord(1, 8000, 16, 2, minBufferSize * 4);
+ this.f596g = audioRecord;
+ if (audioRecord.getState() == 1) {
+ audioRecord.startRecording();
+ if (audioRecord.getState() != 1) {
+ Log.e("AudioRecord", "cannot start");
+ }
+ atomicBoolean.set(true);
+ newSingleThreadExecutor.execute(this);
+ return;
+ }
+ Log.e("AudioInput", "Failed to initialize");
+ }
+
+ @Override // java.lang.Runnable
+ public final void run() {
+ while (true) {
+ try {
+ if (this.f598i.get()) {
+ float[] fArr = this.f600k;
+ AudioRecord audioRecord = this.f596g;
+ short[] sArr = this.f599j;
+ int i4 = this.f;
+ if (audioRecord.read(sArr, 0, i4) == i4) {
+ for (int i5 = 0; i5 < i4; i5++) {
+ fArr[i5] = sArr[i5] / 32768.0f;
+ }
+ b bVar = this.f601l;
+ if (bVar != null) {
+ bVar.a(fArr);
+ }
+ }
+ } else {
+ TimeUnit.MILLISECONDS.sleep(100L);
+ }
+ } catch (Exception e4) {
+ Log.e("Audio thread", "Exception: ", e4);
+ }
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/H2/b.java b/feature/cw/src/main/java/H2/b.java
new file mode 100644
index 00000000..3012a6b3
--- /dev/null
+++ b/feature/cw/src/main/java/H2/b.java
@@ -0,0 +1,582 @@
+package H2;
+
+import B.RunnableC0001b;
+import D.n;
+import android.content.Context;
+import android.media.MediaScannerConnection;
+import android.os.Handler;
+import android.os.Looper;
+import android.text.SpannableStringBuilder;
+import android.text.format.DateFormat;
+import android.text.style.ForegroundColorSpan;
+import android.util.Log;
+import com.ve3nea.morse_expert.MainActivity;
+import com.ve3nea.morse_expert.WaterfallSurfaceView;
+import i3.d;
+import java.io.BufferedOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import k3.s;
+import pas.decoder;
+import pas.nativedecoder;
+
+/* loaded from: classes.dex */
+public final class b {
+
+ /* renamed from: A, reason: collision with root package name */
+ public static final int f602A;
+
+ /* renamed from: B, reason: collision with root package name */
+ public static final int f603B;
+
+ /* renamed from: C, reason: collision with root package name */
+ public static final int f604C;
+
+ /* renamed from: D, reason: collision with root package name */
+ public static final d f605D;
+
+ /* renamed from: z, reason: collision with root package name */
+ public static final int f606z;
+
+ /* renamed from: a, reason: collision with root package name */
+ public final float[] f607a;
+
+ /* renamed from: b, reason: collision with root package name */
+ public final float[] f608b;
+ public final float[] c;
+
+ /* renamed from: d, reason: collision with root package name */
+ public final float[] f609d;
+
+ /* renamed from: e, reason: collision with root package name */
+ public final nativedecoder.TNativeDecoder f610e;
+ public int f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public int f611g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public int f612h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public decoder.TDecoderState f613i;
+
+ /* renamed from: j, reason: collision with root package name */
+ public String f614j;
+
+ /* renamed from: k, reason: collision with root package name */
+ public final c f615k;
+
+ /* renamed from: l, reason: collision with root package name */
+ public int f616l;
+
+ /* renamed from: m, reason: collision with root package name */
+ public final I2.b f617m;
+
+ /* renamed from: n, reason: collision with root package name */
+ public final Handler f618n;
+
+ /* renamed from: o, reason: collision with root package name */
+ public WaterfallSurfaceView f619o;
+
+ /* renamed from: p, reason: collision with root package name */
+ public MainActivity f620p;
+
+ /* renamed from: q, reason: collision with root package name */
+ public MainActivity f621q;
+
+ /* renamed from: r, reason: collision with root package name */
+ public final AtomicInteger f622r;
+
+ /* renamed from: s, reason: collision with root package name */
+ public final AtomicBoolean f623s;
+
+ /* renamed from: t, reason: collision with root package name */
+ public final Context f624t;
+
+ /* renamed from: u, reason: collision with root package name */
+ public int f625u;
+
+ /* renamed from: v, reason: collision with root package name */
+ public final AtomicBoolean f626v;
+
+ /* renamed from: w, reason: collision with root package name */
+ public DataOutputStream f627w;
+
+ /* renamed from: x, reason: collision with root package name */
+ public int f628x;
+
+ /* renamed from: y, reason: collision with root package name */
+ public String f629y;
+
+ /* JADX WARN: Removed duplicated region for block: B:14:0x012d */
+ /* JADX WARN: Type inference failed for: r0v4, types: [i3.d, java.lang.Object] */
+ static {
+ boolean z3;
+ float f;
+ float f4;
+ float f5;
+ int round = Math.round(25.6f);
+ f606z = round;
+ int round2 = Math.round(153.6f);
+ f602A = round2;
+ f603B = round2 - round;
+ f604C = Math.round(85.333336f);
+ i3.d obj = new i3.d();
+ if (2048 > 1073741824) {
+ z3 = true;
+ } else {
+ z3 = false;
+ }
+ obj.f11709l = z3;
+ int i4 = (int) 1024;
+ obj.f11700a = i4;
+ obj.f11701b = 1024L;
+ if (!z3) {
+ obj.f11708k = 1;
+ int[] iArr = new int[((int) g3.c.a((1 << (((int) (g3.c.d(((float) 1024) + 0.5f) / g3.c.d(2.0d))) / 2)) + 2)) + 2];
+ obj.c = iArr;
+ float[] fArr = new float[i4];
+ obj.f11703e = fArr;
+ int i5 = (i4 * 2) >> 2;
+ obj.f11704g = i5;
+ iArr[0] = i5;
+ iArr[1] = 1;
+ if (i5 > 2) {
+ int i6 = i5 >> 1;
+ float f6 = 0.7853982f / i6;
+ float f7 = 2.0f * f6;
+ float b4 = (float) g3.c.b(i6 * f6); // r9 = i6 (smali)
+ fArr[0] = 1.0f;
+ fArr[1] = b4;
+ if (i6 == 4) {
+ double d4 = f7;
+ f4 = 0.5f;
+ fArr[2] = (float) g3.c.b(d4);
+ fArr[3] = (float) g3.c.f(d4);
+ } else {
+ f4 = 0.5f;
+ if (i6 > 4) {
+ iArr[2] = 0;
+ iArr[3] = 16;
+ int i7 = i5;
+ int i8 = 2;
+ f5 = 1.0f;
+ while (i7 > 32) {
+ int i9 = i8 << 1;
+ int i10 = i8 << 4;
+ for (int i11 = i8; i11 < i9; i11++) {
+ int i12 = iArr[i11] << 2;
+ iArr[i8 + i11] = i12;
+ iArr[i9 + i11] = i12 + i10;
+ }
+ i7 >>= 2;
+ i8 = i9;
+ }
+ fArr[2] = 0.5f / ((float) g3.c.b(f7));
+ fArr[3] = 0.5f / ((float) g3.c.b(6.0f * f6));
+ for (int i13 = 4; i13 < i6; i13 += 4) {
+ float f8 = i13 * f6;
+ double d5 = f8;
+ fArr[i13] = (float) g3.c.b(d5);
+ fArr[i13 + 1] = (float) g3.c.f(d5);
+ double d6 = 3.0f * f8;
+ fArr[i13 + 2] = (float) g3.c.b(d6);
+ fArr[i13 + 3] = -((float) g3.c.f(d6));
+ }
+ int i14 = 0;
+ while (i6 > 2) {
+ int i15 = i14 + i6;
+ i6 >>= 1;
+ fArr[i15] = f5;
+ fArr[i15 + 1] = b4;
+ if (i6 == 4) {
+ float f9 = fArr[i14 + 4];
+ float f10 = fArr[i14 + 5];
+ fArr[i15 + 2] = f9;
+ fArr[i15 + 3] = f10;
+ } else if (i6 > 4) {
+ float f11 = fArr[i14 + 4];
+ float f12 = fArr[i14 + 6];
+ fArr[i15 + 2] = f4 / f11;
+ fArr[i15 + 3] = f4 / f12;
+ for (int i16 = 4; i16 < i6; i16 += 4) {
+ int i17 = (i16 * 2) + i14;
+ int i18 = i15 + i16;
+ float f13 = fArr[i17];
+ float f14 = fArr[i17 + 1];
+ float f15 = fArr[i17 + 2];
+ float f16 = fArr[i17 + 3];
+ fArr[i18] = f13;
+ fArr[i18 + 1] = f14;
+ fArr[i18 + 2] = f15;
+ fArr[i18 + 3] = f16;
+ }
+ }
+ i14 = i15;
+ }
+ }
+ }
+ f5 = 1.0f;
+ int i142 = 0;
+ while (i6 > 2) {
+ }
+ }
+ int i19 = i4 >> 2;
+ obj.f11706i = i19;
+ iArr[1] = i19;
+ if (i19 > 1) {
+ int i20 = i19 >> 1;
+ float f17 = 0.7853982f / i20;
+ float b5 = (float) g3.c.b(i20 * f17); // r6 = i20 (smali)
+ fArr[i5] = b5;
+ fArr[i5 + i20] = b5 * 0.5f;
+ for (int i21 = 1; i21 < i20; i21++) {
+ double d7 = i21 * f17;
+ fArr[i5 + i21] = ((float) g3.c.b(d7)) * 0.5f;
+ fArr[(i5 + i19) - i21] = ((float) g3.c.f(d7)) * 0.5f;
+ }
+ }
+ } else {
+ obj.f11708k = 1;
+ s sVar = new s(((long) g3.c.a((1 << ((int) (((long) (g3.c.d(((float) 1024) + 0.5f) / g3.c.d(2.0d))) / 2))) + 2)) + 2, true);
+ obj.f11702d = sVar;
+ k3.d dVar = new k3.d(1024L, true);
+ obj.f = dVar;
+ obj.f11705h = 512L;
+ sVar.c(0L, 512L);
+ sVar.c(1L, 1L);
+ if (512 > 2) {
+ long j4 = 512 >> 1;
+ float f18 = 0.7853982f / ((float) j4);
+ float f19 = f18 * 2.0f;
+ float b6 = (float) g3.c.b(j4 * f18); // r14 = j4 (smali 同模式)
+ dVar.c(0L, 1.0f);
+ dVar.c(1L, b6);
+ if (j4 == 4) {
+ f = 0.5f;
+ double d8 = f19;
+ dVar.c(2L, (float) g3.c.b(d8));
+ dVar.c(3L, (float) g3.c.f(d8));
+ } else {
+ f = 0.5f;
+ if (j4 > 4) {
+ sVar.c(2L, 0L);
+ sVar.c(3L, 16L);
+ long j5 = 2;
+ long j6 = 512;
+ while (j6 > 32) {
+ long j7 = j5 << 1;
+ long j8 = j5 << 4;
+ long j9 = j5;
+ while (j9 < j7) {
+ long b7 = sVar.b(j9) << 2;
+ sVar.c(j5 + j9, b7);
+ sVar.c(j7 + j9, b7 + j8);
+ j9++;
+ f19 = f19;
+ }
+ j6 >>= 2;
+ j5 = j7;
+ }
+ dVar.c(2L, 0.5f / ((float) g3.c.b(f19)));
+ dVar.c(3L, 0.5f / ((float) g3.c.b(6.0f * f18)));
+ long j10 = 4;
+ while (j10 < j4) {
+ float f20 = ((float) j10) * f18;
+ double d9 = f20;
+ dVar.c(j10, (float) g3.c.b(d9));
+ dVar.c(j10 + 1, (float) g3.c.f(d9));
+ double d10 = 3.0f * f20;
+ long j11 = j10;
+ dVar.c(j10 + 2, (float) g3.c.b(d10));
+ dVar.c(j11 + 3, -((float) g3.c.f(d10)));
+ j10 = j11 + 4;
+ }
+ }
+ }
+ long j12 = 0;
+ long j13 = 2;
+ while (j4 > j13) {
+ long j14 = j12 + j4;
+ j4 >>= 1;
+ dVar.c(j14, 1.0f);
+ dVar.c(j14 + 1, b6);
+ if (j4 == 4) {
+ float b8 = dVar.b(j12 + 4);
+ float b9 = dVar.b(j12 + 5);
+ j13 = 2;
+ dVar.c(j14 + 2, b8);
+ dVar.c(j14 + 3, b9);
+ } else {
+ j13 = 2;
+ if (j4 > 4) {
+ float b10 = dVar.b(j12 + 4);
+ float b11 = dVar.b(6 + j12);
+ dVar.c(j14 + 2, f / b10);
+ dVar.c(j14 + 3, f / b11);
+ long j15 = 4;
+ while (j15 < j4) {
+ long j16 = (j15 * 2) + j12;
+ float f21 = b6;
+ long j17 = j14 + j15;
+ long j18 = j12;
+ float b12 = dVar.b(j16);
+ long j19 = j14;
+ float b13 = dVar.b(j16 + 1);
+ float b14 = dVar.b(j16 + 2);
+ float b15 = dVar.b(j16 + 3);
+ dVar.c(j17, b12);
+ dVar.c(j17 + 1, b13);
+ dVar.c(j17 + 2, b14);
+ dVar.c(j17 + 3, b15);
+ j15 += 4;
+ b6 = f21;
+ j12 = j18;
+ j14 = j19;
+ }
+ }
+ }
+ b6 = b6;
+ j12 = j14;
+ }
+ }
+ long j20 = 256;
+ obj.f11707j = 256L;
+ long j21 = 1;
+ sVar.c(1L, 256L);
+ if (256 > 1) {
+ long j22 = 256 >> 1;
+ float f22 = 0.7853982f / ((float) j22);
+ long j23 = 512;
+ dVar.c(512L, (float) g3.c.b(j22 * f22)); // r1 = j22 (smali)
+ dVar.c(512 + j22, dVar.b(512L) * 0.5f);
+ long j24 = 1;
+ while (j24 < j22) {
+ long j25 = j20;
+ long j26 = j21;
+ double d11 = ((float) j24) * f22;
+ long j27 = j23;
+ dVar.c(j23 + j24, ((float) g3.c.b(d11)) * 0.5f);
+ dVar.c((j27 + j25) - j24, ((float) g3.c.f(d11)) * 0.5f);
+ j24 += j26;
+ j20 = j25;
+ j21 = j26;
+ j23 = j27;
+ }
+ }
+ }
+ f605D = obj;
+ }
+
+ public b(Context context) {
+ float[] fArr = new float[1024];
+ fArr[512] = 1.0f;
+ for (int i4 = 1; i4 < 512; i4++) {
+ double d4 = (i4 * 6.283185307179586d) / 1024;
+ float cos = (float) ((Math.cos(d4 * 2.0d) * 0.08d) + (0.42d - (Math.cos(d4) * 0.5d)));
+ fArr[i4] = cos;
+ double d5 = 0.003125f * 6.283185307179586d * (i4 - 512);
+ float sin = (float) ((Math.sin(d5) / d5) * cos);
+ fArr[i4] = sin;
+ fArr[1024 - i4] = sin;
+ }
+ this.f607a = fArr;
+ this.f608b = new float[1024];
+ this.c = new float[1024];
+ this.f609d = new float[f603B];
+ this.f610e = nativedecoder.TNativeDecoder.Create();
+ this.f614j = "";
+ this.f615k = new c(4000, 0);
+ I2.b bVar = new I2.b();
+ this.f617m = bVar;
+ this.f618n = new Handler(Looper.getMainLooper());
+ this.f622r = new AtomicInteger();
+ this.f623s = new AtomicBoolean(false);
+ this.f625u = 0;
+ this.f626v = new AtomicBoolean(false);
+ this.f628x = 0;
+ this.f624t = context;
+ bVar.b(context);
+ }
+
+ /* JADX WARN: Removed duplicated region for block: B:57:0x01e2 */
+ /* JADX WARN: Removed duplicated region for block: B:63:0x020a A[LOOP:6: B:62:0x0208->B:63:0x020a, LOOP_END] */
+ /* JADX WARN: Removed duplicated region for block: B:66:0x0216 A[LOOP:7: B:65:0x0214->B:66:0x0216, LOOP_END] */
+ /* JADX WARN: Removed duplicated region for block: B:70:0x0232 */
+ /* JADX WARN: Removed duplicated region for block: B:73:? A[RETURN, SYNTHETIC] */
+ /*
+ Code decompiled incorrectly, please refer to instructions dump.
+ */
+ public final void a(float[] fArr) {
+ c cVar;
+ float[] fArr2;
+ float[] fArr3;
+ b bVar;
+ Exception exc;
+ int i4;
+ float f;
+ int i5;
+ WaterfallSurfaceView waterfallSurfaceView;
+ int length = fArr.length;
+ int i6 = 0;
+ while (true) {
+ cVar = this.f615k;
+ if (i6 >= length) {
+ break;
+ }
+ cVar.c(Math.abs(fArr[i6]));
+ i6++;
+ }
+ this.f616l = Math.round(((float) Math.log10(Math.max(-0.5d, cVar.f633e))) * 20.0f);
+ int i7 = f604C;
+ int i8 = 1024 - i7;
+ float[] fArr4 = this.f608b;
+ System.arraycopy(fArr4, i7, fArr4, 0, i8);
+ System.arraycopy(fArr, 0, fArr4, i8, i7);
+ int i9 = 0;
+ while (true) {
+ fArr2 = this.c;
+ if (i9 >= 1024) {
+ break;
+ }
+ fArr2[i9] = fArr4[i9] * this.f607a[i9];
+ i9++;
+ }
+ f605D.k(fArr2, 0);
+ int i10 = f606z;
+ int i11 = i10;
+ while (true) {
+ int i12 = f602A;
+ float f4 = 0.0f;
+ fArr3 = this.f609d;
+ if (i11 < i12) {
+ int i13 = i11 * 2;
+ float f5 = fArr2[i13];
+ float f6 = fArr2[i13 + 1];
+ float f7 = ((f6 * f6) + (f5 * f5)) * 0.001f;
+ if (!Float.isNaN(f7)) {
+ f4 = f7;
+ }
+ fArr3[i11 - i10] = f4;
+ i11++;
+ } else {
+ // smali: 循环内无 try; 录音写入 try 在循环后(见下)
+ break;
+ }
+ }
+ DataOutputStream dataOutputStream = this.f627w;
+ Context context = this.f624t;
+ AtomicBoolean atomicBoolean = this.f626v;
+ try { // smali try_start_0: 录音写入整块(原 jadx 误把 try 放 break 处)
+ if (dataOutputStream == null && atomicBoolean.get()) {
+ File file = new File(context.getExternalFilesDir(null), ((String) DateFormat.format("yyyy-MM-dd_HH_mm_ss", new Date())) + "_spectra.bin");
+ this.f629y = file.getAbsoluteFile().toString();
+ this.f627w = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file, false)));
+ this.f628x = 0;
+ this.f614j = " Recording...";
+ }
+ if (this.f627w != null) {
+ for (float f8 : fArr3) {
+ this.f627w.writeFloat(f8);
+ }
+ }
+ if (atomicBoolean.get()) {
+ int i14 = this.f628x + 1;
+ this.f628x = i14;
+ if (i14 >= 2048) {
+ atomicBoolean.set(false);
+ this.f627w.close();
+ this.f627w = null;
+ this.f614j = "";
+ MediaScannerConnection.scanFile(context, new String[]{this.f629y}, new String[]{"application/x-binary"}, null);
+ }
+ }
+ } catch (IOException e4) {
+ Log.e("File write", "Exception: ", e4);
+ }
+ nativedecoder.TNativeDecoder tNativeDecoder = this.f610e;
+ try {
+ this.f613i = tNativeDecoder.ProcessSpectrum(fArr3);
+ int i15 = this.f625u + 1;
+ this.f625u = i15;
+ Handler handler = this.f618n;
+ if (i15 == 15) {
+ try {
+ this.f625u = 0;
+ this.f = tNativeDecoder.getPitch();
+ this.f611g = tNativeDecoder.getSnr();
+ this.f612h = tNativeDecoder.getWpm();
+ handler.post(new B0.b(this, this.f614j, new int[]{this.f616l, this.f, this.f611g, this.f612h, tNativeDecoder.getSignalCount(), this.f613i.Value}));
+ AtomicInteger atomicInteger = this.f622r;
+ int i16 = atomicInteger.get();
+ if (i16 != 0) {
+ tNativeDecoder.LockToPitch(i16);
+ atomicInteger.set(0);
+ }
+ tNativeDecoder.setHamMode(this.f623s.get());
+ } catch (Exception e5) {
+ // jadx 幻觉区(空循环/空 if 为 catch 错位还原)已裁剪; 原 smali: 记录异常后跳回正常流程尾部
+ exc = e5;
+ bVar = this;
+ Log.e("Audio Processor", "Exception", exc);
+ }
+ }
+ int charCount = tNativeDecoder.getCharCount();
+ if (charCount > 0) {
+ SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
+ int i18 = 0;
+ while (i18 < charCount) {
+ decoder.TCharInfo GetChar = tNativeDecoder.GetChar(i18);
+ spannableStringBuilder.append(GetChar.getChar());
+ ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(this.f617m.a(GetChar));
+ int i19 = i18 + 1;
+ spannableStringBuilder.setSpan(foregroundColorSpan, i18, i19, 33);
+ i18 = i19;
+ }
+ bVar = this;
+ try {
+ handler.post(new RunnableC0001b(bVar, spannableStringBuilder, tNativeDecoder.getDeleteCount(), 2, false));
+ } catch (Exception e6) {
+ // jadx 幻觉区已裁剪(同 catch e5); 原 smali: 记录异常后跳回正常流程尾部
+ exc = e6;
+ Log.e("Audio Processor", "Exception", exc);
+ }
+ } else {
+ bVar = this;
+ }
+ } catch (Exception e7) {
+ // jadx 幻觉(e 变量)已裁剪
+ bVar = this;
+ }
+ i4 = f603B;
+ int i1722 = i4 / 2;
+ float[] copyOfRange22 = Arrays.copyOfRange(fArr3, i1722 - 20, i1722 + 20);
+ Arrays.sort(copyOfRange22);
+ f = copyOfRange22[20];
+ if (f > 0.0f) {
+ for (int i20 = 0; i20 < i4; i20++) {
+ fArr3[i20] = fArr3[i20] / f;
+ }
+ }
+ float[] fArr522 = (float[]) fArr3.clone();
+ new c(12, 1).a(fArr522);
+ new c(12, 0).a(fArr522);
+ for (i5 = 0; i5 < i4; i5++) {
+ fArr3[i5] = fArr3[i5] - fArr522[i5];
+ }
+ for (int i21 = 0; i21 < i4; i21++) {
+ fArr3[i21] = ((float) Math.log10(Math.max(-0.5d, fArr3[i21]) + 1.0d)) * 10.0f;
+ }
+ waterfallSurfaceView = bVar.f619o;
+ if (waterfallSurfaceView != null) {
+ waterfallSurfaceView.queueEvent(new n(waterfallSurfaceView, 1, (float[]) fArr3.clone()));
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/H2/c.java b/feature/cw/src/main/java/H2/c.java
new file mode 100644
index 00000000..a3de54f4
--- /dev/null
+++ b/feature/cw/src/main/java/H2/c.java
@@ -0,0 +1,89 @@
+package H2;
+
+/* loaded from: classes.dex */
+public final class c {
+
+ /* renamed from: a, reason: collision with root package name */
+ public final int f630a;
+
+ /* renamed from: b, reason: collision with root package name */
+ public float[] f631b;
+ public int c;
+
+ /* renamed from: d, reason: collision with root package name */
+ public float f632d;
+
+ /* renamed from: e, reason: collision with root package name */
+ public float f633e;
+ public final /* synthetic */ int f;
+
+ public c(int i4, int i5) {
+ this.f = i5;
+ this.f630a = i4 - 1;
+ }
+
+ public final void a(float[] fArr) {
+ int i4 = this.f630a / 2;
+ int length = fArr.length;
+ if (length > i4) {
+ this.f631b = null;
+ for (int i5 = 0; i5 < i4; i5++) {
+ c(fArr[i5]);
+ }
+ for (int i6 = i4; i6 < length; i6++) {
+ fArr[i6 - i4] = c(fArr[i6]);
+ }
+ for (int i7 = length; i7 < length + i4; i7++) {
+ fArr[i7 - i4] = c(fArr[length - 1]);
+ }
+ return;
+ }
+ throw new IllegalArgumentException("Sliding Filter error: input too short");
+ }
+
+ public final float b(float f, float f4) {
+ switch (this.f) {
+ case 0:
+ return Math.max(f, f4);
+ default:
+ return Math.min(f, f4);
+ }
+ }
+
+ public final float c(float f) {
+ float[] fArr = this.f631b;
+ int i4 = this.f630a;
+ if (fArr == null) {
+ this.f631b = new float[i4];
+ for (int i5 = 0; i5 < i4; i5++) {
+ this.f631b[i5] = f;
+ }
+ this.f632d = f;
+ return f;
+ }
+ float b4 = b(this.f632d, f);
+ this.f632d = b4;
+ this.f633e = b(this.f631b[this.c], b4);
+ float[] fArr2 = this.f631b;
+ int i6 = this.c;
+ int i7 = i6 + 1;
+ this.c = i7;
+ fArr2[i6] = f;
+ if (i7 == i4) {
+ int length = fArr2.length;
+ while (true) {
+ this.c = length - 1;
+ int i8 = this.c;
+ if (i8 <= 0) {
+ break;
+ }
+ float[] fArr3 = this.f631b;
+ fArr3[i8 - 1] = b(fArr3[i8 - 1], fArr3[i8]);
+ length = this.c;
+ }
+ this.c = 0;
+ this.f632d = f;
+ }
+ return this.f633e;
+ }
+}
diff --git a/feature/cw/src/main/java/I0/d.java b/feature/cw/src/main/java/I0/d.java
new file mode 100644
index 00000000..f63089ac
--- /dev/null
+++ b/feature/cw/src/main/java/I0/d.java
@@ -0,0 +1,42 @@
+package I0;
+
+/**
+ * 照搬自 Morse Expert 1.15 I0.d, 类名保持混淆原名。
+ * R8 合并类手术: 只保留 (i3.d, int, int, float[]) FFT 任务构造;
+ * run() 按 smali 原样还原: R8 已将任务体优化为死代码(aget 后 throw null,
+ * 永不执行), 保留原语义(行为与原 APK 完全一致)。
+ * SystemForegroundService(work 库)case 已裁剪。
+ */
+public final class d implements Runnable {
+ public final /* synthetic */ int f = 0;
+
+ /* renamed from: g, reason: collision with root package name */
+ public final /* synthetic */ int f653g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public final /* synthetic */ int f654h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public final /* synthetic */ Object f655i;
+
+ /* renamed from: j, reason: collision with root package name */
+ public final /* synthetic */ Object f656j;
+
+ public d(i3.d dVar, int i4, int i5, float[] fArr) {
+ this.f656j = dVar;
+ this.f653g = i4;
+ this.f654h = i5;
+ this.f655i = fArr;
+ }
+
+ @Override // java.lang.Runnable
+ public final void run() {
+ int i6 = this.f654h;
+ int i7 = this.f653g;
+ if (i7 >= i6) {
+ return;
+ }
+ float f = ((float[]) this.f655i)[i7 * 2];
+ // R8 原代码: aget 后 throw null(死代码, 永不执行) —— 照搬语义, 不执行任何计算
+ }
+}
diff --git a/feature/cw/src/main/java/I2/b.java b/feature/cw/src/main/java/I2/b.java
new file mode 100644
index 00000000..e4077025
--- /dev/null
+++ b/feature/cw/src/main/java/I2/b.java
@@ -0,0 +1,73 @@
+package I2;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import pas.decoder;
+
+/* loaded from: classes.dex */
+public final class b {
+
+ /* renamed from: b, reason: collision with root package name */
+ public static final String[] f663b = {"bg_color", "text_color", "text_color_weak", "call_color", "call_color_weak", "cq_color", "cq_color_weak", "rst_color", "rst_color_weak"};
+ public static final String[] c = {"Background color", "Text color", "Text color, weak", "Callsign color", "Callsign color, weak", "CQ color", "CQ color, weak", "RST color", "RST color, weak"};
+
+ /* renamed from: d, reason: collision with root package name */
+ public static final int[] f664d = {-3084048, -16777216, -5592406, -65536, -30584, -16776961, -7829249, -65281, -30465};
+
+ /* renamed from: a, reason: collision with root package name */
+ public final int[] f665a = (int[]) f664d.clone();
+
+ public final int a(decoder.TCharInfo tCharInfo) {
+ boolean lowSnr = tCharInfo.getLowSnr();
+ int[] iArr = this.f665a;
+ if (lowSnr) {
+ int i4 = tCharInfo.getWordType().Value;
+ if (i4 != 0) {
+ if (i4 != 1) {
+ if (i4 != 2) {
+ if (i4 != 3) {
+ if (i4 != 4) {
+ if (i4 == 5) {
+ return iArr[4];
+ }
+ return -16777216;
+ }
+ return iArr[2];
+ }
+ return iArr[6];
+ }
+ return iArr[8];
+ }
+ return iArr[2];
+ }
+ return iArr[2];
+ }
+ int i5 = tCharInfo.getWordType().Value;
+ if (i5 != 0) {
+ if (i5 != 1) {
+ if (i5 != 2) {
+ if (i5 != 3) {
+ if (i5 != 4) {
+ if (i5 != 5) {
+ return -16777216;
+ }
+ return iArr[3];
+ }
+ return iArr[1];
+ }
+ return iArr[5];
+ }
+ return iArr[7];
+ }
+ return iArr[1];
+ }
+ return iArr[1];
+ }
+
+ public final void b(Context context) {
+ SharedPreferences sharedPreferences = context.getSharedPreferences(context.getPackageName() + "_preferences", 0); // 原 c0.x.a(context)
+ for (int i4 = 0; i4 < 9; i4++) {
+ this.f665a[i4] = sharedPreferences.getInt(f663b[i4], f664d[i4]);
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/J2/a.java b/feature/cw/src/main/java/J2/a.java
new file mode 100644
index 00000000..5431d71a
--- /dev/null
+++ b/feature/cw/src/main/java/J2/a.java
@@ -0,0 +1,45 @@
+package J2;
+
+/* loaded from: classes.dex */
+public final class a {
+
+ /* renamed from: b, reason: collision with root package name */
+ public static final int[] f726b = {16, 17749, 65535, 16776960, 16711680};
+
+ /* renamed from: a, reason: collision with root package name */
+ public final int[] f727a;
+
+ public a() {
+ int[] iArr = new int[256];
+ this.f727a = iArr;
+ int i4 = 4;
+ float f = 255.0f / 4;
+ int[] iArr2 = f726b;
+ int i5 = 0;
+ int i6 = -16777216;
+ iArr[0] = iArr2[0] | (-16777216);
+ int i7 = 1;
+ while (i7 <= i4) {
+ int round = Math.round(i7 * f);
+ iArr[round] = iArr2[i7] | i6;
+ int i8 = round - i5;
+ int i9 = iArr[i5];
+ int i10 = (i9 >> 16) & 255;
+ int i11 = (i9 >> 8) & 255;
+ int i12 = i9 & 255;
+ float f4 = i8;
+ // r10 = iArr2[i7] (下一个锚点色, smali: aget v10, v4, v8)
+ float f5 = (((iArr2[i7] >> 16) & 255) - i10) / f4;
+ float f6 = (((iArr2[i7] >> 8) & 255) - i11) / f4;
+ float f7 = ((iArr2[i7] & 255) - i12) / f4;
+ for (int i13 = 1; i13 < i8; i13++) {
+ float f8 = i13;
+ iArr[i5 + i13] = ((Math.round(f5 * f8) + i10) << 16) | (-16777216) | ((Math.round(f6 * f8) + i11) << 8) | (Math.round(f8 * f7) + i12);
+ }
+ i7++;
+ i5 = round;
+ i4 = 4;
+ i6 = -16777216;
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/J2/b.java b/feature/cw/src/main/java/J2/b.java
new file mode 100644
index 00000000..7ed2e82e
--- /dev/null
+++ b/feature/cw/src/main/java/J2/b.java
@@ -0,0 +1,183 @@
+package J2;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLUtils;
+import android.os.SystemClock;
+import android.util.Log;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+/* loaded from: classes.dex */
+public final class b implements GLSurfaceView.Renderer {
+
+ /* renamed from: b, reason: collision with root package name */
+ public FloatBuffer f729b;
+ public int c;
+
+ /* renamed from: d, reason: collision with root package name */
+ public final Bitmap f730d;
+ public final Context f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public double f732g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public final Bitmap f733h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public final a f734i;
+
+ /* renamed from: j, reason: collision with root package name */
+ public long f735j;
+
+ /* renamed from: k, reason: collision with root package name */
+ public double f736k;
+
+ /* renamed from: l, reason: collision with root package name */
+ public int f737l;
+
+ /* renamed from: a, reason: collision with root package name */
+ public final int[] f728a = new int[1];
+
+ /* renamed from: e, reason: collision with root package name */
+ public final float[] f731e = {-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f};
+
+ public b(Context context, int i4) {
+ Bitmap.Config config = Bitmap.Config.ARGB_8888;
+ Bitmap createBitmap = Bitmap.createBitmap(2048, i4, config);
+ this.f730d = createBitmap;
+ createBitmap.eraseColor(16);
+ this.f732g = 0.09375d;
+ this.f734i = new a();
+ this.f735j = 0L;
+ this.f736k = 0.0d;
+ this.f737l = -1;
+ this.f = context;
+ this.f733h = Bitmap.createBitmap(1, i4, config);
+ }
+
+ public static void a() {
+ int glGetError = GLES20.glGetError();
+ if (glGetError != 0) {
+ StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[3];
+ Log.e(stackTraceElement.getFileName() + ":" + stackTraceElement.getLineNumber(), ", GLES20 error: " + glGetError);
+ }
+ }
+
+ public final double b() {
+ long uptimeMillis = SystemClock.uptimeMillis();
+ double width = (((uptimeMillis - this.f735j) * this.f732g) + this.f736k) % this.f730d.getWidth();
+ this.f735j = uptimeMillis;
+ this.f736k = width;
+ return width;
+ }
+
+ public final void c(GL10 gl10) {
+ GLES20.glUseProgram(this.c);
+ a();
+ GLES20.glActiveTexture(33984);
+ a();
+ GLES20.glBindTexture(3553, this.f728a[0]);
+ a();
+ GLES20.glUniform1i(GLES20.glGetUniformLocation(this.c, "uTexture"), 0);
+ a();
+ int glGetAttribLocation = GLES20.glGetAttribLocation(this.c, "aPosition");
+ a();
+ int glGetAttribLocation2 = GLES20.glGetAttribLocation(this.c, "aTexPos");
+ a();
+ this.f729b.position(0);
+ a();
+ GLES20.glVertexAttribPointer(glGetAttribLocation, 2, 5126, false, 16, (Buffer) this.f729b);
+ a();
+ GLES20.glEnableVertexAttribArray(glGetAttribLocation);
+ a();
+ this.f729b.position(2);
+ a();
+ GLES20.glVertexAttribPointer(glGetAttribLocation2, 2, 5126, false, 16, (Buffer) this.f729b);
+ a();
+ GLES20.glEnableVertexAttribArray(glGetAttribLocation2);
+ a();
+ GLES20.glDrawArrays(5, 0, 4);
+ a();
+ }
+
+ public final void d(GL10 gl10, int i4, int i5) {
+ GLES20.glViewport(0, 0, i4, i5);
+ a();
+ }
+
+ @Override // android.opengl.GLSurfaceView.Renderer
+ public final void onDrawFrame(GL10 gl10) {
+ float b4 = (float) (b() / this.f730d.getWidth());
+ float f = 0.5f + b4;
+ float[] fArr = this.f731e;
+ fArr[6] = f;
+ fArr[2] = f;
+ float f4 = b4 + 1.0f;
+ fArr[14] = f4;
+ fArr[10] = f4;
+ this.f729b.position(0);
+ this.f729b.put(this.f731e);
+ c(gl10);
+ }
+
+ @Override // android.opengl.GLSurfaceView.Renderer
+ public final void onSurfaceChanged(GL10 gl10, int i4, int i5) {
+ d(gl10, i4, i5);
+ float width = 1.0f - (((this.f730d.getWidth() * 0.7f) / (i4 / this.f.getResources().getDisplayMetrics().density)) * 2.0f);
+ float[] fArr = this.f731e;
+ fArr[4] = width;
+ fArr[0] = width;
+ this.f729b.position(0);
+ this.f729b.put(this.f731e);
+ }
+
+ @Override // android.opengl.GLSurfaceView.Renderer
+ public final void onSurfaceCreated(GL10 gl10, EGLConfig eGLConfig) {
+ int glCreateShader = GLES20.glCreateShader(35633);
+ a();
+ GLES20.glShaderSource(glCreateShader, "attribute vec2 aPosition;\nattribute vec2 aTexPos;\nvarying vec2 vTexPos;\nvoid main() {\n vTexPos = aTexPos;\n gl_Position = vec4(aPosition.xy, 0.0, 1.0);\n}");
+ a();
+ GLES20.glCompileShader(glCreateShader);
+ a();
+ int glCreateShader2 = GLES20.glCreateShader(35632);
+ a();
+ GLES20.glShaderSource(glCreateShader2, "precision mediump float;\nuniform sampler2D uTexture;\nvarying vec2 vTexPos;\nvoid main(void)\n{\n gl_FragColor = texture2D(uTexture, vTexPos);\n}");
+ a();
+ GLES20.glCompileShader(glCreateShader2);
+ a();
+ this.c = GLES20.glCreateProgram();
+ a();
+ GLES20.glAttachShader(this.c, glCreateShader);
+ a();
+ GLES20.glAttachShader(this.c, glCreateShader2);
+ a();
+ GLES20.glLinkProgram(this.c);
+ a();
+ int[] iArr = this.f728a;
+ GLES20.glGenTextures(1, iArr, 0);
+ a();
+ GLES20.glBindTexture(3553, iArr[0]);
+ a();
+ GLES20.glTexParameteri(3553, 10240, 9729);
+ GLES20.glTexParameteri(3553, 10242, 10497);
+ GLES20.glTexParameteri(3553, 10241, 9729);
+ GLES20.glTexParameteri(3553, 10243, 10497);
+ a();
+ GLUtils.texImage2D(3553, 0, this.f730d, 0);
+ a();
+ float[] fArr = this.f731e;
+ ByteBuffer allocateDirect = ByteBuffer.allocateDirect(fArr.length * 4);
+ allocateDirect.order(ByteOrder.nativeOrder());
+ FloatBuffer asFloatBuffer = allocateDirect.asFloatBuffer();
+ this.f729b = asFloatBuffer;
+ asFloatBuffer.put(fArr);
+ }
+}
diff --git a/feature/cw/src/main/java/K1/a.java b/feature/cw/src/main/java/K1/a.java
new file mode 100644
index 00000000..8d6a1950
--- /dev/null
+++ b/feature/cw/src/main/java/K1/a.java
@@ -0,0 +1,10 @@
+package K1;
+
+/**
+ * 照搬自 Morse Expert 1.15 K1.a 精简版: 仅保留 k3 FFT 库引用的内存统计静态字段
+ * (K1.a.c 长整型记账)。原 K1.a(828 行)的其余方法为状态栏/库代码, 已裁剪
+ * (状态栏逻辑已在 MainActivity 内联)。
+ */
+public class a {
+ public static long c = 0;
+}
diff --git a/feature/cw/src/main/java/com/rtbishop/look4sat/feature/cw/CwDecodeScreen.kt b/feature/cw/src/main/java/com/rtbishop/look4sat/feature/cw/CwDecodeScreen.kt
new file mode 100644
index 00000000..447c9866
--- /dev/null
+++ b/feature/cw/src/main/java/com/rtbishop/look4sat/feature/cw/CwDecodeScreen.kt
@@ -0,0 +1,213 @@
+/*
+ * CwDecodeScreen.kt — Look4Sat 的 CW 解码页面(Compose 外壳)。
+ *
+ * 照搬自 Morse Expert 1.15 的 com.ve3nea.morse_expert.MainActivity(已改为普通控制器类):
+ * - AndroidView 嵌入原版 activity_main.xml(ConstraintLayout 根, 含 decodedTextView/scaleView/
+ * statusTextView/verticalLayout/waterfallView);
+ * - 生命周期 onCreate/onResume/onPause/onDestroy 全部委托给控制器, 顺序与原 Activity 一致
+ * (onCreate 必须在 onResume 前, onDispose 先 onPause 再 onDestroy);
+ * - 麦克风权限(RECORD_AUDIO)由 Compose 侧管理, 授予后调用 onPermissionGranted()(= v()),
+ * 用 initialized 标记保证只调一次(v() 会 new a() 覆盖 f11036E);
+ * - 原 options_menu 的 清除/暂停/保存/录音/设置 改为顶部一行按钮(图标用模块内原版 drawable)。
+ *
+ * 注意: 控制器 onCreate 内的 setImmersive(window, false) 会把宿主窗口恢复为
+ * decorFitsSystemWindows(true)(原版行为照搬, 会对整个宿主 Activity 生效)。
+ */
+package com.rtbishop.look4sat.feature.cw
+
+import android.Manifest
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.net.Uri
+import android.provider.Settings
+import android.view.LayoutInflater
+import androidx.activity.compose.BackHandler
+import androidx.activity.compose.rememberLauncherForActivityResult
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBarsPadding
+import androidx.compose.material3.Button
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextButton
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.constraintlayout.widget.ConstraintLayout
+import com.ve3nea.morse_expert.MainActivity
+
+@Composable
+fun CwDecodeScreen(navigateUp: () -> Unit = {}) {
+ val context = LocalContext.current
+ val activity = remember(context) {
+ context as? Activity ?: error("CwDecodeScreen must be hosted in an Activity")
+ }
+ // 照搬的控制器(普通类, 非 Activity); 每次进入页面新建实例
+ val controller = remember { MainActivity() }
+ // 提前 inflate 原版布局, 供 AndroidView 与控制器 onCreate 共用同一根视图
+ val rootView = remember(context) {
+ LayoutInflater.from(context).inflate(R.layout.activity_main, null) as ConstraintLayout
+ }
+
+ var permissionGranted by remember {
+ mutableStateOf(
+ context.checkSelfPermission(Manifest.permission.RECORD_AUDIO) ==
+ PackageManager.PERMISSION_GRANTED
+ )
+ }
+ var permanentlyDenied by remember { mutableStateOf(false) }
+ // v() 会 new a() 覆盖 f11036E, 必须保证只初始化一次
+ var initialized by remember { mutableStateOf(false) }
+ var showSettings by remember { mutableStateOf(false) }
+
+ // 生命周期: onCreate 必须在 onResume 前; onDispose 先 onPause 再 onDestroy
+ DisposableEffect(Unit) {
+ controller.onCreate(activity, rootView)
+ controller.onResume()
+ onDispose {
+ controller.onPause()
+ controller.onDestroy()
+ }
+ }
+
+ // 权限授予后启动解码核心; "首次进入已授权" 与 "弹窗回调授权" 两条路径统一走这里
+ LaunchedEffect(permissionGranted) {
+ if (permissionGranted && !initialized) {
+ controller.onPermissionGranted() // = v(): 创建音频采集 + 解码核心
+ // v() 只创建核心; 页面此刻已处于 resumed, 需再走一次 onResume 立即启动录音
+ // (AudioRecord 是新建的, startRecording 不会重复; GLSurfaceView.onResume 幂等)
+ controller.onResume()
+ initialized = true
+ }
+ }
+
+ val permissionLauncher = rememberLauncherForActivityResult(
+ ActivityResultContracts.RequestPermission()
+ ) { granted ->
+ permissionGranted = granted
+ permanentlyDenied = !granted &&
+ !activity.shouldShowRequestPermissionRationale(Manifest.permission.RECORD_AUDIO)
+ }
+
+ // 原版 tap_back_again_to_close: 单击返回只提示, 2 秒内再按才退出
+ BackHandler {
+ if (!controller.handleBackPress()) navigateUp()
+ }
+
+ if (showSettings) {
+ CwSettingsDialog(controller = controller, onDismiss = { showSettings = false })
+ }
+
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .systemBarsPadding()
+ ) {
+ // 原 options_menu: 暂停/清除/保存(原版图标) + 录音/设置(文字按钮)
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 4.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.SpaceEvenly
+ ) {
+ IconButton(onClick = { controller.togglePause() }) {
+ Icon(
+ painter = painterResource(R.drawable.ic_baseline_pause_24),
+ contentDescription = stringResource(R.string.pause)
+ )
+ }
+ IconButton(onClick = { controller.clearDecoded() }) {
+ Icon(
+ painter = painterResource(R.drawable.ic_baseline_delete_24),
+ contentDescription = stringResource(R.string.clear)
+ )
+ }
+ IconButton(onClick = { controller.saveText() }) {
+ Icon(
+ painter = painterResource(R.drawable.ic_baseline_save_24),
+ contentDescription = stringResource(R.string.save_text)
+ )
+ }
+ // recordSignals 需要解码核心(f11037F), 未初始化时禁用
+ TextButton(
+ onClick = { if (initialized) controller.recordSignals() },
+ enabled = initialized
+ ) {
+ Text(stringResource(R.string.record_signals))
+ }
+ TextButton(onClick = { showSettings = true }) {
+ Text(stringResource(R.string.settings))
+ }
+ }
+
+ Box(modifier = Modifier.weight(1f).fillMaxWidth()) {
+ AndroidView(
+ factory = { rootView },
+ modifier = Modifier.fillMaxSize()
+ )
+ if (!permissionGranted) {
+ // 未授予麦克风权限: 遮罩 + 提示文字 + 请求按钮
+ Box(
+ modifier = Modifier
+ .fillMaxSize()
+ .background(Color(0x99000000)),
+ contentAlignment = Alignment.Center
+ ) {
+ Column(horizontalAlignment = Alignment.CenterHorizontally) {
+ Text(
+ text = stringResource(R.string.cw_mic_permission),
+ color = Color.White,
+ textAlign = TextAlign.Center,
+ modifier = Modifier.padding(horizontal = 24.dp)
+ )
+ Spacer(modifier = Modifier.height(12.dp))
+ Button(onClick = {
+ permissionLauncher.launch(Manifest.permission.RECORD_AUDIO)
+ }) {
+ Text(stringResource(R.string.cw_grant_permission))
+ }
+ if (permanentlyDenied) {
+ // 勾选了"不再询问": 引导去系统设置开启
+ TextButton(onClick = {
+ activity.startActivity(
+ Intent(
+ Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+ Uri.parse("package:${activity.packageName}")
+ )
+ )
+ }) {
+ Text(stringResource(R.string.cw_open_settings))
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/com/rtbishop/look4sat/feature/cw/CwSettingsDialog.kt b/feature/cw/src/main/java/com/rtbishop/look4sat/feature/cw/CwSettingsDialog.kt
new file mode 100644
index 00000000..ce817298
--- /dev/null
+++ b/feature/cw/src/main/java/com/rtbishop/look4sat/feature/cw/CwSettingsDialog.kt
@@ -0,0 +1,218 @@
+/*
+ * Look4Sat. Amateur radio satellite tracker and pass predictor.
+ * Copyright (C) 2019-2026 Arty Bishop and contributors.
+ *
+ * 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.
+ */
+package com.rtbishop.look4sat.feature.cw
+
+import android.content.Context
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+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.foundation.rememberScrollState
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.AlertDialog
+import androidx.compose.material3.HorizontalDivider
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.RadioButton
+import androidx.compose.material3.Slider
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextButton
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import com.ve3nea.morse_expert.MainActivity
+import kotlin.math.roundToInt
+
+/** 键名/默认值照搬原 Morse Expert(root_preferences.xml + SettingsActivity 逻辑)。 */
+private const val KEY_MESSAGE_TYPE = "message_type"
+private const val KEY_TEXT_FONT_SIZE = "text_font_size"
+private const val DEFAULT_MESSAGE_TYPE = "general_text"
+private const val DEFAULT_TEXT_FONT_SIZE = 18
+private const val MIN_FONT_SIZE = 7
+private const val MAX_FONT_SIZE = 99
+
+/** 预置色板(9 色, 3x3 网格);原 ColorPreferenceCompat 用第三方 colorpicker, 不引入。 */
+private val PaletteColors = listOf(
+ 0xFFD0F0F0.toInt(), 0xFF000000.toInt(), 0xFFFFFFFF.toInt(),
+ 0xFFAAAAAA.toInt(), 0xFFFF0000.toInt(), 0xFF00FF00.toInt(),
+ 0xFF0000FF.toInt(), 0xFFFFFF00.toInt(), 0xFFFF00FF.toInt(),
+)
+
+/**
+ * CW 设置弹窗(替代原 Morse Expert 的 SettingsActivity)。
+ * 设置项与键名照搬原 APK: message_type / text_font_size / 9 个颜色
+ * (I2.b.f663b 键名, I2.b.f664d 默认值, I2.b.c 英文标题)。
+ * 存储: SharedPreferences(getPackageName() + "_preferences")。
+ * 点击 OK 保存并调用 controller.onResume() 立即生效; Cancel/点外部仅关闭不保存。
+ */
+@Composable
+fun CwSettingsDialog(controller: MainActivity, onDismiss: () -> Unit) {
+ val activity = controller.mActivity ?: return
+ val prefs = remember(activity) {
+ activity.getSharedPreferences(activity.packageName + "_preferences", Context.MODE_PRIVATE)
+ }
+
+ var messageType by remember {
+ mutableStateOf(prefs.getString(KEY_MESSAGE_TYPE, DEFAULT_MESSAGE_TYPE) ?: DEFAULT_MESSAGE_TYPE)
+ }
+ var fontSize by remember {
+ mutableStateOf(
+ prefs.getInt(KEY_TEXT_FONT_SIZE, DEFAULT_TEXT_FONT_SIZE)
+ .toFloat().coerceIn(MIN_FONT_SIZE.toFloat(), MAX_FONT_SIZE.toFloat())
+ )
+ }
+ var colorValues by remember {
+ mutableStateOf(IntArray(9) { i -> prefs.getInt(I2.b.f663b[i], I2.b.f664d[i]) })
+ }
+
+ AlertDialog(
+ onDismissRequest = onDismiss,
+ title = { Text("CW Settings") },
+ text = {
+ Column(
+ modifier = Modifier
+ .verticalScroll(rememberScrollState())
+ .padding(top = 4.dp)
+ ) {
+ Text("Message type", style = MaterialTheme.typography.titleSmall)
+ MessageTypeRow("general_text", "General Text", messageType) { messageType = it }
+ MessageTypeRow("ham_radio_qso", "Ham Radio QSO", messageType) { messageType = it }
+ HorizontalDivider(Modifier.padding(vertical = 8.dp))
+
+ Text("Text font size", style = MaterialTheme.typography.titleSmall)
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ Slider(
+ value = fontSize,
+ onValueChange = { fontSize = it },
+ valueRange = MIN_FONT_SIZE.toFloat()..MAX_FONT_SIZE.toFloat(),
+ steps = MAX_FONT_SIZE - MIN_FONT_SIZE - 1,
+ modifier = Modifier.weight(1f),
+ )
+ Text(
+ text = "${fontSize.roundToInt()}",
+ style = MaterialTheme.typography.titleMedium,
+ textAlign = TextAlign.End,
+ modifier = Modifier.width(44.dp),
+ )
+ }
+ HorizontalDivider(Modifier.padding(vertical = 8.dp))
+
+ Text("Colors", style = MaterialTheme.typography.titleSmall)
+ for (i in 0 until 9) {
+ ColorSettingRow(
+ title = I2.b.c[i],
+ value = colorValues[i],
+ onSelect = { selected ->
+ colorValues = colorValues.copyOf().also { it[i] = selected }
+ },
+ )
+ }
+ }
+ },
+ confirmButton = {
+ TextButton(onClick = {
+ val editor = prefs.edit()
+ editor.putString(KEY_MESSAGE_TYPE, messageType)
+ editor.putInt(KEY_TEXT_FONT_SIZE, fontSize.roundToInt())
+ for (i in 0 until 9) {
+ editor.putInt(I2.b.f663b[i], colorValues[i])
+ }
+ editor.apply()
+ // 原 SettingsActivity 返回时由 MainActivity.onResume() 重新读取全部设置; 照搬逻辑已就位
+ controller.onResume()
+ onDismiss()
+ }) { Text("OK") }
+ },
+ dismissButton = {
+ TextButton(onClick = onDismiss) { Text("Cancel") }
+ },
+ )
+}
+
+@Composable
+private fun MessageTypeRow(option: String, label: String, selected: String, onSelect: (String) -> Unit) {
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .clip(RoundedCornerShape(6.dp))
+ .clickable { onSelect(option) }
+ .padding(vertical = 2.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ RadioButton(selected = option == selected, onClick = { onSelect(option) })
+ Text(label, style = MaterialTheme.typography.bodyMedium)
+ }
+}
+
+@Composable
+private fun ColorSettingRow(title: String, value: Int, onSelect: (Int) -> Unit) {
+ Column(Modifier.fillMaxWidth().padding(vertical = 6.dp)) {
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ Text(title, style = MaterialTheme.typography.bodyMedium, modifier = Modifier.weight(1f))
+ Box(
+ Modifier
+ .size(20.dp)
+ .clip(RoundedCornerShape(4.dp))
+ .background(Color(value)),
+ )
+ Spacer(Modifier.width(6.dp))
+ Text(
+ text = String.format("#%06X", value and 0xFFFFFF),
+ style = MaterialTheme.typography.bodySmall,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ )
+ }
+ Spacer(Modifier.height(6.dp))
+ PaletteGrid(selected = value, onSelect = onSelect)
+ }
+}
+
+@Composable
+private fun PaletteGrid(selected: Int, onSelect: (Int) -> Unit) {
+ Column(verticalArrangement = Arrangement.spacedBy(6.dp)) {
+ PaletteColors.chunked(3).forEach { rowColors ->
+ Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
+ rowColors.forEach { color ->
+ val isSelected = color == selected
+ Box(
+ modifier = Modifier
+ .size(36.dp)
+ .border(
+ width = if (isSelected) 3.dp else 1.dp,
+ color = if (isSelected) MaterialTheme.colorScheme.primary
+ else MaterialTheme.colorScheme.outlineVariant,
+ shape = RoundedCornerShape(6.dp),
+ )
+ .clip(RoundedCornerShape(6.dp))
+ .background(Color(color))
+ .clickable { onSelect(color) },
+ )
+ }
+ }
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/com/rtbishop/look4sat/feature/cw/suncompat/Cleaner.java b/feature/cw/src/main/java/com/rtbishop/look4sat/feature/cw/suncompat/Cleaner.java
new file mode 100644
index 00000000..d6e10aaf
--- /dev/null
+++ b/feature/cw/src/main/java/com/rtbishop/look4sat/feature/cw/suncompat/Cleaner.java
@@ -0,0 +1,14 @@
+package com.rtbishop.look4sat.feature.cw.suncompat;
+
+/**
+ * 编译期 stub:Android 无 sun.misc.Cleaner(照搬 Morse Expert 1.15 k3 FFT 库的清理回调,
+ * 实际 FFT 1024 点不触发 native 路径)。
+ */
+public class Cleaner {
+ public static Cleaner create(Object referent, Runnable thunk) {
+ return null;
+ }
+
+ public void clean() {
+ }
+}
diff --git a/feature/cw/src/main/java/com/rtbishop/look4sat/feature/cw/suncompat/Unsafe.java b/feature/cw/src/main/java/com/rtbishop/look4sat/feature/cw/suncompat/Unsafe.java
new file mode 100644
index 00000000..fc90ae2f
--- /dev/null
+++ b/feature/cw/src/main/java/com/rtbishop/look4sat/feature/cw/suncompat/Unsafe.java
@@ -0,0 +1,83 @@
+package com.rtbishop.look4sat.feature.cw.suncompat;
+
+/**
+ * 编译期 stub:Android 无 sun.misc.Unsafe(运行时通过反射获取,失败时 k3.r.f12109a 为 null)。
+ * 照搬自 Morse Expert 1.15(k3 FFT 库的大数组 native 路径 >1GB 不触发,实际 FFT 走 float[] 分支)。
+ */
+public class Unsafe {
+ public long allocateMemory(long bytes) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public void freeMemory(long address) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public byte getByte(long address) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public void putByte(long address, byte value) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public short getShort(long address) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public void putShort(long address, short value) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public int getInt(long address) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public void putInt(long address, int value) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public long getLong(long address) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public void putLong(long address, long value) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public float getFloat(long address) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public void putFloat(long address, float value) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public double getDouble(long address) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public void putDouble(long address, double value) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public void setMemory(long address, long bytes, byte value) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public void copyMemory(long src, long dst, long len) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public Object getObject(Object o, long offset) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public void putObject(Object o, long offset, Object value) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+
+ public long objectFieldOffset(java.lang.reflect.Field field) {
+ throw new UnsupportedOperationException("sun.misc.Unsafe not available on Android");
+ }
+}
diff --git a/feature/cw/src/main/java/com/ve3nea/morse_expert/DecodedTextView.java b/feature/cw/src/main/java/com/ve3nea/morse_expert/DecodedTextView.java
new file mode 100644
index 00000000..b6c16808
--- /dev/null
+++ b/feature/cw/src/main/java/com/ve3nea/morse_expert/DecodedTextView.java
@@ -0,0 +1,138 @@
+package com.ve3nea.morse_expert;
+
+import F2.a;
+import android.content.Context;
+import android.content.Intent;
+import android.media.MediaScannerConnection;
+import android.text.Layout;
+import android.text.Selection;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
+import android.text.format.DateFormat;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.ActionMode;
+import android.widget.TextView;
+import android.widget.Toast;
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * 照搬自 Morse Expert 1.15 DecodedTextView, 类名保持混淆原名。
+ * 适配: 原 extends l.C1702e0(appcompat 混淆类) -> 直接 extends TextView
+ * (C1702e0 仅提供 TextView 兼容功能, 本类未使用其特有方法)。
+ */
+public class DecodedTextView extends TextView {
+
+ /* renamed from: m, reason: collision with root package name */
+ public final Context f11031m;
+
+ /* renamed from: n, reason: collision with root package name */
+ public boolean f11032n;
+
+ /* renamed from: o, reason: collision with root package name */
+ public final AtomicBoolean f11033o;
+
+ public DecodedTextView(Context context, AttributeSet attributeSet) {
+ super(context, attributeSet);
+ this.f11032n = false;
+ this.f11033o = new AtomicBoolean(false);
+ this.f11031m = context;
+ setCustomSelectionActionModeCallback(getActionModeCallback());
+ }
+
+ private ActionMode.Callback getActionModeCallback() {
+ return new a(this);
+ }
+
+ private String getDecodedText() {
+ int selectionStart = getSelectionStart();
+ int selectionEnd = getSelectionEnd();
+ int max = Math.max(0, Math.min(selectionStart, selectionEnd));
+ int max2 = Math.max(0, Math.max(selectionStart, selectionEnd));
+ if (max2 > max) {
+ return getText().subSequence(max, max2).toString();
+ }
+ return getText().toString();
+ }
+
+ @Override // android.widget.TextView
+ public final void onSelectionChanged(int i4, int i5) {
+ super.onSelectionChanged(i4, i5);
+ if (hasSelection()) {
+ this.f11032n = true;
+ }
+ }
+
+ public final void q(SpannableStringBuilder spannableStringBuilder) {
+ boolean z3;
+ try {
+ CharSequence text = getText();
+ Layout layout = getLayout();
+ int lineCount = getLineCount();
+ int length = text.length();
+ int lineHeight = getLineHeight();
+ int scrollY = getScrollY();
+ if (layout.getLineBottom(lineCount - 1) == getHeight() + scrollY) {
+ z3 = true;
+ } else {
+ z3 = false;
+ }
+ getSelectionStart();
+ getSelectionEnd();
+ hasSelection();
+ if (z3) {
+ Selection.setSelection((Spannable) text, length, length);
+ }
+ append(spannableStringBuilder);
+ int i4 = lineCount - 50;
+ if (i4 > 0) {
+ int i5 = lineHeight * i4;
+ getEditableText().delete(0, layout.getLineEnd(lineCount - 51));
+ if (scrollY >= i5) {
+ scrollBy(0, -i5);
+ }
+ }
+ } catch (Exception e4) {
+ Log.e("printChars()", "Exception: ", e4);
+ }
+ }
+
+ public final void r() {
+ String decodedText = getDecodedText();
+ boolean isEmpty = TextUtils.isEmpty(decodedText);
+ Context context = this.f11031m;
+ if (isEmpty) {
+ Toast.makeText(context, "No text to save", 0).show();
+ return;
+ }
+ try {
+ File file = new File(getContext().getExternalFilesDir(null), ((String) DateFormat.format("yyyy-MM-dd_HH_mm_ss", new Date())) + ".txt");
+ String absolutePath = file.getAbsolutePath();
+ PrintWriter printWriter = new PrintWriter(file);
+ try {
+ printWriter.println(decodedText);
+ printWriter.close();
+ MediaScannerConnection.scanFile(context, new String[]{absolutePath}, new String[]{"text/plain"}, null);
+ Toast.makeText(context, "Text saved to " + absolutePath, 1).show();
+ } catch (Throwable th) {
+ printWriter.close();
+ throw th;
+ }
+ } catch (Exception e4) {
+ Log.e("File Save", "Failed", e4);
+ Toast.makeText(context, "Unable to save: " + e4.getMessage(), 1).show();
+ }
+ }
+
+ public final void s() {
+ Intent intent = new Intent("android.intent.action.SEND");
+ intent.setFlags(268435456);
+ intent.putExtra("android.intent.extra.TEXT", getDecodedText());
+ intent.setType("text/plain");
+ this.f11031m.startActivity(Intent.createChooser(intent, "Share Decoded Text"));
+ }
+}
diff --git a/feature/cw/src/main/java/com/ve3nea/morse_expert/MainActivity.java b/feature/cw/src/main/java/com/ve3nea/morse_expert/MainActivity.java
new file mode 100644
index 00000000..547a740e
--- /dev/null
+++ b/feature/cw/src/main/java/com/ve3nea/morse_expert/MainActivity.java
@@ -0,0 +1,232 @@
+
+package com.ve3nea.morse_expert;
+
+import android.content.Context;
+import android.os.Build;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import com.rtbishop.look4sat.feature.cw.R;
+import E2.g;
+import H2.a;
+import H2.b;
+import j1.C1646n;
+
+/**
+ * Ported verbatim from Morse Expert 1.15 MainActivity (com.ve3nea.morse_expert); obfuscated
+ * class/field names kept as-is. Surgery notes: originally extends e.AbstractActivityC1557l
+ * (obfuscated AppCompat base) -> now a plain controller class, Activity injected via
+ * onCreate(Activity, ConstraintLayout) for Compose AndroidView integration. Ads (d1.*),
+ * billing (I2.a), premium/rate menu removed per user. h3.b.r (recursive findViewById),
+ * K1.a.M (immersive status bar), B.i (permissions) replaced with equivalent standard APIs.
+ * Decoder logic (H2.a audio, H2.b core, pas engine) untouched.
+ */
+public class MainActivity {
+
+ public static final /* synthetic */ int f11034K = 0;
+
+ /* renamed from: D, reason: collision with root package name */
+ public C1646n f11035D;
+
+ /* renamed from: E, reason: collision with root package name */
+ public a f11036E;
+
+ /* renamed from: F, reason: collision with root package name */
+ public b f11037F;
+
+ /* renamed from: G, reason: collision with root package name */
+ public long f11038G = 0;
+
+ /* renamed from: J, reason: collision with root package name */
+ public final g f11040J = new g(this, 1);
+
+ /** Injected Activity context (replaces the original this Activity capabilities) */
+ public android.app.Activity mActivity;
+
+ public void onCreate(android.app.Activity activity, ConstraintLayout constraintLayout) {
+ onCreate(activity, constraintLayout, true);
+ }
+
+ /**
+ * applyImmersive=false 用于嵌入小容器(如转发器 CW 面板):
+ * 不触碰宿主窗口的系统栏标志(避免影响整个 Activity)。
+ */
+ public void onCreate(android.app.Activity activity, ConstraintLayout constraintLayout, boolean applyImmersive) {
+ this.mActivity = activity;
+ if (applyImmersive) {
+ // K1.a.M(getWindow(), false): immersive status bar (nav/fullscreen flags, ported as-is)
+ setImmersive(activity.getWindow(), false);
+ }
+ View inflate = constraintLayout;
+ int i4 = R.id.decodedTextView;
+ DecodedTextView decodedTextView = (DecodedTextView) findViewRecursive(inflate, R.id.decodedTextView);
+ if (decodedTextView != null) {
+ i4 = R.id.scaleView;
+ ScaleView scaleView = (ScaleView) findViewRecursive(inflate, R.id.scaleView);
+ if (scaleView != null) {
+ i4 = R.id.statusTextView;
+ TextView textView = (TextView) findViewRecursive(inflate, R.id.statusTextView);
+ if (textView != null) {
+ i4 = R.id.verticalLayout;
+ LinearLayout linearLayout = (LinearLayout) findViewRecursive(inflate, R.id.verticalLayout);
+ if (linearLayout != null) {
+ i4 = R.id.waterfallView;
+ WaterfallSurfaceView waterfallSurfaceView = (WaterfallSurfaceView) findViewRecursive(inflate, R.id.waterfallView);
+ if (waterfallSurfaceView != null) {
+ this.f11035D = new C1646n(constraintLayout, decodedTextView, scaleView, textView, linearLayout, waterfallSurfaceView);
+ ((WaterfallSurfaceView) this.f11035D.f11892k).setOnTouchListener(this.f11040J);
+ // Originally: permission check then v(); permission flow handled by the Compose page
+ // Originally: ad banner mounting (removed)
+ return;
+ }
+ }
+ }
+ }
+ }
+ throw new NullPointerException("Missing required view with ID: " + inflate.getResources().getResourceName(i4));
+ }
+
+ /** Original h3.b.r: recursive findViewById (ported behavior) */
+ private static View findViewRecursive(View view, int id) {
+ if (view instanceof ViewGroup) {
+ ViewGroup viewGroup = (ViewGroup) view;
+ int childCount = viewGroup.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View found = viewGroup.getChildAt(i).findViewById(id);
+ if (found != null) {
+ return found;
+ }
+ }
+ return null;
+ }
+ return null;
+ }
+
+ /** Original K1.a.M(window, false): immersive (hide nav/fullscreen flags, ported as-is) */
+ private static void setImmersive(Window window, boolean immersive) {
+ if (Build.VERSION.SDK_INT >= 30) {
+ window.setDecorFitsSystemWindows(!immersive);
+ if (immersive) {
+ window.getDecorView().setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN);
+ } else {
+ window.getDecorView().setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+ }
+ } else {
+ View decorView = window.getDecorView();
+ int systemUiVisibility = decorView.getSystemUiVisibility();
+ decorView.setSystemUiVisibility(immersive ? (systemUiVisibility & (-1793)) : (systemUiVisibility | 1792));
+ }
+ }
+
+ /** Original v(): audio capture + decoder core init (logic unchanged) */
+ public void v() {
+ this.f11036E = new a();
+ b bVar = new b(mActivity.getApplicationContext());
+ this.f11037F = bVar;
+ this.f11036E.f601l = bVar;
+ bVar.f619o = (WaterfallSurfaceView) this.f11035D.f11892k;
+ bVar.f620p = this;
+ bVar.f621q = this;
+ }
+
+ /** Original onResume: restore decoding (message type/font/background/record start/waterfall) */
+ public void onResume() {
+ android.content.SharedPreferences prefs = mActivity.getSharedPreferences(
+ mActivity.getPackageName() + "_preferences", Context.MODE_PRIVATE);
+ String messageType = prefs.getString("message_type", "general_text");
+ b bVar = this.f11037F;
+ if (bVar != null) {
+ bVar.f623s.set(messageType.equals("ham_radio_qso"));
+ }
+ ((DecodedTextView) this.f11035D.f11888g).setTextSize(Math.max(7, prefs.getInt("text_font_size", 18)));
+ b bVar2 = this.f11037F;
+ if (bVar2 != null) {
+ bVar2.f617m.b(mActivity);
+ ((DecodedTextView) this.f11035D.f11888g).setBackgroundColor(this.f11037F.f617m.f665a[0]);
+ }
+ a aVar = this.f11036E;
+ if (aVar != null) {
+ android.media.AudioRecord audioRecord = aVar.f596g;
+ audioRecord.startRecording();
+ if (audioRecord.getState() != 1) {
+ android.util.Log.e("AudioRecord", "cannot start");
+ }
+ aVar.f598i.set(true);
+ }
+ ((WaterfallSurfaceView) this.f11035D.f11892k).onResume();
+ // Originally: ad lifecycle (removed)
+ }
+
+ /** Original onPause: stop recording + waterfall pause */
+ public void onPause() {
+ a aVar = this.f11036E;
+ if (aVar != null) {
+ aVar.f598i.set(false);
+ android.media.AudioRecord audioRecord = aVar.f596g;
+ audioRecord.stop();
+ if (audioRecord.getState() != 1) {
+ android.util.Log.e("AudioRecord", "cannot stop");
+ }
+ }
+ ((WaterfallSurfaceView) this.f11035D.f11892k).onPause();
+ }
+
+ /** Original onDestroy: release audio/decoder (billing cleanup removed) */
+ public void onDestroy() {
+ a aVar = this.f11036E;
+ if (aVar != null) {
+ aVar.f598i.set(false);
+ try {
+ aVar.f596g.stop();
+ aVar.f596g.release();
+ } catch (Exception ignored) {
+ }
+ aVar.f597h.shutdownNow();
+ }
+ this.f11036E = null;
+ this.f11037F = null;
+ }
+
+ /** Menu: clear decoded text (original clear_mnu) */
+ public void clearDecoded() {
+ ((DecodedTextView) this.f11035D.f11888g).setText("");
+ }
+
+ /** Menu: pause/resume decoding (original pause_mnu, red/white icon toggle logic) */
+ public boolean togglePause() {
+ java.util.concurrent.atomic.AtomicBoolean atomicBoolean = ((DecodedTextView) this.f11035D.f11888g).f11033o;
+ atomicBoolean.set(!atomicBoolean.get());
+ return atomicBoolean.get();
+ }
+
+ /** Menu: save text (original save_mnu -> DecodedTextView.r()) */
+ public void saveText() {
+ ((DecodedTextView) this.f11035D.f11888g).r();
+ }
+
+ /** Menu: record signals (original record_signals_mnu) */
+ public void recordSignals() {
+ this.f11037F.f626v.set(true);
+ }
+
+ /** Original tap_back_again_to_close hint */
+ public boolean handleBackPress() {
+ if (System.currentTimeMillis() < this.f11038G + 2000) {
+ return true; // double-back: exit
+ }
+ this.f11038G = System.currentTimeMillis();
+ Toast.makeText(mActivity, R.string.tap_back_again_to_close, 0).show();
+ return false;
+ }
+
+ /** Start decoding after permission granted (original onRequestPermissionsResult success) */
+ public void onPermissionGranted() {
+ v();
+ }
+}
diff --git a/feature/cw/src/main/java/com/ve3nea/morse_expert/ScaleView.java b/feature/cw/src/main/java/com/ve3nea/morse_expert/ScaleView.java
new file mode 100644
index 00000000..16e7410e
--- /dev/null
+++ b/feature/cw/src/main/java/com/ve3nea/morse_expert/ScaleView.java
@@ -0,0 +1,76 @@
+package com.ve3nea.morse_expert;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.util.AttributeSet;
+import android.view.View;
+
+/* loaded from: classes.dex */
+public class ScaleView extends View {
+ public int f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public int f11041g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public final Paint f11042h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public final Paint f11043i;
+
+ /* renamed from: j, reason: collision with root package name */
+ public final Paint f11044j;
+
+ /* renamed from: k, reason: collision with root package name */
+ public final Paint f11045k;
+
+ public ScaleView(Context context, AttributeSet attributeSet) {
+ super(context, attributeSet);
+ Paint paint = new Paint();
+ this.f11042h = paint;
+ paint.setColor(-16711936);
+ Paint paint2 = new Paint();
+ this.f11043i = paint2;
+ paint2.setColor(-16744448);
+ Paint paint3 = new Paint();
+ this.f11044j = paint3;
+ paint3.setColor(-256);
+ Paint paint4 = new Paint();
+ this.f11045k = paint4;
+ paint4.setColor(-8355840);
+ }
+
+ @Override // android.view.View
+ public final void onDraw(Canvas canvas) {
+ Paint paint;
+ super.onDraw(canvas);
+ int i4 = this.f11041g;
+ if (i4 != 1) {
+ if (i4 != 2) {
+ if (i4 != 3) {
+ if (i4 != 4) {
+ return;
+ } else {
+ paint = this.f11044j;
+ }
+ } else {
+ paint = this.f11045k;
+ }
+ } else {
+ paint = this.f11042h;
+ }
+ } else {
+ paint = this.f11043i;
+ }
+ int round = (int) Math.round(getWidth() * 0.7d);
+ Path path = new Path();
+ path.moveTo(0.0f, this.f);
+ float f = round;
+ path.lineTo(f, this.f - round);
+ path.lineTo(f, this.f + round);
+ path.close();
+ canvas.drawPath(path, paint);
+ }
+}
diff --git a/feature/cw/src/main/java/com/ve3nea/morse_expert/WaterfallSurfaceView.java b/feature/cw/src/main/java/com/ve3nea/morse_expert/WaterfallSurfaceView.java
new file mode 100644
index 00000000..73d51de7
--- /dev/null
+++ b/feature/cw/src/main/java/com/ve3nea/morse_expert/WaterfallSurfaceView.java
@@ -0,0 +1,19 @@
+package com.ve3nea.morse_expert;
+
+import J2.b;
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+
+/* loaded from: classes.dex */
+public class WaterfallSurfaceView extends GLSurfaceView {
+ public final b f;
+
+ public WaterfallSurfaceView(Context context, AttributeSet attributeSet) {
+ super(context, attributeSet);
+ setEGLContextClientVersion(2);
+ b bVar = new b(context, H2.b.f603B);
+ this.f = bVar;
+ setRenderer(bVar);
+ }
+}
diff --git a/feature/cw/src/main/java/d1/AbstractC1518b.java b/feature/cw/src/main/java/d1/AbstractC1518b.java
new file mode 100644
index 00000000..ca3196fa
--- /dev/null
+++ b/feature/cw/src/main/java/d1/AbstractC1518b.java
@@ -0,0 +1,82 @@
+package d1;
+
+/* renamed from: d1.b, reason: case insensitive filesystem */
+/* 照搬自 Morse Expert 1.15, 混淆名保持。b(Parcel)/c(y2.d) 为库工具已裁剪(L1/y2 库依赖)。 */
+public abstract /* synthetic */ class AbstractC1518b {
+ public static float a(float f, float f4, k3.d dVar, long j4, float f5, float f6) {
+ dVar.c(j4, f - f4);
+ return f5 + f6;
+ }
+
+ public static String d(String str, int i4) {
+ return str + i4;
+ }
+
+ public static String e(String str, String str2) {
+ return str + str2;
+ }
+
+ public static String f(String str, String str2, String str3) {
+ return str + str2 + str3;
+ }
+
+ public static String g(StringBuilder sb, int i4, String str) {
+ sb.append(i4);
+ sb.append(str);
+ return sb.toString();
+ }
+
+ public static String h(StringBuilder sb, String str, String str2) {
+ sb.append(str);
+ sb.append(str2);
+ return sb.toString();
+ }
+
+ public static /* synthetic */ boolean i(Object obj) {
+ return obj != null;
+ }
+
+ public static float j(float f, float f4, k3.d dVar, long j4, float f5, float f6) {
+ dVar.c(j4, f + f4);
+ return f5 + f6;
+ }
+
+ public static String k(String str, String str2) {
+ return str + str2;
+ }
+
+ public static float l(float f, float f4, k3.d dVar, long j4, float f5, float f6) {
+ dVar.c(j4, f - f4);
+ return f5 - f6;
+ }
+
+ public static float m(float f, float f4, k3.d dVar, long j4, float f5, float f6) {
+ dVar.c(j4, f + f4);
+ return f5 - f6;
+ }
+
+ public static /* synthetic */ String n(int i4) {
+ switch (i4) {
+ case 1:
+ return "NONE";
+ case 2:
+ return "LEFT";
+ case 3:
+ return "TOP";
+ case 4:
+ return "RIGHT";
+ case 5:
+ return "BOTTOM";
+ case 6:
+ return "BASELINE";
+ case 7:
+ return "CENTER";
+ case 8:
+ return "CENTER_X";
+ case 9:
+ return "CENTER_Y";
+ default:
+ throw null;
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/g3/a.java b/feature/cw/src/main/java/g3/a.java
new file mode 100644
index 00000000..bef09c6e
--- /dev/null
+++ b/feature/cw/src/main/java/g3/a.java
@@ -0,0 +1,34 @@
+package g3;
+
+/* loaded from: classes.dex */
+public final class a {
+
+ /* renamed from: a, reason: collision with root package name */
+ public final int f11582a;
+
+ /* renamed from: b, reason: collision with root package name */
+ public final double f11583b;
+ public final double c;
+
+ public a(double d4) {
+ int i4 = (int) (0.6366197723675814d * d4);
+ while (true) {
+ double d5 = -i4;
+ double d6 = 1.570796251296997d * d5;
+ double d7 = d4 + d6;
+ double d8 = 7.549789948768648E-8d * d5;
+ double d9 = d8 + d7;
+ double d10 = (-((d7 - d4) - d6)) + (-((d9 - d7) - d8));
+ double d11 = d5 * 6.123233995736766E-17d;
+ double d12 = d11 + d9;
+ double d13 = d10 + (-((d12 - d9) - d11));
+ if (d12 > 0.0d) {
+ this.f11582a = i4;
+ this.f11583b = d12;
+ this.c = d13;
+ return;
+ }
+ i4--;
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/g3/b.java b/feature/cw/src/main/java/g3/b.java
new file mode 100644
index 00000000..780e84ee
--- /dev/null
+++ b/feature/cw/src/main/java/g3/b.java
@@ -0,0 +1,8 @@
+package g3;
+
+/* loaded from: classes.dex */
+public abstract class b {
+
+ /* renamed from: a, reason: collision with root package name */
+ public static final double[][] f11584a = (double[][]) d.f11591a.clone();
+}
diff --git a/feature/cw/src/main/java/g3/c.java b/feature/cw/src/main/java/g3/c.java
new file mode 100644
index 00000000..b196010f
--- /dev/null
+++ b/feature/cw/src/main/java/g3/c.java
@@ -0,0 +1,507 @@
+package g3;
+
+/* loaded from: classes.dex */
+public abstract class c {
+
+ /* renamed from: a, reason: collision with root package name */
+ public static final double[][] f11585a;
+
+ /* renamed from: b, reason: collision with root package name */
+ public static final double[] f11586b;
+ public static final double[] c;
+
+ /* renamed from: d, reason: collision with root package name */
+ public static final double[] f11587d;
+
+ /* renamed from: e, reason: collision with root package name */
+ public static final double[] f11588e;
+ public static final long[] f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public static final long[] f11589g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public static final double[] f11590h;
+
+ static {
+ StrictMath.log(Double.MAX_VALUE);
+ f11585a = new double[][]{new double[]{1.0d, 5.669184079525E-24d}, new double[]{-0.25d, -0.25d}, new double[]{0.3333333134651184d, 1.986821492305628E-8d}, new double[]{-0.25d, -6.663542893624021E-14d}, new double[]{0.19999998807907104d, 1.1921056801463227E-8d}, new double[]{-0.1666666567325592d, -7.800414592973399E-9d}, new double[]{0.1428571343421936d, 5.650007086920087E-9d}, new double[]{-0.12502530217170715d, -7.44321345601866E-11d}, new double[]{0.11113807559013367d, 9.219544613762692E-9d}};
+ f11586b = new double[]{0.0d, 0.1246747374534607d, 0.24740394949913025d, 0.366272509098053d, 0.4794255495071411d, 0.5850973129272461d, 0.6816387176513672d, 0.7675435543060303d, 0.8414709568023682d, 0.902267575263977d, 0.9489846229553223d, 0.9808930158615112d, 0.9974949359893799d, 0.9985313415527344d};
+ c = new double[]{0.0d, -4.068233003401932E-9d, 9.755392680573412E-9d, 1.9987994582857286E-8d, -1.0902938113007961E-8d, -3.9986783938944604E-8d, 4.23719669792332E-8d, -5.207000323380292E-8d, 2.800552834259E-8d, 1.883511811213715E-8d, -3.5997360512765566E-9d, 4.116164446561962E-8d, 5.0614674548127384E-8d, -1.0129027912496858E-9d};
+ f11587d = new double[]{1.0d, 0.9921976327896118d, 0.9689123630523682d, 0.9305076599121094d, 0.8775825500488281d, 0.8109631538391113d, 0.7316888570785522d, 0.6409968137741089d, 0.5403022766113281d, 0.4311765432357788d, 0.3153223395347595d, 0.19454771280288696d, 0.07073719799518585d, -0.05417713522911072d};
+ f11588e = new double[]{0.0d, 3.4439717236742845E-8d, 5.865827662008209E-8d, -3.7999795083850525E-8d, 1.184154459111628E-8d, -3.43338934259355E-8d, 1.1795268640216787E-8d, 4.438921624363781E-8d, 2.925681159240093E-8d, -2.6437112632041807E-8d, 2.2860509143963117E-8d, -4.813899778443457E-9d, 3.6725170580355583E-9d, 2.0217439756338078E-10d};
+ f = new long[]{2935890503282001226L, 9154082963658192752L, 3952090531849364496L, 9193070505571053912L, 7910884519577875640L, 113236205062349959L, 4577762542105553359L, -5034868814120038111L, 4208363204685324176L, 5648769086999809661L, 2819561105158720014L, -4035746434778044925L, -302932621132653753L, -2644281811660520851L, -3183605296591799669L, 6722166367014452318L, -3512299194304650054L, -7278142539171889152L};
+ f11589g = new long[]{-3958705157555305932L, -4267615245585081135L};
+ f11590h = new double[]{0.0d, 0.125d, 0.25d, 0.375d, 0.5d, 0.625d, 0.75d, 0.875d, 1.0d, 1.125d, 1.25d, 1.375d, 1.5d, 1.625d};
+ }
+
+ public static double a(double d4) {
+ double d5;
+ if (d4 != d4) {
+ return d4;
+ }
+ if (d4 == d4 && d4 < 4.503599627370496E15d && d4 > -4.503599627370496E15d) {
+ long j4 = (long) d4;
+ if (d4 < 0.0d && j4 != d4) {
+ j4--;
+ }
+ if (j4 == 0) {
+ d5 = j4 * d4;
+ } else {
+ d5 = j4;
+ }
+ } else {
+ d5 = d4;
+ }
+ if (d5 == d4) {
+ return d5;
+ }
+ double d6 = d5 + 1.0d;
+ if (d6 == 0.0d) {
+ return d4 * d6;
+ }
+ return d6;
+ }
+
+ public static double b(double d4) {
+ double g4;
+ double d5 = 0.0d;
+ if (d4 < 0.0d) {
+ d4 = -d4;
+ }
+ if (d4 != d4 || d4 == Double.POSITIVE_INFINITY) {
+ return Double.NaN;
+ }
+ int i4 = 0;
+ if (d4 > 3294198.0d) {
+ double[] dArr = new double[3];
+ e(d4, dArr);
+ i4 = ((int) dArr[0]) & 3;
+ d4 = dArr[1];
+ d5 = dArr[2];
+ } else if (d4 > 1.5707963267948966d) {
+ a aVar = new a(d4);
+ i4 = aVar.f11582a & 3;
+ d4 = aVar.f11583b;
+ d5 = aVar.c;
+ }
+ if (i4 != 0) {
+ if (i4 != 1) {
+ if (i4 != 2) {
+ if (i4 != 3) {
+ return Double.NaN;
+ }
+ return g(d4, d5);
+ }
+ g4 = c(d4, d5);
+ } else {
+ g4 = g(d4, d5);
+ }
+ return -g4;
+ }
+ return c(d4, d5);
+ }
+
+ public static double c(double d4, double d5) {
+ double d6 = 1.5707963267948966d - d4;
+ return g(d6, (6.123233995736766E-17d - d5) + (-((d6 - 1.5707963267948966d) + d4)));
+ }
+
+ public static double d(double d4) {
+ if (d4 != 0.0d) {
+ long doubleToRawLongBits = Double.doubleToRawLongBits(d4);
+ if (((Long.MIN_VALUE & doubleToRawLongBits) != 0 || d4 != d4) && d4 != 0.0d) {
+ return Double.NaN;
+ }
+ if (d4 == Double.POSITIVE_INFINITY) {
+ return Double.POSITIVE_INFINITY;
+ }
+ int i4 = ((int) (doubleToRawLongBits >> 52)) - 1023;
+ if ((9218868437227405312L & doubleToRawLongBits) == 0) {
+ if (d4 == 0.0d) {
+ return Double.NEGATIVE_INFINITY;
+ }
+ doubleToRawLongBits <<= 1;
+ while ((4503599627370496L & doubleToRawLongBits) == 0) {
+ i4--;
+ doubleToRawLongBits <<= 1;
+ }
+ }
+ if ((i4 == -1 || i4 == 0) && d4 < 1.01d && d4 > 0.99d) {
+ double d5 = d4 - 1.0d;
+ double d6 = d5 * 1.073741824E9d;
+ double d7 = (d5 + d6) - d6;
+ double d8 = d5 - d7;
+ double[][] dArr = f11585a;
+ double[] dArr2 = dArr[dArr.length - 1];
+ double d9 = dArr2[0];
+ double d10 = dArr2[1];
+ for (int length = dArr.length - 2; length >= 0; length--) {
+ double d11 = d9 * d7;
+ double d12 = (d10 * d8) + (d10 * d7) + (d9 * d8);
+ double d13 = d11 * 1.073741824E9d;
+ double d14 = (d11 + d13) - d13;
+ double d15 = (d11 - d14) + d12;
+ double[] dArr3 = dArr[length];
+ double d16 = d14 + dArr3[0];
+ double d17 = d15 + dArr3[1];
+ double d18 = d16 * 1.073741824E9d;
+ d9 = (d16 + d18) - d18;
+ d10 = (d16 - d9) + d17;
+ }
+ double d19 = d9 * d7;
+ double d20 = (d10 * d8) + (d7 * d10) + (d9 * d8);
+ double d21 = 1.073741824E9d * d19;
+ double d22 = (d19 + d21) - d21;
+ return (d19 - d22) + d20 + d22;
+ }
+ long j4 = 4499201580859392L & doubleToRawLongBits;
+ double[] dArr4 = b.f11584a[(int) (j4 >> 42)];
+ double d23 = (doubleToRawLongBits & 4398046511103L) / (j4 + 4.503599627370496E15d);
+ double d24 = (((((((((((-0.16624882440418567d) * d23) + 0.19999954120254515d) * d23) - 0.2499999997677497d) * d23) + 0.3333333333332802d) * d23) - 0.5d) * d23) + 1.0d) * d23;
+ double d25 = i4;
+ double d26 = 0.6931470632553101d * d25;
+ double d27 = dArr4[0];
+ double d28 = d26 + d27;
+ double d29 = (-((d28 - d26) - d27)) + 0.0d;
+ double d30 = d28 + d24;
+ double d31 = d29 + (-((d30 - d28) - d24));
+ double d32 = d25 * 1.1730463525082348E-7d;
+ double d33 = d30 + d32;
+ double d34 = d31 + (-((d33 - d30) - d32));
+ double d35 = dArr4[1];
+ double d36 = d33 + d35;
+ double d37 = d36 + 0.0d;
+ return d34 + (-((d36 - d33) - d35)) + (-((d37 - d36) - 0.0d)) + d37;
+ }
+ return Double.NEGATIVE_INFINITY;
+ }
+
+ public static void e(double d4, double[] dArr) {
+ long j4;
+ long j5;
+ long j6;
+ boolean z3;
+ boolean z4;
+ boolean z5;
+ boolean z6;
+ boolean z7;
+ boolean z8;
+ boolean z9;
+ boolean z10;
+ boolean z11;
+ boolean z12;
+ boolean z13;
+ boolean z14;
+ boolean z15;
+ boolean z16;
+ boolean z17;
+ boolean z18;
+ boolean z19;
+ boolean z20;
+ boolean z21;
+ boolean z22;
+ boolean z23;
+ long j7;
+ long doubleToRawLongBits = Double.doubleToRawLongBits(d4);
+ int i4 = ((int) ((doubleToRawLongBits >> 52) & 2047)) - 1022;
+ long j8 = ((doubleToRawLongBits & 4503599627370495L) | 4503599627370496L) << 11;
+ int i5 = i4 >> 6;
+ int i6 = i4 - (i5 << 6);
+ long[] jArr = f;
+ if (i6 != 0) {
+ if (i5 == 0) {
+ j7 = 0;
+ } else {
+ j7 = jArr[i5 - 1] << i6;
+ }
+ long j9 = jArr[i5];
+ int i7 = 64 - i6;
+ j4 = j7 | (j9 >>> i7);
+ long j10 = jArr[i5 + 1];
+ j5 = (j9 << i6) | (j10 >>> i7);
+ j6 = (jArr[i5 + 2] >>> i7) | (j10 << i6);
+ } else {
+ if (i5 == 0) {
+ j4 = 0;
+ } else {
+ j4 = jArr[i5 - 1];
+ }
+ j5 = jArr[i5];
+ j6 = jArr[i5 + 1];
+ }
+ long j11 = j8 >>> 32;
+ long j12 = j8 & 4294967295L;
+ long j13 = j5 >>> 32;
+ long j14 = j5 & 4294967295L;
+ long j15 = j11 * j13;
+ long j16 = j12 * j14;
+ long j17 = j13 * j12;
+ long j18 = j14 * j11;
+ long j19 = j16 + (j18 << 32);
+ long j20 = j15 + (j18 >>> 32);
+ if ((j16 & Long.MIN_VALUE) != 0) {
+ z3 = true;
+ } else {
+ z3 = false;
+ }
+ if ((j18 & 2147483648L) != 0) {
+ z4 = true;
+ } else {
+ z4 = false;
+ }
+ long j21 = j19 & Long.MIN_VALUE;
+ if (j21 != 0) {
+ z5 = true;
+ } else {
+ z5 = false;
+ }
+ if ((z3 && z4) || ((z3 || z4) && !z5)) {
+ j20++;
+ }
+ if (j21 != 0) {
+ z6 = true;
+ } else {
+ z6 = false;
+ }
+ if ((j17 & 2147483648L) != 0) {
+ z7 = true;
+ } else {
+ z7 = false;
+ }
+ long j22 = j19 + (j17 << 32);
+ long j23 = j20 + (j17 >>> 32);
+ long j24 = j22 & Long.MIN_VALUE;
+ if (j24 != 0) {
+ z8 = true;
+ } else {
+ z8 = false;
+ }
+ if ((z6 && z7) || ((z6 || z7) && !z8)) {
+ j23++;
+ }
+ long j25 = j6 >>> 32;
+ long j26 = (j11 * j25) + ((((j6 & 4294967295L) * j11) + (j25 * j12)) >>> 32);
+ if (j24 != 0) {
+ z9 = true;
+ } else {
+ z9 = false;
+ }
+ if ((j26 & Long.MIN_VALUE) != 0) {
+ z10 = true;
+ } else {
+ z10 = false;
+ }
+ long j27 = j22 + j26;
+ if ((j27 & Long.MIN_VALUE) != 0) {
+ z11 = true;
+ } else {
+ z11 = false;
+ }
+ if ((z9 && z10) || ((z9 || z10) && !z11)) {
+ j23++;
+ }
+ long j28 = j4 >>> 32;
+ long j29 = j4 & 4294967295L;
+ long j30 = (j12 * j29) + (((j11 * j29) + (j12 * j28)) << 32) + j23;
+ int i8 = (int) (j30 >>> 62);
+ long j31 = (j27 >>> 62) | (j30 << 2);
+ long j32 = j27 << 2;
+ long j33 = j31 >>> 32;
+ long j34 = j31 & 4294967295L;
+ long[] jArr2 = f11589g;
+ long j35 = jArr2[0];
+ long j36 = j35 >>> 32;
+ long j37 = j35 & 4294967295L;
+ long j38 = j34 * j37;
+ long j39 = j34 * j36;
+ long j40 = j33 * j37;
+ long j41 = j38 + (j40 << 32);
+ long j42 = (j33 * j36) + (j40 >>> 32);
+ if ((j38 & Long.MIN_VALUE) != 0) {
+ z12 = true;
+ } else {
+ z12 = false;
+ }
+ if ((j40 & 2147483648L) != 0) {
+ z13 = true;
+ } else {
+ z13 = false;
+ }
+ long j43 = j41 & Long.MIN_VALUE;
+ if (j43 != 0) {
+ z14 = true;
+ } else {
+ z14 = false;
+ }
+ if ((z12 && z13) || ((z12 || z13) && !z14)) {
+ j42++;
+ }
+ if (j43 != 0) {
+ z15 = true;
+ } else {
+ z15 = false;
+ }
+ if ((j39 & 2147483648L) != 0) {
+ z16 = true;
+ } else {
+ z16 = false;
+ }
+ long j44 = j41 + (j39 << 32);
+ long j45 = j42 + (j39 >>> 32);
+ long j46 = j44 & Long.MIN_VALUE;
+ if (j46 != 0) {
+ z17 = true;
+ } else {
+ z17 = false;
+ }
+ if ((z15 && z16) || ((z15 || z16) && !z17)) {
+ j45++;
+ }
+ long j47 = jArr2[1];
+ long j48 = j47 >>> 32;
+ long j49 = (j33 * j48) + (((j33 * (j47 & 4294967295L)) + (j34 * j48)) >>> 32);
+ if (j46 != 0) {
+ z18 = true;
+ } else {
+ z18 = false;
+ }
+ if ((j49 & Long.MIN_VALUE) != 0) {
+ z19 = true;
+ } else {
+ z19 = false;
+ }
+ long j50 = j44 + j49;
+ long j51 = j50 & Long.MIN_VALUE;
+ if (j51 != 0) {
+ z20 = true;
+ } else {
+ z20 = false;
+ }
+ if ((z18 && z19) || ((z18 || z19) && !z20)) {
+ j45++;
+ }
+ long j52 = j32 >>> 32;
+ long j53 = (j52 * j36) + (((j52 * j37) + ((j32 & 4294967295L) * j36)) >>> 32);
+ if (j51 != 0) {
+ z21 = true;
+ } else {
+ z21 = false;
+ }
+ if ((j53 & Long.MIN_VALUE) != 0) {
+ z22 = true;
+ } else {
+ z22 = false;
+ }
+ if (((j50 + j53) & Long.MIN_VALUE) != 0) {
+ z23 = true;
+ } else {
+ z23 = false;
+ }
+ if ((z21 && z22) || ((z21 || z22) && !z23)) {
+ j45++;
+ }
+ double d5 = (j45 >>> 12) / 4.503599627370496E15d;
+ double d6 = ((((j45 & 4095) << 40) + (f11589g[0] >>> 24)) / 4.503599627370496E15d) / 4.503599627370496E15d; // r34 = f11589g[0](smali: aget-wide v5, v2)
+ double d7 = d5 + d6;
+ dArr[0] = i8;
+ dArr[1] = d7 * 2.0d;
+ dArr[2] = (-((d7 - d5) - d6)) * 2.0d;
+ }
+
+ /* JADX WARN: Removed duplicated region for block: B:20:0x005f */
+ /* JADX WARN: Removed duplicated region for block: B:22:0x0063 */
+ /* JADX WARN: Removed duplicated region for block: B:32:0x007a */
+ /*
+ Code decompiled incorrectly, please refer to instructions dump.
+ */
+ public static double f(double d4) {
+ boolean z3;
+ double d5;
+ double d6;
+ double g4;
+ int i4 = 0;
+ double d7 = 0.0d;
+ if (d4 < 0.0d) {
+ d5 = -d4;
+ z3 = true;
+ } else {
+ z3 = false;
+ d5 = d4;
+ }
+ if (d5 == 0.0d) {
+ if (Double.doubleToRawLongBits(d4) >= 0) {
+ return 0.0d;
+ }
+ return -0.0d;
+ }
+ if (d5 != d5 || d5 == Double.POSITIVE_INFINITY) {
+ return Double.NaN;
+ }
+ if (d5 > 3294198.0d) {
+ double[] dArr = new double[3];
+ e(d5, dArr);
+ i4 = ((int) dArr[0]) & 3;
+ d5 = dArr[1];
+ d6 = dArr[2];
+ } else {
+ if (d5 > 1.5707963267948966d) {
+ a aVar = new a(d5);
+ int i5 = aVar.f11582a & 3;
+ d5 = aVar.f11583b;
+ d6 = aVar.c;
+ i4 = i5;
+ }
+ if (z3) {
+ i4 ^= 2;
+ }
+ // smali 证实: f() = sin(象限 switch!):
+ // case 0 -> g(d5,0)(sin(0-π/2))
+ // case 1 -> c(d5,0)(sin(π/2-π) = cos(余角))
+ // case 2 -> -g(d5,0)(sin(π-3π/2) = -sin(余角))
+ // case 3 -> -c(d5,0)(sin(3π/2-2π) = -cos(余角))
+ // jadx 畸形嵌套 if 把 case 0 还原成 return NaN(小角度全 NaN!),
+ // 且 case 1/2/3 全走 g() —— 旋转因子表 329 个 NaN + 频谱错乱的根源!
+ if (i4 == 0) {
+ return g(d5, d7);
+ }
+ if (i4 == 1) {
+ return c(d5, d7);
+ }
+ if (i4 == 2) {
+ return -g(d5, d7);
+ }
+ return -c(d5, d7);
+ }
+ d7 = d6;
+ // jadx 还原不完整(smali 650 行, jadx 只还原 63 行); f() 未被任何代码调用(死代码),
+ // 按 smali 尾部语义补 return(cond_0: v22 = v22 + v14; return v22)
+ return d7;
+ }
+
+ public static double g(double d4, double d5) {
+ int i4 = (int) ((8.0d * d4) + 0.5d);
+ double d6 = d4 - f11590h[i4];
+ double d7 = f11586b[i4];
+ double d8 = c[i4];
+ double d9 = f11587d[i4];
+ double d10 = f11588e[i4];
+ double d11 = d6 * d6;
+ double d12 = ((((((2.7553817452272217E-6d * d11) - 1.9841269659586505E-4d) * d11) + 0.008333333333329196d) * d11) - 0.16666666666666666d) * d11 * d6;
+ double d13 = ((((((2.479773539153719E-5d * d11) - 0.0013888888689039883d) * d11) + 0.041666666666621166d) * d11) - 0.49999999999999994d) * d11;
+ double d14 = 1.073741824E9d * d6;
+ double d15 = (d6 + d14) - d14;
+ double d16 = (d6 - d15) + d12;
+ double d17 = d7 + 0.0d;
+ double d18 = d9 * d15;
+ double d19 = d17 + d18;
+ double d20 = (d10 * d16) + (d8 * d13) + (d10 * d15) + (d9 * d16) + (d7 * d13) + (-((d17 - 0.0d) - d7)) + 0.0d + (-((d19 - d17) - d18)) + d8;
+ if (d5 != 0.0d) {
+ double d21 = (((d13 + 1.0d) * (d9 + d10)) - ((d15 + d16) * (d7 + d8))) * d5;
+ double d22 = d19 + d21;
+ d20 += -((d22 - d19) - d21);
+ d19 = d22;
+ }
+ return d19 + d20;
+ }
+}
diff --git a/feature/cw/src/main/java/g3/d.java b/feature/cw/src/main/java/g3/d.java
new file mode 100644
index 00000000..c39a4f98
--- /dev/null
+++ b/feature/cw/src/main/java/g3/d.java
@@ -0,0 +1,9 @@
+package g3;
+
+/* loaded from: classes.dex */
+public abstract class d {
+
+ /* renamed from: a, reason: collision with root package name */
+ public static final double[][] f11591a = {new double[]{0.0d, 0.0d}, new double[]{9.760860120877624E-4d, -3.903230345984362E-11d}, new double[]{0.0019512202125042677d, -8.124251825289188E-11d}, new double[]{0.0029254043474793434d, -1.8374207360194882E-11d}, new double[]{0.0038986406289041042d, -2.1324678121885073E-10d}, new double[]{0.004870930686593056d, -4.5199654318611534E-10d}, new double[]{0.00584227591753006d, -2.933016992001806E-10d}, new double[]{0.006812678650021553d, -2.325147219074669E-10d}, new double[]{0.007782140746712685d, -3.046577356838847E-10d}, new double[]{0.008750664070248604d, -5.500631513861575E-10d}, new double[]{0.00971824862062931d, 8.48292035519895E-10d}, new double[]{0.010684899985790253d, 1.1422610134013436E-10d}, new double[]{0.01165061630308628d, 9.168889933128375E-10d}, new double[]{0.012615403160452843d, -5.303786078838E-10d}, new double[]{0.013579258695244789d, -5.688639355498786E-10d}, new double[]{0.01454218477010727d, 7.296670293275653E-10d}, new double[]{0.015504186972975731d, -4.370104767451421E-10d}, new double[]{0.016465261578559875d, 1.43695591408832E-9d}, new double[]{0.01742541790008545d, -1.1862263158849434E-9d}, new double[]{0.018384650349617004d, -9.482976524690715E-10d}, new double[]{0.01934296265244484d, 1.9068609515836638E-10d}, new double[]{0.020300358533859253d, 2.655990315697216E-10d}, new double[]{0.021256837993860245d, 1.0315548713040775E-9d}, new double[]{0.022212404757738113d, 5.13345647019085E-10d}, new double[]{0.02316705882549286d, 4.5604151934208014E-10d}, new double[]{0.02412080392241478d, -1.1255706987475148E-9d}, new double[]{0.025073636323213577d, 1.2289023836765196E-9d}, new double[]{0.02602556347846985d, 1.7990281828096504E-9d}, new double[]{0.026976589113473892d, -1.4152718164638451E-9d}, new double[]{0.02792670577764511d, 7.568772963781632E-10d}, new double[]{0.0288759246468544d, -1.1449998592111558E-9d}, new double[]{0.029824241995811462d, -1.6850976862319495E-9d}, new double[]{0.030771657824516296d, 8.422373919843096E-10d}, new double[]{0.0317181795835495d, 6.872350402175489E-10d}, new double[]{0.03266380727291107d, -4.541194749189272E-10d}, new double[]{0.03360854089260101d, -8.9064764856495E-10d}, new double[]{0.034552380442619324d, 1.0640404096769032E-9d}, new double[]{0.0354953333735466d, -3.5901655945224663E-10d}, new double[]{0.03643739968538284d, -3.4829517943661266E-9d}, new double[]{0.037378571927547455d, 8.149473794244232E-10d}, new double[]{0.03831886500120163d, -6.990650304449166E-10d}, new double[]{0.03925827145576477d, 1.0883076226453258E-9d}, new double[]{0.040196798741817474d, 3.845192807999274E-10d}, new double[]{0.04113444685935974d, -1.1570594692045927E-9d}, new double[]{0.04207121580839157d, -1.8877045166697178E-9d}, new double[]{0.043007105588912964d, -1.6332083257987747E-10d}, new double[]{0.04394212365150452d, -1.7950057534514933E-9d}, new double[]{0.04487626254558563d, 2.302710041648838E-9d}, new double[]{0.045809537172317505d, -1.1410233017161343E-9d}, new double[]{0.04674194008111954d, -3.0498741599744685E-9d}, new double[]{0.04767347127199173d, -1.8026348269183678E-9d}, new double[]{0.04860413819551468d, -3.233204600453039E-9d}, new double[]{0.04953393340110779d, 1.7211688427961583E-9d}, new double[]{0.05046287178993225d, -2.329967807055457E-10d}, new double[]{0.05139094591140747d, -4.191810118556531E-11d}, new double[]{0.052318163216114044d, -3.5574324788328143E-9d}, new double[]{0.053244516253471375d, -1.7346590916458485E-9d}, new double[]{0.05417001247406006d, -4.343048751383674E-10d}, new double[]{0.055094651877880096d, 1.92909364037955E-9d}, new double[]{0.056018441915512085d, -5.139745677199588E-10d}, new double[]{0.05694137513637543d, 1.2637629975129189E-9d}, new double[]{0.05786345899105072d, 1.3840561112481119E-9d}, new double[]{0.058784693479537964d, 1.414889689612056E-9d}, new double[]{0.05970507860183716d, 2.9199191907666474E-9d}, new double[]{0.0606246218085289d, 7.90594243412116E-12d}, new double[]{0.06154331564903259d, 1.6844747839686189E-9d}, new double[]{0.06246116757392883d, 2.0498074572151747E-9d}, new double[]{0.06337818503379822d, -4.800180493433863E-9d}, new double[]{0.06429435312747955d, -2.4220822960064277E-9d}, new double[]{0.06520968675613403d, -4.179048566709334E-9d}, new double[]{0.06612417101860046d, 6.363872957010456E-9d}, new double[]{0.06703783571720123d, 9.339468680056365E-10d}, new double[]{0.06795066595077515d, -4.04226739708981E-9d}, new double[]{0.0688626617193222d, -7.043545052852817E-9d}, new double[]{0.06977382302284241d, -6.552819560439773E-9d}, new double[]{0.07068414986133575d, -1.0571674860370546E-9d}, new double[]{0.07159365713596344d, -3.948954622015801E-9d}, new double[]{0.07250232994556427d, 1.1776625988228244E-9d}, new double[]{0.07341018319129944d, 9.221072639606492E-10d}, new double[]{0.07431721687316895d, -3.219119568928366E-9d}, new double[]{0.0752234160900116d, 5.147575929018918E-9d}, new double[]{0.07612881064414978d, -2.291749683541979E-9d}, new double[]{0.07703337073326111d, 5.749565906124772E-9d}, new double[]{0.07793712615966797d, 9.495158151301779E-10d}, new double[]{0.07884006202220917d, -3.144331429489291E-10d}, new double[]{0.0797421783208847d, 3.430029236134205E-9d}, new double[]{0.08064348995685577d, -1.2499290483167703E-9d}, new double[]{0.08154398202896118d, 2.011215719133196E-9d}, new double[]{0.08244366943836212d, -2.2728753031387152E-10d}, new double[]{0.0833425521850586d, -6.508966857277253E-9d}, new double[]{0.0842406153678894d, -4.801131671405377E-10d}, new double[]{0.08513787388801575d, 4.406750291994231E-9d}, new double[]{0.08603434264659882d, -5.304795662536171E-9d}, new double[]{0.08692999184131622d, 1.6284313912612293E-9d}, new double[]{0.08782485127449036d, -3.158898981674071E-9d}, new double[]{0.08871890604496002d, -3.3324878834139977E-9d}, new double[]{0.08961215615272522d, 2.536961912893389E-9d}, new double[]{0.09050461649894714d, 9.737596728980696E-10d}, new double[]{0.0913962870836258d, -6.600437262505396E-9d}, new double[]{0.09228715300559998d, -3.866609889222889E-9d}, new double[]{0.09317722916603088d, -4.311847594020281E-9d}, new double[]{0.09406651556491852d, -6.525851105645959E-9d}, new double[]{0.09495499730110168d, 5.799080912675435E-9d}, new double[]{0.09584270417690277d, 4.2634204358490415E-9d}, new double[]{0.09672962129116058d, 5.167390528799477E-9d}, new double[]{0.09761576354503632d, -4.994827392841906E-9d}, new double[]{0.09850110113620758d, 4.970725577861395E-9d}, new double[]{0.09938566386699677d, 6.6496705953229645E-9d}, new double[]{0.10026945173740387d, 1.4262712796792241E-9d}, new double[]{0.1011524498462677d, 5.5822855204629114E-9d}, new double[]{0.10203467309474945d, 5.593494835247651E-9d}, new double[]{0.10291612148284912d, 2.8332008343480686E-9d}, new double[]{0.10379679501056671d, -1.3289231465997192E-9d}, new double[]{0.10467669367790222d, -5.526819276639527E-9d}, new double[]{0.10555580258369446d, 6.503128678219282E-9d}, new double[]{0.10643415153026581d, 6.317463237641817E-9d}, new double[]{0.10731174051761627d, -4.728528221305482E-9d}, new double[]{0.10818853974342346d, 4.519199083083901E-9d}, new double[]{0.10906457901000977d, 5.606492666349878E-9d}, new double[]{0.10993985831737518d, -1.220176214398581E-10d}, new double[]{0.11081436276435852d, 3.5759315936869937E-9d}, new double[]{0.11168810725212097d, 3.1367659571899855E-9d}, new double[]{0.11256109178066254d, -1.0543075713098835E-10d}, new double[]{0.11343331634998322d, -4.820065619207094E-9d}, new double[]{0.11430476605892181d, 5.221136819669415E-9d}, new double[]{0.11517547070980072d, 1.5395018670011342E-9d}, new double[]{0.11604541540145874d, 3.5638391501880846E-10d}, new double[]{0.11691460013389587d, 2.9885336757136527E-9d}, new double[]{0.11778303980827332d, -4.151889860890893E-9d}, new double[]{0.11865071952342987d, -4.853823938804204E-9d}, new double[]{0.11951763927936554d, 2.189226237170704E-9d}, new double[]{0.12038381397724152d, 3.3791993048776982E-9d}, new double[]{0.1212492436170578d, 1.5811884868243975E-11d}, new double[]{0.12211392819881439d, -6.6045909118908625E-9d}, new double[]{0.1229778528213501d, -2.8786263916116364E-10d}, new double[]{0.12384103238582611d, 5.354472503748251E-9d}, new double[]{0.12470348179340363d, -3.2924463896248744E-9d}, new double[]{0.12556517124176025d, 4.856678149580005E-9d}, new double[]{0.12642613053321838d, 1.2791850600366742E-9d}, new double[]{0.12728634476661682d, 2.1525945093362843E-9d}, new double[]{0.12814581394195557d, 8.749974471767862E-9d}, new double[]{0.129004567861557d, -7.461209161105275E-9d}, new double[]{0.12986254692077637d, 1.4390208226263824E-8d}, new double[]{0.1307198405265808d, -1.3839477920475328E-8d}, new double[]{0.13157635927200317d, -1.483283901239408E-9d}, new double[]{0.13243216276168823d, -6.889072914229094E-9d}, new double[]{0.1332872211933136d, 9.990351100568362E-10d}, new double[]{0.13414156436920166d, -6.370937412495338E-9d}, new double[]{0.13499516248703003d, 2.05047480130511E-9d}, new double[]{0.1358480453491211d, -2.29509872547079E-9d}, new double[]{0.13670018315315247d, 1.16354361977249E-8d}, new double[]{0.13755163550376892d, -1.452496267904829E-8d}, new double[]{0.1384023129940033d, 9.865115839786888E-9d}, new double[]{0.13925230503082275d, -3.369999130712228E-9d}, new double[]{0.14010155200958252d, 6.602496401651853E-9d}, new double[]{0.14095008373260498d, 1.1205312852298845E-8d}, new double[]{0.14179790019989014d, 1.1660367213160203E-8d}, new double[]{0.142645001411438d, 9.186471222585239E-9d}, new double[]{0.14349138736724854d, 4.999341878263704E-9d}, new double[]{0.14433705806732178d, 3.11611905696257E-10d}, new double[]{0.14518201351165771d, -3.6671598175618173E-9d}, new double[]{0.14602625370025635d, -5.730477881659618E-9d}, new double[]{0.14686977863311768d, -4.674900007989718E-9d}, new double[]{0.1477125883102417d, 6.999732437141968E-10d}, new double[]{0.14855468273162842d, 1.159150872494107E-8d}, new double[]{0.14939609169960022d, -6.082714828488485E-10d}, new double[]{0.15023678541183472d, -4.905712741596318E-9d}, new double[]{0.1510767638683319d, -1.124848988733307E-10d}, new double[]{0.15191605687141418d, -1.484557220949851E-8d}, new double[]{0.15275460481643677d, 1.1682026251371384E-8d}, new double[]{0.15359249711036682d, -8.757272519238786E-9d}, new double[]{0.15442964434623718d, 1.4419920764774415E-8d}, new double[]{0.15526613593101501d, -7.019891063126053E-9d}, new double[]{0.15610191226005554d, -1.230153548825964E-8d}, new double[]{0.15693697333335876d, -2.574172005933276E-10d}, new double[]{0.15777134895324707d, 4.748140799544371E-10d}, new double[]{0.15860503911972046d, -8.943081874891003E-9d}, new double[]{0.15943801403045654d, 2.4500739038517657E-9d}, new double[]{0.1602703034877777d, 6.007922084557054E-9d}, new double[]{0.16110190749168396d, 2.8835418231126645E-9d}, new double[]{0.1619328260421753d, -5.772862039728412E-9d}, new double[]{0.16276302933692932d, 1.0988372954605789E-8d}, new double[]{0.16359257698059082d, -5.292913162607026E-9d}, new double[]{0.16442140936851501d, 6.12956339275823E-9d}, new double[]{0.16524958610534668d, -1.3210039516811888E-8d}, new double[]{0.16607704758644104d, -2.5711014608334873E-9d}, new double[]{0.16690382361412048d, 9.37721319457112E-9d}, new double[]{0.1677299439907074d, -6.0370682395944045E-9d}, new double[]{0.168555349111557d, 1.1918249660105651E-8d}, new double[]{0.1693800985813141d, 4.763282949656017E-9d}, new double[]{0.17020416259765625d, 3.4223342273948817E-9d}, new double[]{0.1710275411605835d, 9.014612241310916E-9d}, new double[]{0.1718502640724182d, -7.145758990550526E-9d}, new double[]{0.172672301530838d, -1.4142763934081504E-8d}, new double[]{0.1734936535358429d, -1.0865453656579032E-8d}, new double[]{0.17431432008743286d, 3.794385569450774E-9d}, new double[]{0.1751343309879303d, 1.1399188501627291E-9d}, new double[]{0.17595365643501282d, 1.2076238768270153E-8d}, new double[]{0.1767723262310028d, 7.901084730502162E-9d}, new double[]{0.17759034037590027d, -1.0288181007465474E-8d}, new double[]{0.1784076690673828d, -1.15945645153806E-8d}, new double[]{0.17922431230545044d, 5.073923825786778E-9d}, new double[]{0.18004029989242554d, 1.1004278077575267E-8d}, new double[]{0.1808556318283081d, 7.2831502374676964E-9d}, new double[]{0.18167030811309814d, -5.0054634662706464E-9d}, new double[]{0.18248429894447327d, 5.022108460298934E-9d}, new double[]{0.18329763412475586d, 8.642254225732676E-9d}, new double[]{0.18411031365394592d, 6.931054493326395E-9d}, new double[]{0.18492233753204346d, 9.619685356326533E-10d}, new double[]{0.18573370575904846d, -8.194157257980706E-9d}, new double[]{0.18654438853263855d, 1.0333241479437797E-8d}, new double[]{0.1873544454574585d, -1.9948340196027965E-9d}, new double[]{0.1881638467311859d, -1.4313002926259948E-8d}, new double[]{0.1889725625514984d, 4.241536392174967E-9d}, new double[]{0.18978065252304077d, -4.877952454011428E-9d}, new double[]{0.1905880868434906d, -1.0813801247641613E-8d}, new double[]{0.1913948655128479d, -1.2513218445781325E-8d}, new double[]{0.19220098853111267d, -8.925958555729115E-9d}, new double[]{0.1930064558982849d, 9.956860681280245E-10d}, new double[]{0.193811297416687d, -1.1505428993246996E-8d}, new double[]{0.1946154534816742d, 1.4217997464522202E-8d}, new double[]{0.19541901350021362d, -1.0200858727747717E-8d}, new double[]{0.19622188806533813d, 5.682607223902455E-9d}, new double[]{0.1970241367816925d, 3.2988908516009827E-9d}, new double[]{0.19782572984695435d, 1.3482965534659446E-8d}, new double[]{0.19862669706344604d, 7.462678536479685E-9d}, new double[]{0.1994270384311676d, -1.3734273888891115E-8d}, new double[]{0.20022669434547424d, 1.0521983802642893E-8d}, new double[]{0.20102575421333313d, -8.152742388541905E-9d}, new double[]{0.2018241584300995d, -9.133484280193855E-9d}, new double[]{0.20262190699577332d, 8.59763959528144E-9d}, new double[]{0.2034190595149994d, -1.3548568223001414E-8d}, new double[]{0.20421552658081055d, 1.4847880344628818E-8d}, new double[]{0.20501139760017395d, 5.390620378060543E-9d}, new double[]{0.2058066427707672d, -1.1109834472051523E-8d}, new double[]{0.20660123229026794d, -3.845373872038116E-9d}, new double[]{0.20739519596099854d, -1.6149279479975042E-9d}, new double[]{0.20818853378295898d, -3.4174925203771133E-9d}, new double[]{0.2089812457561493d, -8.254443919468538E-9d}, new double[]{0.20977330207824707d, 1.4672790944499144E-8d}, new double[]{0.2105647623538971d, 6.753452542942992E-9d}, new double[]{0.21135559678077698d, -1.218609462241927E-9d}, new double[]{0.21214580535888672d, -8.254218316367887E-9d}, new double[]{0.21293538808822632d, -1.3366540360587255E-8d}, new double[]{0.2137243151664734d, 1.4231244750190031E-8d}, new double[]{0.2145126760005951d, -1.3885660525939072E-8d}, new double[]{0.21530038118362427d, -7.3304404046850136E-9d}, new double[]{0.2160874605178833d, 5.072117654842356E-9d}, new double[]{0.21687394380569458d, -5.505080220459036E-9d}, new double[]{0.21765980124473572d, -8.286782292266659E-9d}, new double[]{0.2184450328350067d, -2.302351152358085E-9d}, new double[]{0.21922963857650757d, 1.3416565858314603E-8d}, new double[]{0.22001364827156067d, 1.0033721426962048E-8d}, new double[]{0.22079706192016602d, -1.1487079818684332E-8d}, new double[]{0.22157981991767883d, 9.420348186357043E-9d}, new double[]{0.2223619818687439d, 1.4110645699377834E-8d}, new double[]{0.2231435477733612d, 3.5408485497116107E-9d}, new double[]{0.22392448782920837d, 8.468072777056227E-9d}, new double[]{0.2247048318386078d, 4.255446699237779E-11d}, new double[]{0.22548454999923706d, 9.016946273084244E-9d}, new double[]{0.22626367211341858d, 6.537034810260226E-9d}, new double[]{0.22704219818115234d, -6.451285264969768E-9d}, new double[]{0.22782009840011597d, 7.979956357126066E-10d}, new double[]{0.22859740257263184d, -5.759582672039005E-10d}, new double[]{0.22937411069869995d, -9.633854121180397E-9d}, new double[]{0.23015019297599792d, 4.363736368635843E-9d}, new double[]{0.23092567920684814d, 1.2549416560182509E-8d}, new double[]{0.231700599193573d, -1.3946383592553814E-8d}, new double[]{0.2324748933315277d, -1.458843364504023E-8d}, new double[]{0.23324856162071228d, 1.1551692104697154E-8d}, new double[]{0.23402166366577148d, 5.795621295524984E-9d}, new double[]{0.23479416966438293d, -1.1301979046684263E-9d}, new double[]{0.23556607961654663d, -8.303779721781787E-9d}, new double[]{0.23633739352226257d, -1.4805271785394075E-8d}, new double[]{0.23710808157920837d, 1.0085373835899469E-8d}, new double[]{0.2378782033920288d, 7.679117635349454E-9d}, new double[]{0.2386477291584015d, 8.69177352065934E-9d}, new double[]{0.23941665887832642d, 1.4034725764547136E-8d}, new double[]{0.24018502235412598d, -5.185064518887831E-9d}, new double[]{0.2409527599811554d, 1.1544236628121676E-8d}, new double[]{0.24171993136405945d, 5.523085719902123E-9d}, new double[]{0.24248650670051575d, 7.456824943331887E-9d}, new double[]{0.24325251579284668d, -1.1555923403029638E-8d}, new double[]{0.24401789903640747d, 8.988361382732908E-9d}, new double[]{0.2447827160358429d, 1.0381848020926893E-8d}, new double[]{0.24554696679115295d, -6.480706118857055E-9d}, new double[]{0.24631062150001526d, -1.0904271124793968E-8d}, new double[]{0.2470736801624298d, -1.998183061531611E-9d}, new double[]{0.247836172580719d, -8.676137737360023E-9d}, new double[]{0.24859806895256042d, -2.4921733203932487E-10d}, new double[]{0.2493593990802765d, -5.635173762130303E-9d}, new double[]{0.2501201629638672d, -2.3951455355985637E-8d}, new double[]{0.25088030099868774d, 5.287121672447825E-9d}, new double[]{0.2516399025917053d, -6.447877375049486E-9d}, new double[]{0.25239890813827515d, 1.32472428796441E-9d}, new double[]{0.2531573176383972d, 2.9479464287605006E-8d}, new double[]{0.2539151906967163d, 1.9284247135543574E-8d}, new double[]{0.2546725273132324d, -2.8390360197221716E-8d}, new double[]{0.255429208278656d, 6.533522495226226E-9d}, new double[]{0.2561853528022766d, 5.713225978895991E-9d}, new double[]{0.25694090127944946d, 2.9618050962556135E-8d}, new double[]{0.25769591331481934d, 1.950605015323617E-8d}, new double[]{0.25845038890838623d, -2.3762031507525576E-8d}, new double[]{0.2592042088508606d, 1.98818938195077E-8d}, new double[]{0.25995755195617676d, -2.751925069084042E-8d}, new double[]{0.2607102394104004d, 1.3703391844683932E-8d}, new double[]{0.26146239042282104d, 2.5193525310038174E-8d}, new double[]{0.2622140049934387d, 7.802219817310385E-9d}, new double[]{0.26296502351760864d, 2.1983272709242607E-8d}, new double[]{0.2637155055999756d, 8.979279989292184E-9d}, new double[]{0.2644653916358948d, 2.9240221157844312E-8d}, new double[]{0.265214741230011d, 2.4004885823813374E-8d}, new double[]{0.2659635543823242d, -5.885186277410878E-9d}, new double[]{0.2667117714881897d, 1.4300386517357162E-11d}, new double[]{0.2674594521522522d, -1.7063531531989365E-8d}, new double[]{0.26820653676986694d, 3.3218524692903896E-9d}, new double[]{0.2689530849456787d, 2.3998252479954764E-9d}, new double[]{0.2696990966796875d, -1.8997462070389404E-8d}, new double[]{0.27044451236724854d, -4.350745270980051E-10d}, new double[]{0.2711893916130066d, -6.892221115467135E-10d}, new double[]{0.27193373441696167d, -1.89333199110902E-8d}, new double[]{0.272677481174469d, 5.262017392507765E-9d}, new double[]{0.27342069149017334d, 1.3115046679980076E-8d}, new double[]{0.2741633653640747d, 5.4468361834451975E-9d}, new double[]{0.2749055027961731d, -1.692337384653611E-8d}, new double[]{0.27564704418182373d, 6.426479056697412E-9d}, new double[]{0.2763880491256714d, 1.670735065191342E-8d}, new double[]{0.27712851762771606d, 1.4733029698334834E-8d}, new double[]{0.27786844968795776d, 1.315498542514467E-9d}, new double[]{0.2786078453063965d, -2.2735061539223372E-8d}, new double[]{0.27934664487838745d, 2.994379757313727E-9d}, new double[]{0.28008490800857544d, 1.970577274107218E-8d}, new double[]{0.28082263469696045d, 2.820392733542077E-8d}, new double[]{0.2815598249435425d, 2.929187356678173E-8d}, new double[]{0.28229647874832153d, 2.377086680926386E-8d}, new double[]{0.2830325961112976d, 1.2440393009992529E-8d}, new double[]{0.2837681770324707d, -3.901826104778096E-9d}, new double[]{0.2845032215118408d, -2.4459827842685974E-8d}, new double[]{0.2852376699447632d, 1.1165241398059789E-8d}, new double[]{0.28597164154052734d, -1.54434478239181E-8d}, new double[]{0.28670501708984375d, 1.5714110564653245E-8d}, new double[]{0.28743791580200195d, -1.3782394940142479E-8d}, new double[]{0.2881702184677124d, 1.6063569876284005E-8d}, new double[]{0.28890204429626465d, -1.317176818216125E-8d}, new double[]{0.28963327407836914d, 1.8504673536253893E-8d}, new double[]{0.29036402702331543d, -7.334319635123628E-9d}, new double[]{0.29109418392181396d, 2.9300903540317107E-8d}, new double[]{0.2918238639831543d, 9.979706999541057E-9d}, new double[]{0.29255300760269165d, -4.916314210412424E-9d}, new double[]{0.293281614780426d, -1.4611908070155308E-8d}, new double[]{0.2940096855163574d, -1.833351586679361E-8d}, new double[]{0.29473721981048584d, -1.530926726615185E-8d}, new double[]{0.2954642176628113d, -4.7689754029101934E-9d}, new double[]{0.29619067907333374d, 1.4055868011423819E-8d}, new double[]{0.296916663646698d, -1.7672547212604003E-8d}, new double[]{0.2976420521736145d, 2.0020234215759705E-8d}, new double[]{0.2983669638633728d, 8.688424478730524E-9d}, new double[]{0.2990913391113281d, 8.69851089918337E-9d}, new double[]{0.29981517791748047d, 2.0810681643102672E-8d}, new double[]{0.3005385398864746d, -1.3821169493779352E-8d}, new double[]{0.301261305809021d, 2.4769140784919128E-8d}, new double[]{0.3019835948944092d, 1.8127576600610336E-8d}, new double[]{0.3027053475379944d, 2.6612401062437074E-8d}, new double[]{0.3034266233444214d, -8.629042891789934E-9d}, new double[]{0.3041473627090454d, -2.724174869314043E-8d}, new double[]{0.30486756563186646d, -2.8476975783775358E-8d}, new double[]{0.3055872321128845d, -1.1587600174449919E-8d}, new double[]{0.3063063621520996d, 2.417189020581056E-8d}, new double[]{0.3070250153541565d, 1.99407553679345E-8d}, new double[]{0.3077431917190552d, -2.35387025694381E-8d}, new double[]{0.3084607720375061d, 1.3683509995845583E-8d}, new double[]{0.30917787551879883d, 1.3137214081023085E-8d}, new double[]{0.30989450216293335d, -2.444006866174775E-8d}, new double[]{0.3106105327606201d, 2.0896888605749563E-8d}, new double[]{0.31132614612579346d, -2.893149098508887E-8d}, new double[]{0.31204116344451904d, 5.621509038251498E-9d}, new double[]{0.3127557039260864d, 6.0778104626050015E-9d}, new double[]{0.3134697675704956d, -2.6832941696716294E-8d}, new double[]{0.31418323516845703d, 2.6826625274495256E-8d}, new double[]{0.31489628553390503d, -1.1030897183911054E-8d}, new double[]{0.31560879945755005d, -2.047124671392676E-8d}, new double[]{0.3163207769393921d, -7.709990443086711E-10d}, new double[]{0.3170322775840759d, -1.0812918808112342E-8d}, new double[]{0.3177432417869568d, 9.727979174888975E-9d}, new double[]{0.31845372915267944d, 1.9658551724508715E-9d}, new double[]{0.3191636800765991d, 2.6222628001695826E-8d}, new double[]{0.3198731541633606d, 2.3609400272358744E-8d}, new double[]{0.32058215141296387d, -5.159602957634814E-9d}, new double[]{0.32129061222076416d, 2.329701319016099E-10d}, new double[]{0.32199859619140625d, -1.910633190395738E-8d}, new double[]{0.32270604372024536d, -2.863180390093667E-9d}, new double[]{0.32341301441192627d, -9.934041364456825E-9d}, new double[]{0.3241194486618042d, 1.999240777687192E-8d}, new double[]{0.3248254060745239d, 2.801670341647724E-8d}, new double[]{0.32553088665008545d, 1.4842534265191358E-8d}, new double[]{0.32623589038848877d, -1.882789920477354E-8d}, new double[]{0.3269403576850891d, -1.268923579073577E-8d}, new double[]{0.32764434814453125d, -2.564688370677835E-8d}, new double[]{0.3283478021621704d, 2.6015626820520968E-9d}, new double[]{0.32905077934265137d, 1.3147747907784344E-8d}, new double[]{0.3297532796859741d, 6.686493860720675E-9d}, new double[]{0.33045530319213867d, -1.608884086544153E-8d}, new double[]{0.33115679025650024d, 5.118287907840204E-9d}, new double[]{0.3318578004837036d, 1.139367970944884E-8d}, new double[]{0.3325583338737488d, 3.426327822115399E-9d}, new double[]{0.33325839042663574d, -1.809622142990733E-8d}, new double[]{0.3339579105377197d, 7.116780143398601E-9d}, new double[]{0.3346569538116455d, 2.0145352306345386E-8d}, new double[]{0.3353555202484131d, 2.167272474431968E-8d}, new double[]{0.33605360984802246d, 1.2380696294966822E-8d}, new double[]{0.33675122261047363d, -7.050361059209181E-9d}, new double[]{0.3374482989311218d, 2.366314656322868E-8d}, new double[]{0.3381449580192566d, -1.4010540194086646E-8d}, new double[]{0.3388410806655884d, -1.860165465666482E-10d}, new double[]{0.33953672647476196d, 6.206776940880773E-9d}, new double[]{0.34023189544677734d, 5.841137379010982E-9d}, new double[]{0.3409265875816345d, -6.11041311179286E-10d}, new double[]{0.3416208028793335d, -1.2479264502054702E-8d}, new double[]{0.34231454133987427d, -2.909443297645926E-8d}, new double[]{0.34300774335861206d, 9.815805717097634E-9d}, new double[]{0.3437005281448364d, -1.4291517981101049E-8d}, new double[]{0.3443927764892578d, 1.8457821628427503E-8d}, new double[]{0.34508460760116577d, -1.0481908869377813E-8d}, new double[]{0.34577590227127075d, 1.876076001514746E-8d}, new double[]{0.3464667797088623d, -1.2362653723769037E-8d}, new double[]{0.3471571207046509d, 1.6016578405624026E-8d}, new double[]{0.347847044467926d, -1.4652759033760925E-8d}, new double[]{0.3485364317893982d, 1.549533655901835E-8d}, new double[]{0.34922540187835693d, -1.2093068629412478E-8d}, new double[]{0.3499138355255127d, 2.244531711424792E-8d}, new double[]{0.35060185194015503d, 5.538565518604807E-10d}, new double[]{0.35128939151763916d, -1.7511499366215853E-8d}, new double[]{0.3519763946533203d, 2.850385787215544E-8d}, new double[]{0.35266298055648804d, 2.003926370146842E-8d}, new double[]{0.35334908962249756d, 1.734665280502264E-8d}, new double[]{0.3540347218513489d, 2.1071983674869414E-8d}, new double[]{0.35471993684768677d, -2.774475773922311E-8d}, new double[]{0.3554046154022217d, -9.250975291734664E-9d}, new double[]{0.3560888171195984d, 1.7590672330295415E-8d}, new double[]{0.35677260160446167d, -6.1837904549178745E-9d}, new double[]{0.35745590925216675d, -2.0330362973820856E-8d}, new double[]{0.3581387400627136d, -2.42109990366786E-8d}, new double[]{0.3588210940361023d, -1.7188958587407816E-8d}, new double[]{0.35950297117233276d, 1.3711958590112228E-9d}, new double[]{0.3601844310760498d, -2.7501042008405925E-8d}, new double[]{0.36086535453796387d, 1.6036460343275798E-8d}, new double[]{0.3615458607673645d, 1.3405964389498495E-8d}, new double[]{0.36222589015960693d, 2.484237749027735E-8d}, new double[]{0.36290550231933594d, -8.629967484362177E-9d}, new double[]{0.36358463764190674d, -2.6778729562324134E-8d}, new double[]{0.36426329612731934d, -2.8977490516960565E-8d}, new double[]{0.36494147777557373d, -1.4601106624823502E-8d}, new double[]{0.3656191825866699d, 1.69742947894444E-8d}, new double[]{0.3662964701652527d, 6.7666740211281175E-9d}, new double[]{0.36697328090667725d, 1.500201674336832E-8d}, new double[]{0.3676496744155884d, -1.730424167425052E-8d}, new double[]{0.36832553148269653d, 2.9676011119845104E-8d}, new double[]{0.36900103092193604d, -2.2253590346826743E-8d}, new double[]{0.36967599391937256d, 6.3372065441089185E-9d}, new double[]{0.37035053968429565d, -3.145816653215968E-9d}, new double[]{0.37102460861206055d, 9.515812117036965E-9d}, new double[]{0.371698260307312d, -1.4669965113042639E-8d}, new double[]{0.3723714351654053d, -1.548715389333397E-8d}, new double[]{0.37304413318634033d, 7.674361647125109E-9d}, new double[]{0.37371641397476196d, -4.181177882069608E-9d}, new double[]{0.3743882179260254d, 9.158530500130718E-9d}, new double[]{0.3750596046447754d, -1.13047236597869E-8d}, new double[]{0.3757305145263672d, -5.36108186384227E-9d}, new double[]{0.3764009475708008d, 2.7593452284747873E-8d}, new double[]{0.37707096338272095d, 2.8557016344085205E-8d}, new double[]{0.3777405619621277d, -1.868818164036E-9d}, new double[]{0.3784096837043762d, -3.479042513414447E-9d}, new double[]{0.37907832860946655d, 2.432550290565648E-8d}, new double[]{0.37974655628204346d, 2.2538131805476768E-8d}, new double[]{0.38041436672210693d, -8.244395239939089E-9d}, new double[]{0.3810817003250122d, -7.821867597227376E-9d}, new double[]{0.3817485570907593d, 2.4400089062515914E-8d}, new double[]{0.3824149966239929d, 2.9410015940087773E-8d}, new double[]{0.38308101892471313d, 7.799913824734797E-9d}, new double[]{0.38374656438827515d, 1.976524624939355E-8d}, new double[]{0.38441169261932373d, 6.291008309266035E-9d}, new double[]{0.3850763440132141d, 2.757030889767851E-8d}, new double[]{0.38574057817459106d, 2.4585794728405612E-8d}, new double[]{0.3864043951034546d, -2.0764122246389383E-9d}, new double[]{0.3870677351951599d, 7.77328837578952E-9d}, new double[]{0.3877306580543518d, -4.8859560029989374E-9d}, new double[]{0.3883931040763855d, 2.0133131420595028E-8d}, new double[]{0.38905513286590576d, 2.380738071335498E-8d}, new double[]{0.3897167444229126d, 6.7171126157142075E-9d}, new double[]{0.39037787914276123d, 2.9046141593926277E-8d}, new double[]{0.3910386562347412d, -2.7836800219410262E-8d}, new double[]{0.3916988968849182d, 1.545909820981726E-8d}, new double[]{0.39235877990722656d, -1.930436269002062E-8d}, new double[]{0.3930181860923767d, -1.2343297554921835E-8d}, new double[]{0.3936771750450134d, -2.268889128622553E-8d}, new double[]{0.39433568716049194d, 9.835827818608177E-9d}, new double[]{0.39499378204345703d, 2.6197411946856397E-8d}, new double[]{0.3956514596939087d, 2.6965931069318893E-8d}, new double[]{0.3963087201118469d, 1.2710331127772166E-8d}, new double[]{0.39696556329727173d, -1.6001563011916016E-8d}, new double[]{0.39762192964553833d, 1.0016001590267064E-9d}, new double[]{0.3982778787612915d, 4.680767399874334E-9d}, new double[]{0.39893341064453125d, -4.399582029272418E-9d}, new double[]{0.39958852529525757d, -2.5676078228301587E-8d}, new double[]{0.4002431631088257d, 1.0181870233355787E-9d}, new double[]{0.40089738368988037d, 1.6639728835984655E-8d}, new double[]{0.40155118703842163d, 2.174860642202632E-8d}, new double[]{0.40220457315444946d, 1.6903781197123503E-8d}, new double[]{0.40285754203796387d, 2.663119647467697E-9d}, new double[]{0.40351009368896484d, -2.0416603812329616E-8d}, new double[]{0.4041621685028076d, 7.82494078472695E-9d}, new double[]{0.40481382608413696d, 2.833770747113627E-8d}, new double[]{0.40546512603759766d, -1.7929433274271985E-8d}, new double[]{0.40611594915390015d, -1.1214757379328965E-8d}, new double[]{0.4067663550376892d, -1.0571553019207106E-8d}, new double[]{0.40741634368896484d, -1.5449538712332313E-8d}, new double[]{0.40806591510772705d, -2.529950530235105E-8d}, new double[]{0.40871500968933105d, 2.0031331601617008E-8d}, new double[]{0.4093637466430664d, 1.880755298741952E-9d}, new double[]{0.41001206636428833d, -1.9600580584843318E-8d}, new double[]{0.41065990924835205d, 1.573691633515306E-8d}, new double[]{0.4113073945045471d, -1.0772154376548336E-8d}, new double[]{0.411954402923584d, 2.0624330192486066E-8d}, new double[]{0.4126010537147522d, -8.741139170029572E-9d}, new double[]{0.4132472276687622d, 2.0881457123894216E-8d}, new double[]{0.41389304399490356d, -9.177488027521808E-9d}, new double[]{0.4145383834838867d, 2.0829952491625585E-8d}, new double[]{0.4151833653450012d, -7.767915492597301E-9d}, new double[]{0.4158278703689575d, 2.4774753446082082E-8d}, new double[]{0.41647201776504517d, -2.1581119071750435E-10d}, new double[]{0.4171157479286194d, -2.260047972865202E-8d}, new double[]{0.4177590012550354d, 1.775884601423381E-8d}, new double[]{0.41840189695358276d, 2.185301053838889E-9d}, new double[]{0.4190443754196167d, -9.185071463667081E-9d}, new double[]{0.4196864366531372d, -1.5821896727910552E-8d}, new double[]{0.4203280806541443d, -1.719582086188318E-8d}, new double[]{0.42096930742263794d, -1.2778508303324259E-8d}, new double[]{0.42161011695861816d, -2.042639194493364E-9d}, new double[]{0.42225050926208496d, 1.5538093219698803E-8d}, new double[]{0.4228905439376831d, -1.9115659590156936E-8d}, new double[]{0.42353010177612305d, 1.3729680248843432E-8d}, new double[]{0.42416930198669434d, -4.611893838830296E-9d}, new double[]{0.4248080849647522d, -1.4013456880651706E-8d}, new double[]{0.42544645071029663d, -1.3953728897042917E-8d}, new double[]{0.42608439922332764d, -3.912427573594197E-9d}, new double[]{0.4267219305038452d, 1.6629734283189315E-8d}, new double[]{0.42735910415649414d, -1.1413593493354881E-8d}, new double[]{0.42799586057662964d, -2.792046157580119E-8d}, new double[]{0.42863214015960693d, 2.723009182661306E-8d}, new double[]{0.42926812171936035d, -2.4260535621557444E-8d}, new double[]{0.42990362644195557d, -3.064060124024764E-9d}, new double[]{0.43053877353668213d, -2.787640178598121E-8d}, new double[]{0.4311734437942505d, 2.102412085257792E-8d}, new double[]{0.4318077564239502d, 2.4939635093999683E-8d}, new double[]{0.43244171142578125d, -1.5619414792273914E-8d}, new double[]{0.4330751895904541d, 1.9065734894871523E-8d}, new double[]{0.4337083101272583d, 1.0294301092654604E-8d}, new double[]{0.4343410134315491d, 1.8178469851136E-8d}, new double[]{0.4349733591079712d, -1.6379825102473853E-8d}, new double[]{0.4356052279472351d, 2.6334323946685834E-8d}, new double[]{0.43623673915863037d, 2.761628769925529E-8d}, new double[]{0.436867892742157d, -1.2030229087793677E-8d}, new double[]{0.4374985694885254d, 2.7106814809424793E-8d}, new double[]{0.43812888860702515d, 2.631993083235205E-8d}, new double[]{0.43875885009765625d, -1.3890028312254422E-8d}, new double[]{0.43938833475112915d, 2.6186133735555794E-8d}, new double[]{0.4400174617767334d, 2.783809071694788E-8d}, new double[]{0.440646231174469d, -8.436135220472006E-9d}, new double[]{0.44127458333969116d, -2.2534815932619883E-8d}, new double[]{0.4419025182723999d, -1.3961804471714283E-8d}, new double[]{0.4425300359725952d, 1.7778112039716255E-8d}, new double[]{0.4431571960449219d, 1.3574569976673652E-8d}, new double[]{0.4437839984893799d, -2.607907890164073E-8d}, new double[]{0.4444103240966797d, 1.8518879652136628E-8d}, new double[]{0.44503629207611084d, 2.865065604247164E-8d}, new double[]{0.44566190242767334d, 4.806827797299427E-9d}, new double[]{0.4462870955467224d, 7.0816970994232115E-9d}, new double[]{0.44691193103790283d, -2.3640641240074437E-8d}, new double[]{0.4475363492965698d, -2.7267718387865538E-8d}, new double[]{0.4481603503227234d, -3.3126235292976077E-9d}, new double[]{0.4487839937210083d, -1.0894001590268427E-8d}, new double[]{0.4494072198867798d, 1.0077883359971829E-8d}, new double[]{0.4500300884246826d, 4.825712712114668E-10d}, new double[]{0.450652539730072d, 2.0407987470746858E-8d}, new double[]{0.4512746334075928d, 1.073186581170719E-8d}, new double[]{0.4518963694572449d, -2.8064314757880205E-8d}, new double[]{0.45251762866973877d, 2.3709316816226527E-8d}, new double[]{0.4531385898590088d, -1.2281487504266522E-8d}, new double[]{0.4537591338157654d, -1.634864487421458E-8d}, new double[]{0.45437926054000854d, 1.1985747222409522E-8d}, new double[]{0.45499902963638306d, 1.3594057956219485E-8d}, new double[]{0.4556184411048889d, -1.1047585095328619E-8d}, new double[]{0.45623743534088135d, -1.8592937532754405E-9d}, new double[]{0.4568560719490051d, -1.797135137545755E-8d}, new double[]{0.4574742913246155d, 6.943684261645378E-10d}, new double[]{0.4580921530723572d, -4.994175141684681E-9d}, new double[]{0.45870959758758545d, 2.5039391215625133E-8d}, new double[]{0.45932674407958984d, -2.7943366835352838E-8d}, new double[]{0.45994341373443604d, 1.534146910128904E-8d}, new double[]{0.46055978536605835d, -2.3450920230816267E-8d}, new double[]{0.46117573976516724d, -2.4642997069960124E-8d}, new double[]{0.4617912769317627d, 1.2232622070370946E-8d}, new double[]{0.4624064564704895d, 2.80378133047839E-8d}, new double[]{0.46302127838134766d, 2.3238237048117092E-8d}, new double[]{0.46363574266433716d, -1.7013046451109475E-9d}, new double[]{0.46424978971481323d, 1.3287778803035383E-8d}, new double[]{0.46486347913742065d, 9.06393426961373E-9d}, new double[]{0.4654768109321594d, -1.3910598647592876E-8d}, new double[]{0.46608972549438477d, 4.430214458933614E-9d}, new double[]{0.46670228242874146d, 4.942270562885745E-9d}, new double[]{0.4673144817352295d, -1.1914734393460718E-8d}, new double[]{0.4679262638092041d, 1.3922696570638494E-8d}, new double[]{0.46853768825531006d, 2.3307929211781914E-8d}, new double[]{0.46914875507354736d, 1.669813444584674E-8d}, new double[]{0.469759464263916d, -5.450354376430758E-9d}, new double[]{0.47036975622177124d, 1.6922605350647674E-8d}, new double[]{0.4709796905517578d, 2.4667033200046904E-8d}, new double[]{0.47158926725387573d, 1.8236762070433784E-8d}, new double[]{0.472198486328125d, -1.915204563140137E-9d}, new double[]{0.47280728816986084d, 2.426795414605756E-8d}, new double[]{0.4734157919883728d, -2.19717006713618E-8d}, new double[]{0.47402387857437134d, -2.0974352165535873E-8d}, new double[]{0.47463154792785645d, 2.770970558184228E-8d}, new double[]{0.4752389192581177d, 5.32006955298355E-9d}, new double[]{0.47584593296051025d, -2.809054633964104E-8d}, new double[]{0.4764525294303894d, -1.2470243596102937E-8d}, new double[]{0.4770587682723999d, -6.977226702440138E-9d}, new double[]{0.47766464948654175d, -1.1165866833118273E-8d}, new double[]{0.47827017307281494d, -2.4591344661022708E-8d}, new double[]{0.4788752794265747d, 1.2794996377383974E-8d}, new double[]{0.4794800877571106d, -1.7772927065973874E-8d}, new double[]{0.48008447885513306d, 3.35657712457243E-9d}, new double[]{0.48068851232528687d, 1.7020465042442242E-8d}, new double[]{0.481292188167572d, 2.365953779624783E-8d}, new double[]{0.4818955063819885d, 2.3713798664443718E-8d}, new double[]{0.4824984669685364d, 1.7622455019548098E-8d}, new double[]{0.4831010699272156d, 5.823920246566496E-9d}, new double[]{0.4837033152580261d, -1.1244184344361017E-8d}, new double[]{0.48430514335632324d, 2.645961716432205E-8d}, new double[]{0.4849066734313965d, 1.6207809718247905E-10d}, new double[]{0.4855077862739563d, 2.9507744508973654E-8d}, new double[]{0.48610860109329224d, -4.278201128741098E-9d}, new double[]{0.48670899868011475d, 1.844722015961139E-8d}, new double[]{0.4873090982437134d, -2.1092372471088425E-8d}, new double[]{0.4879087805747986d, -3.2555596107382053E-9d}, new double[]{0.48850810527801514d, 1.2784366845429667E-8d}, new double[]{0.48910707235336304d, 2.7457984659996047E-8d}, new double[]{0.48970574140548706d, -1.8409546441412518E-8d}, new double[]{0.49030399322509766d, -5.179903818099661E-9d}, new double[]{0.4909018874168396d, 7.97053127828682E-9d}, new double[]{0.4914994239807129d, 2.146925464473481E-8d}, new double[]{0.4920966625213623d, -2.3861648589988232E-8d}, new double[]{0.4926934838294983d, -8.386923035320549E-9d}, new double[]{0.4932899475097656d, 8.713990131749256E-9d}, new double[]{0.4938860535621643d, 2.7865534085810115E-8d}, new double[]{0.4944818615913391d, -1.011325138560159E-8d}, new double[]{0.4950772523880005d, 1.4409851026316708E-8d}, new double[]{0.495672345161438d, -1.735227547472004E-8d}, new double[]{0.49626702070236206d, 1.4231078209064581E-8d}, new double[]{0.49686139822006226d, -9.628709342929729E-9d}, new double[]{0.4974554181098938d, -2.8907074856577267E-8d}, new double[]{0.4980490207672119d, 1.6419797090870802E-8d}, new double[]{0.49864232540130615d, 7.561041519403049E-9d}, new double[]{0.49923527240753174d, 4.538983468118194E-9d}, new double[]{0.49982786178588867d, 7.770560657946324E-9d}, new double[]{0.500420093536377d, 1.767197002609876E-8d}, new double[]{0.5010119676589966d, 3.46586694799214E-8d}, new double[]{0.5016034841537476d, 5.914537964556077E-8d}, new double[]{0.5021947622299194d, -2.7663203939320167E-8d}, new double[]{0.5027855634689331d, 1.3064749115929298E-8d}, new double[]{0.5033761262893677d, -5.667682106730711E-8d}, new double[]{0.503966212272644d, 1.9424534974370594E-9d}, new double[]{0.5045560598373413d, -4.908494602153544E-8d}, new double[]{0.5051454305648804d, 2.906989285008994E-8d}, new double[]{0.5057345628738403d, -1.602000800745108E-9d}, new double[]{0.5063233375549316d, -2.148245271118002E-8d}, new double[]{0.5069117546081543d, -3.016329994276181E-8d}, new double[]{0.5074998140335083d, -2.7237099632871992E-8d}, new double[]{0.5080875158309937d, -1.2297127301923986E-8d}, new double[]{0.5086748600006104d, 1.5062624834468093E-8d}, new double[]{0.5092618465423584d, 5.524744954836658E-8d}, new double[]{0.5098485946655273d, -1.054736327333046E-8d}, new double[]{0.5104348659515381d, 5.650063324725722E-8d}, new double[]{0.5110208988189697d, 1.8376017791642605E-8d}, new double[]{0.5116065740585327d, -5.309470636324855E-9d}, new double[]{0.512191891670227d, -1.4154089255217218E-8d}, new double[]{0.5127768516540527d, -7.756800301729815E-9d}, new double[]{0.5133614540100098d, 1.4282730618002001E-8d}, new double[]{0.5139456987380981d, 5.2364136172269755E-8d}, new double[]{0.5145297050476074d, -1.2322940607922115E-8d}, new double[]{0.5151132345199585d, 5.903831350855322E-8d}, new double[]{0.5156965255737305d, 2.8426856726994483E-8d}, new double[]{0.5162794589996338d, 1.544882070711032E-8d}, new double[]{0.5168620347976685d, 2.0500353979930155E-8d}, new double[]{0.5174442529678345d, 4.397691311390564E-8d}, new double[]{0.5180262327194214d, -3.2936025225250634E-8d}, new double[]{0.5186077356338501d, 2.857419553449673E-8d}, new double[]{0.5191890001296997d, -9.51761338269325E-9d}, new double[]{0.5197699069976807d, -2.7609457648450225E-8d}, new double[]{0.520350456237793d, -2.5309316441333305E-8d}, new double[]{0.5209306478500366d, -2.2258513086839407E-9d}, new double[]{0.5215104818344116d, 4.203159541613745E-8d}, new double[]{0.5220900774002075d, -1.1356287358852729E-8d}, new double[]{0.5226693153381348d, -4.279090925831093E-8d}, new double[]{0.5232481956481934d, -5.188364552285819E-8d}, new double[]{0.5238267183303833d, -3.82465458937857E-8d}, new double[]{0.5244048833847046d, -1.4923330530645769E-9d}, new double[]{0.5249826908111572d, 5.8765598932137004E-8d}, new double[]{0.5255602598190308d, 2.3703896609663678E-8d}, new double[]{0.5261374711990356d, 1.2917117341231647E-8d}, new double[]{0.5267143249511719d, 2.6789862192139226E-8d}, new double[]{0.527290940284729d, -5.350322253112414E-8d}, new double[]{0.5278670787811279d, 1.0839714455426386E-8d}, new double[]{0.5284429788589478d, -1.821729591343314E-8d}, new double[]{0.5290185213088989d, -2.1083014672301448E-8d}, new double[]{0.5295937061309814d, 2.623848491704216E-9d}, new double[]{0.5301685333251953d, 5.328392630534142E-8d}, new double[]{0.5307431221008301d, 1.206790586971942E-8d}, new double[]{0.5313173532485962d, -1.4356011804377797E-9d}, new double[]{0.5318912267684937d, 1.3152074173459994E-8d}, new double[]{0.5324647426605225d, 5.6208949382936426E-8d}, new double[]{0.5330380201339722d, 8.90310227565917E-9d}, new double[]{0.5336109399795532d, -9.179458802504127E-9d}, new double[]{0.5341835021972656d, 2.337337845617735E-9d}, new double[]{0.5347557067871094d, 4.3828918300477925E-8d}, new double[]{0.535327672958374d, -3.5392250480081715E-9d}, new double[]{0.53589928150177d, -2.0183663375378704E-8d}, new double[]{0.5364705324172974d, -5.730898606435436E-9d}, new double[]{0.537041425704956d, 4.0191927599879235E-8d}, new double[]{0.5376120805740356d, -1.2522542401353875E-9d}, new double[]{0.5381823778152466d, -1.0482571326594316E-8d}, new double[]{0.5387523174285889d, 1.2871924223480165E-8d}, new double[]{0.539322018623352d, -5.002774317612589E-8d}, new double[]{0.539891242980957d, 3.960668706590162E-8d}, new double[]{0.5404602289199829d, 4.372568630242375E-8d}, new double[]{0.5410289764404297d, -3.730232461206926E-8d}, new double[]{0.5415972471237183d, 3.5309026109857795E-8d}, new double[]{0.5421652793884277d, 2.3508325311148225E-8d}, new double[]{0.5427329540252686d, 4.6871403168921666E-8d}, new double[]{0.5433003902435303d, -1.3445113140270216E-8d}, new double[]{0.5438674688339233d, -3.786663982218041E-8d}, new double[]{0.5444341897964478d, -2.602850370608209E-8d}, new double[]{0.5450005531311035d, 2.2433348713144506E-8d}, new double[]{0.5455666780471802d, -1.1326936872620137E-8d}, new double[]{0.5461324453353882d, -7.737252533211342E-9d}, new double[]{0.5466978549957275d, 3.3564604642699844E-8d}, new double[]{0.5472630262374878d, -6.269066061111782E-9d}, new double[]{0.5478278398513794d, -7.667998948729528E-9d}, new double[]{0.5483922958374023d, 2.9728170818998143E-8d}, new double[]{0.5489565134048462d, -1.2930091396008281E-8d}, new double[]{0.5495203733444214d, -1.607434968107079E-8d}, new double[]{0.5500838756561279d, 2.0653935146671156E-8d}, new double[]{0.5506471395492554d, -2.1596593091833788E-8d}, new double[]{0.5512100458145142d, -2.3259315921149476E-8d}, new double[]{0.5517725944519043d, 1.6022492496522704E-8d}, new double[]{0.5523349046707153d, -2.260433328226171E-8d}, new double[]{0.5528968572616577d, -1.957497997726303E-8d}, new double[]{0.5534584522247314d, 2.5465477111883854E-8d}, new double[]{0.5540198087692261d, -6.33792454933092E-9d}, new double[]{0.554580807685852d, 4.577835263278281E-9d}, new double[]{0.5551414489746094d, 5.856589221771548E-8d}, new double[]{0.5557018518447876d, 3.6769498759522324E-8d}, new double[]{0.5562618970870972d, 5.874989409410614E-8d}, new double[]{0.5568217039108276d, 5.649147309876989E-9d}, new double[]{0.5573811531066895d, -2.9726830960751796E-9d}, new double[]{0.5579402446746826d, 3.323458344853057E-8d}, new double[]{0.5584990978240967d, -4.588749093664028E-9d}, new double[]{0.5590575933456421d, 3.115616594184543E-9d}, new double[]{0.5596157312393188d, 5.6696103838614634E-8d}, new double[]{0.5601736307144165d, 3.7291263280048303E-8d}, new double[]{0.5607312917709351d, -5.4751646725093355E-8d}, new double[]{0.5612884759902954d, 1.9332630743320287E-8d}, new double[]{0.5618454217910767d, 2.147161515775941E-8d}, new double[]{0.5624021291732788d, -4.7989172862560625E-8d}, new double[]{0.5629583597183228d, 4.971378973445109E-8d}, new double[]{0.5635144710540771d, -4.2702997139152675E-8d}, new double[]{0.5640701055526733d, 3.273212962622764E-8d}, new double[]{0.5646255016326904d, 3.79438125545842E-8d}, new double[]{0.5651806592941284d, -2.6725298288329835E-8d}, new double[]{0.5657354593276978d, -4.1723833577410244E-8d}, new double[]{0.5662899017333984d, -6.71028256490915E-9d}, new double[]{0.56684410572052d, -4.055299181908475E-8d}, new double[]{0.567397952079773d, -2.3702295314000405E-8d}, new double[]{0.5679514408111572d, 4.4181618172507453E-8d}, new double[]{0.5685046911239624d, 4.4228706309734985E-8d}, new double[]{0.5690577030181885d, -2.3222346436879016E-8d}, new double[]{0.5696103572845459d, -3.862412756175274E-8d}, new double[]{0.5701626539230347d, -1.6390743801589046E-9d}, new double[]{0.5707147121429443d, -3.1139472791083883E-8d}, new double[]{0.5712664127349854d, -7.579587391156013E-9d}, new double[]{0.5718178749084473d, -4.983281844744412E-8d}, new double[]{0.5723689794540405d, -3.835454246739619E-8d}, new double[]{0.5729197263717651d, 2.7190020372374008E-8d}, new double[]{0.5734702348709106d, 2.7925807446276126E-8d}, new double[]{0.574020504951477d, -3.5813506001861646E-8d}, new double[]{0.5745704174041748d, -4.448550564530588E-8d}, new double[]{0.5751199722290039d, 2.2423840341717488E-9d}, new double[]{0.5756692886352539d, -1.450709904687712E-8d}, new double[]{0.5762182474136353d, 2.4806815282282017E-8d}, new double[]{0.5767669677734375d, 1.3057724436551892E-9d}, new double[]{0.5773153305053711d, 3.4529452510568104E-8d}, new double[]{0.5778634548187256d, 5.598413198183808E-9d}, new double[]{0.5784112215042114d, 3.405124925700107E-8d}, new double[]{0.5789587497711182d, 1.0074354568442952E-9d}, new double[]{0.5795059204101562d, 2.600448597385527E-8d}, new double[]{0.5800528526306152d, -9.83920263200211E-9d}, new double[]{0.5805994272232056d, 1.3012807963586057E-8d}, new double[]{0.5811457633972168d, -2.432215917965441E-8d}, new double[]{0.5816917419433594d, -2.308736892479391E-9d}, new double[]{0.5822374820709229d, -3.983067093146514E-8d}, new double[]{0.5827828645706177d, -1.735366061128156E-8d}, new double[]{0.5833280086517334d, -5.376251584638963E-8d}, new double[]{0.5838727951049805d, -2.952399778965259E-8d}, new double[]{0.5844172239303589d, 5.5685313670430624E-8d}, new double[]{0.5849615335464478d, -3.6230268489088716E-8d}, new double[]{0.5855053663253784d, 5.267948957869391E-8d}, new double[]{0.5860490798950195d, -3.489144132234588E-8d}, new double[]{0.5865923166275024d, 5.9006122320612716E-8d}, new double[]{0.5871354341506958d, -2.2934896740542648E-8d}, new double[]{0.5876781940460205d, -4.1975650319859075E-8d}, new double[]{0.5882205963134766d, 2.2036094805348692E-9d}, new double[]{0.5887627601623535d, -9.287179048539306E-9d}, new double[]{0.5893045663833618d, 4.3079982556221595E-8d}, new double[]{0.589846134185791d, 4.041399585161321E-8d}, new double[]{0.5903874635696411d, -1.696746473863933E-8d}, new double[]{0.5909284353256226d, -9.53795080582038E-9d}, new double[]{0.5914691686630249d, -5.619010749352923E-8d}, new double[]{0.5920095443725586d, -3.7398514182529506E-8d}, new double[]{0.5925495624542236d, 4.71524479659295E-8d}, new double[]{0.5930894613265991d, -4.0640692434639215E-8d}, new double[]{0.5936288833618164d, 5.716453096255401E-8d}, new double[]{0.5941681861877441d, -1.6745661720946737E-8d}, new double[]{0.5947071313858032d, -2.3639110433141897E-8d}, new double[]{0.5952457189559937d, 3.67972590471072E-8d}, new double[]{0.595784068107605d, 4.566672575206695E-8d}, new double[]{0.5963221788406372d, 3.2813537149653483E-9d}, new double[]{0.5968599319458008d, 2.916199305533732E-8d}, new double[]{0.5973974466323853d, 4.410412409109416E-9d}, new double[]{0.5979346036911011d, 4.85464582112459E-8d}, new double[]{0.5984715223312378d, 4.267089756924666E-8d}, new double[]{0.5990082025527954d, -1.2906712010774655E-8d}, new double[]{0.5995445251464844d, 1.3319784467641742E-9d}, new double[]{0.6000806093215942d, -3.35137581974451E-8d}, new double[]{0.6006163358688354d, 2.0734340706476473E-9d}, new double[]{0.6011518239974976d, -1.0808162722402073E-8d}, new double[]{0.601686954498291d, 4.735781872502109E-8d}, new double[]{0.6022218465805054d, 5.76686738430634E-8d}, new double[]{0.6027565002441406d, 2.043049589651736E-8d}, new double[]{0.6032907962799072d, 5.515817703577808E-8d}, new double[]{0.6038248538970947d, 4.2947540692649586E-8d}, new double[]{0.6043586730957031d, -1.589678872195875E-8d}, new double[]{0.6048921346664429d, -1.8613847754677912E-9d}, new double[]{0.6054253578186035d, -3.3851886626187444E-8d}, new double[]{0.6059582233428955d, 7.64416021682279E-9d}, new double[]{0.6064908504486084d, 3.7201467248814224E-9d}, new double[]{0.6070232391357422d, -4.532172996647129E-8d}, new double[]{0.6075552701950073d, -1.997046552871766E-8d}, new double[]{0.6080870628356934d, -3.913411606668587E-8d}, new double[]{0.6086184978485107d, 1.6697361107868944E-8d}, new double[]{0.609149694442749d, 2.8614950293715483E-8d}, new double[]{0.6096806526184082d, -3.081552929643174E-9d}, new double[]{0.6102112531661987d, 4.111645931319645E-8d}, new double[]{0.6107416152954102d, 4.2298539553668435E-8d}, new double[]{0.6112717390060425d, 7.630546413718035E-10d}, new double[]{0.6118015050888062d, 3.601718675118614E-8d}, new double[]{0.6123310327529907d, 2.914906573537692E-8d}, new double[]{0.6128603219985962d, -1.9544361222269494E-8d}, new double[]{0.613389253616333d, 9.442671392695732E-9d}, new double[]{0.6139179468154907d, -2.8031202304593286E-9d}, new double[]{0.6144464015960693d, -5.598619958143586E-8d}, new double[]{0.6149744987487793d, -3.060220883766096E-8d}, new double[]{0.6155023574829102d, -4.556583652800433E-8d}, new double[]{0.6160298585891724d, 1.8626341656366314E-8d}, new double[]{0.6165571212768555d, 4.305870564227991E-8d}, new double[]{0.6170841455459595d, 2.8024460607734262E-8d}, new double[]{0.6176109313964844d, -2.6183651590639875E-8d}, new double[]{0.6181373596191406d, -6.406189112730307E-11d}, new double[]{0.6186635494232178d, -1.2534241706168776E-8d}, new double[]{0.6191893815994263d, 5.5906456251308664E-8d}, new double[]{0.6197150945663452d, -3.286964881802063E-8d}, new double[]{0.6202404499053955d, -4.0153537978961E-8d}, new double[]{0.6207654476165771d, 3.434477109643361E-8d}, new double[]{0.6212903261184692d, -4.750377491075032E-8d}, new double[]{0.6218148469924927d, -4.699152670372743E-8d}, new double[]{0.6223390102386475d, 3.617013128065961E-8d}, new double[]{0.6228630542755127d, -3.6149218175202596E-8d}, new double[]{0.6233867406845093d, -2.5243286814648133E-8d}, new double[]{0.6239101886749268d, -5.003410681432538E-8d}, new double[]{0.6244332790374756d, 8.974417915105033E-9d}, new double[]{0.6249561309814453d, 3.285935446876949E-8d}, new double[]{0.6254787445068359d, 2.190661054038537E-8d}, new double[]{0.6260011196136475d, -2.3598354190515998E-8d}, new double[]{0.6265231370925903d, 1.5838762427747586E-8d}, new double[]{0.6270449161529541d, 2.129323729978037E-8d}, new double[]{0.6275664567947388d, -6.950808333865794E-9d}, new double[]{0.6280876398086548d, 5.059959203156465E-8d}, new double[]{0.6286087036132812d, -4.41909071122557E-8d}, new double[]{0.6291294097900391d, -5.262093550784066E-8d}, new double[]{0.6296497583389282d, 2.559185648444699E-8d}, new double[]{0.6301699876785278d, -4.768920119497491E-8d}, new double[]{0.6306898593902588d, -3.376406008397877E-8d}, new double[]{0.6312094926834106d, -5.156097914033476E-8d}, new double[]{0.6317287683486938d, 1.840992392368355E-8d}, new double[]{0.632247805595398d, 5.721951534729663E-8d}, new double[]{0.6327667236328125d, -5.406177467045421E-8d}, new double[]{0.6332851648330688d, 4.247320713683124E-8d}, new double[]{0.6338034868240356d, -1.0524557502830645E-8d}, new double[]{0.6343214511871338d, 2.5641927558519502E-8d}, new double[]{0.6348391771316528d, 3.204135737993823E-8d}, new double[]{0.6353566646575928d, 8.951285029786536E-9d}, new double[]{0.6358739137649536d, -4.335116707228395E-8d}, new double[]{0.6363908052444458d, -5.380016714089483E-9d}, new double[]{0.6369074583053589d, 3.931710344901743E-9d}, new double[]{0.6374238729476929d, -1.5140150088220166E-8d}, new double[]{0.6379399299621582d, 5.688910024377372E-8d}, new double[]{0.638455867767334d, -1.8124135273572568E-8d}, new double[]{0.6389714479446411d, -1.486720391901626E-9d}, new double[]{0.6394867897033691d, -1.2133811978747018E-8d}, new double[]{0.6400018930435181d, -4.9791700939901716E-8d}, new double[]{0.6405166387557983d, 5.022188652837274E-9d}, new double[]{0.6410311460494995d, 3.337143177933685E-8d}, new double[]{0.6415454149246216d, 3.55284719912458E-8d}, new double[]{0.6420594453811646d, 1.1765332726757802E-8d}, new double[]{0.6425732374191284d, -3.7646381826067834E-8d}, new double[]{0.6430866718292236d, 6.773803682579552E-9d}, new double[]{0.6435998678207397d, 2.608736797081283E-8d}, new double[]{0.6441128253936768d, 2.056466263408266E-8d}, new double[]{0.6446255445480347d, -9.524376551107945E-9d}, new double[]{0.6451379060745239d, 5.5299060775883977E-8d}, new double[]{0.6456501483917236d, -2.3114497793159813E-8d}, new double[]{0.6461620330810547d, -6.077779731902102E-9d}, new double[]{0.6466736793518066d, -1.2531793589140273E-8d}, new double[]{0.6471850872039795d, -4.220866994206517E-8d}, new double[]{0.6476961374282837d, 2.4368339445199057E-8d}, new double[]{0.6482070684432983d, -5.095229574221907E-8d}, new double[]{0.6487176418304443d, -2.9485356677301627E-8d}, new double[]{0.6492279767990112d, -3.0173901411577916E-8d}, new double[]{0.649738073348999d, -5.275210583909726E-8d}, new double[]{0.6502478122711182d, 2.2254737134350224E-8d}, new double[]{0.6507574319839478d, -4.330693978322885E-8d}, new double[]{0.6512666940689087d, -1.0753950588009912E-8d}, new double[]{0.6517757177352905d, 9.686179886293545E-10d}, new double[]{0.6522845029830933d, -7.875434494414498E-9d}, new double[]{0.6527930498123169d, -3.702271091849158E-8d}, new double[]{0.6533012390136719d, 3.2999073763758614E-8d}, new double[]{0.6538093090057373d, -3.5966064858620067E-8d}, new double[]{0.6543170213699341d, -5.23735298540578E-9d}, new double[]{0.6548244953155518d, 6.237715351293023E-9d}, new double[]{0.6553317308425903d, -1.279462699936282E-9d}, new double[]{0.6558387279510498d, -2.7527887552743672E-8d}, new double[]{0.6563453674316406d, 4.696233317356646E-8d}, new double[]{0.6568518877029419d, -1.5967172745329108E-8d}, new double[]{0.6573580503463745d, 2.2361985518423144E-8d}, new double[]{0.657863974571228d, 4.2999935789083046E-8d}, new double[]{0.6583696603775024d, 4.620570188811826E-8d}, new double[]{0.6588751077651978d, 3.223791487908353E-8d}, new double[]{0.659380316734314d, 1.3548138612715822E-9d}, new double[]{0.6598852872848511d, -4.618575323863973E-8d}, new double[]{0.6603899002075195d, 9.082960673843353E-9d}, new double[]{0.6608942747116089d, 4.820873399634487E-8d}, new double[]{0.6613985300064087d, -4.776104368314602E-8d}, new double[]{0.6619024276733398d, -4.0151502150238136E-8d}, new double[]{0.6624060869216919d, -4.791602708710648E-8d}, new double[]{0.6629093885421753d, 4.8410188461165925E-8d}, new double[]{0.6634125709533691d, 1.0663697110471944E-8d}, new double[]{0.6639155149459839d, -4.1691464781797555E-8d}, new double[]{0.66441810131073d, 1.080835500478704E-8d}, new double[]{0.664920449256897d, 4.920784622407246E-8d}, new double[]{0.6654226779937744d, -4.544868396511241E-8d}, new double[]{0.6659245491027832d, -3.448944157854234E-8d}, new double[]{0.6664261817932129d, -3.6870882345139385E-8d}, new double[]{0.6669275760650635d, -5.234055273962444E-8d}, new double[]{0.6674286127090454d, 3.856291077979099E-8d}, new double[]{0.6679295301437378d, -2.327375671320742E-9d}, new double[]{0.6684302091598511d, -5.555080534042001E-8d}, new double[]{0.6689305305480957d, -1.6471487337453832E-9d}, new double[]{0.6694306135177612d, 4.042486803683015E-8d}, new double[]{0.6699305772781372d, -4.8293856891818295E-8d}, new double[]{0.6704301834106445d, -2.9134931730784303E-8d}, new double[]{0.6709295511245728d, -2.1058207594753368E-8d}, new double[]{0.6714286804199219d, -2.3814619551682855E-8d}, new double[]{0.6719275712966919d, -3.7155475428252136E-8d}, new double[]{0.6724261045455933d, 5.8376834484391746E-8d}, new double[]{0.6729245185852051d, 2.4611679969129262E-8d}, new double[]{0.6734226942062378d, -1.899407107267079E-8d}, new double[]{0.6739205121994019d, 4.7016079464436395E-8d}, new double[]{0.6744182109832764d, -1.5529608026276525E-8d}, new double[]{0.6749155521392822d, 3.203391672602453E-8d}, new double[]{0.6754127740859985d, -4.8465821804075345E-8d}, new double[]{0.6759096384048462d, -1.8364507801369988E-8d}, new double[]{0.6764062643051147d, 3.3739397633046517E-9d}, new double[]{0.6769026517868042d, 1.6994526063192333E-8d}, new double[]{0.6773988008499146d, 2.2741891590028428E-8d}, new double[]{0.6778947114944458d, 2.0860312877435047E-8d}, new double[]{0.678390383720398d, 1.1593703222523284E-8d}, new double[]{0.678885817527771d, -4.814386594291911E-9d}, new double[]{0.6793810129165649d, -2.812076759125914E-8d}, new double[]{0.6798759698867798d, -5.808261186903479E-8d}, new double[]{0.680370569229126d, 2.4751837654582522E-8d}, new double[]{0.6808650493621826d, -1.7793890245755405E-8d},
+ new double[]{0.6813591718673706d, 5.294053246347931E-8d}, new double[]{0.681853175163269d, -1.2220826223585654E-9d}, new double[]{0.6823468208312988d, 5.8377876767612725E-8d}, new double[]{0.6828403472900391d, -6.437492120743254E-9d}, new double[]{0.6833335161209106d, 4.2990710043633113E-8d}, new double[]{0.6838265657424927d, -3.1516131027023284E-8d}, new double[]{0.684319257736206d, 8.70017386744679E-9d}, new double[]{0.6848117113113403d, 4.466959125843237E-8d}, new double[]{0.6853040456771851d, -4.25782656420497E-8d}, new double[]{0.6857960224151611d, -1.4386267593671393E-8d}, new double[]{0.6862877607345581d, 1.0274494061148778E-8d}, new double[]{0.686779260635376d, 3.164186629229597E-8d}, new double[]{0.6872705221176147d, 4.995334552140326E-8d}, new double[]{0.687761664390564d, -5.3763211240398744E-8d}, new double[]{0.6882524490356445d, -4.0852427502515625E-8d}, new double[]{0.688742995262146d, -3.0287143914420064E-8d}, new double[]{0.6892333030700684d, -2.183125937905008E-8d}, new double[]{0.6897233724594116d, -1.524901992178814E-8d}, new double[]{0.6902132034301758d, -1.0305018010328949E-8d}, new double[]{0.6907027959823608d, -6.764191876212205E-9d}, new double[]{0.6911921501159668d, -4.391824838015402E-9d}, new double[]{0.6916812658309937d, -2.9535446262017846E-9d}, new double[]{0.6921701431274414d, -2.2153227096187463E-9d}, new double[]{0.6926587820053101d, -1.943473623641502E-9d}};
+}
diff --git a/feature/cw/src/main/java/i3/a.java b/feature/cw/src/main/java/i3/a.java
new file mode 100644
index 00000000..b1220a2c
--- /dev/null
+++ b/feature/cw/src/main/java/i3/a.java
@@ -0,0 +1,41 @@
+package i3;
+
+/* loaded from: classes.dex */
+public final class a implements Runnable {
+ public final /* synthetic */ int f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public final /* synthetic */ int f11686g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public final /* synthetic */ int f11687h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public final /* synthetic */ float[] f11688i;
+
+ /* renamed from: j, reason: collision with root package name */
+ public final /* synthetic */ float[] f11689j;
+
+ /* renamed from: k, reason: collision with root package name */
+ public final /* synthetic */ d f11690k;
+
+ public a(d dVar, int i4, int i5, int i6, float[] fArr, float[] fArr2) {
+ this.f11690k = dVar;
+ this.f = i4;
+ this.f11686g = i5;
+ this.f11687h = i6;
+ this.f11688i = fArr;
+ this.f11689j = fArr2;
+ }
+
+ @Override // java.lang.Runnable
+ public final void run() {
+ int i4 = this.f11686g;
+ int i5 = this.f;
+ if (i5 >= i4) {
+ return;
+ }
+ float f = this.f11689j[this.f11687h + i5];
+ throw null;
+ }
+}
diff --git a/feature/cw/src/main/java/i3/b.java b/feature/cw/src/main/java/i3/b.java
new file mode 100644
index 00000000..c3a410fd
--- /dev/null
+++ b/feature/cw/src/main/java/i3/b.java
@@ -0,0 +1,41 @@
+package i3;
+
+/* loaded from: classes.dex */
+public final class b implements Runnable {
+ public final /* synthetic */ long f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public final /* synthetic */ long f11691g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public final /* synthetic */ long f11692h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public final /* synthetic */ k3.d f11693i;
+
+ /* renamed from: j, reason: collision with root package name */
+ public final /* synthetic */ k3.d f11694j;
+
+ /* renamed from: k, reason: collision with root package name */
+ public final /* synthetic */ d f11695k;
+
+ public b(d dVar, long j4, long j5, long j6, k3.d dVar2, k3.d dVar3) {
+ this.f11695k = dVar;
+ this.f = j4;
+ this.f11691g = j5;
+ this.f11692h = j6;
+ this.f11693i = dVar2;
+ this.f11694j = dVar3;
+ }
+
+ @Override // java.lang.Runnable
+ public final void run() {
+ long j4 = this.f11691g;
+ long j5 = this.f;
+ if (j5 >= j4) {
+ return;
+ }
+ this.f11694j.b(this.f11692h + j5);
+ throw null;
+ }
+}
diff --git a/feature/cw/src/main/java/i3/c.java b/feature/cw/src/main/java/i3/c.java
new file mode 100644
index 00000000..1de182dd
--- /dev/null
+++ b/feature/cw/src/main/java/i3/c.java
@@ -0,0 +1,55 @@
+package i3;
+
+import k3.g;
+import k3.s;
+
+/* loaded from: classes.dex */
+public final class c implements Runnable {
+ public final /* synthetic */ int f = 1;
+
+ /* renamed from: g, reason: collision with root package name */
+ public final /* synthetic */ long f11696g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public final /* synthetic */ long f11697h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public final /* synthetic */ g f11698i;
+
+ /* renamed from: j, reason: collision with root package name */
+ public final /* synthetic */ Object f11699j;
+
+ public c(long j4, long j5, s sVar, s sVar2) {
+ this.f11696g = j4;
+ this.f11697h = j5;
+ this.f11698i = sVar;
+ this.f11699j = sVar2;
+ }
+
+ @Override // java.lang.Runnable
+ public final void run() {
+ switch (this.f) {
+ case 0:
+ k3.d dVar = (k3.d) this.f11698i;
+ long j4 = this.f11697h;
+ long j5 = this.f11696g;
+ if (j5 >= j4) {
+ return;
+ }
+ dVar.b(j5 * 2);
+ throw null;
+ default:
+ for (long j6 = this.f11696g; j6 < this.f11697h; j6++) {
+ ((s) this.f11698i).c(j6, ((s) this.f11699j).b(j6));
+ }
+ return;
+ }
+ }
+
+ public c(d dVar, long j4, long j5, k3.d dVar2) {
+ this.f11699j = dVar;
+ this.f11696g = j4;
+ this.f11697h = j5;
+ this.f11698i = dVar2;
+ }
+}
diff --git a/feature/cw/src/main/java/i3/d.java b/feature/cw/src/main/java/i3/d.java
new file mode 100644
index 00000000..e709e0ac
--- /dev/null
+++ b/feature/cw/src/main/java/i3/d.java
@@ -0,0 +1,1267 @@
+package i3;
+
+import d1.AbstractC1518b;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import k3.g;
+import k3.q;
+import k3.r;
+import k3.s;
+import s.AbstractC1880e;
+
+/* loaded from: classes.dex */
+public final class d {
+
+ /* renamed from: a, reason: collision with root package name */
+ public int f11700a;
+
+ /* renamed from: b, reason: collision with root package name */
+ public long f11701b;
+ public int[] c;
+
+ /* renamed from: d, reason: collision with root package name */
+ public s f11702d;
+
+ /* renamed from: e, reason: collision with root package name */
+ public float[] f11703e;
+ public k3.d f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public int f11704g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public long f11705h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public int f11706i;
+
+ /* renamed from: j, reason: collision with root package name */
+ public long f11707j;
+
+ /* renamed from: k, reason: collision with root package name */
+ public int f11708k;
+
+ /* renamed from: l, reason: collision with root package name */
+ public boolean f11709l;
+
+ public final void a(int i4, int i5, int i6, int i7, int i8, float[] fArr, float[] fArr2) {
+ int i9 = i5 * i4;
+ int i10 = i4 * 2;
+ for (int i11 = 0; i11 < i5; i11++) {
+ int i12 = (i11 * i10) + i7;
+ int i13 = (i11 * i4) + i6;
+ int i14 = i13 + i9;
+ float f = fArr[i13];
+ float f4 = fArr[i14];
+ fArr2[i12] = f + f4;
+ fArr2[(i12 + i10) - 1] = f - f4;
+ }
+ if (i4 >= 2) {
+ if (i4 != 2) {
+ for (int i15 = 0; i15 < i5; i15++) {
+ i10 = i15 * i4;
+ int i16 = i10 + i9;
+ if (2 < i4) {
+ int i17 = i6 + 2;
+ int i18 = i10 + i17;
+ int i19 = i17 + i16;
+ float f5 = fArr[i18 - 1];
+ float f6 = fArr[i18];
+ float f7 = fArr[i19 - 1];
+ float f8 = fArr[i19];
+ throw null;
+ }
+ }
+ if (i4 % 2 == 1) {
+ return;
+ }
+ }
+ int i20 = i10 * 2;
+ for (int i21 = 0; i21 < i5; i21++) {
+ int i22 = i7 + i20 + i4;
+ int i23 = ((i6 + i4) - 1) + (i21 * i4);
+ fArr2[i22] = -fArr[i23 + i9];
+ fArr2[i22 - 1] = fArr[i23];
+ }
+ }
+ }
+
+ public final void b(long j4, long j5, long j6, long j7, long j8, k3.d dVar, k3.d dVar2) {
+ long j9 = j5 * j4;
+ long j10 = 2;
+ long j11 = j4 * 2;
+ long j12 = 0;
+ while (j12 < j5) {
+ long j13 = (j12 * j11) + j7;
+ long j14 = (j12 * j4) + j6;
+ float b4 = dVar.b(j14);
+ float b5 = dVar.b(j14 + j9);
+ dVar2.c((j13 + j11) - 1, AbstractC1518b.m(b4, b5, dVar2, j13, b4, b5));
+ j12++;
+ j10 = j10;
+ }
+ long j15 = j10;
+ if (j4 >= j15) {
+ if (j4 != j15) {
+ for (long j16 = 0; j16 < j5; j16++) {
+ j11 = j16 * j4;
+ long j17 = j11 + j9;
+ if (j15 < j4) {
+ long j18 = j6 + j15;
+ long j19 = j11 + j18;
+ long j20 = j18 + j17;
+ dVar.b(j19 - 1);
+ dVar.b(j19);
+ dVar.b(j20 - 1);
+ dVar.b(j20);
+ throw null;
+ }
+ }
+ if (j4 % j15 == 1) {
+ return;
+ }
+ }
+ long j21 = j11 * j15;
+ for (long j22 = 0; j22 < j5; j22++) {
+ long j23 = j7 + j21 + j4;
+ long j24 = ((j6 + j4) - 1) + (j22 * j4);
+ dVar2.c(j23, -dVar.b(j24 + j9));
+ dVar2.c(j23 - 1, dVar.b(j24));
+ }
+ }
+ }
+
+ public final void c(int i4, int i5, int i6, int i7, int i8, float[] fArr, float[] fArr2) {
+ int i9 = i5 * i4;
+ for (int i10 = 0; i10 < i5; i10++) {
+ int i11 = i10 * i4;
+ int i12 = ((i10 * 3) + 1) * i4;
+ int i13 = i6 + i11;
+ int i14 = i13 + i9;
+ int i15 = (i9 * 2) + i13;
+ float f = fArr[i13];
+ float f4 = fArr[i14];
+ float f5 = fArr[i15];
+ float f6 = f4 + f5;
+ fArr2[(i11 * 3) + i7] = f + f6;
+ fArr2[i7 + i12 + i4] = (f5 - f4) * 0.8660254f;
+ fArr2[((i7 + i4) - 1) + i12] = (f6 * (-0.5f)) + f;
+ }
+ if (i4 != 1) {
+ for (int i16 = 0; i16 < i5; i16++) {
+ if (2 < i4) {
+ throw null;
+ }
+ }
+ }
+ }
+
+ public final void d(long j4, long j5, long j6, long j7, long j8, k3.d dVar, k3.d dVar2) {
+ long j9 = j5 * j4;
+ for (long j10 = 0; j10 < j5; j10++) {
+ long j11 = j10 * j4;
+ long j12 = ((j10 * 3) + 1) * j4;
+ long j13 = j6 + j11;
+ long j14 = j13 + j9;
+ long j15 = (2 * j9) + j13;
+ float b4 = dVar.b(j13);
+ float b5 = dVar.b(j14);
+ float b6 = dVar.b(j15);
+ float f = b5 + b6;
+ dVar2.c((j11 * 3) + j7, b4 + f);
+ dVar2.c(j7 + j12 + j4, (b6 - b5) * 0.8660254f);
+ dVar2.c(((j7 + j4) - 1) + j12, (f * (-0.5f)) + b4);
+ }
+ if (j4 != 1) {
+ for (long j16 = 0; j16 < j5; j16++) {
+ if (2 < j4) {
+ throw null;
+ }
+ }
+ }
+ }
+
+ public final void e(int i4, int i5, int i6, int i7, int i8, float[] fArr, float[] fArr2) {
+ int i9 = i5 * i4;
+ for (int i10 = 0; i10 < i5; i10++) {
+ int i11 = i10 * i4;
+ int i12 = i11 * 4;
+ int i13 = i11 + i9;
+ int i14 = i13 + i9;
+ int i15 = i14 + i9;
+ float f = fArr[i6 + i11];
+ float f4 = fArr[i6 + i13];
+ float f5 = fArr[i6 + i14];
+ float f6 = fArr[i6 + i15];
+ float f7 = f4 + f6;
+ float f8 = f + f5;
+ int i16 = i7 + i12 + i4 + i4;
+ fArr2[i7 + i12] = f7 + f8;
+ int i17 = i16 - 1;
+ fArr2[i17 + i4 + i4] = f8 - f7;
+ fArr2[i17] = f - f5;
+ fArr2[i16] = f6 - f4;
+ }
+ if (i4 >= 2) {
+ if (i4 != 2) {
+ for (int i18 = 0; i18 < i5; i18++) {
+ if (2 < i4) {
+ throw null;
+ }
+ }
+ if (i4 % 2 == 1) {
+ return;
+ }
+ }
+ for (int i19 = 0; i19 < i5; i19++) {
+ int i20 = i19 * i4;
+ int i21 = i20 * 4;
+ int i22 = i20 + i9;
+ int i23 = i22 + i9;
+ int i24 = i23 + i9;
+ int i25 = i21 + i4;
+ int i26 = i25 + i4;
+ int i27 = (i6 + i4) - 1;
+ float f9 = fArr[i20 + i27];
+ float f10 = fArr[i22 + i27];
+ float f11 = fArr[i23 + i27];
+ float f12 = fArr[i27 + i24];
+ float f13 = (f10 + f12) * (-0.70710677f);
+ float f14 = (f10 - f12) * 0.70710677f;
+ int i28 = (i7 + i4) - 1;
+ fArr2[i21 + i28] = f14 + f9;
+ fArr2[i28 + i26] = f9 - f14;
+ fArr2[i7 + i25] = f13 - f11;
+ fArr2[i7 + i26 + i4] = f13 + f11;
+ }
+ }
+ }
+
+ public final void f(long j4, long j5, long j6, long j7, long j8, k3.d dVar, k3.d dVar2) {
+ long j9 = j5 * j4;
+ for (long j10 = 0; j10 < j5; j10++) {
+ long j11 = j10 * j4;
+ long j12 = 4 * j11;
+ long j13 = j11 + j9;
+ long j14 = j13 + j9;
+ long j15 = j12 + j4;
+ float b4 = dVar.b(j6 + j11);
+ float b5 = dVar.b(j6 + j13);
+ float b6 = dVar.b(j6 + j14);
+ float b7 = dVar.b(j6 + j14 + j9);
+ float f = b5 + b7;
+ float f4 = b4 + b6;
+ long j16 = j7 + j15 + j4;
+ dVar2.c(j7 + j12, f + f4);
+ long j17 = j16 - 1;
+ dVar2.c(j17, AbstractC1518b.l(f4, f, dVar2, j17 + j4 + j4, b4, b6));
+ dVar2.c(j16, b7 - b5);
+ }
+ if (j4 >= 2) {
+ if (j4 != 2) {
+ for (long j18 = 0; j18 < j5; j18++) {
+ if (2 < j4) {
+ throw null;
+ }
+ }
+ if (j4 % 2 == 1) {
+ return;
+ }
+ }
+ for (long j19 = 0; j19 < j5; j19++) {
+ long j20 = j19 * j4;
+ long j21 = j20 * 4;
+ long j22 = j20 + j9;
+ long j23 = j22 + j9;
+ long j24 = j21 + j4;
+ long j25 = j24 + j4;
+ long j26 = (j6 + j4) - 1;
+ float b8 = dVar.b(j26 + j20);
+ float b9 = dVar.b(j26 + j22);
+ float b10 = dVar.b(j26 + j23);
+ float b11 = dVar.b(j26 + j23 + j9);
+ float f5 = (b9 + b11) * (-0.70710677f);
+ float f6 = (b9 - b11) * 0.70710677f;
+ long j27 = (j7 + j4) - 1;
+ dVar2.c(j27 + j21, f6 + b8);
+ dVar2.c(j27 + j25, b8 - f6);
+ dVar2.c(j7 + j24, f5 - b10);
+ dVar2.c(j7 + j25 + j4, f5 + b10);
+ }
+ }
+ }
+
+ public final void g(int i4, int i5, int i6, int i7, int i8, float[] fArr, float[] fArr2) {
+ int i9 = i5 * i4;
+ for (int i10 = 0; i10 < i5; i10++) {
+ int i11 = i10 * i4;
+ int i12 = i11 * 5;
+ int i13 = i12 + i4;
+ int i14 = i13 + i4;
+ int i15 = i14 + i4;
+ int i16 = i11 + i9;
+ int i17 = i16 + i9;
+ int i18 = i17 + i9;
+ int i19 = (i7 + i4) - 1;
+ float f = fArr[i6 + i11];
+ float f4 = fArr[i6 + i16];
+ float f5 = fArr[i6 + i17];
+ float f6 = fArr[i6 + i18];
+ float f7 = fArr[i6 + i18 + i9];
+ float f8 = f7 + f4;
+ float f9 = f7 - f4;
+ float f10 = f6 + f5;
+ float f11 = f6 - f5;
+ fArr2[i7 + i12] = f + f8 + f10;
+ fArr2[i19 + i13] = (f10 * (-0.809017f)) + (f8 * 0.309017f) + f;
+ fArr2[i7 + i14] = (f11 * 0.58778524f) + (f9 * 0.95105654f);
+ fArr2[i19 + i15] = (f10 * 0.309017f) + (f8 * (-0.809017f)) + f;
+ fArr2[i7 + i15 + i4] = (f9 * 0.58778524f) - (f11 * 0.95105654f);
+ }
+ if (i4 != 1) {
+ for (int i20 = 0; i20 < i5; i20++) {
+ if (2 < i4) {
+ throw null;
+ }
+ }
+ }
+ }
+
+ public final void h(long j4, long j5, long j6, long j7, long j8, k3.d dVar, k3.d dVar2) {
+ long j9 = j5 * j4;
+ long j10 = 0;
+ while (j10 < j5) {
+ long j11 = j10 * j4;
+ long j12 = 5 * j11;
+ long j13 = j12 + j4;
+ long j14 = j13 + j4;
+ long j15 = j14 + j4;
+ long j16 = j11 + j9;
+ long j17 = j16 + j9;
+ long j18 = j17 + j9;
+ long j19 = (j7 + j4) - 1;
+ float b4 = dVar.b(j6 + j11);
+ float b5 = dVar.b(j6 + j16);
+ float b6 = dVar.b(j6 + j17);
+ float b7 = dVar.b(j6 + j18);
+ long j20 = j9;
+ float b8 = dVar.b(j6 + j18 + j9);
+ float f = b8 + b5;
+ float f4 = b8 - b5;
+ float f5 = b7 + b6;
+ float f6 = b7 - b6;
+ dVar2.c(j7 + j12, b4 + f + f5);
+ dVar2.c(j19 + j13, (f5 * (-0.809017f)) + (f * 0.309017f) + b4);
+ dVar2.c(j7 + j14, (f6 * 0.58778524f) + (f4 * 0.95105654f));
+ dVar2.c(j19 + j15, (f5 * 0.309017f) + (f * (-0.809017f)) + b4);
+ dVar2.c(j7 + j15 + j4, (f4 * 0.58778524f) - (f6 * 0.95105654f));
+ j10++;
+ j9 = j20;
+ }
+ if (j4 != 1) {
+ for (long j21 = 0; j21 < j5; j21++) {
+ if (2 < j4) {
+ throw null;
+ }
+ }
+ }
+ }
+
+ public final void i(int i4, int i5, int i6, int i7, float[] fArr, int i8, float[] fArr2, int i9, int i10) {
+ int i11 = i4;
+ int i12 = i5;
+ double d4 = 6.2831855f / i12;
+ float b4 = (float) g3.c.b(d4);
+ float f = (float) g3.c.f(d4);
+ int i13 = (i12 + 1) / 2;
+ int i14 = (i11 - 1) / 2;
+ if (i11 != 1) {
+ for (int i15 = 0; i15 < i7; i15++) {
+ fArr2[i9 + i15] = fArr[i8 + i15];
+ }
+ for (int i16 = 1; i16 < i12; i16++) {
+ int i17 = i16 * i6 * i11;
+ for (int i18 = 0; i18 < i6; i18++) {
+ int i19 = (i18 * i11) + i17;
+ fArr2[i9 + i19] = fArr[i8 + i19];
+ }
+ }
+ if (i14 <= i6) {
+ for (int i20 = 1; i20 < i12; i20++) {
+ if (2 < i11) {
+ throw null;
+ }
+ }
+ } else {
+ for (int i21 = 1; i21 < i12; i21++) {
+ for (int i22 = 0; i22 < i6; i22++) {
+ if (2 < i11) {
+ throw null;
+ }
+ }
+ }
+ }
+ if (i14 >= i6) {
+ for (int i23 = 1; i23 < i13; i23++) {
+ int i24 = i23 * i6 * i11;
+ int i25 = (i12 - i23) * i6 * i11;
+ for (int i26 = 0; i26 < i6; i26++) {
+ int i27 = i26 * i11;
+ int i28 = i27 + i24;
+ int i29 = i27 + i25;
+ for (int i30 = 2; i30 < i11; i30 += 2) {
+ int i31 = i8 + i30;
+ int i32 = i9 + i30;
+ int i33 = i31 + i28;
+ int i34 = i31 + i29;
+ int i35 = i32 + i28;
+ int i36 = i32 + i29;
+ float f4 = fArr2[i35 - 1];
+ float f5 = fArr2[i35];
+ float f6 = fArr2[i36 - 1];
+ float f7 = fArr2[i36];
+ fArr[i33 - 1] = f4 + f6;
+ fArr[i33] = f5 + f7;
+ fArr[i34 - 1] = f5 - f7;
+ fArr[i34] = f6 - f4;
+ }
+ }
+ }
+ } else {
+ int i37 = 1;
+ while (i37 < i13) {
+ int i38 = i37 * i6 * i11;
+ int i39 = (i12 - i37) * i6 * i11;
+ for (int i40 = 2; i40 < i11; i40 += 2) {
+ int i41 = i8 + i40;
+ int i42 = i9 + i40;
+ for (int i43 = 0; i43 < i6; i43++) {
+ int i44 = i43 * i11;
+ int i45 = i44 + i38;
+ int i46 = i44 + i39;
+ int i47 = i41 + i45;
+ int i48 = i41 + i46;
+ int i49 = i42 + i45;
+ int i50 = i42 + i46;
+ float f8 = fArr2[i49 - 1];
+ float f9 = fArr2[i49];
+ float f10 = fArr2[i50 - 1];
+ float f11 = fArr2[i50];
+ fArr[i47 - 1] = f8 + f10;
+ fArr[i47] = f9 + f11;
+ fArr[i48 - 1] = f9 - f11;
+ fArr[i48] = f10 - f8;
+ }
+ }
+ i37++;
+ i12 = i5;
+ }
+ }
+ } else {
+ System.arraycopy(fArr2, i9, fArr, i8, i7);
+ }
+ for (int i51 = 1; i51 < i13; i51++) {
+ int i52 = i51 * i6 * i11;
+ int i53 = (i5 - i51) * i6 * i11;
+ for (int i54 = 0; i54 < i6; i54++) {
+ int i55 = i54 * i11;
+ int i56 = i55 + i52;
+ int i57 = i55 + i53;
+ float f12 = fArr2[i9 + i56];
+ float f13 = fArr2[i9 + i57];
+ fArr[i8 + i56] = f12 + f13;
+ fArr[i57 + i8] = f13 - f12;
+ }
+ }
+ int i58 = (i5 - 1) * i7;
+ float f14 = 1.0f;
+ float f15 = 0.0f;
+ int i59 = 1;
+ while (i59 < i13) {
+ float f16 = (b4 * f14) - (f * f15);
+ f15 = (f15 * b4) + (f14 * f);
+ int i60 = i59 * i7;
+ int i61 = (i5 - i59) * i7;
+ int i62 = i58;
+ for (int i63 = 0; i63 < i7; i63++) {
+ int i64 = i9 + i63;
+ int i65 = i8 + i63;
+ fArr2[i64 + i60] = (fArr[i65 + i7] * f16) + fArr[i65];
+ fArr2[i64 + i61] = fArr[i65 + i62] * f15;
+ }
+ float f17 = f15;
+ float f18 = f16;
+ int i66 = 2;
+ while (i66 < i13) {
+ float f19 = (f16 * f18) - (f15 * f17);
+ f17 = (f18 * f15) + (f17 * f16);
+ int i67 = i66 * i7;
+ int i68 = (i5 - i66) * i7;
+ int i69 = i66;
+ for (int i70 = 0; i70 < i7; i70++) {
+ int i71 = i9 + i70;
+ int i72 = i8 + i70;
+ int i73 = i71 + i60;
+ fArr2[i73] = (fArr[i72 + i67] * f19) + fArr2[i73];
+ int i74 = i71 + i61;
+ fArr2[i74] = (fArr[i72 + i68] * f17) + fArr2[i74];
+ }
+ i66 = i69 + 1;
+ f18 = f19;
+ }
+ i59++;
+ f14 = f16;
+ i58 = i62;
+ }
+ for (int i75 = 1; i75 < i13; i75++) {
+ int i76 = i75 * i7;
+ for (int i77 = 0; i77 < i7; i77++) {
+ int i78 = i9 + i77;
+ fArr2[i78] = fArr2[i78] + fArr[i8 + i77 + i76];
+ }
+ }
+ if (i11 >= i6) {
+ for (int i79 = 0; i79 < i6; i79++) {
+ int i80 = i79 * i11;
+ int i81 = i80 * i5;
+ for (int i82 = 0; i82 < i11; i82++) {
+ fArr[i8 + i82 + i81] = fArr2[i9 + i82 + i80];
+ }
+ }
+ } else {
+ for (int i83 = 0; i83 < i11; i83++) {
+ for (int i84 = 0; i84 < i6; i84++) {
+ int i85 = i84 * i11;
+ fArr[(i85 * i5) + i8 + i83] = fArr2[i9 + i83 + i85];
+ }
+ }
+ }
+ int i86 = i5 * i11;
+ for (int i87 = 1; i87 < i13; i87++) {
+ int i88 = i87 * i6 * i11;
+ int i89 = (i5 - i87) * i6 * i11;
+ int i90 = i87 * 2 * i11;
+ for (int i91 = 0; i91 < i6; i91++) {
+ int i92 = i91 * i11;
+ int i93 = i91 * i86;
+ fArr[((((i8 + i11) - 1) + i90) - i11) + i93] = fArr2[i92 + i88 + i9];
+ fArr[i8 + i90 + i93] = fArr2[i92 + i89 + i9];
+ }
+ }
+ if (i11 == 1) {
+ return;
+ }
+ if (i14 >= i6) {
+ for (int i94 = 1; i94 < i13; i94++) {
+ int i95 = i94 * i6 * i11;
+ int i96 = (i5 - i94) * i6 * i11;
+ int i97 = i94 * 2 * i11;
+ for (int i98 = 0; i98 < i6; i98++) {
+ int i99 = i98 * i86;
+ int i100 = i98 * i11;
+ for (int i101 = 2; i101 < i11; i101 += 2) {
+ int i102 = i8 + i101 + i97 + i99;
+ int i103 = (((i8 + (i11 - i101)) + i97) - i11) + i99;
+ int i104 = i9 + i101 + i100;
+ int i105 = i104 + i95;
+ int i106 = i104 + i96;
+ float f20 = fArr2[i105 - 1];
+ float f21 = fArr2[i105];
+ float f22 = fArr2[i106 - 1];
+ float f23 = fArr2[i106];
+ fArr[i102 - 1] = f20 + f22;
+ fArr[i103 - 1] = f20 - f22;
+ fArr[i102] = f21 + f23;
+ fArr[i103] = f23 - f21;
+ }
+ }
+ }
+ return;
+ }
+ int i107 = 1;
+ while (i107 < i13) {
+ int i108 = i107 * i6 * i11;
+ int i109 = (i5 - i107) * i6 * i11;
+ int i110 = i107 * 2 * i11;
+ int i111 = 2;
+ while (i111 < i11) {
+ int i112 = i8 + i111;
+ int i113 = (i11 - i111) + i8;
+ int i114 = i9 + i111;
+ for (int i115 = 0; i115 < i6; i115++) {
+ int i116 = i115 * i86;
+ int i117 = i112 + i110 + i116;
+ int i118 = ((i113 + i110) - i4) + i116;
+ int i119 = i114 + (i115 * i4);
+ int i120 = i119 + i108;
+ int i121 = i119 + i109;
+ float f24 = fArr2[i120 - 1];
+ float f25 = fArr2[i120];
+ float f26 = fArr2[i121 - 1];
+ float f27 = fArr2[i121];
+ fArr[i117 - 1] = f24 + f26;
+ fArr[i118 - 1] = f24 - f26;
+ fArr[i117] = f25 + f27;
+ fArr[i118] = f27 - f25;
+ }
+ i111 += 2;
+ i11 = i4;
+ }
+ i107++;
+ i11 = i4;
+ }
+ }
+
+ public final void j(long j4, long j5, long j6, long j7, k3.d dVar, long j8, k3.d dVar2, long j9, long j10) {
+ float f;
+ float f4;
+ long j11;
+ long j12;
+ long j13 = j5;
+ k3.d dVar3 = dVar;
+ k3.d dVar4 = dVar2;
+ double d4 = 6.2831855f / ((float) j13);
+ float b4 = (float) g3.c.b(d4);
+ float f5 = (float) g3.c.f(d4);
+ long j14 = 1;
+ long j15 = 2;
+ long j16 = (j13 + 1) / 2;
+ long j17 = (j4 - 1) / 2;
+ if (j4 != 1) {
+ for (long j18 = 0; j18 < j7; j18++) {
+ dVar4.c(j9 + j18, dVar3.b(j8 + j18));
+ }
+ for (long j19 = 1; j19 < j13; j19 += j14) {
+ long j20 = j19 * j6 * j4;
+ long j21 = 0;
+ while (j21 < j6) {
+ long j22 = (j21 * j4) + j20;
+ long j23 = j14;
+ dVar4.c(j9 + j22, dVar3.b(j8 + j22));
+ j21 += j23;
+ j14 = j23;
+ j15 = j15;
+ }
+ }
+ j11 = j14;
+ j12 = j15;
+ if (j17 <= j6) {
+ for (long j24 = j11; j24 < j13; j24 += j11) {
+ if (j12 < j4) {
+ throw null;
+ }
+ }
+ } else {
+ for (long j25 = j11; j25 < j13; j25 += j11) {
+ for (long j26 = 0; j26 < j6; j26 += j11) {
+ if (j12 < j4) {
+ throw null;
+ }
+ }
+ }
+ }
+ if (j17 >= j6) {
+ long j27 = j11;
+ while (j27 < j16) {
+ long j28 = j27 * j6 * j4;
+ long j29 = (j13 - j27) * j6 * j4;
+ for (long j30 = 0; j30 < j6; j30 += j11) {
+ long j31 = j30 * j4;
+ long j32 = j31 + j28;
+ long j33 = j31 + j29;
+ long j34 = j12;
+ while (j34 < j4) {
+ long j35 = j8 + j34;
+ long j36 = j9 + j34;
+ long j37 = j35 + j32;
+ long j38 = j35 + j33;
+ long j39 = j36 + j32;
+ long j40 = j36 + j33;
+ float b5 = dVar4.b(j39 - j11);
+ float b6 = dVar4.b(j39);
+ float b7 = dVar4.b(j40 - j11);
+ float b8 = dVar4.b(j40);
+ dVar3.c(j37, AbstractC1518b.j(b5, b7, dVar3, j37 - j11, b6, b8));
+ dVar3.c(j38, AbstractC1518b.l(b6, b8, dVar3, j38 - j11, b7, b5));
+ j34 += j12;
+ b4 = b4;
+ f5 = f5;
+ }
+ }
+ j27 += j11;
+ j13 = j5;
+ }
+ f = b4;
+ f4 = f5;
+ } else {
+ f = b4;
+ f4 = f5;
+ long j41 = j11;
+ while (j41 < j16) {
+ long j42 = j41 * j6 * j4;
+ long j43 = (j5 - j41) * j6 * j4;
+ long j44 = j12;
+ while (j44 < j4) {
+ long j45 = j8 + j44;
+ long j46 = j9 + j44;
+ long j47 = 0;
+ while (j47 < j6) {
+ long j48 = j47 * j4;
+ long j49 = j48 + j42;
+ long j50 = j48 + j43;
+ long j51 = j45 + j49;
+ long j52 = j41;
+ long j53 = j45 + j50;
+ long j54 = j46 + j49;
+ long j55 = j46 + j50;
+ float b9 = dVar4.b(j54 - j11);
+ float b10 = dVar4.b(j54);
+ float b11 = dVar4.b(j55 - j11);
+ float b12 = dVar4.b(j55);
+ dVar3.c(j51, AbstractC1518b.j(b9, b11, dVar3, j51 - j11, b10, b12));
+ dVar3.c(j53, AbstractC1518b.l(b10, b12, dVar3, j53 - j11, b11, b9));
+ j47 += j11;
+ dVar4 = dVar2;
+ j41 = j52;
+ j42 = j42;
+ }
+ j44 += j12;
+ dVar4 = dVar2;
+ }
+ j41 += j11;
+ dVar4 = dVar2;
+ }
+ dVar4 = dVar2;
+ }
+ } else {
+ f = b4;
+ f4 = f5;
+ j11 = 1;
+ j12 = 2;
+ r.a(j9, j8, j7, dVar4, dVar3);
+ dVar3 = dVar3;
+ dVar4 = dVar4;
+ }
+ long j56 = j11;
+ while (j56 < j16) {
+ long j57 = j56 * j6 * j4;
+ long j58 = (j5 - j56) * j6 * j4;
+ long j59 = 0;
+ while (j59 < j6) {
+ long j60 = j59 * j4;
+ long j61 = j60 + j57;
+ long j62 = j60 + j58;
+ long j63 = j56;
+ float b13 = dVar4.b(j9 + j61);
+ float b14 = dVar4.b(j9 + j62);
+ dVar3.c(j8 + j61, b13 + b14);
+ dVar3.c(j8 + j62, b14 - b13);
+ j59 += j11;
+ j56 = j63;
+ }
+ j56 += j11;
+ }
+ long j64 = (j5 - j11) * j7;
+ float f6 = 1.0f;
+ float f7 = 0.0f;
+ long j65 = j11;
+ while (j65 < j16) {
+ float f8 = (f * f6) - (f4 * f7);
+ float f9 = (f7 * f) + (f4 * f6);
+ long j66 = j65 * j7;
+ long j67 = (j5 - j65) * j7;
+ long j68 = 0;
+ while (j68 < j7) {
+ long j69 = j9 + j68;
+ long j70 = j64;
+ long j71 = j8 + j68;
+ float f10 = f9;
+ dVar4.c(j69 + j66, (dVar3.b(j71 + j7) * f8) + dVar3.b(j71));
+ dVar4.c(j69 + j67, dVar3.b(j71 + j70) * f10);
+ j68 += j11;
+ f9 = f10;
+ j64 = j70;
+ }
+ long j72 = j64;
+ float f11 = f9;
+ float f12 = f8;
+ long j73 = j12;
+ while (j73 < j16) {
+ float f13 = (f8 * f12) - (f11 * f9);
+ f9 = (f9 * f8) + (f12 * f11);
+ long j74 = j73 * j7;
+ long j75 = (j5 - j73) * j7;
+ long j76 = 0;
+ while (j76 < j7) {
+ long j77 = j9 + j76;
+ long j78 = j8 + j76;
+ long j79 = j73;
+ long j80 = j77 + j66;
+ float f14 = f9;
+ dVar4.c(j80, (dVar3.b(j78 + j74) * f13) + dVar4.b(j80));
+ long j81 = j77 + j67;
+ dVar4.c(j81, (dVar3.b(j78 + j75) * f14) + dVar4.b(j81));
+ j76 += j11;
+ f9 = f14;
+ j73 = j79;
+ }
+ j73 += j11;
+ f12 = f13;
+ }
+ j65 += j11;
+ f6 = f8;
+ f7 = f11;
+ j64 = j72;
+ }
+ for (long j82 = j11; j82 < j16; j82 += j11) {
+ long j83 = j82 * j7;
+ for (long j84 = 0; j84 < j7; j84 += j11) {
+ long j85 = j9 + j84;
+ dVar4.c(j85, dVar3.b(j8 + j84 + j83) + dVar4.b(j85));
+ }
+ }
+ if (j4 >= j6) {
+ for (long j86 = 0; j86 < j6; j86 += j11) {
+ long j87 = j86 * j4;
+ long j88 = j87 * j5;
+ for (long j89 = 0; j89 < j4; j89 += j11) {
+ dVar3.c(j8 + j89 + j88, dVar4.b(j9 + j89 + j87));
+ }
+ }
+ } else {
+ for (long j90 = 0; j90 < j4; j90 += j11) {
+ for (long j91 = 0; j91 < j6; j91 += j11) {
+ long j92 = j91 * j4;
+ dVar3.c((j92 * j5) + j8 + j90, dVar4.b(j9 + j90 + j92));
+ }
+ }
+ }
+ long j93 = j5 * j4;
+ long j94 = j11;
+ while (j94 < j16) {
+ long j95 = j94 * j6 * j4;
+ long j96 = (j5 - j94) * j6 * j4;
+ long j97 = j94 * j12 * j4;
+ long j98 = 0;
+ while (j98 < j6) {
+ long j99 = j98 * j4;
+ long j100 = j98 * j93;
+ long j101 = j93;
+ dVar3.c(((((j8 + j4) - j11) + j97) - j4) + j100, dVar4.b(j9 + j99 + j95));
+ dVar3.c(j8 + j97 + j100, dVar4.b(j9 + j99 + j96));
+ j98 += j11;
+ j93 = j101;
+ j94 = j94;
+ }
+ j94 += j11;
+ }
+ long j102 = j93;
+ if (j4 == 1) {
+ return;
+ }
+ if (j17 >= j6) {
+ long j103 = j11;
+ while (j103 < j16) {
+ long j104 = j103 * j6 * j4;
+ long j105 = (j5 - j103) * j6 * j4;
+ long j106 = j103 * j12 * j4;
+ for (long j107 = 0; j107 < j6; j107 += j11) {
+ long j108 = j107 * j102;
+ long j109 = j107 * j4;
+ long j110 = j12;
+ while (j110 < j4) {
+ long j111 = j8 + j110 + j106 + j108;
+ long j112 = (((j8 + (j4 - j110)) + j106) - j4) + j108;
+ long j113 = j9 + j110 + j109;
+ long j114 = j103;
+ long j115 = j113 + j104;
+ long j116 = j113 + j105;
+ float b15 = dVar4.b(j115 - j11);
+ float b16 = dVar4.b(j115);
+ float b17 = dVar4.b(j116 - j11);
+ float b18 = dVar4.b(j116);
+ dVar3.c(j111 - j11, b15 + b17);
+ dVar3.c(j111, AbstractC1518b.a(b15, b17, dVar3, j112 - j11, b16, b18));
+ dVar3.c(j112, b18 - b16);
+ j110 += j12;
+ j103 = j114;
+ j104 = j104;
+ }
+ }
+ j103 += j11;
+ }
+ return;
+ }
+ long j117 = j11;
+ while (j117 < j16) {
+ long j118 = j117 * j6 * j4;
+ long j119 = (j5 - j117) * j6 * j4;
+ long j120 = j117 * j12 * j4;
+ long j121 = j12;
+ while (j121 < j4) {
+ long j122 = j8 + j121;
+ long j123 = j8 + (j4 - j121);
+ long j124 = j9 + j121;
+ long j125 = 0;
+ while (j125 < j6) {
+ long j126 = j125 * j102;
+ long j127 = j122 + j120 + j126;
+ long j128 = ((j123 + j120) - j4) + j126;
+ long j129 = j124 + (j125 * j4);
+ long j130 = j129 + j118;
+ long j131 = j129 + j119;
+ long j132 = j117;
+ float b19 = dVar4.b(j130 - j11);
+ float b20 = dVar4.b(j130);
+ float b21 = dVar4.b(j131 - j11);
+ float b22 = dVar4.b(j131);
+ dVar3.c(j127 - j11, b19 + b21);
+ dVar3.c(j127, AbstractC1518b.a(b19, b21, dVar3, j128 - j11, b20, b22));
+ dVar3.c(j128, b22 - b20);
+ j125 += j11;
+ dVar4 = dVar2;
+ j118 = j118;
+ j117 = j132;
+ }
+ j121 += j12;
+ dVar4 = dVar2;
+ }
+ j117 += j11;
+ dVar4 = dVar2;
+ }
+ }
+
+ /* JADX WARN: Removed duplicated region for block: B:132:0x0395 */
+ /* JADX WARN: Removed duplicated region for block: B:134:0x0397 */
+ /* JADX WARN: Type inference failed for: r9v7, types: [k3.g, k3.d] */
+ /*
+ Code decompiled incorrectly, please refer to instructions dump.
+ */
+ public final void k(float[] fArr, int i4) {
+ d dVar;
+ float[] fArr2;
+ int i5;
+ int i6;
+ long j4;
+ long j5;
+ k3.d dVar2;
+ long j6;
+ long j7;
+ d dVar3 = this;
+ float[] fArr3 = fArr;
+ int i7 = dVar3.f11708k;
+ int i8 = dVar3.f11700a;
+ boolean z3 = dVar3.f11709l;
+ Class cls = d.class;
+ int i9 = 4;
+ if (z3) {
+ k3.d gVar = new k3.d();
+ gVar.f = q.f12106g;
+ gVar.f12103h = 4L;
+ gVar.f12102g = fArr3.length;
+ gVar.f12096k = fArr3;
+ long j8 = i4;
+ long j9 = dVar3.f11701b;
+ if (!z3) {
+ if (j8 < 2147483647L) {
+ dVar3.k(fArr3, (int) j8);
+ } else {
+ throw new IllegalArgumentException("The data array is too big.");
+ }
+ } else {
+ long j10 = 1;
+ if (j9 != 1) {
+ int a4 = AbstractC1880e.a(i7);
+ long j11 = 0;
+ if (a4 != 0) {
+ if (a4 != 1) {
+ if (a4 == 2) {
+ long j12 = 0 * 2;
+ k3.d dVar4 = new k3.d(j12, true);
+ int i10 = k3.c.c;
+ if (i10 > 1 && j9 > 8192) {
+ if (i10 < 4 || j9 <= 65536) {
+ i9 = 2;
+ }
+ Future[] futureArr = new Future[i9];
+ long j13 = i9;
+ long j14 = j9 / j13;
+ int i11 = 0;
+ while (i11 < i9) {
+ Class cls2 = cls;
+ long j15 = i11 * j14;
+ if (i11 == i9 - 1) {
+ j7 = j9;
+ } else {
+ j7 = j15 + j14;
+ }
+ int i12 = i11;
+ k3.d dVar5 = dVar4;
+ long j16 = j8;
+ dVar3 = this;
+ j8 = j16;
+ futureArr[i12] = k3.c.a(new b(dVar3, j15, j7, j16, dVar5, gVar));
+ i11 = i12 + 1;
+ j13 = j13;
+ cls = cls2;
+ j12 = j12;
+ dVar4 = dVar5;
+ }
+ j5 = j12;
+ dVar2 = dVar4;
+ long j17 = j13;
+ Class cls3 = cls;
+ try {
+ k3.c.b(futureArr);
+ } catch (InterruptedException e4) {
+ Logger.getLogger(cls3.getName()).log(Level.SEVERE, (String) null, (Throwable) e4);
+ } catch (ExecutionException e5) {
+ Logger.getLogger(cls3.getName()).log(Level.SEVERE, (String) null, (Throwable) e5);
+ }
+ j3.c.h(j5, dVar2, dVar3.f11702d, dVar3.f11705h, dVar3.f);
+ long j18 = 0 / j17;
+ for (int i13 = 0; i13 < i9; i13++) {
+ long j19 = i13 * j18;
+ if (i13 == i9 - 1) {
+ j6 = 0;
+ } else {
+ j6 = j19 + j18;
+ }
+ futureArr[i13] = k3.c.a(new c(dVar3, j19, j6, dVar2));
+ }
+ try {
+ k3.c.b(futureArr);
+ } catch (InterruptedException e6) {
+ Logger.getLogger(cls3.getName()).log(Level.SEVERE, (String) null, (Throwable) e6);
+ } catch (ExecutionException e7) {
+ Logger.getLogger(cls3.getName()).log(Level.SEVERE, (String) null, (Throwable) e7);
+ }
+ } else {
+ j5 = j12;
+ dVar2 = dVar4;
+ if (0 >= j9) {
+ j3.c.h(j5, dVar2, dVar3.f11702d, dVar3.f11705h, dVar3.f);
+ if (0 < 0) {
+ dVar2.b(0 * 2);
+ throw null;
+ }
+ } else {
+ gVar.b(j8 + 0);
+ throw null;
+ }
+ }
+ j3.c.r(j5, dVar2, 0L, dVar3.f11702d, dVar3.f11705h, dVar3.f);
+ if (j9 % 2 == 0) {
+ throw null;
+ }
+ throw null;
+ }
+ } else {
+ if (j9 != 1) {
+ new k3.d(j9, true);
+ throw null;
+ }
+ while (true) {
+ j9--;
+ if (j9 < 2) {
+ break;
+ }
+ long j20 = j8 + j9;
+ float b4 = gVar.b(j20);
+ long j21 = j20 - 1;
+ gVar.c(j20, gVar.b(j21));
+ gVar.c(j21, b4);
+ }
+ }
+ } else {
+ long j22 = dVar3.f11701b;
+ if (j22 > 4) {
+ j3.c.r(j22, gVar, j8, dVar3.f11702d, dVar3.f11705h, dVar3.f);
+ long j23 = dVar3.f11707j;
+ k3.d dVar6 = dVar3.f;
+ long j24 = dVar3.f11705h;
+ long j25 = j9 >> 1;
+ long j26 = (j23 * 2) / j25;
+ long j27 = 2;
+ while (j27 < j25) {
+ j11 += j26;
+ long j28 = j10;
+ float b5 = 0.5f - dVar6.b((j24 + j23) - j11);
+ float b6 = dVar6.b(j24 + j11);
+ k3.d dVar7 = dVar6;
+ long j29 = j8 + j27;
+ long j30 = j8 + (j9 - j27);
+ float b7 = gVar.b(j29) - gVar.b(j30);
+ long j31 = j23;
+ long j32 = j29 + j28;
+ long j33 = j24;
+ long j34 = j30 + j28;
+ float b8 = gVar.b(j34) + gVar.b(j32);
+ float f = (b5 * b7) - (b6 * b8);
+ float f4 = (b7 * b6) + (b5 * b8);
+ gVar.c(j29, gVar.b(j29) - f);
+ gVar.c(j32, f4 - gVar.b(j32));
+ gVar.c(j30, gVar.b(j30) + f);
+ gVar.c(j34, f4 - gVar.b(j34));
+ j27 += 2;
+ j10 = j28;
+ dVar6 = dVar7;
+ j23 = j31;
+ j24 = j33;
+ }
+ j4 = j10;
+ long j35 = j8 + j25 + j4;
+ gVar.c(j35, -gVar.b(j35));
+ } else {
+ j4 = 1;
+ if (j22 == 4) {
+ long j36 = j8 + 2;
+ float b9 = gVar.b(j8) - gVar.b(j36);
+ long j37 = j8 + 1;
+ long j38 = 3 + j8;
+ float b10 = gVar.b(j38) + (-gVar.b(j37));
+ gVar.c(j8, gVar.b(j36) + gVar.b(j8));
+ gVar.c(j37, gVar.b(j38) + gVar.b(j37));
+ gVar.c(j36, b9);
+ gVar.c(j38, b10);
+ }
+ }
+ long j39 = j8 + j4;
+ float b11 = gVar.b(j8) - gVar.b(j39);
+ gVar.c(j8, gVar.b(j39) + gVar.b(j8));
+ gVar.c(j39, b11);
+ }
+ }
+ }
+ } else {
+ int i14 = 0;
+ if (i8 != 1) {
+ int a5 = AbstractC1880e.a(i7);
+ if (a5 != 0) {
+ if (a5 != 1) {
+ if (a5 == 2) {
+ int i15 = 0 * 2;
+ float[] fArr4 = new float[i15];
+ int i16 = k3.c.c;
+ if (i16 > 1) {
+ long j40 = i8;
+ if (j40 >= 8192) {
+ if (i16 < 4 || j40 < 65536) {
+ i9 = 2;
+ }
+ Future[] futureArr2 = new Future[i9];
+ int i17 = i8 / i9;
+ int i18 = 0;
+ while (i18 < i9) {
+ int i19 = i18 * i17;
+ if (i18 == i9 - 1) {
+ i6 = i8;
+ } else {
+ i6 = i19 + i17;
+ }
+ futureArr2[i18] = k3.c.a(new a(this, i19, i6, i4, fArr4, fArr3));
+ i18++;
+ fArr3 = fArr;
+ }
+ dVar = this;
+ fArr2 = fArr4;
+ try {
+ k3.c.b(futureArr2);
+ } catch (InterruptedException e8) {
+ Logger.getLogger(cls.getName()).log(Level.SEVERE, (String) null, (Throwable) e8);
+ } catch (ExecutionException e9) {
+ Logger.getLogger(cls.getName()).log(Level.SEVERE, (String) null, (Throwable) e9);
+ }
+ j3.c.g(i15, fArr2, dVar.c, dVar.f11704g, dVar.f11703e);
+ int i20 = 0 / i9;
+ for (int i21 = 0; i21 < i9; i21++) {
+ int i22 = i21 * i20;
+ if (i21 == i9 - 1) {
+ i5 = 0;
+ } else {
+ i5 = i22 + i20;
+ }
+ futureArr2[i21] = k3.c.a(new I0.d(dVar, i22, i5, fArr2));
+ }
+ try {
+ k3.c.b(futureArr2);
+ } catch (InterruptedException e10) {
+ Logger.getLogger(cls.getName()).log(Level.SEVERE, (String) null, (Throwable) e10);
+ } catch (ExecutionException e11) {
+ Logger.getLogger(cls.getName()).log(Level.SEVERE, (String) null, (Throwable) e11);
+ }
+ j3.c.q(i15, fArr2, 0, dVar.c, dVar.f11704g, dVar.f11703e);
+ if (i8 % 2 != 0) {
+ throw null;
+ }
+ throw null;
+ }
+ }
+ dVar = this;
+ fArr2 = fArr4;
+ if (i8 <= 0) {
+ j3.c.g(i15, fArr2, dVar.c, dVar.f11704g, dVar.f11703e);
+ j3.c.q(i15, fArr2, 0, dVar.c, dVar.f11704g, dVar.f11703e);
+ if (i8 % 2 != 0) {
+ }
+ } else {
+ float f5 = fArr[i4 + 0];
+ throw null;
+ }
+ }
+ }
+ } else {
+ // smali cond_22(a5==0, k=1 时运行时路径!): 单线程 FFT + 后处理
+ // jadx 原把这段错塞进 if(i8!=1) 的 else(死代码), a5==0 的 else 是幻觉(throw null)
+ int i26 = this.f11700a;
+ if (i26 > 4) {
+ j3.c.q(i26, fArr, i4, this.c, this.f11704g, this.f11703e);
+ int i27 = this.f11706i;
+ float[] fArr6 = this.f11703e;
+ int i28 = this.f11704g;
+ int i29 = i8 >> 1;
+ int i30 = (i27 * 2) / i29;
+ for (int i31 = 2; i31 < i29; i31 += 2) {
+ i14 += i30;
+ float f7 = 0.5f - fArr6[(i28 + i27) - i14];
+ float f8 = fArr6[i28 + i14];
+ int i32 = i4 + i31;
+ int i33 = i4 + (i8 - i31);
+ float f9 = fArr[i32];
+ float f10 = f9 - fArr[i33];
+ int i34 = i32 + 1;
+ int i35 = i33 + 1;
+ float f11 = fArr[i34] + fArr[i35];
+ float f12 = (f7 * f10) - (f8 * f11);
+ float f13 = (f8 * f10) + (f7 * f11);
+ fArr[i32] = f9 - f12;
+ fArr[i34] = f13 - fArr[i34];
+ fArr[i33] = fArr[i33] + f12;
+ fArr[i35] = f13 - fArr[i35];
+ }
+ int i36 = i4 + i29 + 1;
+ fArr[i36] = -fArr[i36];
+ } else if (i26 == 4) {
+ float f14 = fArr[i4];
+ int i37 = i4 + 2;
+ float f15 = fArr[i37];
+ int i38 = i4 + 1;
+ int i39 = i4 + 3;
+ float f16 = (-fArr[i38]) + fArr[i39];
+ fArr[i4] = f14 + f15;
+ fArr[i38] = fArr[i38] + fArr[i39];
+ fArr[i37] = f14 - f15;
+ fArr[i39] = f16;
+ }
+ float f17 = fArr[i4];
+ int i40 = i4 + 1;
+ float f18 = fArr[i40];
+ fArr[i4] = f17 + f18;
+ fArr[i40] = f17 - f18;
+ }
+ }
+ }
+ }
+ }
diff --git a/feature/cw/src/main/java/j1/C1646n.java b/feature/cw/src/main/java/j1/C1646n.java
new file mode 100644
index 00000000..aadaa907
--- /dev/null
+++ b/feature/cw/src/main/java/j1/C1646n.java
@@ -0,0 +1,42 @@
+package j1;
+
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import com.ve3nea.morse_expert.DecodedTextView;
+import com.ve3nea.morse_expert.ScaleView;
+import com.ve3nea.morse_expert.WaterfallSurfaceView;
+
+/**
+ * 照搬自 Morse Expert 1.15 j1.C1646n, 类名/字段名保持混淆原名。
+ * R8 合并类手术: 只保留视图持有器(6 参构造 + 5 个 View 字段);
+ * 其余 158-1278 行(广告/计费合并方法)已整段裁剪(用户要求广告不迁移)。
+ */
+public final class C1646n {
+
+ public final /* synthetic */ int f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public Object f11888g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public Object f11889h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public Object f11890i;
+
+ /* renamed from: j, reason: collision with root package name */
+ public Object f11891j;
+
+ /* renamed from: k, reason: collision with root package name */
+ public Object f11892k;
+
+ public C1646n(ConstraintLayout constraintLayout, DecodedTextView decodedTextView, ScaleView scaleView, TextView textView, LinearLayout linearLayout, WaterfallSurfaceView waterfallSurfaceView) {
+ this.f = 1;
+ this.f11888g = decodedTextView;
+ this.f11889h = scaleView;
+ this.f11890i = textView;
+ this.f11891j = linearLayout;
+ this.f11892k = waterfallSurfaceView;
+ }
+}
diff --git a/feature/cw/src/main/java/j3/a.java b/feature/cw/src/main/java/j3/a.java
new file mode 100644
index 00000000..12143462
--- /dev/null
+++ b/feature/cw/src/main/java/j3/a.java
@@ -0,0 +1,100 @@
+package j3;
+
+/* loaded from: classes.dex */
+public final class a implements Runnable {
+ public final /* synthetic */ int f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public final /* synthetic */ int f11919g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public final /* synthetic */ int f11920h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public final /* synthetic */ int f11921i;
+
+ /* renamed from: j, reason: collision with root package name */
+ public final /* synthetic */ float[] f11922j;
+
+ /* renamed from: k, reason: collision with root package name */
+ public final /* synthetic */ float[] f11923k;
+
+ /* renamed from: l, reason: collision with root package name */
+ public final /* synthetic */ int f11924l;
+
+ public /* synthetic */ a(int i4, int i5, int i6, int i7, int i8, float[] fArr, float[] fArr2) {
+ this.f = i8;
+ this.f11919g = i4;
+ this.f11920h = i5;
+ this.f11921i = i6;
+ this.f11922j = fArr;
+ this.f11923k = fArr2;
+ this.f11924l = i7;
+ }
+
+ @Override // java.lang.Runnable
+ public final void run() {
+ switch (this.f) {
+ case 0:
+ int i4 = this.f11919g;
+ int i5 = this.f11920h;
+ int i6 = i4 + i5;
+ int i7 = this.f11921i;
+ while (true) {
+ int i8 = i7;
+ if (i8 > 512) {
+ i7 = i8 >> 2;
+ c.w(i7, i6 - i7, this.f11924l - (i8 >> 3), this.f11922j, this.f11923k);
+ } else {
+ int i9 = this.f11924l;
+ float[] fArr = this.f11923k;
+ c.u(i8, 1, this.f11922j, i6 - i8, i9, fArr);
+ int i10 = i4 - i8;
+ int i11 = 0;
+ int i12 = i5 - i8;
+ while (i12 > 0) {
+ int i13 = i11 + 1;
+ int i14 = this.f11924l;
+ float[] fArr2 = this.f11923k;
+ int i15 = i12;
+ i11 = i13;
+ int i16 = this.f11924l;
+ float[] fArr3 = this.f11923k;
+ c.u(i8, c.E(i8, i12, i13, this.f11919g, i14, this.f11922j, fArr2), this.f11922j, i10 + i15, i16, fArr3);
+ i12 = i15 - i8;
+ }
+ return;
+ }
+ }
+ default:
+ int i17 = this.f11919g;
+ int i18 = this.f11920h;
+ int i19 = i17 + i18;
+ int i20 = this.f11921i;
+ int i21 = 1;
+ while (i20 > 512) {
+ i20 >>= 2;
+ i21 <<= 2;
+ c.y(i20, i19 - i20, this.f11924l - i20, this.f11922j, this.f11923k);
+ }
+ int i22 = this.f11924l;
+ float[] fArr4 = this.f11923k;
+ c.u(i20, 0, this.f11922j, i19 - i20, i22, fArr4);
+ int i23 = i21 >> 1;
+ int i24 = i17 - i20;
+ int i25 = i18 - i20;
+ while (i25 > 0) {
+ int i26 = i23 + 1;
+ int i27 = this.f11924l;
+ float[] fArr5 = this.f11923k;
+ int i28 = i25;
+ i23 = i26;
+ int i29 = this.f11924l;
+ float[] fArr6 = this.f11923k;
+ c.u(i20, c.E(i20, i25, i26, this.f11919g, i27, this.f11922j, fArr5), this.f11922j, i24 + i28, i29, fArr6);
+ i25 = i28 - i20;
+ }
+ return;
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/j3/b.java b/feature/cw/src/main/java/j3/b.java
new file mode 100644
index 00000000..b5997a2d
--- /dev/null
+++ b/feature/cw/src/main/java/j3/b.java
@@ -0,0 +1,104 @@
+package j3;
+
+import k3.d;
+
+/* loaded from: classes.dex */
+public final class b implements Runnable {
+ public final /* synthetic */ int f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public final /* synthetic */ long f11925g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public final /* synthetic */ long f11926h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public final /* synthetic */ long f11927i;
+
+ /* renamed from: j, reason: collision with root package name */
+ public final /* synthetic */ d f11928j;
+
+ /* renamed from: k, reason: collision with root package name */
+ public final /* synthetic */ d f11929k;
+
+ /* renamed from: l, reason: collision with root package name */
+ public final /* synthetic */ long f11930l;
+
+ public /* synthetic */ b(long j4, long j5, long j6, d dVar, d dVar2, long j7, int i4) {
+ this.f = i4;
+ this.f11925g = j4;
+ this.f11926h = j5;
+ this.f11927i = j6;
+ this.f11928j = dVar;
+ this.f11929k = dVar2;
+ this.f11930l = j7;
+ }
+
+ @Override // java.lang.Runnable
+ public final void run() {
+ switch (this.f) {
+ case 0:
+ long j4 = this.f11925g;
+ long j5 = this.f11926h;
+ long j6 = j4 + j5;
+ long j7 = this.f11927i;
+ while (j7 > 512) {
+ long j8 = j7 >> 2;
+ c.x(j8, j6 - j8, this.f11930l - (j7 >> 3), this.f11928j, this.f11929k);
+ j7 = j8;
+ }
+ c.v(j7, 1L, j6 - j7, this.f11930l, this.f11928j, this.f11929k);
+ long j9 = j4 - j7;
+ long j10 = j5 - j7;
+ long j11 = 0;
+ for (long j12 = 0; j10 > j12; j12 = 0) {
+ long j13 = j11 + 1;
+ long j14 = j10;
+ c.v(j7, c.F(j7, j10, j13, this.f11925g, this.f11930l, this.f11928j, this.f11929k), j9 + j14, this.f11930l, this.f11928j, this.f11929k);
+ j10 = j14 - j7;
+ j11 = j13;
+ j9 = j9;
+ }
+ return;
+ case 1:
+ long j15 = this.f11925g;
+ long j16 = this.f11926h;
+ long j17 = j15 + j16;
+ long j18 = this.f11927i;
+ long j19 = 1;
+ while (j18 > 512) {
+ long j20 = j18 >> 2;
+ j19 <<= 2;
+ c.z(j20, j17 - j20, this.f11930l - j20, this.f11928j, this.f11929k);
+ j18 = j20;
+ }
+ c.v(j18, 0L, j17 - j18, this.f11930l, this.f11928j, this.f11929k);
+ long j21 = j19 >> 1;
+ long j22 = j15 - j18;
+ long j23 = j16 - j18;
+ while (j23 > 0) {
+ long j24 = j21 + 1;
+ long j25 = j23;
+ j21 = j24;
+ c.v(j18, c.F(j18, j23, j24, this.f11925g, this.f11930l, this.f11928j, this.f11929k), j22 + j25, this.f11930l, this.f11928j, this.f11929k);
+ j23 = j25 - j18;
+ }
+ return;
+ default:
+ for (long j26 = this.f11925g; j26 < this.f11926h; j26++) {
+ this.f11928j.c(this.f11927i + j26, this.f11929k.b(this.f11930l + j26));
+ }
+ return;
+ }
+ }
+
+ public b(long j4, long j5, long j6, long j7, d dVar, d dVar2) {
+ this.f = 2;
+ this.f11925g = j4;
+ this.f11926h = j5;
+ this.f11928j = dVar;
+ this.f11927i = j6;
+ this.f11929k = dVar2;
+ this.f11930l = j7;
+ }
+}
diff --git a/feature/cw/src/main/java/j3/c.java b/feature/cw/src/main/java/j3/c.java
new file mode 100644
index 00000000..3935c4fe
--- /dev/null
+++ b/feature/cw/src/main/java/j3/c.java
@@ -0,0 +1,5783 @@
+package j3;
+
+import d1.AbstractC1518b;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import k3.d;
+import k3.s;
+
+/**
+ * 照搬自 Morse Expert 1.15 j3.c (R8 合并类), 类名保持混淆原名。
+ * 仅保留 k3 FFT 库实际调用的静态 FFT 方法 (u/v/w/x/y/z/E/F/g/h/q/r 及其辅助
+ * A/B/C/D/G/H/i/j/k/l/m/n/o/p/s/t/d/J), 其余 R8 合并的 billing/ads/TextView
+ * 兼容代码及 M.Z 接口实现已裁剪。依据: apktool smali (j3/c.smali) 静态调用关系。
+ * d 方法中 K1.a.z 的 Guava lenientFormat 以 String.format 等价替换
+ * (K1.a 已裁剪为仅保留内存统计字段)。
+ */
+public final class c {
+ public static void A(int i4, int i5, int i6, float[] fArr, float[] fArr2) {
+ int i7 = i5 + i4;
+ int i8 = i4;
+ while (i8 > 512) {
+ int i9 = i8 >> 2;
+ w(i9, i7 - i9, i6 - (i8 >> 3), fArr, fArr2);
+ i8 = i9;
+ }
+ float[] fArr3 = fArr;
+ float[] fArr4 = fArr2;
+ u(i8, 1, fArr3, i7 - i8, i6, fArr4);
+ int i10 = i5 - i8;
+ int i11 = 0;
+ int i12 = i4 - i8;
+ while (i12 > 0) {
+ i11++;
+ float[] fArr5 = fArr4;
+ float[] fArr6 = fArr3;
+ int E3 = E(i8, i12, i11, i5, i6, fArr6, fArr5);
+ int i13 = i12;
+ fArr3 = fArr6;
+ fArr4 = fArr5;
+ u(i8, E3, fArr3, i10 + i13, i6, fArr4);
+ i12 = i13 - i8;
+ }
+ }
+
+ public static void B(long j4, long j5, long j6, d dVar, d dVar2) {
+ long j7 = j5 + j4;
+ long j8 = j4;
+ while (j8 > 512) {
+ long j9 = j8 >> 2;
+ x(j9, j7 - j9, j6 - (j8 >> 3), dVar, dVar2);
+ j8 = j9;
+ }
+ v(j8, 1L, j7 - j8, j6, dVar, dVar2);
+ long j10 = j5 - j8;
+ long j11 = j4 - j8;
+ long j12 = 0;
+ while (j11 > 0) {
+ long j13 = j12 + 1;
+ long j14 = j11;
+ v(j8, F(j8, j11, j13, j5, j6, dVar, dVar2), j10 + j14, j6, dVar, dVar2);
+ j11 = j14 - j8;
+ j12 = j13;
+ }
+ }
+
+ public static void C(int i4, int i5, int i6, float[] fArr, float[] fArr2) {
+ int i7;
+ int i8;
+ int i9;
+ int i10 = i4 >> 1;
+ if (i4 >= 65536) {
+ i10 = i4 >> 2;
+ i8 = 1;
+ i7 = 4;
+ } else {
+ i7 = 2;
+ i8 = 0;
+ }
+ int i11 = i10;
+ Future[] futureArr = new Future[i7];
+ int i12 = 0;
+ for (int i13 = 0; i13 < i7; i13++) {
+ int i14 = (i13 * i11) + i5;
+ if (i13 != i8) {
+ i9 = i12 + 1;
+ futureArr[i12] = k3.c.a(new a(i14, i11, i4, i6, 0, fArr, fArr2));
+ } else {
+ i9 = i12 + 1;
+ futureArr[i12] = k3.c.a(new a(i14, i11, i4, i6, 1, fArr, fArr2));
+ }
+ i12 = i9;
+ }
+ try {
+ k3.c.b(futureArr);
+ } catch (InterruptedException e4) {
+ Logger.getLogger(c.class.getName()).log(Level.SEVERE, (String) null, (Throwable) e4);
+ } catch (ExecutionException e5) {
+ Logger.getLogger(c.class.getName()).log(Level.SEVERE, (String) null, (Throwable) e5);
+ }
+ }
+
+ public static void D(long j4, long j5, long j6, d dVar, d dVar2) {
+ long j7;
+ int i4;
+ int i5;
+ int i6 = 1;
+ long j8 = j4 >> 1;
+ if (j4 >= 65536) {
+ j7 = j4 >> 2;
+ i4 = 4;
+ } else {
+ j7 = j8;
+ i6 = 0;
+ i4 = 2;
+ }
+ Future[] futureArr = new Future[i4];
+ int i7 = 0;
+ for (int i8 = 0; i8 < i4; i8++) {
+ long j9 = (i8 * j7) + j5;
+ if (i8 != i6) {
+ i5 = i7 + 1;
+ futureArr[i7] = k3.c.a(new b(j9, j7, j4, dVar, dVar2, j6, 0));
+ } else {
+ i5 = i7 + 1;
+ futureArr[i7] = k3.c.a(new b(j9, j7, j4, dVar, dVar2, j6, 1));
+ }
+ i7 = i5;
+ }
+ try {
+ k3.c.b(futureArr);
+ } catch (InterruptedException e4) {
+ Logger.getLogger(c.class.getName()).log(Level.SEVERE, (String) null, (Throwable) e4);
+ } catch (ExecutionException e5) {
+ Logger.getLogger(c.class.getName()).log(Level.SEVERE, (String) null, (Throwable) e5);
+ }
+ }
+
+ public static int E(int i4, int i5, int i6, int i7, int i8, float[] fArr, float[] fArr2) {
+ int i9 = i7 - i4;
+ if ((i6 & 3) != 0) {
+ int i10 = i6 & 1;
+ if (i10 != 0) {
+ w(i4, i9 + i5, i8 - (i4 >> 1), fArr, fArr2);
+ return i10;
+ }
+ y(i4, i9 + i5, i8 - i4, fArr, fArr2);
+ return i10;
+ }
+ while ((i6 & 3) == 0) {
+ i4 <<= 2;
+ i6 >>= 2;
+ }
+ int i11 = i6 & 1;
+ int i12 = i7 + i5;
+ if (i11 != 0) {
+ while (i4 > 128) {
+ w(i4, i12 - i4, i8 - (i4 >> 1), fArr, fArr2);
+ i4 >>= 2;
+ }
+ } else {
+ while (i4 > 128) {
+ y(i4, i12 - i4, i8 - i4, fArr, fArr2);
+ i4 >>= 2;
+ }
+ }
+ return i11;
+ }
+
+ public static long F(long j4, long j5, long j6, long j7, long j8, d dVar, d dVar2) {
+ long j9 = j7 - j4;
+ if ((j6 & 3) != 0) {
+ long j10 = j6 & 1;
+ if (j10 != 0) {
+ x(j4, j9 + j5, j8 - (j4 >> 1), dVar, dVar2);
+ return j10;
+ }
+ z(j4, j9 + j5, j8 - j4, dVar, dVar2);
+ return j10;
+ }
+ long j11 = j4;
+ long j12 = j6;
+ while ((j12 & 3) == 0) {
+ j11 <<= 2;
+ j12 >>= 2;
+ }
+ long j13 = j12 & 1;
+ long j14 = j7 + j5;
+ if (j13 != 0) {
+ while (j11 > 128) {
+ x(j11, j14 - j11, j8 - (j11 >> 1), dVar, dVar2);
+ j11 >>= 2;
+ }
+ } else {
+ while (j11 > 128) {
+ z(j11, j14 - j11, j8 - j11, dVar, dVar2);
+ j11 >>= 2;
+ }
+ }
+ return j13;
+ }
+
+ public static void G(d dVar, long j4) {
+ long j5 = 2 + j4;
+ float b4 = dVar.b(j4) - dVar.b(j5);
+ long j6 = 1 + j4;
+ long j7 = 3 + j4;
+ float b5 = dVar.b(j6) - dVar.b(j7);
+ dVar.c(j4, dVar.b(j5) + dVar.b(j4));
+ dVar.c(j6, dVar.b(j7) + dVar.b(j6));
+ dVar.c(j5, b4);
+ dVar.c(j7, b5);
+ }
+
+ public static void H(float[] fArr, int i4) {
+ float f4 = fArr[i4];
+ int i5 = i4 + 2;
+ float f5 = fArr[i5];
+ int i6 = i4 + 1;
+ int i7 = i4 + 3;
+ float f6 = fArr[i6] - fArr[i7];
+ fArr[i4] = f4 + f5;
+ fArr[i6] = fArr[i6] + fArr[i7];
+ fArr[i5] = f4 - f5;
+ fArr[i7] = f6;
+ }
+
+ public static void J(int i4) {
+ if (i4 >= 0) {
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public static String d(int i4, int i5, String str) {
+ if (i4 < 0) {
+ return String.format("%s (%s) must not be negative", str, Integer.valueOf(i4));
+ }
+ if (i5 >= 0) {
+ return String.format("%s (%s) must not be greater than size (%s)", str, Integer.valueOf(i4), Integer.valueOf(i5));
+ }
+ throw new IllegalArgumentException(AbstractC1518b.d("negative size: ", i5));
+ }
+
+ public static void g(int i4, float[] fArr, int[] iArr, int i5, float[] fArr2) {
+ if (i4 <= 8) {
+ if (i4 != 8) {
+ if (i4 == 4) {
+ H(fArr, 0);
+ return;
+ }
+ return;
+ }
+ float f4 = fArr[0];
+ float f5 = fArr[4];
+ float f6 = f4 + f5;
+ float f7 = fArr[1];
+ float f8 = fArr[5];
+ float f9 = f7 + f8;
+ float f10 = f4 - f5;
+ float f11 = f7 - f8;
+ float f12 = fArr[2];
+ float f13 = fArr[6];
+ float f14 = f12 + f13;
+ float f15 = fArr[3];
+ float f16 = fArr[7];
+ float f17 = f15 + f16;
+ float f18 = f12 - f13;
+ float f19 = f15 - f16;
+ fArr[0] = f6 + f14;
+ fArr[1] = f9 + f17;
+ fArr[2] = f10 + f19;
+ fArr[3] = f11 - f18;
+ fArr[4] = f6 - f14;
+ fArr[5] = f9 - f17;
+ fArr[6] = f10 - f19;
+ fArr[7] = f11 + f18;
+ return;
+ }
+ if (i4 <= 32) {
+ if (i4 == 32) {
+ n(fArr, 0, fArr2, i5 - 8);
+ float f20 = fArr[2];
+ float f21 = fArr[3];
+ float f22 = fArr[4];
+ float f23 = fArr[5];
+ float f24 = fArr[6];
+ float f25 = fArr[7];
+ float f26 = fArr[8];
+ float f27 = fArr[9];
+ float f28 = fArr[10];
+ float f29 = fArr[11];
+ float f30 = fArr[12];
+ float f31 = fArr[13];
+ float f32 = fArr[14];
+ float f33 = fArr[15];
+ float f34 = fArr[16];
+ float f35 = fArr[17];
+ float f36 = fArr[18];
+ float f37 = fArr[19];
+ float f38 = fArr[20];
+ float f39 = fArr[21];
+ float f40 = fArr[22];
+ float f41 = fArr[23];
+ float f42 = fArr[24];
+ float f43 = fArr[25];
+ float f44 = fArr[26];
+ float f45 = fArr[27];
+ float f46 = fArr[28];
+ float f47 = fArr[29];
+ float f48 = fArr[30];
+ float f49 = fArr[31];
+ fArr[2] = f48;
+ fArr[3] = f49;
+ fArr[4] = f32;
+ fArr[5] = f33;
+ fArr[6] = f40;
+ fArr[7] = f41;
+ fArr[8] = f24;
+ fArr[9] = f25;
+ fArr[10] = f44;
+ fArr[11] = f45;
+ fArr[12] = f28;
+ fArr[13] = f29;
+ fArr[14] = f36;
+ fArr[15] = f37;
+ fArr[16] = f20;
+ fArr[17] = f21;
+ fArr[18] = f46;
+ fArr[19] = f47;
+ fArr[20] = f30;
+ fArr[21] = f31;
+ fArr[22] = f38;
+ fArr[23] = f39;
+ fArr[24] = f22;
+ fArr[25] = f23;
+ fArr[26] = f42;
+ fArr[27] = f43;
+ fArr[28] = f26;
+ fArr[29] = f27;
+ fArr[30] = f34;
+ fArr[31] = f35;
+ return;
+ }
+ j(fArr, 0, fArr2, 0);
+ float f50 = fArr[2];
+ float f51 = fArr[3];
+ float f52 = fArr[4];
+ float f53 = fArr[5];
+ float f54 = fArr[6];
+ float f55 = fArr[7];
+ float f56 = fArr[8];
+ float f57 = fArr[9];
+ float f58 = fArr[10];
+ float f59 = fArr[11];
+ float f60 = fArr[12];
+ float f61 = fArr[13];
+ float f62 = fArr[14];
+ float f63 = fArr[15];
+ fArr[2] = f62;
+ fArr[3] = f63;
+ fArr[4] = f54;
+ fArr[5] = f55;
+ fArr[6] = f58;
+ fArr[7] = f59;
+ fArr[8] = f50;
+ fArr[9] = f51;
+ fArr[10] = f60;
+ fArr[11] = f61;
+ fArr[12] = f52;
+ fArr[13] = f53;
+ fArr[14] = f56;
+ fArr[15] = f57;
+ return;
+ }
+ int i6 = i4 >> 2;
+ int i7 = i5 - i6;
+ int i8 = i4 >> 3;
+ int i9 = i8 * 2;
+ int i10 = i9 + i9;
+ int i11 = i10 + i9;
+ float f64 = fArr[0];
+ float f65 = fArr[i10];
+ float f66 = f64 + f65;
+ float f67 = -fArr[1];
+ int i12 = i10 + 1;
+ float f68 = fArr[i12];
+ float f69 = f67 - f68;
+ float f70 = f64 - f65;
+ float f71 = f67 + f68;
+ float f72 = fArr[i9];
+ float f73 = fArr[i11];
+ float f74 = f72 + f73;
+ int i13 = i9 + 1;
+ float f75 = fArr[i13];
+ int i14 = i11 + 1;
+ float f76 = fArr[i14];
+ float f77 = f75 + f76;
+ float f78 = f72 - f73;
+ float f79 = f75 - f76;
+ fArr[0] = f66 + f74;
+ fArr[1] = f69 - f77;
+ fArr[i9] = f66 - f74;
+ fArr[i13] = f69 + f77;
+ fArr[i10] = f70 + f79;
+ fArr[i12] = f71 + f78;
+ fArr[i11] = f70 - f79;
+ fArr[i14] = f71 - f78;
+ float f80 = fArr2[i7 + 1];
+ float f81 = fArr2[i7 + 2];
+ float f82 = fArr2[i7 + 3];
+ float f83 = 1.0f;
+ int i15 = 2;
+ float f84 = 1.0f;
+ float f85 = 0.0f;
+ float f86 = 0.0f;
+ int i16 = 0;
+ while (i15 < i8 - 2) {
+ i16 += 4;
+ int i17 = i7 + i16;
+ float f87 = fArr2[i17];
+ float f88 = (f83 + f87) * f81;
+ float f89 = fArr2[i17 + 1];
+ float f90 = (f85 + f89) * f81;
+ float f91 = fArr2[i17 + 2];
+ float f92 = (f84 + f91) * f82;
+ float f93 = fArr2[i17 + 3];
+ float f94 = (f86 + f93) * f82;
+ int i18 = i15 + i9;
+ int i19 = i18 + i9;
+ int i20 = i19 + i9;
+ float f95 = fArr[i15];
+ float f96 = fArr[i19];
+ float f97 = f95 + f96;
+ int i21 = i15 + 1;
+ float f98 = -fArr[i21];
+ int i22 = i19 + 1;
+ float f99 = fArr[i22];
+ float f100 = f98 - f99;
+ float f101 = f95 - f96;
+ float f102 = f98 + f99;
+ int i23 = i15 + 2;
+ float f103 = fArr[i23];
+ int i24 = i19 + 2;
+ float f104 = fArr[i24];
+ float f105 = f103 + f104;
+ int i25 = i15 + 3;
+ float f106 = -fArr[i25];
+ int i26 = i19 + 3;
+ float f107 = fArr[i26];
+ float f108 = f106 - f107;
+ float f109 = f103 - f104;
+ float f110 = f106 + f107;
+ float f111 = fArr[i18];
+ float f112 = fArr[i20];
+ float f113 = f111 + f112;
+ int i27 = i18 + 1;
+ float f114 = fArr[i27];
+ int i28 = i20 + 1;
+ float f115 = fArr[i28];
+ float f116 = f114 + f115;
+ float f117 = f111 - f112;
+ float f118 = f114 - f115;
+ int i29 = i18 + 2;
+ float f119 = fArr[i29];
+ int i30 = i20 + 2;
+ float f120 = fArr[i30];
+ float f121 = f119 + f120;
+ int i31 = i18 + 3;
+ float f122 = fArr[i31];
+ int i32 = i20 + 3;
+ float f123 = fArr[i32];
+ float f124 = f122 + f123;
+ float f125 = f119 - f120;
+ float f126 = f122 - f123;
+ fArr[i15] = f97 + f113;
+ fArr[i21] = f100 - f116;
+ fArr[i23] = f105 + f121;
+ fArr[i25] = f108 - f124;
+ fArr[i18] = f97 - f113;
+ fArr[i27] = f100 + f116;
+ fArr[i29] = f105 - f121;
+ fArr[i31] = f108 + f124;
+ float f127 = f101 + f118;
+ float f128 = f102 + f117;
+ fArr[i19] = (f88 * f127) - (f90 * f128);
+ fArr[i22] = (f127 * f90) + (f128 * f88);
+ float f129 = f109 + f126;
+ float f130 = f110 + f125;
+ fArr[i24] = (f87 * f129) - (f89 * f130);
+ fArr[i26] = (f129 * f89) + (f130 * f87);
+ float f131 = f101 - f118;
+ float f132 = f102 - f117;
+ fArr[i20] = (f94 * f132) + (f92 * f131);
+ fArr[i28] = (f132 * f92) - (f131 * f94);
+ float f133 = f109 - f126;
+ float f134 = f110 - f125;
+ fArr[i30] = (f93 * f134) + (f91 * f133);
+ fArr[i32] = (f134 * f91) - (f133 * f93);
+ int i33 = i9 - i15;
+ int i34 = i33 + i9;
+ int i35 = i34 + i9;
+ int i36 = i35 + i9;
+ float f135 = fArr[i33];
+ float f136 = fArr[i35];
+ float f137 = f135 + f136;
+ int i37 = i33 + 1;
+ float f138 = -fArr[i37];
+ int i38 = i35 + 1;
+ float f139 = fArr[i38];
+ float f140 = f138 - f139;
+ float f141 = f135 - f136;
+ float f142 = f138 + f139;
+ int i39 = i33 - 2;
+ float f143 = fArr[i39];
+ int i40 = i35 - 2;
+ float f144 = fArr[i40];
+ float f145 = f143 + f144;
+ int i41 = i33 - 1;
+ float f146 = -fArr[i41];
+ int i42 = i35 - 1;
+ float f147 = fArr[i42];
+ float f148 = f146 - f147;
+ float f149 = f143 - f144;
+ float f150 = f146 + f147;
+ float f151 = fArr[i34];
+ float f152 = fArr[i36];
+ float f153 = f151 + f152;
+ int i43 = i34 + 1;
+ float f154 = fArr[i43];
+ int i44 = i36 + 1;
+ float f155 = fArr[i44];
+ float f156 = f154 + f155;
+ float f157 = f151 - f152;
+ float f158 = f154 - f155;
+ int i45 = i34 - 2;
+ float f159 = fArr[i45];
+ int i46 = i36 - 2;
+ float f160 = fArr[i46];
+ float f161 = f159 + f160;
+ int i47 = i34 - 1;
+ float f162 = fArr[i47];
+ int i48 = i36 - 1;
+ float f163 = fArr[i48];
+ float f164 = f162 + f163;
+ float f165 = f159 - f160;
+ float f166 = f162 - f163;
+ fArr[i33] = f137 + f153;
+ fArr[i37] = f140 - f156;
+ fArr[i39] = f145 + f161;
+ fArr[i41] = f148 - f164;
+ fArr[i34] = f137 - f153;
+ fArr[i43] = f140 + f156;
+ fArr[i45] = f145 - f161;
+ fArr[i47] = f148 + f164;
+ float f167 = f141 + f158;
+ float f168 = f142 + f157;
+ fArr[i35] = (f90 * f167) - (f88 * f168);
+ fArr[i38] = (f88 * f167) + (f90 * f168);
+ float f169 = f149 + f166;
+ float f170 = f150 + f165;
+ fArr[i40] = (f89 * f169) - (f87 * f170);
+ fArr[i42] = (f169 * f87) + (f170 * f89);
+ float f171 = f141 - f158;
+ float f172 = f142 - f157;
+ fArr[i36] = (f92 * f172) + (f94 * f171);
+ fArr[i44] = (f94 * f172) - (f92 * f171);
+ float f173 = f149 - f166;
+ float f174 = f150 - f165;
+ fArr[i46] = (f91 * f174) + (f93 * f173);
+ fArr[i48] = (f174 * f93) - (f173 * f91);
+ i15 += 4;
+ f86 = f93;
+ f83 = f87;
+ f85 = f89;
+ f84 = f91;
+ }
+ float f175 = (f83 + f80) * f81;
+ float f176 = (f85 + f80) * f81;
+ float f177 = (f84 - f80) * f82;
+ float f178 = (f86 - f80) * f82;
+ int i49 = i8 + i9;
+ int i50 = i49 + i9;
+ int i51 = i9 + i50;
+ int i52 = i8 - 2;
+ float f179 = fArr[i52];
+ int i53 = i50 - 2;
+ float f180 = fArr[i53];
+ float f181 = f179 + f180;
+ int i54 = i8 - 1;
+ float f182 = -fArr[i54];
+ int i55 = i50 - 1;
+ float f183 = fArr[i55];
+ float f184 = f182 - f183;
+ float f185 = f179 - f180;
+ float f186 = f182 + f183;
+ int i56 = i49 - 2;
+ float f187 = fArr[i56];
+ int i57 = i51 - 2;
+ float f188 = fArr[i57];
+ float f189 = f187 + f188;
+ int i58 = i49 - 1;
+ float f190 = fArr[i58];
+ int i59 = i51 - 1;
+ float f191 = fArr[i59];
+ float f192 = f190 + f191;
+ float f193 = f187 - f188;
+ float f194 = f190 - f191;
+ fArr[i52] = f181 + f189;
+ fArr[i54] = f184 - f192;
+ fArr[i56] = f181 - f189;
+ fArr[i58] = f184 + f192;
+ float f195 = f185 + f194;
+ float f196 = f186 + f193;
+ fArr[i53] = (f175 * f195) - (f176 * f196);
+ fArr[i55] = (f195 * f176) + (f196 * f175);
+ float f197 = f185 - f194;
+ float f198 = f186 - f193;
+ fArr[i57] = (f178 * f198) + (f177 * f197);
+ fArr[i59] = (f198 * f177) - (f197 * f178);
+ float f199 = fArr[i8];
+ float f200 = fArr[i50];
+ float f201 = f199 + f200;
+ int i60 = i8 + 1;
+ float f202 = -fArr[i60];
+ int i61 = i50 + 1;
+ float f203 = fArr[i61];
+ float f204 = f202 - f203;
+ float f205 = f199 - f200;
+ float f206 = f202 + f203;
+ float f207 = fArr[i49];
+ float f208 = fArr[i51];
+ float f209 = f207 + f208;
+ int i62 = i49 + 1;
+ float f210 = fArr[i62];
+ int i63 = i51 + 1;
+ float f211 = fArr[i63];
+ float f212 = f210 + f211;
+ float f213 = f207 - f208;
+ float f214 = f210 - f211;
+ fArr[i8] = f201 + f209;
+ fArr[i60] = f204 - f212;
+ fArr[i49] = f201 - f209;
+ fArr[i62] = f204 + f212;
+ float f215 = f205 + f214;
+ float f216 = f206 + f213;
+ fArr[i50] = (f215 - f216) * f80;
+ fArr[i61] = (f216 + f215) * f80;
+ float f217 = f205 - f214;
+ float f218 = f206 - f213;
+ float f219 = -f80;
+ fArr[i51] = (f217 + f218) * f219;
+ fArr[i63] = (f218 - f217) * f219;
+ int i64 = i8 + 2;
+ float f220 = fArr[i64];
+ int i65 = i50 + 2;
+ float f221 = fArr[i65];
+ float f222 = f220 + f221;
+ int i66 = i8 + 3;
+ float f223 = -fArr[i66];
+ int i67 = i50 + 3;
+ float f224 = fArr[i67];
+ float f225 = f223 - f224;
+ float f226 = f220 - f221;
+ float f227 = f223 + f224;
+ int i68 = i49 + 2;
+ float f228 = fArr[i68];
+ int i69 = i51 + 2;
+ float f229 = fArr[i69];
+ float f230 = f228 + f229;
+ int i70 = i49 + 3;
+ float f231 = fArr[i70];
+ int i71 = i51 + 3;
+ float f232 = fArr[i71];
+ float f233 = f231 + f232;
+ float f234 = f228 - f229;
+ float f235 = f231 - f232;
+ fArr[i64] = f222 + f230;
+ fArr[i66] = f225 - f233;
+ fArr[i68] = f222 - f230;
+ fArr[i70] = f225 + f233;
+ float f236 = f226 + f235;
+ float f237 = f227 + f234;
+ fArr[i65] = (f176 * f236) - (f175 * f237);
+ fArr[i67] = (f175 * f236) + (f176 * f237);
+ float f238 = f226 - f235;
+ float f239 = f227 - f234;
+ fArr[i69] = (f177 * f239) + (f178 * f238);
+ fArr[i71] = (f178 * f239) - (f177 * f238);
+ if (k3.c.c > 1 && i4 >= 8192) {
+ C(i4, 0, i5, fArr, fArr2);
+ } else if (i4 > 512) {
+ A(i4, 0, i5, fArr, fArr2);
+ } else if (i4 > 128) {
+ u(i4, 1, fArr, 0, i5, fArr2);
+ } else {
+ s(i4, 0, i5, fArr, fArr2);
+ }
+ int i72 = 1;
+ while (i6 > 8) {
+ i72 <<= 1;
+ i6 >>= 2;
+ }
+ int i73 = i4 >> 1;
+ int i74 = i72 * 4;
+ if (i6 != 8) {
+ for (int i75 = 0; i75 < i72; i75++) {
+ int i76 = i75 * 4;
+ for (int i77 = 0; i77 < i75; i77++) {
+ int i78 = (i77 * 4) + iArr[i72 + i75];
+ int i79 = iArr[i72 + i77] + i76;
+ float f240 = fArr[i78];
+ int i80 = i78 + 1;
+ float f241 = -fArr[i80];
+ float f242 = fArr[i79];
+ int i81 = i79 + 1;
+ float f243 = -fArr[i81];
+ fArr[i78] = f242;
+ fArr[i80] = f243;
+ fArr[i79] = f240;
+ fArr[i81] = f241;
+ int i82 = i78 + i74;
+ int i83 = i79 + i74;
+ float f244 = fArr[i82];
+ int i84 = i82 + 1;
+ float f245 = -fArr[i84];
+ float f246 = fArr[i83];
+ int i85 = i83 + 1;
+ float f247 = -fArr[i85];
+ fArr[i82] = f246;
+ fArr[i84] = f247;
+ fArr[i83] = f244;
+ fArr[i85] = f245;
+ int i86 = i82 + i73;
+ int i87 = i83 + 2;
+ float f248 = fArr[i86];
+ int i88 = i86 + 1;
+ float f249 = -fArr[i88];
+ float f250 = fArr[i87];
+ int i89 = i83 + 3;
+ float f251 = -fArr[i89];
+ fArr[i86] = f250;
+ fArr[i88] = f251;
+ fArr[i87] = f248;
+ fArr[i89] = f249;
+ int i90 = i86 - i74;
+ int i91 = i87 - i74;
+ float f252 = fArr[i90];
+ int i92 = i90 + 1;
+ float f253 = -fArr[i92];
+ float f254 = fArr[i91];
+ int i93 = i91 + 1;
+ float f255 = -fArr[i93];
+ fArr[i90] = f254;
+ fArr[i92] = f255;
+ fArr[i91] = f252;
+ fArr[i93] = f253;
+ int i94 = i90 + 2;
+ int i95 = i91 + i73;
+ float f256 = fArr[i94];
+ int i96 = i90 + 3;
+ float f257 = -fArr[i96];
+ float f258 = fArr[i95];
+ int i97 = i95 + 1;
+ float f259 = -fArr[i97];
+ fArr[i94] = f258;
+ fArr[i96] = f259;
+ fArr[i95] = f256;
+ fArr[i97] = f257;
+ int i98 = i94 + i74;
+ int i99 = i95 + i74;
+ float f260 = fArr[i98];
+ int i100 = i98 + 1;
+ float f261 = -fArr[i100];
+ float f262 = fArr[i99];
+ int i101 = i99 + 1;
+ float f263 = -fArr[i101];
+ fArr[i98] = f262;
+ fArr[i100] = f263;
+ fArr[i99] = f260;
+ fArr[i101] = f261;
+ int i102 = i98 - i73;
+ int i103 = i99 - 2;
+ float f264 = fArr[i102];
+ int i104 = i102 + 1;
+ float f265 = -fArr[i104];
+ float f266 = fArr[i103];
+ int i105 = i99 - 1;
+ float f267 = -fArr[i105];
+ fArr[i102] = f266;
+ fArr[i104] = f267;
+ fArr[i103] = f264;
+ fArr[i105] = f265;
+ int i106 = i102 - i74;
+ int i107 = i103 - i74;
+ float f268 = fArr[i106];
+ int i108 = i106 + 1;
+ float f269 = -fArr[i108];
+ float f270 = fArr[i107];
+ int i109 = i107 + 1;
+ float f271 = -fArr[i109];
+ fArr[i106] = f270;
+ fArr[i108] = f271;
+ fArr[i107] = f268;
+ fArr[i109] = f269;
+ }
+ int i110 = i76 + iArr[i72 + i75];
+ int i111 = i110 + 2;
+ int i112 = i110 + i73;
+ int i113 = i110 + 1;
+ fArr[i113] = -fArr[i113];
+ float f272 = fArr[i111];
+ int i114 = i110 + 3;
+ float f273 = -fArr[i114];
+ float f274 = fArr[i112];
+ int i115 = i112 + 1;
+ float f275 = -fArr[i115];
+ fArr[i111] = f274;
+ fArr[i114] = f275;
+ fArr[i112] = f272;
+ fArr[i115] = f273;
+ int i116 = i112 + 3;
+ fArr[i116] = -fArr[i116];
+ int i117 = i111 + i74;
+ int i118 = i112 + i74;
+ int i119 = i117 - 1;
+ fArr[i119] = -fArr[i119];
+ float f276 = fArr[i117];
+ int i120 = i117 + 1;
+ float f277 = -fArr[i120];
+ float f278 = fArr[i118];
+ int i121 = i118 + 1;
+ float f279 = -fArr[i121];
+ fArr[i117] = f278;
+ fArr[i120] = f279;
+ fArr[i118] = f276;
+ fArr[i121] = f277;
+ int i122 = i118 + 3;
+ fArr[i122] = -fArr[i122];
+ }
+ return;
+ }
+ for (int i123 = 0; i123 < i72; i123++) {
+ int i124 = i123 * 4;
+ for (int i125 = 0; i125 < i123; i125++) {
+ int i126 = (iArr[i72 + i123] * 2) + (i125 * 4);
+ int i127 = (iArr[i72 + i125] * 2) + i124;
+ float f280 = fArr[i126];
+ int i128 = i126 + 1;
+ float f281 = -fArr[i128];
+ float f282 = fArr[i127];
+ int i129 = i127 + 1;
+ float f283 = -fArr[i129];
+ fArr[i126] = f282;
+ fArr[i128] = f283;
+ fArr[i127] = f280;
+ fArr[i129] = f281;
+ int i130 = i126 + i74;
+ int i131 = i72 * 8;
+ int i132 = i127 + i131;
+ float f284 = fArr[i130];
+ int i133 = i130 + 1;
+ float f285 = -fArr[i133];
+ float f286 = fArr[i132];
+ int i134 = i132 + 1;
+ float f287 = -fArr[i134];
+ fArr[i130] = f286;
+ fArr[i133] = f287;
+ fArr[i132] = f284;
+ fArr[i134] = f285;
+ int i135 = i130 + i74;
+ int i136 = i132 - i74;
+ float f288 = fArr[i135];
+ int i137 = i135 + 1;
+ float f289 = -fArr[i137];
+ float f290 = fArr[i136];
+ int i138 = i136 + 1;
+ float f291 = -fArr[i138];
+ fArr[i135] = f290;
+ fArr[i137] = f291;
+ fArr[i136] = f288;
+ fArr[i138] = f289;
+ int i139 = i135 + i74;
+ int i140 = i136 + i131;
+ float f292 = fArr[i139];
+ int i141 = i139 + 1;
+ float f293 = -fArr[i141];
+ float f294 = fArr[i140];
+ int i142 = i140 + 1;
+ float f295 = -fArr[i142];
+ fArr[i139] = f294;
+ fArr[i141] = f295;
+ fArr[i140] = f292;
+ fArr[i142] = f293;
+ int i143 = i139 + i73;
+ int i144 = i140 + 2;
+ float f296 = fArr[i143];
+ int i145 = i143 + 1;
+ float f297 = -fArr[i145];
+ float f298 = fArr[i144];
+ int i146 = i140 + 3;
+ float f299 = -fArr[i146];
+ fArr[i143] = f298;
+ fArr[i145] = f299;
+ fArr[i144] = f296;
+ fArr[i146] = f297;
+ int i147 = i143 - i74;
+ int i148 = i144 - i131;
+ float f300 = fArr[i147];
+ int i149 = i147 + 1;
+ float f301 = -fArr[i149];
+ float f302 = fArr[i148];
+ int i150 = i148 + 1;
+ float f303 = -fArr[i150];
+ fArr[i147] = f302;
+ fArr[i149] = f303;
+ fArr[i148] = f300;
+ fArr[i150] = f301;
+ int i151 = i147 - i74;
+ int i152 = i148 + i74;
+ float f304 = fArr[i151];
+ int i153 = i151 + 1;
+ float f305 = -fArr[i153];
+ float f306 = fArr[i152];
+ int i154 = i152 + 1;
+ float f307 = -fArr[i154];
+ fArr[i151] = f306;
+ fArr[i153] = f307;
+ fArr[i152] = f304;
+ fArr[i154] = f305;
+ int i155 = i151 - i74;
+ int i156 = i152 - i131;
+ float f308 = fArr[i155];
+ int i157 = i155 + 1;
+ float f309 = -fArr[i157];
+ float f310 = fArr[i156];
+ int i158 = i156 + 1;
+ float f311 = -fArr[i158];
+ fArr[i155] = f310;
+ fArr[i157] = f311;
+ fArr[i156] = f308;
+ fArr[i158] = f309;
+ int i159 = i155 + 2;
+ int i160 = i156 + i73;
+ float f312 = fArr[i159];
+ int i161 = i155 + 3;
+ float f313 = -fArr[i161];
+ float f314 = fArr[i160];
+ int i162 = i160 + 1;
+ float f315 = -fArr[i162];
+ fArr[i159] = f314;
+ fArr[i161] = f315;
+ fArr[i160] = f312;
+ fArr[i162] = f313;
+ int i163 = i159 + i74;
+ int i164 = i160 + i131;
+ float f316 = fArr[i163];
+ int i165 = i163 + 1;
+ float f317 = -fArr[i165];
+ float f318 = fArr[i164];
+ int i166 = i164 + 1;
+ float f319 = -fArr[i166];
+ fArr[i163] = f318;
+ fArr[i165] = f319;
+ fArr[i164] = f316;
+ fArr[i166] = f317;
+ int i167 = i163 + i74;
+ int i168 = i164 - i74;
+ float f320 = fArr[i167];
+ int i169 = i167 + 1;
+ float f321 = -fArr[i169];
+ float f322 = fArr[i168];
+ int i170 = i168 + 1;
+ float f323 = -fArr[i170];
+ fArr[i167] = f322;
+ fArr[i169] = f323;
+ fArr[i168] = f320;
+ fArr[i170] = f321;
+ int i171 = i167 + i74;
+ int i172 = i168 + i131;
+ float f324 = fArr[i171];
+ int i173 = i171 + 1;
+ float f325 = -fArr[i173];
+ float f326 = fArr[i172];
+ int i174 = i172 + 1;
+ float f327 = -fArr[i174];
+ fArr[i171] = f326;
+ fArr[i173] = f327;
+ fArr[i172] = f324;
+ fArr[i174] = f325;
+ int i175 = i171 - i73;
+ int i176 = i172 - 2;
+ float f328 = fArr[i175];
+ int i177 = i175 + 1;
+ float f329 = -fArr[i177];
+ float f330 = fArr[i176];
+ int i178 = i172 - 1;
+ float f331 = -fArr[i178];
+ fArr[i175] = f330;
+ fArr[i177] = f331;
+ fArr[i176] = f328;
+ fArr[i178] = f329;
+ int i179 = i175 - i74;
+ int i180 = i176 - i131;
+ float f332 = fArr[i179];
+ int i181 = i179 + 1;
+ float f333 = -fArr[i181];
+ float f334 = fArr[i180];
+ int i182 = i180 + 1;
+ float f335 = -fArr[i182];
+ fArr[i179] = f334;
+ fArr[i181] = f335;
+ fArr[i180] = f332;
+ fArr[i182] = f333;
+ int i183 = i179 - i74;
+ int i184 = i180 + i74;
+ float f336 = fArr[i183];
+ int i185 = i183 + 1;
+ float f337 = -fArr[i185];
+ float f338 = fArr[i184];
+ int i186 = i184 + 1;
+ float f339 = -fArr[i186];
+ fArr[i183] = f338;
+ fArr[i185] = f339;
+ fArr[i184] = f336;
+ fArr[i186] = f337;
+ int i187 = i183 - i74;
+ int i188 = i184 - i131;
+ float f340 = fArr[i187];
+ int i189 = i187 + 1;
+ float f341 = -fArr[i189];
+ float f342 = fArr[i188];
+ int i190 = i188 + 1;
+ float f343 = -fArr[i190];
+ fArr[i187] = f342;
+ fArr[i189] = f343;
+ fArr[i188] = f340;
+ fArr[i190] = f341;
+ }
+ int i191 = (iArr[i72 + i123] * 2) + i124;
+ int i192 = i191 + 2;
+ int i193 = i191 + i73;
+ int i194 = i191 + 1;
+ fArr[i194] = -fArr[i194];
+ float f344 = fArr[i192];
+ int i195 = i191 + 3;
+ float f345 = -fArr[i195];
+ float f346 = fArr[i193];
+ int i196 = i193 + 1;
+ float f347 = -fArr[i196];
+ fArr[i192] = f346;
+ fArr[i195] = f347;
+ fArr[i193] = f344;
+ fArr[i196] = f345;
+ int i197 = i193 + 3;
+ fArr[i197] = -fArr[i197];
+ int i198 = i192 + i74;
+ int i199 = i72 * 8;
+ int i200 = i193 + i199;
+ float f348 = fArr[i198];
+ int i201 = i198 + 1;
+ float f349 = -fArr[i201];
+ float f350 = fArr[i200];
+ int i202 = i200 + 1;
+ float f351 = -fArr[i202];
+ fArr[i198] = f350;
+ fArr[i201] = f351;
+ fArr[i200] = f348;
+ fArr[i202] = f349;
+ int i203 = i198 + i74;
+ int i204 = i200 - i74;
+ float f352 = fArr[i203];
+ int i205 = i203 + 1;
+ float f353 = -fArr[i205];
+ float f354 = fArr[i204];
+ int i206 = i204 + 1;
+ float f355 = -fArr[i206];
+ fArr[i203] = f354;
+ fArr[i205] = f355;
+ fArr[i204] = f352;
+ fArr[i206] = f353;
+ int i207 = i203 - 2;
+ int i208 = i204 - i73;
+ float f356 = fArr[i207];
+ int i209 = i203 - 1;
+ float f357 = -fArr[i209];
+ float f358 = fArr[i208];
+ int i210 = i208 + 1;
+ float f359 = -fArr[i210];
+ fArr[i207] = f358;
+ fArr[i209] = f359;
+ fArr[i208] = f356;
+ fArr[i210] = f357;
+ int i211 = i73 + 2;
+ int i212 = i207 + i211;
+ int i213 = i208 + i211;
+ float f360 = fArr[i212];
+ int i214 = i212 + 1;
+ float f361 = -fArr[i214];
+ float f362 = fArr[i213];
+ int i215 = i213 + 1;
+ float f363 = -fArr[i215];
+ fArr[i212] = f362;
+ fArr[i214] = f363;
+ fArr[i213] = f360;
+ fArr[i215] = f361;
+ int i216 = i212 - (i73 - i74);
+ int i217 = (i199 - 2) + i213;
+ int i218 = i216 - 1;
+ fArr[i218] = -fArr[i218];
+ float f364 = fArr[i216];
+ int i219 = i216 + 1;
+ float f365 = -fArr[i219];
+ float f366 = fArr[i217];
+ int i220 = i217 + 1;
+ float f367 = -fArr[i220];
+ fArr[i216] = f366;
+ fArr[i219] = f367;
+ fArr[i217] = f364;
+ fArr[i220] = f365;
+ int i221 = i217 + 3;
+ fArr[i221] = -fArr[i221];
+ }
+ }
+
+ public static void h(long j4, d dVar, s sVar, long j5, d dVar2) {
+ d dVar3;
+ d dVar4 = dVar2;
+ if (j4 <= 8) {
+ if (j4 != 8) {
+ if (j4 == 4) {
+ G(dVar, 0L);
+ return;
+ }
+ return;
+ }
+ float b4 = dVar.b(0L) + dVar.b(4L);
+ float b5 = dVar.b(5L) + dVar.b(1L);
+ float b6 = dVar.b(0L) - dVar.b(4L);
+ float b7 = dVar.b(1L) - dVar.b(5L);
+ float b8 = dVar.b(2L) + dVar.b(6L);
+ float b9 = dVar.b(7L) + dVar.b(3L);
+ float b10 = dVar.b(2L) - dVar.b(6L);
+ float b11 = dVar.b(3L) - dVar.b(7L);
+ dVar.c(1L, AbstractC1518b.j(b4, b8, dVar, 0L, b5, b9));
+ dVar.c(3L, AbstractC1518b.m(b6, b11, dVar, 2L, b7, b10));
+ dVar.c(5L, AbstractC1518b.l(b4, b8, dVar, 4L, b5, b9));
+ dVar.c(7L, AbstractC1518b.a(b6, b11, dVar, 6L, b7, b10));
+ return;
+ }
+ if (j4 <= 32) {
+ if (j4 == 32) {
+ m(dVar, 0L, dVar2, j5 - 8);
+ float b12 = dVar.b(2L);
+ float b13 = dVar.b(3L);
+ float b14 = dVar.b(4L);
+ float b15 = dVar.b(5L);
+ float b16 = dVar.b(6L);
+ float b17 = dVar.b(7L);
+ float b18 = dVar.b(8L);
+ float b19 = dVar.b(9L);
+ float b20 = dVar.b(10L);
+ float b21 = dVar.b(11L);
+ float b22 = dVar.b(12L);
+ float b23 = dVar.b(13L);
+ float b24 = dVar.b(14L);
+ float b25 = dVar.b(15L);
+ float b26 = dVar.b(16L);
+ float b27 = dVar.b(17L);
+ float b28 = dVar.b(18L);
+ float b29 = dVar.b(19L);
+ float b30 = dVar.b(20L);
+ float b31 = dVar.b(21L);
+ float b32 = dVar.b(22L);
+ float b33 = dVar.b(23L);
+ float b34 = dVar.b(24L);
+ float b35 = dVar.b(25L);
+ float b36 = dVar.b(26L);
+ float b37 = dVar.b(27L);
+ float b38 = dVar.b(28L);
+ float b39 = dVar.b(29L);
+ float b40 = dVar.b(30L);
+ float b41 = dVar.b(31L);
+ dVar.c(2L, b40);
+ dVar.c(3L, b41);
+ dVar.c(4L, b24);
+ dVar.c(5L, b25);
+ dVar.c(6L, b32);
+ dVar.c(7L, b33);
+ dVar.c(8L, b16);
+ dVar.c(9L, b17);
+ dVar.c(10L, b36);
+ dVar.c(11L, b37);
+ dVar.c(12L, b20);
+ dVar.c(13L, b21);
+ dVar.c(14L, b28);
+ dVar.c(15L, b29);
+ dVar.c(16L, b12);
+ dVar.c(17L, b13);
+ dVar.c(18L, b38);
+ dVar.c(19L, b39);
+ dVar.c(20L, b22);
+ dVar.c(21L, b23);
+ dVar.c(22L, b30);
+ dVar.c(23L, b31);
+ dVar.c(24L, b14);
+ dVar.c(25L, b15);
+ dVar.c(26L, b34);
+ dVar.c(27L, b35);
+ dVar.c(28L, b18);
+ dVar.c(29L, b19);
+ dVar.c(30L, b26);
+ dVar.c(31L, b27);
+ return;
+ }
+ i(dVar, 0L, dVar2, 0L);
+ float b42 = dVar.b(2L);
+ float b43 = dVar.b(3L);
+ float b44 = dVar.b(4L);
+ float b45 = dVar.b(5L);
+ float b46 = dVar.b(6L);
+ float b47 = dVar.b(7L);
+ float b48 = dVar.b(8L);
+ float b49 = dVar.b(9L);
+ float b50 = dVar.b(10L);
+ float b51 = dVar.b(11L);
+ float b52 = dVar.b(12L);
+ float b53 = dVar.b(13L);
+ float b54 = dVar.b(14L);
+ float b55 = dVar.b(15L);
+ dVar.c(2L, b54);
+ dVar.c(3L, b55);
+ dVar.c(4L, b46);
+ dVar.c(5L, b47);
+ dVar.c(6L, b50);
+ dVar.c(7L, b51);
+ dVar.c(8L, b42);
+ dVar.c(9L, b43);
+ dVar.c(10L, b52);
+ dVar.c(11L, b53);
+ dVar.c(12L, b44);
+ dVar.c(13L, b45);
+ dVar.c(14L, b48);
+ dVar.c(15L, b49);
+ return;
+ }
+ long j6 = j4 >> 2;
+ long j7 = j5 - j6;
+ long j8 = j4 >> 3;
+ long j9 = j8 * 2;
+ long j10 = j9 + j9;
+ long j11 = j10 + j9;
+ float b56 = dVar.b(j10) + dVar.b(0L);
+ long j12 = j10 + 1;
+ float b57 = (-dVar.b(1L)) - dVar.b(j12);
+ float b58 = dVar.b(0L) - dVar.b(j10);
+ float b59 = dVar.b(j12) + (-dVar.b(1L));
+ float b60 = dVar.b(j11) + dVar.b(j9);
+ long j13 = j9 + 1;
+ long j14 = j11 + 1;
+ float b61 = dVar.b(j14) + dVar.b(j13);
+ float b62 = dVar.b(j9) - dVar.b(j11);
+ float b63 = dVar.b(j13) - dVar.b(j14);
+ long j15 = 1;
+ dVar.c(1L, AbstractC1518b.m(b56, b60, dVar, 0L, b57, b61));
+ dVar.c(j13, AbstractC1518b.a(b56, b60, dVar, j9, b57, b61));
+ dVar.c(j12, AbstractC1518b.j(b58, b63, dVar, j10, b59, b62));
+ dVar.c(j14, AbstractC1518b.l(b58, b63, dVar, j11, b59, b62));
+ float b64 = dVar4.b(j7 + 1);
+ float b65 = dVar4.b(j7 + 2);
+ long j16 = 3;
+ float b66 = dVar4.b(j7 + 3);
+ float f4 = 1.0f;
+ long j17 = 2;
+ long j18 = 0;
+ float f5 = 1.0f;
+ float f6 = 0.0f;
+ float f7 = 0.0f;
+ while (j17 < j8 - 2) {
+ j18 += 4;
+ long j19 = j15;
+ long j20 = j7 + j18;
+ float b67 = (dVar4.b(j20) + f4) * b65;
+ long j21 = j16;
+ long j22 = j20 + j19;
+ float b68 = (dVar4.b(j22) + f6) * b65;
+ long j23 = j20 + 2;
+ float b69 = (dVar4.b(j23) + f5) * b66;
+ long j24 = j20 + j21;
+ float b70 = (dVar4.b(j24) + f7) * b66;
+ float b71 = dVar4.b(j20);
+ float b72 = dVar4.b(j22);
+ float b73 = dVar4.b(j23);
+ float b74 = dVar4.b(j24);
+ long j25 = j17 + j9;
+ long j26 = j25 + j9;
+ long j27 = j26 + j9;
+ float b75 = dVar.b(j26) + dVar.b(j17);
+ long j28 = j17 + j19;
+ float f8 = b65;
+ long j29 = j26 + j19;
+ float b76 = (-dVar.b(j28)) - dVar.b(j29);
+ float b77 = dVar.b(j17) - dVar.b(j26);
+ float b78 = dVar.b(j29) + (-dVar.b(j28));
+ long j30 = j17 + 2;
+ long j31 = j26 + 2;
+ float b79 = dVar.b(j31) + dVar.b(j30);
+ long j32 = j17 + j21;
+ long j33 = j17;
+ long j34 = j26 + j21;
+ float b80 = (-dVar.b(j32)) - dVar.b(j34);
+ float b81 = dVar.b(j30) - dVar.b(j31);
+ float b82 = dVar.b(j34) + (-dVar.b(j32));
+ float b83 = dVar.b(j27) + dVar.b(j25);
+ long j35 = j25 + j19;
+ long j36 = j27 + j19;
+ float b84 = dVar.b(j36) + dVar.b(j35);
+ float b85 = dVar.b(j25) - dVar.b(j27);
+ float b86 = dVar.b(j35) - dVar.b(j36);
+ long j37 = j25 + 2;
+ long j38 = j27 + 2;
+ float b87 = dVar.b(j38) + dVar.b(j37);
+ long j39 = j25 + j21;
+ long j40 = j27 + j21;
+ float b88 = dVar.b(j40) + dVar.b(j39);
+ float b89 = dVar.b(j37) - dVar.b(j38);
+ float b90 = dVar.b(j39) - dVar.b(j40);
+ float f9 = b66;
+ dVar.c(j28, AbstractC1518b.m(b75, b83, dVar, j33, b76, b84));
+ dVar.c(j32, AbstractC1518b.m(b79, b87, dVar, j30, b80, b88));
+ dVar.c(j35, AbstractC1518b.a(b75, b83, dVar, j25, b76, b84));
+ dVar.c(j39, AbstractC1518b.a(b79, b87, dVar, j37, b80, b88));
+ float f10 = b77 + b86;
+ float f11 = b78 + b85;
+ dVar.c(j26, (b67 * f10) - (b68 * f11));
+ float j41 = AbstractC1518b.j(f10 * b68, f11 * b67, dVar, j29, b81, b90);
+ float f12 = b82 + b89;
+ dVar.c(j31, (b71 * j41) - (b72 * f12));
+ float m2 = AbstractC1518b.m(j41 * b72, f12 * b71, dVar, j34, b77, b86);
+ float f13 = b78 - b85;
+ dVar.c(j27, (b70 * f13) + (b69 * m2));
+ float l3 = AbstractC1518b.l(f13 * b69, b70 * m2, dVar, j36, b81, b90);
+ float f14 = b82 - b89;
+ dVar.c(j38, (b74 * f14) + (b73 * l3));
+ dVar.c(j40, (b73 * f14) - (b74 * l3));
+ long j42 = j9 - j33;
+ long j43 = j42 + j9;
+ long j44 = j43 + j9;
+ long j45 = j44 + j9;
+ float b91 = dVar.b(j42) + dVar.b(j44);
+ long j46 = j42 + j19;
+ long j47 = j44 + j19;
+ float b92 = (-dVar.b(j46)) - dVar.b(j47);
+ float b93 = dVar.b(j42) - dVar.b(j44);
+ float b94 = dVar.b(j47) + (-dVar.b(j46));
+ long j48 = j42 - 2;
+ long j49 = j44 - 2;
+ float b95 = dVar.b(j49) + dVar.b(j48);
+ long j50 = j42 - j19;
+ long j51 = j44 - j19;
+ float b96 = (-dVar.b(j50)) - dVar.b(j51);
+ float b97 = dVar.b(j48) - dVar.b(j49);
+ float b98 = dVar.b(j51) + (-dVar.b(j50));
+ float b99 = dVar.b(j45) + dVar.b(j43);
+ long j52 = j43 + j19;
+ long j53 = j45 + j19;
+ float b100 = dVar.b(j53) + dVar.b(j52);
+ float b101 = dVar.b(j43) - dVar.b(j45);
+ float b102 = dVar.b(j52) - dVar.b(j53);
+ long j54 = j43 - 2;
+ long j55 = j45 - 2;
+ float b103 = dVar.b(j55) + dVar.b(j54);
+ long j56 = j43 - j19;
+ long j57 = j45 - j19;
+ float b104 = dVar.b(j57) + dVar.b(j56);
+ float b105 = dVar.b(j54) - dVar.b(j55);
+ float b106 = dVar.b(j56) - dVar.b(j57);
+ dVar.c(j46, AbstractC1518b.m(b91, b99, dVar, j42, b92, b100));
+ dVar.c(j50, AbstractC1518b.m(b95, b103, dVar, j48, b96, b104));
+ dVar.c(j52, AbstractC1518b.a(b91, b99, dVar, j43, b92, b100));
+ dVar.c(j56, AbstractC1518b.a(b95, b103, dVar, j54, b96, b104));
+ float f15 = b93 + b102;
+ float f16 = b94 + b101;
+ dVar.c(j44, (b68 * f15) - (b67 * f16));
+ float j58 = AbstractC1518b.j(f15 * b67, f16 * b68, dVar, j47, b97, b106);
+ float f17 = b98 + b105;
+ dVar.c(j49, (b72 * j58) - (b71 * f17));
+ float m3 = AbstractC1518b.m(j58 * b71, f17 * b72, dVar, j51, b93, b102);
+ float f18 = b94 - b101;
+ dVar.c(j45, (b69 * f18) + (b70 * m3));
+ float l4 = AbstractC1518b.l(b70 * f18, b69 * m3, dVar, j53, b97, b106);
+ float f19 = b98 - b105;
+ dVar.c(j55, (b73 * f19) + (b74 * l4));
+ dVar.c(j57, (b74 * f19) - (b73 * l4));
+ j17 = j33 + 4;
+ dVar4 = dVar2;
+ j15 = j19;
+ f4 = b71;
+ f6 = b72;
+ j16 = j21;
+ f5 = b73;
+ b66 = f9;
+ f7 = b74;
+ b65 = f8;
+ b64 = b64;
+ }
+ float f20 = b64;
+ float f21 = b65;
+ long j59 = j15;
+ long j60 = j16;
+ float f22 = b66;
+ float f23 = (f4 + f20) * f21;
+ float f24 = (f6 + f20) * f21;
+ float f25 = (f5 - f20) * f22;
+ float f26 = (f7 - f20) * f22;
+ long j61 = j8 + j9;
+ long j62 = j61 + j9;
+ long j63 = j62 + j9;
+ long j64 = j8 - 2;
+ long j65 = j62 - 2;
+ float b107 = dVar.b(j65) + dVar.b(j64);
+ long j66 = j8 - j59;
+ long j67 = j62 - j59;
+ float b108 = (-dVar.b(j66)) - dVar.b(j67);
+ float b109 = dVar.b(j64) - dVar.b(j65);
+ float b110 = dVar.b(j67) + (-dVar.b(j66));
+ long j68 = j61 - 2;
+ long j69 = j63 - 2;
+ float b111 = dVar.b(j69) + dVar.b(j68);
+ long j70 = j61 - j59;
+ long j71 = j63 - j59;
+ float b112 = dVar.b(j71) + dVar.b(j70);
+ float b113 = dVar.b(j68) - dVar.b(j69);
+ float b114 = dVar.b(j70) - dVar.b(j71);
+ dVar.c(j66, AbstractC1518b.m(b107, b111, dVar, j64, b108, b112));
+ dVar.c(j70, AbstractC1518b.a(b107, b111, dVar, j68, b108, b112));
+ float f27 = b109 + b114;
+ float f28 = b110 + b113;
+ dVar.c(j65, (f23 * f27) - (f24 * f28));
+ float m4 = AbstractC1518b.m(f27 * f24, f28 * f23, dVar, j67, b109, b114);
+ float f29 = b110 - b113;
+ dVar.c(j69, (f26 * f29) + (f25 * m4));
+ dVar.c(j71, (f25 * f29) - (f26 * m4));
+ float b115 = dVar.b(j8) + dVar.b(j62);
+ long j72 = j8 + j59;
+ long j73 = j62 + j59;
+ float b116 = (-dVar.b(j72)) - dVar.b(j73);
+ float b117 = dVar.b(j8) - dVar.b(j62);
+ float b118 = dVar.b(j73) + (-dVar.b(j72));
+ float b119 = dVar.b(j61) + dVar.b(j63);
+ long j74 = j61 + j59;
+ long j75 = j63 + j59;
+ float b120 = dVar.b(j75) + dVar.b(j74);
+ float b121 = dVar.b(j61) - dVar.b(j63);
+ float b122 = dVar.b(j74) - dVar.b(j75);
+ dVar.c(j72, AbstractC1518b.m(b115, b119, dVar, j8, b116, b120));
+ dVar.c(j74, AbstractC1518b.a(b115, b119, dVar, j61, b116, b120));
+ float f30 = b117 + b122;
+ float f31 = b118 + b121;
+ dVar.c(j62, (f30 - f31) * f20);
+ dVar.c(j73, (f31 + f30) * f20);
+ float f32 = b117 - b122;
+ float f33 = b118 - b121;
+ float f34 = -f20;
+ dVar.c(j63, (f32 + f33) * f34);
+ dVar.c(j75, (f33 - f32) * f34);
+ long j76 = j8 + 2;
+ long j77 = j62 + 2;
+ float b123 = dVar.b(j76) + dVar.b(j77);
+ long j78 = j8 + j60;
+ long j79 = j62 + j60;
+ float b124 = (-dVar.b(j78)) - dVar.b(j79);
+ float b125 = dVar.b(j76) - dVar.b(j77);
+ float b126 = dVar.b(j79) + (-dVar.b(j78));
+ long j80 = j61 + 2;
+ long j81 = j63 + 2;
+ float b127 = dVar.b(j81) + dVar.b(j80);
+ long j82 = j61 + j60;
+ long j83 = j63 + j60;
+ float b128 = dVar.b(j83) + dVar.b(j82);
+ float b129 = dVar.b(j80) - dVar.b(j81);
+ float b130 = dVar.b(j82) - dVar.b(j83);
+ dVar.c(j78, AbstractC1518b.m(b123, b127, dVar, j76, b124, b128));
+ dVar.c(j82, AbstractC1518b.a(b123, b127, dVar, j80, b124, b128));
+ float f35 = b125 + b130;
+ float f36 = b126 + b129;
+ dVar.c(j77, (f24 * f35) - (f23 * f36));
+ float m5 = AbstractC1518b.m(f35 * f23, f36 * f24, dVar, j79, b125, b130);
+ float f37 = b126 - b129;
+ dVar.c(j81, (f25 * f37) + (f26 * m5));
+ dVar.c(j83, (f26 * f37) - (f25 * m5));
+ if (k3.c.c > 1 && j4 >= 8192) {
+ D(j4, 0L, j5, dVar, dVar2);
+ } else if (j4 > 512) {
+ B(j4, 0L, j5, dVar, dVar2);
+ } else if (j4 > 128) {
+ v(j4, 1L, 0L, j5, dVar, dVar2);
+ } else {
+ t(j4, 0L, j5, dVar, dVar2);
+ dVar3 = dVar;
+ long j84 = j59;
+ while (j6 > 8) {
+ j84 <<= 1;
+ j6 >>= 2;
+ }
+ long j85 = j4 >> 1;
+ long j86 = j84 * 4;
+ if (j6 != 8) {
+ long j87 = 0;
+ while (j87 < j84) {
+ long j88 = j87 * 4;
+ long j89 = 0;
+ while (j89 < j87) {
+ long j90 = j84;
+ long b131 = (sVar.b(j90 + j87) * 2) + (j89 * 4);
+ long j91 = j85;
+ long b132 = (sVar.b(j90 + j89) * 2) + j88;
+ float b133 = dVar3.b(b131);
+ long j92 = j87;
+ long j93 = b131 + j59;
+ long j94 = j88;
+ float f38 = -dVar3.b(j93);
+ float b134 = dVar3.b(b132);
+ long j95 = j89;
+ long j96 = b132 + j59;
+ long j97 = j86;
+ float f39 = -dVar3.b(j96);
+ dVar3.c(b131, b134);
+ dVar3.c(j93, f39);
+ dVar3.c(b132, b133);
+ dVar3.c(j96, f38);
+ long j98 = b131 + j97;
+ long j99 = j90 * 8;
+ long j100 = b132 + j99;
+ float b135 = dVar3.b(j98);
+ long j101 = j98 + j59;
+ float f40 = -dVar3.b(j101);
+ float b136 = dVar3.b(j100);
+ long j102 = j100 + j59;
+ float f41 = -dVar3.b(j102);
+ dVar3.c(j98, b136);
+ dVar3.c(j101, f41);
+ dVar3.c(j100, b135);
+ dVar3.c(j102, f40);
+ long j103 = j98 + j97;
+ long j104 = j100 - j97;
+ float b137 = dVar3.b(j103);
+ long j105 = j103 + j59;
+ float f42 = -dVar3.b(j105);
+ float b138 = dVar3.b(j104);
+ long j106 = j104 + j59;
+ float f43 = -dVar3.b(j106);
+ dVar3.c(j103, b138);
+ dVar3.c(j105, f43);
+ dVar3.c(j104, b137);
+ dVar3.c(j106, f42);
+ long j107 = j103 + j97;
+ long j108 = j104 + j99;
+ float b139 = dVar3.b(j107);
+ long j109 = j107 + j59;
+ float f44 = -dVar3.b(j109);
+ float b140 = dVar3.b(j108);
+ long j110 = j108 + j59;
+ float f45 = -dVar3.b(j110);
+ dVar3.c(j107, b140);
+ dVar3.c(j109, f45);
+ dVar3.c(j108, b139);
+ dVar3.c(j110, f44);
+ long j111 = j107 + j91;
+ long j112 = j108 + 2;
+ float b141 = dVar3.b(j111);
+ long j113 = j111 + j59;
+ float f46 = -dVar3.b(j113);
+ float b142 = dVar3.b(j112);
+ long j114 = j108 + j60;
+ float f47 = -dVar3.b(j114);
+ dVar3.c(j111, b142);
+ dVar3.c(j113, f47);
+ dVar3.c(j112, b141);
+ dVar3.c(j114, f46);
+ long j115 = j111 - j97;
+ long j116 = j112 - j99;
+ float b143 = dVar3.b(j115);
+ long j117 = j115 + j59;
+ float f48 = -dVar3.b(j117);
+ float b144 = dVar3.b(j116);
+ long j118 = j116 + j59;
+ float f49 = -dVar3.b(j118);
+ dVar3.c(j115, b144);
+ dVar3.c(j117, f49);
+ dVar3.c(j116, b143);
+ dVar3.c(j118, f48);
+ long j119 = j115 - j97;
+ long j120 = j116 + j97;
+ float b145 = dVar3.b(j119);
+ long j121 = j119 + j59;
+ float f50 = -dVar3.b(j121);
+ float b146 = dVar3.b(j120);
+ long j122 = j120 + j59;
+ float f51 = -dVar3.b(j122);
+ dVar3.c(j119, b146);
+ dVar3.c(j121, f51);
+ dVar3.c(j120, b145);
+ dVar3.c(j122, f50);
+ long j123 = j119 - j97;
+ long j124 = j120 - j99;
+ float b147 = dVar3.b(j123);
+ long j125 = j123 + j59;
+ float f52 = -dVar3.b(j125);
+ float b148 = dVar3.b(j124);
+ long j126 = j124 + j59;
+ float f53 = -dVar3.b(j126);
+ dVar3.c(j123, b148);
+ dVar3.c(j125, f53);
+ dVar3.c(j124, b147);
+ dVar3.c(j126, f52);
+ long j127 = j123 + 2;
+ long j128 = j124 + j91;
+ float b149 = dVar3.b(j127);
+ long j129 = j123 + j60;
+ float f54 = -dVar3.b(j129);
+ float b150 = dVar3.b(j128);
+ long j130 = j128 + j59;
+ float f55 = -dVar3.b(j130);
+ dVar3.c(j127, b150);
+ dVar3.c(j129, f55);
+ dVar3.c(j128, b149);
+ dVar3.c(j130, f54);
+ long j131 = j127 + j97;
+ long j132 = j128 + j99;
+ float b151 = dVar3.b(j131);
+ long j133 = j131 + j59;
+ float f56 = -dVar3.b(j133);
+ float b152 = dVar3.b(j132);
+ long j134 = j132 + j59;
+ float f57 = -dVar3.b(j134);
+ dVar3.c(j131, b152);
+ dVar3.c(j133, f57);
+ dVar3.c(j132, b151);
+ dVar3.c(j134, f56);
+ long j135 = j131 + j97;
+ long j136 = j132 - j97;
+ float b153 = dVar3.b(j135);
+ long j137 = j135 + j59;
+ float f58 = -dVar3.b(j137);
+ float b154 = dVar3.b(j136);
+ long j138 = j136 + j59;
+ float f59 = -dVar3.b(j138);
+ dVar3.c(j135, b154);
+ dVar3.c(j137, f59);
+ dVar3.c(j136, b153);
+ dVar3.c(j138, f58);
+ long j139 = j135 + j97;
+ long j140 = j136 + j99;
+ float b155 = dVar3.b(j139);
+ long j141 = j139 + j59;
+ float f60 = -dVar3.b(j141);
+ float b156 = dVar3.b(j140);
+ long j142 = j140 + j59;
+ float f61 = -dVar3.b(j142);
+ dVar3.c(j139, b156);
+ dVar3.c(j141, f61);
+ dVar3.c(j140, b155);
+ dVar3.c(j142, f60);
+ long j143 = j139 - j91;
+ long j144 = j140 - 2;
+ float b157 = dVar3.b(j143);
+ long j145 = j143 + j59;
+ float f62 = -dVar3.b(j145);
+ float b158 = dVar3.b(j144);
+ long j146 = j140 - j59;
+ float f63 = -dVar3.b(j146);
+ dVar3.c(j143, b158);
+ dVar3.c(j145, f63);
+ dVar3.c(j144, b157);
+ dVar3.c(j146, f62);
+ long j147 = j143 - j97;
+ long j148 = j144 - j99;
+ float b159 = dVar3.b(j147);
+ long j149 = j147 + j59;
+ float f64 = -dVar3.b(j149);
+ float b160 = dVar3.b(j148);
+ long j150 = j148 + j59;
+ float f65 = -dVar3.b(j150);
+ dVar3.c(j147, b160);
+ dVar3.c(j149, f65);
+ dVar3.c(j148, b159);
+ dVar3.c(j150, f64);
+ long j151 = j147 - j97;
+ long j152 = j148 + j97;
+ float b161 = dVar3.b(j151);
+ long j153 = j151 + j59;
+ float f66 = -dVar3.b(j153);
+ float b162 = dVar3.b(j152);
+ long j154 = j152 + j59;
+ float f67 = -dVar3.b(j154);
+ dVar3.c(j151, b162);
+ dVar3.c(j153, f67);
+ dVar3.c(j152, b161);
+ dVar3.c(j154, f66);
+ long j155 = j151 - j97;
+ long j156 = j152 - j99;
+ float b163 = dVar3.b(j155);
+ long j157 = j155 + j59;
+ float f68 = -dVar3.b(j157);
+ float b164 = dVar3.b(j156);
+ long j158 = j156 + j59;
+ float f69 = -dVar3.b(j158);
+ dVar3.c(j155, b164);
+ dVar3.c(j157, f69);
+ dVar3.c(j156, b163);
+ dVar3.c(j158, f68);
+ j89 = j95 + j59;
+ j85 = j91;
+ j84 = j90;
+ j87 = j92;
+ j88 = j94;
+ j86 = j97;
+ }
+ long j159 = j84;
+ long j160 = j85;
+ long j161 = j87;
+ long j162 = j86;
+ long b165 = (sVar.b(j159 + j161) * 2) + j88;
+ long j163 = b165 + 2;
+ long j164 = b165 + j160;
+ long j165 = b165 + j59;
+ dVar3.c(j165, -dVar3.b(j165));
+ float b166 = dVar3.b(j163);
+ long j166 = b165 + j60;
+ float f70 = -dVar3.b(j166);
+ float b167 = dVar3.b(j164);
+ long j167 = j164 + j59;
+ float f71 = -dVar3.b(j167);
+ dVar3.c(j163, b167);
+ dVar3.c(j166, f71);
+ dVar3.c(j164, b166);
+ dVar3.c(j167, f70);
+ long j168 = j164 + j60;
+ dVar3.c(j168, -dVar3.b(j168));
+ long j169 = j163 + j162;
+ long j170 = j159 * 8;
+ long j171 = j164 + j170;
+ float b168 = dVar3.b(j169);
+ long j172 = j169 + j59;
+ float f72 = -dVar3.b(j172);
+ float b169 = dVar3.b(j171);
+ long j173 = j171 + j59;
+ float f73 = -dVar3.b(j173);
+ dVar3.c(j169, b169);
+ dVar3.c(j172, f73);
+ dVar3.c(j171, b168);
+ dVar3.c(j173, f72);
+ long j174 = j169 + j162;
+ long j175 = j171 - j162;
+ float b170 = dVar3.b(j174);
+ long j176 = j174 + j59;
+ float f74 = -dVar3.b(j176);
+ float b171 = dVar3.b(j175);
+ long j177 = j175 + j59;
+ float f75 = -dVar3.b(j177);
+ dVar3.c(j174, b171);
+ dVar3.c(j176, f75);
+ dVar3.c(j175, b170);
+ dVar3.c(j177, f74);
+ long j178 = j174 - 2;
+ long j179 = j175 - j160;
+ float b172 = dVar3.b(j178);
+ long j180 = j174 - j59;
+ float f76 = -dVar3.b(j180);
+ float b173 = dVar3.b(j179);
+ long j181 = j179 + j59;
+ float f77 = -dVar3.b(j181);
+ dVar3.c(j178, b173);
+ dVar3.c(j180, f77);
+ dVar3.c(j179, b172);
+ dVar3.c(j181, f76);
+ long j182 = j160 + 2;
+ long j183 = j178 + j182;
+ long j184 = j179 + j182;
+ float b174 = dVar3.b(j183);
+ long j185 = j183 + j59;
+ float f78 = -dVar3.b(j185);
+ float b175 = dVar3.b(j184);
+ long j186 = j184 + j59;
+ float f79 = -dVar3.b(j186);
+ dVar3.c(j183, b175);
+ dVar3.c(j185, f79);
+ dVar3.c(j184, b174);
+ dVar3.c(j186, f78);
+ long j187 = j183 - (j160 - j162);
+ long j188 = (j170 - 2) + j184;
+ long j189 = j187 - j59;
+ dVar3.c(j189, -dVar3.b(j189));
+ float b176 = dVar3.b(j187);
+ long j190 = j187 + j59;
+ float f80 = -dVar3.b(j190);
+ float b177 = dVar3.b(j188);
+ long j191 = j188 + j59;
+ float f81 = -dVar3.b(j191);
+ dVar3.c(j187, b177);
+ dVar3.c(j190, f81);
+ dVar3.c(j188, b176);
+ dVar3.c(j191, f80);
+ long j192 = j188 + j60;
+ dVar3.c(j192, -dVar3.b(j192));
+ j87 = j161 + j59;
+ j85 = j160;
+ j84 = j159;
+ j86 = j162;
+ }
+ return;
+ }
+ long j193 = j84;
+ int i4 = 0;
+ while (true) {
+ long j194 = i4;
+ if (j194 >= j193) {
+ return;
+ }
+ long j195 = i4 * 4;
+ int i5 = 0;
+ while (i5 < i4) {
+ long b178 = sVar.b(j193 + j194) + (i5 * 4);
+ long b179 = sVar.b(j193 + i5) + j195;
+ float b180 = dVar3.b(b178);
+ long j196 = b178 + j59;
+ float f82 = -dVar3.b(j196);
+ int i6 = i4;
+ float b181 = dVar3.b(b179);
+ long j197 = j194;
+ long j198 = b179 + j59;
+ long j199 = j195;
+ float f83 = -dVar3.b(j198);
+ dVar3.c(b178, b181);
+ dVar3.c(j196, f83);
+ dVar3.c(b179, b180);
+ dVar3.c(j198, f82);
+ long j200 = b178 + j86;
+ long j201 = b179 + j86;
+ float b182 = dVar3.b(j200);
+ long j202 = j200 + j59;
+ float f84 = -dVar3.b(j202);
+ float b183 = dVar3.b(j201);
+ long j203 = j201 + j59;
+ float f85 = -dVar3.b(j203);
+ dVar3.c(j200, b183);
+ dVar3.c(j202, f85);
+ dVar3.c(j201, b182);
+ dVar3.c(j203, f84);
+ long j204 = j200 + j85;
+ long j205 = j201 + 2;
+ float b184 = dVar3.b(j204);
+ long j206 = j204 + j59;
+ float f86 = -dVar3.b(j206);
+ float b185 = dVar3.b(j205);
+ long j207 = j201 + j60;
+ float f87 = -dVar3.b(j207);
+ dVar3.c(j204, b185);
+ dVar3.c(j206, f87);
+ dVar3.c(j205, b184);
+ dVar3.c(j207, f86);
+ long j208 = j204 - j86;
+ long j209 = j205 - j86;
+ float b186 = dVar3.b(j208);
+ long j210 = j208 + j59;
+ float f88 = -dVar3.b(j210);
+ float b187 = dVar3.b(j209);
+ long j211 = j209 + j59;
+ float f89 = -dVar3.b(j211);
+ dVar3.c(j208, b187);
+ dVar3.c(j210, f89);
+ dVar3.c(j209, b186);
+ dVar3.c(j211, f88);
+ long j212 = j208 + 2;
+ long j213 = j209 + j85;
+ float b188 = dVar3.b(j212);
+ long j214 = j208 + j60;
+ float f90 = -dVar3.b(j214);
+ float b189 = dVar3.b(j213);
+ long j215 = j213 + j59;
+ float f91 = -dVar3.b(j215);
+ dVar3.c(j212, b189);
+ dVar3.c(j214, f91);
+ dVar3.c(j213, b188);
+ dVar3.c(j215, f90);
+ long j216 = j212 + j86;
+ long j217 = j213 + j86;
+ float b190 = dVar3.b(j216);
+ long j218 = j216 + j59;
+ float f92 = -dVar3.b(j218);
+ float b191 = dVar3.b(j217);
+ long j219 = j217 + j59;
+ float f93 = -dVar3.b(j219);
+ dVar3.c(j216, b191);
+ dVar3.c(j218, f93);
+ dVar3.c(j217, b190);
+ dVar3.c(j219, f92);
+ long j220 = j216 - j85;
+ long j221 = j217 - 2;
+ float b192 = dVar3.b(j220);
+ long j222 = j220 + j59;
+ float f94 = -dVar3.b(j222);
+ float b193 = dVar3.b(j221);
+ long j223 = j217 - j59;
+ float f95 = -dVar3.b(j223);
+ dVar3.c(j220, b193);
+ dVar3.c(j222, f95);
+ dVar3.c(j221, b192);
+ dVar3.c(j223, f94);
+ long j224 = j220 - j86;
+ long j225 = j221 - j86;
+ float b194 = dVar3.b(j224);
+ long j226 = j224 + j59;
+ float f96 = -dVar3.b(j226);
+ float b195 = dVar3.b(j225);
+ long j227 = j225 + j59;
+ float f97 = -dVar3.b(j227);
+ dVar3.c(j224, b195);
+ dVar3.c(j226, f97);
+ dVar3.c(j225, b194);
+ dVar3.c(j227, f96);
+ i5++;
+ i4 = i6;
+ j194 = j197;
+ j195 = j199;
+ }
+ int i7 = i4;
+ long b196 = sVar.b(j193 + j194) + j195;
+ long j228 = b196 + 2;
+ long j229 = b196 + j85;
+ long j230 = b196 + j59;
+ dVar3.c(j230, -dVar3.b(j230));
+ float b197 = dVar3.b(j228);
+ long j231 = b196 + j60;
+ float f98 = -dVar3.b(j231);
+ float b198 = dVar3.b(j229);
+ long j232 = j229 + j59;
+ float f99 = -dVar3.b(j232);
+ dVar3.c(j228, b198);
+ dVar3.c(j231, f99);
+ dVar3.c(j229, b197);
+ dVar3.c(j232, f98);
+ long j233 = j229 + j60;
+ dVar3.c(j233, -dVar3.b(j233));
+ long j234 = j228 + j86;
+ long j235 = j229 + j86;
+ long j236 = j234 - j59;
+ dVar3.c(j236, -dVar3.b(j236));
+ float b199 = dVar3.b(j234);
+ long j237 = j234 + j59;
+ float f100 = -dVar3.b(j237);
+ float b200 = dVar3.b(j235);
+ long j238 = j235 + j59;
+ float f101 = -dVar3.b(j238);
+ dVar3.c(j234, b200);
+ dVar3.c(j237, f101);
+ dVar3.c(j235, b199);
+ dVar3.c(j238, f100);
+ long j239 = j235 + j60;
+ dVar3.c(j239, -dVar3.b(j239));
+ i4 = i7 + 1;
+ }
+ }
+ dVar3 = dVar;
+ long j842 = j59;
+ while (j6 > 8) {
+ }
+ long j852 = j4 >> 1;
+ long j862 = j842 * 4;
+ if (j6 != 8) {
+ }
+ }
+
+ public static void i(d dVar, long j4, d dVar2, long j5) {
+ float b4 = dVar2.b(j5 + 1);
+ long j6 = j4 + 8;
+ float b5 = dVar.b(j6) + dVar.b(j4);
+ long j7 = j4 + 1;
+ long j8 = j4 + 9;
+ float b6 = dVar.b(j8) + dVar.b(j7);
+ float b7 = dVar.b(j4) - dVar.b(j6);
+ float b8 = dVar.b(j7) - dVar.b(j8);
+ long j9 = j4 + 4;
+ long j10 = j4 + 12;
+ float b9 = dVar.b(j10) + dVar.b(j9);
+ long j11 = j4 + 5;
+ long j12 = j4 + 13;
+ float b10 = dVar.b(j12) + dVar.b(j11);
+ float b11 = dVar.b(j9) - dVar.b(j10);
+ float b12 = dVar.b(j11) - dVar.b(j12);
+ float f4 = b5 + b9;
+ float f5 = b6 + b10;
+ float f6 = b5 - b9;
+ float f7 = b6 - b10;
+ float f8 = b7 - b12;
+ float f9 = b8 + b11;
+ float f10 = b7 + b12;
+ float f11 = b8 - b11;
+ long j13 = j4 + 2;
+ long j14 = j4 + 10;
+ float b13 = dVar.b(j14) + dVar.b(j13);
+ long j15 = j4 + 3;
+ long j16 = j4 + 11;
+ float b14 = dVar.b(j16) + dVar.b(j15);
+ float b15 = dVar.b(j13) - dVar.b(j14);
+ float b16 = dVar.b(j15) - dVar.b(j16);
+ long j17 = j4 + 6;
+ long j18 = j4 + 14;
+ float b17 = dVar.b(j18) + dVar.b(j17);
+ long j19 = j4 + 7;
+ long j20 = j4 + 15;
+ float b18 = dVar.b(j20) + dVar.b(j19);
+ float b19 = dVar.b(j17) - dVar.b(j18);
+ float b20 = dVar.b(j19) - dVar.b(j20);
+ float f12 = b13 + b17;
+ float f13 = b14 + b18;
+ float f14 = b13 - b17;
+ float f15 = b14 - b18;
+ float f16 = b15 - b20;
+ float f17 = b16 + b19;
+ float f18 = b15 + b20;
+ float f19 = b16 - b19;
+ float f20 = (f16 - f17) * b4;
+ float f21 = (f16 + f17) * b4;
+ float f22 = (f18 - f19) * b4;
+ float f23 = (f18 + f19) * b4;
+ dVar.c(j8, AbstractC1518b.j(f8, f20, dVar, j6, f9, f21));
+ dVar.c(j16, AbstractC1518b.l(f8, f20, dVar, j14, f9, f21));
+ dVar.c(j12, AbstractC1518b.a(f10, f23, dVar, j10, f11, f22));
+ dVar.c(j20, AbstractC1518b.m(f10, f23, dVar, j18, f11, f22));
+ dVar.c(j7, AbstractC1518b.j(f4, f12, dVar, j4, f5, f13));
+ dVar.c(j15, AbstractC1518b.l(f4, f12, dVar, j13, f5, f13));
+ dVar.c(j11, AbstractC1518b.a(f6, f15, dVar, j9, f7, f14));
+ dVar.c(j19, AbstractC1518b.m(f6, f15, dVar, j17, f7, f14));
+ }
+
+ public static void j(float[] fArr, int i4, float[] fArr2, int i5) {
+ float f4 = fArr2[i5 + 1];
+ float f5 = fArr[i4];
+ int i6 = i4 + 8;
+ float f6 = fArr[i6];
+ float f7 = f5 + f6;
+ int i7 = i4 + 1;
+ float f8 = fArr[i7];
+ int i8 = i4 + 9;
+ float f9 = fArr[i8];
+ float f10 = f8 + f9;
+ float f11 = f5 - f6;
+ float f12 = f8 - f9;
+ int i9 = i4 + 4;
+ float f13 = fArr[i9];
+ int i10 = i4 + 12;
+ float f14 = fArr[i10];
+ float f15 = f13 + f14;
+ int i11 = i4 + 5;
+ float f16 = fArr[i11];
+ int i12 = i4 + 13;
+ float f17 = fArr[i12];
+ float f18 = f16 + f17;
+ float f19 = f13 - f14;
+ float f20 = f16 - f17;
+ float f21 = f7 + f15;
+ float f22 = f10 + f18;
+ float f23 = f7 - f15;
+ float f24 = f10 - f18;
+ float f25 = f11 - f20;
+ float f26 = f12 + f19;
+ float f27 = f11 + f20;
+ float f28 = f12 - f19;
+ int i13 = i4 + 2;
+ float f29 = fArr[i13];
+ int i14 = i4 + 10;
+ float f30 = fArr[i14];
+ float f31 = f29 + f30;
+ int i15 = i4 + 3;
+ float f32 = fArr[i15];
+ int i16 = i4 + 11;
+ float f33 = fArr[i16];
+ float f34 = f32 + f33;
+ float f35 = f29 - f30;
+ float f36 = f32 - f33;
+ int i17 = i4 + 6;
+ float f37 = fArr[i17];
+ int i18 = i4 + 14;
+ float f38 = fArr[i18];
+ float f39 = f37 + f38;
+ int i19 = i4 + 7;
+ float f40 = fArr[i19];
+ int i20 = i4 + 15;
+ float f41 = fArr[i20];
+ float f42 = f40 + f41;
+ float f43 = f37 - f38;
+ float f44 = f40 - f41;
+ float f45 = f31 + f39;
+ float f46 = f34 + f42;
+ float f47 = f31 - f39;
+ float f48 = f34 - f42;
+ float f49 = f35 - f44;
+ float f50 = f36 + f43;
+ float f51 = f35 + f44;
+ float f52 = f36 - f43;
+ float f53 = (f49 - f50) * f4;
+ float f54 = (f49 + f50) * f4;
+ float f55 = (f51 - f52) * f4;
+ float f56 = (f51 + f52) * f4;
+ fArr[i6] = f25 + f53;
+ fArr[i8] = f26 + f54;
+ fArr[i14] = f25 - f53;
+ fArr[i16] = f26 - f54;
+ fArr[i10] = f27 - f56;
+ fArr[i12] = f28 + f55;
+ fArr[i18] = f27 + f56;
+ fArr[i20] = f28 - f55;
+ fArr[i4] = f21 + f45;
+ fArr[i7] = f22 + f46;
+ fArr[i13] = f21 - f45;
+ fArr[i15] = f22 - f46;
+ fArr[i9] = f23 - f48;
+ fArr[i11] = f24 + f47;
+ fArr[i17] = f23 + f48;
+ fArr[i19] = f24 - f47;
+ }
+
+ /* JADX WARN: Type inference failed for: r0v2, types: [F.i, android.graphics.drawable.Drawable] */
+ public static void k(d dVar, long j4, d dVar2, long j5) {
+ float b4 = dVar2.b(j5 + 1);
+ float b5 = dVar2.b(j5 + 2);
+ float b6 = dVar2.b(j5 + 3);
+ long j6 = j4 + 9;
+ float b7 = dVar.b(j4) - dVar.b(j6);
+ long j7 = j4 + 1;
+ long j8 = j4 + 8;
+ float b8 = dVar.b(j8) + dVar.b(j7);
+ float b9 = dVar.b(j6) + dVar.b(j4);
+ float b10 = dVar.b(j7) - dVar.b(j8);
+ long j9 = j4 + 4;
+ long j10 = j4 + 13;
+ float b11 = dVar.b(j9) - dVar.b(j10);
+ long j11 = j4 + 5;
+ long j12 = j4 + 12;
+ float b12 = dVar.b(j12) + dVar.b(j11);
+ float f4 = (b11 - b12) * b4;
+ float f5 = (b12 + b11) * b4;
+ float b13 = dVar.b(j10) + dVar.b(j9);
+ float b14 = dVar.b(j11) - dVar.b(j12);
+ float f6 = (b13 - b14) * b4;
+ float f7 = (b14 + b13) * b4;
+ long j13 = j4 + 2;
+ long j14 = j4 + 11;
+ float b15 = dVar.b(j13) - dVar.b(j14);
+ long j15 = j4 + 3;
+ long j16 = j4 + 10;
+ float b16 = dVar.b(j16) + dVar.b(j15);
+ float f8 = (b5 * b15) - (b6 * b16);
+ float f9 = (b15 * b6) + (b16 * b5);
+ float b17 = dVar.b(j14) + dVar.b(j13);
+ float b18 = dVar.b(j15) - dVar.b(j16);
+ float f10 = (b6 * b17) - (b5 * b18);
+ float f11 = (b17 * b5) + (b18 * b6);
+ long j17 = j4 + 6;
+ long j18 = j4 + 15;
+ float b19 = dVar.b(j17) - dVar.b(j18);
+ long j19 = j4 + 7;
+ long j20 = j4 + 14;
+ float b20 = dVar.b(j20) + dVar.b(j19);
+ float f12 = (b6 * b19) - (b5 * b20);
+ float f13 = (b19 * b5) + (b20 * b6);
+ float b21 = dVar.b(j18) + dVar.b(j17);
+ float b22 = dVar.b(j19) - dVar.b(j20);
+ float f14 = (b5 * b21) - (b6 * b22);
+ float f15 = (b6 * b21) + (b22 * b5);
+ float f16 = b7 + f4;
+ float f17 = b8 + f5;
+ float f18 = f8 + f12;
+ float f19 = f9 + f13;
+ dVar.c(j7, AbstractC1518b.j(f16, f18, dVar, j4, f17, f19));
+ dVar.c(j15, AbstractC1518b.l(f16, f18, dVar, j13, f17, f19));
+ float f20 = b7 - f4;
+ float f21 = b8 - f5;
+ float f22 = f8 - f12;
+ float f23 = f9 - f13;
+ dVar.c(j11, AbstractC1518b.a(f20, f23, dVar, j9, f21, f22));
+ dVar.c(j19, AbstractC1518b.m(f20, f23, dVar, j17, f21, f22));
+ float f24 = b9 - f7;
+ float f25 = b10 + f6;
+ float f26 = f10 - f14;
+ float f27 = f11 - f15;
+ dVar.c(j6, AbstractC1518b.j(f24, f26, dVar, j8, f25, f27));
+ dVar.c(j14, AbstractC1518b.l(f24, f26, dVar, j16, f25, f27));
+ float f28 = b9 + f7;
+ float f29 = b10 - f6;
+ float f30 = f10 + f14;
+ float f31 = f11 + f15;
+ dVar.c(j10, AbstractC1518b.a(f28, f31, dVar, j12, f29, f30));
+ dVar.c(j18, AbstractC1518b.m(f28, f31, dVar, j20, f29, f30));
+ }
+
+ public static void l(float[] fArr, int i4, float[] fArr2, int i5) {
+ float f4 = fArr2[i5 + 1];
+ float f5 = fArr2[i5 + 2];
+ float f6 = fArr2[i5 + 3];
+ float f7 = fArr[i4];
+ int i6 = i4 + 9;
+ float f8 = fArr[i6];
+ float f9 = f7 - f8;
+ int i7 = i4 + 1;
+ float f10 = fArr[i7];
+ int i8 = i4 + 8;
+ float f11 = fArr[i8];
+ float f12 = f10 + f11;
+ float f13 = f7 + f8;
+ float f14 = f10 - f11;
+ int i9 = i4 + 4;
+ float f15 = fArr[i9];
+ int i10 = i4 + 13;
+ float f16 = fArr[i10];
+ float f17 = f15 - f16;
+ int i11 = i4 + 5;
+ float f18 = fArr[i11];
+ int i12 = i4 + 12;
+ float f19 = fArr[i12];
+ float f20 = f18 + f19;
+ float f21 = (f17 - f20) * f4;
+ float f22 = (f20 + f17) * f4;
+ float f23 = f15 + f16;
+ float f24 = f18 - f19;
+ float f25 = (f23 - f24) * f4;
+ float f26 = (f24 + f23) * f4;
+ int i13 = i4 + 2;
+ float f27 = fArr[i13];
+ int i14 = i4 + 11;
+ float f28 = fArr[i14];
+ float f29 = f27 - f28;
+ int i15 = i4 + 3;
+ float f30 = fArr[i15];
+ int i16 = i4 + 10;
+ float f31 = fArr[i16];
+ float f32 = f30 + f31;
+ float f33 = (f5 * f29) - (f6 * f32);
+ float f34 = (f29 * f6) + (f32 * f5);
+ float f35 = f27 + f28;
+ float f36 = f30 - f31;
+ float f37 = (f6 * f35) - (f5 * f36);
+ float f38 = (f35 * f5) + (f36 * f6);
+ int i17 = i4 + 6;
+ float f39 = fArr[i17];
+ int i18 = i4 + 15;
+ float f40 = fArr[i18];
+ float f41 = f39 - f40;
+ int i19 = i4 + 7;
+ float f42 = fArr[i19];
+ int i20 = i4 + 14;
+ float f43 = fArr[i20];
+ float f44 = f42 + f43;
+ float f45 = (f6 * f41) - (f5 * f44);
+ float f46 = (f41 * f5) + (f44 * f6);
+ float f47 = f39 + f40;
+ float f48 = f42 - f43;
+ float f49 = (f5 * f47) - (f6 * f48);
+ float f50 = (f6 * f47) + (f5 * f48);
+ float f51 = f9 + f21;
+ float f52 = f12 + f22;
+ float f53 = f33 + f45;
+ float f54 = f34 + f46;
+ fArr[i4] = f51 + f53;
+ fArr[i7] = f52 + f54;
+ fArr[i13] = f51 - f53;
+ fArr[i15] = f52 - f54;
+ float f55 = f9 - f21;
+ float f56 = f12 - f22;
+ float f57 = f33 - f45;
+ float f58 = f34 - f46;
+ fArr[i9] = f55 - f58;
+ fArr[i11] = f56 + f57;
+ fArr[i17] = f55 + f58;
+ fArr[i19] = f56 - f57;
+ float f59 = f13 - f26;
+ float f60 = f14 + f25;
+ float f61 = f37 - f49;
+ float f62 = f38 - f50;
+ fArr[i8] = f59 + f61;
+ fArr[i6] = f60 + f62;
+ fArr[i16] = f59 - f61;
+ fArr[i14] = f60 - f62;
+ float f63 = f13 + f26;
+ float f64 = f14 - f25;
+ float f65 = f37 + f49;
+ float f66 = f38 + f50;
+ fArr[i12] = f63 - f66;
+ fArr[i10] = f64 + f65;
+ fArr[i20] = f63 + f66;
+ fArr[i18] = f64 - f65;
+ }
+
+ public static void m(d dVar, long j4, d dVar2, long j5) {
+ float b4 = dVar2.b(j5 + 1);
+ float b5 = dVar2.b(j5 + 2);
+ float b6 = dVar2.b(j5 + 3);
+ long j6 = j4 + 16;
+ float b7 = dVar.b(j6) + dVar.b(j4);
+ long j7 = j4 + 1;
+ long j8 = j4 + 17;
+ float b8 = dVar.b(j8) + dVar.b(j7);
+ float b9 = dVar.b(j4) - dVar.b(j6);
+ float b10 = dVar.b(j7) - dVar.b(j8);
+ long j9 = j4 + 8;
+ long j10 = j4 + 24;
+ float b11 = dVar.b(j10) + dVar.b(j9);
+ long j11 = j4 + 9;
+ long j12 = j4 + 25;
+ float b12 = dVar.b(j12) + dVar.b(j11);
+ float b13 = dVar.b(j9) - dVar.b(j10);
+ float b14 = dVar.b(j11) - dVar.b(j12);
+ float f4 = b7 + b11;
+ float f5 = b8 + b12;
+ float f6 = b7 - b11;
+ float f7 = b8 - b12;
+ float f8 = b9 - b14;
+ float f9 = b10 + b13;
+ float f10 = b9 + b14;
+ float f11 = b10 - b13;
+ long j13 = j4 + 2;
+ long j14 = j4 + 18;
+ float b15 = dVar.b(j14) + dVar.b(j13);
+ long j15 = j4 + 3;
+ long j16 = j4 + 19;
+ float b16 = dVar.b(j16) + dVar.b(j15);
+ float b17 = dVar.b(j13) - dVar.b(j14);
+ float b18 = dVar.b(j15) - dVar.b(j16);
+ long j17 = j4 + 10;
+ long j18 = j4 + 26;
+ float b19 = dVar.b(j18) + dVar.b(j17);
+ long j19 = j4 + 11;
+ long j20 = j4 + 27;
+ float b20 = dVar.b(j20) + dVar.b(j19);
+ float b21 = dVar.b(j17) - dVar.b(j18);
+ float b22 = dVar.b(j19) - dVar.b(j20);
+ float f12 = b15 + b19;
+ float f13 = b16 + b20;
+ float f14 = b15 - b19;
+ float f15 = b16 - b20;
+ float f16 = b17 - b22;
+ float f17 = b18 + b21;
+ float f18 = (b5 * f16) - (b6 * f17);
+ float f19 = (f16 * b6) + (f17 * b5);
+ float f20 = b17 + b22;
+ float f21 = b18 - b21;
+ float f22 = (b6 * f20) - (b5 * f21);
+ float f23 = (f20 * b5) + (f21 * b6);
+ long j21 = j4 + 4;
+ long j22 = j4 + 20;
+ float b23 = dVar.b(j22) + dVar.b(j21);
+ long j23 = j4 + 5;
+ long j24 = j4 + 21;
+ float b24 = dVar.b(j24) + dVar.b(j23);
+ float b25 = dVar.b(j21) - dVar.b(j22);
+ float b26 = dVar.b(j23) - dVar.b(j24);
+ long j25 = j4 + 12;
+ long j26 = j4 + 28;
+ float b27 = dVar.b(j26) + dVar.b(j25);
+ long j27 = j4 + 13;
+ long j28 = j4 + 29;
+ float b28 = dVar.b(j28) + dVar.b(j27);
+ float b29 = dVar.b(j25) - dVar.b(j26);
+ float b30 = dVar.b(j27) - dVar.b(j28);
+ float f24 = b23 + b27;
+ float f25 = b24 + b28;
+ float f26 = b23 - b27;
+ float f27 = b24 - b28;
+ float f28 = b25 - b30;
+ float f29 = b26 + b29;
+ float f30 = (f28 - f29) * b4;
+ float f31 = (f29 + f28) * b4;
+ float f32 = b25 + b30;
+ float f33 = b26 - b29;
+ float f34 = (f32 + f33) * b4;
+ float f35 = (f33 - f32) * b4;
+ long j29 = j4 + 6;
+ long j30 = j4 + 22;
+ float b31 = dVar.b(j30) + dVar.b(j29);
+ long j31 = j4 + 7;
+ long j32 = j4 + 23;
+ float b32 = dVar.b(j32) + dVar.b(j31);
+ float b33 = dVar.b(j29) - dVar.b(j30);
+ float b34 = dVar.b(j31) - dVar.b(j32);
+ long j33 = j4 + 14;
+ long j34 = j4 + 30;
+ float b35 = dVar.b(j34) + dVar.b(j33);
+ long j35 = j4 + 15;
+ long j36 = j4 + 31;
+ float b36 = dVar.b(j36) + dVar.b(j35);
+ float b37 = dVar.b(j33) - dVar.b(j34);
+ float b38 = dVar.b(j35) - dVar.b(j36);
+ float f36 = b31 + b35;
+ float f37 = b32 + b36;
+ float f38 = b31 - b35;
+ float f39 = b32 - b36;
+ float f40 = b33 - b38;
+ float f41 = b34 + b37;
+ float f42 = (b6 * f40) - (b5 * f41);
+ float f43 = (f40 * b5) + (f41 * b6);
+ float f44 = b33 + b38;
+ float f45 = b34 - b37;
+ float f46 = (b5 * f44) - (b6 * f45);
+ float f47 = (b6 * f44) + (b5 * f45);
+ float f48 = f10 - f34;
+ float f49 = f11 - f35;
+ float f50 = f10 + f34;
+ float f51 = f11 + f35;
+ float f52 = f22 - f46;
+ float f53 = f23 - f47;
+ float f54 = f22 + f46;
+ float f55 = f23 + f47;
+ dVar.c(j12, AbstractC1518b.j(f48, f52, dVar, j10, f49, f53));
+ dVar.c(j20, AbstractC1518b.l(f48, f52, dVar, j18, f49, f53));
+ dVar.c(j28, AbstractC1518b.a(f50, f55, dVar, j26, f51, f54));
+ dVar.c(j36, AbstractC1518b.m(f50, f55, dVar, j34, f51, f54));
+ float f56 = f8 + f30;
+ float f57 = f9 + f31;
+ float f58 = f8 - f30;
+ float f59 = f9 - f31;
+ float f60 = f18 + f42;
+ float f61 = f19 + f43;
+ float f62 = f18 - f42;
+ float f63 = f19 - f43;
+ dVar.c(j8, AbstractC1518b.j(f56, f60, dVar, j6, f57, f61));
+ dVar.c(j16, AbstractC1518b.l(f56, f60, dVar, j14, f57, f61));
+ dVar.c(j24, AbstractC1518b.a(f58, f63, dVar, j22, f59, f62));
+ dVar.c(j32, AbstractC1518b.m(f58, f63, dVar, j30, f59, f62));
+ float f64 = f14 - f39;
+ float f65 = f15 + f38;
+ float f66 = (f64 - f65) * b4;
+ float f67 = (f65 + f64) * b4;
+ float f68 = f14 + f39;
+ float f69 = f15 - f38;
+ float f70 = (f68 - f69) * b4;
+ float f71 = (f69 + f68) * b4;
+ float f72 = f6 - f27;
+ float f73 = f7 + f26;
+ float f74 = f6 + f27;
+ float f75 = f7 - f26;
+ dVar.c(j11, AbstractC1518b.j(f72, f66, dVar, j9, f73, f67));
+ dVar.c(j19, AbstractC1518b.l(f72, f66, dVar, j17, f73, f67));
+ dVar.c(j27, AbstractC1518b.a(f74, f71, dVar, j25, f75, f70));
+ dVar.c(j35, AbstractC1518b.m(f74, f71, dVar, j33, f75, f70));
+ float f76 = f4 + f24;
+ float f77 = f5 + f25;
+ float f78 = f4 - f24;
+ float f79 = f5 - f25;
+ float f80 = f12 + f36;
+ float f81 = f13 + f37;
+ float f82 = f12 - f36;
+ float f83 = f13 - f37;
+ dVar.c(j7, AbstractC1518b.j(f76, f80, dVar, j4, f77, f81));
+ dVar.c(j15, AbstractC1518b.l(f76, f80, dVar, j13, f77, f81));
+ dVar.c(j23, AbstractC1518b.a(f78, f83, dVar, j21, f79, f82));
+ dVar.c(j31, AbstractC1518b.m(f78, f83, dVar, j29, f79, f82));
+ }
+
+ public static void n(float[] fArr, int i4, float[] fArr2, int i5) {
+ float f4 = fArr2[i5 + 1];
+ float f5 = fArr2[i5 + 2];
+ float f6 = fArr2[i5 + 3];
+ float f7 = fArr[i4];
+ int i6 = i4 + 16;
+ float f8 = fArr[i6];
+ float f9 = f7 + f8;
+ int i7 = i4 + 1;
+ float f10 = fArr[i7];
+ int i8 = i4 + 17;
+ float f11 = fArr[i8];
+ float f12 = f10 + f11;
+ float f13 = f7 - f8;
+ float f14 = f10 - f11;
+ int i9 = i4 + 8;
+ float f15 = fArr[i9];
+ int i10 = i4 + 24;
+ float f16 = fArr[i10];
+ float f17 = f15 + f16;
+ int i11 = i4 + 9;
+ float f18 = fArr[i11];
+ int i12 = i4 + 25;
+ float f19 = fArr[i12];
+ float f20 = f18 + f19;
+ float f21 = f15 - f16;
+ float f22 = f18 - f19;
+ float f23 = f9 + f17;
+ float f24 = f12 + f20;
+ float f25 = f9 - f17;
+ float f26 = f12 - f20;
+ float f27 = f13 - f22;
+ float f28 = f14 + f21;
+ float f29 = f13 + f22;
+ float f30 = f14 - f21;
+ int i13 = i4 + 2;
+ float f31 = fArr[i13];
+ int i14 = i4 + 18;
+ float f32 = fArr[i14];
+ float f33 = f31 + f32;
+ int i15 = i4 + 3;
+ float f34 = fArr[i15];
+ int i16 = i4 + 19;
+ float f35 = fArr[i16];
+ float f36 = f34 + f35;
+ float f37 = f31 - f32;
+ float f38 = f34 - f35;
+ int i17 = i4 + 10;
+ float f39 = fArr[i17];
+ int i18 = i4 + 26;
+ float f40 = fArr[i18];
+ float f41 = f39 + f40;
+ int i19 = i4 + 11;
+ float f42 = fArr[i19];
+ int i20 = i4 + 27;
+ float f43 = fArr[i20];
+ float f44 = f42 + f43;
+ float f45 = f39 - f40;
+ float f46 = f42 - f43;
+ float f47 = f33 + f41;
+ float f48 = f36 + f44;
+ float f49 = f33 - f41;
+ float f50 = f36 - f44;
+ float f51 = f37 - f46;
+ float f52 = f38 + f45;
+ float f53 = (f5 * f51) - (f6 * f52);
+ float f54 = (f51 * f6) + (f52 * f5);
+ float f55 = f37 + f46;
+ float f56 = f38 - f45;
+ float f57 = (f6 * f55) - (f5 * f56);
+ float f58 = (f55 * f5) + (f56 * f6);
+ int i21 = i4 + 4;
+ float f59 = fArr[i21];
+ int i22 = i4 + 20;
+ float f60 = fArr[i22];
+ float f61 = f59 + f60;
+ int i23 = i4 + 5;
+ float f62 = fArr[i23];
+ int i24 = i4 + 21;
+ float f63 = fArr[i24];
+ float f64 = f62 + f63;
+ float f65 = f59 - f60;
+ float f66 = f62 - f63;
+ int i25 = i4 + 12;
+ float f67 = fArr[i25];
+ int i26 = i4 + 28;
+ float f68 = fArr[i26];
+ float f69 = f67 + f68;
+ int i27 = i4 + 13;
+ float f70 = fArr[i27];
+ int i28 = i4 + 29;
+ float f71 = fArr[i28];
+ float f72 = f70 + f71;
+ float f73 = f67 - f68;
+ float f74 = f70 - f71;
+ float f75 = f61 + f69;
+ float f76 = f64 + f72;
+ float f77 = f61 - f69;
+ float f78 = f64 - f72;
+ float f79 = f65 - f74;
+ float f80 = f66 + f73;
+ float f81 = (f79 - f80) * f4;
+ float f82 = (f80 + f79) * f4;
+ float f83 = f65 + f74;
+ float f84 = f66 - f73;
+ float f85 = (f83 + f84) * f4;
+ float f86 = (f84 - f83) * f4;
+ int i29 = i4 + 6;
+ float f87 = fArr[i29];
+ int i30 = i4 + 22;
+ float f88 = fArr[i30];
+ float f89 = f87 + f88;
+ int i31 = i4 + 7;
+ float f90 = fArr[i31];
+ int i32 = i4 + 23;
+ float f91 = fArr[i32];
+ float f92 = f90 + f91;
+ float f93 = f87 - f88;
+ float f94 = f90 - f91;
+ int i33 = i4 + 14;
+ float f95 = fArr[i33];
+ int i34 = i4 + 30;
+ float f96 = fArr[i34];
+ float f97 = f95 + f96;
+ int i35 = i4 + 15;
+ float f98 = fArr[i35];
+ int i36 = i4 + 31;
+ float f99 = fArr[i36];
+ float f100 = f98 + f99;
+ float f101 = f95 - f96;
+ float f102 = f98 - f99;
+ float f103 = f89 + f97;
+ float f104 = f92 + f100;
+ float f105 = f89 - f97;
+ float f106 = f92 - f100;
+ float f107 = f93 - f102;
+ float f108 = f94 + f101;
+ float f109 = (f6 * f107) - (f5 * f108);
+ float f110 = (f107 * f5) + (f108 * f6);
+ float f111 = f93 + f102;
+ float f112 = f94 - f101;
+ float f113 = (f5 * f111) - (f6 * f112);
+ float f114 = (f6 * f111) + (f5 * f112);
+ float f115 = f29 - f85;
+ float f116 = f30 - f86;
+ float f117 = f29 + f85;
+ float f118 = f30 + f86;
+ float f119 = f57 - f113;
+ float f120 = f58 - f114;
+ float f121 = f57 + f113;
+ float f122 = f58 + f114;
+ fArr[i10] = f115 + f119;
+ fArr[i12] = f116 + f120;
+ fArr[i18] = f115 - f119;
+ fArr[i20] = f116 - f120;
+ fArr[i26] = f117 - f122;
+ fArr[i28] = f118 + f121;
+ fArr[i34] = f117 + f122;
+ fArr[i36] = f118 - f121;
+ float f123 = f27 + f81;
+ float f124 = f28 + f82;
+ float f125 = f27 - f81;
+ float f126 = f28 - f82;
+ float f127 = f53 + f109;
+ float f128 = f54 + f110;
+ float f129 = f53 - f109;
+ float f130 = f54 - f110;
+ fArr[i6] = f123 + f127;
+ fArr[i8] = f124 + f128;
+ fArr[i14] = f123 - f127;
+ fArr[i16] = f124 - f128;
+ fArr[i22] = f125 - f130;
+ fArr[i24] = f126 + f129;
+ fArr[i30] = f125 + f130;
+ fArr[i32] = f126 - f129;
+ float f131 = f49 - f106;
+ float f132 = f50 + f105;
+ float f133 = (f131 - f132) * f4;
+ float f134 = (f132 + f131) * f4;
+ float f135 = f49 + f106;
+ float f136 = f50 - f105;
+ float f137 = (f135 - f136) * f4;
+ float f138 = (f136 + f135) * f4;
+ float f139 = f25 - f78;
+ float f140 = f26 + f77;
+ float f141 = f25 + f78;
+ float f142 = f26 - f77;
+ fArr[i9] = f139 + f133;
+ fArr[i11] = f140 + f134;
+ fArr[i17] = f139 - f133;
+ fArr[i19] = f140 - f134;
+ fArr[i25] = f141 - f138;
+ fArr[i27] = f142 + f137;
+ fArr[i33] = f141 + f138;
+ fArr[i35] = f142 - f137;
+ float f143 = f23 + f75;
+ float f144 = f24 + f76;
+ float f145 = f23 - f75;
+ float f146 = f24 - f76;
+ float f147 = f47 + f103;
+ float f148 = f48 + f104;
+ float f149 = f47 - f103;
+ float f150 = f48 - f104;
+ fArr[i4] = f143 + f147;
+ fArr[i7] = f144 + f148;
+ fArr[i13] = f143 - f147;
+ fArr[i15] = f144 - f148;
+ fArr[i21] = f145 - f150;
+ fArr[i23] = f146 + f149;
+ fArr[i29] = f145 + f150;
+ fArr[i31] = f146 - f149;
+ }
+
+ public static void o(d dVar, long j4, d dVar2, long j5) {
+ float b4 = dVar2.b(j5 + 1);
+ float b5 = dVar2.b(j5 + 4);
+ float b6 = dVar2.b(j5 + 5);
+ float b7 = dVar2.b(j5 + 6);
+ float f4 = -dVar2.b(j5 + 7);
+ float b8 = dVar2.b(j5 + 8);
+ float b9 = dVar2.b(j5 + 9);
+ long j6 = j4 + 17;
+ float b10 = dVar.b(j4) - dVar.b(j6);
+ long j7 = j4 + 1;
+ long j8 = j4 + 16;
+ float b11 = dVar.b(j8) + dVar.b(j7);
+ long j9 = j4 + 8;
+ long j10 = j4 + 25;
+ float b12 = dVar.b(j9) - dVar.b(j10);
+ long j11 = j4 + 9;
+ float b13 = dVar.b(j11);
+ long j12 = j4 + 24;
+ float b14 = dVar.b(j12) + b13;
+ float f5 = (b12 - b14) * b4;
+ float f6 = (b14 + b12) * b4;
+ float f7 = b10 + f5;
+ float f8 = b11 + f6;
+ float f9 = b10 - f5;
+ float f10 = b11 - f6;
+ float b15 = dVar.b(j6) + dVar.b(j4);
+ float b16 = dVar.b(j7) - dVar.b(j8);
+ float b17 = dVar.b(j10) + dVar.b(j9);
+ float b18 = dVar.b(j11) - dVar.b(j12);
+ float f11 = (b17 - b18) * b4;
+ float f12 = (b18 + b17) * b4;
+ float f13 = b15 - f12;
+ float f14 = b16 + f11;
+ float f15 = b15 + f12;
+ float f16 = b16 - f11;
+ long j13 = j4 + 2;
+ long j14 = j4 + 19;
+ float b19 = dVar.b(j13) - dVar.b(j14);
+ long j15 = j4 + 3;
+ long j16 = j4 + 18;
+ float b20 = dVar.b(j16) + dVar.b(j15);
+ float f17 = (b5 * b19) - (b6 * b20);
+ float f18 = (b19 * b6) + (b20 * b5);
+ long j17 = j4 + 10;
+ long j18 = j4 + 27;
+ float b21 = dVar.b(j17) - dVar.b(j18);
+ long j19 = j4 + 11;
+ float b22 = dVar.b(j19);
+ long j20 = j4 + 26;
+ float b23 = dVar.b(j20) + b22;
+ float f19 = (f4 * b21) - (b7 * b23);
+ float f20 = (b21 * b7) + (b23 * f4);
+ float f21 = f17 + f19;
+ float f22 = f18 + f20;
+ float f23 = f17 - f19;
+ float f24 = f18 - f20;
+ float b24 = dVar.b(j14) + dVar.b(j13);
+ float b25 = dVar.b(j15) - dVar.b(j16);
+ float f25 = (b7 * b24) - (f4 * b25);
+ float f26 = (b24 * f4) + (b25 * b7);
+ float b26 = dVar.b(j18) + dVar.b(j17);
+ float b27 = dVar.b(j19) - dVar.b(j20);
+ float f27 = (b6 * b27) + (b5 * b26);
+ float f28 = (b27 * b5) - (b6 * b26);
+ float f29 = f25 - f27;
+ float f30 = f26 - f28;
+ float f31 = f25 + f27;
+ float f32 = f26 + f28;
+ long j21 = j4 + 4;
+ long j22 = j4 + 21;
+ float b28 = dVar.b(j21) - dVar.b(j22);
+ long j23 = j4 + 5;
+ long j24 = j4 + 20;
+ float b29 = dVar.b(j24) + dVar.b(j23);
+ float f33 = (b8 * b28) - (b9 * b29);
+ float f34 = (b28 * b9) + (b29 * b8);
+ long j25 = j4 + 12;
+ long j26 = j4 + 29;
+ float b30 = dVar.b(j25) - dVar.b(j26);
+ long j27 = j4 + 13;
+ float b31 = dVar.b(j27);
+ long j28 = j4 + 28;
+ float b32 = dVar.b(j28) + b31;
+ float f35 = (b9 * b30) - (b8 * b32);
+ float f36 = (b30 * b8) + (b32 * b9);
+ float f37 = f33 + f35;
+ float f38 = f34 + f36;
+ float f39 = f33 - f35;
+ float f40 = f34 - f36;
+ float b33 = dVar.b(j22) + dVar.b(j21);
+ float b34 = dVar.b(j23) - dVar.b(j24);
+ float f41 = (b9 * b33) - (b8 * b34);
+ float f42 = (b33 * b8) + (b34 * b9);
+ float b35 = dVar.b(j26) + dVar.b(j25);
+ float b36 = dVar.b(j27) - dVar.b(j28);
+ float f43 = (b8 * b35) - (b9 * b36);
+ float f44 = (b9 * b35) + (b36 * b8);
+ float f45 = f41 - f43;
+ float f46 = f42 - f44;
+ float f47 = f41 + f43;
+ float f48 = f42 + f44;
+ long j29 = j4 + 6;
+ long j30 = j4 + 23;
+ float b37 = dVar.b(j29) - dVar.b(j30);
+ long j31 = j4 + 7;
+ long j32 = j4 + 22;
+ float b38 = dVar.b(j32) + dVar.b(j31);
+ float f49 = (b7 * b37) - (f4 * b38);
+ float f50 = (b37 * f4) + (b38 * b7);
+ long j33 = j4 + 14;
+ long j34 = j4 + 31;
+ float b39 = dVar.b(j33) - dVar.b(j34);
+ long j35 = j4 + 15;
+ float b40 = dVar.b(j35);
+ long j36 = j4 + 30;
+ float b41 = dVar.b(j36) + b40;
+ float f51 = (b6 * b39) - (b5 * b41);
+ float f52 = (b39 * b5) + (b41 * b6);
+ float f53 = f49 + f51;
+ float f54 = f50 + f52;
+ float f55 = f49 - f51;
+ float f56 = f50 - f52;
+ float b42 = dVar.b(j30) + dVar.b(j29);
+ float b43 = dVar.b(j31) - dVar.b(j32);
+ float f57 = (b5 * b43) + (b6 * b42);
+ float f58 = (b43 * b6) - (b42 * b5);
+ float b44 = dVar.b(j34) + dVar.b(j33);
+ float b45 = dVar.b(j35) - dVar.b(j36);
+ float f59 = (f4 * b44) - (b7 * b45);
+ float f60 = (b7 * b44) + (b45 * f4);
+ float f61 = f57 + f59;
+ float f62 = f58 + f60;
+ float f63 = f57 - f59;
+ float f64 = f58 - f60;
+ float f65 = f7 + f37;
+ float f66 = f8 + f38;
+ float f67 = f21 + f53;
+ float f68 = f22 + f54;
+ dVar.c(j7, AbstractC1518b.j(f65, f67, dVar, j4, f66, f68));
+ dVar.c(j15, AbstractC1518b.l(f65, f67, dVar, j13, f66, f68));
+ float f69 = f7 - f37;
+ float f70 = f8 - f38;
+ float f71 = f21 - f53;
+ float f72 = f22 - f54;
+ dVar.c(j23, AbstractC1518b.a(f69, f72, dVar, j21, f70, f71));
+ dVar.c(j31, AbstractC1518b.m(f69, f72, dVar, j29, f70, f71));
+ float f73 = f9 - f40;
+ float f74 = f10 + f39;
+ float f75 = f23 - f56;
+ float f76 = f24 + f55;
+ float f77 = (f75 - f76) * b4;
+ float f78 = (f76 + f75) * b4;
+ dVar.c(j11, AbstractC1518b.j(f73, f77, dVar, j9, f74, f78));
+ dVar.c(j19, AbstractC1518b.l(f73, f77, dVar, j17, f74, f78));
+ float f79 = f9 + f40;
+ float f80 = f10 - f39;
+ float f81 = f23 + f56;
+ float f82 = f24 - f55;
+ float f83 = (f81 - f82) * b4;
+ float f84 = (f82 + f81) * b4;
+ dVar.c(j27, AbstractC1518b.a(f79, f84, dVar, j25, f80, f83));
+ dVar.c(j35, AbstractC1518b.m(f79, f84, dVar, j33, f80, f83));
+ float f85 = f13 + f45;
+ float f86 = f14 + f46;
+ float f87 = f29 - f61;
+ float f88 = f30 - f62;
+ dVar.c(j6, AbstractC1518b.j(f85, f87, dVar, j8, f86, f88));
+ dVar.c(j14, AbstractC1518b.l(f85, f87, dVar, j16, f86, f88));
+ float f89 = f13 - f45;
+ float f90 = f14 - f46;
+ float f91 = f29 + f61;
+ float f92 = f30 + f62;
+ dVar.c(j22, AbstractC1518b.a(f89, f92, dVar, j24, f90, f91));
+ dVar.c(j30, AbstractC1518b.m(f89, f92, dVar, j32, f90, f91));
+ float f93 = f15 - f48;
+ float f94 = f16 + f47;
+ float f95 = f31 + f64;
+ float f96 = f32 - f63;
+ float f97 = (f95 - f96) * b4;
+ float f98 = (f96 + f95) * b4;
+ dVar.c(j10, AbstractC1518b.j(f93, f97, dVar, j12, f94, f98));
+ dVar.c(j18, AbstractC1518b.l(f93, f97, dVar, j20, f94, f98));
+ float f99 = f15 + f48;
+ float f100 = f16 - f47;
+ float f101 = f31 - f64;
+ float f102 = f32 + f63;
+ float f103 = (f101 - f102) * b4;
+ float f104 = (f102 + f101) * b4;
+ dVar.c(j26, AbstractC1518b.a(f99, f104, dVar, j28, f100, f103));
+ dVar.c(j34, AbstractC1518b.m(f99, f104, dVar, j36, f100, f103));
+ }
+
+ public static void p(float[] fArr, int i4, float[] fArr2, int i5) {
+ float f4 = fArr2[i5 + 1];
+ float f5 = fArr2[i5 + 4];
+ float f6 = fArr2[i5 + 5];
+ float f7 = fArr2[i5 + 6];
+ float f8 = -fArr2[i5 + 7];
+ float f9 = fArr2[i5 + 8];
+ float f10 = fArr2[i5 + 9];
+ float f11 = fArr[i4];
+ int i6 = i4 + 17;
+ float f12 = fArr[i6];
+ float f13 = f11 - f12;
+ int i7 = i4 + 1;
+ float f14 = fArr[i7];
+ int i8 = i4 + 16;
+ float f15 = fArr[i8];
+ float f16 = f14 + f15;
+ int i9 = i4 + 8;
+ float f17 = fArr[i9];
+ int i10 = i4 + 25;
+ float f18 = fArr[i10];
+ float f19 = f17 - f18;
+ int i11 = i4 + 9;
+ float f20 = fArr[i11];
+ int i12 = i4 + 24;
+ float f21 = fArr[i12];
+ float f22 = f20 + f21;
+ float f23 = (f19 - f22) * f4;
+ float f24 = (f22 + f19) * f4;
+ float f25 = f13 + f23;
+ float f26 = f16 + f24;
+ float f27 = f13 - f23;
+ float f28 = f16 - f24;
+ float f29 = f11 + f12;
+ float f30 = f14 - f15;
+ float f31 = f17 + f18;
+ float f32 = f20 - f21;
+ float f33 = (f31 - f32) * f4;
+ float f34 = (f32 + f31) * f4;
+ float f35 = f29 - f34;
+ float f36 = f30 + f33;
+ float f37 = f29 + f34;
+ float f38 = f30 - f33;
+ int i13 = i4 + 2;
+ float f39 = fArr[i13];
+ int i14 = i4 + 19;
+ float f40 = fArr[i14];
+ float f41 = f39 - f40;
+ int i15 = i4 + 3;
+ float f42 = fArr[i15];
+ int i16 = i4 + 18;
+ float f43 = fArr[i16];
+ float f44 = f42 + f43;
+ float f45 = (f5 * f41) - (f6 * f44);
+ float f46 = (f41 * f6) + (f44 * f5);
+ int i17 = i4 + 10;
+ float f47 = fArr[i17];
+ int i18 = i4 + 27;
+ float f48 = fArr[i18];
+ float f49 = f47 - f48;
+ int i19 = i4 + 11;
+ float f50 = fArr[i19];
+ int i20 = i4 + 26;
+ float f51 = fArr[i20];
+ float f52 = f50 + f51;
+ float f53 = (f8 * f49) - (f7 * f52);
+ float f54 = (f49 * f7) + (f52 * f8);
+ float f55 = f45 + f53;
+ float f56 = f46 + f54;
+ float f57 = f45 - f53;
+ float f58 = f46 - f54;
+ float f59 = f39 + f40;
+ float f60 = f42 - f43;
+ float f61 = (f7 * f59) - (f8 * f60);
+ float f62 = (f59 * f8) + (f60 * f7);
+ float f63 = f47 + f48;
+ float f64 = f50 - f51;
+ float f65 = (f6 * f64) + (f5 * f63);
+ float f66 = (f64 * f5) - (f63 * f6);
+ float f67 = f61 - f65;
+ float f68 = f62 - f66;
+ float f69 = f61 + f65;
+ float f70 = f62 + f66;
+ int i21 = i4 + 4;
+ float f71 = fArr[i21];
+ int i22 = i4 + 21;
+ float f72 = fArr[i22];
+ float f73 = f71 - f72;
+ int i23 = i4 + 5;
+ float f74 = fArr[i23];
+ int i24 = i4 + 20;
+ float f75 = fArr[i24];
+ float f76 = f74 + f75;
+ float f77 = (f9 * f73) - (f10 * f76);
+ float f78 = (f73 * f10) + (f76 * f9);
+ int i25 = i4 + 12;
+ float f79 = fArr[i25];
+ int i26 = i4 + 29;
+ float f80 = fArr[i26];
+ float f81 = f79 - f80;
+ int i27 = i4 + 13;
+ float f82 = fArr[i27];
+ int i28 = i4 + 28;
+ float f83 = fArr[i28];
+ float f84 = f82 + f83;
+ float f85 = (f10 * f81) - (f9 * f84);
+ float f86 = (f81 * f9) + (f84 * f10);
+ float f87 = f77 + f85;
+ float f88 = f78 + f86;
+ float f89 = f77 - f85;
+ float f90 = f78 - f86;
+ float f91 = f71 + f72;
+ float f92 = f74 - f75;
+ float f93 = (f10 * f91) - (f9 * f92);
+ float f94 = (f91 * f9) + (f92 * f10);
+ float f95 = f79 + f80;
+ float f96 = f82 - f83;
+ float f97 = (f9 * f95) - (f10 * f96);
+ float f98 = (f10 * f95) + (f9 * f96);
+ float f99 = f93 - f97;
+ float f100 = f94 - f98;
+ float f101 = f93 + f97;
+ float f102 = f94 + f98;
+ int i29 = i4 + 6;
+ float f103 = fArr[i29];
+ int i30 = i4 + 23;
+ float f104 = fArr[i30];
+ float f105 = f103 - f104;
+ int i31 = i4 + 7;
+ float f106 = fArr[i31];
+ int i32 = i4 + 22;
+ float f107 = fArr[i32];
+ float f108 = f106 + f107;
+ float f109 = (f7 * f105) - (f8 * f108);
+ float f110 = (f105 * f8) + (f108 * f7);
+ int i33 = i4 + 14;
+ float f111 = fArr[i33];
+ int i34 = i4 + 31;
+ float f112 = fArr[i34];
+ float f113 = f111 - f112;
+ int i35 = i4 + 15;
+ float f114 = fArr[i35];
+ int i36 = i4 + 30;
+ float f115 = fArr[i36];
+ float f116 = f114 + f115;
+ float f117 = (f6 * f113) - (f5 * f116);
+ float f118 = (f113 * f5) + (f116 * f6);
+ float f119 = f109 + f117;
+ float f120 = f110 + f118;
+ float f121 = f109 - f117;
+ float f122 = f110 - f118;
+ float f123 = f103 + f104;
+ float f124 = f106 - f107;
+ float f125 = (f5 * f124) + (f6 * f123);
+ float f126 = (f6 * f124) - (f5 * f123);
+ float f127 = f111 + f112;
+ float f128 = f114 - f115;
+ float f129 = (f8 * f127) - (f7 * f128);
+ float f130 = (f7 * f127) + (f8 * f128);
+ float f131 = f125 + f129;
+ float f132 = f126 + f130;
+ float f133 = f125 - f129;
+ float f134 = f126 - f130;
+ float f135 = f25 + f87;
+ float f136 = f26 + f88;
+ float f137 = f55 + f119;
+ float f138 = f56 + f120;
+ fArr[i4] = f135 + f137;
+ fArr[i7] = f136 + f138;
+ fArr[i13] = f135 - f137;
+ fArr[i15] = f136 - f138;
+ float f139 = f25 - f87;
+ float f140 = f26 - f88;
+ float f141 = f55 - f119;
+ float f142 = f56 - f120;
+ fArr[i21] = f139 - f142;
+ fArr[i23] = f140 + f141;
+ fArr[i29] = f139 + f142;
+ fArr[i31] = f140 - f141;
+ float f143 = f27 - f90;
+ float f144 = f28 + f89;
+ float f145 = f57 - f122;
+ float f146 = f58 + f121;
+ float f147 = (f145 - f146) * f4;
+ float f148 = (f146 + f145) * f4;
+ fArr[i9] = f143 + f147;
+ fArr[i11] = f144 + f148;
+ fArr[i17] = f143 - f147;
+ fArr[i19] = f144 - f148;
+ float f149 = f27 + f90;
+ float f150 = f28 - f89;
+ float f151 = f57 + f122;
+ float f152 = f58 - f121;
+ float f153 = (f151 - f152) * f4;
+ float f154 = (f152 + f151) * f4;
+ fArr[i25] = f149 - f154;
+ fArr[i27] = f150 + f153;
+ fArr[i33] = f149 + f154;
+ fArr[i35] = f150 - f153;
+ float f155 = f35 + f99;
+ float f156 = f36 + f100;
+ float f157 = f67 - f131;
+ float f158 = f68 - f132;
+ fArr[i8] = f155 + f157;
+ fArr[i6] = f156 + f158;
+ fArr[i16] = f155 - f157;
+ fArr[i14] = f156 - f158;
+ float f159 = f35 - f99;
+ float f160 = f36 - f100;
+ float f161 = f67 + f131;
+ float f162 = f68 + f132;
+ fArr[i24] = f159 - f162;
+ fArr[i22] = f160 + f161;
+ fArr[i32] = f159 + f162;
+ fArr[i30] = f160 - f161;
+ float f163 = f37 - f102;
+ float f164 = f38 + f101;
+ float f165 = f69 + f134;
+ float f166 = f70 - f133;
+ float f167 = (f165 - f166) * f4;
+ float f168 = (f166 + f165) * f4;
+ fArr[i12] = f163 + f167;
+ fArr[i10] = f164 + f168;
+ fArr[i20] = f163 - f167;
+ fArr[i18] = f164 - f168;
+ float f169 = f37 + f102;
+ float f170 = f38 - f101;
+ float f171 = f69 - f134;
+ float f172 = f70 + f133;
+ float f173 = (f171 - f172) * f4;
+ float f174 = (f172 + f171) * f4;
+ fArr[i28] = f169 - f174;
+ fArr[i26] = f170 + f173;
+ fArr[i36] = f169 + f174;
+ fArr[i34] = f170 - f173;
+ }
+
+ public static void q(int i4, float[] fArr, int i5, int[] iArr, int i6, float[] fArr2) {
+ if (i4 <= 8) {
+ if (i4 != 8) {
+ if (i4 == 4) {
+ H(fArr, i5);
+ return;
+ }
+ return;
+ }
+ float f4 = fArr[i5];
+ int i7 = i5 + 4;
+ float f5 = fArr[i7];
+ float f6 = f4 + f5;
+ int i8 = i5 + 1;
+ float f7 = fArr[i8];
+ int i9 = i5 + 5;
+ float f8 = fArr[i9];
+ float f9 = f7 + f8;
+ float f10 = f4 - f5;
+ float f11 = f7 - f8;
+ int i10 = i5 + 2;
+ float f12 = fArr[i10];
+ int i11 = i5 + 6;
+ float f13 = fArr[i11];
+ float f14 = f12 + f13;
+ int i12 = i5 + 3;
+ float f15 = fArr[i12];
+ int i13 = i5 + 7;
+ float f16 = fArr[i13];
+ float f17 = f15 + f16;
+ float f18 = f12 - f13;
+ float f19 = f15 - f16;
+ fArr[i5] = f6 + f14;
+ fArr[i8] = f9 + f17;
+ fArr[i10] = f10 - f19;
+ fArr[i12] = f11 + f18;
+ fArr[i7] = f6 - f14;
+ fArr[i9] = f9 - f17;
+ fArr[i11] = f10 + f19;
+ fArr[i13] = f11 - f18;
+ return;
+ }
+ if (i4 <= 32) {
+ if (i4 == 32) {
+ n(fArr, i5, fArr2, i6 - 8);
+ int i14 = i5 + 2;
+ float f20 = fArr[i14];
+ int i15 = i5 + 3;
+ float f21 = fArr[i15];
+ int i16 = i5 + 4;
+ float f22 = fArr[i16];
+ int i17 = i5 + 5;
+ float f23 = fArr[i17];
+ int i18 = i5 + 6;
+ float f24 = fArr[i18];
+ int i19 = i5 + 7;
+ float f25 = fArr[i19];
+ int i20 = i5 + 8;
+ float f26 = fArr[i20];
+ int i21 = i5 + 9;
+ float f27 = fArr[i21];
+ int i22 = i5 + 10;
+ float f28 = fArr[i22];
+ int i23 = i5 + 11;
+ float f29 = fArr[i23];
+ int i24 = i5 + 14;
+ float f30 = fArr[i24];
+ int i25 = i5 + 15;
+ float f31 = fArr[i25];
+ int i26 = i5 + 16;
+ float f32 = fArr[i26];
+ int i27 = i5 + 17;
+ float f33 = fArr[i27];
+ int i28 = i5 + 20;
+ float f34 = fArr[i28];
+ int i29 = i5 + 21;
+ float f35 = fArr[i29];
+ int i30 = i5 + 22;
+ float f36 = fArr[i30];
+ int i31 = i5 + 23;
+ float f37 = fArr[i31];
+ int i32 = i5 + 24;
+ float f38 = fArr[i32];
+ int i33 = i5 + 25;
+ float f39 = fArr[i33];
+ int i34 = i5 + 26;
+ float f40 = fArr[i34];
+ int i35 = i5 + 27;
+ float f41 = fArr[i35];
+ int i36 = i5 + 28;
+ float f42 = fArr[i36];
+ int i37 = i5 + 29;
+ float f43 = fArr[i37];
+ fArr[i14] = f32;
+ fArr[i15] = f33;
+ fArr[i16] = f26;
+ fArr[i17] = f27;
+ fArr[i18] = f38;
+ fArr[i19] = f39;
+ fArr[i20] = f22;
+ fArr[i21] = f23;
+ fArr[i22] = f34;
+ fArr[i23] = f35;
+ fArr[i24] = f42;
+ fArr[i25] = f43;
+ fArr[i26] = f20;
+ fArr[i27] = f21;
+ fArr[i28] = f28;
+ fArr[i29] = f29;
+ fArr[i30] = f40;
+ fArr[i31] = f41;
+ fArr[i32] = f24;
+ fArr[i33] = f25;
+ fArr[i34] = f36;
+ fArr[i35] = f37;
+ fArr[i36] = f30;
+ fArr[i37] = f31;
+ return;
+ }
+ j(fArr, i5, fArr2, 0);
+ int i38 = i5 + 2;
+ float f44 = fArr[i38];
+ int i39 = i5 + 3;
+ float f45 = fArr[i39];
+ int i40 = i5 + 6;
+ float f46 = fArr[i40];
+ int i41 = i5 + 7;
+ float f47 = fArr[i41];
+ int i42 = i5 + 8;
+ float f48 = fArr[i42];
+ int i43 = i5 + 9;
+ float f49 = fArr[i43];
+ int i44 = i5 + 12;
+ float f50 = fArr[i44];
+ int i45 = i5 + 13;
+ float f51 = fArr[i45];
+ fArr[i38] = f48;
+ fArr[i39] = f49;
+ fArr[i40] = f50;
+ fArr[i41] = f51;
+ fArr[i42] = f44;
+ fArr[i43] = f45;
+ fArr[i44] = f46;
+ fArr[i45] = f47;
+ return;
+ }
+ int i46 = i4 >> 2;
+ int i47 = i6 - i46;
+ int i48 = i4 >> 3;
+ int i49 = i48 * 2;
+ int i50 = i49 + i49;
+ int i51 = i50 + i49;
+ int i52 = i5 + i49;
+ int i53 = i50 + i5;
+ int i54 = i51 + i5;
+ float f52 = fArr[i5];
+ float f53 = fArr[i53];
+ float f54 = f52 + f53;
+ int i55 = i5 + 1;
+ float f55 = fArr[i55];
+ int i56 = i53 + 1;
+ float f56 = fArr[i56];
+ float f57 = f55 + f56;
+ float f58 = f52 - f53;
+ float f59 = f55 - f56;
+ float f60 = fArr[i52];
+ float f61 = fArr[i54];
+ float f62 = f60 + f61;
+ int i57 = i52 + 1;
+ float f63 = fArr[i57];
+ int i58 = i54 + 1;
+ float f64 = fArr[i58];
+ float f65 = f63 + f64;
+ float f66 = f60 - f61;
+ float f67 = f63 - f64;
+ fArr[i5] = f54 + f62;
+ fArr[i55] = f57 + f65;
+ fArr[i52] = f54 - f62;
+ fArr[i57] = f57 - f65;
+ fArr[i53] = f58 - f67;
+ fArr[i56] = f59 + f66;
+ fArr[i54] = f58 + f67;
+ fArr[i58] = f59 - f66;
+ float f68 = fArr2[i47 + 1];
+ float f69 = fArr2[i47 + 2];
+ float f70 = fArr2[i47 + 3];
+ float f71 = 1.0f;
+ int i59 = 2;
+ float f72 = 1.0f;
+ float f73 = 0.0f;
+ float f74 = 0.0f;
+ int i60 = 0;
+ while (i59 < i48 - 2) {
+ i60 += 4;
+ int i61 = i47 + i60;
+ float f75 = fArr2[i61];
+ float f76 = (f71 + f75) * f69;
+ float f77 = fArr2[i61 + 1];
+ float f78 = (f73 + f77) * f69;
+ float f79 = fArr2[i61 + 2];
+ float f80 = (f72 + f79) * f70;
+ float f81 = fArr2[i61 + 3];
+ float f82 = (f74 + f81) * f70;
+ int i62 = i59 + i49;
+ int i63 = i62 + i49;
+ int i64 = i63 + i49;
+ int i65 = i5 + i62;
+ int i66 = i5 + i63;
+ int i67 = i5 + i64;
+ int i68 = i5 + i59;
+ float f83 = fArr[i68];
+ float f84 = fArr[i66];
+ float f85 = f83 + f84;
+ int i69 = i68 + 1;
+ float f86 = fArr[i69];
+ int i70 = i66 + 1;
+ float f87 = fArr[i70];
+ float f88 = f86 + f87;
+ float f89 = f83 - f84;
+ float f90 = f86 - f87;
+ int i71 = i68 + 2;
+ float f91 = fArr[i71];
+ int i72 = i66 + 2;
+ float f92 = fArr[i72];
+ float f93 = f91 + f92;
+ int i73 = i68 + 3;
+ float f94 = fArr[i73];
+ int i74 = i66 + 3;
+ float f95 = fArr[i74];
+ float f96 = f94 + f95;
+ float f97 = f91 - f92;
+ float f98 = f94 - f95;
+ float f99 = fArr[i65];
+ float f100 = fArr[i67];
+ float f101 = f99 + f100;
+ int i75 = i65 + 1;
+ float f102 = fArr[i75];
+ int i76 = i67 + 1;
+ float f103 = fArr[i76];
+ float f104 = f102 + f103;
+ float f105 = f99 - f100;
+ float f106 = f102 - f103;
+ int i77 = i65 + 2;
+ float f107 = fArr[i77];
+ int i78 = i67 + 2;
+ float f108 = fArr[i78];
+ float f109 = f107 + f108;
+ int i79 = i65 + 3;
+ float f110 = fArr[i79];
+ int i80 = i67 + 3;
+ float f111 = fArr[i80];
+ float f112 = f110 + f111;
+ float f113 = f107 - f108;
+ float f114 = f110 - f111;
+ fArr[i68] = f85 + f101;
+ fArr[i69] = f88 + f104;
+ fArr[i71] = f93 + f109;
+ fArr[i73] = f96 + f112;
+ fArr[i65] = f85 - f101;
+ fArr[i75] = f88 - f104;
+ fArr[i77] = f93 - f109;
+ fArr[i79] = f96 - f112;
+ float f115 = f89 - f106;
+ float f116 = f90 + f105;
+ fArr[i66] = (f76 * f115) - (f78 * f116);
+ fArr[i70] = (f115 * f78) + (f116 * f76);
+ float f117 = f97 - f114;
+ float f118 = f98 + f113;
+ fArr[i72] = (f75 * f117) - (f77 * f118);
+ fArr[i74] = (f117 * f77) + (f118 * f75);
+ float f119 = f89 + f106;
+ float f120 = f90 - f105;
+ fArr[i67] = (f82 * f120) + (f80 * f119);
+ fArr[i76] = (f120 * f80) - (f119 * f82);
+ float f121 = f97 + f114;
+ float f122 = f98 - f113;
+ fArr[i78] = (f81 * f122) + (f79 * f121);
+ fArr[i80] = (f122 * f79) - (f121 * f81);
+ int i81 = i49 - i59;
+ int i82 = i81 + i49;
+ int i83 = i82 + i49;
+ int i84 = i83 + i49;
+ int i85 = i5 + i81;
+ int i86 = i5 + i82;
+ int i87 = i5 + i83;
+ int i88 = i5 + i84;
+ float f123 = fArr[i85];
+ float f124 = fArr[i87];
+ float f125 = f123 + f124;
+ int i89 = i85 + 1;
+ float f126 = fArr[i89];
+ int i90 = i87 + 1;
+ float f127 = fArr[i90];
+ float f128 = f126 + f127;
+ float f129 = f123 - f124;
+ float f130 = f126 - f127;
+ int i91 = i85 - 2;
+ float f131 = fArr[i91];
+ int i92 = i87 - 2;
+ float f132 = fArr[i92];
+ float f133 = f131 + f132;
+ int i93 = i85 - 1;
+ float f134 = fArr[i93];
+ int i94 = i87 - 1;
+ float f135 = fArr[i94];
+ float f136 = f134 + f135;
+ float f137 = f131 - f132;
+ float f138 = f134 - f135;
+ float f139 = fArr[i86];
+ float f140 = fArr[i88];
+ float f141 = f139 + f140;
+ int i95 = i86 + 1;
+ float f142 = fArr[i95];
+ int i96 = i88 + 1;
+ float f143 = fArr[i96];
+ float f144 = f142 + f143;
+ float f145 = f139 - f140;
+ float f146 = f142 - f143;
+ int i97 = i86 - 2;
+ float f147 = fArr[i97];
+ int i98 = i88 - 2;
+ float f148 = fArr[i98];
+ float f149 = f147 + f148;
+ int i99 = i86 - 1;
+ float f150 = fArr[i99];
+ int i100 = i88 - 1;
+ float f151 = fArr[i100];
+ float f152 = f150 + f151;
+ float f153 = f147 - f148;
+ float f154 = f150 - f151;
+ fArr[i85] = f125 + f141;
+ fArr[i89] = f128 + f144;
+ fArr[i91] = f133 + f149;
+ fArr[i93] = f136 + f152;
+ fArr[i86] = f125 - f141;
+ fArr[i95] = f128 - f144;
+ fArr[i97] = f133 - f149;
+ fArr[i99] = f136 - f152;
+ float f155 = f129 - f146;
+ float f156 = f130 + f145;
+ fArr[i87] = (f78 * f155) - (f76 * f156);
+ fArr[i90] = (f76 * f155) + (f78 * f156);
+ float f157 = f137 - f154;
+ float f158 = f138 + f153;
+ fArr[i92] = (f77 * f157) - (f75 * f158);
+ fArr[i94] = (f157 * f75) + (f158 * f77);
+ float f159 = f129 + f146;
+ float f160 = f130 - f145;
+ fArr[i88] = (f80 * f160) + (f82 * f159);
+ fArr[i96] = (f82 * f160) - (f80 * f159);
+ float f161 = f137 + f154;
+ float f162 = f138 - f153;
+ fArr[i98] = (f79 * f162) + (f81 * f161);
+ fArr[i100] = (f162 * f81) - (f161 * f79);
+ i59 += 4;
+ f74 = f81;
+ f71 = f75;
+ f73 = f77;
+ f72 = f79;
+ }
+ float f163 = (f71 + f68) * f69;
+ float f164 = (f73 + f68) * f69;
+ float f165 = (f72 - f68) * f70;
+ float f166 = (f74 - f68) * f70;
+ int i101 = i48 + i49;
+ int i102 = i101 + i49;
+ int i103 = i49 + i102;
+ int i104 = i48 + i5;
+ int i105 = i101 + i5;
+ int i106 = i102 + i5;
+ int i107 = i103 + i5;
+ int i108 = i104 - 2;
+ float f167 = fArr[i108];
+ int i109 = i106 - 2;
+ float f168 = fArr[i109];
+ float f169 = f167 + f168;
+ int i110 = i104 - 1;
+ float f170 = fArr[i110];
+ int i111 = i106 - 1;
+ float f171 = fArr[i111];
+ float f172 = f170 + f171;
+ float f173 = f167 - f168;
+ float f174 = f170 - f171;
+ int i112 = i105 - 2;
+ float f175 = fArr[i112];
+ int i113 = i107 - 2;
+ float f176 = fArr[i113];
+ float f177 = f175 + f176;
+ int i114 = i105 - 1;
+ float f178 = fArr[i114];
+ int i115 = i107 - 1;
+ float f179 = fArr[i115];
+ float f180 = f178 + f179;
+ float f181 = f175 - f176;
+ float f182 = f178 - f179;
+ fArr[i108] = f169 + f177;
+ fArr[i110] = f172 + f180;
+ fArr[i112] = f169 - f177;
+ fArr[i114] = f172 - f180;
+ float f183 = f173 - f182;
+ float f184 = f174 + f181;
+ fArr[i109] = (f163 * f183) - (f164 * f184);
+ fArr[i111] = (f183 * f164) + (f184 * f163);
+ float f185 = f173 + f182;
+ float f186 = f174 - f181;
+ fArr[i113] = (f166 * f186) + (f165 * f185);
+ fArr[i115] = (f186 * f165) - (f185 * f166);
+ float f187 = fArr[i104];
+ float f188 = fArr[i106];
+ float f189 = f187 + f188;
+ int i116 = i104 + 1;
+ float f190 = fArr[i116];
+ int i117 = i106 + 1;
+ float f191 = fArr[i117];
+ float f192 = f190 + f191;
+ float f193 = f187 - f188;
+ float f194 = f190 - f191;
+ float f195 = fArr[i105];
+ float f196 = fArr[i107];
+ float f197 = f195 + f196;
+ int i118 = i105 + 1;
+ float f198 = fArr[i118];
+ int i119 = i107 + 1;
+ float f199 = fArr[i119];
+ float f200 = f198 + f199;
+ float f201 = f195 - f196;
+ float f202 = f198 - f199;
+ fArr[i104] = f189 + f197;
+ fArr[i116] = f192 + f200;
+ fArr[i105] = f189 - f197;
+ fArr[i118] = f192 - f200;
+ float f203 = f193 - f202;
+ float f204 = f194 + f201;
+ fArr[i106] = (f203 - f204) * f68;
+ fArr[i117] = (f204 + f203) * f68;
+ float f205 = f193 + f202;
+ float f206 = f194 - f201;
+ float f207 = -f68;
+ fArr[i107] = (f205 + f206) * f207;
+ fArr[i119] = (f206 - f205) * f207;
+ int i120 = i104 + 2;
+ float f208 = fArr[i120];
+ int i121 = i106 + 2;
+ float f209 = fArr[i121];
+ float f210 = f208 + f209;
+ int i122 = i104 + 3;
+ float f211 = fArr[i122];
+ int i123 = i106 + 3;
+ float f212 = fArr[i123];
+ float f213 = f211 + f212;
+ float f214 = f208 - f209;
+ float f215 = f211 - f212;
+ int i124 = i105 + 2;
+ float f216 = fArr[i124];
+ int i125 = i107 + 2;
+ float f217 = fArr[i125];
+ float f218 = f216 + f217;
+ int i126 = i105 + 3;
+ float f219 = fArr[i126];
+ int i127 = i107 + 3;
+ float f220 = fArr[i127];
+ float f221 = f219 + f220;
+ float f222 = f216 - f217;
+ float f223 = f219 - f220;
+ fArr[i120] = f210 + f218;
+ fArr[i122] = f213 + f221;
+ fArr[i124] = f210 - f218;
+ fArr[i126] = f213 - f221;
+ float f224 = f214 - f223;
+ float f225 = f215 + f222;
+ fArr[i121] = (f164 * f224) - (f163 * f225);
+ fArr[i123] = (f163 * f224) + (f164 * f225);
+ float f226 = f214 + f223;
+ float f227 = f215 - f222;
+ fArr[i125] = (f165 * f227) + (f166 * f226);
+ fArr[i127] = (f166 * f227) - (f165 * f226);
+ if (k3.c.c > 1 && i4 >= 8192) {
+ C(i4, i5, i6, fArr, fArr2);
+ } else if (i4 > 512) {
+ A(i4, i5, i6, fArr, fArr2);
+ } else if (i4 > 128) {
+ u(i4, 1, fArr, i5, i6, fArr2);
+ } else {
+ s(i4, i5, i6, fArr, fArr2);
+ }
+ int i128 = 1;
+ while (i46 > 8) {
+ i128 <<= 1;
+ i46 >>= 2;
+ }
+ int i129 = i4 >> 1;
+ int i130 = i128 * 4;
+ if (i46 != 8) {
+ for (int i131 = 0; i131 < i128; i131++) {
+ int i132 = i131 * 4;
+ for (int i133 = 0; i133 < i131; i133++) {
+ int i134 = (i133 * 4) + iArr[i128 + i131];
+ int i135 = iArr[i128 + i133] + i132;
+ int i136 = i5 + i134;
+ int i137 = i5 + i135;
+ float f228 = fArr[i136];
+ int i138 = i136 + 1;
+ float f229 = fArr[i138];
+ float f230 = fArr[i137];
+ int i139 = i137 + 1;
+ float f231 = fArr[i139];
+ fArr[i136] = f230;
+ fArr[i138] = f231;
+ fArr[i137] = f228;
+ fArr[i139] = f229;
+ int i140 = i134 + i130;
+ int i141 = i135 + i130;
+ int i142 = i5 + i140;
+ int i143 = i5 + i141;
+ float f232 = fArr[i142];
+ int i144 = i142 + 1;
+ float f233 = fArr[i144];
+ float f234 = fArr[i143];
+ int i145 = i143 + 1;
+ float f235 = fArr[i145];
+ fArr[i142] = f234;
+ fArr[i144] = f235;
+ fArr[i143] = f232;
+ fArr[i145] = f233;
+ int i146 = i140 + i129;
+ int i147 = i141 + 2;
+ int i148 = i5 + i146;
+ int i149 = i5 + i147;
+ float f236 = fArr[i148];
+ int i150 = i148 + 1;
+ float f237 = fArr[i150];
+ float f238 = fArr[i149];
+ int i151 = i149 + 1;
+ float f239 = fArr[i151];
+ fArr[i148] = f238;
+ fArr[i150] = f239;
+ fArr[i149] = f236;
+ fArr[i151] = f237;
+ int i152 = i146 - i130;
+ int i153 = i147 - i130;
+ int i154 = i5 + i152;
+ int i155 = i5 + i153;
+ float f240 = fArr[i154];
+ int i156 = i154 + 1;
+ float f241 = fArr[i156];
+ float f242 = fArr[i155];
+ int i157 = i155 + 1;
+ float f243 = fArr[i157];
+ fArr[i154] = f242;
+ fArr[i156] = f243;
+ fArr[i155] = f240;
+ fArr[i157] = f241;
+ int i158 = i152 + 2;
+ int i159 = i153 + i129;
+ int i160 = i5 + i158;
+ int i161 = i5 + i159;
+ float f244 = fArr[i160];
+ int i162 = i160 + 1;
+ float f245 = fArr[i162];
+ float f246 = fArr[i161];
+ int i163 = i161 + 1;
+ float f247 = fArr[i163];
+ fArr[i160] = f246;
+ fArr[i162] = f247;
+ fArr[i161] = f244;
+ fArr[i163] = f245;
+ int i164 = i158 + i130;
+ int i165 = i159 + i130;
+ int i166 = i5 + i164;
+ int i167 = i5 + i165;
+ float f248 = fArr[i166];
+ int i168 = i166 + 1;
+ float f249 = fArr[i168];
+ float f250 = fArr[i167];
+ int i169 = i167 + 1;
+ float f251 = fArr[i169];
+ fArr[i166] = f250;
+ fArr[i168] = f251;
+ fArr[i167] = f248;
+ fArr[i169] = f249;
+ int i170 = i164 - i129;
+ int i171 = i165 - 2;
+ int i172 = i5 + i170;
+ int i173 = i5 + i171;
+ float f252 = fArr[i172];
+ int i174 = i172 + 1;
+ float f253 = fArr[i174];
+ float f254 = fArr[i173];
+ int i175 = i173 + 1;
+ float f255 = fArr[i175];
+ fArr[i172] = f254;
+ fArr[i174] = f255;
+ fArr[i173] = f252;
+ fArr[i175] = f253;
+ int i176 = (i170 - i130) + i5;
+ int i177 = (i171 - i130) + i5;
+ float f256 = fArr[i176];
+ int i178 = i176 + 1;
+ float f257 = fArr[i178];
+ float f258 = fArr[i177];
+ int i179 = i177 + 1;
+ float f259 = fArr[i179];
+ fArr[i176] = f258;
+ fArr[i178] = f259;
+ fArr[i177] = f256;
+ fArr[i179] = f257;
+ }
+ int i180 = i132 + iArr[i128 + i131];
+ int i181 = i180 + 2;
+ int i182 = i180 + i129;
+ int i183 = i5 + i181;
+ int i184 = i5 + i182;
+ float f260 = fArr[i183];
+ int i185 = i183 + 1;
+ float f261 = fArr[i185];
+ float f262 = fArr[i184];
+ int i186 = i184 + 1;
+ float f263 = fArr[i186];
+ fArr[i183] = f262;
+ fArr[i185] = f263;
+ fArr[i184] = f260;
+ fArr[i186] = f261;
+ int i187 = i181 + i130 + i5;
+ int i188 = i182 + i130 + i5;
+ float f264 = fArr[i187];
+ int i189 = i187 + 1;
+ float f265 = fArr[i189];
+ float f266 = fArr[i188];
+ int i190 = i188 + 1;
+ float f267 = fArr[i190];
+ fArr[i187] = f266;
+ fArr[i189] = f267;
+ fArr[i188] = f264;
+ fArr[i190] = f265;
+ }
+ return;
+ }
+ for (int i191 = 0; i191 < i128; i191++) {
+ int i192 = i191 * 4;
+ for (int i193 = 0; i193 < i191; i193++) {
+ int i194 = (iArr[i128 + i191] * 2) + (i193 * 4);
+ int i195 = (iArr[i128 + i193] * 2) + i192;
+ int i196 = i5 + i194;
+ int i197 = i5 + i195;
+ float f268 = fArr[i196];
+ int i198 = i196 + 1;
+ float f269 = fArr[i198];
+ float f270 = fArr[i197];
+ int i199 = i197 + 1;
+ float f271 = fArr[i199];
+ fArr[i196] = f270;
+ fArr[i198] = f271;
+ fArr[i197] = f268;
+ fArr[i199] = f269;
+ int i200 = i194 + i130;
+ int i201 = i128 * 8;
+ int i202 = i195 + i201;
+ int i203 = i5 + i200;
+ int i204 = i5 + i202;
+ float f272 = fArr[i203];
+ int i205 = i203 + 1;
+ float f273 = fArr[i205];
+ float f274 = fArr[i204];
+ int i206 = i204 + 1;
+ float f275 = fArr[i206];
+ fArr[i203] = f274;
+ fArr[i205] = f275;
+ fArr[i204] = f272;
+ fArr[i206] = f273;
+ int i207 = i200 + i130;
+ int i208 = i202 - i130;
+ int i209 = i5 + i207;
+ int i210 = i5 + i208;
+ float f276 = fArr[i209];
+ int i211 = i209 + 1;
+ float f277 = fArr[i211];
+ float f278 = fArr[i210];
+ int i212 = i210 + 1;
+ float f279 = fArr[i212];
+ fArr[i209] = f278;
+ fArr[i211] = f279;
+ fArr[i210] = f276;
+ fArr[i212] = f277;
+ int i213 = i207 + i130;
+ int i214 = i208 + i201;
+ int i215 = i5 + i213;
+ int i216 = i5 + i214;
+ float f280 = fArr[i215];
+ int i217 = i215 + 1;
+ float f281 = fArr[i217];
+ float f282 = fArr[i216];
+ int i218 = i216 + 1;
+ float f283 = fArr[i218];
+ fArr[i215] = f282;
+ fArr[i217] = f283;
+ fArr[i216] = f280;
+ fArr[i218] = f281;
+ int i219 = i213 + i129;
+ int i220 = i214 + 2;
+ int i221 = i5 + i219;
+ int i222 = i5 + i220;
+ float f284 = fArr[i221];
+ int i223 = i221 + 1;
+ float f285 = fArr[i223];
+ float f286 = fArr[i222];
+ int i224 = i222 + 1;
+ float f287 = fArr[i224];
+ fArr[i221] = f286;
+ fArr[i223] = f287;
+ fArr[i222] = f284;
+ fArr[i224] = f285;
+ int i225 = i219 - i130;
+ int i226 = i220 - i201;
+ int i227 = i5 + i225;
+ int i228 = i5 + i226;
+ float f288 = fArr[i227];
+ int i229 = i227 + 1;
+ float f289 = fArr[i229];
+ float f290 = fArr[i228];
+ int i230 = i228 + 1;
+ float f291 = fArr[i230];
+ fArr[i227] = f290;
+ fArr[i229] = f291;
+ fArr[i228] = f288;
+ fArr[i230] = f289;
+ int i231 = i225 - i130;
+ int i232 = i226 + i130;
+ int i233 = i5 + i231;
+ int i234 = i5 + i232;
+ float f292 = fArr[i233];
+ int i235 = i233 + 1;
+ float f293 = fArr[i235];
+ float f294 = fArr[i234];
+ int i236 = i234 + 1;
+ float f295 = fArr[i236];
+ fArr[i233] = f294;
+ fArr[i235] = f295;
+ fArr[i234] = f292;
+ fArr[i236] = f293;
+ int i237 = i231 - i130;
+ int i238 = i232 - i201;
+ int i239 = i5 + i237;
+ int i240 = i5 + i238;
+ float f296 = fArr[i239];
+ int i241 = i239 + 1;
+ float f297 = fArr[i241];
+ float f298 = fArr[i240];
+ int i242 = i240 + 1;
+ float f299 = fArr[i242];
+ fArr[i239] = f298;
+ fArr[i241] = f299;
+ fArr[i240] = f296;
+ fArr[i242] = f297;
+ int i243 = i237 + 2;
+ int i244 = i238 + i129;
+ int i245 = i5 + i243;
+ int i246 = i5 + i244;
+ float f300 = fArr[i245];
+ int i247 = i245 + 1;
+ float f301 = fArr[i247];
+ float f302 = fArr[i246];
+ int i248 = i246 + 1;
+ float f303 = fArr[i248];
+ fArr[i245] = f302;
+ fArr[i247] = f303;
+ fArr[i246] = f300;
+ fArr[i248] = f301;
+ int i249 = i243 + i130;
+ int i250 = i244 + i201;
+ int i251 = i5 + i249;
+ int i252 = i5 + i250;
+ float f304 = fArr[i251];
+ int i253 = i251 + 1;
+ float f305 = fArr[i253];
+ float f306 = fArr[i252];
+ int i254 = i252 + 1;
+ float f307 = fArr[i254];
+ fArr[i251] = f306;
+ fArr[i253] = f307;
+ fArr[i252] = f304;
+ fArr[i254] = f305;
+ int i255 = i249 + i130;
+ int i256 = i250 - i130;
+ int i257 = i5 + i255;
+ int i258 = i5 + i256;
+ float f308 = fArr[i257];
+ int i259 = i257 + 1;
+ float f309 = fArr[i259];
+ float f310 = fArr[i258];
+ int i260 = i258 + 1;
+ float f311 = fArr[i260];
+ fArr[i257] = f310;
+ fArr[i259] = f311;
+ fArr[i258] = f308;
+ fArr[i260] = f309;
+ int i261 = i255 + i130;
+ int i262 = i256 + i201;
+ int i263 = i5 + i261;
+ int i264 = i5 + i262;
+ float f312 = fArr[i263];
+ int i265 = i263 + 1;
+ float f313 = fArr[i265];
+ float f314 = fArr[i264];
+ int i266 = i264 + 1;
+ float f315 = fArr[i266];
+ fArr[i263] = f314;
+ fArr[i265] = f315;
+ fArr[i264] = f312;
+ fArr[i266] = f313;
+ int i267 = i261 - i129;
+ int i268 = i262 - 2;
+ int i269 = i5 + i267;
+ int i270 = i5 + i268;
+ float f316 = fArr[i269];
+ int i271 = i269 + 1;
+ float f317 = fArr[i271];
+ float f318 = fArr[i270];
+ int i272 = i270 + 1;
+ float f319 = fArr[i272];
+ fArr[i269] = f318;
+ fArr[i271] = f319;
+ fArr[i270] = f316;
+ fArr[i272] = f317;
+ int i273 = i267 - i130;
+ int i274 = i268 - i201;
+ int i275 = i5 + i273;
+ int i276 = i5 + i274;
+ float f320 = fArr[i275];
+ int i277 = i275 + 1;
+ float f321 = fArr[i277];
+ float f322 = fArr[i276];
+ int i278 = i276 + 1;
+ float f323 = fArr[i278];
+ fArr[i275] = f322;
+ fArr[i277] = f323;
+ fArr[i276] = f320;
+ fArr[i278] = f321;
+ int i279 = i273 - i130;
+ int i280 = i274 + i130;
+ int i281 = i5 + i279;
+ int i282 = i5 + i280;
+ float f324 = fArr[i281];
+ int i283 = i281 + 1;
+ float f325 = fArr[i283];
+ float f326 = fArr[i282];
+ int i284 = i282 + 1;
+ float f327 = fArr[i284];
+ fArr[i281] = f326;
+ fArr[i283] = f327;
+ fArr[i282] = f324;
+ fArr[i284] = f325;
+ int i285 = (i279 - i130) + i5;
+ int i286 = (i280 - i201) + i5;
+ float f328 = fArr[i285];
+ int i287 = i285 + 1;
+ float f329 = fArr[i287];
+ float f330 = fArr[i286];
+ int i288 = i286 + 1;
+ float f331 = fArr[i288];
+ fArr[i285] = f330;
+ fArr[i287] = f331;
+ fArr[i286] = f328;
+ fArr[i288] = f329;
+ }
+ int i289 = (iArr[i128 + i191] * 2) + i192;
+ int i290 = i289 + 2;
+ int i291 = i289 + i129;
+ int i292 = i5 + i290;
+ int i293 = i5 + i291;
+ float f332 = fArr[i292];
+ int i294 = i292 + 1;
+ float f333 = fArr[i294];
+ float f334 = fArr[i293];
+ int i295 = i293 + 1;
+ float f335 = fArr[i295];
+ fArr[i292] = f334;
+ fArr[i294] = f335;
+ fArr[i293] = f332;
+ fArr[i295] = f333;
+ int i296 = i290 + i130;
+ int i297 = i128 * 8;
+ int i298 = i291 + i297;
+ int i299 = i5 + i296;
+ int i300 = i5 + i298;
+ float f336 = fArr[i299];
+ int i301 = i299 + 1;
+ float f337 = fArr[i301];
+ float f338 = fArr[i300];
+ int i302 = i300 + 1;
+ float f339 = fArr[i302];
+ fArr[i299] = f338;
+ fArr[i301] = f339;
+ fArr[i300] = f336;
+ fArr[i302] = f337;
+ int i303 = i296 + i130;
+ int i304 = i298 - i130;
+ int i305 = i5 + i303;
+ int i306 = i5 + i304;
+ float f340 = fArr[i305];
+ int i307 = i305 + 1;
+ float f341 = fArr[i307];
+ float f342 = fArr[i306];
+ int i308 = i306 + 1;
+ float f343 = fArr[i308];
+ fArr[i305] = f342;
+ fArr[i307] = f343;
+ fArr[i306] = f340;
+ fArr[i308] = f341;
+ int i309 = i303 - 2;
+ int i310 = i304 - i129;
+ int i311 = i5 + i309;
+ int i312 = i5 + i310;
+ float f344 = fArr[i311];
+ int i313 = i311 + 1;
+ float f345 = fArr[i313];
+ float f346 = fArr[i312];
+ int i314 = i312 + 1;
+ float f347 = fArr[i314];
+ fArr[i311] = f346;
+ fArr[i313] = f347;
+ fArr[i312] = f344;
+ fArr[i314] = f345;
+ int i315 = i129 + 2;
+ int i316 = i309 + i315;
+ int i317 = i310 + i315;
+ int i318 = i5 + i316;
+ int i319 = i5 + i317;
+ float f348 = fArr[i318];
+ int i320 = i318 + 1;
+ float f349 = fArr[i320];
+ float f350 = fArr[i319];
+ int i321 = i319 + 1;
+ float f351 = fArr[i321];
+ fArr[i318] = f350;
+ fArr[i320] = f351;
+ fArr[i319] = f348;
+ fArr[i321] = f349;
+ int i322 = (i316 - (i129 - i130)) + i5;
+ int i323 = i5 + (i297 - 2) + i317;
+ float f352 = fArr[i322];
+ int i324 = i322 + 1;
+ float f353 = fArr[i324];
+ float f354 = fArr[i323];
+ int i325 = i323 + 1;
+ float f355 = fArr[i325];
+ fArr[i322] = f354;
+ fArr[i324] = f355;
+ fArr[i323] = f352;
+ fArr[i325] = f353;
+ }
+ }
+
+ public static void r(long j4, d dVar, long j5, s sVar, long j6, d dVar2) {
+ d dVar3;
+ long j7;
+ if (j4 <= 8) {
+ if (j4 != 8) {
+ if (j4 == 4) {
+ G(dVar, j5);
+ return;
+ }
+ return;
+ }
+ long j8 = j5 + 4;
+ float b4 = dVar.b(j5) + dVar.b(j8);
+ long j9 = j5 + 1;
+ long j10 = j5 + 5;
+ float b5 = dVar.b(j10) + dVar.b(j9);
+ float b6 = dVar.b(j5) - dVar.b(j8);
+ float b7 = dVar.b(j9) - dVar.b(j10);
+ long j11 = j5 + 2;
+ long j12 = j5 + 6;
+ float b8 = dVar.b(j11) + dVar.b(j12);
+ long j13 = j5 + 3;
+ long j14 = j5 + 7;
+ float b9 = dVar.b(j13) + dVar.b(j14);
+ float b10 = dVar.b(j11) - dVar.b(j12);
+ float b11 = dVar.b(j13) - dVar.b(j14);
+ dVar.c(j9, AbstractC1518b.j(b4, b8, dVar, j5, b5, b9));
+ dVar.c(j13, AbstractC1518b.a(b6, b11, dVar, j11, b7, b10));
+ dVar.c(j10, AbstractC1518b.l(b4, b8, dVar, j8, b5, b9));
+ dVar.c(j14, AbstractC1518b.m(b6, b11, dVar, j12, b7, b10));
+ return;
+ }
+ if (j4 <= 32) {
+ if (j4 == 32) {
+ m(dVar, j5, dVar2, j6 - 8);
+ long j15 = j5 + 2;
+ float b12 = dVar.b(j15);
+ long j16 = j5 + 3;
+ float b13 = dVar.b(j16);
+ long j17 = j5 + 4;
+ float b14 = dVar.b(j17);
+ long j18 = j5 + 5;
+ float b15 = dVar.b(j18);
+ long j19 = j5 + 6;
+ float b16 = dVar.b(j19);
+ long j20 = j5 + 7;
+ float b17 = dVar.b(j20);
+ long j21 = j5 + 8;
+ float b18 = dVar.b(j21);
+ long j22 = j5 + 9;
+ float b19 = dVar.b(j22);
+ long j23 = j5 + 10;
+ float b20 = dVar.b(j23);
+ long j24 = j5 + 11;
+ float b21 = dVar.b(j24);
+ long j25 = j5 + 14;
+ float b22 = dVar.b(j25);
+ long j26 = j5 + 15;
+ float b23 = dVar.b(j26);
+ long j27 = j5 + 16;
+ float b24 = dVar.b(j27);
+ long j28 = j5 + 17;
+ float b25 = dVar.b(j28);
+ long j29 = j5 + 20;
+ float b26 = dVar.b(j29);
+ long j30 = j5 + 21;
+ float b27 = dVar.b(j30);
+ long j31 = j5 + 22;
+ float b28 = dVar.b(j31);
+ long j32 = j5 + 23;
+ float b29 = dVar.b(j32);
+ long j33 = j5 + 24;
+ float b30 = dVar.b(j33);
+ long j34 = j5 + 25;
+ float b31 = dVar.b(j34);
+ long j35 = j5 + 26;
+ float b32 = dVar.b(j35);
+ long j36 = j5 + 27;
+ float b33 = dVar.b(j36);
+ long j37 = j5 + 28;
+ float b34 = dVar.b(j37);
+ long j38 = j5 + 29;
+ float b35 = dVar.b(j38);
+ dVar.c(j15, b24);
+ dVar.c(j16, b25);
+ dVar.c(j17, b18);
+ dVar.c(j18, b19);
+ dVar.c(j19, b30);
+ dVar.c(j20, b31);
+ dVar.c(j21, b14);
+ dVar.c(j22, b15);
+ dVar.c(j23, b26);
+ dVar.c(j24, b27);
+ dVar.c(j25, b34);
+ dVar.c(j26, b35);
+ dVar.c(j27, b12);
+ dVar.c(j28, b13);
+ dVar.c(j29, b20);
+ dVar.c(j30, b21);
+ dVar.c(j31, b32);
+ dVar.c(j32, b33);
+ dVar.c(j33, b16);
+ dVar.c(j34, b17);
+ dVar.c(j35, b28);
+ dVar.c(j36, b29);
+ dVar.c(j37, b22);
+ dVar.c(j38, b23);
+ return;
+ }
+ i(dVar, j5, dVar2, 0L);
+ long j39 = j5 + 2;
+ float b36 = dVar.b(j39);
+ long j40 = j5 + 3;
+ float b37 = dVar.b(j40);
+ long j41 = j5 + 6;
+ float b38 = dVar.b(j41);
+ long j42 = j5 + 7;
+ float b39 = dVar.b(j42);
+ long j43 = j5 + 8;
+ float b40 = dVar.b(j43);
+ long j44 = j5 + 9;
+ float b41 = dVar.b(j44);
+ long j45 = j5 + 12;
+ float b42 = dVar.b(j45);
+ long j46 = j5 + 13;
+ float b43 = dVar.b(j46);
+ dVar.c(j39, b40);
+ dVar.c(j40, b41);
+ dVar.c(j41, b42);
+ dVar.c(j42, b43);
+ dVar.c(j43, b36);
+ dVar.c(j44, b37);
+ dVar.c(j45, b38);
+ dVar.c(j46, b39);
+ return;
+ }
+ long j47 = j4 >> 2;
+ long j48 = j6 - j47;
+ long j49 = j4 >> 3;
+ long j50 = j49 * 2;
+ long j51 = j50 + j50;
+ long j52 = j51 + j50;
+ long j53 = j5 + j50;
+ long j54 = j5 + j51;
+ long j55 = j5 + j52;
+ float b44 = dVar.b(j54) + dVar.b(j5);
+ long j56 = j5 + 1;
+ long j57 = j54 + 1;
+ float b45 = dVar.b(j57) + dVar.b(j56);
+ float b46 = dVar.b(j5) - dVar.b(j54);
+ float b47 = dVar.b(j56) - dVar.b(j57);
+ float b48 = dVar.b(j55) + dVar.b(j53);
+ long j58 = j53 + 1;
+ long j59 = j55 + 1;
+ float b49 = dVar.b(j59) + dVar.b(j58);
+ float b50 = dVar.b(j53) - dVar.b(j55);
+ float b51 = dVar.b(j58) - dVar.b(j59);
+ dVar.c(j56, AbstractC1518b.j(b44, b48, dVar, j5, b45, b49));
+ dVar.c(j58, AbstractC1518b.l(b44, b48, dVar, j53, b45, b49));
+ dVar.c(j57, AbstractC1518b.a(b46, b51, dVar, j54, b47, b50));
+ dVar.c(j59, AbstractC1518b.m(b46, b51, dVar, j55, b47, b50));
+ d dVar4 = dVar2;
+ float b52 = dVar4.b(j48 + 1);
+ float b53 = dVar4.b(j48 + 2);
+ float b54 = dVar4.b(j48 + 3);
+ float f4 = 1.0f;
+ float f5 = 1.0f;
+ float f6 = 0.0f;
+ float f7 = 0.0f;
+ long j60 = 0;
+ int i4 = 2;
+ while (true) {
+ long j61 = i4;
+ if (j61 >= j49 - 2) {
+ break;
+ }
+ long j62 = j60 + 4;
+ long j63 = j48 + j62;
+ float b55 = (dVar4.b(j63) + f4) * b53;
+ long j64 = j63 + 1;
+ float b56 = (dVar4.b(j64) + f6) * b53;
+ long j65 = j63 + 2;
+ float b57 = (dVar4.b(j65) + f5) * b54;
+ float f8 = b54;
+ long j66 = j63 + 3;
+ float b58 = (dVar4.b(j66) + f7) * f8;
+ float b59 = dVar4.b(j63);
+ float b60 = dVar4.b(j64);
+ float b61 = dVar4.b(j65);
+ float b62 = dVar4.b(j66);
+ long j67 = j61 + j50;
+ long j68 = j67 + j50;
+ long j69 = j68 + j50;
+ long j70 = j5 + j67;
+ long j71 = j5 + j68;
+ long j72 = j5 + j69;
+ long j73 = j5 + j61;
+ float b63 = dVar.b(j71) + dVar.b(j73);
+ long j74 = j73 + 1;
+ float f9 = b53;
+ long j75 = j71 + 1;
+ float b64 = dVar.b(j75) + dVar.b(j74);
+ float b65 = dVar.b(j73) - dVar.b(j71);
+ float b66 = dVar.b(j74) - dVar.b(j75);
+ long j76 = j73 + 2;
+ long j77 = j71 + 2;
+ float b67 = dVar.b(j77) + dVar.b(j76);
+ long j78 = j73 + 3;
+ long j79 = j71 + 3;
+ float b68 = dVar.b(j79) + dVar.b(j78);
+ float b69 = dVar.b(j76) - dVar.b(j77);
+ float b70 = dVar.b(j78) - dVar.b(j79);
+ float b71 = dVar.b(j72) + dVar.b(j70);
+ long j80 = j70 + 1;
+ long j81 = j72 + 1;
+ float b72 = dVar.b(j81) + dVar.b(j80);
+ float b73 = dVar.b(j70) - dVar.b(j72);
+ float b74 = dVar.b(j80) - dVar.b(j81);
+ long j82 = j70 + 2;
+ long j83 = j72 + 2;
+ float b75 = dVar.b(j83) + dVar.b(j82);
+ long j84 = j70 + 3;
+ long j85 = j72 + 3;
+ float b76 = dVar.b(j85) + dVar.b(j84);
+ float b77 = dVar.b(j82) - dVar.b(j83);
+ float b78 = dVar.b(j84) - dVar.b(j85);
+ dVar.c(j74, AbstractC1518b.j(b63, b71, dVar, j73, b64, b72));
+ dVar.c(j78, AbstractC1518b.j(b67, b75, dVar, j76, b68, b76));
+ dVar.c(j80, AbstractC1518b.l(b63, b71, dVar, j70, b64, b72));
+ dVar.c(j84, AbstractC1518b.l(b67, b75, dVar, j82, b68, b76));
+ float f10 = b65 - b74;
+ float f11 = b66 + b73;
+ dVar.c(j71, (b55 * f10) - (b56 * f11));
+ float m2 = AbstractC1518b.m(f10 * b56, f11 * b55, dVar, j75, b69, b78);
+ float f12 = b70 + b77;
+ dVar.c(j77, (b59 * m2) - (b60 * f12));
+ float j86 = AbstractC1518b.j(m2 * b60, f12 * b59, dVar, j79, b65, b74);
+ float f13 = b66 - b73;
+ dVar.c(j72, (b58 * f13) + (b57 * j86));
+ float a4 = AbstractC1518b.a(f13 * b57, b58 * j86, dVar, j81, b69, b78);
+ float f14 = b70 - b77;
+ dVar.c(j83, (b62 * f14) + (b61 * a4));
+ dVar.c(j85, (f14 * b61) - (b62 * a4));
+ long j87 = j50 - j61;
+ long j88 = j87 + j50;
+ long j89 = j88 + j50;
+ long j90 = j5 + j87;
+ long j91 = j5 + j88;
+ long j92 = j5 + j89;
+ long j93 = j5 + j89 + j50;
+ float b79 = dVar.b(j92) + dVar.b(j90);
+ long j94 = j90 + 1;
+ long j95 = j92 + 1;
+ float b80 = dVar.b(j95) + dVar.b(j94);
+ float b81 = dVar.b(j90) - dVar.b(j92);
+ float b82 = dVar.b(j94) - dVar.b(j95);
+ long j96 = j90 - 2;
+ long j97 = j92 - 2;
+ float b83 = dVar.b(j97) + dVar.b(j96);
+ long j98 = j90 - 1;
+ long j99 = j92 - 1;
+ float b84 = dVar.b(j99) + dVar.b(j98);
+ float b85 = dVar.b(j96) - dVar.b(j97);
+ float b86 = dVar.b(j98) - dVar.b(j99);
+ float b87 = dVar.b(j93) + dVar.b(j91);
+ long j100 = j91 + 1;
+ long j101 = j93 + 1;
+ float b88 = dVar.b(j101) + dVar.b(j100);
+ float b89 = dVar.b(j91) - dVar.b(j93);
+ float b90 = dVar.b(j100) - dVar.b(j101);
+ long j102 = j91 - 2;
+ long j103 = j93 - 2;
+ float b91 = dVar.b(j103) + dVar.b(j102);
+ long j104 = j91 - 1;
+ long j105 = j93 - 1;
+ float b92 = dVar.b(j105) + dVar.b(j104);
+ float b93 = dVar.b(j102) - dVar.b(j103);
+ float b94 = dVar.b(j104) - dVar.b(j105);
+ dVar.c(j94, AbstractC1518b.j(b79, b87, dVar, j90, b80, b88));
+ dVar.c(j98, AbstractC1518b.j(b83, b91, dVar, j96, b84, b92));
+ dVar.c(j100, AbstractC1518b.l(b79, b87, dVar, j91, b80, b88));
+ dVar.c(j104, AbstractC1518b.l(b83, b91, dVar, j102, b84, b92));
+ float f15 = b81 - b90;
+ float f16 = b82 + b89;
+ dVar.c(j92, (b56 * f15) - (b55 * f16));
+ float m3 = AbstractC1518b.m(f15 * b55, f16 * b56, dVar, j95, b85, b94);
+ float f17 = b86 + b93;
+ dVar.c(j97, (b60 * m3) - (b59 * f17));
+ float j106 = AbstractC1518b.j(m3 * b59, f17 * b60, dVar, j99, b81, b90);
+ float f18 = b82 - b89;
+ dVar.c(j93, (b57 * f18) + (b58 * j106));
+ float a5 = AbstractC1518b.a(b58 * f18, b57 * j106, dVar, j101, b85, b94);
+ float f19 = b86 - b93;
+ dVar.c(j103, (b61 * f19) + (b62 * a5));
+ dVar.c(j105, (b62 * f19) - (a5 * b61));
+ i4 += 4;
+ dVar4 = dVar2;
+ j60 = j62;
+ f4 = b59;
+ f6 = b60;
+ b54 = f8;
+ f5 = b61;
+ f7 = b62;
+ b53 = f9;
+ b52 = b52;
+ }
+ float f20 = b52;
+ float f21 = b53;
+ float f22 = b54;
+ float f23 = (f4 + f20) * f21;
+ float f24 = (f6 + f20) * f21;
+ float f25 = (f5 - f20) * f22;
+ float f26 = (f7 - f20) * f22;
+ long j107 = j49 + j50;
+ long j108 = j107 + j50;
+ long j109 = j5 + j49;
+ long j110 = j5 + j107;
+ long j111 = j5 + j108;
+ long j112 = j5 + j108 + j50;
+ long j113 = j109 - 2;
+ long j114 = j111 - 2;
+ float b95 = dVar.b(j114) + dVar.b(j113);
+ long j115 = j109 - 1;
+ long j116 = j111 - 1;
+ float b96 = dVar.b(j116) + dVar.b(j115);
+ float b97 = dVar.b(j113) - dVar.b(j114);
+ float b98 = dVar.b(j115) - dVar.b(j116);
+ long j117 = j110 - 2;
+ long j118 = j112 - 2;
+ float b99 = dVar.b(j118) + dVar.b(j117);
+ long j119 = j110 - 1;
+ long j120 = j112 - 1;
+ float b100 = dVar.b(j120) + dVar.b(j119);
+ float b101 = dVar.b(j117) - dVar.b(j118);
+ float b102 = dVar.b(j119) - dVar.b(j120);
+ dVar.c(j115, AbstractC1518b.j(b95, b99, dVar, j113, b96, b100));
+ dVar.c(j119, AbstractC1518b.l(b95, b99, dVar, j117, b96, b100));
+ float f27 = b97 - b102;
+ float f28 = b98 + b101;
+ dVar.c(j114, (f23 * f27) - (f24 * f28));
+ float j121 = AbstractC1518b.j(f27 * f24, f28 * f23, dVar, j116, b97, b102);
+ float f29 = b98 - b101;
+ dVar.c(j118, (f26 * f29) + (f25 * j121));
+ dVar.c(j120, (f25 * f29) - (j121 * f26));
+ float b103 = dVar.b(j109) + dVar.b(j111);
+ long j122 = j109 + 1;
+ long j123 = j111 + 1;
+ float b104 = dVar.b(j123) + dVar.b(j122);
+ float b105 = dVar.b(j109) - dVar.b(j111);
+ float b106 = dVar.b(j122) - dVar.b(j123);
+ float b107 = dVar.b(j110) + dVar.b(j112);
+ long j124 = j110 + 1;
+ long j125 = j112 + 1;
+ float b108 = dVar.b(j125) + dVar.b(j124);
+ float b109 = dVar.b(j110) - dVar.b(j112);
+ float b110 = dVar.b(j124) - dVar.b(j125);
+ dVar.c(j122, AbstractC1518b.j(b103, b107, dVar, j109, b104, b108));
+ dVar.c(j124, AbstractC1518b.l(b103, b107, dVar, j110, b104, b108));
+ float f30 = b105 - b110;
+ float f31 = b106 + b109;
+ dVar.c(j111, (f30 - f31) * f20);
+ dVar.c(j123, (f31 + f30) * f20);
+ float f32 = b105 + b110;
+ float f33 = b106 - b109;
+ float f34 = -f20;
+ dVar.c(j112, (f32 + f33) * f34);
+ dVar.c(j125, (f33 - f32) * f34);
+ long j126 = j109 + 2;
+ long j127 = j111 + 2;
+ float b111 = dVar.b(j126) + dVar.b(j127);
+ long j128 = j109 + 3;
+ long j129 = j111 + 3;
+ float b112 = dVar.b(j129) + dVar.b(j128);
+ float b113 = dVar.b(j126) - dVar.b(j127);
+ float b114 = dVar.b(j128) - dVar.b(j129);
+ long j130 = j110 + 2;
+ long j131 = j112 + 2;
+ float b115 = dVar.b(j131) + dVar.b(j130);
+ long j132 = j110 + 3;
+ long j133 = j112 + 3;
+ float b116 = dVar.b(j133) + dVar.b(j132);
+ float b117 = dVar.b(j130) - dVar.b(j131);
+ float b118 = dVar.b(j132) - dVar.b(j133);
+ dVar.c(j128, AbstractC1518b.j(b111, b115, dVar, j126, b112, b116));
+ dVar.c(j132, AbstractC1518b.l(b111, b115, dVar, j130, b112, b116));
+ float f35 = b113 - b118;
+ float f36 = b114 + b117;
+ dVar.c(j127, (f24 * f35) - (f23 * f36));
+ float j134 = AbstractC1518b.j(f35 * f23, f36 * f24, dVar, j129, b113, b118);
+ float f37 = b114 - b117;
+ dVar.c(j131, (f25 * f37) + (f26 * j134));
+ dVar.c(j133, (f26 * f37) - (f25 * j134));
+ if (k3.c.c > 1 && j4 >= 8192) {
+ D(j4, j5, j6, dVar, dVar2);
+ } else if (j4 > 512) {
+ B(j4, j5, j6, dVar, dVar2);
+ } else if (j4 > 128) {
+ v(j4, 1L, j5, j6, dVar, dVar2);
+ } else {
+ t(j4, j5, j6, dVar, dVar2);
+ dVar3 = dVar;
+ j7 = j47;
+ long j135 = 1;
+ while (j7 > 8) {
+ j135 <<= 1;
+ j7 >>= 2;
+ }
+ long j136 = j4 >> 1;
+ long j137 = j135 * 4;
+ if (j7 == 8) {
+ long j138 = j135;
+ long j139 = 0;
+ while (j139 < j138) {
+ long j140 = j139 * 4;
+ long j141 = 0;
+ while (j141 < j139) {
+ long b119 = sVar.b(j138 + j139) + (j141 * 4);
+ long b120 = sVar.b(j138 + j141) + j140;
+ long j142 = j5 + b119;
+ long j143 = j5 + b120;
+ long j144 = j139;
+ float b121 = dVar3.b(j142);
+ long j145 = j140;
+ long j146 = j142 + 1;
+ float b122 = dVar3.b(j146);
+ long j147 = j141;
+ float b123 = dVar3.b(j143);
+ long j148 = j143 + 1;
+ float b124 = dVar3.b(j148);
+ dVar3.c(j142, b123);
+ dVar3.c(j146, b124);
+ dVar3.c(j143, b121);
+ dVar3.c(j148, b122);
+ long j149 = b119 + j137;
+ long j150 = b120 + j137;
+ long j151 = j5 + j149;
+ long j152 = j5 + j150;
+ float b125 = dVar3.b(j151);
+ long j153 = j151 + 1;
+ float b126 = dVar3.b(j153);
+ float b127 = dVar3.b(j152);
+ long j154 = j152 + 1;
+ float b128 = dVar3.b(j154);
+ dVar3.c(j151, b127);
+ dVar3.c(j153, b128);
+ dVar3.c(j152, b125);
+ dVar3.c(j154, b126);
+ long j155 = j149 + j136;
+ long j156 = j150 + 2;
+ long j157 = j5 + j155;
+ long j158 = j5 + j156;
+ float b129 = dVar3.b(j157);
+ long j159 = j157 + 1;
+ float b130 = dVar3.b(j159);
+ float b131 = dVar3.b(j158);
+ long j160 = j158 + 1;
+ float b132 = dVar3.b(j160);
+ dVar3.c(j157, b131);
+ dVar3.c(j159, b132);
+ dVar3.c(j158, b129);
+ dVar3.c(j160, b130);
+ long j161 = j155 - j137;
+ long j162 = j156 - j137;
+ long j163 = j5 + j161;
+ long j164 = j5 + j162;
+ float b133 = dVar3.b(j163);
+ long j165 = j163 + 1;
+ float b134 = dVar3.b(j165);
+ float b135 = dVar3.b(j164);
+ long j166 = j164 + 1;
+ float b136 = dVar3.b(j166);
+ dVar3.c(j163, b135);
+ dVar3.c(j165, b136);
+ dVar3.c(j164, b133);
+ dVar3.c(j166, b134);
+ long j167 = j161 + 2;
+ long j168 = j162 + j136;
+ long j169 = j5 + j167;
+ long j170 = j5 + j168;
+ float b137 = dVar3.b(j169);
+ long j171 = j169 + 1;
+ float b138 = dVar3.b(j171);
+ float b139 = dVar3.b(j170);
+ long j172 = j170 + 1;
+ float b140 = dVar3.b(j172);
+ dVar3.c(j169, b139);
+ dVar3.c(j171, b140);
+ dVar3.c(j170, b137);
+ dVar3.c(j172, b138);
+ long j173 = j167 + j137;
+ long j174 = j168 + j137;
+ long j175 = j5 + j173;
+ long j176 = j5 + j174;
+ float b141 = dVar3.b(j175);
+ long j177 = j175 + 1;
+ float b142 = dVar3.b(j177);
+ float b143 = dVar3.b(j176);
+ long j178 = j176 + 1;
+ float b144 = dVar3.b(j178);
+ dVar3.c(j175, b143);
+ dVar3.c(j177, b144);
+ dVar3.c(j176, b141);
+ dVar3.c(j178, b142);
+ long j179 = j173 - j136;
+ long j180 = j174 - 2;
+ long j181 = j5 + j179;
+ long j182 = j5 + j180;
+ float b145 = dVar3.b(j181);
+ long j183 = j181 + 1;
+ float b146 = dVar3.b(j183);
+ float b147 = dVar3.b(j182);
+ long j184 = j182 + 1;
+ float b148 = dVar3.b(j184);
+ dVar3.c(j181, b147);
+ dVar3.c(j183, b148);
+ dVar3.c(j182, b145);
+ dVar3.c(j184, b146);
+ long j185 = j5 + (j179 - j137);
+ long j186 = j5 + (j180 - j137);
+ float b149 = dVar3.b(j185);
+ long j187 = j185 + 1;
+ float b150 = dVar3.b(j187);
+ float b151 = dVar3.b(j186);
+ long j188 = j186 + 1;
+ float b152 = dVar3.b(j188);
+ dVar3.c(j185, b151);
+ dVar3.c(j187, b152);
+ dVar3.c(j186, b149);
+ dVar3.c(j188, b150);
+ j141 = j147 + 1;
+ j139 = j144;
+ j140 = j145;
+ }
+ long j189 = j139;
+ long b153 = sVar.b(j138 + j189) + j140;
+ long j190 = b153 + 2;
+ long j191 = b153 + j136;
+ long j192 = j5 + j190;
+ long j193 = j5 + j191;
+ float b154 = dVar3.b(j192);
+ long j194 = j192 + 1;
+ float b155 = dVar3.b(j194);
+ float b156 = dVar3.b(j193);
+ long j195 = j193 + 1;
+ float b157 = dVar3.b(j195);
+ dVar3.c(j192, b156);
+ dVar3.c(j194, b157);
+ dVar3.c(j193, b154);
+ dVar3.c(j195, b155);
+ long j196 = j5 + j190 + j137;
+ long j197 = j5 + j191 + j137;
+ float b158 = dVar3.b(j196);
+ long j198 = j196 + 1;
+ float b159 = dVar3.b(j198);
+ float b160 = dVar3.b(j197);
+ long j199 = j197 + 1;
+ float b161 = dVar3.b(j199);
+ dVar3.c(j196, b160);
+ dVar3.c(j198, b161);
+ dVar3.c(j197, b158);
+ dVar3.c(j199, b159);
+ j139 = j189 + 1;
+ }
+ return;
+ }
+ long j200 = 0;
+ while (j200 < j135) {
+ long j201 = j200 * 4;
+ long j202 = 0;
+ while (j202 < j200) {
+ long j203 = j135;
+ long b162 = (sVar.b(j203 + j200) * 2) + (j202 * 4);
+ long b163 = (sVar.b(j203 + j202) * 2) + j201;
+ long j204 = j5 + b162;
+ long j205 = j136;
+ long j206 = j5 + b163;
+ long j207 = j137;
+ float b164 = dVar3.b(j204);
+ long j208 = j200;
+ long j209 = j204 + 1;
+ float b165 = dVar3.b(j209);
+ long j210 = j201;
+ float b166 = dVar3.b(j206);
+ long j211 = j202;
+ long j212 = j206 + 1;
+ float b167 = dVar3.b(j212);
+ dVar3.c(j204, b166);
+ dVar3.c(j209, b167);
+ dVar3.c(j206, b164);
+ dVar3.c(j212, b165);
+ long j213 = b162 + j207;
+ long j214 = j203 * 8;
+ long j215 = b163 + j214;
+ long j216 = j5 + j213;
+ long j217 = j5 + j215;
+ float b168 = dVar3.b(j216);
+ long j218 = j216 + 1;
+ float b169 = dVar3.b(j218);
+ float b170 = dVar3.b(j217);
+ long j219 = j217 + 1;
+ float b171 = dVar3.b(j219);
+ dVar3.c(j216, b170);
+ dVar3.c(j218, b171);
+ dVar3.c(j217, b168);
+ dVar3.c(j219, b169);
+ long j220 = j213 + j207;
+ long j221 = j215 - j207;
+ long j222 = j5 + j220;
+ long j223 = j5 + j221;
+ float b172 = dVar3.b(j222);
+ long j224 = j222 + 1;
+ float b173 = dVar3.b(j224);
+ float b174 = dVar3.b(j223);
+ long j225 = j223 + 1;
+ float b175 = dVar3.b(j225);
+ dVar3.c(j222, b174);
+ dVar3.c(j224, b175);
+ dVar3.c(j223, b172);
+ dVar3.c(j225, b173);
+ long j226 = j220 + j207;
+ long j227 = j221 + j214;
+ long j228 = j5 + j226;
+ long j229 = j5 + j227;
+ float b176 = dVar3.b(j228);
+ long j230 = j228 + 1;
+ float b177 = dVar3.b(j230);
+ float b178 = dVar3.b(j229);
+ long j231 = j229 + 1;
+ float b179 = dVar3.b(j231);
+ dVar3.c(j228, b178);
+ dVar3.c(j230, b179);
+ dVar3.c(j229, b176);
+ dVar3.c(j231, b177);
+ long j232 = j226 + j205;
+ long j233 = j227 + 2;
+ long j234 = j5 + j232;
+ long j235 = j5 + j233;
+ float b180 = dVar3.b(j234);
+ long j236 = j234 + 1;
+ float b181 = dVar3.b(j236);
+ float b182 = dVar3.b(j235);
+ long j237 = j235 + 1;
+ float b183 = dVar3.b(j237);
+ dVar3.c(j234, b182);
+ dVar3.c(j236, b183);
+ dVar3.c(j235, b180);
+ dVar3.c(j237, b181);
+ long j238 = j232 - j207;
+ long j239 = j233 - j214;
+ long j240 = j5 + j238;
+ long j241 = j5 + j239;
+ float b184 = dVar3.b(j240);
+ long j242 = j240 + 1;
+ float b185 = dVar3.b(j242);
+ float b186 = dVar3.b(j241);
+ long j243 = j241 + 1;
+ float b187 = dVar3.b(j243);
+ dVar3.c(j240, b186);
+ dVar3.c(j242, b187);
+ dVar3.c(j241, b184);
+ dVar3.c(j243, b185);
+ long j244 = j238 - j207;
+ long j245 = j239 + j207;
+ long j246 = j5 + j244;
+ long j247 = j5 + j245;
+ float b188 = dVar3.b(j246);
+ long j248 = j246 + 1;
+ float b189 = dVar3.b(j248);
+ float b190 = dVar3.b(j247);
+ long j249 = j247 + 1;
+ float b191 = dVar3.b(j249);
+ dVar3.c(j246, b190);
+ dVar3.c(j248, b191);
+ dVar3.c(j247, b188);
+ dVar3.c(j249, b189);
+ long j250 = j244 - j207;
+ long j251 = j245 - j214;
+ long j252 = j5 + j250;
+ long j253 = j5 + j251;
+ float b192 = dVar3.b(j252);
+ long j254 = j252 + 1;
+ float b193 = dVar3.b(j254);
+ float b194 = dVar3.b(j253);
+ long j255 = j253 + 1;
+ float b195 = dVar3.b(j255);
+ dVar3.c(j252, b194);
+ dVar3.c(j254, b195);
+ dVar3.c(j253, b192);
+ dVar3.c(j255, b193);
+ long j256 = j250 + 2;
+ long j257 = j251 + j205;
+ long j258 = j5 + j256;
+ long j259 = j5 + j257;
+ float b196 = dVar3.b(j258);
+ long j260 = j258 + 1;
+ float b197 = dVar3.b(j260);
+ float b198 = dVar3.b(j259);
+ long j261 = j259 + 1;
+ float b199 = dVar3.b(j261);
+ dVar3.c(j258, b198);
+ dVar3.c(j260, b199);
+ dVar3.c(j259, b196);
+ dVar3.c(j261, b197);
+ long j262 = j256 + j207;
+ long j263 = j257 + j214;
+ long j264 = j5 + j262;
+ long j265 = j5 + j263;
+ float b200 = dVar3.b(j264);
+ long j266 = j264 + 1;
+ float b201 = dVar3.b(j266);
+ float b202 = dVar3.b(j265);
+ long j267 = j265 + 1;
+ float b203 = dVar3.b(j267);
+ dVar3.c(j264, b202);
+ dVar3.c(j266, b203);
+ dVar3.c(j265, b200);
+ dVar3.c(j267, b201);
+ long j268 = j262 + j207;
+ long j269 = j263 - j207;
+ long j270 = j5 + j268;
+ long j271 = j5 + j269;
+ float b204 = dVar3.b(j270);
+ long j272 = j270 + 1;
+ float b205 = dVar3.b(j272);
+ float b206 = dVar3.b(j271);
+ long j273 = j271 + 1;
+ float b207 = dVar3.b(j273);
+ dVar3.c(j270, b206);
+ dVar3.c(j272, b207);
+ dVar3.c(j271, b204);
+ dVar3.c(j273, b205);
+ long j274 = j268 + j207;
+ long j275 = j269 + j214;
+ long j276 = j5 + j274;
+ long j277 = j5 + j275;
+ float b208 = dVar3.b(j276);
+ long j278 = j276 + 1;
+ float b209 = dVar3.b(j278);
+ float b210 = dVar3.b(j277);
+ long j279 = j277 + 1;
+ float b211 = dVar3.b(j279);
+ dVar3.c(j276, b210);
+ dVar3.c(j278, b211);
+ dVar3.c(j277, b208);
+ dVar3.c(j279, b209);
+ long j280 = j274 - j205;
+ long j281 = j275 - 2;
+ long j282 = j5 + j280;
+ long j283 = j5 + j281;
+ float b212 = dVar3.b(j282);
+ long j284 = j282 + 1;
+ float b213 = dVar3.b(j284);
+ float b214 = dVar3.b(j283);
+ long j285 = j283 + 1;
+ float b215 = dVar3.b(j285);
+ dVar3.c(j282, b214);
+ dVar3.c(j284, b215);
+ dVar3.c(j283, b212);
+ dVar3.c(j285, b213);
+ long j286 = j280 - j207;
+ long j287 = j281 - j214;
+ long j288 = j5 + j286;
+ long j289 = j5 + j287;
+ float b216 = dVar3.b(j288);
+ long j290 = j288 + 1;
+ float b217 = dVar3.b(j290);
+ float b218 = dVar3.b(j289);
+ long j291 = j289 + 1;
+ float b219 = dVar3.b(j291);
+ dVar3.c(j288, b218);
+ dVar3.c(j290, b219);
+ dVar3.c(j289, b216);
+ dVar3.c(j291, b217);
+ long j292 = j286 - j207;
+ long j293 = j287 + j207;
+ long j294 = j5 + j292;
+ long j295 = j5 + j293;
+ float b220 = dVar3.b(j294);
+ long j296 = j294 + 1;
+ float b221 = dVar3.b(j296);
+ float b222 = dVar3.b(j295);
+ long j297 = j295 + 1;
+ float b223 = dVar3.b(j297);
+ dVar3.c(j294, b222);
+ dVar3.c(j296, b223);
+ dVar3.c(j295, b220);
+ dVar3.c(j297, b221);
+ long j298 = j5 + (j292 - j207);
+ long j299 = j5 + (j293 - j214);
+ float b224 = dVar3.b(j298);
+ long j300 = j298 + 1;
+ float b225 = dVar3.b(j300);
+ float b226 = dVar3.b(j299);
+ long j301 = j299 + 1;
+ float b227 = dVar3.b(j301);
+ dVar3.c(j298, b226);
+ dVar3.c(j300, b227);
+ dVar3.c(j299, b224);
+ dVar3.c(j301, b225);
+ j202 = j211 + 1;
+ j135 = j203;
+ j136 = j205;
+ j137 = j207;
+ j200 = j208;
+ j201 = j210;
+ }
+ long j302 = j135;
+ long j303 = j136;
+ long j304 = j137;
+ long j305 = j200;
+ long b228 = (sVar.b(j302 + j305) * 2) + j201;
+ long j306 = b228 + 2;
+ long j307 = b228 + j303;
+ long j308 = j5 + j306;
+ long j309 = j5 + j307;
+ float b229 = dVar3.b(j308);
+ long j310 = j308 + 1;
+ float b230 = dVar3.b(j310);
+ float b231 = dVar3.b(j309);
+ long j311 = j309 + 1;
+ float b232 = dVar3.b(j311);
+ dVar3.c(j308, b231);
+ dVar3.c(j310, b232);
+ dVar3.c(j309, b229);
+ dVar3.c(j311, b230);
+ long j312 = j306 + j304;
+ long j313 = j302 * 8;
+ long j314 = j307 + j313;
+ long j315 = j5 + j312;
+ long j316 = j5 + j314;
+ float b233 = dVar3.b(j315);
+ long j317 = j315 + 1;
+ float b234 = dVar3.b(j317);
+ float b235 = dVar3.b(j316);
+ long j318 = j316 + 1;
+ float b236 = dVar3.b(j318);
+ dVar3.c(j315, b235);
+ dVar3.c(j317, b236);
+ dVar3.c(j316, b233);
+ dVar3.c(j318, b234);
+ long j319 = j312 + j304;
+ long j320 = j314 - j304;
+ long j321 = j5 + j319;
+ long j322 = j5 + j320;
+ float b237 = dVar3.b(j321);
+ long j323 = j321 + 1;
+ float b238 = dVar3.b(j323);
+ float b239 = dVar3.b(j322);
+ long j324 = j322 + 1;
+ float b240 = dVar3.b(j324);
+ dVar3.c(j321, b239);
+ dVar3.c(j323, b240);
+ dVar3.c(j322, b237);
+ dVar3.c(j324, b238);
+ long j325 = j319 - 2;
+ long j326 = j320 - j303;
+ long j327 = j5 + j325;
+ long j328 = j5 + j326;
+ float b241 = dVar3.b(j327);
+ long j329 = j327 + 1;
+ float b242 = dVar3.b(j329);
+ float b243 = dVar3.b(j328);
+ long j330 = j328 + 1;
+ float b244 = dVar3.b(j330);
+ dVar3.c(j327, b243);
+ dVar3.c(j329, b244);
+ dVar3.c(j328, b241);
+ dVar3.c(j330, b242);
+ long j331 = j303 + 2;
+ long j332 = j325 + j331;
+ long j333 = j326 + j331;
+ long j334 = j5 + j332;
+ long j335 = j5 + j333;
+ float b245 = dVar3.b(j334);
+ long j336 = j334 + 1;
+ float b246 = dVar3.b(j336);
+ float b247 = dVar3.b(j335);
+ long j337 = j335 + 1;
+ float b248 = dVar3.b(j337);
+ dVar3.c(j334, b247);
+ dVar3.c(j336, b248);
+ dVar3.c(j335, b245);
+ dVar3.c(j337, b246);
+ long j338 = (j313 - 2) + j333;
+ long j339 = j5 + (j332 - (j303 - j304));
+ long j340 = j5 + j338;
+ float b249 = dVar3.b(j339);
+ long j341 = j339 + 1;
+ float b250 = dVar3.b(j341);
+ float b251 = dVar3.b(j340);
+ long j342 = j340 + 1;
+ float b252 = dVar3.b(j342);
+ dVar3.c(j339, b251);
+ dVar3.c(j341, b252);
+ dVar3.c(j340, b249);
+ dVar3.c(j342, b250);
+ j200 = j305 + 1;
+ j135 = j302;
+ j136 = j303;
+ j137 = j304;
+ }
+ return;
+ }
+ dVar3 = dVar;
+ j7 = j47;
+ long j1352 = 1;
+ while (j7 > 8) {
+ }
+ long j1362 = j4 >> 1;
+ long j1372 = j1352 * 4;
+ if (j7 == 8) {
+ }
+ }
+
+ public static void s(int i4, int i5, int i6, float[] fArr, float[] fArr2) {
+ if (i4 == 128) {
+ int i7 = i6 - 8;
+ n(fArr, i5, fArr2, i7);
+ p(fArr, i5 + 32, fArr2, i6 - 32);
+ n(fArr, i5 + 64, fArr2, i7);
+ n(fArr, i5 + 96, fArr2, i7);
+ return;
+ }
+ int i8 = i6 - 8;
+ j(fArr, i5, fArr2, i8);
+ l(fArr, i5 + 16, fArr2, i8);
+ j(fArr, i5 + 32, fArr2, i8);
+ j(fArr, i5 + 48, fArr2, i8);
+ }
+
+ public static void t(long j4, long j5, long j6, d dVar, d dVar2) {
+ if (j4 == 128) {
+ long j7 = j6 - 8;
+ m(dVar, j5, dVar2, j7);
+ o(dVar, j5 + 32, dVar2, j6 - 32);
+ m(dVar, j5 + 64, dVar2, j7);
+ m(dVar, j5 + 96, dVar2, j7);
+ return;
+ }
+ long j8 = j6 - 8;
+ i(dVar, j5, dVar2, j8);
+ k(dVar, j5 + 16, dVar2, j8);
+ i(dVar, j5 + 32, dVar2, j8);
+ i(dVar, j5 + 48, dVar2, j8);
+ }
+
+ public static void u(int i4, int i5, float[] fArr, int i6, int i7, float[] fArr2) {
+ if (i4 == 512) {
+ int i8 = i7 - 64;
+ w(128, i6, i8, fArr, fArr2);
+ int i9 = i7 - 8;
+ n(fArr, i6, fArr2, i9);
+ int i10 = i7 - 32;
+ p(fArr, i6 + 32, fArr2, i10);
+ n(fArr, i6 + 64, fArr2, i9);
+ n(fArr, i6 + 96, fArr2, i9);
+ int i11 = i6 + 128;
+ int i12 = i7 - 128;
+ y(128, i11, i12, fArr, fArr2);
+ n(fArr, i11, fArr2, i9);
+ p(fArr, i6 + 160, fArr2, i10);
+ n(fArr, i6 + 192, fArr2, i9);
+ p(fArr, i6 + 224, fArr2, i10);
+ int i13 = i6 + 256;
+ w(128, i13, i8, fArr, fArr2);
+ n(fArr, i13, fArr2, i9);
+ p(fArr, i6 + 288, fArr2, i10);
+ n(fArr, i6 + 320, fArr2, i9);
+ n(fArr, i6 + 352, fArr2, i9);
+ if (i5 != 0) {
+ w(128, i6 + 384, i8, fArr, fArr2);
+ n(fArr, i6 + 480, fArr2, i9);
+ } else {
+ y(128, i6 + 384, i12, fArr, fArr2);
+ p(fArr, i6 + 480, fArr2, i10);
+ }
+ n(fArr, i6 + 384, fArr2, i9);
+ p(fArr, i6 + 416, fArr2, i10);
+ n(fArr, i6 + 448, fArr2, i9);
+ return;
+ }
+ int i14 = i7 - 32;
+ w(64, i6, i14, fArr, fArr2);
+ int i15 = i7 - 8;
+ j(fArr, i6, fArr2, i15);
+ l(fArr, i6 + 16, fArr2, i15);
+ j(fArr, i6 + 32, fArr2, i15);
+ j(fArr, i6 + 48, fArr2, i15);
+ int i16 = i6 + 64;
+ int i17 = i7 - 64;
+ y(64, i16, i17, fArr, fArr2);
+ j(fArr, i16, fArr2, i15);
+ l(fArr, i6 + 80, fArr2, i15);
+ j(fArr, i6 + 96, fArr2, i15);
+ l(fArr, i6 + 112, fArr2, i15);
+ int i18 = i6 + 128;
+ w(64, i18, i14, fArr, fArr2);
+ j(fArr, i18, fArr2, i15);
+ l(fArr, i6 + 144, fArr2, i15);
+ j(fArr, i6 + 160, fArr2, i15);
+ j(fArr, i6 + 176, fArr2, i15);
+ if (i5 != 0) {
+ w(64, i6 + 192, i14, fArr, fArr2);
+ j(fArr, i6 + 240, fArr2, i15);
+ } else {
+ y(64, i6 + 192, i17, fArr, fArr2);
+ l(fArr, i6 + 240, fArr2, i15);
+ }
+ j(fArr, i6 + 192, fArr2, i15);
+ l(fArr, i6 + 208, fArr2, i15);
+ j(fArr, i6 + 224, fArr2, i15);
+ }
+
+ public static void v(long j4, long j5, long j6, long j7, d dVar, d dVar2) {
+ long j8;
+ if (j4 == 512) {
+ long j9 = j7 - 64;
+ x(128L, j6, j9, dVar, dVar2);
+ long j10 = j7 - 8;
+ m(dVar, j6, dVar2, j10);
+ long j11 = j7 - 32;
+ o(dVar, j6 + 32, dVar2, j11);
+ m(dVar, j6 + 64, dVar2, j10);
+ m(dVar, j6 + 96, dVar2, j10);
+ long j12 = j6 + 128;
+ long j13 = j7 - 128;
+ z(128L, j12, j13, dVar, dVar2);
+ m(dVar, j12, dVar2, j10);
+ o(dVar, j6 + 160, dVar2, j11);
+ m(dVar, j6 + 192, dVar2, j10);
+ o(dVar, j6 + 224, dVar2, j11);
+ long j14 = j6 + 256;
+ x(128L, j14, j9, dVar, dVar2);
+ m(dVar, j14, dVar2, j10);
+ o(dVar, j6 + 288, dVar2, j11);
+ m(dVar, j6 + 320, dVar2, j10);
+ m(dVar, j6 + 352, dVar2, j10);
+ if (j5 != 0) {
+ x(128L, j6 + 384, j9, dVar, dVar2);
+ m(dVar, j6 + 480, dVar2, j10);
+ } else {
+ z(128L, j6 + 384, j13, dVar, dVar2);
+ o(dVar, j6 + 480, dVar2, j11);
+ }
+ m(dVar, j6 + 384, dVar2, j10);
+ o(dVar, j6 + 416, dVar2, j11);
+ m(dVar, j6 + 448, dVar2, j10);
+ return;
+ }
+ long j15 = j7 - 32;
+ x(64L, j6, j15, dVar, dVar2);
+ long j16 = j7 - 8;
+ i(dVar, j6, dVar2, j16);
+ k(dVar, j6 + 16, dVar2, j16);
+ i(dVar, j6 + 32, dVar2, j16);
+ i(dVar, j6 + 48, dVar2, j16);
+ long j17 = j6 + 64;
+ long j18 = j7 - 64;
+ z(64L, j17, j18, dVar, dVar2);
+ i(dVar, j17, dVar2, j16);
+ k(dVar, j6 + 80, dVar2, j16);
+ i(dVar, j6 + 96, dVar2, j16);
+ k(dVar, j6 + 112, dVar2, j16);
+ long j19 = j6 + 128;
+ x(64L, j19, j15, dVar, dVar2);
+ i(dVar, j19, dVar2, j16);
+ k(dVar, j6 + 144, dVar2, j16);
+ i(dVar, j6 + 160, dVar2, j16);
+ i(dVar, j6 + 176, dVar2, j16);
+ if (j5 != 0) {
+ x(64L, j6 + 192, j15, dVar, dVar2);
+ j8 = j16;
+ i(dVar, j6 + 240, dVar2, j8);
+ } else {
+ z(64L, j6 + 192, j18, dVar, dVar2);
+ j8 = j16;
+ k(dVar, j6 + 240, dVar2, j8);
+ }
+ i(dVar, j6 + 192, dVar2, j8);
+ k(dVar, j6 + 208, dVar2, j8);
+ i(dVar, j6 + 224, dVar2, j8);
+ }
+
+ public static void w(int i4, int i5, int i6, float[] fArr, float[] fArr2) {
+ int i7 = i4 >> 3;
+ int i8 = i7 * 2;
+ int i9 = i8 + i8;
+ int i10 = i9 + i8;
+ int i11 = i5 + i8;
+ int i12 = i5 + i9;
+ int i13 = i5 + i10;
+ float f4 = fArr[i5];
+ float f5 = fArr[i12];
+ float f6 = f4 + f5;
+ int i14 = i5 + 1;
+ float f7 = fArr[i14];
+ int i15 = i12 + 1;
+ float f8 = fArr[i15];
+ float f9 = f7 + f8;
+ float f10 = f4 - f5;
+ float f11 = f7 - f8;
+ float f12 = fArr[i11];
+ float f13 = fArr[i13];
+ float f14 = f12 + f13;
+ int i16 = i11 + 1;
+ float f15 = fArr[i16];
+ int i17 = i13 + 1;
+ float f16 = fArr[i17];
+ float f17 = f15 + f16;
+ float f18 = f12 - f13;
+ float f19 = f15 - f16;
+ fArr[i5] = f6 + f14;
+ fArr[i14] = f9 + f17;
+ fArr[i11] = f6 - f14;
+ fArr[i16] = f9 - f17;
+ fArr[i12] = f10 - f19;
+ fArr[i15] = f11 + f18;
+ fArr[i13] = f10 + f19;
+ fArr[i17] = f11 - f18;
+ float f20 = fArr2[i6 + 1];
+ int i18 = 0;
+ for (int i19 = 2; i19 < i7; i19 += 2) {
+ i18 += 4;
+ int i20 = i6 + i18;
+ float f21 = fArr2[i20];
+ float f22 = fArr2[i20 + 1];
+ float f23 = fArr2[i20 + 2];
+ float f24 = fArr2[i20 + 3];
+ int i21 = i19 + i8;
+ int i22 = i21 + i8;
+ int i23 = i22 + i8;
+ int i24 = i5 + i21;
+ int i25 = i5 + i22;
+ int i26 = i5 + i23;
+ int i27 = i5 + i19;
+ float f25 = fArr[i27];
+ float f26 = fArr[i25];
+ float f27 = f25 + f26;
+ int i28 = i27 + 1;
+ float f28 = fArr[i28];
+ int i29 = i25 + 1;
+ float f29 = fArr[i29];
+ float f30 = f28 + f29;
+ float f31 = f25 - f26;
+ float f32 = f28 - f29;
+ float f33 = fArr[i24];
+ float f34 = fArr[i26];
+ float f35 = f33 + f34;
+ int i30 = i24 + 1;
+ float f36 = fArr[i30];
+ int i31 = i26 + 1;
+ float f37 = fArr[i31];
+ float f38 = f36 + f37;
+ float f39 = f33 - f34;
+ float f40 = f36 - f37;
+ fArr[i27] = f27 + f35;
+ fArr[i28] = f30 + f38;
+ fArr[i24] = f27 - f35;
+ fArr[i30] = f30 - f38;
+ float f41 = f31 - f40;
+ float f42 = f32 + f39;
+ fArr[i25] = (f21 * f41) - (f22 * f42);
+ fArr[i29] = (f41 * f22) + (f42 * f21);
+ float f43 = f31 + f40;
+ float f44 = f32 - f39;
+ fArr[i26] = (f24 * f44) + (f23 * f43);
+ fArr[i31] = (f44 * f23) - (f43 * f24);
+ int i32 = i8 - i19;
+ int i33 = i32 + i8;
+ int i34 = i33 + i8;
+ int i35 = i34 + i8;
+ int i36 = i5 + i32;
+ int i37 = i5 + i33;
+ int i38 = i5 + i34;
+ int i39 = i5 + i35;
+ float f45 = fArr[i36];
+ float f46 = fArr[i38];
+ float f47 = f45 + f46;
+ int i40 = i36 + 1;
+ float f48 = fArr[i40];
+ int i41 = i38 + 1;
+ float f49 = fArr[i41];
+ float f50 = f48 + f49;
+ float f51 = f45 - f46;
+ float f52 = f48 - f49;
+ float f53 = fArr[i37];
+ float f54 = fArr[i39];
+ float f55 = f53 + f54;
+ int i42 = i37 + 1;
+ float f56 = fArr[i42];
+ int i43 = i39 + 1;
+ float f57 = fArr[i43];
+ float f58 = f56 + f57;
+ float f59 = f53 - f54;
+ float f60 = f56 - f57;
+ fArr[i36] = f47 + f55;
+ fArr[i40] = f50 + f58;
+ fArr[i37] = f47 - f55;
+ fArr[i42] = f50 - f58;
+ float f61 = f51 - f60;
+ float f62 = f52 + f59;
+ fArr[i38] = (f22 * f61) - (f21 * f62);
+ fArr[i41] = (f21 * f61) + (f22 * f62);
+ float f63 = f51 + f60;
+ float f64 = f52 - f59;
+ fArr[i39] = (f23 * f64) + (f24 * f63);
+ fArr[i43] = (f24 * f64) - (f23 * f63);
+ }
+ int i44 = i7 + i8;
+ int i45 = i44 + i8;
+ int i46 = i8 + i45;
+ int i47 = i5 + i7;
+ int i48 = i5 + i44;
+ int i49 = i5 + i45;
+ int i50 = i5 + i46;
+ float f65 = fArr[i47];
+ float f66 = fArr[i49];
+ float f67 = f65 + f66;
+ int i51 = i47 + 1;
+ float f68 = fArr[i51];
+ int i52 = i49 + 1;
+ float f69 = fArr[i52];
+ float f70 = f68 + f69;
+ float f71 = f65 - f66;
+ float f72 = f68 - f69;
+ float f73 = fArr[i48];
+ float f74 = fArr[i50];
+ float f75 = f73 + f74;
+ int i53 = i48 + 1;
+ float f76 = fArr[i53];
+ int i54 = i50 + 1;
+ float f77 = fArr[i54];
+ float f78 = f76 + f77;
+ float f79 = f73 - f74;
+ float f80 = f76 - f77;
+ fArr[i47] = f67 + f75;
+ fArr[i51] = f70 + f78;
+ fArr[i48] = f67 - f75;
+ fArr[i53] = f70 - f78;
+ float f81 = f71 - f80;
+ float f82 = f72 + f79;
+ fArr[i49] = (f81 - f82) * f20;
+ fArr[i52] = (f82 + f81) * f20;
+ float f83 = f71 + f80;
+ float f84 = f72 - f79;
+ float f85 = -f20;
+ fArr[i50] = (f83 + f84) * f85;
+ fArr[i54] = (f84 - f83) * f85;
+ }
+
+ public static void x(long j4, long j5, long j6, d dVar, d dVar2) {
+ long j7 = j4 >> 3;
+ long j8 = j7 * 2;
+ long j9 = j8 + j8;
+ long j10 = j9 + j8;
+ long j11 = j5 + j8;
+ long j12 = j9 + j5;
+ long j13 = j10 + j5;
+ float b4 = dVar.b(j12) + dVar.b(j5);
+ long j14 = j5 + 1;
+ long j15 = j12 + 1;
+ float b5 = dVar.b(j15) + dVar.b(j14);
+ float b6 = dVar.b(j5) - dVar.b(j12);
+ float b7 = dVar.b(j14) - dVar.b(j15);
+ float b8 = dVar.b(j13) + dVar.b(j11);
+ long j16 = j11 + 1;
+ long j17 = j13 + 1;
+ float b9 = dVar.b(j17) + dVar.b(j16);
+ float b10 = dVar.b(j11) - dVar.b(j13);
+ float b11 = dVar.b(j16) - dVar.b(j17);
+ dVar.c(j14, AbstractC1518b.j(b4, b8, dVar, j5, b5, b9));
+ dVar.c(j16, AbstractC1518b.l(b4, b8, dVar, j11, b5, b9));
+ dVar.c(j15, AbstractC1518b.a(b6, b11, dVar, j12, b7, b10));
+ dVar.c(j17, AbstractC1518b.m(b6, b11, dVar, j13, b7, b10));
+ d dVar3 = dVar2;
+ float b12 = dVar3.b(j6 + 1);
+ long j18 = 0;
+ long j19 = 2;
+ while (j19 < j7) {
+ long j20 = j18 + 4;
+ long j21 = j6 + j20;
+ float b13 = dVar3.b(j21);
+ float b14 = dVar3.b(j21 + 1);
+ float b15 = dVar3.b(j21 + 2);
+ float b16 = dVar3.b(j21 + 3);
+ long j22 = j19 + j8;
+ long j23 = j22 + j8;
+ long j24 = j23 + j8;
+ long j25 = j5 + j22;
+ long j26 = j5 + j23;
+ long j27 = j5 + j24;
+ long j28 = j19;
+ long j29 = j5 + j28;
+ float b17 = dVar.b(j26) + dVar.b(j29);
+ long j30 = j29 + 1;
+ long j31 = j26 + 1;
+ float b18 = dVar.b(j31) + dVar.b(j30);
+ float b19 = dVar.b(j29) - dVar.b(j26);
+ float b20 = dVar.b(j30) - dVar.b(j31);
+ float b21 = dVar.b(j27) + dVar.b(j25);
+ long j32 = j25 + 1;
+ long j33 = j27 + 1;
+ float b22 = dVar.b(j33) + dVar.b(j32);
+ float b23 = dVar.b(j25) - dVar.b(j27);
+ float b24 = dVar.b(j32) - dVar.b(j33);
+ dVar.c(j30, AbstractC1518b.j(b17, b21, dVar, j29, b18, b22));
+ dVar.c(j32, AbstractC1518b.l(b17, b21, dVar, j25, b18, b22));
+ float f4 = b19 - b24;
+ float f5 = b20 + b23;
+ dVar.c(j26, (b13 * f4) - (b14 * f5));
+ float j34 = AbstractC1518b.j(f4 * b14, f5 * b13, dVar, j31, b19, b24);
+ float f6 = b20 - b23;
+ dVar.c(j27, (b16 * f6) + (b15 * j34));
+ dVar.c(j33, (f6 * b15) - (j34 * b16));
+ long j35 = j8 - j28;
+ long j36 = j35 + j8;
+ long j37 = j36 + j8;
+ long j38 = j5 + j35;
+ long j39 = j5 + j36;
+ long j40 = j5 + j37;
+ long j41 = j5 + j37 + j8;
+ float b25 = dVar.b(j38) + dVar.b(j40);
+ long j42 = j38 + 1;
+ long j43 = j40 + 1;
+ float b26 = dVar.b(j43) + dVar.b(j42);
+ float b27 = dVar.b(j38) - dVar.b(j40);
+ float b28 = dVar.b(j42) - dVar.b(j43);
+ float b29 = dVar.b(j41) + dVar.b(j39);
+ long j44 = j39 + 1;
+ long j45 = j41 + 1;
+ float b30 = dVar.b(j45) + dVar.b(j44);
+ float b31 = dVar.b(j39) - dVar.b(j41);
+ float b32 = dVar.b(j44) - dVar.b(j45);
+ dVar.c(j42, AbstractC1518b.j(b25, b29, dVar, j38, b26, b30));
+ dVar.c(j44, AbstractC1518b.l(b25, b29, dVar, j39, b26, b30));
+ float f7 = b27 - b32;
+ float f8 = b28 + b31;
+ dVar.c(j40, (b14 * f7) - (b13 * f8));
+ float j46 = AbstractC1518b.j(f7 * b13, f8 * b14, dVar, j43, b27, b32);
+ float f9 = b28 - b31;
+ dVar.c(j41, (b15 * f9) + (b16 * j46));
+ dVar.c(j45, (b16 * f9) - (b15 * j46));
+ j19 = j28 + 2;
+ dVar3 = dVar2;
+ b12 = b12;
+ j18 = j20;
+ }
+ float f10 = b12;
+ long j47 = j7 + j8;
+ long j48 = j47 + j8;
+ long j49 = j5 + j7;
+ long j50 = j5 + j47;
+ long j51 = j5 + j48;
+ long j52 = j5 + j48 + j8;
+ float b33 = dVar.b(j49) + dVar.b(j51);
+ long j53 = j49 + 1;
+ long j54 = j51 + 1;
+ float b34 = dVar.b(j54) + dVar.b(j53);
+ float b35 = dVar.b(j49) - dVar.b(j51);
+ float b36 = dVar.b(j53) - dVar.b(j54);
+ float b37 = dVar.b(j52) + dVar.b(j50);
+ long j55 = j50 + 1;
+ long j56 = j52 + 1;
+ float b38 = dVar.b(j56) + dVar.b(j55);
+ float b39 = dVar.b(j50) - dVar.b(j52);
+ float b40 = dVar.b(j55) - dVar.b(j56);
+ dVar.c(j53, AbstractC1518b.j(b33, b37, dVar, j49, b34, b38));
+ dVar.c(j55, AbstractC1518b.l(b33, b37, dVar, j50, b34, b38));
+ float f11 = b35 - b40;
+ float f12 = b36 + b39;
+ dVar.c(j51, (f11 - f12) * f10);
+ dVar.c(j54, (f12 + f11) * f10);
+ float f13 = b35 + b40;
+ float f14 = b36 - b39;
+ float f15 = -f10;
+ dVar.c(j52, (f13 + f14) * f15);
+ dVar.c(j56, f15 * (f14 - f13));
+ }
+
+ public static void y(int i4, int i5, int i6, float[] fArr, float[] fArr2) {
+ int i7 = i4 >> 3;
+ int i8 = i7 * 2;
+ float f4 = fArr2[i6 + 1];
+ int i9 = i8 + i8;
+ int i10 = i9 + i8;
+ int i11 = i5 + i8;
+ int i12 = i5 + i9;
+ int i13 = i5 + i10;
+ float f5 = fArr[i5];
+ int i14 = i12 + 1;
+ float f6 = fArr[i14];
+ float f7 = f5 - f6;
+ int i15 = i5 + 1;
+ float f8 = fArr[i15];
+ float f9 = fArr[i12];
+ float f10 = f8 + f9;
+ float f11 = f5 + f6;
+ float f12 = f8 - f9;
+ float f13 = fArr[i11];
+ int i16 = i13 + 1;
+ float f14 = fArr[i16];
+ float f15 = f13 - f14;
+ int i17 = i11 + 1;
+ float f16 = fArr[i17];
+ float f17 = fArr[i13];
+ float f18 = f16 + f17;
+ float f19 = f13 + f14;
+ float f20 = f16 - f17;
+ float f21 = (f15 - f18) * f4;
+ float f22 = (f18 + f15) * f4;
+ fArr[i5] = f7 + f21;
+ fArr[i15] = f10 + f22;
+ fArr[i11] = f7 - f21;
+ fArr[i17] = f10 - f22;
+ float f23 = (f19 - f20) * f4;
+ float f24 = (f20 + f19) * f4;
+ fArr[i12] = f11 - f24;
+ fArr[i14] = f12 + f23;
+ fArr[i13] = f11 + f24;
+ fArr[i16] = f12 - f23;
+ int i18 = i7 * 4;
+ int i19 = 0;
+ for (int i20 = 2; i20 < i7; i20 += 2) {
+ i19 += 4;
+ int i21 = i6 + i19;
+ float f25 = fArr2[i21];
+ float f26 = fArr2[i21 + 1];
+ float f27 = fArr2[i21 + 2];
+ float f28 = fArr2[i21 + 3];
+ i18 -= 4;
+ int i22 = i6 + i18;
+ float f29 = fArr2[i22];
+ float f30 = fArr2[i22 + 1];
+ float f31 = fArr2[i22 + 2];
+ float f32 = fArr2[i22 + 3];
+ int i23 = i20 + i8;
+ int i24 = i23 + i8;
+ int i25 = i24 + i8;
+ int i26 = i5 + i23;
+ int i27 = i5 + i24;
+ int i28 = i5 + i25;
+ int i29 = i5 + i20;
+ float f33 = fArr[i29];
+ int i30 = i27 + 1;
+ float f34 = fArr[i30];
+ float f35 = f33 - f34;
+ int i31 = i29 + 1;
+ float f36 = fArr[i31];
+ float f37 = fArr[i27];
+ float f38 = f36 + f37;
+ float f39 = f33 + f34;
+ float f40 = f36 - f37;
+ float f41 = fArr[i26];
+ int i32 = i28 + 1;
+ float f42 = fArr[i32];
+ float f43 = f41 - f42;
+ int i33 = i26 + 1;
+ float f44 = fArr[i33];
+ float f45 = fArr[i28];
+ float f46 = f44 + f45;
+ float f47 = f41 + f42;
+ float f48 = f44 - f45;
+ float f49 = (f25 * f35) - (f26 * f38);
+ float f50 = (f35 * f26) + (f38 * f25);
+ float f51 = (f30 * f43) - (f29 * f46);
+ float f52 = (f43 * f29) + (f46 * f30);
+ fArr[i29] = f49 + f51;
+ fArr[i31] = f50 + f52;
+ fArr[i26] = f49 - f51;
+ fArr[i33] = f50 - f52;
+ float f53 = (f28 * f40) + (f27 * f39);
+ float f54 = (f40 * f27) - (f39 * f28);
+ float f55 = (f31 * f48) + (f32 * f47);
+ float f56 = (f48 * f32) - (f47 * f31);
+ fArr[i27] = f53 + f55;
+ fArr[i30] = f54 + f56;
+ fArr[i28] = f53 - f55;
+ fArr[i32] = f54 - f56;
+ int i34 = i8 - i20;
+ int i35 = i34 + i8;
+ int i36 = i35 + i8;
+ int i37 = i36 + i8;
+ int i38 = i5 + i34;
+ int i39 = i5 + i35;
+ int i40 = i5 + i36;
+ int i41 = i5 + i37;
+ float f57 = fArr[i38];
+ int i42 = i40 + 1;
+ float f58 = fArr[i42];
+ float f59 = f57 - f58;
+ int i43 = i38 + 1;
+ float f60 = fArr[i43];
+ float f61 = fArr[i40];
+ float f62 = f60 + f61;
+ float f63 = f57 + f58;
+ float f64 = f60 - f61;
+ float f65 = fArr[i39];
+ int i44 = i41 + 1;
+ float f66 = fArr[i44];
+ float f67 = f65 - f66;
+ int i45 = i39 + 1;
+ float f68 = fArr[i45];
+ float f69 = fArr[i41];
+ float f70 = f68 + f69;
+ float f71 = f65 + f66;
+ float f72 = f68 - f69;
+ float f73 = (f29 * f59) - (f30 * f62);
+ float f74 = (f30 * f59) + (f29 * f62);
+ float f75 = (f26 * f67) - (f25 * f70);
+ float f76 = (f25 * f67) + (f26 * f70);
+ fArr[i38] = f73 + f75;
+ fArr[i43] = f74 + f76;
+ fArr[i39] = f73 - f75;
+ fArr[i45] = f74 - f76;
+ float f77 = (f32 * f64) + (f31 * f63);
+ float f78 = (f31 * f64) - (f32 * f63);
+ float f79 = (f27 * f72) + (f28 * f71);
+ float f80 = (f28 * f72) - (f27 * f71);
+ fArr[i40] = f77 + f79;
+ fArr[i42] = f78 + f80;
+ fArr[i41] = f77 - f79;
+ fArr[i44] = f78 - f80;
+ }
+ int i46 = i6 + i8;
+ float f81 = fArr2[i46];
+ float f82 = fArr2[i46 + 1];
+ int i47 = i7 + i8;
+ int i48 = i47 + i8;
+ int i49 = i8 + i48;
+ int i50 = i5 + i7;
+ int i51 = i5 + i47;
+ int i52 = i5 + i48;
+ int i53 = i5 + i49;
+ float f83 = fArr[i50];
+ int i54 = i52 + 1;
+ float f84 = fArr[i54];
+ float f85 = f83 - f84;
+ int i55 = i50 + 1;
+ float f86 = fArr[i55];
+ float f87 = fArr[i52];
+ float f88 = f86 + f87;
+ float f89 = f83 + f84;
+ float f90 = f86 - f87;
+ float f91 = fArr[i51];
+ int i56 = i53 + 1;
+ float f92 = fArr[i56];
+ float f93 = f91 - f92;
+ int i57 = i51 + 1;
+ float f94 = fArr[i57];
+ float f95 = fArr[i53];
+ float f96 = f94 + f95;
+ float f97 = f91 + f92;
+ float f98 = f94 - f95;
+ float f99 = (f81 * f85) - (f82 * f88);
+ float f100 = (f85 * f82) + (f88 * f81);
+ float f101 = (f82 * f93) - (f81 * f96);
+ float f102 = (f93 * f81) + (f96 * f82);
+ fArr[i50] = f99 + f101;
+ fArr[i55] = f100 + f102;
+ fArr[i51] = f99 - f101;
+ fArr[i57] = f100 - f102;
+ float f103 = (f82 * f89) - (f81 * f90);
+ float f104 = (f89 * f81) + (f90 * f82);
+ float f105 = (f81 * f97) - (f82 * f98);
+ float f106 = (f82 * f97) + (f81 * f98);
+ fArr[i52] = f103 - f105;
+ fArr[i54] = f104 - f106;
+ fArr[i53] = f103 + f105;
+ fArr[i56] = f104 + f106;
+ }
+
+ public static void z(long j4, long j5, long j6, d dVar, d dVar2) {
+ long j7 = j4 >> 3;
+ long j8 = j7 * 2;
+ float b4 = dVar2.b(j6 + 1);
+ long j9 = j8 + j8;
+ long j10 = j9 + j8;
+ long j11 = j5 + j8;
+ long j12 = j9 + j5;
+ long j13 = j10 + j5;
+ long j14 = j12 + 1;
+ float b5 = dVar.b(j5) - dVar.b(j14);
+ long j15 = j5 + 1;
+ float b6 = dVar.b(j12) + dVar.b(j15);
+ float b7 = dVar.b(j14) + dVar.b(j5);
+ float b8 = dVar.b(j15) - dVar.b(j12);
+ long j16 = j13 + 1;
+ float b9 = dVar.b(j11) - dVar.b(j16);
+ long j17 = j11 + 1;
+ float b10 = dVar.b(j13) + dVar.b(j17);
+ float b11 = dVar.b(j16) + dVar.b(j11);
+ float b12 = dVar.b(j17) - dVar.b(j13);
+ float f4 = (b9 - b10) * b4;
+ float f5 = (b10 + b9) * b4;
+ dVar.c(j15, AbstractC1518b.j(b5, f4, dVar, j5, b6, f5));
+ dVar.c(j17, AbstractC1518b.l(b5, f4, dVar, j11, b6, f5));
+ float f6 = (b11 - b12) * b4;
+ float f7 = (b12 + b11) * b4;
+ dVar.c(j14, AbstractC1518b.a(b7, f7, dVar, j12, b8, f6));
+ dVar.c(j16, AbstractC1518b.m(b7, f7, dVar, j13, b8, f6));
+ long j18 = 4;
+ long j19 = j7 * 4;
+ long j20 = 0;
+ int i4 = 2;
+ while (true) {
+ long j21 = i4;
+ if (j21 < j7) {
+ long j22 = j20 + j18;
+ long j23 = j6 + j22;
+ float b13 = dVar2.b(j23);
+ float b14 = dVar2.b(j23 + 1);
+ float b15 = dVar2.b(j23 + 2);
+ float b16 = dVar2.b(j23 + 3);
+ long j24 = j19 - j18;
+ long j25 = j6 + j24;
+ float b17 = dVar2.b(j25);
+ float b18 = dVar2.b(j25 + 1);
+ float b19 = dVar2.b(j25 + 2);
+ float b20 = dVar2.b(j25 + 3);
+ long j26 = j21 + j8;
+ long j27 = j26 + j8;
+ long j28 = j27 + j8;
+ long j29 = j5 + j26;
+ long j30 = j5 + j27;
+ long j31 = j5 + j28;
+ long j32 = j5 + j21;
+ int i5 = i4;
+ long j33 = j30 + 1;
+ float b21 = dVar.b(j32) - dVar.b(j33);
+ long j34 = j32 + 1;
+ float b22 = dVar.b(j30) + dVar.b(j34);
+ float b23 = dVar.b(j33) + dVar.b(j32);
+ float b24 = dVar.b(j34) - dVar.b(j30);
+ long j35 = j31 + 1;
+ float b25 = dVar.b(j29) - dVar.b(j35);
+ long j36 = j29 + 1;
+ float b26 = dVar.b(j31) + dVar.b(j36);
+ float b27 = dVar.b(j35) + dVar.b(j29);
+ float b28 = dVar.b(j36) - dVar.b(j31);
+ float f8 = (b13 * b21) - (b14 * b22);
+ float f9 = (b21 * b14) + (b22 * b13);
+ float f10 = (b18 * b25) - (b17 * b26);
+ float f11 = (b25 * b17) + (b26 * b18);
+ dVar.c(j34, AbstractC1518b.j(f8, f10, dVar, j32, f9, f11));
+ dVar.c(j36, AbstractC1518b.l(f8, f10, dVar, j29, f9, f11));
+ float f12 = (b15 * b23) + (b16 * b24);
+ float f13 = (b15 * b24) - (b23 * b16);
+ float f14 = (b20 * b27) + (b19 * b28);
+ float f15 = (b28 * b20) - (b27 * b19);
+ dVar.c(j33, AbstractC1518b.j(f12, f14, dVar, j30, f13, f15));
+ dVar.c(j35, AbstractC1518b.l(f12, f14, dVar, j31, f13, f15));
+ long j37 = j8 - j21;
+ long j38 = j37 + j8;
+ long j39 = j38 + j8;
+ long j40 = j39 + j8;
+ long j41 = j5 + j37;
+ long j42 = j5 + j38;
+ long j43 = j5 + j39;
+ long j44 = j5 + j40;
+ long j45 = j43 + 1;
+ float b29 = dVar.b(j41) - dVar.b(j45);
+ long j46 = j41 + 1;
+ float b30 = dVar.b(j43) + dVar.b(j46);
+ float b31 = dVar.b(j45) + dVar.b(j41);
+ float b32 = dVar.b(j46) - dVar.b(j43);
+ long j47 = j44 + 1;
+ float b33 = dVar.b(j42) - dVar.b(j47);
+ long j48 = j42 + 1;
+ float b34 = dVar.b(j44) + dVar.b(j48);
+ float b35 = dVar.b(j47) + dVar.b(j42);
+ float b36 = dVar.b(j48) - dVar.b(j44);
+ float f16 = (b17 * b29) - (b18 * b30);
+ float f17 = (b18 * b29) + (b17 * b30);
+ float f18 = (b14 * b33) - (b13 * b34);
+ float f19 = (b33 * b13) + (b14 * b34);
+ dVar.c(j46, AbstractC1518b.j(f16, f18, dVar, j41, f17, f19));
+ dVar.c(j48, AbstractC1518b.l(f16, f18, dVar, j42, f17, f19));
+ float f20 = (b19 * b31) + (b20 * b32);
+ float f21 = (b19 * b32) - (b20 * b31);
+ float f22 = (b16 * b35) + (b15 * b36);
+ float f23 = (b16 * b36) - (b15 * b35);
+ dVar.c(j45, AbstractC1518b.j(f20, f22, dVar, j43, f21, f23));
+ dVar.c(j47, AbstractC1518b.l(f20, f22, dVar, j44, f21, f23));
+ i4 = i5 + 2;
+ j19 = j24;
+ j20 = j22;
+ j18 = 4;
+ } else {
+ long j49 = j6 + j8;
+ float b37 = dVar2.b(j49);
+ float b38 = dVar2.b(j49 + 1);
+ long j50 = j7 + j8;
+ long j51 = j50 + j8;
+ long j52 = j51 + j8;
+ long j53 = j5 + j7;
+ long j54 = j5 + j50;
+ long j55 = j5 + j51;
+ long j56 = j5 + j52;
+ long j57 = j55 + 1;
+ float b39 = dVar.b(j53) - dVar.b(j57);
+ long j58 = j53 + 1;
+ float b40 = dVar.b(j55) + dVar.b(j58);
+ float b41 = dVar.b(j57) + dVar.b(j53);
+ float b42 = dVar.b(j58) - dVar.b(j55);
+ long j59 = j56 + 1;
+ float b43 = dVar.b(j54) - dVar.b(j59);
+ long j60 = j54 + 1;
+ float b44 = dVar.b(j56) + dVar.b(j60);
+ float b45 = dVar.b(j59) + dVar.b(j54);
+ float b46 = dVar.b(j60) - dVar.b(j56);
+ float f24 = (b37 * b39) - (b38 * b40);
+ float f25 = (b39 * b38) + (b37 * b40);
+ float f26 = (b38 * b43) - (b37 * b44);
+ float f27 = (b43 * b37) + (b44 * b38);
+ dVar.c(j58, AbstractC1518b.j(f24, f26, dVar, j53, f25, f27));
+ dVar.c(j60, AbstractC1518b.l(f24, f26, dVar, j54, f25, f27));
+ float f28 = (b38 * b41) - (b37 * b42);
+ float f29 = (b37 * b41) + (b38 * b42);
+ float f30 = (b37 * b45) - (b38 * b46);
+ float f31 = (b38 * b45) + (b37 * b46);
+ dVar.c(j57, AbstractC1518b.l(f28, f30, dVar, j55, f29, f31));
+ dVar.c(j59, AbstractC1518b.j(f28, f30, dVar, j56, f29, f31));
+ return;
+ }
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/k3/a.java b/feature/cw/src/main/java/k3/a.java
new file mode 100644
index 00000000..01fcf988
--- /dev/null
+++ b/feature/cw/src/main/java/k3/a.java
@@ -0,0 +1,11 @@
+package k3;
+
+import java.lang.Thread;
+
+/* loaded from: classes.dex */
+public final class a implements Thread.UncaughtExceptionHandler {
+ @Override // java.lang.Thread.UncaughtExceptionHandler
+ public final void uncaughtException(Thread thread, Throwable th) {
+ th.printStackTrace();
+ }
+}
diff --git a/feature/cw/src/main/java/k3/b.java b/feature/cw/src/main/java/k3/b.java
new file mode 100644
index 00000000..7c1a67f6
--- /dev/null
+++ b/feature/cw/src/main/java/k3/b.java
@@ -0,0 +1,25 @@
+package k3;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+/* loaded from: classes.dex */
+public final class b implements ThreadFactory {
+
+ /* renamed from: b, reason: collision with root package name */
+ public static final ThreadFactory f12091b = Executors.defaultThreadFactory();
+
+ /* renamed from: a, reason: collision with root package name */
+ public final a f12092a;
+
+ public b(a aVar) {
+ this.f12092a = aVar;
+ }
+
+ @Override // java.util.concurrent.ThreadFactory
+ public final Thread newThread(Runnable runnable) {
+ Thread newThread = f12091b.newThread(runnable);
+ newThread.setUncaughtExceptionHandler(this.f12092a);
+ return newThread;
+ }
+}
diff --git a/feature/cw/src/main/java/k3/c.java b/feature/cw/src/main/java/k3/c.java
new file mode 100644
index 00000000..90783e85
--- /dev/null
+++ b/feature/cw/src/main/java/k3/c.java
@@ -0,0 +1,42 @@
+package k3;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+/* loaded from: classes.dex */
+public abstract class c {
+
+ /* renamed from: a, reason: collision with root package name */
+ public static final ExecutorService f12093a;
+
+ /* renamed from: b, reason: collision with root package name */
+ public static ExecutorService f12094b;
+ public static final int c;
+
+ /* renamed from: d, reason: collision with root package name */
+ public static final long f12095d;
+
+ /* JADX WARN: Type inference failed for: r1v0, types: [java.lang.Object, k3.a] */
+ static {
+ ExecutorService newCachedThreadPool = Executors.newCachedThreadPool(new b(new a()));
+ f12093a = newCachedThreadPool;
+ f12094b = newCachedThreadPool;
+ c = Runtime.getRuntime().availableProcessors();
+ f12095d = 100000L;
+ }
+
+ public static Future a(Runnable runnable) {
+ if (f12094b.isShutdown() || f12094b.isTerminated()) {
+ f12094b = f12093a;
+ }
+ return f12094b.submit(runnable);
+ }
+
+ public static void b(Future[] futureArr) throws InterruptedException, java.util.concurrent.ExecutionException {
+ // smali: 无 catch 直接向上抛 -> Java 声明 throws(忠实表达)
+ for (Future future : futureArr) {
+ future.get();
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/k3/d.java b/feature/cw/src/main/java/k3/d.java
new file mode 100644
index 00000000..06bd755f
--- /dev/null
+++ b/feature/cw/src/main/java/k3/d.java
@@ -0,0 +1,100 @@
+package k3;
+
+import com.rtbishop.look4sat.feature.cw.suncompat.Cleaner;
+
+/* loaded from: classes.dex */
+public final class d extends g {
+
+ /* renamed from: k, reason: collision with root package name */
+ public float[] f12096k;
+
+ public d() {
+ }
+
+ public d(long j4, boolean z3) {
+ this.f = q.f12106g;
+ this.f12103h = 4L;
+ if (j4 > 0) {
+ this.f12102g = j4;
+ if (j4 > 1073741824) {
+ this.f12105j = r.f12109a.allocateMemory(4 * j4);
+ if (z3) {
+ a(j4);
+ }
+ Cleaner.create(this, new f(this.f12105j, this.f12102g, this.f12103h));
+ K1.a.c += this.f12102g * this.f12103h;
+ return;
+ }
+ this.f12096k = new float[(int) j4];
+ return;
+ }
+ throw new IllegalArgumentException(j4 + " is not a positive long value");
+ }
+
+ public final float b(long j4) {
+ float[] fArr = this.f12096k;
+ long j5 = this.f12105j;
+ if (j5 != 0) {
+ return r.f12109a.getFloat((this.f12103h * j4) + j5);
+ }
+ if (this.f12104i) {
+ return fArr[0];
+ }
+ return fArr[(int) j4];
+ }
+
+ public final void c(long j4, float f) {
+ long j5 = this.f12105j;
+ if (j5 != 0) {
+ r.f12109a.putFloat((this.f12103h * j4) + j5, f);
+ } else {
+ if (!this.f12104i) {
+ this.f12096k[(int) j4] = f;
+ return;
+ }
+ throw new IllegalAccessError("Constant arrays cannot be modified.");
+ }
+ }
+
+ /* JADX WARN: Type inference failed for: r0v1, types: [k3.g, java.lang.Object, k3.d] */
+ public final Object clone() {
+ if (this.f12104i) {
+ long j4 = this.f12102g;
+ float b4 = b(0L);
+ d gVar = new d();
+ gVar.f = q.f12106g;
+ gVar.f12103h = 4L;
+ if (j4 > 0) {
+ gVar.f12102g = j4;
+ gVar.f12104i = true;
+ gVar.f12096k = new float[]{b4};
+ return gVar;
+ }
+ throw new IllegalArgumentException(j4 + " is not a positive long value");
+ }
+ d dVar = new d(this.f12102g, false);
+ r.a(0L, 0L, this.f12102g, this, dVar);
+ return dVar;
+ }
+
+ @Override // k3.g
+ public final boolean equals(Object obj) {
+ if (!super.equals(obj) || this.f12096k != ((d) obj).f12096k) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override // k3.g
+ public final int hashCode() {
+ int i4;
+ int hashCode = super.hashCode() * 29;
+ float[] fArr = this.f12096k;
+ if (fArr != null) {
+ i4 = fArr.hashCode();
+ } else {
+ i4 = 0;
+ }
+ return hashCode + i4;
+ }
+}
diff --git a/feature/cw/src/main/java/k3/e.java b/feature/cw/src/main/java/k3/e.java
new file mode 100644
index 00000000..a1a72529
--- /dev/null
+++ b/feature/cw/src/main/java/k3/e.java
@@ -0,0 +1,79 @@
+package k3;
+
+/* loaded from: classes.dex */
+public final class e implements Runnable {
+ public final /* synthetic */ long f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public final /* synthetic */ long f12097g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public final /* synthetic */ long f12098h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public final /* synthetic */ g f12099i;
+
+ public e(g gVar, long j4, long j5, long j6) {
+ this.f12099i = gVar;
+ this.f = j4;
+ this.f12097g = j5;
+ this.f12098h = j6;
+ }
+
+ /* JADX WARN: Can't fix incorrect switch cases order, some code will duplicate */
+ /* JADX WARN: Failed to find 'out' block for switch in B:2:0x0011. Please report as an issue. */
+ @Override // java.lang.Runnable
+ public final void run() {
+ g gVar = this.f12099i;
+ int ordinal = gVar.f.ordinal();
+ long j4 = this.f12098h;
+ long j5 = this.f12097g;
+ long j6 = this.f;
+ switch (ordinal) {
+ case 0:
+ case 1:
+ case 2:
+ case 10:
+ case 11:
+ while (j6 < j5) {
+ r.f12109a.putByte((gVar.f12103h * j6) + j4, (byte) 0);
+ j6++;
+ }
+ return;
+ case 3:
+ while (j6 < j5) {
+ r.f12109a.putShort((gVar.f12103h * j6) + j4, (short) 0);
+ j6++;
+ }
+ return;
+ case 4:
+ while (j6 < j5) {
+ r.f12109a.putInt((gVar.f12103h * j6) + j4, 0);
+ j6++;
+ }
+ return;
+ case 5:
+ while (j6 < j5) {
+ r.f12109a.putLong((gVar.f12103h * j6) + j4, 0L);
+ j6++;
+ }
+ return;
+ case 6:
+ while (j6 < j5) {
+ r.f12109a.putFloat((gVar.f12103h * j6) + j4, 0.0f);
+ j6++;
+ }
+ return;
+ case 7:
+ while (j6 < j5) {
+ r.f12109a.putDouble((gVar.f12103h * j6) + j4, 0.0d);
+ j6++;
+ }
+ return;
+ case 8:
+ case 9:
+ default:
+ throw new IllegalArgumentException("Invalid array type.");
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/k3/f.java b/feature/cw/src/main/java/k3/f.java
new file mode 100644
index 00000000..2427a13e
--- /dev/null
+++ b/feature/cw/src/main/java/k3/f.java
@@ -0,0 +1,32 @@
+package k3;
+
+/* loaded from: classes.dex */
+public final class f implements Runnable {
+ public long f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public final long f12100g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public final long f12101h;
+
+ public f(long j4, long j5, long j6) {
+ this.f = j4;
+ this.f12100g = j5;
+ this.f12101h = j6;
+ }
+
+ @Override // java.lang.Runnable
+ public final void run() {
+ long j4 = this.f;
+ if (j4 != 0) {
+ r.f12109a.freeMemory(j4);
+ this.f = 0L;
+ long j5 = K1.a.c - (this.f12100g * this.f12101h);
+ K1.a.c = j5;
+ if (j5 < 0) {
+ K1.a.c = 0L;
+ }
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/k3/g.java b/feature/cw/src/main/java/k3/g.java
new file mode 100644
index 00000000..150b3b7f
--- /dev/null
+++ b/feature/cw/src/main/java/k3/g.java
@@ -0,0 +1,92 @@
+package k3;
+
+import java.io.Serializable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+/* loaded from: classes.dex */
+public abstract class g implements Serializable, Cloneable {
+ public q f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public long f12102g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public long f12103h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public boolean f12104i = false;
+
+ /* renamed from: j, reason: collision with root package name */
+ public long f12105j = 0;
+
+ public final void a(long j4) {
+ long j5;
+ g gVar = this;
+ long j6 = gVar.f12105j;
+ if (j6 != 0) {
+ long j7 = c.c;
+ double[][] dArr = g3.c.f11585a;
+ if (j4 <= j7) {
+ j7 = j4;
+ }
+ int i4 = (int) j7;
+ if (i4 > 2 && j4 >= c.f12095d) {
+ long j8 = j4 / i4;
+ Future[] futureArr = new Future[i4];
+ int i5 = 0;
+ while (i5 < i4) {
+ long j9 = i5 * j8;
+ if (i5 == i4 - 1) {
+ j5 = j4;
+ } else {
+ j5 = j9 + j8;
+ }
+ futureArr[i5] = c.a(new e(gVar, j9, j5, j6));
+ i5++;
+ gVar = gVar;
+ j6 = j6;
+ }
+ g gVar2 = gVar;
+ try {
+ c.b(futureArr);
+ return;
+ } catch (InterruptedException unused) {
+ r.f12109a.setMemory(gVar2.f12105j, gVar2.f12103h * j4, (byte) 0);
+ return;
+ } catch (ExecutionException unused2) {
+ r.f12109a.setMemory(gVar2.f12105j, j4 * gVar2.f12103h, (byte) 0);
+ return;
+ }
+ }
+ r.f12109a.setMemory(j6, gVar.f12103h * j4, (byte) 0);
+ }
+ }
+
+ public boolean equals(Object obj) {
+ if (obj != null && (obj instanceof g)) {
+ g gVar = (g) obj;
+ if (this.f == gVar.f && this.f12102g == gVar.f12102g && this.f12103h == gVar.f12103h && this.f12104i == gVar.f12104i && this.f12105j == gVar.f12105j) {
+ return true;
+ }
+ return false;
+ }
+ return false;
+ }
+
+ public int hashCode() {
+ int i4;
+ q qVar = this.f;
+ if (qVar != null) {
+ i4 = qVar.hashCode();
+ } else {
+ i4 = 0;
+ }
+ long j4 = this.f12102g;
+ int i5 = (((203 + i4) * 29) + ((int) (j4 ^ (j4 >>> 32)))) * 29;
+ long j5 = this.f12103h;
+ int i6 = (((i5 + ((int) (j5 ^ (j5 >>> 32)))) * 29) + (this.f12104i ? 1 : 0)) * 841;
+ long j6 = this.f12105j;
+ return i6 + ((int) (j6 ^ (j6 >>> 32)));
+ }
+}
diff --git a/feature/cw/src/main/java/k3/l.java b/feature/cw/src/main/java/k3/l.java
new file mode 100644
index 00000000..fc29d402
--- /dev/null
+++ b/feature/cw/src/main/java/k3/l.java
@@ -0,0 +1,8 @@
+package k3;
+
+/* loaded from: classes.dex */
+public final class l extends q {
+ public l() {
+ super("LONG", 5);
+ }
+}
diff --git a/feature/cw/src/main/java/k3/m.java b/feature/cw/src/main/java/k3/m.java
new file mode 100644
index 00000000..b01535dc
--- /dev/null
+++ b/feature/cw/src/main/java/k3/m.java
@@ -0,0 +1,8 @@
+package k3;
+
+/* loaded from: classes.dex */
+public final class m extends q {
+ public m() {
+ super("FLOAT", 6);
+ }
+}
diff --git a/feature/cw/src/main/java/k3/n.java b/feature/cw/src/main/java/k3/n.java
new file mode 100644
index 00000000..463f7e84
--- /dev/null
+++ b/feature/cw/src/main/java/k3/n.java
@@ -0,0 +1,8 @@
+package k3;
+
+/* loaded from: classes.dex */
+public final class n extends q {
+ public n() {
+ super("DOUBLE", 7);
+ }
+}
diff --git a/feature/cw/src/main/java/k3/q.java b/feature/cw/src/main/java/k3/q.java
new file mode 100644
index 00000000..5f84ea2d
--- /dev/null
+++ b/feature/cw/src/main/java/k3/q.java
@@ -0,0 +1,68 @@
+package k3;
+
+/**
+ * R8 生成的伪 enum(k3 FFT 库的数组类型枚举)。
+ * smali 中 q 的直接子类:l(LONG/5)、m(FLOAT/6)、n(DOUBLE/7),
+ * 其余常量(BYTE/UNSIGNED_BYTE/SHORT/INT/COMPLEX_FLOAT/COMPLEX_DOUBLE/STRING/OBJECT)
+ * 直接以 q 实例表达。
+ */
+public class q {
+ public static final l f;
+
+ /* renamed from: g, reason: collision with root package name */
+ public static final m f12106g;
+
+ /* renamed from: h, reason: collision with root package name */
+ public static final n f12107h;
+
+ /* renamed from: i, reason: collision with root package name */
+ public static final /* synthetic */ q[] f12108i;
+
+ private final String name;
+ private final int ordinal;
+
+ protected q(String name, int ordinal) {
+ this.name = name;
+ this.ordinal = ordinal;
+ }
+
+ public final String name() {
+ return name;
+ }
+
+ public final int ordinal() {
+ return ordinal;
+ }
+
+ public static q valueOf(String str) {
+ for (q qVar : f12108i) {
+ if (qVar.name.equals(str)) {
+ return qVar;
+ }
+ }
+ throw new IllegalArgumentException("No enum constant k3.q." + str);
+ }
+
+ public static q[] values() {
+ return (q[]) f12108i.clone();
+ }
+
+ static {
+ q logic = new q("LOGIC", 0);
+ q byteType = new q("BYTE", 1);
+ q unsignedByte = new q("UNSIGNED_BYTE", 2);
+ q shortType = new q("SHORT", 3);
+ q intType = new q("INT", 4);
+ l longType = new l();
+ f = longType;
+ m floatType = new m();
+ f12106g = floatType;
+ n doubleType = new n();
+ f12107h = doubleType;
+ q complexFloat = new q("COMPLEX_FLOAT", 8);
+ q complexDouble = new q("COMPLEX_DOUBLE", 9);
+ q string = new q("STRING", 10);
+ q object = new q("OBJECT", 11);
+ f12108i = new q[]{logic, byteType, unsignedByte, shortType, intType, longType, floatType, doubleType, complexFloat, complexDouble, string, object};
+ }
+}
diff --git a/feature/cw/src/main/java/k3/r.java b/feature/cw/src/main/java/k3/r.java
new file mode 100644
index 00000000..fa9bbf88
--- /dev/null
+++ b/feature/cw/src/main/java/k3/r.java
@@ -0,0 +1,97 @@
+package k3;
+
+import java.lang.reflect.Field;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import com.rtbishop.look4sat.feature.cw.suncompat.Unsafe;
+
+/* loaded from: classes.dex */
+public abstract class r {
+
+ /* renamed from: a, reason: collision with root package name */
+ public static final Unsafe f12109a;
+
+ static {
+ Object obj = null;
+ try {
+ Class> cls = Class.forName("sun.misc.Unsafe");
+ Field declaredField = cls.getDeclaredField("theUnsafe");
+ declaredField.setAccessible(true);
+ obj = declaredField.get(cls);
+ } catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException | NoSuchFieldException | SecurityException ignored) {
+ // Android 适配: sun.misc.Unsafe 可能不可用(隐藏 API), 静默降级为 null;
+ // 大数组 native 路径(j4 > 1GB)不会在实际解码中触发
+ }
+ f12109a = (Unsafe) obj;
+ }
+
+ public static void a(long j4, long j5, long j6, d dVar, d dVar2) {
+ long j7;
+ if (j4 >= 0 && j4 < dVar.f12102g) {
+ if (j5 >= 0 && j5 < dVar2.f12102g) {
+ if (j6 >= 0) {
+ if (!dVar2.f12104i) {
+ long j8 = c.c;
+ double[][] dArr = g3.c.f11585a;
+ if (j6 <= j8) {
+ j8 = j6;
+ }
+ int i4 = (int) j8;
+ if (i4 >= 2 && j6 >= c.f12095d) {
+ long j9 = j6 / i4;
+ Future[] futureArr = new Future[i4];
+ int i5 = 0;
+ while (i5 < i4) {
+ long j10 = i5 * j9;
+ if (i5 == i4 - 1) {
+ j7 = j6;
+ } else {
+ j7 = j10 + j9;
+ }
+ Future[] futureArr2 = futureArr;
+ int i6 = i5;
+ futureArr2[i6] = c.a(new j3.b(j10, j7, j5, j4, dVar2, dVar));
+ i5 = i6 + 1;
+ futureArr = futureArr2;
+ }
+ try {
+ c.b(futureArr);
+ return;
+ } catch (InterruptedException unused) {
+ long j11 = j4;
+ long j12 = j5;
+ while (j11 < j4 + j6) {
+ dVar2.c(j12, dVar.b(j11));
+ j11++;
+ j12++;
+ }
+ return;
+ } catch (ExecutionException unused2) {
+ long j13 = j4;
+ long j14 = j5;
+ while (j13 < j4 + j6) {
+ dVar2.c(j14, dVar.b(j13));
+ j13++;
+ j14++;
+ }
+ return;
+ }
+ }
+ long j15 = j4;
+ long j16 = j5;
+ while (j15 < j4 + j6) {
+ dVar2.c(j16, dVar.b(j15));
+ j15++;
+ j16++;
+ }
+ return;
+ }
+ throw new IllegalArgumentException("Constant arrays cannot be modified.");
+ }
+ throw new IllegalArgumentException("length < 0");
+ }
+ throw new ArrayIndexOutOfBoundsException("destPos < 0 || destPos >= dest.length()");
+ }
+ throw new ArrayIndexOutOfBoundsException("srcPos < 0 || srcPos >= src.length()");
+ }
+}
diff --git a/feature/cw/src/main/java/k3/s.java b/feature/cw/src/main/java/k3/s.java
new file mode 100644
index 00000000..e0176656
--- /dev/null
+++ b/feature/cw/src/main/java/k3/s.java
@@ -0,0 +1,167 @@
+package k3;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import com.rtbishop.look4sat.feature.cw.suncompat.Cleaner;
+import com.rtbishop.look4sat.feature.cw.suncompat.Unsafe;
+
+/* loaded from: classes.dex */
+public final class s extends g {
+
+ /* renamed from: k, reason: collision with root package name */
+ public long[] f12110k;
+
+ public s() {
+ }
+
+ public s(long j4, boolean z3) {
+ this.f = q.f;
+ this.f12103h = 8L;
+ if (j4 > 0) {
+ this.f12102g = j4;
+ if (j4 > 1073741824) {
+ this.f12105j = r.f12109a.allocateMemory(8 * j4);
+ if (z3) {
+ a(j4);
+ }
+ Cleaner.create(this, new f(this.f12105j, this.f12102g, this.f12103h));
+ K1.a.c += this.f12102g * this.f12103h;
+ return;
+ }
+ this.f12110k = new long[(int) j4];
+ return;
+ }
+ throw new IllegalArgumentException(j4 + " is not a positive long value");
+ }
+
+ public final long b(long j4) {
+ long[] jArr = this.f12110k;
+ long j5 = this.f12105j;
+ if (j5 != 0) {
+ return r.f12109a.getLong((this.f12103h * j4) + j5);
+ }
+ if (this.f12104i) {
+ return jArr[0];
+ }
+ return jArr[(int) j4];
+ }
+
+ public final void c(long j4, long j5) {
+ long j6 = this.f12105j;
+ if (j6 != 0) {
+ r.f12109a.putLong((this.f12103h * j4) + j6, j5);
+ } else {
+ if (!this.f12104i) {
+ this.f12110k[(int) j4] = j5;
+ return;
+ }
+ throw new IllegalAccessError("Constant arrays cannot be modified.");
+ }
+ }
+
+ /* JADX WARN: Type inference failed for: r0v29, types: [k3.g, java.lang.Object, k3.s] */
+ public final Object clone() {
+ long j4;
+ int i4 = 0;
+ long j5 = 0;
+ if (this.f12104i) {
+ long j6 = this.f12102g;
+ long b4 = b(0L);
+ s gVar = new s();
+ gVar.f = q.f12107h;
+ gVar.f12103h = 8L;
+ if (j6 > 0) {
+ gVar.f12102g = j6;
+ gVar.f12104i = true;
+ gVar.f12110k = new long[]{b4};
+ return gVar;
+ }
+ throw new IllegalArgumentException(j6 + " is not a positive long value");
+ }
+ s sVar = new s(this.f12102g, false);
+ long j7 = this.f12102g;
+ Unsafe unsafe = r.f12109a;
+ if (0 < j7) {
+ if (0 < sVar.f12102g) {
+ if (j7 >= 0) {
+ if (!sVar.f12104i) {
+ long j8 = c.c;
+ double[][] dArr = g3.c.f11585a;
+ if (j7 <= j8) {
+ j8 = j7;
+ }
+ int i5 = (int) j8;
+ if (i5 >= 2 && j7 >= c.f12095d) {
+ long j9 = j7 / i5;
+ Future[] futureArr = new Future[i5];
+ while (i4 < i5) {
+ long j10 = i4 * j9;
+ if (i4 == i5 - 1) {
+ j4 = j7;
+ } else {
+ j4 = j10 + j9;
+ }
+ Future[] futureArr2 = futureArr;
+ int i6 = i4;
+ futureArr2[i6] = c.a(new i3.c(j10, j4, sVar, this));
+ i4 = i6 + 1;
+ futureArr = futureArr2;
+ }
+ try {
+ c.b(futureArr);
+ return sVar;
+ } catch (InterruptedException unused) {
+ long j11 = 0;
+ while (j5 < j7) {
+ sVar.c(j11, b(j5));
+ j5++;
+ j11++;
+ }
+ } catch (ExecutionException unused2) {
+ long j12 = 0;
+ while (j5 < j7) {
+ sVar.c(j12, b(j5));
+ j5++;
+ j12++;
+ }
+ }
+ } else {
+ long j13 = 0;
+ while (j5 < j7) {
+ sVar.c(j13, b(j5));
+ j5++;
+ j13++;
+ }
+ }
+ return sVar;
+ }
+ throw new IllegalArgumentException("Constant arrays cannot be modified.");
+ }
+ throw new IllegalArgumentException("length < 0");
+ }
+ throw new ArrayIndexOutOfBoundsException("destPos < 0 || destPos >= dest.length()");
+ }
+ throw new ArrayIndexOutOfBoundsException("srcPos < 0 || srcPos >= src.length()");
+ }
+
+ @Override // k3.g
+ public final boolean equals(Object obj) {
+ if (!super.equals(obj) || this.f12110k != ((s) obj).f12110k) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override // k3.g
+ public final int hashCode() {
+ int i4;
+ int hashCode = super.hashCode() * 29;
+ long[] jArr = this.f12110k;
+ if (jArr != null) {
+ i4 = jArr.hashCode();
+ } else {
+ i4 = 0;
+ }
+ return hashCode + i4;
+ }
+}
diff --git a/feature/cw/src/main/java/pas/cwstru.java b/feature/cw/src/main/java/pas/cwstru.java
new file mode 100644
index 00000000..8d872af2
--- /dev/null
+++ b/feature/cw/src/main/java/pas/cwstru.java
@@ -0,0 +1,144 @@
+package pas;
+
+import pas.system;
+
+/* loaded from: classes.dex */
+public class cwstru {
+
+ /* loaded from: classes.dex */
+ public static class TMorseCharInfo extends system.Record {
+ public TMorseCharInfo(long j4, boolean z3) {
+ __Init(j4, z3);
+ }
+
+ private native void __Destroy(long j4);
+
+ @Override // pas.system.PascalObjectEx
+ public void __Release() {
+ __Destroy(this._pasobj);
+ this._pasobj = 0L;
+ }
+
+ @Override // pas.system.Record
+ public int __Size() {
+ return __Size(0);
+ }
+
+ public native char getCh();
+
+ public native int getIdxE();
+
+ public native boolean getLowSnr();
+
+ public native TWordEndType getWordEnd();
+
+ public native float getWordSpaceProb();
+
+ public native TMorseWordType getWordType();
+
+ public native void setCh(char c);
+
+ public native void setIdxE(int i4);
+
+ public native void setLowSnr(boolean z3);
+
+ public native void setWordEnd(TWordEndType tWordEndType);
+
+ public native void setWordSpaceProb(float f);
+
+ public native void setWordType(TMorseWordType tMorseWordType);
+
+ public TMorseCharInfo() {
+ __Init(0L, true);
+ }
+
+ public TMorseCharInfo(system.PascalObject pascalObject) {
+ super(pascalObject);
+ }
+
+ public TMorseCharInfo(long j4) {
+ super(j4);
+ }
+ }
+
+ /* loaded from: classes.dex */
+ public static class TMorseWordType extends system.Enum {
+ public static final int wtCall = 5;
+ public static final int wtCq = 3;
+ public static final int wtGenWord = 0;
+ public static final int wtKeyword = 1;
+ public static final int wtQrl = 4;
+ public static final int wtRst = 2;
+
+ public TMorseWordType(int i4) {
+ this.Value = i4;
+ }
+
+ public static TMorseWordType wtCall() {
+ return new TMorseWordType(5);
+ }
+
+ public static TMorseWordType wtCq() {
+ return new TMorseWordType(3);
+ }
+
+ public static TMorseWordType wtGenWord() {
+ return new TMorseWordType(0);
+ }
+
+ public static TMorseWordType wtKeyword() {
+ return new TMorseWordType(1);
+ }
+
+ public static TMorseWordType wtQrl() {
+ return new TMorseWordType(4);
+ }
+
+ public static TMorseWordType wtRst() {
+ return new TMorseWordType(2);
+ }
+
+ @Override // pas.system.Enum
+ public boolean equals(Object obj) {
+ if (((obj instanceof TMorseWordType) && this.Value == ((TMorseWordType) obj).Value) || super.equals(obj)) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /* loaded from: classes.dex */
+ public static class TWordEndType extends system.Enum {
+ public static final int weLong = 2;
+ public static final int weNone = 0;
+ public static final int weShort = 1;
+
+ public TWordEndType(int i4) {
+ this.Value = i4;
+ }
+
+ public static TWordEndType weLong() {
+ return new TWordEndType(2);
+ }
+
+ public static TWordEndType weNone() {
+ return new TWordEndType(0);
+ }
+
+ public static TWordEndType weShort() {
+ return new TWordEndType(1);
+ }
+
+ @Override // pas.system.Enum
+ public boolean equals(Object obj) {
+ if (((obj instanceof TWordEndType) && this.Value == ((TWordEndType) obj).Value) || super.equals(obj)) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ static {
+ system.InitJni();
+ }
+}
diff --git a/feature/cw/src/main/java/pas/decoder.java b/feature/cw/src/main/java/pas/decoder.java
new file mode 100644
index 00000000..ca3f7540
--- /dev/null
+++ b/feature/cw/src/main/java/pas/decoder.java
@@ -0,0 +1,171 @@
+package pas;
+
+import pas.cwstru;
+import pas.system;
+
+/* loaded from: classes.dex */
+public class decoder {
+
+ /* loaded from: classes.dex */
+ public static class TCharInfo extends system.TObject {
+ public TCharInfo(system.PascalObject pascalObject) {
+ super(pascalObject);
+ }
+
+ public static TCharInfo Class() {
+ return new TCharInfo(system.GetClassRef(1));
+ }
+
+ public static native TCharInfo Create();
+
+ public static native TCharInfo Create(char c);
+
+ public static native TCharInfo Create(cwstru.TMorseCharInfo tMorseCharInfo);
+
+ public static system.TClass TClass() {
+ return system.GetTClass(1);
+ }
+
+ public native char getChar();
+
+ public native boolean getLowSnr();
+
+ public native TMorseWordType getWordType();
+
+ public TCharInfo(long j4) {
+ super(j4);
+ }
+ }
+
+ /* loaded from: classes.dex */
+ public static class TDecoder extends system.TObject {
+ public TDecoder(system.PascalObject pascalObject) {
+ super(pascalObject);
+ }
+
+ public static TDecoder Class() {
+ return new TDecoder(system.GetClassRef(2));
+ }
+
+ public static native TDecoder Create();
+
+ public static system.TClass TClass() {
+ return system.GetTClass(2);
+ }
+
+ public native TCharInfo GetChar(int i4);
+
+ public native void LockToPitch(int i4);
+
+ public native int getCharCount();
+
+ public native int getDeleteCount();
+
+ public native boolean getHamMode();
+
+ public native int getPitch();
+
+ public native int getSignalCount();
+
+ public native int getSnr();
+
+ public native int getWpm();
+
+ public native void setHamMode(boolean z3);
+
+ public TDecoder(long j4) {
+ super(j4);
+ }
+ }
+
+ /* loaded from: classes.dex */
+ public static class TDecoderState extends system.Enum {
+ public static final int dsDecoding = 2;
+ public static final int dsLockedDecoding = 4;
+ public static final int dsLockedPause = 3;
+ public static final int dsNone = 0;
+ public static final int dsPause = 1;
+
+ public TDecoderState(int i4) {
+ this.Value = i4;
+ }
+
+ public static TDecoderState dsDecoding() {
+ return new TDecoderState(2);
+ }
+
+ public static TDecoderState dsLockedDecoding() {
+ return new TDecoderState(4);
+ }
+
+ public static TDecoderState dsLockedPause() {
+ return new TDecoderState(3);
+ }
+
+ public static TDecoderState dsNone() {
+ return new TDecoderState(0);
+ }
+
+ public static TDecoderState dsPause() {
+ return new TDecoderState(1);
+ }
+
+ @Override // pas.system.Enum
+ public boolean equals(Object obj) {
+ if (((obj instanceof TDecoderState) && this.Value == ((TDecoderState) obj).Value) || super.equals(obj)) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /* loaded from: classes.dex */
+ public static class TMorseWordType extends system.Enum {
+ public static final int wtCall = 5;
+ public static final int wtCq = 3;
+ public static final int wtGenWord = 0;
+ public static final int wtKeyword = 1;
+ public static final int wtQrl = 4;
+ public static final int wtRst = 2;
+
+ public TMorseWordType(int i4) {
+ this.Value = i4;
+ }
+
+ public static TMorseWordType wtCall() {
+ return new TMorseWordType(5);
+ }
+
+ public static TMorseWordType wtCq() {
+ return new TMorseWordType(3);
+ }
+
+ public static TMorseWordType wtGenWord() {
+ return new TMorseWordType(0);
+ }
+
+ public static TMorseWordType wtKeyword() {
+ return new TMorseWordType(1);
+ }
+
+ public static TMorseWordType wtQrl() {
+ return new TMorseWordType(4);
+ }
+
+ public static TMorseWordType wtRst() {
+ return new TMorseWordType(2);
+ }
+
+ @Override // pas.system.Enum
+ public boolean equals(Object obj) {
+ if (((obj instanceof TMorseWordType) && this.Value == ((TMorseWordType) obj).Value) || super.equals(obj)) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ static {
+ system.InitJni();
+ }
+}
diff --git a/feature/cw/src/main/java/pas/nativedecoder.java b/feature/cw/src/main/java/pas/nativedecoder.java
new file mode 100644
index 00000000..5e9b4290
--- /dev/null
+++ b/feature/cw/src/main/java/pas/nativedecoder.java
@@ -0,0 +1,35 @@
+package pas;
+
+import pas.decoder;
+import pas.system;
+
+/* loaded from: classes.dex */
+public class nativedecoder {
+
+ /* loaded from: classes.dex */
+ public static class TNativeDecoder extends decoder.TDecoder {
+ public TNativeDecoder(system.PascalObject pascalObject) {
+ super(pascalObject);
+ }
+
+ public static TNativeDecoder Class() {
+ return new TNativeDecoder(system.GetClassRef(3));
+ }
+
+ public static native TNativeDecoder Create();
+
+ public static system.TClass TClass() {
+ return system.GetTClass(3);
+ }
+
+ public native decoder.TDecoderState ProcessSpectrum(Object obj);
+
+ public TNativeDecoder(long j4) {
+ super(j4);
+ }
+ }
+
+ static {
+ system.InitJni();
+ }
+}
diff --git a/feature/cw/src/main/java/pas/system.java b/feature/cw/src/main/java/pas/system.java
new file mode 100644
index 00000000..9516d74a
--- /dev/null
+++ b/feature/cw/src/main/java/pas/system.java
@@ -0,0 +1,385 @@
+package pas;
+
+import java.util.Date;
+import java.util.TimeZone;
+
+/* loaded from: classes.dex */
+public class system {
+ private static boolean _JniLibLoaded = false;
+
+ /* loaded from: classes.dex */
+ public static abstract class BaseSet {
+ protected int Value = 0;
+
+ public abstract int Base();
+
+ public abstract int ElMax();
+
+ public abstract byte Size();
+ }
+
+ /* loaded from: classes.dex */
+ public static class Enum {
+ public int Value;
+
+ public int Ord() {
+ return this.Value;
+ }
+
+ public boolean equals(Object obj) {
+ return (obj instanceof Integer) && this.Value == ((Integer) obj).intValue();
+ }
+
+ public int hashCode() {
+ return this.Value;
+ }
+
+ public boolean equals(int i4) {
+ return this.Value == i4;
+ }
+ }
+
+ /* loaded from: classes.dex */
+ public static class MethodPtr extends PascalObjectEx {
+ protected String mName;
+ protected Object mObject;
+ protected String mSignature;
+
+ public MethodPtr() {
+ this._cleanup = true;
+ this._pasobj = -1L;
+ }
+
+ private native void __Destroy();
+
+ private native void __Init(Object obj, String str, String str2, boolean z3);
+
+ public void Init() {
+ boolean z3;
+ Object obj = this.mObject;
+ String str = this.mName;
+ String str2 = this.mSignature;
+ if (this != obj) {
+ z3 = true;
+ } else {
+ z3 = false;
+ }
+ __Init(obj, str, str2, z3);
+ }
+
+ @Override // pas.system.PascalObjectEx
+ public void __Release() {
+ if (this._pasobj > 0) {
+ __Destroy();
+ }
+ }
+ }
+
+ /* loaded from: classes.dex */
+ public static abstract class PascalInterface extends PascalObjectEx {
+ public PascalInterface(long j4, boolean z3) {
+ this._pasobj = j4;
+ __Init();
+ }
+
+ public abstract void __Init();
+
+ public void __TypeCast(PascalObject pascalObject, String str) {
+ if (pascalObject != null) {
+ if (pascalObject instanceof PascalInterface) {
+ this._pasobj = pascalObject._pasobj;
+ __Init();
+ } else {
+ this._pasobj = system.InterfaceCast(pascalObject._pasobj, str);
+ }
+ }
+ }
+ }
+
+ /* loaded from: classes.dex */
+ public static class Record extends PascalObjectEx {
+ protected PascalObject _objref;
+
+ public Record(PascalObject pascalObject) {
+ super(pascalObject);
+ this._objref = pascalObject;
+ }
+
+ public void __Init(long j4, boolean z3) {
+ this._pasobj = j4;
+ this._cleanup = z3;
+ if (j4 == 0 && __Size() != 0) {
+ this._pasobj = system.AllocMemory(__Size());
+ }
+ }
+
+ public int __Size() {
+ return 0;
+ }
+
+ @Override // pas.system.PascalObjectEx, pas.system.PascalObject
+ public void finalize() {
+ long j4 = this._pasobj;
+ if (j4 < 0) {
+ this._pasobj = -j4;
+ this._cleanup = true;
+ }
+ super.finalize();
+ }
+
+ public Record(long j4) {
+ super(j4);
+ }
+
+ public final int __Size(int i4) {
+ return system.GetRecordSize(i4);
+ }
+
+ public Record() {
+ }
+ }
+
+ /* loaded from: classes.dex */
+ public static abstract class Set extends BaseSet {
+ public Set() {
+ }
+
+ public void Assign(TS ts) {
+ this.Value = ts.Value;
+ }
+
+ public void Exclude(TE... teArr) {
+ for (TE te : teArr) {
+ this.Value = (~GetMask(te)) & this.Value;
+ }
+ }
+
+ public int GetMask(TE te) {
+ return 1 << (te.Ord() - Base());
+ }
+
+ public boolean Has(TE te) {
+ if ((GetMask(te) & this.Value) != 0) {
+ return true;
+ }
+ return false;
+ }
+
+ public void Include(TE... teArr) {
+ for (TE te : teArr) {
+ this.Value = GetMask(te) | this.Value;
+ }
+ }
+
+ public void Intersect(TS ts) {
+ this.Value = ts.Value & this.Value;
+ }
+
+ public boolean IsEmpty() {
+ if (this.Value == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean equals(TS ts) {
+ return this.Value == ts.Value;
+ }
+
+ public Set(TE... teArr) {
+ Include(teArr);
+ }
+
+ public void Exclude(TS ts) {
+ this.Value = (~ts.Value) & this.Value;
+ }
+
+ public void Include(TS ts) {
+ this.Value = ts.Value | this.Value;
+ }
+
+ public boolean equals(TE te) {
+ return this.Value == te.Ord();
+ }
+
+ public Set(TS... tsArr) {
+ for (TS ts : tsArr) {
+ Include(ts); // smali: Set(TS...) 循环调 Include(BaseSet)
+ }
+ }
+
+ public boolean equals(int i4) {
+ return this.Value == i4;
+ }
+ }
+
+ /* loaded from: classes.dex */
+ public static class TClass extends TObject {
+ public TClass(PascalObject pascalObject) {
+ super(pascalObject);
+ }
+ }
+
+ /* loaded from: classes.dex */
+ public static class TDateTime {
+ public static double get(Date date) {
+ return ((date.getTime() + TimeZone.getDefault().getOffset(date.getTime())) / 8.64E7d) + 25569.0d;
+ }
+
+ public static double getUTC(Date date) {
+ return (date.getTime() / 8.64E7d) + 25569.0d;
+ }
+
+ public static Date toDate(double d4) {
+ return new Date(Math.round((d4 - 25569.0d) * 8.64E7d) - TimeZone.getDefault().getOffset(Math.round((d4 - 25569.0d) * 8.64E7d))); // r3 = 前值(smali)
+ }
+
+ public static Date toDateUTC(double d4) {
+ return new Date(Math.round((d4 - 25569.0d) * 8.64E7d));
+ }
+ }
+
+ /* loaded from: classes.dex */
+ public static class TObject extends PascalObject {
+ public TObject(PascalObject pascalObject) {
+ super(pascalObject);
+ }
+
+ public static TObject Class() {
+ return new TObject(system.GetClassRef(0));
+ }
+
+ public static native TObject Create();
+
+ public static TClass TClass() {
+ return system.GetTClass(0);
+ }
+
+ public native String ClassName();
+
+ public native boolean ClassNameIs(String str);
+
+ public native TClass ClassParent();
+
+ public native TClass ClassType();
+
+ public native void Destroy();
+
+ public native void Free();
+
+ public native boolean InheritsFrom(TClass tClass);
+
+ public native int InstanceSize();
+
+ public TObject(long j4) {
+ super(j4);
+ }
+ }
+
+ static {
+ InitJni();
+ }
+
+ public static native long AllocMemory(int i4);
+
+ public static native long GetClassRef(int i4);
+
+ public static native byte[] GetMemoryAsArray(long j4, int i4);
+
+ /* JADX INFO: Access modifiers changed from: private */
+ public static native int GetRecordSize(int i4);
+
+ public static TClass GetTClass(int i4) {
+ TClass tClass = new TClass(null);
+ tClass._pasobj = GetClassRef(i4);
+ return tClass;
+ }
+
+ public static void InitJni() {
+ if (!_JniLibLoaded) {
+ _JniLibLoaded = true;
+ System.loadLibrary("nativedecoderjni");
+ }
+ }
+
+ /* JADX INFO: Access modifiers changed from: private */
+ public static native long InterfaceCast(long j4, String str);
+
+ public static long Pointer(PascalObject pascalObject) {
+ if (pascalObject == null) {
+ return 0L;
+ }
+ return pascalObject._pasobj;
+ }
+
+ public static native void SetMemoryFromArray(long j4, byte[] bArr);
+
+ /* loaded from: classes.dex */
+ public static class PascalObject {
+ protected long _pasobj;
+
+ static {
+ system.InitJni();
+ }
+
+ public PascalObject() {
+ this._pasobj = 0L;
+ }
+
+ public boolean equals(Object obj) {
+ if ((obj instanceof PascalObject) && this._pasobj == ((PascalObject) obj)._pasobj) {
+ return true;
+ }
+ return false;
+ }
+
+ public void finalize() {
+ }
+
+ public int hashCode() {
+ return (int) this._pasobj;
+ }
+
+ public PascalObject(PascalObject pascalObject) {
+ this._pasobj = 0L;
+ if (pascalObject != null) {
+ this._pasobj = pascalObject._pasobj;
+ }
+ }
+
+ public PascalObject(long j4) {
+ this._pasobj = j4;
+ }
+ }
+
+ /* loaded from: classes.dex */
+ public static class PascalObjectEx extends PascalObject {
+ protected boolean _cleanup;
+
+ public PascalObjectEx() {
+ this._cleanup = false;
+ }
+
+ public void __Release() {
+ this._pasobj = 0L;
+ }
+
+ @Override // pas.system.PascalObject
+ public void finalize() {
+ if (this._cleanup) {
+ __Release();
+ }
+ super.finalize();
+ }
+
+ public PascalObjectEx(PascalObject pascalObject) {
+ super(pascalObject);
+ this._cleanup = false;
+ }
+
+ public PascalObjectEx(long j4) {
+ super(j4);
+ this._cleanup = false;
+ }
+ }
+}
diff --git a/feature/cw/src/main/java/s/AbstractC1880e.java b/feature/cw/src/main/java/s/AbstractC1880e.java
new file mode 100644
index 00000000..53072157
--- /dev/null
+++ b/feature/cw/src/main/java/s/AbstractC1880e.java
@@ -0,0 +1,16 @@
+package s;
+
+/* renamed from: s.e, reason: case insensitive filesystem */
+/* loaded from: classes.dex */
+public abstract /* synthetic */ class AbstractC1880e {
+
+ /* renamed from: a, reason: collision with root package name */
+ public static final /* synthetic */ int[] f13163a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28};
+
+ public static /* synthetic */ int a(int i4) {
+ if (i4 != 0) {
+ return i4 - 1;
+ }
+ throw null;
+ }
+}
diff --git a/feature/cw/src/main/jniLibs/armeabi-v7a/libnativedecoderjni.so b/feature/cw/src/main/jniLibs/armeabi-v7a/libnativedecoderjni.so
new file mode 100644
index 00000000..d91e4130
Binary files /dev/null and b/feature/cw/src/main/jniLibs/armeabi-v7a/libnativedecoderjni.so differ
diff --git a/feature/cw/src/main/res/drawable/ic_baseline_delete_24.xml b/feature/cw/src/main/res/drawable/ic_baseline_delete_24.xml
new file mode 100644
index 00000000..f5023823
--- /dev/null
+++ b/feature/cw/src/main/res/drawable/ic_baseline_delete_24.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/feature/cw/src/main/res/drawable/ic_baseline_pause_24.xml b/feature/cw/src/main/res/drawable/ic_baseline_pause_24.xml
new file mode 100644
index 00000000..b9174383
--- /dev/null
+++ b/feature/cw/src/main/res/drawable/ic_baseline_pause_24.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/feature/cw/src/main/res/drawable/ic_baseline_save_24.xml b/feature/cw/src/main/res/drawable/ic_baseline_save_24.xml
new file mode 100644
index 00000000..fe7ba8b0
--- /dev/null
+++ b/feature/cw/src/main/res/drawable/ic_baseline_save_24.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/feature/cw/src/main/res/drawable/ic_baseline_share_24.xml b/feature/cw/src/main/res/drawable/ic_baseline_share_24.xml
new file mode 100644
index 00000000..a2437117
--- /dev/null
+++ b/feature/cw/src/main/res/drawable/ic_baseline_share_24.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/feature/cw/src/main/res/layout/activity_main.xml b/feature/cw/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..ef7099b0
--- /dev/null
+++ b/feature/cw/src/main/res/layout/activity_main.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/feature/cw/src/main/res/layout/cw_panel_main.xml b/feature/cw/src/main/res/layout/cw_panel_main.xml
new file mode 100644
index 00000000..bc647b7d
--- /dev/null
+++ b/feature/cw/src/main/res/layout/cw_panel_main.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/feature/cw/src/main/res/menu/options_menu.xml b/feature/cw/src/main/res/menu/options_menu.xml
new file mode 100644
index 00000000..6c762008
--- /dev/null
+++ b/feature/cw/src/main/res/menu/options_menu.xml
@@ -0,0 +1,33 @@
+
+
diff --git a/feature/cw/src/main/res/values-id/app_values.xml b/feature/cw/src/main/res/values-id/app_values.xml
new file mode 100644
index 00000000..19601995
--- /dev/null
+++ b/feature/cw/src/main/res/values-id/app_values.xml
@@ -0,0 +1,22 @@
+
+
+ #ff6200ee
+ 18
+ Diam
+ Tampilan waterfall
+ Skala frekuensi
+ Teks terdekode
+ Bersihkan
+ Jeda Dekode
+ Simpan Teks
+ Rekam Sinyal
+ Pengaturan
+ Bantuan Daring
+ Nilai Aplikasi Ini
+ Dapatkan Versi Premium
+ Ketuk Kembali lagi untuk menutup aplikasi
+ Tipe Pesan
+ Izin mikrofon diperlukan untuk dekode CW
+ Beri izin
+ Buka pengaturan aplikasi
+
diff --git a/feature/cw/src/main/res/values-in-rID/app_values.xml b/feature/cw/src/main/res/values-in-rID/app_values.xml
new file mode 100644
index 00000000..19601995
--- /dev/null
+++ b/feature/cw/src/main/res/values-in-rID/app_values.xml
@@ -0,0 +1,22 @@
+
+
+ #ff6200ee
+ 18
+ Diam
+ Tampilan waterfall
+ Skala frekuensi
+ Teks terdekode
+ Bersihkan
+ Jeda Dekode
+ Simpan Teks
+ Rekam Sinyal
+ Pengaturan
+ Bantuan Daring
+ Nilai Aplikasi Ini
+ Dapatkan Versi Premium
+ Ketuk Kembali lagi untuk menutup aplikasi
+ Tipe Pesan
+ Izin mikrofon diperlukan untuk dekode CW
+ Beri izin
+ Buka pengaturan aplikasi
+
diff --git a/feature/cw/src/main/res/values-in/app_values.xml b/feature/cw/src/main/res/values-in/app_values.xml
new file mode 100644
index 00000000..19601995
--- /dev/null
+++ b/feature/cw/src/main/res/values-in/app_values.xml
@@ -0,0 +1,22 @@
+
+
+ #ff6200ee
+ 18
+ Diam
+ Tampilan waterfall
+ Skala frekuensi
+ Teks terdekode
+ Bersihkan
+ Jeda Dekode
+ Simpan Teks
+ Rekam Sinyal
+ Pengaturan
+ Bantuan Daring
+ Nilai Aplikasi Ini
+ Dapatkan Versi Premium
+ Ketuk Kembali lagi untuk menutup aplikasi
+ Tipe Pesan
+ Izin mikrofon diperlukan untuk dekode CW
+ Beri izin
+ Buka pengaturan aplikasi
+
diff --git a/feature/cw/src/main/res/values-tr/app_values.xml b/feature/cw/src/main/res/values-tr/app_values.xml
new file mode 100644
index 00000000..a5d91c08
--- /dev/null
+++ b/feature/cw/src/main/res/values-tr/app_values.xml
@@ -0,0 +1,22 @@
+
+
+ #ff6200ee
+ 18
+ Beklemede
+ Şelale görüntüsü
+ Frekans ölçeği
+ Çözülen metin
+ Temizle
+ Çözmeyi Duraklat
+ Metni Kaydet
+ Sinyalleri Kaydet
+ Ayarlar
+ Çevrimiçi Yardım
+ Bu Uygulamayı Değerlendir
+ Premium Sürümü Al
+ Kapatmak için Geriye tekrar dokunun
+ Mesaj Türü
+ CW çözme için mikrofon izni gereklidir
+ İzin ver
+ Uygulama ayarlarını aç
+
diff --git a/feature/cw/src/main/res/values-zh/app_values.xml b/feature/cw/src/main/res/values-zh/app_values.xml
new file mode 100644
index 00000000..acf5972c
--- /dev/null
+++ b/feature/cw/src/main/res/values-zh/app_values.xml
@@ -0,0 +1,22 @@
+
+
+ #ff6200ee
+ 18
+ 空闲
+ 瀑布图
+ 频率刻度
+ 解码文本
+ 清除
+ 暂停解码
+ 保存文本
+ 录音信号
+ 设置
+ 在线帮助
+ 评价此应用
+ 获取高级版
+ 再次按返回键退出应用
+ 消息类型
+ CW 解码需要麦克风权限
+ 授予权限
+ 打开应用设置
+
diff --git a/feature/cw/src/main/res/values/app_values.xml b/feature/cw/src/main/res/values/app_values.xml
new file mode 100644
index 00000000..83e4e89b
--- /dev/null
+++ b/feature/cw/src/main/res/values/app_values.xml
@@ -0,0 +1,22 @@
+
+
+ #ff6200ee
+ 18
+ Idle
+ Waterfall display
+ Frequency scale
+ Decoded text
+ Clear
+ Pause Decoding
+ Save Text
+ Record Signals
+ Settings
+ Online Help
+ Rate this App
+ Get Premium Version
+ Tap Back again to close the app
+ Message Type
+ Microphone permission is required for CW decoding
+ Grant permission
+ Open app settings
+
diff --git a/feature/radar/build.gradle.kts b/feature/radar/build.gradle.kts
index 723edbae..9125bb22 100644
--- a/feature/radar/build.gradle.kts
+++ b/feature/radar/build.gradle.kts
@@ -8,4 +8,8 @@ android {
dependencies {
implementation(project(":feature:mutual"))
+ // CW 解码面板: 复用 feature:cw 的 Morse Expert 引擎(布局 cw_panel_main + MainActivity 控制器)
+ implementation(project(":feature:cw"))
+ // 与 feature:cw 一致(控制器按 ID 递归查找 ConstraintLayout 视图)
+ implementation("androidx.constraintlayout:constraintlayout:2.2.1")
}
\ No newline at end of file
diff --git a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/LogTab.kt b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/LogTab.kt
new file mode 100644
index 00000000..89896d9e
--- /dev/null
+++ b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/LogTab.kt
@@ -0,0 +1,479 @@
+/*
+ * LogTab.kt — 雷达页「Log」标签(4.5.2 WaveLog 日志)。
+ *
+ * 布局: 转发器列表(点开选一个, 边看频率边填) → 呼号输入回车存本地 →
+ * 下方本地记录列表(时间/频率/呼号)。记录支持自绘左滑删除:
+ * 滑动中显示黄色垃圾桶, 滑过 75% 变撤销键, 5 秒内不点撤销则删除。
+ *
+ * 回车只存本地(WavelogQueue), 上传由 10 分钟周期/手动触发(防抄收错误)。
+ */
+package com.rtbishop.look4sat.feature.radar
+
+import androidx.compose.animation.core.Spring
+import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.animation.core.spring
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.gestures.detectHorizontalDragGestures
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.ui.layout.onSizeChanged
+import androidx.compose.foundation.layout.offset
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.text.KeyboardActions
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.DropdownMenuItem
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExposedDropdownMenuBox
+import androidx.compose.material3.ExposedDropdownMenuDefaults
+import androidx.compose.material3.MenuAnchorType
+import androidx.compose.material3.Icon
+import androidx.compose.material3.HorizontalDivider
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.OutlinedTextField
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.rtbishop.look4sat.core.domain.model.SatRadio
+import com.rtbishop.look4sat.core.domain.predict.OrbitalPos
+import com.rtbishop.look4sat.core.domain.utility.DopplerFrequencyCalculator
+import com.rtbishop.look4sat.core.domain.wavelog.WavelogQso
+import com.rtbishop.look4sat.core.domain.wavelog.WavelogQueue
+import com.rtbishop.look4sat.core.presentation.R
+import com.rtbishop.look4sat.core.presentation.formatFrequency
+import kotlinx.coroutines.delay
+import java.util.Calendar
+import java.util.TimeZone
+import java.util.UUID
+import kotlin.math.roundToInt
+
+private val WaveLogYellow = Color(0xFFFFC107)
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun LogTab(
+ transceivers: List,
+ orbitalPos: OrbitalPos?,
+ satelliteName: String,
+ queue: WavelogQueue,
+ wavelogConfigured: Boolean,
+ showToast: (String) -> Unit,
+ txBaseFrequencyHz: Long? = null,
+ aosTimeMs: Long = 0L,
+ modifier: Modifier = Modifier
+) {
+ var selectedUuid by remember { mutableStateOf(null) }
+ var refreshTick by remember { mutableIntStateOf(0) }
+ val entries = remember(refreshTick) { queue.all() }
+
+ Column(
+ modifier = modifier
+ .fillMaxSize()
+ .verticalScroll(rememberScrollState())
+ .padding(8.dp),
+ verticalArrangement = Arrangement.spacedBy(6.dp)
+ ) {
+ if (!wavelogConfigured) {
+ Text(
+ text = stringResource(id = R.string.wavelog_need_config),
+ fontSize = 13.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant
+ )
+ }
+
+ // 转发器选择(下拉选择框): 选中后底下出现输入区
+ // 选中项按 uuid 从 transceivers 实时派生(多普勒频率每秒更新, 频率显示随之刷新)
+ var menuExpanded by remember { mutableStateOf(false) }
+ val selectedRadio = transceivers.firstOrNull { it.uuid == selectedUuid }
+ ExposedDropdownMenuBox(
+ expanded = menuExpanded,
+ onExpandedChange = { menuExpanded = it }
+ ) {
+ OutlinedTextField(
+ value = selectedRadio?.info ?: "",
+ onValueChange = {},
+ readOnly = true,
+ label = { Text(stringResource(id = R.string.wavelog_select_transponder)) },
+ trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = menuExpanded) },
+ textStyle = MaterialTheme.typography.bodyMedium,
+ modifier = Modifier
+ .menuAnchor(MenuAnchorType.PrimaryNotEditable)
+ .fillMaxWidth()
+ )
+ ExposedDropdownMenu(
+ expanded = menuExpanded,
+ onDismissRequest = { menuExpanded = false }
+ ) {
+ transceivers.forEach { radio ->
+ DropdownMenuItem(
+ text = {
+ Text(
+ text = radio.info,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis
+ )
+ },
+ onClick = {
+ selectedUuid = radio.uuid
+ menuExpanded = false
+ }
+ )
+ }
+ }
+ }
+
+ // 选中转发器后: 输入区(实时频率 + 呼号 + 模式)
+ selectedRadio?.let { radio ->
+ ExpandedLogInput(
+ radio = radio,
+ orbitalPos = orbitalPos,
+ satelliteName = satelliteName,
+ queue = queue,
+ showToast = showToast,
+ txBaseFrequencyHz = txBaseFrequencyHz,
+ aosTimeMs = aosTimeMs,
+ onSaved = { refreshTick++ }
+ )
+ }
+
+ // 本地记录列表(时间/频率/呼号)
+ Text(
+ text = stringResource(id = R.string.wavelog_saved),
+ fontSize = 12.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant
+ )
+ if (entries.isEmpty()) {
+ Text(
+ text = stringResource(id = R.string.wavelog_empty),
+ fontSize = 13.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.padding(vertical = 8.dp)
+ )
+ } else {
+ // 按场次分组(sessionId = 卫星名-AOS 时间戳), 组间粗线分隔
+ entries.groupBy { it.sessionId.ifBlank { "un" } }.forEach { (sessionId, groupEntries) ->
+ // 组标题 + 分隔线
+ HorizontalDivider(thickness = 2.dp, color = MaterialTheme.colorScheme.primary)
+ Text(
+ text = if (sessionId == "un") stringResource(id = R.string.wavelog_ungrouped)
+ else sessionId.substringBeforeLast('-'),
+ fontSize = 11.sp,
+ fontWeight = FontWeight.Bold,
+ color = MaterialTheme.colorScheme.primary,
+ modifier = Modifier.padding(horizontal = 10.dp, vertical = 4.dp)
+ )
+ groupEntries.forEach { entry ->
+ SwipeDeleteRow(
+ onDelete = {
+ queue.remove(entry.id)
+ refreshTick++
+ }
+ ) {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier
+ .fillMaxWidth()
+ .background(MaterialTheme.colorScheme.surfaceContainer)
+ .padding(horizontal = 10.dp, vertical = 8.dp)
+ ) {
+ Text(
+ text = formatLocalTime(entry.timeUtcMs),
+ fontSize = 12.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.width(64.dp)
+ )
+ Text(
+ text = formatFrequency(entry.freqTxHz),
+ fontSize = 12.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.width(76.dp)
+ )
+ Text(
+ text = entry.call,
+ fontSize = 14.sp,
+ fontWeight = FontWeight.Medium,
+ modifier = Modifier.weight(1f)
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/** 转发器展开输入区: 实时频率 + 呼号(回车存本地) + 模式修正 */
+@Composable
+private fun ExpandedLogInput(
+ radio: SatRadio,
+ orbitalPos: OrbitalPos?,
+ satelliteName: String,
+ queue: WavelogQueue,
+ showToast: (String) -> Unit,
+ txBaseFrequencyHz: Long? = null,
+ aosTimeMs: Long = 0L,
+ onSaved: () -> Unit
+) {
+ var callsign by remember { mutableStateOf("") }
+ var mode by remember { mutableStateOf(radio.uplinkMode ?: "FM") }
+
+ val savedMsg = stringResource(id = R.string.wavelog_saved)
+
+ fun submit() {
+ val call = callsign.trim().uppercase()
+ if (call.length < 3) return
+ // 频率直接取转发器栏的数字(radio 每秒多普勒修正, 回车那一秒的值)
+ val tx = radio.uplinkLow ?: radio.downlinkLow ?: 0L
+ val rx = radio.downlinkLow ?: radio.uplinkLow ?: 0L
+ queue.add(
+ WavelogQso(
+ id = UUID.randomUUID().toString(),
+ timeUtcMs = System.currentTimeMillis(),
+ call = call,
+ mode = mode.trim().ifBlank { "FM" }.uppercase(),
+ freqTxHz = tx,
+ freqRxHz = rx,
+ satName = satelliteName,
+ sessionId = buildSessionId(satelliteName, aosTimeMs)
+ )
+ )
+ callsign = ""
+ onSaved()
+ showToast(savedMsg)
+ }
+
+ // 频率显示与转发器栏完全一致: TX 行 + RX 行(radio 来自每秒多普勒重算, 实时刷新)
+ val txForDisplay = radio.uplinkLow ?: radio.downlinkLow ?: 0L
+ val rxForDisplay = radio.downlinkLow ?: radio.uplinkLow ?: 0L
+ val upLow = radio.uplinkLow
+ val upHigh = radio.uplinkHigh
+ val downLow = radio.downlinkLow
+ val downHigh = radio.downlinkHigh
+ val isLinearRange = upLow != null && upHigh != null && upLow != upHigh
+ Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
+ // TX 行
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ Text(
+ text = "TX: ",
+ fontSize = 12.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant
+ )
+ Text(
+ text = "${formatFrequency(txForDisplay)} MHz",
+ fontSize = 14.sp,
+ fontWeight = FontWeight.Bold,
+ color = MaterialTheme.colorScheme.primary
+ )
+ if (isLinearRange) {
+ Text(
+ text = " (${formatFrequency(upLow)} – ${formatFrequency(upHigh)})",
+ fontSize = 11.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant
+ )
+ }
+ }
+ // RX 行(与转发器栏 RX 一致)
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ Text(
+ text = "RX: ",
+ fontSize = 12.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant
+ )
+ Text(
+ text = "${formatFrequency(rxForDisplay)} MHz",
+ fontSize = 14.sp,
+ fontWeight = FontWeight.Bold,
+ color = MaterialTheme.colorScheme.primary
+ )
+ if (downLow != null && downHigh != null && downLow != downHigh) {
+ Text(
+ text = " (${formatFrequency(downLow)} – ${formatFrequency(downHigh)})",
+ fontSize = 11.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant
+ )
+ }
+ }
+ OutlinedTextField(
+ value = callsign,
+ onValueChange = { callsign = it.take(12) },
+ label = { Text(stringResource(id = R.string.wavelog_call_hint)) },
+ singleLine = true,
+ keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
+ keyboardActions = KeyboardActions(onDone = { submit() }),
+ textStyle = MaterialTheme.typography.bodyMedium,
+ modifier = Modifier.fillMaxWidth()
+ )
+ OutlinedTextField(
+ value = mode,
+ onValueChange = { mode = it.take(8) },
+ label = { Text(stringResource(id = R.string.wavelog_mode_hint)) },
+ singleLine = true,
+ textStyle = MaterialTheme.typography.bodyMedium,
+ modifier = Modifier.fillMaxWidth()
+ )
+ }
+}
+
+/**
+ * 自绘左滑删除行(用户定制交互):
+ * 左滑 → 右侧黄色垃圾桶; 滑过 75% → 变撤销键(待删除, 不立即删);
+ * 5 秒倒计时内点撤销恢复, 不点自动删除。
+ */
+@Composable
+internal fun SwipeDeleteRow(
+ onDelete: () -> Unit,
+ content: @Composable () -> Unit
+) {
+ var offsetX by remember { mutableStateOf(0f) }
+ var pending by remember { mutableStateOf(false) }
+ var countdown by remember { mutableIntStateOf(5) }
+ var rowWidth by remember { mutableIntStateOf(0) }
+ val threshold = rowWidth * 0.75f
+
+ // 平滑弹回/滑入(动画)
+ val animatedOffset by animateFloatAsState(
+ targetValue = offsetX,
+ animationSpec = if (pending) tween(200) else spring(dampingRatio = Spring.DampingRatioNoBouncy),
+ label = "swipeOffset"
+ )
+
+ // 倒计时: 进入待删除后 5 秒自动删
+ LaunchedEffect(pending) {
+ if (pending) {
+ countdown = 5
+ while (countdown > 0) {
+ delay(1000)
+ countdown--
+ }
+ if (pending) {
+ onDelete()
+ pending = false
+ offsetX = 0f
+ }
+ }
+ }
+
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .onSizeChanged { rowWidth = it.width }
+ ) {
+ // 背景层(右侧图标: 垃圾桶 / 撤销+倒计时)
+ Box(
+ modifier = Modifier
+ .matchParentSize()
+ .background(WaveLogYellow.copy(alpha = 0.25f)),
+ contentAlignment = Alignment.CenterEnd
+ ) {
+ if (pending) {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier.padding(end = 12.dp),
+ horizontalArrangement = Arrangement.spacedBy(4.dp)
+ ) {
+ Text(
+ text = "$countdown",
+ fontSize = 14.sp,
+ fontWeight = FontWeight.Bold,
+ color = WaveLogYellow
+ )
+ Text(
+ text = stringResource(id = R.string.wavelog_delete_undo),
+ fontSize = 13.sp,
+ fontWeight = FontWeight.Bold,
+ color = WaveLogYellow,
+ modifier = Modifier
+ .clip(RoundedCornerShape(8.dp))
+ .background(WaveLogYellow.copy(alpha = 0.15f))
+ .clickable {
+ pending = false
+ offsetX = 0f
+ }
+ .padding(horizontal = 10.dp, vertical = 6.dp)
+ )
+ }
+ } else {
+ // 垃圾桶(滑动过程中一直显示, 黄色)
+ Text(
+ text = "🗑",
+ fontSize = 20.sp,
+ modifier = Modifier.padding(end = 16.dp)
+ )
+ }
+ }
+ // 内容层(跟手滑动): 背景在 offset 内侧(随内容移动)!
+ // 平时盖住垃圾桶, 左滑时内容带背景移开 → 右侧露出黄色垃圾桶/撤销倒计时
+ Box(
+ modifier = Modifier
+ .offset { IntOffset(animatedOffset.roundToInt(), 0) }
+ .background(MaterialTheme.colorScheme.surfaceContainer)
+ .pointerInput(Unit) {
+ detectHorizontalDragGestures(
+ onDragStart = { if (pending) { pending = false } },
+ onHorizontalDrag = { change, dragAmount ->
+ change.consume()
+ offsetX = (offsetX + dragAmount).coerceIn(-rowWidth.toFloat(), 0f)
+ },
+ onDragEnd = {
+ if (offsetX <= -threshold) {
+ pending = true
+ countdown = 5
+ } else {
+ offsetX = 0f
+ }
+ },
+ onDragCancel = { offsetX = 0f }
+ )
+ }
+ ) {
+ content()
+ }
+ }
+}
+
+private fun formatLocalTime(utcMs: Long): String {
+ val cal = Calendar.getInstance(TimeZone.getDefault())
+ cal.timeInMillis = utcMs
+ return "%02d:%02d".format(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE))
+}
+
+/** 场次 ID: 卫星名-AOS 时间戳(UTC yyyyMMdd-HHmm); 无 AOS 时用回车时刻 */
+private fun buildSessionId(satName: String, aosTimeMs: Long): String {
+ val cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
+ cal.timeInMillis = if (aosTimeMs > 0) aosTimeMs else System.currentTimeMillis()
+ val stamp = "%04d%02d%02d-%02d%02d".format(
+ cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH),
+ cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)
+ )
+ return "$satName-$stamp"
+}
diff --git a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarScreen.kt b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarScreen.kt
index 617412b0..ae30c2c9 100644
--- a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarScreen.kt
+++ b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarScreen.kt
@@ -61,6 +61,9 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.rtbishop.look4sat.core.domain.predict.OrbitalPos
import com.rtbishop.look4sat.core.domain.repository.IContainerProvider
import com.rtbishop.look4sat.core.domain.repository.MutualPassData
+import com.rtbishop.look4sat.core.domain.wavelog.UploadOutcome
+import com.rtbishop.look4sat.core.domain.wavelog.WavelogQueue
+import com.rtbishop.look4sat.core.domain.utility.DopplerFrequencyCalculator
import com.rtbishop.look4sat.core.domain.utility.toDegrees
import com.rtbishop.look4sat.core.presentation.EmptyListCard
import com.rtbishop.look4sat.core.presentation.IconCard
@@ -78,6 +81,8 @@ import kotlin.math.PI
private enum class RadarPage(val title: String) {
Transceivers("Transceivers"),
+ Log("Log"),
+ Calculator("Calculator"),
Sstv("SSTV")
}
@@ -119,9 +124,33 @@ fun RadarDestination(navigateUp: () -> Unit) {
viewModel.onAction(RadarAction.SstvPermissionResult(granted))
viewModel.onAction(RadarAction.CwPermissionResult(granted))
}
- RadarScreen(uiState, viewModel::onAction, navigateUpAndClearMutual, mutualData, requestMicPermission = {
- permissionLauncher.launch(Manifest.permission.RECORD_AUDIO)
- })
+ // WaveLog(4.5.2): 自动上传 — 每 10 分钟重试本地队列(开关开启时)
+ val wavelogUploader = remember { container.provideWavelogUploader() }
+ LaunchedEffect(Unit) {
+ while (true) {
+ delay(10 * 60 * 1000L)
+ val s = container.settingsRepo.otherSettings.value
+ if (s.wavelogAutoUpload && s.wavelogUrl.isNotBlank()) {
+ // 网格不一致时静默跳过(留给手动上传确认), 其余失败自动下次重试
+ val outcome = wavelogUploader.uploadQueue()
+ if (outcome is UploadOutcome.NeedConfirm) {
+ // 跳过本次; 用户可在设置页手动上传并确认
+ }
+ }
+ }
+ }
+ RadarScreen(
+ uiState,
+ viewModel::onAction,
+ navigateUpAndClearMutual,
+ mutualData,
+ { permissionLauncher.launch(Manifest.permission.RECORD_AUDIO) },
+ wavelogQueue = container.wavelogQueue,
+ wavelogConfigured = container.settingsRepo.otherSettings.value.let {
+ it.wavelogUrl.isNotBlank() && it.wavelogApiKey.isNotBlank() && it.wavelogStationId.isNotBlank()
+ },
+ showToast = { msg -> container.provideShowToast()(msg) }
+ )
}
@Composable
@@ -130,7 +159,10 @@ private fun RadarScreen(
onAction: (RadarAction) -> Unit,
navigateUp: () -> Unit,
mutualData: MutualPassData,
- requestMicPermission: () -> Unit
+ requestMicPermission: () -> Unit,
+ wavelogQueue: WavelogQueue,
+ wavelogConfigured: Boolean,
+ showToast: (String) -> Unit
) {
val upcomingPass = uiState.currentPass ?: getDefaultPass()
val addToCalendar: () -> Unit = {
@@ -184,11 +216,11 @@ private fun RadarScreen(
}
if (isVertical) {
RadarCard(uiState, trackB, trackBPosition, Modifier.weight(1f))
- PagerCard(uiState, onAction, requestMicPermission, Modifier.weight(1f))
+ PagerCard(uiState, onAction, requestMicPermission, wavelogQueue, wavelogConfigured, showToast, Modifier.weight(1f))
} else {
Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
RadarCard(uiState, trackB, trackBPosition, Modifier.weight(1f))
- PagerCard(uiState, onAction, requestMicPermission, Modifier.weight(1f))
+ PagerCard(uiState, onAction, requestMicPermission, wavelogQueue, wavelogConfigured, showToast, Modifier.weight(1f))
}
}
}
@@ -199,18 +231,37 @@ private fun PagerCard(
uiState: RadarState,
onAction: (RadarAction) -> Unit,
requestMicPermission: () -> Unit,
+ wavelogQueue: WavelogQueue,
+ wavelogConfigured: Boolean,
+ showToast: (String) -> Unit,
modifier: Modifier = Modifier
) {
- val pages = RadarPage.entries
+ val hasCalculatorPage = remember(uiState.transceivers.transmitters) {
+ uiState.transceivers.transmitters.any(DopplerFrequencyCalculator::isNamedLinearTransponder)
+ }
+ val pages = remember(hasCalculatorPage) {
+ buildList {
+ add(RadarPage.Transceivers)
+ add(RadarPage.Log)
+ if (hasCalculatorPage) add(RadarPage.Calculator)
+ add(RadarPage.Sstv)
+ }
+ }
val pagerState = rememberPagerState(pageCount = { pages.size })
val coroutineScope = rememberCoroutineScope()
+ LaunchedEffect(pages.size) {
+ val lastPage = pages.lastIndex
+ if (pagerState.currentPage > lastPage) pagerState.scrollToPage(lastPage)
+ }
+
ElevatedCard(modifier = modifier) {
Column(modifier = Modifier.fillMaxSize()) {
- PrimaryTabRow(selectedTabIndex = pagerState.currentPage) {
+ val selectedTabIndex = pagerState.currentPage.coerceIn(0, pages.lastIndex)
+ PrimaryTabRow(selectedTabIndex = selectedTabIndex) {
pages.forEachIndexed { index, page ->
Tab(
- selected = pagerState.currentPage == index,
+ selected = selectedTabIndex == index,
onClick = { coroutineScope.launch { pagerState.animateScrollToPage(index) } },
text = { Text(text = page.title, maxLines = 1, overflow = TextOverflow.Ellipsis) }
)
@@ -222,20 +273,35 @@ private fun PagerCard(
) { pageIndex ->
when (pages[pageIndex]) {
RadarPage.Transceivers -> TransceiversPage(
- transceivers = uiState.transceivers.transmitters,
- selectedUuid = uiState.transceivers.selectedUuid,
- orbitalPos = uiState.orbitalPos,
- cw = uiState.cw,
- radioControl = uiState.radioControl,
- onAction = onAction,
- requestMicPermission = requestMicPermission
- )
+ transceivers = uiState.transceivers.transmitters,
+ selectedUuid = uiState.transceivers.selectedUuid,
+ radioControl = uiState.radioControl,
+ onAction = onAction
+ )
+ RadarPage.Calculator -> CalculatorPage(
+ transceivers = uiState.transceivers.transmitters,
+ selectedUuid = uiState.transceivers.selectedUuid,
+ orbitalPos = uiState.orbitalPos,
+ cw = uiState.cw,
+ onAction = onAction,
+ requestMicPermission = requestMicPermission
+ )
RadarPage.Sstv -> SstvPage(
sstv = uiState.sstv,
dopplerFrequency = uiState.transceivers.selectedFrequency?.let { formatFrequency(it) },
onAction = onAction,
requestMicPermission = requestMicPermission
)
+ RadarPage.Log -> LogTab(
+ transceivers = uiState.transceivers.transmitters,
+ orbitalPos = uiState.orbitalPos,
+ satelliteName = uiState.currentPass?.name ?: "",
+ queue = wavelogQueue,
+ wavelogConfigured = wavelogConfigured,
+ showToast = showToast,
+ txBaseFrequencyHz = uiState.radioControl.txBaseFrequencyHz,
+ aosTimeMs = uiState.currentPass?.aosTime ?: 0L
+ )
}
}
}
diff --git a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarView.kt b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarView.kt
index 142e7755..ceed8c7d 100644
--- a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarView.kt
+++ b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarView.kt
@@ -94,14 +94,21 @@ fun RadarViewCompose(
animationSpec = infiniteRepeatable(tween(1000)),
label = "animScale"
)
- // Drive the sweep from the animation framework to eliminate state mutation inside the draw block
- val sweepTransition = rememberInfiniteTransition(label = "sweep")
- val sweepDegrees by sweepTransition.animateFloat(
- initialValue = 0f,
- targetValue = 360f,
- animationSpec = infiniteRepeatable(tween(SWEEP_DURATION_MS, easing = LinearEasing)),
- label = "sweepDegrees"
- )
+ // Drive the sweep from the animation framework to eliminate state mutation inside the draw block.
+ // Only create the infinite transition when the sweep is enabled — otherwise the canvas would
+ // be invalidated every frame for an effect that isn't visible, wasting GPU and battery.
+ val sweepDegrees = if (shouldShowSweep) {
+ val sweepTransition = rememberInfiniteTransition(label = "sweep")
+ val animatedSweep by sweepTransition.animateFloat(
+ initialValue = 0f,
+ targetValue = 360f,
+ animationSpec = infiniteRepeatable(tween(SWEEP_DURATION_MS, easing = LinearEasing)),
+ label = "sweepDegrees"
+ )
+ animatedSweep
+ } else {
+ 0f
+ }
val measurer = rememberTextMeasurer()
val sunPainter = painterResource(R.drawable.ic_sun)
val moonPainter = painterResource(R.drawable.ic_moon)
diff --git a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarViewModel.kt b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarViewModel.kt
index c3a84532..2b0fe4b8 100644
--- a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarViewModel.kt
+++ b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/RadarViewModel.kt
@@ -181,7 +181,7 @@ class RadarViewModel(
orbitalPos = pos, sunPosition = cachedSunPos, moonPosition = cachedMoonPos
)
}
- processRadios(allRadios, pass.orbitalObject, timeNow)
+ processRadios(allRadios, pos)
sendPassData(pos)
}
@@ -342,8 +342,8 @@ class RadarViewModel(
}
}
- private suspend fun processRadios(radios: List, orbitalObject: OrbitalObject, time: Long) {
- val transmitters = satelliteRepo.getRadios(orbitalObject, stationPos, radios, time)
+ private suspend fun processRadios(radios: List, satPos: OrbitalPos) {
+ val transmitters = satelliteRepo.getRadios(satPos, radios)
_uiState.update { state ->
val freq = if (state.transceivers.selectedUuid != null) {
val selectedRadio = transmitters.firstOrNull { it.uuid == state.transceivers.selectedUuid }
diff --git a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/TransceiversPage.kt b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/TransceiversPage.kt
index 7c93b44c..f4af915b 100644
--- a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/TransceiversPage.kt
+++ b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/TransceiversPage.kt
@@ -17,6 +17,8 @@
*/
package com.rtbishop.look4sat.feature.radar
+import android.app.Activity
+import android.view.LayoutInflater
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.expandVertically
import androidx.compose.animation.shrinkVertically
@@ -41,7 +43,6 @@ import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button
-import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.FilterChip
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
@@ -50,6 +51,7 @@ import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -60,6 +62,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
@@ -68,6 +71,8 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.constraintlayout.widget.ConstraintLayout
import com.rtbishop.look4sat.core.domain.model.SatRadio
import com.rtbishop.look4sat.core.domain.predict.OrbitalPos
import com.rtbishop.look4sat.core.domain.utility.DopplerFrequencyCalculator
@@ -75,6 +80,8 @@ import com.rtbishop.look4sat.core.presentation.CardButton
import com.rtbishop.look4sat.core.presentation.R
import com.rtbishop.look4sat.core.presentation.formatFrequency
import com.rtbishop.look4sat.core.presentation.infiniteMarquee
+import com.rtbishop.look4sat.feature.cw.R as CwR
+import com.ve3nea.morse_expert.MainActivity
import java.util.Locale
import kotlin.time.Duration.Companion.milliseconds
@@ -82,11 +89,8 @@ import kotlin.time.Duration.Companion.milliseconds
fun TransceiversPage(
transceivers: List,
selectedUuid: String?,
- orbitalPos: OrbitalPos?,
- cw: CwSubState,
radioControl: RadioControlSubState,
onAction: (RadarAction) -> Unit,
- requestMicPermission: () -> Unit = {},
modifier: Modifier = Modifier
) {
if (transceivers.isEmpty()) {
@@ -109,11 +113,8 @@ fun TransceiversPage(
TransceiverItem(
radio = radio,
isExpanded = isExpanded,
- orbitalPos = orbitalPos,
- cw = cw,
radioControl = radioControl,
onAction = onAction,
- requestMicPermission = requestMicPermission,
onToggle = { onAction(RadarAction.SelectTransmitter(radio.uuid)) }
)
}
@@ -121,6 +122,87 @@ fun TransceiversPage(
}
}
+@Composable
+fun CalculatorPage(
+ transceivers: List,
+ selectedUuid: String?,
+ orbitalPos: OrbitalPos?,
+ cw: CwSubState,
+ onAction: (RadarAction) -> Unit,
+ requestMicPermission: () -> Unit = {},
+ modifier: Modifier = Modifier
+) {
+ val calculatorTransceivers = remember(transceivers) {
+ transceivers.filter(DopplerFrequencyCalculator::isNamedLinearTransponder)
+ }
+ val selectedTransceiver = remember(calculatorTransceivers, selectedUuid) {
+ calculatorTransceivers.firstOrNull { it.uuid == selectedUuid }
+ ?: calculatorTransceivers.firstOrNull()
+ }
+
+ if (selectedTransceiver == null) {
+ EmptyTransceiversContent(modifier)
+ return
+ }
+
+ LazyColumn(
+ modifier = modifier
+ .fillMaxSize()
+ .padding(8.dp),
+ verticalArrangement = Arrangement.spacedBy(10.dp)
+ ) {
+ if (calculatorTransceivers.size > 1) {
+ item {
+ FlowRow(
+ horizontalArrangement = Arrangement.spacedBy(6.dp),
+ verticalArrangement = Arrangement.spacedBy(4.dp),
+ modifier = Modifier.fillMaxWidth()
+ ) {
+ calculatorTransceivers.forEach { radio ->
+ FilterChip(
+ selected = radio.uuid == selectedTransceiver.uuid,
+ onClick = {
+ if (radio.uuid != selectedUuid) onAction(RadarAction.SelectTransmitter(radio.uuid))
+ },
+ label = {
+ Text(
+ text = transceiverTitle(radio),
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis
+ )
+ }
+ )
+ }
+ }
+ }
+ }
+
+ item {
+ DopplerFrequencyCalculator(
+ transponder = selectedTransceiver,
+ orbitalPos = orbitalPos,
+ modifier = Modifier.fillMaxWidth()
+ )
+ }
+
+ item {
+ HorizontalDivider(
+ thickness = 1.dp,
+ color = MaterialTheme.colorScheme.outline.copy(alpha = 0.3f)
+ )
+ }
+
+ item {
+ CwDecoderPanel(
+ cw = cw,
+ onAction = onAction,
+ requestMicPermission = requestMicPermission,
+ modifier = Modifier.fillMaxWidth()
+ )
+ }
+ }
+}
+
@Composable
private fun EmptyTransceiversContent(modifier: Modifier = Modifier) {
Box(contentAlignment = Alignment.Center, modifier = modifier.fillMaxSize()) {
@@ -148,11 +230,8 @@ private fun EmptyTransceiversContent(modifier: Modifier = Modifier) {
private fun TransceiverItem(
radio: SatRadio,
isExpanded: Boolean,
- orbitalPos: OrbitalPos?,
- cw: CwSubState,
radioControl: RadioControlSubState,
onAction: (RadarAction) -> Unit,
- requestMicPermission: () -> Unit,
onToggle: () -> Unit
) {
val bgColor = if (isExpanded) MaterialTheme.colorScheme.surfaceContainerHighest
@@ -193,11 +272,8 @@ private fun TransceiverItem(
)
}
// Title with mode
- val title = if (radio.isInverted) "INV: ${radio.info}" else radio.info
- val mode = "${radio.downlinkMode ?: "--"}/${radio.uplinkMode ?: "--"}"
- val fullTitle = "$title ($mode)"
Text(
- text = fullTitle,
+ text = transceiverTitle(radio),
textAlign = TextAlign.Center,
color = MaterialTheme.colorScheme.onSurface,
maxLines = 1,
@@ -245,11 +321,8 @@ private fun TransceiverItem(
) {
ExpandedRadioControl(
radio = radio,
- orbitalPos = orbitalPos,
- cw = cw,
radioControl = radioControl,
- onAction = onAction,
- requestMicPermission = requestMicPermission
+ onAction = onAction
)
}
@@ -318,11 +391,8 @@ private fun UnifiedFrequencyRow(
@Composable
private fun ExpandedRadioControl(
radio: SatRadio,
- orbitalPos: OrbitalPos?,
- cw: CwSubState,
radioControl: RadioControlSubState,
onAction: (RadarAction) -> Unit,
- requestMicPermission: () -> Unit = {},
) {
Column(
modifier = Modifier
@@ -431,23 +501,6 @@ private fun ExpandedRadioControl(
}
}
- // Doppler frequency calculator (linear transponders only)
- DopplerFrequencyCalculator(
- transponder = radio,
- orbitalPos = orbitalPos,
- modifier = Modifier.fillMaxWidth()
- )
-
- // CW decoder panel (linear transponders only)
- if (DopplerFrequencyCalculator.isLinearTransponder(radio)) {
- CwDecoderPanel(
- cw = cw,
- onAction = onAction,
- requestMicPermission = requestMicPermission,
- modifier = Modifier.fillMaxWidth()
- )
- }
-
// Control buttons
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
if (!radioControl.txPanel.isConnected && !radioControl.rxPanel.isConnected) {
@@ -565,7 +618,7 @@ private fun DopplerFrequencyCalculator(
},
label = { Text(stringResource(R.string.radar_doppler_offset_hint)) },
singleLine = true,
- keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal),
+ keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
modifier = Modifier.fillMaxWidth()
)
@@ -661,19 +714,54 @@ private fun CwDecoderPanel(
}
AnimatedVisibility(visible = cw.isExpanded) {
+ // PR #1 Morse Expert engine: mini layout with waterfall + decoded text.
+ // Keep the old Kotlin decoder state/actions as fallback code, but this panel no longer feeds it.
+ val context = LocalContext.current
+ val activity = remember { context as? Activity }
+ val controller = remember { MainActivity() }
+ val rootView = remember {
+ LayoutInflater.from(context).inflate(CwR.layout.cw_panel_main, null) as ConstraintLayout
+ }
+ var initialized by remember { mutableStateOf(false) }
+ var listening by remember { mutableStateOf(false) }
+
+ DisposableEffect(Unit) {
+ if (activity != null) {
+ controller.onCreate(activity, rootView, false)
+ }
+ onDispose {
+ controller.onPause()
+ controller.onDestroy()
+ }
+ }
+
+ LaunchedEffect(cw.hasPermission) {
+ if (cw.hasPermission && !initialized) {
+ controller.onPermissionGranted()
+ controller.onResume()
+ initialized = true
+ listening = true
+ }
+ }
+
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
- // Control buttons row
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.fillMaxWidth()
) {
- if (cw.status == CwStatus.Idle) {
+ if (!listening) {
Button(
onClick = {
if (!cw.hasPermission) {
requestMicPermission()
+ } else if (!initialized) {
+ controller.onPermissionGranted()
+ controller.onResume()
+ initialized = true
+ listening = true
} else {
- onAction(RadarAction.CwStartListening)
+ controller.onResume()
+ listening = true
}
},
modifier = Modifier.weight(1f)
@@ -682,58 +770,29 @@ private fun CwDecoderPanel(
}
} else {
Button(
- onClick = { onAction(RadarAction.CwStopListening) },
+ onClick = {
+ controller.onPause()
+ listening = false
+ },
modifier = Modifier.weight(1f)
) {
Text(stringResource(R.string.radar_cw_stop))
}
}
OutlinedButton(
- onClick = { onAction(RadarAction.CwReset) },
+ onClick = { controller.clearDecoded() },
modifier = Modifier.weight(1f)
) {
Text(stringResource(R.string.radar_cw_reset))
}
}
- // Signal strength indicator
- if (cw.status == CwStatus.Listening && cw.signalStrength > 0f) {
- val strengthPct = (cw.signalStrength * 100).toInt()
- Text(
- text = "Signal: $strengthPct%",
- fontSize = 12.sp,
- color = if (cw.signalStrength > 0.5f) Color(0xFF4CAF50)
- else if (cw.signalStrength > 0.2f) Color(0xFFFFC107)
- else MaterialTheme.colorScheme.onSurfaceVariant
- )
- }
-
- // Decoded text output
- ElevatedCard(
+ AndroidView(
+ factory = { rootView },
modifier = Modifier
.fillMaxWidth()
- .height(120.dp)
- ) {
- Column(
- modifier = Modifier
- .fillMaxSize()
- .padding(8.dp)
- ) {
- Text(
- text = "Decoded:",
- fontSize = 12.sp,
- fontWeight = FontWeight.Bold,
- color = MaterialTheme.colorScheme.onSurfaceVariant
- )
- Spacer(modifier = Modifier.height(4.dp))
- Text(
- text = cw.decodedText.ifEmpty { "Waiting for CW signal..." },
- fontSize = 16.sp,
- fontWeight = FontWeight.Medium,
- color = MaterialTheme.colorScheme.onSurface
- )
- }
- }
+ .height(150.dp)
+ )
}
}
}
@@ -754,5 +813,11 @@ private fun FrequencyText(frequency: Long?, modifier: Modifier = Modifier) {
)
}
+private fun transceiverTitle(radio: SatRadio): String {
+ val title = if (radio.isInverted) "INV: ${radio.info}" else radio.info
+ val mode = "${radio.downlinkMode ?: "--"}/${radio.uplinkMode ?: "--"}"
+ return "$title ($mode)"
+}
+
private val FREQ_ADJUSTMENTS =
listOf(-10_000L to "-10k", -1_000L to "-1k", -100L to "-100", 100L to "+100", 1_000L to "+1k", 10_000L to "+10k")
diff --git a/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/WavelogLogScreen.kt b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/WavelogLogScreen.kt
new file mode 100644
index 00000000..4e3c001c
--- /dev/null
+++ b/feature/radar/src/main/java/com/rtbishop/look4sat/feature/radar/WavelogLogScreen.kt
@@ -0,0 +1,236 @@
+/*
+ * WavelogLogScreen.kt — 「日志」页面(更多菜单, 4.5.2 修复)。
+ *
+ * 表格形式展示本地存储的日志: 时间 | 频率 | 卫星 | 呼号 | 已上传(✓)。
+ * 完整格子线(表头横线 + 行横线 + 列竖线 + 外边框); 行复用左滑删除。
+ */
+package com.rtbishop.look4sat.feature.radar
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.HorizontalDivider
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.rtbishop.look4sat.core.domain.wavelog.WavelogQueue
+import com.rtbishop.look4sat.core.presentation.R
+import com.rtbishop.look4sat.core.presentation.formatFrequency
+import java.util.Calendar
+import java.util.TimeZone
+
+private val CheckGreen = Color(0xFF4CAF50)
+private val GridLineColor = Color(0xFF3A3A3A)
+
+@Composable
+fun WavelogLogScreen(
+ queue: WavelogQueue,
+ modifier: Modifier = Modifier
+) {
+ var refreshTick by remember { mutableIntStateOf(0) }
+ val entries = remember(refreshTick) { queue.all() }
+
+ Column(
+ modifier = modifier
+ .fillMaxSize()
+ .verticalScroll(rememberScrollState())
+ .padding(8.dp)
+ ) {
+ // 表格外边框(左右 + 上下由表头/行底线构成)
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .background(MaterialTheme.colorScheme.surfaceContainer)
+ ) {
+ // 表头
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(38.dp)
+ ) {
+ HeaderCell(stringResource(id = R.string.wavelog_col_time), 72.dp)
+ GridVLine()
+ HeaderCell(stringResource(id = R.string.wavelog_col_freq), 64.dp)
+ GridVLine()
+ HeaderCell(stringResource(id = R.string.wavelog_col_sat), 0.dp, weight = 1.2f)
+ GridVLine()
+ HeaderCell(stringResource(id = R.string.wavelog_col_call), 0.dp, weight = 1f)
+ GridVLine()
+ HeaderCell(stringResource(id = R.string.wavelog_col_uploaded), 44.dp)
+ }
+ // 表头横线
+ HorizontalDivider(thickness = 1.5.dp, color = GridLineColor)
+ // 表头与数据区留白
+ Box(modifier = Modifier.height(8.dp))
+
+ if (entries.isEmpty()) {
+ Text(
+ text = stringResource(id = R.string.wavelog_empty),
+ fontSize = 13.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.padding(horizontal = 10.dp, vertical = 12.dp)
+ )
+ } else {
+ // 按场次分组(sessionId = 卫星名-AOS 时间戳); 空 sessionId 归"未分组"放最后
+ val groups = entries.groupBy { it.sessionId.ifBlank { UNGROUPED } }
+ .toSortedMap(compareByDescending { id ->
+ entries.filter { it.sessionId.ifBlank { UNGROUPED } == id }.minOfOrNull { it.timeUtcMs } ?: 0L
+ }.thenByDescending { it })
+ groups.forEach { (sessionId, groupEntries) ->
+ // 组标题(场次名 + 本地时间)
+ val (satPart, timePart) = parseSession(sessionId)
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ Text(
+ text = if (sessionId == UNGROUPED) stringResource(id = R.string.wavelog_ungrouped)
+ else "$satPart - ${formatSessionTime(timePart)}",
+ fontSize = 12.sp,
+ fontWeight = FontWeight.Bold,
+ color = MaterialTheme.colorScheme.primary,
+ modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp)
+ )
+ }
+ // 组间横线(md --- 效果)
+ HorizontalDivider(thickness = 1.5.dp, color = GridLineColor)
+ groupEntries.forEach { entry ->
+ SwipeDeleteRow(
+ onDelete = {
+ queue.remove(entry.id)
+ refreshTick++
+ }
+ ) {
+ Column(modifier = Modifier.fillMaxWidth()) {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(36.dp)
+ ) {
+ Cell(formatLocalTime(entry.timeUtcMs), 72.dp)
+ GridVLine()
+ Cell(formatFrequency(entry.freqTxHz), 64.dp)
+ GridVLine()
+ Cell(entry.satName, 0.dp, weight = 1.2f)
+ GridVLine()
+ Cell(entry.call, 0.dp, weight = 1f)
+ GridVLine()
+ Box(modifier = Modifier.width(44.dp)) {
+ if (entry.uploaded) {
+ Text(
+ text = "✓",
+ fontSize = 15.sp,
+ fontWeight = FontWeight.Bold,
+ color = CheckGreen
+ )
+ }
+ }
+ }
+ // 行分隔线
+ HorizontalDivider(thickness = 1.dp, color = GridLineColor)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/** 列竖线 */
+@Composable
+private fun GridVLine() {
+ Box(
+ modifier = Modifier
+ .width(1.dp)
+ .fillMaxHeight()
+ .background(GridLineColor)
+ )
+}
+
+@Composable
+private fun RowScope.HeaderCell(text: String, width: Dp, weight: Float = 0f) {
+ val mod = if (weight > 0f) Modifier.weight(weight) else Modifier.width(width)
+ Text(
+ text = text,
+ fontSize = 12.sp,
+ fontWeight = FontWeight.Bold,
+ color = MaterialTheme.colorScheme.primary,
+ maxLines = 1,
+ modifier = mod.padding(horizontal = 6.dp)
+ )
+}
+
+@Composable
+private fun RowScope.Cell(text: String, width: Dp, weight: Float = 0f) {
+ val mod = if (weight > 0f) Modifier.weight(weight) else Modifier.width(width)
+ Text(
+ text = text,
+ fontSize = 12.sp,
+ maxLines = 1,
+ modifier = mod.padding(horizontal = 6.dp)
+ )
+}
+
+private const val UNGROUPED = "__ungrouped__"
+
+/** 解析场次 ID: "ASRTU-1-20260804-2014" → (卫星名, "20260804-2014") */
+private fun parseSession(sessionId: String): Pair {
+ val parts = sessionId.split('-')
+ if (parts.size < 3) return sessionId to ""
+ val timePart = parts.takeLast(2).joinToString("-")
+ val satPart = parts.dropLast(2).joinToString("-")
+ return satPart to timePart
+}
+
+/** 场次时间(UTC "20260804-2014") → 本地 "MM-dd HH:mm" */
+private fun formatSessionTime(timePart: String): String {
+ if (timePart.length != 13 || timePart[8] != '-') return timePart
+ return try {
+ val year = timePart.substring(0, 4).toInt()
+ val month = timePart.substring(4, 6).toInt()
+ val day = timePart.substring(6, 8).toInt()
+ val hour = timePart.substring(9, 11).toInt()
+ val minute = timePart.substring(11, 13).toInt()
+ val cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
+ cal.set(year, month - 1, day, hour, minute, 0)
+ cal.timeInMillis = cal.timeInMillis + TimeZone.getDefault().getOffset(cal.timeInMillis)
+ "%02d-%02d %02d:%02d".format(
+ cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH),
+ cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)
+ )
+ } catch (_: Exception) {
+ timePart
+ }
+}
+
+private fun formatLocalTime(utcMs: Long): String {
+ val cal = Calendar.getInstance(TimeZone.getDefault())
+ cal.timeInMillis = utcMs
+ return "%02d-%02d %02d:%02d".format(
+ cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH),
+ cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)
+ )
+}
diff --git a/feature/roaming/build.gradle.kts b/feature/roaming/build.gradle.kts
new file mode 100644
index 00000000..982bdb5a
--- /dev/null
+++ b/feature/roaming/build.gradle.kts
@@ -0,0 +1,11 @@
+plugins {
+ alias(libs.plugins.convention.featurePlugin)
+}
+
+android {
+ namespace = "com.rtbishop.look4sat.feature.roaming"
+}
+
+dependencies {
+ implementation(project(":core:data"))
+}
diff --git a/feature/roaming/src/main/java/com/rtbishop/look4sat/feature/roaming/RoamingScreen.kt b/feature/roaming/src/main/java/com/rtbishop/look4sat/feature/roaming/RoamingScreen.kt
new file mode 100644
index 00000000..a876519a
--- /dev/null
+++ b/feature/roaming/src/main/java/com/rtbishop/look4sat/feature/roaming/RoamingScreen.kt
@@ -0,0 +1,791 @@
+/*
+ * Look4Sat. Amateur radio satellite tracker and pass predictor.
+ * Copyright (C) 2019-2026 Arty Bishop and contributors.
+ *
+ * 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 .
+ */
+package com.rtbishop.look4sat.feature.roaming
+
+import android.Manifest
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.location.Location
+import android.location.LocationListener
+import android.location.LocationManager
+import android.os.Bundle
+import android.provider.Settings
+import androidx.activity.compose.rememberLauncherForActivityResult
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.offset
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.windowInsetsPadding
+import androidx.compose.foundation.layout.systemBars
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.core.content.ContextCompat
+import java.text.SimpleDateFormat
+import java.util.Date
+import java.util.Locale
+
+/**
+ * 漫游页 —— 原样照搬自 QTH定位器 2.0 (com.us1pm.gridsquarelocator)。
+ * UI: res/layout/main.xml (结构/尺寸/颜色逐项照搬, 不做任何更改)
+ * 逻辑: MainActivity.showLocation() / checkEnabled() / GPS 实时监听
+ * 红线: UI 与逻辑均不更改, 与成品截图逐像素对齐。
+ */
+@Composable
+fun RoamingScreen() {
+ val context = LocalContext.current
+ var state by remember { mutableStateOf(RoamingState()) }
+ // 照搬 onCreate: 日期固定文本 + 小时前缀(定位时拼接分钟)
+ val dateText = remember { SimpleDateFormat("dd MMM yyyy", Locale.getDefault()).format(Date()) }
+ var hourPrefix by remember { mutableStateOf("") }
+ // 照搬 onCreate: 初始 checkEnabled() -> 红点+设置按钮, 日期隐藏
+ var hasPermission by remember { mutableStateOf(false) }
+ val permissionLauncher = rememberLauncherForActivityResult(
+ ActivityResultContracts.RequestMultiplePermissions()
+ ) { }
+ LaunchedEffect(Unit) {
+ hourPrefix = SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date()).substring(0, 3)
+ val fine = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) ==
+ PackageManager.PERMISSION_GRANTED
+ val coarse = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) ==
+ PackageManager.PERMISSION_GRANTED
+ hasPermission = fine || coarse
+ if (!hasPermission) {
+ permissionLauncher.launch(
+ arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION)
+ )
+ } else {
+ // 照搬 onResume: 绿点+进度条+提示+日期显示, 红点/按钮隐藏
+ state = state.copy(gpsOn = true, gpsOff = false, showSettings = false, showProgress = true, showNotice = true, showDate = true)
+ }
+ }
+ // 照搬 onResume/onPause: GPS + network 监听, 10 秒 / 10 米
+ val locationManager = remember { context.getSystemService(Context.LOCATION_SERVICE) as LocationManager }
+ DisposableEffect(locationManager, hasPermission) {
+ if (hasPermission) {
+ @SuppressLint("MissingPermission")
+ val listener = object : LocationListener {
+ override fun onLocationChanged(location: Location) {
+ // 照搬 showLocation 开头: 只接受 gps / network provider
+ if (location.provider != "gps" && location.provider != "network") return
+ state = roamingStateFromLocation(location.latitude, location.longitude, location.time, hourPrefix)
+ .copy(date = dateText)
+ }
+
+ override fun onProviderDisabled(provider: String) {
+ // 照搬 checkEnabled: 红点+按钮, 日期隐藏
+ state = state.copy(gpsOn = false, gpsOff = true, showSettings = true, showProgress = false, showNotice = false, showDate = false)
+ }
+
+ override fun onProviderEnabled(provider: String) {
+ state = state.copy(gpsOn = true, gpsOff = false, showSettings = false, showProgress = true, showNotice = true, showDate = true)
+ }
+
+ @Deprecated("Deprecated in Java")
+ override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) = Unit
+ }
+ try {
+ locationManager.requestLocationUpdates("gps", 10_000L, 10f, listener)
+ locationManager.requestLocationUpdates("network", 10_000L, 10f, listener)
+ } catch (_: SecurityException) {
+ }
+ onDispose { locationManager.removeUpdates(listener) }
+ } else {
+ onDispose { }
+ }
+ }
+ // 照搬 res/layout/main.xml: 浅色页面, 蓝色信息区, 43sp 定位码, 3x3 九宫格, 底部版权
+ // 按用户要求: 上下往内缩进系统栏安全区, 避免内容被状态栏/导航栏遮挡
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .background(MaterialTheme.colorScheme.background)
+ .windowInsetsPadding(WindowInsets.systemBars)
+ ) {
+ // relativeLayout7: 顶部 GPS 状态条, 25dp 高, holo_blue_bright
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(2.dp)
+ .height(25.dp)
+ .background(MaterialTheme.colorScheme.surfaceVariant)
+ ) {
+ Row(modifier = Modifier.fillMaxSize(), verticalAlignment = Alignment.CenterVertically) {
+ // tvTitleGPS: "GPS" 14sp 黑, 左 8dp
+ Text(
+ text = "GPS",
+ fontSize = 14.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.padding(start = 8.dp)
+ )
+ // imGps: toRightOf tvTitleGPS + marginLeft 15dp (成品 main.xml)
+ Spacer(modifier = Modifier.width(15.dp))
+ // imGps: 绿点 (15dp, 主题色 primary -> 夜间滤镜下可见)
+ if (state.gpsOn) {
+ Box(
+ modifier = Modifier
+ .size(15.dp)
+ .background(MaterialTheme.colorScheme.primary, CircleShape)
+ )
+ }
+ // imGpsOff: 红点叠层 (15dp, 主题色 error)
+ if (state.gpsOff) {
+ Box(
+ modifier = Modifier
+ .size(15.dp)
+ .background(MaterialTheme.colorScheme.error, CircleShape)
+ )
+ }
+ Spacer(modifier = Modifier.weight(1f))
+ // tvDate: 14sp 黑, 居中
+ if (state.showDate) {
+ Text(text = state.date.ifEmpty { dateText }, fontSize = 14.sp, color = MaterialTheme.colorScheme.onSurfaceVariant)
+ }
+ Spacer(modifier = Modifier.weight(1f))
+ // tvTime: 14sp 黑, 右对齐
+ Text(
+ text = state.time,
+ fontSize = 14.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.padding(end = 8.dp)
+ )
+ }
+ // btnLocationSettings: 黄色按钮, 居中
+ // btnLocationSettings: 成品 #faf8f54a 半透明黄, 14sp 黑字, 居中
+ if (state.showSettings) {
+ Box(
+ modifier = Modifier
+ .align(Alignment.Center)
+ .background(MaterialTheme.colorScheme.primary)
+ .clickable { context.startActivity(Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)) }
+ .padding(horizontal = 5.dp),
+ contentAlignment = Alignment.Center
+ ) {
+ Text(text = "设置启用GPS", fontSize = 14.sp, color = MaterialTheme.colorScheme.onPrimary)
+ }
+ }
+ }
+ // linearLayout4: 经纬度区, holo_blue_bright
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 2.dp)
+ .background(MaterialTheme.colorScheme.surfaceVariant)
+ ) {
+ // 纬度行: tvLati 16sp 黑 左 8dp | tvLat 右对齐 3dp
+ Row(modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp), verticalAlignment = Alignment.CenterVertically) {
+ Text(text = state.latLabel, fontSize = 16.sp, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.padding(start = 8.dp))
+ Spacer(modifier = Modifier.weight(1f))
+ Text(text = state.latValue, fontSize = 14.sp, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.padding(end = 3.dp))
+ }
+ // 经度行
+ Row(modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp), verticalAlignment = Alignment.CenterVertically) {
+ Text(text = state.lonLabel, fontSize = 16.sp, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.padding(start = 8.dp))
+ Spacer(modifier = Modifier.weight(1f))
+ Text(text = state.lonValue, fontSize = 14.sp, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.padding(end = 3.dp))
+ }
+ }
+ // relativeLayout6: 定位码区, 43sp bold 黑居中
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(2.dp)
+ .background(MaterialTheme.colorScheme.surfaceVariant)
+ ) {
+ Text(
+ text = state.loc,
+ fontSize = 43.sp,
+ fontWeight = FontWeight.Bold,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ textAlign = TextAlign.Center,
+ modifier = Modifier.fillMaxWidth()
+ )
+ // progressBar: 加载中, 居中
+ if (state.showProgress) {
+ CircularProgressIndicator(
+ modifier = Modifier.size(24.dp).align(Alignment.Center),
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ strokeWidth = 2.dp
+ )
+ }
+ // tvNotice: 提示文字, 居中顶部
+ if (state.showNotice) {
+ Text(
+ text = "请稍等,加载可能需要几分钟的时间。",
+ fontSize = 16.sp,
+ fontStyle = androidx.compose.ui.text.font.FontStyle.Italic,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.align(Alignment.TopCenter).padding(top = 2.dp)
+ )
+ }
+ }
+ // relativeLayout: 九宫格, 占满剩余, 底部 15dp
+ // 用 Box 等价 RelativeLayout 布局: 左格贴左 / 中格水平居中 / 右格贴右 (成品 main.xml)
+ Column(modifier = Modifier.fillMaxWidth().weight(1f).padding(bottom = 15.dp)) {
+ // 行1: relativeLayout5 (上排: 纬度 +1)
+ Box(modifier = Modifier.fillMaxWidth().weight(1f)) {
+ GridCell(text = state.grids[0], modifier = Modifier.width(80.dp).fillMaxHeight().align(Alignment.CenterStart))
+ GridCell(text = state.grids[1], modifier = Modifier.width(200.dp).fillMaxHeight().align(Alignment.Center))
+ GridCell(text = state.grids[2], modifier = Modifier.width(80.dp).fillMaxHeight().align(Alignment.CenterEnd))
+ }
+ // 行2: relativeLayout4, 205dp 高 (中排: 中央)
+ Box(modifier = Modifier.fillMaxWidth().height(205.dp)) {
+ GridCell(text = state.grids[3], modifier = Modifier.width(80.dp).fillMaxHeight().align(Alignment.CenterStart))
+ // 中央列: tv22 (100x80dp centerInParent) 叠在 linearLayout3 (200x200dp) 之上
+ Box(modifier = Modifier.width(200.dp).fillMaxHeight().align(Alignment.Center)) {
+ // linearLayout3: 200x200dp, marginTop 2dp, holo_blue_bright
+ Box(
+ modifier = Modifier
+ .align(Alignment.TopCenter)
+ .offset(y = 2.dp)
+ .size(width = 200.dp, height = 200.dp)
+ .background(MaterialTheme.colorScheme.surfaceVariant)
+ ) {
+ // iv: 红点 10x10dp, top|left, leftMargin/topMargin 查表绝对定位
+ Image(
+ painter = painterResource(R.drawable.roam_pnt),
+ contentDescription = null,
+ modifier = Modifier
+ .size(10.dp)
+ .offset(x = state.markerLeft.dp, y = state.markerTop.dp)
+ )
+ }
+ // tv22: 100x80dp centerInParent, 30sp bold, textColorHighlight(白)
+ Text(
+ text = state.grids[4],
+ fontSize = 30.sp,
+ fontWeight = FontWeight.Bold,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ textAlign = TextAlign.Center,
+ modifier = Modifier
+ .size(width = 100.dp, height = 80.dp)
+ .align(Alignment.Center)
+ )
+ }
+ GridCell(text = state.grids[5], modifier = Modifier.width(80.dp).fillMaxHeight().align(Alignment.CenterEnd))
+ }
+ // 行3: relativeLayout3 (下排: 纬度 -1)
+ Box(modifier = Modifier.fillMaxWidth().weight(1f)) {
+ GridCell(text = state.grids[6], modifier = Modifier.width(80.dp).fillMaxHeight().align(Alignment.CenterStart))
+ GridCell(text = state.grids[7], modifier = Modifier.width(200.dp).fillMaxHeight().align(Alignment.Center))
+ GridCell(text = state.grids[8], modifier = Modifier.width(80.dp).fillMaxHeight().align(Alignment.CenterEnd))
+ }
+ }
+ // tv4: 底部版权, 10sp 黑 (往上拉, 底部预留空间避免被导航栏遮挡)
+ Text(
+ text = "制作:US1PM 汉化:BA7LCE",
+ fontSize = 10.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ textAlign = TextAlign.Center,
+ modifier = Modifier.fillMaxWidth().padding(bottom = 10.dp)
+ )
+ }
+}
+
+// 周边格: 60/200/60dp, #0BACF1, bold 居中, 2dp margin (照搬 tv11/tv13/tv21/tv23/tv31/tv33)
+@Composable
+private fun GridCell(text: String, modifier: Modifier) {
+ Box(
+ modifier = modifier
+ .padding(2.dp)
+ .background(MaterialTheme.colorScheme.surface),
+ contentAlignment = Alignment.Center
+ ) {
+ Text(
+ text = text,
+ fontSize = 14.sp,
+ fontWeight = FontWeight.Bold,
+ color = MaterialTheme.colorScheme.onSurface,
+ textAlign = TextAlign.Center
+ )
+ }
+}
+
+/**
+ * 照搬 MainActivity.showLocation() 的状态。
+ * 网格/九宫格/红点查表与成品逐行一致。
+ */
+data class RoamingState(
+ val date: String = "",
+ val time: String = "",
+ val latLabel: String = "纬度",
+ val latValue: String = "",
+ val lonLabel: String = "经度",
+ val lonValue: String = "",
+ val loc: String = "",
+ val grids: List = List(9) { "" },
+ /** 红点 leftMargin(dp), 经度第 3 对字符查表 */
+ val markerLeft: Int = 0,
+ /** 红点 topMargin(dp), 纬度第 3 对字符查表(屏幕 Y 反转) */
+ val markerTop: Int = 0,
+ val gpsOn: Boolean = false,
+ val gpsOff: Boolean = true,
+ val showSettings: Boolean = true,
+ val showProgress: Boolean = false,
+ val showNotice: Boolean = false,
+ val showDate: Boolean = false
+)
+
+/**
+ * 照搬 showLocation() 的完整计算: 时间/经纬度 DMS/8 位网格/九宫格/红点查表。
+ */
+fun roamingStateFromLocation(lat: Double, lon: Double, fixTime: Long, hourPrefix: String): RoamingState {
+ // 照搬: tvTime = 缓存小时前缀 + 定位时间分钟
+ val minute = SimpleDateFormat("mm", Locale.getDefault()).format(Date(fixTime))
+ val time = hourPrefix + minute
+ // 方向字符
+ val ew = if (lon >= 0.0) "E" else "W"
+ val ns = if (lat >= 0.0) "N" else "S"
+ // 照搬: 纬度 DMS (String.valueOf 无补零)
+ val latAbs = if (lat < 0.0) -lat else lat
+ val latDeg = latAbs.toInt()
+ val latMinFull = (latAbs - latDeg) * 60.0
+ val latMin = latMinFull.toInt()
+ val latSec = ((latMinFull - latMin) * 60.0).toInt()
+ val latLabel = "纬度 $latDeg° $latMin' $latSec\" $ns"
+ val latValue = "$lat° "
+ // 照搬: 经度 DMS
+ val lonAbs = if (lon < 0.0) -lon else lon
+ val lonDeg = lonAbs.toInt()
+ val lonMinFull = (lonAbs - lonDeg) * 60.0
+ val lonMin = lonMinFull.toInt()
+ val lonSec = ((lonMinFull - lonMin) * 60.0).toInt()
+ val lonLabel = "经度 $lonDeg° $lonMin' $lonSec\" $ew"
+ val lonValue = "$lon° "
+ // 照搬: 8 位网格编码 (区间查表)
+ val (str, str2, str3, str4) = encodeLon(lon)
+ val (str5, str6, str38, str9) = encodeLat(lat)
+ val loc = str + str5 + str2 + str6 + str3 + str38 + str4 + str9
+ // 照搬: 九宫格 parseInt3 五分支
+ val grids = buildGrids(str, str5, str2, str6, str3, str38)
+ // 照搬: 红点查表 (第 3 对字符)
+ val markerLeft = lonMargin[str3.firstOrNull()] ?: 0
+ val markerTop = latMargin[str38.firstOrNull()] ?: 0
+ return RoamingState(
+ time = time,
+ latLabel = latLabel,
+ latValue = latValue,
+ lonLabel = lonLabel,
+ lonValue = lonValue,
+ loc = loc,
+ grids = grids,
+ markerLeft = markerLeft,
+ markerTop = markerTop,
+ gpsOn = true,
+ gpsOff = false,
+ showSettings = false,
+ showProgress = false,
+ showNotice = false,
+ showDate = true
+ )
+}
+
+// 红点 leftMargin 查表 (MainActivity 1286-1386 行): 经度第 3 对 a..x -> -2..190 dp
+private val lonMargin = mapOf(
+ 'a' to -2, 'b' to 8, 'c' to 16, 'd' to 24, 'e' to 32, 'f' to 40, 'g' to 48, 'h' to 56,
+ 'i' to 65, 'j' to 74, 'k' to 83, 'l' to 92, 'm' to 101, 'n' to 110, 'o' to 119, 'p' to 128,
+ 'q' to 137, 'r' to 146, 's' to 155, 't' to 163, 'u' to 171, 'v' to 179, 'w' to 184, 'x' to 190
+)
+
+// 红点 topMargin 查表 (MainActivity 1315-1363 行): 纬度第 3 对 a..x -> 190..-2 dp (屏幕 Y 反转)
+private val latMargin = mapOf(
+ 'a' to 190, 'b' to 182, 'c' to 174, 'd' to 169, 'e' to 163, 'f' to 155, 'g' to 146, 'h' to 137,
+ 'i' to 128, 'j' to 119, 'k' to 110, 'l' to 101, 'm' to 92, 'n' to 83, 'o' to 74, 'p' to 65,
+ 'q' to 56, 'r' to 48, 's' to 40, 't' to 32, 'u' to 24, 'v' to 16, 'w' to 8, 'x' to -2
+)
+
+// 照搬 311-611 行: 经度 -> (20°区字母, 2°数字, 2'字母, 30"数字)
+private fun encodeLon(inputLon: Double): List {
+ var longitude = inputLon
+ var d = 0.0
+ val str = when {
+ (longitude >= -180.0) && (longitude <= -160.0) -> { longitude += 180.0; "A" }
+ (longitude >= -160.0) && (longitude <= -140.0) -> { longitude += 160.0; "B" }
+ (longitude >= -140.0) && (longitude <= -120.0) -> { longitude += 140.0; "C" }
+ (longitude >= -120.0) && (longitude <= -100.0) -> { longitude += 120.0; "D" }
+ (longitude >= -100.0) && (longitude <= -80.0) -> { longitude += 100.0; "E" }
+ (longitude >= -80.0) && (longitude <= -60.0) -> { longitude += 80.0; "F" }
+ (longitude >= -60.0) && (longitude <= -40.0) -> { longitude += 60.0; "G" }
+ (longitude >= -40.0) && (longitude <= -20.0) -> { longitude += 40.0; "H" }
+ (longitude >= -20.0) && (longitude <= 0.0) -> { longitude += 20.0; "I" }
+ (longitude >= 0.0) && (longitude <= 20.0) -> "J"
+ (longitude >= 20.0) && (longitude <= 40.0) -> { longitude -= 20.0; "K" }
+ (longitude >= 40.0) && (longitude <= 60.0) -> { longitude -= 40.0; "L" }
+ (longitude >= 60.0) && (longitude <= 80.0) -> { longitude -= 60.0; "M" }
+ (longitude >= 80.0) && (longitude <= 100.0) -> { longitude -= 80.0; "N" }
+ (longitude >= 100.0) && (longitude <= 120.0) -> { longitude -= 100.0; "O" }
+ (longitude >= 120.0) && (longitude <= 140.0) -> { longitude -= 120.0; "P" }
+ (longitude >= 140.0) && (longitude <= 160.0) -> { longitude -= 140.0; "Q" }
+ (longitude >= 160.0) && (longitude <= 180.0) -> { longitude -= 160.0; "R" }
+ else -> { longitude = 0.0; " " }
+ }
+ val str2 = when {
+ ((longitude >= 0.0) && (longitude <= 2.0)) || ((longitude >= -20.0) && (longitude <= -18.0)) -> { d = longitude * 60.0; "0" }
+ ((longitude >= 2.0) && (longitude <= 4.0)) || ((longitude >= -18.0) && (longitude <= -16.0)) -> { d = (longitude - 2.0) * 60.0; "1" }
+ ((longitude >= 4.0) && (longitude <= 6.0)) || ((longitude >= -16.0) && (longitude <= -14.0)) -> { d = (longitude - 4.0) * 60.0; "2" }
+ ((longitude >= 6.0) && (longitude <= 8.0)) || ((longitude >= -14.0) && (longitude <= -12.0)) -> { d = (longitude - 6.0) * 60.0; "3" }
+ ((longitude >= 8.0) && (longitude <= 10.0)) || ((longitude >= -12.0) && (longitude <= -10.0)) -> { d = (longitude - 8.0) * 60.0; "4" }
+ ((longitude >= 10.0) && (longitude <= 12.0)) || ((longitude >= -10.0) && (longitude <= -8.0)) -> { d = (longitude - 10.0) * 60.0; "5" }
+ ((longitude >= 12.0) && (longitude <= 14.0)) || ((longitude >= -8.0) && (longitude <= -6.0)) -> { d = (longitude - 12.0) * 60.0; "6" }
+ ((longitude >= 14.0) && (longitude <= 16.0)) || ((longitude >= -6.0) && (longitude <= -4.0)) -> { d = (longitude - 14.0) * 60.0; "7" }
+ ((longitude >= 16.0) && (longitude <= 18.0)) || ((longitude >= -4.0) && (longitude <= -2.0)) -> { d = (longitude - 16.0) * 60.0; "8" }
+ ((longitude >= 18.0) && (longitude <= 20.0)) || ((longitude >= -2.0) && (longitude <= 0.0)) -> { d = (longitude - 18.0) * 60.0; "9" }
+ else -> { d = 0.0; " " }
+ }
+ val str3 = when {
+ ((d >= 0.0) && (d <= 5.0)) || ((d >= -120.0) && (d <= -115.0)) -> { longitude = d * 60.0; "a" }
+ ((d >= 5.0) && (d <= 10.0)) || ((d >= -115.0) && (d <= -110.0)) -> { longitude = (d - 5.0) * 60.0; "b" }
+ ((d >= 10.0) && (d <= 15.0)) || ((d >= -110.0) && (d <= -105.0)) -> { longitude = (d - 10.0) * 60.0; "c" }
+ ((d >= 15.0) && (d <= 20.0)) || ((d >= -105.0) && (d <= -100.0)) -> { longitude = (d - 15.0) * 60.0; "d" }
+ ((d >= 20.0) && (d <= 25.0)) || ((d >= -100.0) && (d <= -95.0)) -> { longitude = (d - 20.0) * 60.0; "e" }
+ ((d >= 25.0) && (d <= 30.0)) || ((d >= -95.0) && (d <= -90.0)) -> { longitude = (d - 25.0) * 60.0; "f" }
+ ((d >= 30.0) && (d <= 35.0)) || ((d >= -90.0) && (d <= -85.0)) -> { longitude = (d - 30.0) * 60.0; "g" }
+ ((d >= 35.0) && (d <= 40.0)) || ((d >= -85.0) && (d <= -80.0)) -> { longitude = (d - 35.0) * 60.0; "h" }
+ ((d >= 40.0) && (d <= 45.0)) || ((d >= -80.0) && (d <= -75.0)) -> { longitude = (d - 40.0) * 60.0; "i" }
+ ((d >= 45.0) && (d <= 50.0)) || ((d >= -75.0) && (d <= -70.0)) -> { longitude = (d - 45.0) * 60.0; "j" }
+ ((d >= 50.0) && (d <= 55.0)) || ((d >= -70.0) && (d <= -65.0)) -> { longitude = (d - 50.0) * 60.0; "k" }
+ ((d >= 55.0) && (d <= 60.0)) || ((d >= -65.0) && (d <= -60.0)) -> { longitude = (d - 55.0) * 60.0; "l" }
+ ((d >= 60.0) && (d <= 65.0)) || ((d >= -60.0) && (d <= -55.0)) -> { longitude = (d - 60.0) * 60.0; "m" }
+ ((d >= 65.0) && (d <= 70.0)) || ((d >= -55.0) && (d <= -50.0)) -> { longitude = (d - 65.0) * 60.0; "n" }
+ ((d >= 70.0) && (d <= 75.0)) || ((d >= -50.0) && (d <= -45.0)) -> { longitude = (d - 70.0) * 60.0; "o" }
+ ((d >= 75.0) && (d <= 80.0)) || ((d >= -45.0) && (d <= -40.0)) -> { longitude = (d - 75.0) * 60.0; "p" }
+ ((d >= 80.0) && (d <= 85.0)) || ((d >= -40.0) && (d <= -35.0)) -> { longitude = (d - 80.0) * 60.0; "q" }
+ ((d >= 85.0) && (d <= 90.0)) || ((d >= -35.0) && (d <= -30.0)) -> { longitude = (d - 85.0) * 60.0; "r" }
+ ((d >= 90.0) && (d <= 95.0)) || ((d >= -30.0) && (d <= -25.0)) -> { longitude = (d - 90.0) * 60.0; "s" }
+ ((d >= 95.0) && (d <= 100.0)) || ((d >= -25.0) && (d <= -20.0)) -> { longitude = (d - 95.0) * 60.0; "t" }
+ ((d >= 100.0) && (d <= 105.0)) || ((d >= -20.0) && (d <= -15.0)) -> { longitude = (d - 100.0) * 60.0; "u" }
+ ((d >= 105.0) && (d <= 110.0)) || ((d >= -15.0) && (d <= -10.0)) -> { longitude = (d - 105.0) * 60.0; "v" }
+ ((d >= 110.0) && (d <= 115.0)) || ((d >= -10.0) && (d <= -5.0)) -> { longitude = (d - 110.0) * 60.0; "w" }
+ ((d >= 115.0) && (d <= 120.0)) || ((d >= -5.0) && (d <= 0.0)) -> { longitude = (d - 115.0) * 60.0; "x" }
+ else -> { longitude = 0.0; " " }
+ }
+ val str4 = when {
+ ((longitude >= 0.0) && (longitude <= 30.0)) || ((longitude >= -300.0) && (longitude <= -270.0)) -> "0"
+ ((longitude >= 30.0) && (longitude <= 60.0)) || ((longitude >= -270.0) && (longitude <= -240.0)) -> "1"
+ ((longitude >= 60.0) && (longitude <= 90.0)) || ((longitude >= -240.0) && (longitude <= -210.0)) -> "2"
+ ((longitude >= 90.0) && (longitude <= 120.0)) || ((longitude >= -210.0) && (longitude <= -180.0)) -> "3"
+ ((longitude >= 120.0) && (longitude <= 150.0)) || ((longitude >= -180.0) && (longitude <= -150.0)) -> "4"
+ ((longitude >= 150.0) && (longitude <= 180.0)) || ((longitude >= -150.0) && (longitude <= -120.0)) -> "5"
+ ((longitude >= 180.0) && (longitude <= 210.0)) || ((longitude >= -120.0) && (longitude <= -90.0)) -> "6"
+ ((longitude >= 210.0) && (longitude <= 240.0)) || ((longitude >= -90.0) && (longitude <= -60.0)) -> "7"
+ ((longitude >= 240.0) && (longitude <= 270.0)) || ((longitude >= -60.0) && (longitude <= -30.0)) -> "8"
+ ((longitude >= 270.0) && (longitude <= 300.0)) || ((longitude >= -30.0) && (longitude <= 0.0)) -> "9"
+ else -> " "
+ }
+ return listOf(str, str2, str3, str4)
+}
+
+// 照搬 612-914 行: 纬度 -> (10°区字母, 1°数字, 1'字母, 15"数字)
+private fun encodeLat(inputLat: Double): List {
+ var latitude = inputLat
+ var d2 = 0.0
+ var d3 = 0.0
+ val str5 = when {
+ (latitude >= -90.0) && (latitude <= -80.0) -> { d2 = latitude + 90.0; "A" }
+ (latitude >= -80.0) && (latitude <= -70.0) -> { d2 = latitude + 80.0; "B" }
+ (latitude >= -70.0) && (latitude <= -60.0) -> { d2 = latitude + 70.0; "C" }
+ (latitude >= -60.0) && (latitude <= -50.0) -> { d2 = latitude + 60.0; "D" }
+ (latitude >= -50.0) && (latitude <= -40.0) -> { d2 = latitude + 50.0; "E" }
+ (latitude >= -40.0) && (latitude <= -30.0) -> { d2 = latitude + 40.0; "F" }
+ (latitude >= -30.0) && (latitude <= -20.0) -> { d2 = latitude + 30.0; "G" }
+ (latitude >= -20.0) && (latitude <= -10.0) -> { d2 = latitude + 20.0; "H" }
+ (latitude >= -10.0) && (latitude <= 0.0) -> { d2 = latitude + 10.0; "I" }
+ (latitude >= 0.0) && (latitude <= 10.0) -> { d2 = latitude; "J" }
+ (latitude >= 10.0) && (latitude <= 20.0) -> { d2 = latitude - 10.0; "K" }
+ (latitude >= 20.0) && (latitude <= 30.0) -> { d2 = latitude - 20.0; "L" }
+ (latitude >= 30.0) && (latitude <= 40.0) -> { d2 = latitude - 30.0; "M" }
+ (latitude >= 40.0) && (latitude <= 50.0) -> { d2 = latitude - 40.0; "N" }
+ (latitude >= 50.0) && (latitude <= 60.0) -> { d2 = latitude - 50.0; "O" }
+ (latitude >= 60.0) && (latitude <= 70.0) -> { d2 = latitude - 60.0; "P" }
+ (latitude >= 70.0) && (latitude <= 80.0) -> { d2 = latitude - 70.0; "Q" }
+ (latitude >= 80.0) && (latitude <= 90.0) -> { d2 = latitude - 80.0; "R" }
+ else -> { d2 = 0.0; " " }
+ }
+ var str6 = " "
+ when {
+ ((d2 >= 0.0) && (d2 <= 1.0)) || ((d2 >= -10.0) && (d2 <= -9.0)) -> { d3 = d2 * 60.0; str6 = "0" }
+ ((d2 >= 1.0) && (d2 <= 2.0)) || ((d2 >= -9.0) && (d2 <= -8.0)) -> { d3 = (d2 - 1.0) * 60.0; str6 = "1" }
+ ((d2 >= 2.0) && (d2 <= 3.0)) || ((d2 >= -8.0) && (d2 <= -7.0)) -> { d3 = (d2 - 2.0) * 60.0; str6 = "2" }
+ ((d2 >= 3.0) && (d2 <= 4.0)) || ((d2 >= -7.0) && (d2 <= -6.0)) -> { d3 = (d2 - 3.0) * 60.0; str6 = "3" }
+ ((d2 >= 4.0) && (d2 <= 5.0)) || ((d2 >= -6.0) && (d2 <= -5.0)) -> { d3 = (d2 - 4.0) * 60.0; str6 = "4" }
+ ((d2 >= 5.0) && (d2 <= 6.0)) || ((d2 >= -5.0) && (d2 <= -4.0)) -> { d3 = (d2 - 5.0) * 60.0; str6 = "5" }
+ ((d2 >= 6.0) && (d2 <= 7.0)) || ((d2 >= -4.0) && (d2 <= -3.0)) -> { d3 = (d2 - 6.0) * 60.0; str6 = "6" }
+ ((d2 >= 7.0) && (d2 <= 8.0)) || ((d2 >= -3.0) && (d2 <= -2.0)) -> { d3 = (d2 - 7.0) * 60.0; str6 = "7" }
+ ((d2 >= 8.0) && (d2 <= 9.0)) || ((d2 >= -2.0) && (d2 <= -1.0)) -> { d3 = (d2 - 8.0) * 60.0; str6 = "8" }
+ ((d2 >= 9.0) && (d2 <= 10.0)) || ((d2 >= -1.0) && (d2 <= 0.0)) -> { d3 = (d2 - 9.0) * 60.0; str6 = "9" }
+ }
+ val str38 = when {
+ ((d3 >= 0.0) && (d3 <= 2.5)) || ((d3 >= -60.0) && (d3 <= -57.5)) -> { d2 = d3 * 60.0; "a" }
+ ((d3 >= 2.5) && (d3 <= 5.0)) || ((d3 >= -57.5) && (d3 <= -55.0)) -> { d2 = (d3 - 2.5) * 60.0; "b" }
+ ((d3 >= 5.0) && (d3 <= 7.5)) || ((d3 >= -55.0) && (d3 <= -52.5)) -> { d2 = (d3 - 5.0) * 60.0; "c" }
+ ((d3 >= 7.5) && (d3 <= 10.0)) || ((d3 >= -52.5) && (d3 <= -50.0)) -> { d2 = (d3 - 7.5) * 60.0; "d" }
+ ((d3 >= 10.0) && (d3 <= 12.5)) || ((d3 >= -50.0) && (d3 <= -47.5)) -> { d2 = (d3 - 10.0) * 60.0; "e" }
+ ((d3 >= 12.5) && (d3 <= 15.0)) || ((d3 >= -47.5) && (d3 <= -45.0)) -> { d2 = (d3 - 12.5) * 60.0; "f" }
+ ((d3 >= 15.0) && (d3 <= 17.5)) || ((d3 >= -45.0) && (d3 <= -42.5)) -> { d2 = (d3 - 15.0) * 60.0; "g" }
+ ((d3 >= 17.5) && (d3 <= 20.0)) || ((d3 >= -42.5) && (d3 <= -40.0)) -> { d2 = (d3 - 17.5) * 60.0; "h" }
+ ((d3 >= 20.0) && (d3 <= 22.5)) || ((d3 >= -40.0) && (d3 <= -37.5)) -> { d2 = (d3 - 20.0) * 60.0; "i" }
+ ((d3 >= 22.5) && (d3 <= 25.0)) || ((d3 >= -37.5) && (d3 <= -35.0)) -> { d2 = (d3 - 22.5) * 60.0; "j" }
+ ((d3 >= 25.0) && (d3 <= 27.5)) || ((d3 >= -35.0) && (d3 <= -32.5)) -> { d2 = (d3 - 25.0) * 60.0; "k" }
+ ((d3 >= 27.5) && (d3 <= 30.0)) || ((d3 >= -32.5) && (d3 <= -30.0)) -> { d2 = (d3 - 27.5) * 60.0; "l" }
+ ((d3 >= 30.0) && (d3 <= 32.5)) || ((d3 >= -30.0) && (d3 <= -27.5)) -> { d2 = (d3 - 30.0) * 60.0; "m" }
+ ((d3 >= 32.5) && (d3 <= 35.0)) || ((d3 >= -27.5) && (d3 <= -25.0)) -> { d2 = (d3 - 32.5) * 60.0; "n" }
+ ((d3 >= 35.0) && (d3 <= 37.5)) || ((d3 >= -25.0) && (d3 <= -22.5)) -> { d2 = (d3 - 35.0) * 60.0; "o" }
+ ((d3 >= 37.5) && (d3 <= 40.0)) || ((d3 >= -22.5) && (d3 <= -20.0)) -> { d2 = (d3 - 37.5) * 60.0; "p" }
+ ((d3 >= 40.0) && (d3 <= 42.5)) || ((d3 >= -20.0) && (d3 <= -17.5)) -> { d2 = (d3 - 40.0) * 60.0; "q" }
+ ((d3 >= 42.5) && (d3 <= 45.0)) || ((d3 >= -17.5) && (d3 <= -15.0)) -> { d2 = (d3 - 42.5) * 60.0; "r" }
+ ((d3 >= 45.0) && (d3 <= 47.5)) || ((d3 >= -15.0) && (d3 <= -12.5)) -> { d2 = (d3 - 45.0) * 60.0; "s" }
+ ((d3 >= 47.5) && (d3 <= 50.0)) || ((d3 >= -12.5) && (d3 <= -10.0)) -> { d2 = (d3 - 47.5) * 60.0; "t" }
+ ((d3 >= 50.0) && (d3 <= 52.5)) || ((d3 >= -10.0) && (d3 <= -7.5)) -> { d2 = (d3 - 50.0) * 60.0; "u" }
+ ((d3 >= 52.5) && (d3 <= 55.0)) || ((d3 >= -7.5) && (d3 <= -5.0)) -> { d2 = (d3 - 52.5) * 60.0; "v" }
+ ((d3 >= 55.0) && (d3 <= 57.5)) || ((d3 >= -5.0) && (d3 <= -2.5)) -> { d2 = (d3 - 55.0) * 60.0; "w" }
+ ((d3 >= 57.5) && (d3 <= 60.0)) || ((d3 >= -2.5) && (d3 <= 0.0)) -> { d2 = (d3 - 57.5) * 60.0; "x" }
+ else -> { d2 = 0.0; " " }
+ }
+ val str9 = when {
+ ((d2 >= 0.0) && (d2 <= 15.0)) || ((d2 >= -150.0) && (d2 <= -135.0)) -> "0"
+ ((d2 >= 15.0) && (d2 <= 30.0)) || ((d2 >= -135.0) && (d2 <= -120.0)) -> "1"
+ ((d2 >= 30.0) && (d2 <= 45.0)) || ((d2 >= -120.0) && (d2 <= -105.0)) -> "2"
+ ((d2 >= 45.0) && (d2 <= 60.0)) || ((d2 >= -105.0) && (d2 <= -90.0)) -> "3"
+ ((d2 >= 60.0) && (d2 <= 75.0)) || ((d2 >= -90.0) && (d2 <= -75.0)) -> "4"
+ ((d2 >= 75.0) && (d2 <= 90.0)) || ((d2 >= -75.0) && (d2 <= -60.0)) -> "5"
+ ((d2 >= 90.0) && (d2 <= 105.0)) || ((d2 >= -60.0) && (d2 <= -45.0)) -> "6"
+ ((d2 >= 105.0) && (d2 <= 120.0)) || ((d2 >= -45.0) && (d2 <= -30.0)) -> "7"
+ ((d2 >= 120.0) && (d2 <= 135.0)) || ((d2 >= -30.0) && (d2 <= -15.0)) -> "8"
+ ((d2 >= 135.0) && (d2 <= 150.0)) || ((d2 >= -15.0) && (d2 <= 0.0)) -> "9"
+ else -> " "
+ }
+ return listOf(str5, str6, str38, str9)
+}
+
+/**
+ * 照搬 917-1283 行: 九宫格 parseInt3 五分支(内部/西界/东界/北界/南界 + 四角)。
+ * 返回 9 格文本: [上左, 上中, 上右, 左中, 中央, 右中, 下左, 下中, 下右]。
+ */
+private fun buildGrids(str: String, str5: String, str2: String, str6: String, str3: String, str38: String): List {
+ val parseInt = str2.toInt()
+ val parseInt2 = str6.toInt()
+ val str39 = str + str5
+ val str40 = str2 + str6
+ val parseInt3 = str40.toInt()
+ val str41 = str39 + str40
+ val g = MutableList(9) { "" }
+ fun fmt2(n: Int) = if (n <= 9) "0$n" else n.toString()
+ if ((parseInt > 0) && (parseInt < 9) && (parseInt2 > 0) && (parseInt2 < 9)) {
+ // 内部: 数字对 ±1
+ val i7 = parseInt3 + 1
+ val i8 = i7 - 10
+ val valueOf9 = fmt2(i8)
+ val str11 = i7.toString()
+ val valueOf18 = (i7 + 10).toString()
+ val i9 = parseInt3 - 10
+ val valueOf10 = fmt2(i9)
+ val valueOf19 = (parseInt3 + 10).toString()
+ val i10 = parseInt3 - 1
+ val i11 = i10 - 10
+ val valueOf11 = fmt2(i11)
+ val str14 = i10.toString()
+ val str15 = (i10 + 10).toString()
+ g[0] = str39 + valueOf9
+ g[1] = str39 + str11
+ g[2] = str39 + valueOf18
+ g[3] = str39 + valueOf10
+ g[4] = str41
+ g[5] = str39 + valueOf19
+ g[6] = str39 + valueOf11
+ g[7] = str39 + str14
+ g[8] = str39 + str15
+ } else if ((parseInt == 0) && (parseInt2 > 0) && (parseInt2 < 9)) {
+ // 西边界: 经度 0 -> 9, 经度字母 -1
+ val str43 = (str[0] - 1).toString() + str5
+ val str44 = "9" + (parseInt2 + 1)
+ val i12 = parseInt3 + 1
+ val valueOf7 = fmt2(i12)
+ val str12 = (i12 + 10).toString()
+ val sb4 = "9" + parseInt2
+ val valueOf20 = (parseInt3 + 10).toString()
+ val str46 = "9" + (parseInt2 - 1)
+ val i13 = parseInt3 - 1
+ val valueOf8 = fmt2(i13)
+ val str15 = (i13 + 10).toString()
+ g[0] = str43 + str44
+ g[1] = str39 + valueOf7
+ g[2] = str39 + str12
+ g[3] = str43 + sb4
+ g[4] = str41
+ g[5] = str39 + valueOf20
+ g[6] = str43 + str46
+ g[7] = str39 + valueOf8
+ g[8] = str39 + str15
+ } else if ((parseInt == 9) && (parseInt2 > 0) && (parseInt2 < 9)) {
+ // 东边界: 经度 9 -> 0, 经度字母 +1
+ val str47 = (str[0] + 1).toString() + str5
+ val i14 = parseInt3 + 1
+ val valueOf21 = (i14 - 10).toString()
+ val valueOf22 = i14.toString()
+ val str48 = "0" + (parseInt2 + 1)
+ val valueOf23 = (parseInt3 - 10).toString()
+ val str49 = "0" + parseInt2
+ val i15 = parseInt3 - 1
+ val valueOf24 = (i15 - 10).toString()
+ val valueOf25 = i15.toString()
+ val str15 = "0" + (parseInt2 - 1)
+ g[0] = str39 + valueOf21
+ g[1] = str39 + valueOf22
+ g[2] = str47 + str48
+ g[3] = str39 + valueOf23
+ g[4] = str41
+ g[5] = str47 + str49
+ g[6] = str39 + valueOf24
+ g[7] = str39 + valueOf25
+ g[8] = str47 + str15
+ } else if ((parseInt < 9) && (parseInt > 0) && (parseInt2 == 9)) {
+ // 北边界: 纬度 9 -> 0, 纬度字母 +1
+ val str50 = str + (str5[0] + 1).toString()
+ val i16 = parseInt3 - 9
+ val i17 = i16 - 10
+ val valueOf4 = fmt2(i17)
+ val valueOf26 = i16.toString()
+ val valueOf27 = (i16 + 10).toString()
+ val i18 = parseInt3 - 10
+ val valueOf5 = fmt2(i18)
+ val valueOf28 = (parseInt3 + 10).toString()
+ val i19 = parseInt3 - 1
+ val i20 = i19 - 10
+ val valueOf6 = fmt2(i20)
+ val str14 = i19.toString()
+ val str15 = (i19 + 10).toString()
+ g[0] = str39 + valueOf4
+ g[1] = str50 + valueOf26
+ g[2] = str39 + valueOf27
+ g[3] = str39 + valueOf5
+ g[4] = str41
+ g[5] = str39 + valueOf28
+ g[6] = str39 + valueOf6
+ g[7] = str39 + str14
+ g[8] = str39 + str15
+ } else if ((parseInt < 9) && (parseInt > 0) && (parseInt2 == 0)) {
+ // 南边界: 纬度 0 -> 9, 纬度字母 -1
+ val str52 = str + (str5[0] - 1).toString()
+ val i21 = parseInt3 + 1
+ val i22 = i21 - 10
+ val valueOf = fmt2(i22)
+ val valueOf29 = i21.toString()
+ val valueOf30 = (i21 + 10).toString()
+ val i23 = parseInt3 - 10
+ val valueOf2 = fmt2(i23)
+ val valueOf31 = (parseInt3 + 10).toString()
+ val i24 = parseInt3 - 1
+ val valueOf3 = fmt2(i24)
+ val str14 = (i24 + 10).toString()
+ val str15 = (i24 + 20).toString()
+ g[0] = str39 + valueOf
+ g[1] = str39 + valueOf29
+ g[2] = str39 + valueOf30
+ g[3] = str39 + valueOf2
+ g[4] = str41
+ g[5] = str39 + valueOf31
+ g[6] = str52 + valueOf3
+ g[7] = str52 + str14
+ g[8] = str52 + str15
+ } else if (parseInt3 == 0) {
+ // 四角 00: 经纬度数字均 -1 进位
+ val v32 = (str[0] - 1).toString()
+ val v33 = (str5[0] - 1).toString()
+ g[0] = v32 + str5 + "91"
+ g[1] = str39 + "01"
+ g[2] = str39 + "11"
+ g[3] = v32 + str5 + "90"
+ g[4] = str41
+ g[5] = v32 + str5 + "10"
+ g[6] = v32 + v33 + "99"
+ g[7] = str + v33 + "09"
+ g[8] = str + v33 + "19"
+ } else if (parseInt3 == 9) {
+ // 四角 09: 经度 -1, 纬度 +1
+ val v34 = (str[0] - 1).toString()
+ val v35 = (str5[0] + 1).toString()
+ g[0] = v34 + v35 + "90"
+ g[1] = str + v35 + "00"
+ g[2] = str + v35 + "10"
+ g[3] = v34 + str5 + "99"
+ g[4] = str41
+ g[5] = v34 + str5 + "19"
+ g[6] = v34 + str5 + "98"
+ g[7] = v34 + str5 + "08"
+ g[8] = v34 + str5 + "18"
+ } else if (parseInt3 == 99) {
+ // 四角 99: 经纬度数字均 +1 进位
+ val v36 = (str[0] + 1).toString()
+ val v37 = (str5[0] + 1).toString()
+ g[0] = str + v37 + "80"
+ g[1] = str + v37 + "90"
+ g[2] = v36 + v37 + "00"
+ g[3] = str39 + "89"
+ g[4] = str41
+ g[5] = v36 + str5 + "09"
+ g[6] = str39 + "88"
+ g[7] = str39 + "98"
+ g[8] = v36 + str5 + "08"
+ } else if (parseInt3 == 90) {
+ // 四角 90: 经度 +1, 纬度 -1
+ val v38 = (str[0] + 1).toString()
+ val v39 = (str5[0] - 1).toString()
+ g[0] = str39 + "81"
+ g[1] = str39 + "91"
+ g[2] = v38 + str5 + "01"
+ g[3] = str39 + "80"
+ g[4] = str41
+ g[5] = v38 + str5 + "00"
+ g[6] = str + v39 + "89"
+ g[7] = str + v39 + "99"
+ g[8] = v38 + v39 + "09"
+ }
+ return g
+}
diff --git a/feature/roaming/src/main/res/drawable/roam_gps_green.png b/feature/roaming/src/main/res/drawable/roam_gps_green.png
new file mode 100644
index 00000000..2202aac6
Binary files /dev/null and b/feature/roaming/src/main/res/drawable/roam_gps_green.png differ
diff --git a/feature/roaming/src/main/res/drawable/roam_gps_red.png b/feature/roaming/src/main/res/drawable/roam_gps_red.png
new file mode 100644
index 00000000..c0af314f
Binary files /dev/null and b/feature/roaming/src/main/res/drawable/roam_gps_red.png differ
diff --git a/feature/roaming/src/main/res/drawable/roam_pnt.png b/feature/roaming/src/main/res/drawable/roam_pnt.png
new file mode 100644
index 00000000..8a1ef8bc
Binary files /dev/null and b/feature/roaming/src/main/res/drawable/roam_pnt.png differ
diff --git a/feature/roaming/src/test/java/com/rtbishop/look4sat/feature/roaming/RoamingStateTest.kt b/feature/roaming/src/test/java/com/rtbishop/look4sat/feature/roaming/RoamingStateTest.kt
new file mode 100644
index 00000000..1297fda8
--- /dev/null
+++ b/feature/roaming/src/test/java/com/rtbishop/look4sat/feature/roaming/RoamingStateTest.kt
@@ -0,0 +1,124 @@
+/*
+ * Look4Sat. Amateur radio satellite tracker and pass predictor.
+ * Copyright (C) 2019-2026 Arty Bishop and contributors.
+ *
+ * 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 .
+ */
+package com.rtbishop.look4sat.feature.roaming
+
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+class RoamingStateTest {
+
+ // 用户实测坐标 (QTH定位器 2.0 成品截图): 22.314066 / 108.706575
+ private fun stateOf(lat: Double, lon: Double) =
+ roamingStateFromLocation(lat, lon, System.currentTimeMillis(), "21:")
+
+ @Test
+ fun `user coordinates produce OL42ih45`() {
+ val state = stateOf(22.314066, 108.706575)
+ assertEquals("OL42ih45", state.loc)
+ }
+
+ @Test
+ fun `red marker from ih pair matches reference lookup`() {
+ val state = stateOf(22.314066, 108.706575)
+ // 成品查表: 经度第3对 'i' -> leftMargin 65dp, 纬度第3对 'h' -> topMargin 137dp
+ assertEquals(65, state.markerLeft)
+ assertEquals(137, state.markerTop)
+ }
+
+ @Test
+ fun `grid nine from OL42 matches reference`() {
+ val state = stateOf(22.314066, 108.706575)
+ val expected = listOf(
+ "OL33", "OL43", "OL53",
+ "OL32", "OL42", "OL52",
+ "OL31", "OL41", "OL51"
+ )
+ assertEquals(expected, state.grids)
+ }
+
+ @Test
+ fun `latitude dms formatting matches reference`() {
+ val state = stateOf(22.314066, 108.706575)
+ assertEquals("纬度 22° 18' 50\" N", state.latLabel)
+ assertEquals("22.314066° ", state.latValue)
+ assertEquals("经度 108° 42' 23\" E", state.lonLabel)
+ assertEquals("108.706575° ", state.lonValue)
+ }
+
+ @Test
+ fun `time is hour prefix plus fix minutes`() {
+ // fixTime = 2026-08-03 21:12:13 UTC+8 -> minutes 12
+ val fix = 1785820333000L // 2026-08-03 21:12:13 +0800
+ val state = roamingStateFromLocation(22.314066, 108.706575, fix, "21:")
+ assertEquals("21:12", state.time)
+ }
+
+ @Test
+ fun `west edge borrows lon letter`() {
+ // 经度 0.5 纬度 22.314066: 数字对 02, 西边界 parseInt==0
+ val state = stateOf(22.314066, 0.5)
+ assertEquals(8, state.loc.length)
+ // 左列经度 0->9, 经度字母 J-1=I: IL92
+ assertEquals("IL92", state.grids[3])
+ }
+
+ @Test
+ fun `north edge carries lat letter`() {
+ // 纬度 29.5 经度 108.706575: 数字对 49? -> 纬度数字 9 -> 北边界
+ val state = stateOf(29.5, 108.706575)
+ assertEquals(8, state.loc.length)
+ // 上排纬度 +1 -> 0, 纬度字母 +1 (M)
+ assertEquals("OM40", state.grids[1])
+ }
+
+ @Test
+ fun `east edge carries lon letter`() {
+ // 经度 119.5 纬度 22.314066: 经度数字 9 -> 东边界
+ val state = stateOf(22.314066, 119.5)
+ assertEquals(8, state.loc.length)
+ // 右上 经度 9->0, 经度字母 O+1=P, 纬度 2+1=3: PL03
+ assertEquals("PL03", state.grids[2])
+ }
+
+ @Test
+ fun `south edge borrows lat letter`() {
+ // 纬度 0.5 经度 108.706575: 纬度数字 0 -> 南边界
+ val state = stateOf(0.5, 108.706575)
+ assertEquals(8, state.loc.length)
+ // 下中 纬度 0->9, 纬度字母 J-1=I: OI49
+ assertEquals("OI49", state.grids[7])
+ }
+
+ @Test
+ fun `boundary values wrap like reference`() {
+ // (90, 180) -> RR99xx99 (成品区间查表行为)
+ val state = stateOf(90.0, 180.0)
+ assertEquals("RR99xx99", state.loc)
+ }
+
+ @Test
+ fun `gps state after fix matches showLocation`() {
+ val state = stateOf(22.314066, 108.706575)
+ assertEquals(true, state.gpsOn)
+ assertEquals(false, state.gpsOff)
+ assertEquals(false, state.showSettings)
+ assertEquals(false, state.showProgress)
+ assertEquals(false, state.showNotice)
+ assertEquals(true, state.showDate)
+ }
+}
diff --git a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsDialog.kt b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsDialog.kt
index c0897b4d..8779c271 100644
--- a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsDialog.kt
+++ b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsDialog.kt
@@ -30,6 +30,8 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.FilterChip
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
@@ -41,11 +43,13 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.rtbishop.look4sat.core.domain.model.RCSettings
+import com.rtbishop.look4sat.core.domain.source.Sources
import com.rtbishop.look4sat.core.domain.model.RadioControlSettings
import com.rtbishop.look4sat.core.presentation.CardButton
import com.rtbishop.look4sat.core.presentation.LocalSpacing
@@ -203,6 +207,17 @@ fun DataSourcesDialog(
singleLine = true,
modifier = Modifier.fillMaxWidth(),
enabled = isEnabledCustomTle.value,
+ trailingIcon = {
+ IconButton(
+ onClick = { urlTle.value = Sources.defaultTleUrl },
+ enabled = isEnabledCustomTle.value
+ ) {
+ Icon(
+ painter = painterResource(id = R.drawable.ic_reset),
+ contentDescription = stringResource(id = R.string.prefs_data_reset_url)
+ )
+ }
+ },
)
Spacer(modifier = Modifier.height(6.dp))
Row(
@@ -232,6 +247,17 @@ fun DataSourcesDialog(
singleLine = true,
modifier = Modifier.fillMaxWidth(),
enabled = isEnabledCustomTransceivers.value,
+ trailingIcon = {
+ IconButton(
+ onClick = { urlTransceivers.value = Sources.defaultTransceiversUrl },
+ enabled = isEnabledCustomTransceivers.value
+ ) {
+ Icon(
+ painter = painterResource(id = R.drawable.ic_reset),
+ contentDescription = stringResource(id = R.string.prefs_data_reset_url)
+ )
+ }
+ },
)
Spacer(modifier = Modifier.height(12.dp))
}
diff --git a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsScreen.kt b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsScreen.kt
index e4c9e2b0..f5a33c29 100644
--- a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsScreen.kt
+++ b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsScreen.kt
@@ -22,39 +22,70 @@ import android.os.Build
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.clickable
+import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.heightIn
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.gestures.detectDragGestures
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.rememberLazyListState
+import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.grid.GridCells
+import android.content.Context
import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
+import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Switch
+import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.Text
+import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.mutableStateListOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
+import kotlin.math.roundToInt
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
+import androidx.compose.ui.zIndex
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -72,6 +103,8 @@ import com.rtbishop.look4sat.core.presentation.R
import com.rtbishop.look4sat.core.presentation.ScreenColumn
import com.rtbishop.look4sat.core.presentation.TopBar
import com.rtbishop.look4sat.core.presentation.infiniteMarquee
+import com.rtbishop.look4sat.core.presentation.defaultScreenOrder
+import com.rtbishop.look4sat.core.presentation.defaultSubMenuOrder
import com.rtbishop.look4sat.core.presentation.isVerticalLayout
import java.text.SimpleDateFormat
import java.util.Date
@@ -84,6 +117,63 @@ fun SettingsDestination() {
val viewModel: SettingsViewModel = viewModel(factory = SettingsViewModel.factory(container))
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
SettingsScreen(uiState, viewModel::onAction)
+
+ // WaveLog 网格不一致确认弹窗(4.5.2)
+ val gridConfirm = viewModel.gridConfirm
+ if (gridConfirm != null) {
+ AlertDialog(
+ onDismissRequest = { viewModel.resolveGridConfirm(false) },
+ title = { Text(text = stringResource(id = R.string.wavelog_title)) },
+ text = {
+ Text(
+ text = stringResource(
+ id = R.string.wavelog_grid_mismatch,
+ gridConfirm.userGrid.take(4),
+ gridConfirm.stationGrid.take(4)
+ )
+ )
+ },
+ confirmButton = {
+ TextButton(onClick = { viewModel.resolveGridConfirm(true) }) {
+ Text(text = stringResource(id = R.string.wavelog_ignore))
+ }
+ },
+ dismissButton = {
+ TextButton(onClick = { viewModel.resolveGridConfirm(false) }) {
+ Text(text = stringResource(id = R.string.wavelog_cancel))
+ }
+ }
+ )
+ }
+
+ // WaveLog 错误详情弹窗(可一键复制)
+ val wavelogError = viewModel.wavelogError
+ if (wavelogError != null) {
+ AlertDialog(
+ onDismissRequest = { viewModel.wavelogError = null },
+ title = { Text(text = stringResource(id = R.string.wavelog_title)) },
+ text = {
+ Text(
+ text = wavelogError,
+ fontSize = 13.sp
+ )
+ },
+ confirmButton = {
+ TextButton(onClick = {
+ val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as android.content.ClipboardManager
+ clipboard.setPrimaryClip(android.content.ClipData.newPlainText("WaveLog error", wavelogError))
+ viewModel.wavelogError = null
+ }) {
+ Text(text = stringResource(id = R.string.wavelog_copy))
+ }
+ },
+ dismissButton = {
+ TextButton(onClick = { viewModel.wavelogError = null }) {
+ Text(text = stringResource(id = R.string.btn_cancel))
+ }
+ }
+ )
+ }
}
@Composable
@@ -299,6 +389,18 @@ private fun SettingsScreen(uiState: SettingsState, onAction: (SettingsAction) ->
)
}
item { OtherCard(uiState.otherSettings, onAction) }
+ item { WavelogCard(uiState.otherSettings, onAction) }
+ item {
+ UiSettingsCard(
+ hiddenScreens = uiState.otherSettings.hiddenScreens,
+ screenOrder = uiState.otherSettings.screenOrder,
+ subMenuOrder = uiState.otherSettings.subMenuOrder,
+ onToggle = { name -> onAction(SettingsAction.ToggleScreen(name)) },
+ onReorder = { order -> onAction(SettingsAction.ReorderScreens(order)) },
+ onResetOrder = { onAction(SettingsAction.ResetMenuOrder) },
+ onUpdateMenu = { main, sub -> onAction(SettingsAction.UpdateMenuOrder(main, sub)) }
+ )
+ }
item { CardCredits() }
}
}
@@ -337,9 +439,11 @@ private fun LocationCard(
Text(text = formatUpdateTime(updateTime = settings.stationPos.timestamp))
Spacer(modifier = Modifier.height(2.dp))
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
- Text(text = "Lat: ${settings.stationPos.latitude}°")
- Text(text = "Lon: ${settings.stationPos.longitude}°")
- Text(text = "Qth: ${settings.stationPos.qthLocator}")
+ Text(text = stringResource(R.string.loc_lat_text, settings.stationPos.latitude))
+ Text(text = stringResource(R.string.loc_lon_text, settings.stationPos.longitude))
+ }
+ Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
+ Text(text = stringResource(R.string.loc_qth_text, settings.stationPos.qthLocator))
}
Spacer(modifier = Modifier.height(1.dp))
Row(horizontalArrangement = Arrangement.SpaceEvenly) {
@@ -484,11 +588,12 @@ private fun OtherCardPreview() = MainTheme {
@Composable
private fun OtherCard(settings: OtherSettings, onAction: (SettingsAction) -> Unit) {
ElevatedCard(
- modifier = Modifier
- .fillMaxWidth()
- .height(268.dp)
+ modifier = Modifier.fillMaxWidth()
) {
- Column(modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)) {
+ Column(
+ modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
+ verticalArrangement = Arrangement.spacedBy(4.dp)
+ ) {
Text(
text = stringResource(id = R.string.prefs_other_title),
color = MaterialTheme.colorScheme.primary
@@ -512,8 +617,295 @@ private fun OtherCard(settings: OtherSettings, onAction: (SettingsAction) -> Uni
}
}
+/**
+ * UI 设置卡片: 控制底部菜单栏各页面显示/隐藏。
+ * 顺序固定(卫星/过境/雷达/匹配/漫游/地图/设置), 关闭后其余自动靠拢;
+ * "设置"页固定显示(防止失去设置入口)。
+ */
+/** WaveLog 日志服务器设置卡片(4.5.2): 照用户截图布局(深色卡片/标签左输入右/按钮行) */
@Composable
-private fun SwitchRow(labelResId: Int, checked: Boolean, onCheckedChange: (Boolean) -> Unit) {
+private fun WavelogCard(
+ settings: OtherSettings,
+ onAction: (SettingsAction) -> Unit
+) {
+ ElevatedCard(modifier = Modifier.fillMaxWidth()) {
+ Column(
+ modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
+ verticalArrangement = Arrangement.spacedBy(4.dp)
+ ) {
+ Text(
+ text = stringResource(id = R.string.prefs_wavelog_title),
+ color = MaterialTheme.colorScheme.primary
+ )
+ OutlinedTextField(
+ value = settings.wavelogUrl,
+ onValueChange = {
+ onAction(SettingsAction.UpdateWavelogSettings(it, settings.wavelogApiKey, settings.wavelogStationId, settings.wavelogAutoUpload))
+ },
+ label = { Text(stringResource(id = R.string.prefs_wavelog_url_hint)) },
+ singleLine = true,
+ textStyle = LocalTextStyle.current.copy(fontSize = 14.sp),
+ modifier = Modifier.fillMaxWidth()
+ )
+ OutlinedTextField(
+ value = settings.wavelogApiKey,
+ onValueChange = {
+ onAction(SettingsAction.UpdateWavelogSettings(settings.wavelogUrl, it, settings.wavelogStationId, settings.wavelogAutoUpload))
+ },
+ label = { Text(stringResource(id = R.string.prefs_wavelog_key_hint)) },
+ singleLine = true,
+ textStyle = LocalTextStyle.current.copy(fontSize = 14.sp),
+ visualTransformation = PasswordVisualTransformation(),
+ modifier = Modifier.fillMaxWidth()
+ )
+ OutlinedTextField(
+ value = settings.wavelogStationId,
+ onValueChange = {
+ onAction(SettingsAction.UpdateWavelogSettings(settings.wavelogUrl, settings.wavelogApiKey, it, settings.wavelogAutoUpload))
+ },
+ label = { Text(stringResource(id = R.string.prefs_wavelog_station_hint)) },
+ singleLine = true,
+ textStyle = LocalTextStyle.current.copy(fontSize = 14.sp),
+ modifier = Modifier.fillMaxWidth()
+ )
+ SwitchRow(R.string.prefs_wavelog_auto, settings.wavelogAutoUpload) {
+ onAction(SettingsAction.UpdateWavelogSettings(settings.wavelogUrl, settings.wavelogApiKey, settings.wavelogStationId, it))
+ }
+ Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
+ CardButton(
+ onClick = { onAction(SettingsAction.TestWavelogConnection) },
+ text = stringResource(id = R.string.prefs_wavelog_test),
+ modifier = Modifier.weight(1f)
+ )
+ CardButton(
+ onClick = { onAction(SettingsAction.UploadWavelogQueue) },
+ text = stringResource(id = R.string.prefs_wavelog_upload),
+ modifier = Modifier.weight(1f)
+ )
+ }
+ }
+ }
+}
+
+@Composable
+private fun UiSettingsCard(
+ hiddenScreens: List,
+ screenOrder: List,
+ subMenuOrder: List,
+ onToggle: (String) -> Unit,
+ onReorder: (List) -> Unit,
+ onResetOrder: () -> Unit,
+ onUpdateMenu: (List, List) -> Unit
+) {
+ val screens = listOf(
+ R.string.nav_sat to "Satellites",
+ R.string.nav_pass to "Passes",
+ R.string.nav_radar to "Radar",
+ R.string.nav_mutual to "Mutual",
+ R.string.nav_roaming to "Roaming",
+ R.string.nav_cw to "CwDecode",
+ R.string.nav_log to "WavelogLog",
+ R.string.nav_amsat to "AMSAT",
+ R.string.nav_map to "Map",
+ R.string.nav_prefs to "Settings"
+ ) // name 必须与 Screen.screenId 一致 (R8 安全)
+ // 主菜单项: 排除更多菜单项, Settings 固定最后
+ val mainItems = remember(screens, screenOrder, subMenuOrder) {
+ val sub = subMenuOrder.ifEmpty { defaultSubMenuOrder }
+ screens.map { it.second }
+ .filter { it !in sub }
+ .sortedBy { name ->
+ screenOrder.indexOf(name).let { idx ->
+ if (idx != -1) idx else defaultScreenOrder.indexOf(name).let {
+ if (it != -1) it else Int.MAX_VALUE
+ }
+ }
+ }
+ .sortedWith(compareBy { if (it == "Settings") 1 else 0 })
+ }
+ // 更多菜单项
+ val subItems = remember(screens, subMenuOrder) {
+ val sub = subMenuOrder.ifEmpty { defaultSubMenuOrder }
+ sub.filter { s -> screens.any { (_, name) -> name == s } }
+ }
+ ElevatedCard(modifier = Modifier.fillMaxWidth()) {
+ Column(
+ modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
+ verticalArrangement = Arrangement.spacedBy(4.dp)
+ ) {
+ Text(
+ text = stringResource(id = R.string.prefs_ui_title),
+ color = MaterialTheme.colorScheme.primary
+ )
+ screens.forEach { (labelRes, name) ->
+ if (name == "Settings") {
+ // 设置页固定显示, 开关禁用
+ SwitchRow(labelRes, true, null)
+ } else {
+ SwitchRow(labelRes, name !in hiddenScreens) {
+ onToggle(name)
+ }
+ }
+ }
+ Text(
+ text = stringResource(id = R.string.prefs_ui_order_title),
+ color = MaterialTheme.colorScheme.primary
+ )
+ // 主菜单区(底部栏, 最多 5 项, 设置锁定最后)
+ Text(
+ text = stringResource(id = R.string.prefs_ui_main_title),
+ fontSize = 12.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant
+ )
+ DragOrderList(
+ items = mainItems,
+ labels = screens,
+ locked = setOf("Settings"),
+ moveLabel = stringResource(id = R.string.prefs_ui_move_out),
+ moveEnabled = { name -> name != "Settings" },
+ onMove = { name ->
+ onUpdateMenu(
+ mainItems.filter { it != name },
+ (subMenuOrder.ifEmpty { defaultSubMenuOrder } + name).distinct()
+ )
+ },
+ onReorder = { main -> onUpdateMenu(main, subMenuOrder) }
+ )
+ // 更多菜单区(进「更多」的页面)
+ Text(
+ text = stringResource(id = R.string.prefs_ui_sub_title),
+ fontSize = 12.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant
+ )
+ DragOrderList(
+ items = subItems,
+ labels = screens,
+ moveLabel = stringResource(id = R.string.prefs_ui_move_back),
+ // 按钮常显; 主菜单满 5 时自动让位(最后一个非"设置"项移入更多, 交换)
+ moveEnabled = { true },
+ onMove = { name ->
+ val mainWithoutSettings = mainItems.filter { it != "Settings" }
+ val needSwap = mainWithoutSettings.size >= 5
+ val evicted = if (needSwap) mainWithoutSettings.last() else null
+ val newMain = if (needSwap) {
+ (mainWithoutSettings.dropLast(1) + name).distinct()
+ } else {
+ (mainWithoutSettings + name).distinct()
+ }
+ val newSub = (subItems.filter { it != name } +
+ if (evicted != null) listOf(evicted) else emptyList()).distinct()
+ onUpdateMenu(newMain, newSub)
+ },
+ onReorder = { sub -> onUpdateMenu(screenOrder, sub) }
+ )
+ TextButton(onClick = onResetOrder) {
+ Text(text = stringResource(id = R.string.prefs_ui_order_reset))
+ }
+ }
+ }
+}
+
+/** 页面顺序拖拽列表: 每行右侧抓手, 按住上下拖动实时换位, 松手持久化 */
+@Composable
+private fun DragOrderList(
+ items: List,
+ labels: List>,
+ locked: Set = emptySet(),
+ moveLabel: String? = null,
+ moveEnabled: (String) -> Boolean = { true },
+ onMove: ((String) -> Unit)? = null,
+ onReorder: (List) -> Unit
+) {
+ val itemHeight = 48.dp
+ val itemHeightPx = with(LocalDensity.current) { itemHeight.toPx() }
+ val listState = rememberLazyListState()
+ val localItems = remember(items) { mutableStateListOf().apply { addAll(items) } }
+ var draggingIndex by remember { mutableIntStateOf(-1) }
+ var dragOffset by remember { mutableStateOf(0f) }
+
+ // 固定高度: 嵌套在 LazyVerticalGrid 内必须给有界高度, 否则无限高度约束崩溃
+ LazyColumn(
+ state = listState,
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(itemHeight * localItems.size)
+ ) {
+ itemsIndexed(localItems, key = { _, name -> name }) { index, name ->
+ val isDragging = draggingIndex == index
+ val isLocked = name in locked
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(itemHeight)
+ .zIndex(if (isDragging) 1f else 0f)
+ .graphicsLayer { translationY = if (isDragging) dragOffset else 0f }
+ .animateItem()
+ ) {
+ Text(
+ text = stringResource(id = labels.first { it.second == name }.first),
+ modifier = Modifier.weight(1f)
+ )
+ if (moveLabel != null && onMove != null && moveEnabled(name)) {
+ TextButton(onClick = { onMove(name) }, contentPadding = PaddingValues(horizontal = 4.dp)) {
+ Text(moveLabel, fontSize = 11.sp)
+ }
+ }
+ if (isLocked) {
+ // 锁定行(设置页): 无抓手, 固定最后
+ Text(
+ text = stringResource(id = R.string.prefs_ui_order_locked),
+ fontSize = 11.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.padding(horizontal = 12.dp)
+ )
+ } else {
+ Box(
+ modifier = Modifier
+ .size(48.dp)
+ .padding(20.dp)
+ .pointerInput(name) {
+ detectDragGestures(
+ onDragStart = { draggingIndex = localItems.indexOf(name) },
+ onDrag = { change, dragAmount ->
+ change.consume()
+ dragOffset += dragAmount.y
+ val currentIndex = draggingIndex
+ val target = (currentIndex + (dragOffset / itemHeightPx).roundToInt())
+ .coerceIn(0, localItems.size - 1)
+ if (target != currentIndex) {
+ localItems.add(target, localItems.removeAt(currentIndex))
+ dragOffset += (currentIndex - target) * itemHeightPx
+ draggingIndex = target
+ }
+ },
+ onDragEnd = {
+ onReorder(localItems.toList())
+ draggingIndex = -1
+ dragOffset = 0f
+ },
+ onDragCancel = {
+ draggingIndex = -1
+ dragOffset = 0f
+ }
+ )
+ }
+ ) {
+ // 小圆点手柄(触控区 padding 20dp 居中 -> 8dp 圆点)
+ Box(
+ modifier = Modifier
+ .fillMaxSize()
+ .background(MaterialTheme.colorScheme.onSurfaceVariant, CircleShape)
+ )
+ }
+ }
+ }
+ }
+ }
+}
+
+@Composable
+private fun SwitchRow(labelResId: Int, checked: Boolean, onCheckedChange: ((Boolean) -> Unit)?) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
@@ -556,15 +948,11 @@ private fun CardCreditsPreview() = MainTheme { CardCredits() }
@Composable
private fun CardCredits(modifier: Modifier = Modifier) {
ElevatedCard(
- modifier = modifier
- .fillMaxWidth()
- .height(268.dp)
+ modifier = modifier.fillMaxWidth()
) {
Column(
- verticalArrangement = Arrangement.SpaceBetween,
- modifier = Modifier
- .padding(horizontal = 8.dp, vertical = 4.dp)
- .fillMaxHeight()
+ verticalArrangement = Arrangement.spacedBy(8.dp),
+ modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
) {
Text(
text = stringResource(id = R.string.prefs_outro_title),
@@ -573,6 +961,8 @@ private fun CardCredits(modifier: Modifier = Modifier) {
Text(
text = stringResource(id = R.string.prefs_outro_thanks)
)
+ // 感谢列表与保修声明之间保留约两行间距 (用户要求)
+ Spacer(modifier = Modifier.height(24.dp))
Text(
text = stringResource(id = R.string.prefs_outro_license),
color = MaterialTheme.colorScheme.primary
@@ -588,7 +978,7 @@ private fun TopCard(onClick: () -> Unit, modifier: Modifier = Modifier, version:
horizontalArrangement = Arrangement.spacedBy(12.dp),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
- .height(48.dp)
+ .heightIn(min = 48.dp)
.clickable { onClick() }) {
Spacer(Modifier)
Icon(
@@ -603,7 +993,6 @@ private fun TopCard(onClick: () -> Unit, modifier: Modifier = Modifier, version:
modifier = Modifier
.weight(1f)
.padding(end = 6.dp)
- .infiniteMarquee()
)
}
}
diff --git a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsState.kt b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsState.kt
index 928cf60b..d29626a7 100644
--- a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsState.kt
+++ b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsState.kt
@@ -64,6 +64,24 @@ sealed interface SettingsAction {
data class ToggleSensor(val value: Boolean) : SettingsAction
data class ToggleLightTheme(val value: Boolean) : SettingsAction
data class ToggleNightMode(val value: Boolean) : SettingsAction
+ // UI 设置: 切换底部导航栏页面的隐藏状态(Screen simpleName)
+ data class ToggleScreen(val screenName: String) : SettingsAction
+ // UI 设置: 更新页面顺序
+ data class ReorderScreens(val order: List) : SettingsAction
+ // UI 设置: 重置为默认顺序
+ data object ResetScreenOrder : SettingsAction
+ // UI 设置: 更新主菜单 + 更多菜单顺序(4.5.1 折叠菜单)
+ data class UpdateMenuOrder(val mainOrder: List, val subOrder: List) : SettingsAction
+ // UI 设置: 重置主菜单 + 更多菜单顺序
+ data object ResetMenuOrder : SettingsAction
+ // WaveLog 日志(4.5.2): 更新服务器配置
+ data class UpdateWavelogSettings(
+ val url: String, val apiKey: String, val stationId: String, val autoUpload: Boolean
+ ) : SettingsAction
+ // WaveLog: 测试连接
+ data object TestWavelogConnection : SettingsAction
+ // WaveLog: 手动上传队列
+ data object UploadWavelogQueue : SettingsAction
// Remote control
data class UpdateRC(val settings: RCSettings) : SettingsAction
diff --git a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsViewModel.kt b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsViewModel.kt
index f43e91f6..8d835882 100644
--- a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsViewModel.kt
+++ b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsViewModel.kt
@@ -25,11 +25,18 @@ import com.rtbishop.look4sat.core.domain.repository.IDatabaseRepo
import com.rtbishop.look4sat.core.domain.repository.IMainContainer
import com.rtbishop.look4sat.core.domain.repository.ISettingsRepo
import com.rtbishop.look4sat.core.domain.usecase.IShowToast
+import com.rtbishop.look4sat.core.domain.wavelog.UploadOutcome
+import com.rtbishop.look4sat.core.domain.wavelog.WaveLogApi
+import com.rtbishop.look4sat.core.domain.wavelog.WavelogResult
+import com.rtbishop.look4sat.core.domain.wavelog.WavelogUploader
import com.rtbishop.look4sat.core.presentation.R
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
class SettingsViewModel(
private val databaseRepo: IDatabaseRepo,
@@ -121,10 +128,34 @@ class SettingsViewModel(
is SettingsAction.ToggleSensor -> settingsRepo.updateOtherSettings { it.copy(stateOfSensors = action.value) }
is SettingsAction.ToggleLightTheme -> settingsRepo.updateOtherSettings { it.copy(stateOfLightTheme = action.value) }
is SettingsAction.ToggleNightMode -> settingsRepo.updateOtherSettings { it.copy(stateOfNightMode = action.value) }
+ is SettingsAction.ToggleScreen -> settingsRepo.updateOtherSettings { current ->
+ val hidden = current.hiddenScreens.toMutableList()
+ if (action.screenName in hidden) hidden.remove(action.screenName) else hidden.add(action.screenName)
+ current.copy(hiddenScreens = hidden)
+ }
+ is SettingsAction.ReorderScreens -> settingsRepo.updateOtherSettings { it.copy(screenOrder = action.order) }
+ SettingsAction.ResetScreenOrder -> settingsRepo.updateOtherSettings { it.copy(screenOrder = emptyList()) }
+ is SettingsAction.UpdateMenuOrder -> settingsRepo.updateOtherSettings {
+ it.copy(screenOrder = action.mainOrder, subMenuOrder = action.subOrder)
+ }
+ SettingsAction.ResetMenuOrder -> settingsRepo.updateOtherSettings {
+ it.copy(screenOrder = emptyList(), subMenuOrder = emptyList())
+ }
// Remote control & data sources
is SettingsAction.UpdateRC -> settingsRepo.updateRCSettings(action.settings)
is SettingsAction.UpdateRadioControl -> settingsRepo.updateRadioControlSettings(action.settings)
is SettingsAction.UpdateDataSources -> settingsRepo.updateDataSourcesSettings(action.settings)
+ // WaveLog 日志(4.5.2)
+ is SettingsAction.UpdateWavelogSettings -> settingsRepo.updateOtherSettings {
+ it.copy(
+ wavelogUrl = action.url,
+ wavelogApiKey = action.apiKey,
+ wavelogStationId = action.stationId,
+ wavelogAutoUpload = action.autoUpload
+ )
+ }
+ SettingsAction.TestWavelogConnection -> testWavelogConnection()
+ SettingsAction.UploadWavelogQueue -> uploadWavelogQueue()
// System
is SettingsAction.ShowToast -> showToast(action.message)
}
@@ -133,7 +164,16 @@ class SettingsViewModel(
// region Position helpers — consolidated from 3 near-identical functions
private fun setGpsPosition() {
- updatePosition(R.string.prefs_loc_gps_error) { settingsRepo.setStationPosition() }
+ viewModelScope.launch {
+ _uiState.update { it.copy(positionSettings = it.positionSettings.copy(isUpdating = true)) }
+ val success = settingsRepo.setStationPosition()
+ _uiState.update {
+ it.copy(positionSettings = it.positionSettings.copy(
+ isUpdating = false,
+ messageResId = if (success) R.string.prefs_loc_success else R.string.prefs_loc_gps_error
+ ))
+ }
+ }
}
private fun setGeoPosition(latitude: Double, longitude: Double) {
@@ -181,6 +221,7 @@ class SettingsViewModel(
it.copy(dataSettings = it.dataSettings.copy(isUpdating = false))
}
println(exception)
+ showToast(R.string.prefs_data_update_failed)
}
}
@@ -197,6 +238,65 @@ class SettingsViewModel(
}
+ // endregion
+
+ // region WaveLog(4.5.2)
+
+ // 由 SettingsScreen 注入的共享 uploader(容器级单例)
+ var pendingUploader: WavelogUploader? = null
+
+ // 网格不一致确认弹窗状态(UI 观察后弹 AlertDialog)
+ var gridConfirm by mutableStateOf(null)
+
+ // WaveLog 错误详情弹窗(UI 观察后弹 AlertDialog, 可一键复制)
+ var wavelogError by mutableStateOf(null)
+
+ data class GridConfirmData(val stationGrid: String, val userGrid: String)
+
+ private fun testWavelogConnection() {
+ viewModelScope.launch {
+ val s = settingsRepo.otherSettings.value
+ val result = WaveLogApi.testToken(s.wavelogUrl, s.wavelogApiKey, s.wavelogStationId)
+ when (result) {
+ is WavelogResult.Success -> showToast("WaveLog: ${result.message}")
+ is WavelogResult.Failure -> wavelogError = result.message
+ }
+ }
+ }
+
+ private fun uploadWavelogQueue() {
+ viewModelScope.launch {
+ val result = pendingUploader?.uploadQueue()
+ when (result) {
+ is UploadOutcome.Done -> {
+ if (result.failedCount > 0 && result.firstError.isNotBlank()) {
+ wavelogError = result.firstError
+ } else {
+ showToast("WaveLog: ${result.message}")
+ }
+ }
+ is UploadOutcome.NeedConfirm -> {
+ gridConfirm = GridConfirmData(result.stationGrid, result.userGrid)
+ }
+ null -> showToast("WaveLog: 上传失败")
+ }
+ }
+ }
+
+ /** 网格确认结果: 忽略并上传 / 取消 */
+ fun resolveGridConfirm(ignoreAndUpload: Boolean) {
+ val confirm = gridConfirm ?: return
+ gridConfirm = null
+ if (!ignoreAndUpload) return
+ viewModelScope.launch {
+ val result = pendingUploader?.uploadQueue(force = true)
+ when (result) {
+ is UploadOutcome.Done -> showToast("WaveLog: ${result.message}")
+ else -> showToast("WaveLog: 上传失败")
+ }
+ }
+ }
+
// endregion
companion object {
@@ -207,7 +307,7 @@ class SettingsViewModel(
databaseRepo = container.databaseRepo,
settingsRepo = container.settingsRepo,
showToast = container.provideShowToast()
- )
+ ).apply { pendingUploader = container.provideWavelogUploader() }
}
}
}
diff --git a/feature/status/build.gradle.kts b/feature/status/build.gradle.kts
new file mode 100644
index 00000000..77b30387
--- /dev/null
+++ b/feature/status/build.gradle.kts
@@ -0,0 +1,17 @@
+import com.android.build.api.dsl.LibraryExtension
+
+plugins {
+ alias(libs.plugins.convention.featurePlugin)
+}
+
+android {
+ namespace = "com.rtbishop.look4sat.feature.status"
+ compileOptions {
+ encoding = "UTF-8"
+ }
+}
+
+dependencies {
+ implementation(project(":core:domain"))
+ implementation(project(":core:presentation"))
+}
diff --git a/feature/status/src/main/java/com/rtbishop/look4sat/feature/status/SatStatusScreen.kt b/feature/status/src/main/java/com/rtbishop/look4sat/feature/status/SatStatusScreen.kt
new file mode 100644
index 00000000..9d3d923c
--- /dev/null
+++ b/feature/status/src/main/java/com/rtbishop/look4sat/feature/status/SatStatusScreen.kt
@@ -0,0 +1,343 @@
+package com.rtbishop.look4sat.feature.status
+
+import androidx.compose.animation.core.RepeatMode
+import androidx.compose.animation.core.animateFloat
+import androidx.compose.animation.core.infiniteRepeatable
+import androidx.compose.animation.core.rememberInfiniteTransition
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+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.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.AlertDialog
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.HorizontalDivider
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextButton
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.rotate
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import androidx.lifecycle.viewmodel.initializer
+import androidx.lifecycle.viewmodel.compose.viewModel
+import androidx.lifecycle.viewmodel.viewModelFactory
+import com.rtbishop.look4sat.core.domain.model.SatDay
+import com.rtbishop.look4sat.core.domain.model.SatReport
+import com.rtbishop.look4sat.core.domain.model.SatSlot
+import com.rtbishop.look4sat.core.domain.model.SatStatus
+import com.rtbishop.look4sat.core.domain.repository.IMainContainer
+import com.rtbishop.look4sat.core.presentation.R
+import java.util.Calendar
+
+// ========== 官网状态色(amsat.org/status 原色) ==========
+val ActiveBlue = Color(0xFF648FFF)
+val TlmOrange = Color(0xFFFFB000)
+val NotHeardPink = Color(0xFFDC267F)
+val ConflictDeepOrange = Color(0xFFFE6100)
+val NoReportGray = Color(0xFFC0C0C0)
+
+@Composable
+fun SatStatusScreen(container: IMainContainer) {
+ val viewModel: SatStatusViewModel = viewModel(
+ factory = viewModelFactory {
+ initializer { SatStatusViewModel(container) }
+ }
+ )
+ val uiState by viewModel.uiState.collectAsStateWithLifecycle()
+ var selectedDay by remember { mutableStateOf?>(null) }
+
+ Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp)) {
+ // 顶部: 图例 + 刷新
+ StatusHeader(
+ fetchedAtUtcMs = uiState.fetchedAtUtcMs,
+ isRefreshing = uiState.isRefreshing,
+ onRefresh = { viewModel.refresh() }
+ )
+ LegendRow()
+
+ when {
+ uiState.isLoading -> {
+ Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
+ CircularProgressIndicator()
+ }
+ }
+ uiState.error != null && uiState.statuses.isEmpty() -> {
+ Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
+ Text(
+ text = stringResource(id = R.string.amsat_load_failed),
+ color = MaterialTheme.colorScheme.error
+ )
+ }
+ }
+ else -> {
+ // 表头
+ HeaderRow(statuses = uiState.statuses)
+ HorizontalDivider(thickness = 1.dp)
+ // 行
+ LazyColumn(modifier = Modifier.fillMaxSize()) {
+ items(uiState.statuses, key = { it.name }) { status ->
+ StatusRow(
+ status = status,
+ onClickDay = { day -> selectedDay = status to day }
+ )
+ }
+ }
+ }
+ }
+ }
+
+ selectedDay?.let { (status, day) ->
+ ReportDialog(
+ statusName = status.name,
+ day = day,
+ reports = uiState.reports,
+ onDismiss = { selectedDay = null }
+ )
+ }
+}
+
+/** 顶部: 更新时间 + 刷新按钮(加载中旋转动画) */
+@Composable
+private fun StatusHeader(
+ fetchedAtUtcMs: Long,
+ isRefreshing: Boolean,
+ onRefresh: () -> Unit
+) {
+ val infiniteTransition = rememberInfiniteTransition(label = "refresh")
+ val angle by infiniteTransition.animateFloat(
+ initialValue = 0f,
+ targetValue = 360f,
+ animationSpec = infiniteRepeatable(tween(800), RepeatMode.Restart),
+ label = "angle"
+ )
+ Row(
+ modifier = Modifier.fillMaxWidth().padding(vertical = 6.dp),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Text(
+ text = if (fetchedAtUtcMs > 0) stringResource(id = R.string.amsat_updated) + " " + formatFetchedAt(fetchedAtUtcMs) else stringResource(id = R.string.amsat_title),
+ fontSize = 13.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.weight(1f)
+ )
+ Box(
+ modifier = Modifier
+ .size(34.dp)
+ .clip(CircleShape)
+ .background(MaterialTheme.colorScheme.surfaceVariant)
+ .clickable(onClick = onRefresh),
+ contentAlignment = Alignment.Center
+ ) {
+ if (isRefreshing) {
+ CircularProgressIndicator(modifier = Modifier.size(18.dp), strokeWidth = 2.dp)
+ } else {
+ Text(
+ text = "↻",
+ fontSize = 20.sp,
+ color = MaterialTheme.colorScheme.primary,
+ modifier = Modifier.rotate(angle)
+ )
+ }
+ }
+ }
+}
+
+/** 图例(官网四色) */
+@Composable
+private fun LegendRow() {
+ val legend = listOf(
+ stringResource(id = R.string.amsat_active) to ActiveBlue,
+ stringResource(id = R.string.amsat_tlm) to TlmOrange,
+ stringResource(id = R.string.amsat_not_heard) to NotHeardPink,
+ stringResource(id = R.string.amsat_conflict) to ConflictDeepOrange
+ )
+ Row(
+ modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp),
+ horizontalArrangement = Arrangement.spacedBy(8.dp)
+ ) {
+ legend.forEach { (label, color) ->
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ Box(
+ modifier = Modifier
+ .size(10.dp)
+ .clip(RoundedCornerShape(2.dp))
+ .background(color)
+ )
+ Spacer(modifier = Modifier.width(3.dp))
+ Text(text = label, fontSize = 10.sp, color = MaterialTheme.colorScheme.onSurfaceVariant)
+ }
+ }
+ }
+}
+
+/** 表头: 卫星名 + 6 天日期 */
+@Composable
+private fun HeaderRow(statuses: List) {
+ val dates = statuses.firstOrNull()?.days?.map { it.dateLabel } ?: emptyList()
+ Row(
+ modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Text(
+ text = stringResource(id = R.string.amsat_name),
+ fontSize = 11.sp,
+ fontWeight = FontWeight.Bold,
+ color = MaterialTheme.colorScheme.primary,
+ modifier = Modifier.weight(1.4f).padding(start = 4.dp)
+ )
+ dates.forEach { date ->
+ Text(
+ text = date,
+ fontSize = 10.sp,
+ fontWeight = FontWeight.Bold,
+ textAlign = TextAlign.Center,
+ color = MaterialTheme.colorScheme.primary,
+ modifier = Modifier.weight(1f)
+ )
+ }
+ }
+}
+
+/** 卫星行: 名称 + 6 天色块(官网色 + 报告数) */
+@Composable
+private fun StatusRow(status: SatStatus, onClickDay: (SatDay) -> Unit) {
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(vertical = 3.dp),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Text(
+ text = status.name,
+ fontSize = 11.sp,
+ maxLines = 1,
+ overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis,
+ modifier = Modifier.weight(1.4f).padding(start = 4.dp)
+ )
+ status.days.forEach { day ->
+ val slot = day.slots.firstOrNull { it.statusColor != NoReportGray.value.toInt().toLong() } ?: day.slots.first()
+ DayCell(
+ slot = slot,
+ modifier = Modifier.weight(1f).padding(horizontal = 1.dp),
+ onClick = { onClickDay(day) }
+ )
+ }
+ }
+}
+
+/** 单天色块: 取当天 12 槽中最新的有报告状态; 无报告则灰 */
+@Composable
+private fun DayCell(slot: SatSlot, modifier: Modifier, onClick: () -> Unit) {
+ val color = Color(slot.statusColor)
+ Box(
+ modifier = modifier
+ .height(26.dp)
+ .clip(RoundedCornerShape(4.dp))
+ .background(color)
+ .clickable(onClick = onClick),
+ contentAlignment = Alignment.Center
+ ) {
+ if (slot.count > 0) {
+ Text(
+ text = slot.count.toString(),
+ fontSize = 11.sp,
+ fontWeight = FontWeight.Bold,
+ color = Color.White
+ )
+ }
+ }
+}
+
+/** 报告详情弹窗(3 级: 呼号/日期/时间/网格) */
+@Composable
+private fun ReportDialog(
+ statusName: String,
+ day: SatDay,
+ reports: Map,
+ onDismiss: () -> Unit
+) {
+ val dayReports = day.slots.flatMap { it.reportIds }
+ .mapNotNull { reports[it] }
+ AlertDialog(
+ onDismissRequest = onDismiss,
+ title = { Text(text = "$statusName · ${day.dateLabel}") },
+ text = {
+ if (dayReports.isEmpty()) {
+ Text(stringResource(id = R.string.amsat_no_reports))
+ } else {
+ LazyColumn(modifier = Modifier.height(320.dp)) {
+ items(dayReports) { report ->
+ Column(modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp)) {
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ Box(
+ modifier = Modifier
+ .size(8.dp)
+ .clip(CircleShape)
+ .background(statusColorOf(report.statusText))
+ )
+ Spacer(modifier = Modifier.width(6.dp))
+ Text(
+ text = report.statusText,
+ fontSize = 13.sp,
+ fontWeight = FontWeight.Bold
+ )
+ }
+ Text(
+ text = "${report.call} ${report.dateUtc} ${report.timeUtc}" +
+ if (report.grid.isNotBlank() && report.grid != "-") " ${report.grid}" else "",
+ fontSize = 12.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant
+ )
+ }
+ HorizontalDivider(thickness = 0.5.dp)
+ }
+ }
+ }
+ },
+ confirmButton = {
+ TextButton(onClick = onDismiss) { Text(stringResource(id = R.string.amsat_close)) }
+ }
+ )
+}
+
+private fun statusColorOf(statusText: String): Color = when {
+ statusText.contains("Heard", ignoreCase = true) && !statusText.contains("Not", ignoreCase = true) -> ActiveBlue
+ statusText.contains("Telemetry", ignoreCase = true) || statusText.contains("Beacon", ignoreCase = true) -> TlmOrange
+ statusText.contains("Not Heard", ignoreCase = true) -> NotHeardPink
+ else -> ConflictDeepOrange
+}
+
+private fun formatFetchedAt(utcMs: Long): String {
+ val cal = Calendar.getInstance()
+ cal.timeInMillis = utcMs
+ return "%02d-%02d %02d:%02d".format(
+ cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH),
+ cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE)
+ )
+}
diff --git a/feature/status/src/main/java/com/rtbishop/look4sat/feature/status/SatStatusViewModel.kt b/feature/status/src/main/java/com/rtbishop/look4sat/feature/status/SatStatusViewModel.kt
new file mode 100644
index 00000000..a6997781
--- /dev/null
+++ b/feature/status/src/main/java/com/rtbishop/look4sat/feature/status/SatStatusViewModel.kt
@@ -0,0 +1,84 @@
+package com.rtbishop.look4sat.feature.status
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.rtbishop.look4sat.core.domain.model.SatReport
+import com.rtbishop.look4sat.core.domain.model.SatStatus
+import com.rtbishop.look4sat.core.domain.repository.IMainContainer
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.launch
+
+data class SatStatusUiState(
+ val isLoading: Boolean = false,
+ val isRefreshing: Boolean = false,
+ val statuses: List = emptyList(),
+ val reports: Map = emptyMap(),
+ val fetchedAtUtcMs: Long = 0L,
+ val error: String? = null
+)
+
+class SatStatusViewModel(
+ private val container: IMainContainer
+) : ViewModel() {
+
+ private val _uiState = MutableStateFlow(SatStatusUiState(isLoading = true))
+ val uiState: StateFlow = _uiState
+
+ init {
+ fetch()
+ }
+
+ fun fetch() {
+ viewModelScope.launch {
+ _uiState.update { it.copy(isLoading = true, error = null) }
+ try {
+ val page = container.amSatRepo.fetchStatus()
+ if (page != null && page.statuses.isNotEmpty()) {
+ _uiState.update {
+ it.copy(
+ isLoading = false,
+ isRefreshing = false,
+ statuses = page.statuses,
+ reports = page.reports,
+ fetchedAtUtcMs = page.fetchedAtUtcMs
+ )
+ }
+ } else {
+ _uiState.update {
+ it.copy(isLoading = false, isRefreshing = false, error = "fetch_failed")
+ }
+ }
+ } catch (exception: Exception) {
+ _uiState.update {
+ it.copy(isLoading = false, isRefreshing = false, error = exception.message ?: "fetch_failed")
+ }
+ }
+ }
+ }
+
+ fun refresh() {
+ if (_uiState.value.isRefreshing) return
+ _uiState.update { it.copy(isRefreshing = true, error = null) }
+ viewModelScope.launch {
+ try {
+ val page = container.amSatRepo.fetchStatus()
+ if (page != null && page.statuses.isNotEmpty()) {
+ _uiState.update {
+ it.copy(
+ isRefreshing = false,
+ statuses = page.statuses,
+ reports = page.reports,
+ fetchedAtUtcMs = page.fetchedAtUtcMs
+ )
+ }
+ } else {
+ _uiState.update { it.copy(isRefreshing = false, error = "fetch_failed") }
+ }
+ } catch (exception: Exception) {
+ _uiState.update { it.copy(isRefreshing = false, error = exception.message ?: "fetch_failed") }
+ }
+ }
+ }
+}
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 6f817fc0..41c552b9 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,8 +1,8 @@
[versions]
#noinspection UnusedVersionCatalogEntry
-appVersionCode = "443"
+appVersionCode = "453"
#noinspection UnusedVersionCatalogEntry
-appVersionName = "4.4.3"
+appVersionName = "4.5.3"
#noinspection UnusedVersionCatalogEntry
compileSdk = "37"
#noinspection UnusedVersionCatalogEntry
@@ -11,6 +11,11 @@ minSdk = "24"
jdkVersion = "21"
#noinspection UnusedVersionCatalogEntry
packageName = "com.rtbishop.look4sat"
+# Fork application ID: official app uses com.rtbishop.look4sat with a different
+# signing cert. Installing a fork with the same applicationId would conflict
+# with the official build (signature mismatch / cannot overwrite), so the fork
+# ships under its own applicationId suffix.
+applicationId = "com.rtbishop.look4sat.bg7nta"
android-gradle-plugin = "9.3.1"
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 45c81f6b..bdfa71fd 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -21,10 +21,13 @@ include(
":core:presentation"
)
include(
+ ":feature:cw",
":feature:map",
":feature:mutual",
":feature:passes",
":feature:radar",
+ ":feature:roaming",
":feature:satellites",
- ":feature:settings"
+ ":feature:settings",
+ ":feature:status"
)