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] } }