Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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: 2 additions & 0 deletions api/src/main/kotlin/handler/LectureSearchHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ data class SearchQueryLegacy(
val offset: Long = page * 20L,
val limit: Int = 20,
val sortCriteria: String? = null,
val oldCategory: List<String>? = null,
) {
fun toSearchDto(): SearchDto {
return SearchDto(
Expand All @@ -67,6 +68,7 @@ data class SearchQueryLegacy(
offset = offset,
limit = limit,
sortBy = sortCriteria,
oldCategory = oldCategory,
)
}

Expand Down
37 changes: 37 additions & 0 deletions batch/src/main/kotlin/oldcategory/api/GoogleDocsApi.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.wafflestudio.snu4t.oldcategory.api

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.client.reactive.ReactorClientHttpConnector
import org.springframework.web.reactive.function.client.ExchangeStrategies
import org.springframework.web.reactive.function.client.WebClient
import reactor.netty.http.client.HttpClient

@Configuration
class GoogleDocsApiConfig {
companion object {
const val GOOGLE_DOCS_BASE_URL = "https://docs.google.com"
}

@Bean
fun googleDocsApi(): GoogleDocsApi {
val exchangeStrategies: ExchangeStrategies =
ExchangeStrategies.builder()
.codecs { it.defaultCodecs().maxInMemorySize(-1) } // to unlimited memory size
.build()

val httpClient =
HttpClient.create()
.followRedirect(true)
.compress(true)

return WebClient.builder()
.baseUrl(GOOGLE_DOCS_BASE_URL)
.clientConnector(ReactorClientHttpConnector(httpClient))
.exchangeStrategies(exchangeStrategies)
.build()
.let(::GoogleDocsApi)
}
}

class GoogleDocsApi(webClient: WebClient) : WebClient by webClient
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.wafflestudio.snu4t.oldcategory.repository

import com.wafflestudio.snu4t.oldcategory.api.GoogleDocsApi
import org.springframework.core.io.buffer.PooledDataBuffer
import org.springframework.http.MediaType
import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.client.awaitBody
import org.springframework.web.reactive.function.client.awaitExchange
import org.springframework.web.reactive.function.client.createExceptionAndAwait

@Component
class OldCategoryRepository(
private val googleDocsApi: GoogleDocsApi,
) {
companion object {
const val SPREADSHEET_PATH = "/spreadsheets/d"
const val SPREADSHEET_KEY = "/1Ok2gu7rW1VYlKmC_zSjNmcljef0kstm19P9zJ_5s_QA"
}

suspend fun fetchOldCategories(): PooledDataBuffer =
googleDocsApi.get().uri { builder ->
builder.run {
path(SPREADSHEET_PATH)
path(SPREADSHEET_KEY)
path("/export")
queryParam("format", "xlsx")
build()
}
}.accept(MediaType.TEXT_HTML).awaitExchange {
if (it.statusCode().is2xxSuccessful) {
it.awaitBody()
} else {
throw it.createExceptionAndAwait()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.wafflestudio.snu4t.oldcategory.service

import com.wafflestudio.snu4t.oldcategory.repository.OldCategoryRepository
import org.apache.poi.ss.usermodel.WorkbookFactory
import org.springframework.stereotype.Service

@Service
class OldCategoryFetchService(
private val oldCategoryRepository: OldCategoryRepository,
) {
suspend fun getOldCategories(): Map<String, String> {
val oldCategoriesXlsx = oldCategoryRepository.fetchOldCategories()
val workbook = WorkbookFactory.create(oldCategoriesXlsx.asInputStream())
return workbook.sheetIterator().asSequence()
.flatMap { sheet ->
sheet.rowIterator().asSequence()
.drop(3)
.filter { row ->
row.getCell(7).stringCellValue.isNotBlank() && row.getCell(1).stringCellValue.isNotBlank()
}
.map { row ->
try {
val currentCourseNumber = row.getCell(7).stringCellValue
val oldCategory = row.getCell(1).stringCellValue
if (currentCourseNumber.isBlank() || oldCategory.isBlank()) {
Copy link
Contributor

@SeonghaeJo SeonghaeJo Jan 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

위에 isNotBlank로 필터링하는 로직이 있어서 로직이 중복되는 것 같아요.
아래 filter 부분은 없어도 될 것 같아요

.filter { row ->
    row.getCell(7).stringCellValue.isNotBlank() && row.getCell(1).stringCellValue.isNotBlank()
}

return@map null
}
currentCourseNumber to oldCategory
} catch (e: Exception) {
null
}
}
.filterNotNull()
}
.toMap()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ class SugangSnuFetchServiceImpl(
category = "",
classPlaceAndTimes = classTimes,
registrationCount = registrationCount,
oldCategory = null,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.wafflestudio.snu4t.lecturebuildings.service.LectureBuildingService
import com.wafflestudio.snu4t.lectures.data.Lecture
import com.wafflestudio.snu4t.lectures.service.LectureService
import com.wafflestudio.snu4t.lectures.utils.ClassTimeUtils
import com.wafflestudio.snu4t.oldcategory.service.OldCategoryFetchService
import com.wafflestudio.snu4t.sugangsnu.common.SugangSnuRepository
import com.wafflestudio.snu4t.sugangsnu.common.data.SugangSnuCoursebookCondition
import com.wafflestudio.snu4t.sugangsnu.common.service.SugangSnuFetchService
Expand Down Expand Up @@ -46,6 +47,7 @@ interface SugangSnuSyncService {
@Service
class SugangSnuSyncServiceImpl(
private val sugangSnuFetchService: SugangSnuFetchService,
private val oldCategoryFetchService: OldCategoryFetchService,
private val lectureService: LectureService,
private val timeTableRepository: TimetableRepository,
private val sugangSnuRepository: SugangSnuRepository,
Expand All @@ -56,7 +58,15 @@ class SugangSnuSyncServiceImpl(
private val cache: Cache,
) : SugangSnuSyncService {
override suspend fun updateCoursebook(coursebook: Coursebook): List<UserLectureSyncResult> {
val newLectures = sugangSnuFetchService.getSugangSnuLectures(coursebook.year, coursebook.semester)
val oldCategoryMap = oldCategoryFetchService.getOldCategories()
val newLectures =
sugangSnuFetchService.getSugangSnuLectures(coursebook.year, coursebook.semester)
.map { lecture ->
if (oldCategoryMap[lecture.courseNumber] == null || lecture.year < 2025) {
return@map lecture
}
lecture.copy(oldCategory = oldCategoryMap[lecture.courseNumber])
}
val oldLectures =
lectureService.getLecturesByYearAndSemesterAsFlow(coursebook.year, coursebook.semester).toList()
val compareResult = compareLectures(newLectures, oldLectures)
Expand All @@ -71,7 +81,15 @@ class SugangSnuSyncServiceImpl(
}

override suspend fun addCoursebook(coursebook: Coursebook) {
val newLectures = sugangSnuFetchService.getSugangSnuLectures(coursebook.year, coursebook.semester)
val oldCategoryMap = oldCategoryFetchService.getOldCategories()
val newLectures =
sugangSnuFetchService.getSugangSnuLectures(coursebook.year, coursebook.semester)
.map { lecture ->
if (oldCategoryMap[lecture.courseNumber] == null || lecture.year < 2025) {
return@map lecture
}
lecture.copy(oldCategory = oldCategoryMap[lecture.courseNumber])
}
lectureService.upsertLectures(newLectures)
syncTagList(coursebook, newLectures)

Expand Down Expand Up @@ -125,6 +143,7 @@ class SugangSnuSyncServiceImpl(
credit = acc.credit + lecture.credit,
instructor = acc.instructor + lecture.instructor,
category = acc.category + lecture.category,
oldCategory = acc.oldCategory + lecture.oldCategory,
)
}.let { parsedTag ->
TagCollection(
Expand All @@ -135,6 +154,7 @@ class SugangSnuSyncServiceImpl(
credit = parsedTag.credit.sorted().map { "${it}학점" },
instructor = parsedTag.instructor.filterNotNull().filter { it.isNotBlank() }.sorted(),
category = parsedTag.category.filterNotNull().filter { it.isNotBlank() }.sorted(),
oldCategory = parsedTag.oldCategory.filterNotNull().filter { it.isNotBlank() }.sorted(),
)
}
val tagList =
Expand Down Expand Up @@ -347,4 +367,5 @@ data class ParsedTags(
val instructor: Set<String?> = setOf(),
val category: Set<String?> = setOf(),
val etc: Set<String?> = setOf(),
val oldCategory: Set<String?> = setOf(),
)
1 change: 1 addition & 0 deletions core/src/main/kotlin/lectures/data/Lecture.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ data class Lecture(
var registrationCount: Int = 0,
var wasFull: Boolean = false,
val evInfo: EvInfo? = null,
val oldCategory: String?,
) {
infix fun equalsMetadata(other: Lecture): Boolean {
return this === other ||
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/kotlin/lectures/dto/LectureDto.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ data class LectureDto(
val registrationCount: Int,
val wasFull: Boolean,
val snuttEvLecture: SnuttEvLectureSummaryDto? = null,
val oldCategory: String?,
// FIXME: 안드로이드 구버전 대응용 필드 1년 후 2024년에 삭제 (2023/06/26)
@JsonProperty("class_time_mask")
val classTimeMask: List<Int> = emptyList(),
Expand Down Expand Up @@ -61,5 +62,6 @@ fun LectureDto(
registrationCount = lecture.registrationCount,
wasFull = lecture.wasFull,
snuttEvLecture = snuttevLecture,
oldCategory = lecture.oldCategory,
classTimeMask = ClassTimeUtils.classTimeToBitmask(lecture.classPlaceAndTimes),
)
1 change: 1 addition & 0 deletions core/src/main/kotlin/lectures/dto/SearchDto.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ data class SearchDto(
val offset: Long = page * 20L,
val limit: Int = 20,
val sortBy: String?,
val oldCategory: List<String>? = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class LectureCustomRepositoryImpl(
),
)
},
searchCondition.oldCategory?.takeIf { it.isNotEmpty() }?.let { Lecture::oldCategory inValues it },
*searchCondition.etcTags.orEmpty().map { etcTag ->
when (etcTag) {
"E" -> Lecture::remark regex ".*ⓔ.*"
Expand Down
1 change: 1 addition & 0 deletions core/src/main/kotlin/tag/data/TagList.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ data class TagCollection(
val credit: List<String>,
val instructor: List<String>,
val category: List<String>,
val oldCategory: List<String>?,
)
2 changes: 2 additions & 0 deletions core/src/main/kotlin/tag/data/TagListResponse.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ data class TagListResponse(
val sortCriteria: List<String>,
@JsonProperty("updated_at")
val updatedAt: Long,
val oldCategory: List<String>?,
)

fun TagListResponse(tagList: TagList) =
Expand All @@ -30,4 +31,5 @@ fun TagListResponse(tagList: TagList) =
.map { it.fullName }
.filterNot { it == "기본값" },
updatedAt = tagList.updatedAt.toEpochMilli(),
oldCategory = tagList.tagCollection.oldCategory,
)
Loading