Files
ShiftRing/app/src/main/java/com/example/shiftalarm/ShiftCalculator.kt

90 lines
3.1 KiB
Kotlin

package com.example.shiftalarm
import java.time.LocalDate
import java.time.ZoneId
import java.time.temporal.ChronoUnit
object ShiftCalculator {
val SEOUL_ZONE: ZoneId = ZoneId.of("Asia/Seoul")
val BASE_DATE: LocalDate = LocalDate.of(2026, 2, 1)
// Provided list has 20 items.
// "석간 석간 석간 휴 휴" (5)
// "주간 주간 주간 주간 주간 휴 휴" (7)
// "야간 야간 야간 야간 야간 휴" (6)
// "석간 석간" (2)
// Total 20.
val cycle = listOf(
"석간", "석간", "석간", "휴무", "휴무",
"주간", "주간", "주간", "주간", "주간", "휴무", "휴무",
"야간", "야간", "야간", "야간", "야간", "휴무",
"석간", "석간"
)
val CYCLE_LENGTH = cycle.size
val TEAM_OFFSETS = mapOf(
"A" to 0,
"B" to 15,
"C" to 10,
"D" to 5
)
fun getShift(date: LocalDate, team: String, factory: String = "Jeonju"): String {
return when (factory) {
"Nonsan" -> calculateNonsanShift(date, team)
else -> calculateJeonjuShift(date, team)
}
}
private fun calculateJeonjuShift(date: LocalDate, team: String): String {
val teamOffset = TEAM_OFFSETS[team] ?: 0
val days = ChronoUnit.DAYS.between(BASE_DATE, date).toInt()
val index = Math.floorMod(days + teamOffset, CYCLE_LENGTH)
return cycle[index]
}
private fun calculateNonsanShift(date: LocalDate, team: String): String {
// Nonsan Factory Logic
// Mon-Fri: Work, Sat-Sun: Rest (Off) -> "휴무"
// Base Date: 2026-02-09 (Monday)
// Groups: A, B, C
// User Requirement (Step 145):
// Feb 9 week: Day (주간)
// Feb 16 week: Night (야간)
// Feb 23 week: Evening (석간)
// Cycle: Day -> Night -> Evening
val dayOfWeek = date.dayOfWeek.value // 1=Mon, ..., 7=Sun
if (dayOfWeek >= 6) return "휴무" // Sat, Sun is OFF
// Base Date: 2026-02-09 (Monday)
val baseDateNonsan = LocalDate.of(2026, 2, 9)
// Calculate days between Monday of the target date and base date
// To be safe for "Any date before", we align target date to its Monday
val targetMonday = date.minusDays((dayOfWeek - 1).toLong()) // Align to Monday
val daysDiff = ChronoUnit.DAYS.between(baseDateNonsan, targetMonday).toInt()
val weeksPassed = daysDiff / 7
// Rotation Pattern: 주간 -> 야간 -> 석간
// Index: 0=주간, 1=야간, 2=석간
val rotation = listOf("주간", "야간", "석간")
// Start indices for 2026-02-09 (Week 0)
// A: 주간 (0) -> Matches User Specification
// B, C: Distributed to other shifts.
// Assuming A=0(Day), B=1(Night), C=2(Evening)
val startOffset = when (team) {
"A" -> 0 // 주간
"B" -> 1 // 야간
"C" -> 2 // 석간
else -> 0
}
val currentIndex = Math.floorMod(startOffset + weeksPassed, 3)
return rotation[currentIndex]
}
}