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" )
数字