Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 6차 mvp #46

Merged
merged 1 commit into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.ddd.sonnypolabobe.domain.sticker.controller

import com.ddd.sonnypolabobe.domain.sticker.dto.StickerUseRequest
import com.ddd.sonnypolabobe.domain.sticker.service.StickerService
import com.ddd.sonnypolabobe.domain.user.dto.UserDto
import com.ddd.sonnypolabobe.global.response.ApplicationResponse
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import jakarta.validation.Valid
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/api/v1/stickers")
class StickerController(
private val stickerService: StickerService
) {

@Tag(name = "1.5.0")
@Operation(
summary = "스티커 사용 이력 저장", description = "보드에 사용한 스티커 ID를 배열에 담아 모두 보내주세요."
)
@PostMapping("/use")
fun useSticker(
@RequestBody @Valid request: StickerUseRequest
) : ApplicationResponse<Nothing> {
val user = SecurityContextHolder.getContext().authentication.principal as UserDto.Companion.Res
stickerService.use(request, user)
return ApplicationResponse.ok()
}

@Tag(name = "1.5.0")
@Operation(
summary = "최근 사용한 스티커 조회", description = "최근 30일 이내에 사용한 스티커를 조회합니다."
)
@GetMapping("/recent-use")
fun getRecentUseSticker() : ApplicationResponse<Set<String>> {
val user = SecurityContextHolder.getContext().authentication.principal as UserDto.Companion.Res
return ApplicationResponse.ok(stickerService.getRecentUse(user))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.ddd.sonnypolabobe.domain.sticker.dto

import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotBlank

@Schema(description = "스티커 사용 이력 저장")
data class StickerUseRequest(
@field:Schema(description = "스티커 ID 리스트", example = "[\"STK_0001\",\"STK_0001\"]")
val stickerIds: List<String>,
@field:Schema(description = "게시글 ID", example = "adksjfldskjglaijg")
@field:NotBlank(message = "게시글 ID는 필수입니다.")
val boardId: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.ddd.sonnypolabobe.domain.sticker.repository

import com.ddd.sonnypolabobe.domain.sticker.dto.StickerUseRequest
import com.ddd.sonnypolabobe.domain.user.dto.UserDto

interface StickerJooqRepository {
fun insertAll(request: StickerUseRequest, user: UserDto.Companion.Res)
fun readAllByUserId(userId: Long): Set<String>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.ddd.sonnypolabobe.domain.sticker.repository

import com.ddd.sonnypolabobe.domain.sticker.dto.StickerUseRequest
import com.ddd.sonnypolabobe.domain.user.dto.UserDto
import com.ddd.sonnypolabobe.global.util.DateConverter
import com.ddd.sonnypolabobe.global.util.UuidConverter
import com.ddd.sonnypolabobe.jooq.polabo.tables.references.STICKER_USE_HISTORY
import org.jooq.DSLContext
import org.springframework.stereotype.Repository
import java.time.LocalDateTime

@Repository
class StickerJooqRepositoryImpl(private val dslContext: DSLContext) : StickerJooqRepository{
override fun insertAll(request: StickerUseRequest, user: UserDto.Companion.Res) {
dslContext.batchInsert(
request.stickerIds.map {
STICKER_USE_HISTORY.newRecord().apply {
this.userId = user.id
this.stickerId = it
this.boardId = UuidConverter.uuidToByteArray(UuidConverter.stringToUUID(request.boardId))
this.createdAt = DateConverter.convertToKst(LocalDateTime.now())
}
}
).execute()

}

override fun readAllByUserId(userId: Long): Set<String> {
return dslContext.select(STICKER_USE_HISTORY.STICKER_ID)
.from(STICKER_USE_HISTORY)
.where(STICKER_USE_HISTORY.USER_ID.eq(userId).and(
STICKER_USE_HISTORY.CREATED_AT.gt(
DateConverter.convertToKst(LocalDateTime.now().minusDays(30))
)
))
.fetchInto(String::class.java)
.toSet()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.ddd.sonnypolabobe.domain.sticker.service

import com.ddd.sonnypolabobe.domain.sticker.dto.StickerUseRequest
import com.ddd.sonnypolabobe.domain.sticker.repository.StickerJooqRepository
import com.ddd.sonnypolabobe.domain.user.dto.UserDto
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class StickerService(
private val stickerJooqRepository: StickerJooqRepository
) {
@Transactional
fun use(request: StickerUseRequest, user: UserDto.Companion.Res) {
stickerJooqRepository.insertAll(request, user)
}

@Transactional(readOnly = true)
fun getRecentUse(user: UserDto.Companion.Res): Set<String> {
return stickerJooqRepository.readAllByUserId(user.id)
}
}
190 changes: 0 additions & 190 deletions src/test/kotlin/com/ddd/sonnypolabobe/SonnyPolaboBeApplicationTests.kt
Original file line number Diff line number Diff line change
@@ -1,196 +1,6 @@
package com.ddd.sonnypolabobe

import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import java.util.*

//@SpringBootTest
class SonnyPolaboBeApplicationTests {

@Test
fun contextLoads() {
println(solution(2, 10, intArrayOf(7,4,5,6))) // 8
// println(solution(arrayOf(
// intArrayOf(1,2,1),
// intArrayOf(8,2,0),
// intArrayOf(1,7,2)
// ), intArrayOf(0, 0))) // true
// println(solution(arrayOf(
// intArrayOf(1,2,3,2,1),
// intArrayOf(4,2,0,7,2),
// intArrayOf(1,3,3,8,1),
// intArrayOf(2,0,1,1,1),
// intArrayOf(8,2,8,1,1)
// ), intArrayOf(0, 0))) // false

// println(solution(arrayOf(
// intArrayOf(1,2,3,2,1),
// intArrayOf(4,2,0,7,1),
// intArrayOf(1,3,2,8,1),
// intArrayOf(2,0,1,1,1),
// intArrayOf(8,2,1,2,1)
// ), intArrayOf(4,3)
// )) // true
// println(solution(
// intArrayOf(23), // 고객 수
// intArrayOf(12, 3, 19), // 모델 처리량
// intArrayOf(28, 10, 35) // 모델 비용
// ))

}

fun solution(bridge_length: Int, weight: Int, truck_weights: IntArray): Int {
var answer = 0

val queue: Queue<Int> = LinkedList()
var totalWeight = 0

for(truck in truck_weights) {
queue.add(truck)
}

val bridge = LinkedList(List(bridge_length) { 0 })

while(bridge.isNotEmpty()) {
answer++

totalWeight -= bridge.poll() // 다리를 건넌 트럭의 무게를 빼준다.

if(queue.isNotEmpty()) {
val nextWeight = queue.peek()
if(nextWeight + totalWeight <= weight ) {
totalWeight += nextWeight
bridge.add(queue.poll())
} else {
bridge.add(0)
}
}


}


// while (bridge.isNotEmpty()) {
// answer++
// totalWeight -= bridge.poll()
//
// if (waiting.isNotEmpty()) {
// val nextWeight = waiting.peek()
//
// if (totalWeight + nextWeight <= weight) {
// totalWeight += nextWeight
// bridge.add(waiting.poll())
// } else {
// bridge.add(0)
// }
// }
// }
return answer
}


// fun solution(map : Array<IntArray>, entrancePoint: IntArray) : Boolean {
// // 출발점에서 닭가슴살을 찾을 수 있는지 여부가 answer
// // 닭가슴살은 7
// // 액상 과당은 0, 초콜릿은 8 이라고 할 때
// // map에서 출발점을 기준으로는 좌우로만 갈 수 있다.
// // 이후에는 위 아래로 갈 수 있다.
// // 그 다음에는 좌우로만 갈 수 있다. 이 구성을 반복한다고 할 때 이동 방향으로는 현재 위치의 숫자만큼 간다.
// // 이동의 도착점에 액상 과당이나 초콜릿이 있다면 false를 반환한다.
// // 영역을 벗어나도 false를 반환한다.
//
// var answer = false
// var x = entrancePoint[0]
// var y = entrancePoint[1]
// var direction = if (x % 2 == 0) 0 else 2
// var nextX = 0
// var nextY = 0
//
// while (true) {
// if (map[x][y] == 7) {
// answer = true
// break
// }
// if (map[x][y] == 0 || map[x][y] == 8) {
// break
// }
// when (direction) {
// 0 -> {
// nextX = x
// nextY = y + map[x][y]
// }
// 1 -> {
// nextX = x + map[x][y]
// nextY = y
// }
// 2 -> {
// nextX = x
// nextY = y - map[x][y]
// }
// 3 -> {
// nextX = x - map[x][y]
// nextY = y
// }
// }
// if (nextX < 0 || nextX >= map.size || nextY < 0 || nextY >= map[0].size) {
// break
// }
// x = nextX
// y = nextY
// direction = (direction + 1) % 4 // 방향을 바꾼다.
// }
// return answer
//
// }

// fun solution(customers : IntArray, modelCapacities: IntArray, modelCosts: IntArray) : Int {
// var answer = 0
//
// // 매 시간 고객의 접수 건을 담고 있는 배열 customers
// // 각 모델의 처리량을 담고 있는 배열 modelCapacities 예를 들면, A-12, B-3, C-19
// // 각 모델의 비용을 담고 있는 배열 modelCosts 예를 들면, A-28, B-10, C-35
// // 각 모델은 1시간에 위 처리량만큼 처리할 수 있다.
//
// // 최소 비용으로 처리하고자 할 때, 그 비용을 반환한다.
//
// // 모델의 처리량과 비용을 (처리량, 비용) 쌍으로 묶고, 처리량이 큰 순으로 정렬
// val pair = modelCapacities.zip(modelCosts).sortedByDescending { it.first }
//
// for (customer in customers) {
// var minCost = Int.MAX_VALUE
//
// for (i in pair.indices) {
// val (capacity, cost) = pair[i]
// val fullModelsNeeded = customer / capacity
// val remainder = customer % capacity
//
// // 총 비용 계산
// var totalCost = cost * fullModelsNeeded
//
// // 잔여 고객 처리 비용 추가
// if (remainder > 0) {
// // 잔여 고객을 처리하기 위한 최소 비용을 계산
// var extraCost = Int.MAX_VALUE
// for (j in pair.indices) {
// val (extraCapacity, extraCostValue) = pair[j]
// if (extraCapacity >= remainder) {
// extraCost = minOf(extraCost, extraCostValue)
// }
// }
// totalCost += extraCost
// }
//
// // 최소 비용 업데이트
// minCost = minOf(minCost, totalCost)
// }
// answer += minCost
// }
//
// return answer
// }





}