diff --git a/src/main/kotlin/busanVibe/busan/domain/place/controller/PlaceCongestionController.kt b/src/main/kotlin/busanVibe/busan/domain/place/controller/PlaceCongestionController.kt index cb1df41..ecb4690 100644 --- a/src/main/kotlin/busanVibe/busan/domain/place/controller/PlaceCongestionController.kt +++ b/src/main/kotlin/busanVibe/busan/domain/place/controller/PlaceCongestionController.kt @@ -50,8 +50,23 @@ class PlaceCongestionController ( return ApiResponse.onSuccess(place) } - @GetMapping("/place/{placeId}/real-time") - @Operation(summary = "명소 실시간 혼잡도 조회") + @GetMapping("/place/{placeId}/congestions") + @Operation(summary = "명소 혼잡도 조회", + description = + """ + * congestions_by_day : 각 요일별 현재시간 기준 혼잡도 + - index [ 0:월, 1:화 ... 5:토, 6:일 ] + + * congestions_by_time : 각 요일별 시간별 혼잡도 ( 0~23시 제공 ) + - 명소의 모든 요일의 혼잡도 제공 + - 총 7개의 배열, 각 배열에는 24개의 혼잡도 정보 담김 + + * standard_day와 standard_time 활용해서 현재시간 판단 가능합니다. + 이거도 마찬가지로 0:월 ~ 6:일 + + * 현재(실시간) 혼잡도는 real_time_congestion_level 이용하면 됩니다. + """ + ) fun placeRealTimeCongestion( @PathVariable("placeId") placeId: Long): ApiResponse{ val congestion = placeCongestionQueryService.getCongestion(placeId) diff --git a/src/main/kotlin/busanVibe/busan/domain/place/dto/PlaceMapResponseDTO.kt b/src/main/kotlin/busanVibe/busan/domain/place/dto/PlaceMapResponseDTO.kt index 940f0d9..330c631 100644 --- a/src/main/kotlin/busanVibe/busan/domain/place/dto/PlaceMapResponseDTO.kt +++ b/src/main/kotlin/busanVibe/busan/domain/place/dto/PlaceMapResponseDTO.kt @@ -39,9 +39,11 @@ class PlaceMapResponseDTO { @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class) data class PlaceCongestionDto( + val standardDay: Int, val standardTime: Int, val realTimeCongestionLevel: Int, - val byTimePercent: List + val congestionsByDay: List, + val congestionsByTime: List> ) @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy::class) diff --git a/src/main/kotlin/busanVibe/busan/domain/place/service/PlaceCongestionQueryService.kt b/src/main/kotlin/busanVibe/busan/domain/place/service/PlaceCongestionQueryService.kt index 09f43be..7ad7234 100644 --- a/src/main/kotlin/busanVibe/busan/domain/place/service/PlaceCongestionQueryService.kt +++ b/src/main/kotlin/busanVibe/busan/domain/place/service/PlaceCongestionQueryService.kt @@ -119,28 +119,36 @@ class PlaceCongestionQueryService( @Transactional(readOnly = true) fun getCongestion(placeId: Long): PlaceMapResponseDTO.PlaceCongestionDto { - val current = LocalDateTime.now() - log.info("현재 시간: ${current}시") - - val roundedBase = (current.hour / 3) * 3 - - // 최근 6개 3시간 단위 시간 생성 (기준시간 포함 총 7개) - val hours = (-3 .. 3).map { i -> (roundedBase - i * 3 + 24) % 24 } + // 현재시간 기준 LocalDateTime + val currentDateTime = LocalDateTime.now() + + // 혼잡도 리스트 + val congestionsByDay: MutableList = mutableListOf() // 요일별 + val congestionsByTime: MutableList> = mutableListOf() // 시간대별 + + // 시간대별 혼잡도 ( 월~일, 0~23시 ) + for( day in 1..7){ + val congestions = mutableListOf() // 각 요일의 혼잡도 정보 담을 List + for( hour in 0..23){ + congestions.add(placeRedisUtil.getTimeCongestion(placeId, day, hour)) + } + congestionsByTime.add(congestions) + } - val byTimePercent: List = hours.map { hour -> - val adjustedDateTime = current.withHour(hour) - .withMinute(0).withSecond(0).withNano(0) - .let { - if (hour > current.hour) it.minusDays(1) else it - } - placeRedisUtil.getTimeCongestion(placeId, adjustedDateTime) + // 요일별 현재 시간의 혼잡도 + for( day in 1..7){ + congestionsByDay.add(placeRedisUtil.getTimeCongestion(placeId, day, currentDateTime.hour)) } + // DTO 생성 및 반환 return PlaceMapResponseDTO.PlaceCongestionDto( - standardTime = roundedBase, - realTimeCongestionLevel = placeRedisUtil.getTimeCongestion(placeId, current).toInt(), - byTimePercent = byTimePercent + standardDay = currentDateTime.dayOfWeek.value-1, // 원래 1:월~7:일인데, 0:월~6일로 변경해서 반환 + standardTime = currentDateTime.hour, // 0~23 + realTimeCongestionLevel = placeRedisUtil.getTimeCongestion(placeId).toInt(), + congestionsByDay = congestionsByDay, + congestionsByTime = congestionsByTime ) + } @Transactional(readOnly = false) diff --git a/src/main/kotlin/busanVibe/busan/domain/place/util/PlaceRedisUtil.kt b/src/main/kotlin/busanVibe/busan/domain/place/util/PlaceRedisUtil.kt index 04aee1b..b032596 100644 --- a/src/main/kotlin/busanVibe/busan/domain/place/util/PlaceRedisUtil.kt +++ b/src/main/kotlin/busanVibe/busan/domain/place/util/PlaceRedisUtil.kt @@ -13,46 +13,55 @@ class PlaceRedisUtil( private val log = LoggerFactory.getLogger("busanVibe.busan.domain.place") - // 임의로 혼잡도 생성하여 반환. 레디스 키 값으로 저장함. -// fun getRedisCongestion(placeId: Long?): Int{ -// -// val key = "place:congestion:$placeId" -// val randomCongestion = getRandomCongestion().toInt().toString() -// -// redisTemplate.opsForValue() -// .set(key, randomCongestion) -// -// return Integer.parseInt(randomCongestion) -// } + // 현재 시간 기준 혼잡도 구하는 메서드 + // 현재에 해당하는 요일과 시간의 혼잡도 반환 + fun getTimeCongestion(placeId: Long?):Float{ + return getTimeCongestion(placeId, LocalDateTime.now()) + } + + /** + * [요일(1=Mon..7=Sun), 시간]으로 혼잡도 구하는 메서드 + * @param placeId 조회 대상 장소 ID + * @param dayOfWeek 1..7 (1=월요일, 7=일요일) + * @param hour 0..23 + */ + fun getTimeCongestion(placeId: Long?, day: Int, hour: Int): Float{ + val now = LocalDateTime.now() + return getTimeCongestion( + placeId, + LocalDateTime.of( + now.year, + now.month, + day, + hour, + now.minute + ) + ) + } // 지정 시간 혼잡도 조회 - // null이면 현재시간 기준 fun getTimeCongestion(placeId: Long?, dateTime: LocalDateTime?): Float { + // DateTime val dateTime = dateTime ?: LocalDateTime.now() - val roundedHour = (dateTime.hour / 3) * 3 - val key = "place:congestion:$placeId-${dateTime.year}-${dateTime.monthValue}-${dateTime.dayOfMonth}-$roundedHour" - + val key = getCongestionRedisKey(placeId, dateTime) val value = redisTemplate.opsForValue().get(key) - return (if (value != null) { - value.toFloatOrNull() ?: 0 - } else { - setPlaceTimeCongestion(placeId, dateTime.withHour(roundedHour)) - val newValue = redisTemplate.opsForValue().get(key) - newValue?.toFloatOrNull() ?: 0 - }) as Float - } + val parsed = value?.toFloatOrNull() - fun getTimeCongestion(placeId: Long?):Float{ - return getTimeCongestion(placeId, LocalDateTime.now()) + // 값이 존재하교 유효하다면 + if (parsed != null)return parsed // 그대로 반환 + + // 값이 없다면 + setPlaceTimeCongestion(placeId, dateTime) // 새로 만들어서 할당 + val newValue = redisTemplate.opsForValue().get(key)?.toFloatOrNull() // 새로 설정한 값 조회 + return newValue ?: 0f // 반환, 값이 이상하다면 0 반환 } // 시간 혼잡도 설정 private fun setPlaceTimeCongestion(placeId: Long?, dateTime: LocalDateTime) { - val roundedHour = (dateTime.hour / 3) * 3 - val key = "place:congestion:$placeId-${dateTime.year}-${dateTime.monthValue}-${dateTime.dayOfMonth}-$roundedHour" + val key = getCongestionRedisKey(placeId, dateTime) val congestion = getRandomCongestion().toString() val success = redisTemplate.opsForValue().setIfAbsent(key, congestion, Duration.ofHours(24)) @@ -65,9 +74,11 @@ class PlaceRedisUtil( } // 혼잡도 생성 (1.0 ~ 5.0 사이의 Float) - private fun getRandomCongestion(): Float { - return (Math.random() * 4 + 1).toFloat() - } + private fun getRandomCongestion(): Float = (Math.random() * 4 + 1).toFloat() + + // redis에 저장할 key 생성 + private fun getCongestionRedisKey(placeId: Long?, dateTime: LocalDateTime): String + = "place:congestion:${placeId}-${dateTime.dayOfWeek}-${dateTime.hour}" } \ No newline at end of file