90 lines
3.1 KiB
Kotlin
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]
|
|
}
|
|
}
|