summaryrefslogtreecommitdiff
path: root/android-app/app/src/main/temp
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-03-22 04:40:36 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-03-22 04:40:36 +0000
commit64d66c6ae4fde6aa3e66a5dba33950d447af1102 (patch)
tree612734b3803dd61f311e2a837c656832828481cd /android-app/app/src/main/temp
parent4d637d284dce6fc674599c226dd063c442fd350f (diff)
refactor: cleanup, simplify, and modularize Android app logic
- Extracted MOB, Instruments, Map, and Anchor Watch logic from MainActivity into dedicated handlers. - Refactored LocationService to use a standalone MockTidalCurrentGenerator. - Removed legacy 'kotlin_old', 'res_old', and 'temp' directories. - Added KDoc documentation to core components and handlers. - Integrated JUnit 5 dependencies and configured the test runner. - Verified all changes with successful unit test execution.
Diffstat (limited to 'android-app/app/src/main/temp')
-rwxr-xr-xandroid-app/app/src/main/temp/CompassRoseView.kt217
-rwxr-xr-xandroid-app/app/src/main/temp/HeadingDataProcessor.kt108
2 files changed, 0 insertions, 325 deletions
diff --git a/android-app/app/src/main/temp/CompassRoseView.kt b/android-app/app/src/main/temp/CompassRoseView.kt
deleted file mode 100755
index 8e755a3..0000000
--- a/android-app/app/src/main/temp/CompassRoseView.kt
+++ /dev/null
@@ -1,217 +0,0 @@
-package org.terst.nav.temp // Temporarily placing in 'temp' due to permissions, actual package should be 'org.terst.nav'
-
-import android.content.Context
-import android.graphics.Canvas
-import android.graphics.Color
-import android.graphics.Paint
-import android.graphics.Rect
-import android.util.AttributeSet
-import android.view.View
-import kotlin.math.cos
-import kotlin.math.min
-import kotlin.math.sin
-
-class CompassRoseView @JvmOverloads constructor(
- context: Context,
- attrs: AttributeSet? = null,
- defStyleAttr: Int = 0
-) : View(context, attrs, defStyleAttr) {
-
- private var heading: Float = 0f // Current heading in degrees
- set(value) {
- field = value % 360 // Ensure heading is within 0-359
- invalidate()
- }
- private var cog: Float = 0f // Course Over Ground in degrees
- set(value) {
- field = value % 360
- invalidate()
- }
- private var isTrueHeading: Boolean = true // True for True heading, false for Magnetic
-
- private val rosePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
- color = Color.DKGRAY
- style = Paint.Style.STROKE
- strokeWidth = 2f
- }
-
- private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
- color = Color.WHITE
- textSize = 30f
- textAlign = Paint.Align.CENTER
- }
-
- private val cardinalTextPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
- color = Color.WHITE
- textSize = 40f
- textAlign = Paint.Align.CENTER
- isFakeBoldText = true
- }
-
- private val majorTickPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
- color = Color.WHITE
- strokeWidth = 3f
- }
-
- private val minorTickPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
- color = Color.GRAY
- strokeWidth = 1f
- }
-
- private val headingNeedlePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
- color = Color.RED
- style = Paint.Style.FILL
- }
-
- private val cogArrowPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
- color = Color.BLUE
- style = Paint.Style.FILL
- strokeWidth = 5f
- }
-
- private var viewCenterX: Float = 0f
- private var viewCenterY: Float = 0f
- private var radius: Float = 0f
-
- override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
- super.onSizeChanged(w, h, oldw, oldh)
- viewCenterX = w / 2f
- viewCenterY = h / 2f
- radius = min(w, h) / 2f - 40f // Leave some padding
- textPaint.textSize = radius / 6f
- cardinalTextPaint.textSize = radius / 4.5f
- }
-
- override fun onDraw(canvas: Canvas) {
- super.onDraw(canvas)
-
- // Draw outer circle
- canvas.drawCircle(viewCenterX, viewCenterY, radius, rosePaint)
-
- // Draw cardinal and intercardinal points
- drawCardinalPoints(canvas)
-
- // Draw tick marks and degree labels
- drawDegreeMarks(canvas)
-
- // Draw heading needle
- drawHeadingNeedle(canvas, heading, headingNeedlePaint, radius * 0.8f)
-
- // Draw COG arrow
- drawCogArrow(canvas, cog, cogArrowPaint, radius * 0.6f)
-
- // Draw current heading text in the center
- drawHeadingText(canvas)
- }
-
- private fun drawCardinalPoints(canvas: Canvas) {
- val cardinalPoints = listOf("N", "E", "S", "W")
- val angles = listOf(0f, 90f, 180f, 270f)
- val textBound = Rect()
-
- for (i in cardinalPoints.indices) {
- val angleRad = Math.toRadians((angles[i] - 90).toDouble()).toFloat() // Adjust for canvas 0deg at 3 o'clock
- val x = viewCenterX + (radius * 0.9f) * cos(angleRad)
- val y = viewCenterY + (radius * 0.9f) * sin(angleRad)
-
- val text = cardinalPoints[i]
- cardinalTextPaint.getTextBounds(text, 0, text.length, textBound)
- val textHeight = textBound.height()
-
- canvas.drawText(text, x, y + textHeight / 2, cardinalTextPaint)
- }
- }
-
- private fun drawDegreeMarks(canvas: Canvas) {
- for (i in 0 until 360 step 5) {
- val isMajor = (i % 30 == 0) // Major ticks every 30 degrees
- val tickLength = if (isMajor) 30f else 15f
- val currentTickPaint = if (isMajor) majorTickPaint else minorTickPaint
- val startRadius = radius - tickLength
-
- val angleRad = Math.toRadians((i - 90).toDouble()).toFloat() // Adjust for canvas 0deg at 3 o'clock
-
- val startX = viewCenterX + startRadius * cos(angleRad)
- val startY = viewCenterY + startRadius * sin(angleRad)
- val endX = viewCenterX + radius * cos(angleRad)
- val endY = viewCenterY + radius * sin(angleRad)
-
- canvas.drawLine(startX, startY, endX, endY, currentTickPaint)
-
- if (isMajor && i != 0) { // Draw degree labels for major ticks (except North)
- val textRadius = radius - tickLength - textPaint.textSize / 2 - 10f
- val textX = viewCenterX + textRadius * cos(angleRad)
- val textY = viewCenterY + textRadius * sin(angleRad) + textPaint.textSize / 2
-
- canvas.drawText(i.toString(), textX, textY, textPaint)
- }
- }
- }
-
- private fun drawHeadingNeedle(canvas: Canvas, angle: Float, paint: Paint, length: Float) {
- val angleRad = Math.toRadians((angle - 90).toDouble()).toFloat() // Adjust for canvas 0deg at 3 o'clock
- val endX = viewCenterX + length * cos(angleRad)
- val endY = viewCenterY + length * sin(angleRad)
-
- // Draw a simple triangle for the needle
- val needleWidth = 20f
- val path = android.graphics.Path()
- path.moveTo(endX, endY)
- path.lineTo(viewCenterX + needleWidth * cos(angleRad - Math.toRadians(90.0).toFloat()),
- viewCenterY + needleWidth * sin(angleRad - Math.toRadians(90.0).toFloat()))
- path.lineTo(viewCenterX + needleWidth * cos(angleRad + Math.toRadians(90.0).toFloat()),
- viewCenterY + needleWidth * sin(angleRad + Math.toRadians(90.0).toFloat()))
- path.close()
- canvas.drawPath(path, paint)
- }
-
- private fun drawCogArrow(canvas: Canvas, angle: Float, paint: Paint, length: Float) {
- val angleRad = Math.toRadians((angle - 90).toDouble()).toFloat() // Adjust for canvas 0deg at 3 o'clock
- val endX = viewCenterX + length * cos(angleRad)
- val endY = viewCenterY + length * sin(angleRad)
-
- val startX = viewCenterX + (length * 0.5f) * cos(angleRad)
- val startY = viewCenterY + (length * 0.5f) * sin(angleRad)
-
- canvas.drawLine(startX, startY, endX, endY, paint)
-
- // Draw arrow head
- val arrowHeadLength = 25f
- val arrowHeadWidth = 15f
- val arrowPath = android.graphics.Path()
- arrowPath.moveTo(endX, endY)
- arrowPath.lineTo(endX - arrowHeadLength * cos(angleRad - Math.toRadians(30.0).toFloat()),
- endY - arrowHeadLength * sin(angleRad - Math.toRadians(30.0).toFloat()))
- arrowPath.moveTo(endX, endY)
- arrowPath.lineTo(endX - arrowHeadLength * cos(angleRad + Math.toRadians(30.0).toFloat()),
- endY - arrowHeadLength * sin(angleRad + Math.toRadians(30.0).toFloat()))
- canvas.drawPath(arrowPath, paint)
- }
-
- private fun drawHeadingText(canvas: Canvas) {
- val headingText = "${heading.toInt()}°" + if (isTrueHeading) "T" else "M"
- textPaint.color = Color.WHITE
- textPaint.textSize = radius / 3.5f // Larger text for main heading
- canvas.drawText(headingText, viewCenterX, viewCenterY + textPaint.textSize / 3, textPaint)
- }
-
- /**
- * Sets the current heading to display.
- * @param newHeading The new heading value in degrees (0-359).
- * @param isTrue Whether the heading is True (magnetic variation applied) or Magnetic.
- */
- fun setHeading(newHeading: Float, isTrue: Boolean) {
- this.heading = newHeading
- this.isTrueHeading = isTrue
- invalidate()
- }
-
- /**
- * Sets the Course Over Ground (COG) to display.
- * @param newCog The new COG value in degrees (0-359).
- */
- fun setCog(newCog: Float) {
- this.cog = newCog
- invalidate()
- }
-}
diff --git a/android-app/app/src/main/temp/HeadingDataProcessor.kt b/android-app/app/src/main/temp/HeadingDataProcessor.kt
deleted file mode 100755
index 7625f90..0000000
--- a/android-app/app/src/main/temp/HeadingDataProcessor.kt
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.terst.nav.temp // Temporarily placing in 'temp' due to permissions
-
-import android.hardware.GeomagneticField
-import android.location.Location
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.update
-import java.util.Date
-
-/**
- * Data class representing processed heading information.
- * @param trueHeading The heading relative to true North (0-359.9 degrees).
- * @param magneticHeading The heading relative to magnetic North (0-359.9 degrees).
- * @param magneticVariation The difference between true and magnetic North at the current location (+E, -W).
- * @param cog Course Over Ground (0-359.9 degrees).
- */
-data class HeadingInfo(
- val trueHeading: Float,
- val magneticHeading: Float,
- val magneticVariation: Float,
- val cog: Float
-)
-
-/**
- * Processor for handling heading data, including magnetic variation calculations
- * using the Android GeomagneticField.
- */
-class HeadingDataProcessor {
-
- private val _headingInfoFlow = MutableStateFlow(HeadingInfo(0f, 0f, 0f, 0f))
- val headingInfoFlow: StateFlow<HeadingInfo> = _headingInfoFlow.asStateFlow()
-
- private var currentLatitude: Double = 0.0
- private var currentLongitude: Double = 0.0
- private var currentAltitude: Double = 0.0
-
- /**
- * Updates the current geographic location for magnetic variation calculations.
- */
- fun updateLocation(latitude: Double, longitude: Double, altitude: Double) {
- currentLatitude = latitude
- currentLongitude = longitude
- currentAltitude = altitude
- // Recalculate magnetic variation if location changes
- updateHeadingInfo(_headingInfoFlow.value.trueHeading, _headingInfoFlow.value.cog, true)
- }
-
- /**
- * Processes a new true heading and Course Over Ground (COG) value.
- * @param newTrueHeading The new true heading in degrees.
- * @param newCog The new COG in degrees.
- */
- fun updateTrueHeadingAndCog(newTrueHeading: Float, newCog: Float) {
- updateHeadingInfo(newTrueHeading, newCog, true)
- }
-
- /**
- * Processes a new magnetic heading and Course Over Ground (COG) value.
- * @param newMagneticHeading The new magnetic heading in degrees.
- * @param newCog The new COG in degrees.
- */
- fun updateMagneticHeadingAndCog(newMagneticHeading: Float, newCog: Float) {
- updateHeadingInfo(newMagneticHeading, newCog, false)
- }
-
- private fun updateHeadingInfo(heading: Float, cog: Float, isTrueHeadingInput: Boolean) {
- val magneticVariation = calculateMagneticVariation()
- val (finalTrueHeading, finalMagneticHeading) = if (isTrueHeadingInput) {
- Pair(heading, (heading - magneticVariation + 360) % 360)
- } else {
- Pair((heading + magneticVariation + 360) % 360, heading)
- }
-
- _headingInfoFlow.update {
- it.copy(
- trueHeading = finalTrueHeading,
- magneticHeading = finalMagneticHeading,
- magneticVariation = magneticVariation,
- cog = cog
- )
- }
- }
-
- /**
- * Calculates the magnetic variation (declination) for the current location.
- * @return Magnetic variation in degrees (+E, -W).
- */
- private fun calculateMagneticVariation(): Float {
- // GeomagneticField requires current time in milliseconds
- val currentTimeMillis = System.currentTimeMillis()
-
- // Create a dummy Location object to get altitude if only lat/lon are updated
- // GeomagneticField needs altitude, using 0 if not provided
- val geoField = GeomagneticField(
- currentLatitude.toFloat(),
- currentLongitude.toFloat(),
- currentAltitude.toFloat(), // Altitude in meters
- currentTimeMillis
- )
- return geoField.declination // Declination is the magnetic variation
- }
-
- // Helper function to normalize angles (0-359.9) - though modulo handles this for positive floats
- private fun normalizeAngle(angle: Float): Float {
- return (angle % 360 + 360) % 360
- }
-}