generated from me/template-mit
qwen3.6:35b's first attempt, does not compile (yet).
This commit is contained in:
1 parent
eeda4a18c5
commit
337403721b
17 files changed
+1486
-40
No files matched your search
@@ -0,0 +1,166 @@
|
||||
package com.hyperling.weather
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
/**
|
||||
* The 8 positions on the Celtic Season Wheel.
|
||||
* Based on solar events arranged clockwise starting from Summer at top (12 o'clock).
|
||||
*/
|
||||
enum class Season(
|
||||
val label: String,
|
||||
val fullName: String,
|
||||
val color: Color,
|
||||
/**
|
||||
* Start of season expressed as month (1-12) and day (1-31).
|
||||
* Used for the hand pointer position.
|
||||
*/
|
||||
val startMonth: Int,
|
||||
val startDay: Int,
|
||||
) {
|
||||
// Summer solstice area - top of wheel (12 o'clock = 0 degrees in Compose arc coords)
|
||||
SUMMER1("V1", "Summer Cross Quarter to Fall Equinox", Color(0xFFFBBC04), 6, 21),
|
||||
SUMMER2("V2", "Fall Equinox to Winter Solstice (early)", Color(0xFFFF8F00), 8, 1),
|
||||
|
||||
FALL1("F1", "Fall Equinox to Fall Cross Quarter", Color(0xFFE65100), 9, 21),
|
||||
FALL2("F2", "Winter Solstice to Winter Cross Quarter (early)", Color(0xFF6D4C41), 11, 1),
|
||||
|
||||
WINTER1("W1", "Winter Cross Quarter to Spring Equinox (late)", Color(0xFF546E7A), 12, 21),
|
||||
WINTER2("W2", "Spring Equinox to Summer Solstice (early)", Color(0xFF37474F), 2, 1),
|
||||
|
||||
SPRING1("S1", "Summer Cross Quarter to Fall Equinox", Color(0xFF4CAF50), 3, 21),
|
||||
SPRING2("S2", "Cross Quarter to Summer Solstice", Color(0xFF81C784), 5, 1);
|
||||
|
||||
companion object {
|
||||
val All = values()
|
||||
val Segments = All.size // 8
|
||||
|
||||
/**
|
||||
* Get the current season based on today's date.
|
||||
*/
|
||||
fun current(): Season {
|
||||
val calendar = java.util.Calendar.getInstance()
|
||||
val month = calendar.get(java.util.Calendar.MONTH) + 1 // 1-12
|
||||
val day = calendar.get(java.util.Calendar.DAY_OF_MONTH)
|
||||
|
||||
return All.find { season ->
|
||||
val startStart = season.startMonth * 100 + season.startDay
|
||||
// Calculate end as next season's start
|
||||
val idx = season.ordinal
|
||||
val nextSeason = if (idx < All.size - 1) All[idx + 1] else All[0]
|
||||
val endStart = nextSeason.startMonth * 100 + nextSeason.startDay
|
||||
|
||||
val currentPos = month * 100 + day
|
||||
when {
|
||||
startStart <= endStart ->
|
||||
currentPos in startStart..endStart
|
||||
else ->
|
||||
currentPos >= startStart || currentPos <= endStart
|
||||
}
|
||||
} ?: SPRING1
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hand angle (in radians) for the current date.
|
||||
* 0 radians = top of wheel (Summer Solstice), increasing clockwise.
|
||||
*/
|
||||
fun handAngle(): Double {
|
||||
val calendar = java.util.Calendar.getInstance()
|
||||
val month = calendar.get(java.util.Calendar.MONTH) + 1
|
||||
val day = calendar.get(java.util.Calendar.DAY_OF_MONTH)
|
||||
|
||||
// Calculate which season we're in and how far through it
|
||||
val currentSeason = current()
|
||||
val idx = currentSeason.ordinal
|
||||
val nextIdx = (idx + 1) % All.size
|
||||
val nextSeason = All[nextIdx]
|
||||
|
||||
val startPos = currentSeason.startMonth * 100 + currentSeason.startDay
|
||||
val endPos = nextSeason.startMonth * 100 + nextSeason.startDay
|
||||
|
||||
// Handle year wrap for seasons that cross January
|
||||
var totalDays = if (endPos > startPos) {
|
||||
daysBetween(currentSeason.startMonth, currentSeason.startDay,
|
||||
nextSeason.startMonth, nextSeason.startDay)
|
||||
} else {
|
||||
// Crosses year boundary
|
||||
val daysInCurrentMonth = daysInMonth(currentSeason.startMonth, currentSeason.startDay)
|
||||
val daysRemaining = daysInCurrentMonth - currentSeason.startDay + 1
|
||||
val daysFromStartNext = nextSeason.startMonth * 30 + nextSeason.startDay - 15
|
||||
daysRemaining + daysFromStartNext
|
||||
}
|
||||
|
||||
if (totalDays <= 0) totalDays = 90 // fallback
|
||||
|
||||
val currentPos = month * 100 + day
|
||||
var elapsedDays: Int
|
||||
|
||||
if (endPos > startPos) {
|
||||
elapsedDays = daysBetween(currentSeason.startMonth, currentSeason.startDay, month, day)
|
||||
} else {
|
||||
val daysInCurrentMonth = daysInMonth(currentSeason.startMonth, 1)
|
||||
elapsedDays = (daysInCurrentMonth - currentSeason.startDay + 1) + (day - 1)
|
||||
}
|
||||
|
||||
if (elapsedDays < 0) elapsedDays = 0
|
||||
val fraction = elapsedDays.toDouble() / totalDays.coerceAtLeast(1)
|
||||
|
||||
// Map to angle: 0 at top (Summer Solstice), clockwise
|
||||
return fraction * 2 * PI
|
||||
}
|
||||
|
||||
private fun daysInMonth(month: Int, day: Int): Int {
|
||||
val cal = java.util.Calendar.getInstance().apply {
|
||||
set(java.util.Calendar.MONTH, month - 1)
|
||||
}
|
||||
return cal.getActualMaximum(java.util.Calendar.DAY_OF_MONTH)
|
||||
}
|
||||
|
||||
private fun daysBetween(m1: Int, d1: Int, m2: Int, d2: Int): Int {
|
||||
val start = java.util.GregorianCalendar(2024, m1 - 1, d1).timeInMillis
|
||||
val end = java.util.GregorianCalendar(2024, m2 - 1, d2).timeInMillis
|
||||
return ((end - start) / (1000 * 60 * 60 * 24)).toInt()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the angle for a season's center on the wheel.
|
||||
* 0 radians = top of wheel, increasing clockwise.
|
||||
*/
|
||||
fun angleFor(idx: Int): Double {
|
||||
return (idx.toDouble() / Segments) * 2 * PI
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sweep angle for each wedge (360 degrees / 8 = 45 degrees).
|
||||
*/
|
||||
val wedgeSweep: Double
|
||||
get() = 2 * PI / Segments
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Color palette for the Celtic Wheel UI.
|
||||
*/
|
||||
object SeasonColors {
|
||||
val Background = Color(0xFF1A1A2E)
|
||||
val CenterBg = Color(0xFF16213E)
|
||||
val TextPrimary = Color(0xFFFFFFFF)
|
||||
val TextSecondary = Color(0xFFB0BEC5)
|
||||
val Divider = Color(0xFF37474F)
|
||||
val Shadow = Color(0x4D000000)
|
||||
}
|
||||
|
||||
/**
|
||||
* Current date/time info for the wheel hand.
|
||||
*/
|
||||
data class HandInfo(
|
||||
val dayOfYear: Int,
|
||||
val totalDaysInYear: Int,
|
||||
val fractionThroughSeason: Double,
|
||||
val currentSeason: Season
|
||||
) {
|
||||
val angle: Double
|
||||
get() = (dayOfYear.toDouble() / totalDaysInYear) * 2 * Math.PI
|
||||
}
|
||||
Reference in new issue
Block a user