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

add endTime in Qset #84

Merged
merged 2 commits into from
Aug 10, 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
2 changes: 1 addition & 1 deletion api/src/main/kotlin/com/mashup/dojo/AdminController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class AdminController(
request.questionIds
val customQuestionSet =
questionUseCase.createCustomQuestionSet(
QuestionUseCase.CreateQuestionSetCommand(request.questionIds, request.publishedAt)
QuestionUseCase.CreateQuestionSetCommand(request.questionIds, request.publishedAt, request.endAt)
)

return DojoApiResponse.success(customQuestionSet.id)
Expand Down
2 changes: 2 additions & 0 deletions api/src/main/kotlin/com/mashup/dojo/dto/QuestionDto.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ data class QuestionSetCustomCreateRequest(
val questionIds: List<QuestionId>,
@Schema(description = "μ§ˆλ¬Έμ§€ μ„ΈνŠΈλ₯Ό λ°œν–‰ν•  μ‹œκ°")
val publishedAt: LocalDateTime,
@Schema(description = "μ§ˆλ¬Έμ§€ μ„ΈνŠΈλ₯Ό μ’…λ£Œν•  μ‹œκ°")
val endAt: LocalDateTime,
)

@Schema(description = "μ§ˆλ¬Έμ§€ (νˆ¬ν‘œ μš©μ§€) ν•œ λ‹€μŠ€ 쑰회 응닡")
Expand Down
23 changes: 20 additions & 3 deletions entity/src/main/kotlin/com/mashup/dojo/QuestionSetRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,25 @@ import jakarta.persistence.AttributeConverter
import jakarta.persistence.Column
import jakarta.persistence.Convert
import jakarta.persistence.Entity
import jakarta.persistence.EnumType
import jakarta.persistence.Enumerated
import jakarta.persistence.Id
import jakarta.persistence.Table
import org.springframework.data.jpa.repository.JpaRepository
import java.time.LocalDateTime

interface QuestionSetRepository : JpaRepository<QuestionSetEntity, String> {
// publishedYn : True && publishedAt > now -> ν˜„μž¬ μš΄μ˜μ€‘μΈ QuestionSet
fun findFirstByPublishedYnTrueAndPublishedAtAfterOrderByPublishedAt(compareTime: LocalDateTime = LocalDateTime.now()): QuestionSetEntity?
fun findByPublishedAtAfterAndEndAtBefore(
publishedCompareTime: LocalDateTime = LocalDateTime.now(),
endTimeCompareTime: LocalDateTime = LocalDateTime.now(),
): QuestionSetEntity?

// publishedYn : True && publishedAt < now -> λ°œν–‰ 직전(μ˜ˆμ •) QuestionSet
fun findFirstByPublishedYnTrueAndPublishedAtBeforeOrderByPublishedAt(compareTime: LocalDateTime = LocalDateTime.now()): QuestionSetEntity?
fun findByStatusAndPublishedAtAfter(
status: Status,
compareTime: LocalDateTime = LocalDateTime.now(),
): QuestionSetEntity?

fun findTopByOrderByPublishedAtDesc(): QuestionSetEntity?
}
Expand All @@ -29,11 +37,20 @@ class QuestionSetEntity(
@Column(name = "question_ids", nullable = false)
val questionIds: List<String>,
@Column(name = "published_yn", nullable = false)
val publishedYn: Boolean = false,
@Enumerated(EnumType.STRING)
val status: Status,
@Column(name = "published_at", nullable = false)
val publishedAt: LocalDateTime,
@Column(name = "end_at", nullable = false)
val endAt: LocalDateTime,
) : BaseEntity()

enum class Status {
TERMINATED, // μ’…λ£Œ
ACTIVE, // μš΄μ˜μ€‘
UPCOMING, // μ˜ˆμ •
}

class QuestionIdConverter : AttributeConverter<List<String>, String> {
override fun convertToDatabaseColumn(attribute: List<String>): String {
return attribute.joinToString(DELIMITER)
Expand Down
19 changes: 17 additions & 2 deletions service/src/main/kotlin/com/mashup/dojo/domain/QuestionSet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.mashup.dojo.domain

import com.mashup.dojo.UUIDGenerator
import java.time.LocalDateTime
import java.time.LocalTime

@JvmInline
value class QuestionSetId(val value: String)
Expand All @@ -16,20 +17,34 @@ data class QuestionSet(
// 1 based-order
val questionIds: List<QuestionOrder>,
// λ°œν–‰ μ—¬λΆ€
val publishedYn: Boolean = false,
val status: PublishStatus = PublishStatus.UPCOMING,
// 질문 λ°œν–‰μΌ
val publishedAt: LocalDateTime,
val endAt: LocalDateTime,
) {
companion object {
fun create(
questionOrders: List<QuestionOrder>,
publishedAt: LocalDateTime,
endAt: LocalDateTime,
): QuestionSet {
return QuestionSet(
id = QuestionSetId(UUIDGenerator.generate()),
questionIds = questionOrders,
publishedAt = publishedAt
publishedAt = publishedAt,
endAt = endAt
)
}
}
}

enum class PublishStatus {
TERMINATED, // μ’…λ£Œ
ACTIVE, // μš΄μ˜μ€‘
UPCOMING, // μ˜ˆμ •
}

object PublishedTime {
val OPEN_TIME_1: LocalTime = LocalTime.of(8, 0, 0)
val OPEN_TIME_2: LocalTime = LocalTime.of(11, 0, 0)
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ class DefaultPickService(
): List<Pick> {
return pickRepository.findAllByPickedId(pickedMemberId.value)
.map { it.toPick() }
// return listOf(DEFAULT_PICK)
}

override fun getSolvedPickList(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ import com.mashup.dojo.QuestionSetEntity
import com.mashup.dojo.QuestionSetRepository
import com.mashup.dojo.QuestionSheetEntity
import com.mashup.dojo.QuestionSheetRepository
import com.mashup.dojo.Status
import com.mashup.dojo.domain.ImageId
import com.mashup.dojo.domain.Member
import com.mashup.dojo.domain.MemberId
import com.mashup.dojo.domain.PublishStatus
import com.mashup.dojo.domain.PublishedTime
import com.mashup.dojo.domain.Question
import com.mashup.dojo.domain.QuestionCategory
import com.mashup.dojo.domain.QuestionId
Expand All @@ -26,7 +29,9 @@ import org.springframework.data.domain.Pageable
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import kotlin.math.floor

private val log = KotlinLogging.logger {}
Expand Down Expand Up @@ -58,14 +63,12 @@ interface QuestionService {
emojiImageId: ImageId,
): QuestionId

fun createQuestionSet(
excludedQuestionSet: QuestionSet?,
publishedAt: LocalDateTime,
): QuestionSetId
fun createQuestionSet(excludedQuestionSet: QuestionSet?): QuestionSetId

fun createQuestionSet(
questionIds: List<QuestionId>,
publishedAt: LocalDateTime,
endAt: LocalDateTime,
): QuestionSet

fun createQuestionSheets(
Expand Down Expand Up @@ -107,7 +110,7 @@ class DefaultQuestionService(

// ν˜„μž¬ μš΄μ˜μ€‘μΈ QuestionSet
override fun getOperatingQuestionSet(): QuestionSet? {
return questionSetRepository.findFirstByPublishedYnTrueAndPublishedAtAfterOrderByPublishedAt()
return questionSetRepository.findByPublishedAtAfterAndEndAtBefore(LocalDateTime.now(), LocalDateTime.now())
?.toQuestionSet() ?: run {
log.error { "Published And Operating QuestionSet Entity not found" }
null
Expand All @@ -116,7 +119,7 @@ class DefaultQuestionService(

// λ°œν–‰ 좜격 μ€€λΉ„ μ™„λ£Œ QuestionSet
override fun getNextOperatingQuestionSet(): QuestionSet? {
return questionSetRepository.findFirstByPublishedYnTrueAndPublishedAtBeforeOrderByPublishedAt()
return questionSetRepository.findByStatusAndPublishedAtAfter(Status.UPCOMING, LocalDateTime.now())
?.toQuestionSet() ?: run {
log.error { "Published And Prepared for sortie QuestionSet Entity not found" }
null
Expand All @@ -140,10 +143,7 @@ class DefaultQuestionService(
}

@Transactional
override fun createQuestionSet(
excludedQuestionSet: QuestionSet?,
publishedAt: LocalDateTime,
): QuestionSetId {
override fun createQuestionSet(excludedQuestionSet: QuestionSet?): QuestionSetId {
// λΉ„μœ¨μ— 따라 questionType μ„ μ •
val friendQuestionSize = floor(questionSetSize * friendQuestionRatio).toInt()
val excludedQuestionIds: List<String> = excludedQuestionSet?.questionIds?.map { it.questionId.value } ?: emptyList()
Expand Down Expand Up @@ -172,13 +172,34 @@ class DefaultQuestionService(
QuestionOrder(questionId = question.id, order = index)
}

// λ§ˆμ§€λ§‰ QSet 의 λ°œν–‰ μ‹œκ° κ°€μ Έμ˜€κΈ°
val latestQSet = getLatestPublishedQuestionSet()

val publishedTime =
latestQSet?.endAt ?: run {
val now = LocalTime.now()
val today = LocalDate.now()

when {
now.isBefore(PublishedTime.OPEN_TIME_1) -> today.atTime(PublishedTime.OPEN_TIME_1)
now.isBefore(PublishedTime.OPEN_TIME_2) -> today.atTime(PublishedTime.OPEN_TIME_2)
else -> today.plusDays(1).atTime(PublishedTime.OPEN_TIME_1)
}
}

val endTime =
if (publishedTime.toLocalTime() == PublishedTime.OPEN_TIME_1) {
publishedTime.toLocalDate().atTime(PublishedTime.OPEN_TIME_2)
} else { // publishedTime.toLocalTime() == PublishedTime.OPEN_TIME_2
publishedTime.toLocalDate().plusDays(1).atTime(PublishedTime.OPEN_TIME_1)
}

// μš°μ„  λ§Œλ“€μ–΄μ§€λŠ” μ‹œμ μ΄ λ‹€μŒ νˆ¬ν‘œ 이전에 λ§Œλ“€μ–΄μ§ˆ QSet 을 λ§Œλ“ λ‹€κ³  κ°€μ •, λ”°λΌμ„œ ν•΄λ‹Ή QSet 은 λ°”λ‘œ λ‹€μŒ λ°œν–‰λ  QSet
// todo: QSetμ—μ„œ publishedAt 이 κ°€μž₯ 큰 녀석 κ°€μ Έμ˜¨ ν›„ ν•΄λ‹Ή publishedAt 보닀 큰 startTime 을 가진 PickTime 정보 κ°€μ Έμ˜΄
// (fix publishedAt) ν˜„μž¬ PickTime Entity λŠ” LocalTime 으둜 μ €μž₯되고 있음. LocalDateTime 이어야 μœ„ 가정이 유효
val questionSetEntity =
QuestionSet.create(
questionOrders = questionOrders,
publishedAt = publishedAt
publishedAt = publishedTime,
endAt = endTime
).toEntity()

val id = questionSetRepository.save(questionSetEntity).id
Expand All @@ -190,12 +211,13 @@ class DefaultQuestionService(
override fun createQuestionSet(
questionIds: List<QuestionId>,
publishedAt: LocalDateTime,
endAt: LocalDateTime,
): QuestionSet {
require(questionIds.size == questionSetSize) { "questions size for QuestionSet must be $questionSetSize" }
require(publishedAt >= LocalDateTime.now()) { "publishedAt must be in the future" }

val questionOrders = questionIds.mapIndexed { idx, qId -> QuestionOrder(qId, idx + 1) }
val questionSet = QuestionSet.create(questionOrders, publishedAt)
val questionSet = QuestionSet.create(questionOrders, publishedAt, endAt)

questionSetRepository.save(questionSet.toEntity())
return questionSet
Expand Down Expand Up @@ -235,7 +257,7 @@ class DefaultQuestionService(
emojiImageId = ImageId("345678")
)

val SAMPLE_QUESTION_SET =
private val SAMPLE_QUESTION_SET =
QuestionSet(
id = QuestionSetId("1"),
questionIds =
Expand All @@ -253,7 +275,8 @@ class DefaultQuestionService(
QuestionOrder(QuestionId("11"), 11),
QuestionOrder(QuestionId("12"), 12)
),
publishedAt = LocalDateTime.now()
publishedAt = LocalDateTime.now(),
endAt = LocalDateTime.now().plusHours(12)
)

private val SAMPLE_QUESTION_SHEET =
Expand Down Expand Up @@ -332,7 +355,9 @@ private fun QuestionSet.toEntity(): QuestionSetEntity {
return QuestionSetEntity(
id = id.value,
questionIds = questionIds,
publishedAt = publishedAt
status = status.toDomainPublishStatus(),
publishedAt = publishedAt,
endAt = endAt
)
}

Expand All @@ -348,7 +373,9 @@ private fun QuestionSetEntity.toQuestionSet(): QuestionSet {
return QuestionSet(
id = QuestionSetId(id),
questionIds = questionOrders,
publishedAt = publishedAt
status = status.toDomainPublishStatus(),
publishedAt = publishedAt,
endAt = endAt
)
}

Expand All @@ -361,3 +388,19 @@ private fun QuestionSheetEntity.toQuestionSheetWithCandidatesId(): QuestionSheet
candidates = candidates.map { MemberId(it) }.toList()
)
}

private fun Status.toDomainPublishStatus(): PublishStatus {
return when (this) {
Status.TERMINATED -> PublishStatus.TERMINATED
Status.ACTIVE -> PublishStatus.ACTIVE
Status.UPCOMING -> PublishStatus.UPCOMING
}
}

private fun PublishStatus.toDomainPublishStatus(): Status {
return when (this) {
PublishStatus.TERMINATED -> Status.TERMINATED
PublishStatus.ACTIVE -> Status.ACTIVE
PublishStatus.UPCOMING -> Status.UPCOMING
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ interface QuestionUseCase {
data class CreateQuestionSetCommand(
val questionIdList: List<QuestionId>,
val publishedAt: LocalDateTime,
val endAt: LocalDateTime,
)

data class GetQuestionSheetsResult(
Expand Down Expand Up @@ -105,15 +106,14 @@ class DefaultQuestionUseCase(
@Transactional
override fun createQuestionSet(): QuestionSetId {
// κ°€μž₯ λ§ˆμ§€λ§‰μ— λ§Œλ“€μ–΄μ§„ QSet μ •λ³΄λŠ” μ œμ™Έ
val currentQuestionSet = questionService.getLatestPublishedQuestionSet()
val nextPickTime = pickService.getNextPickTime()
val latestQSet = questionService.getLatestPublishedQuestionSet()

return questionService.createQuestionSet(excludedQuestionSet = currentQuestionSet, nextPickTime)
return questionService.createQuestionSet(excludedQuestionSet = latestQSet)
}

@Transactional
override fun createCustomQuestionSet(command: QuestionUseCase.CreateQuestionSetCommand): QuestionSet {
return questionService.createQuestionSet(command.questionIdList, command.publishedAt)
return questionService.createQuestionSet(command.questionIdList, command.publishedAt, command.endAt)
}

@Transactional
Expand Down
Loading