Skip to content

Commit

Permalink
core & db & frontend: delete DbCardRepository#learnCards with movin…
Browse files Browse the repository at this point in the history
…g logic to core (use `*#updateCards` instead), fix some mistakes in front and db-mem
  • Loading branch information
sszuev committed Mar 10, 2024
1 parent 4d23f11 commit 2bca710
Show file tree
Hide file tree
Showing 15 changed files with 72 additions and 150 deletions.
6 changes: 0 additions & 6 deletions common/src/commonMain/kotlin/repositories/DbCardRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import com.gitlab.sszuev.flashcards.model.common.AppUserId
import com.gitlab.sszuev.flashcards.model.domain.CardEntity
import com.gitlab.sszuev.flashcards.model.domain.CardFilter
import com.gitlab.sszuev.flashcards.model.domain.CardId
import com.gitlab.sszuev.flashcards.model.domain.CardLearn
import com.gitlab.sszuev.flashcards.model.domain.DictionaryEntity
import com.gitlab.sszuev.flashcards.model.domain.DictionaryId

Expand Down Expand Up @@ -44,11 +43,6 @@ interface DbCardRepository {
*/
fun updateCards(userId: AppUserId, cardIds: Iterable<CardId>, update: (CardEntity) -> CardEntity): CardsDbResponse

/**
* Updates cards details.
*/
fun learnCards(userId: AppUserId, cardLearns: List<CardLearn>): CardsDbResponse

/**
* Resets status.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import com.gitlab.sszuev.flashcards.model.common.AppUserId
import com.gitlab.sszuev.flashcards.model.domain.CardEntity
import com.gitlab.sszuev.flashcards.model.domain.CardFilter
import com.gitlab.sszuev.flashcards.model.domain.CardId
import com.gitlab.sszuev.flashcards.model.domain.CardLearn
import com.gitlab.sszuev.flashcards.model.domain.DictionaryId

object NoOpDbCardRepository : DbCardRepository {
Expand Down Expand Up @@ -36,10 +35,6 @@ object NoOpDbCardRepository : DbCardRepository {
noOp()
}

override fun learnCards(userId: AppUserId, cardLearns: List<CardLearn>): CardsDbResponse {
noOp()
}

override fun resetCard(userId: AppUserId, cardId: CardId): CardDbResponse {
noOp()
}
Expand Down
5 changes: 1 addition & 4 deletions core/src/main/kotlin/processes/CardProcessWorkers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,7 @@ fun ChainDSL<CardContext>.processLearnCards() = worker {
this.status == AppStatus.RUN
}
process {
val userId = this.contextUserEntity.id
val res =
this.repositories.cardRepository(this.workMode).learnCards(userId, this.normalizedRequestCardLearnList)
this.postProcess(res)
this.postProcess(this.learnCards())
}
onException {
this.handleThrowable(CardOperation.LEARN_CARDS, it)
Expand Down
22 changes: 22 additions & 0 deletions core/src/main/kotlin/processes/UpdateCardsHelper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.gitlab.sszuev.flashcards.core.processes

import com.gitlab.sszuev.flashcards.CardContext
import com.gitlab.sszuev.flashcards.repositories.CardsDbResponse

fun CardContext.learnCards(): CardsDbResponse {
val cards = this.normalizedRequestCardLearnList.associateBy { it.cardId }
return this.repositories.cardRepository(this.workMode).updateCards(this.contextUserEntity.id, cards.keys) { card ->
val learn = checkNotNull(cards[card.cardId])
var answered = card.answered?.toLong() ?: 0L
val details = card.stats.toMutableMap()
learn.details.forEach {
answered += it.value.toInt()
require(answered < Int.MAX_VALUE && answered > Int.MIN_VALUE)
if (answered < 0) {
answered = 0
}
details.merge(it.key, it.value) { a, b -> a + b }
}
card.copy(stats = details, answered = answered.toInt())
}
}
4 changes: 2 additions & 2 deletions core/src/main/kotlin/validators/CardValidateWorkers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ fun ChainDSL<CardContext>.validateCardLearnListDetails(getCardLearn: (CardContex
}
}
) { (_, score) ->
// right not just check score is positive and not big
score <= 0 || score > 42
// right not just check score is not big
score < -42 || score > 42
}

private fun ChainDSL<CardContext>.validateIds(
Expand Down
16 changes: 6 additions & 10 deletions core/src/test/kotlin/CardCorProcessorRunCardsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.EnumSource

@Suppress("OPT_IN_USAGE")
internal class CardCorProcessorRunCardsTest {
companion object {
private val testUser = AppUserEntity(AppUserId("42"), AppAuthId("00000000-0000-0000-0000-000000000000"))
Expand Down Expand Up @@ -225,10 +224,6 @@ internal class CardCorProcessorRunCardsTest {
val context = testContext(CardOperation.CREATE_CARD, repository)
context.requestCardEntity = testRequestEntity

context.errors.forEach { // TODO
println(it)
}

CardCorProcessor().execute(context)

Assertions.assertTrue(wasCalled)
Expand Down Expand Up @@ -358,10 +353,10 @@ context.errors.forEach { // TODO

var wasCalled = false
val repository = MockDbCardRepository(
invokeLearnCards = { _, it ->
invokeUpdateCards = { _, givenIds, _ ->
wasCalled = true
CardsDbResponse(
cards = if (it == testLearn) testResponseEntities else emptyList(),
cards = if (givenIds == setOf(stubCard.cardId)) testResponseEntities else emptyList(),
)
}
)
Expand All @@ -384,6 +379,7 @@ context.errors.forEach { // TODO
CardLearn(cardId = CardId("1"), details = mapOf(Stage.SELF_TEST to 42)),
CardLearn(cardId = CardId("2"), details = mapOf(Stage.OPTIONS to 2, Stage.MOSAIC to 3))
)
val ids = testLearn.map { it.cardId }.toSet()

val testResponseEntities = stubCards
val testResponseErrors = listOf(
Expand All @@ -392,11 +388,11 @@ context.errors.forEach { // TODO

var wasCalled = false
val repository = MockDbCardRepository(
invokeLearnCards = { _, it ->
invokeUpdateCards = { _, givenIds, _ ->
wasCalled = true
CardsDbResponse(
cards = if (it == testLearn) testResponseEntities else emptyList(),
errors = if (it == testLearn) testResponseErrors else emptyList()
cards = if (givenIds == ids) testResponseEntities else emptyList(),
errors = if (givenIds == ids) testResponseErrors else emptyList()
)
}
)
Expand Down
15 changes: 12 additions & 3 deletions core/src/test/kotlin/CardCorProcessorValidationTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,16 @@ import com.gitlab.sszuev.flashcards.model.common.AppAuthId
import com.gitlab.sszuev.flashcards.model.common.AppError
import com.gitlab.sszuev.flashcards.model.common.AppMode
import com.gitlab.sszuev.flashcards.model.common.AppRequestId
import com.gitlab.sszuev.flashcards.model.domain.*
import com.gitlab.sszuev.flashcards.model.domain.CardEntity
import com.gitlab.sszuev.flashcards.model.domain.CardFilter
import com.gitlab.sszuev.flashcards.model.domain.CardId
import com.gitlab.sszuev.flashcards.model.domain.CardLearn
import com.gitlab.sszuev.flashcards.model.domain.CardOperation
import com.gitlab.sszuev.flashcards.model.domain.CardWordEntity
import com.gitlab.sszuev.flashcards.model.domain.DictionaryId
import com.gitlab.sszuev.flashcards.model.domain.LangId
import com.gitlab.sszuev.flashcards.model.domain.Stage
import com.gitlab.sszuev.flashcards.model.domain.TTSResourceGet
import com.gitlab.sszuev.flashcards.stubs.stubCard
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
Expand All @@ -15,7 +24,7 @@ import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.EnumSource
import org.junit.jupiter.params.provider.MethodSource
import java.util.*
import java.util.UUID

@OptIn(ExperimentalCoroutinesApi::class)
internal class CardCorProcessorValidationTest {
Expand Down Expand Up @@ -314,7 +323,7 @@ internal class CardCorProcessorValidationTest {
val context = testContext(CardOperation.LEARN_CARDS)
context.requestCardLearnList = listOf(
testCardLearn.copy(cardId = CardId("42"), details = mapOf(Stage.OPTIONS to 4200, Stage.WRITING to 42)),
testCardLearn.copy(cardId = CardId("21"), details = mapOf(Stage.MOSAIC to -12, Stage.SELF_TEST to 0)),
testCardLearn.copy(cardId = CardId("21"), details = mapOf(Stage.MOSAIC to -4200, Stage.SELF_TEST to -4200)),
)
processor.execute(context)
Assertions.assertEquals(3, context.errors.size)
Expand Down
15 changes: 15 additions & 0 deletions core/src/test/kotlin/SearchCardsHelperTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,19 @@ internal class SearchCardsHelperTest {
val card2 = CardEntity(words = listOf(CardWordEntity("word", translations = listOf(listOf("b", "slo")))))
Assertions.assertTrue(card1.isSimilar(card2))
}

@Test
fun `test isSimilar #5`() {
val card1 = CardEntity(
words = listOf(
CardWordEntity("moist", translations = listOf(listOf("сырой"), listOf("влажный"), listOf("мокрый")))
)
)
val card2 = CardEntity(
words = listOf(
CardWordEntity("wet", translations = listOf(listOf("влажный"), listOf("сырой")))
)
)
Assertions.assertTrue(card1.isSimilar(card2))
}
}
35 changes: 0 additions & 35 deletions db-common/src/testFixtures/kotlin/DbCardRepositoryTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import com.gitlab.sszuev.flashcards.model.common.NONE
import com.gitlab.sszuev.flashcards.model.domain.CardEntity
import com.gitlab.sszuev.flashcards.model.domain.CardFilter
import com.gitlab.sszuev.flashcards.model.domain.CardId
import com.gitlab.sszuev.flashcards.model.domain.CardLearn
import com.gitlab.sszuev.flashcards.model.domain.CardWordEntity
import com.gitlab.sszuev.flashcards.model.domain.CardWordExampleEntity
import com.gitlab.sszuev.flashcards.model.domain.DictionaryId
Expand Down Expand Up @@ -128,25 +127,6 @@ abstract class DbCardRepositoryTest {
),
)

private val rainCardEntity = CardEntity(
cardId = CardId("248"),
dictionaryId = DictionaryId("2"),
words = listOf(
CardWordEntity(
word = "rain",
transcription = "rein",
partOfSpeech = "noun",
translations = listOf(listOf("дождь")),
examples = listOf(
CardWordExampleEntity(text = "It rains.", translation = "Идет дождь."),
CardWordExampleEntity(text = "heavy rain", translation = "проливной дождь, ливень"),
CardWordExampleEntity(text = "drizzling rain", translation = "изморось"),
CardWordExampleEntity(text = "torrential rain", translation = "проливной дождь"),
),
),
),
)

private val newMurkyCardEntity = CardEntity(
dictionaryId = DictionaryId("2"),
words = listOf(
Expand Down Expand Up @@ -375,21 +355,6 @@ abstract class DbCardRepositoryTest {
)
}

@Order(9)
@Test
fun `test learn cards success`() {
val request = CardLearn(
cardId = rainCardEntity.cardId,
details = mapOf(Stage.SELF_TEST to 3, Stage.WRITING to 4),
)
val res = repository.learnCards(userId, listOf(request))
Assertions.assertEquals(0, res.errors.size) { "Has errors: ${res.errors}" }
Assertions.assertEquals(1, res.cards.size)
val card = res.cards[0]
val expectedCard = rainCardEntity.copy(stats = request.details)
assertCard(expected = expectedCard, actual = card, ignoreChangeAt = true, ignoreId = false)
}

@Order(10)
@Test
fun `test get card & reset card success`() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import com.gitlab.sszuev.flashcards.model.common.AppUserId
import com.gitlab.sszuev.flashcards.model.domain.CardEntity
import com.gitlab.sszuev.flashcards.model.domain.CardFilter
import com.gitlab.sszuev.flashcards.model.domain.CardId
import com.gitlab.sszuev.flashcards.model.domain.CardLearn
import com.gitlab.sszuev.flashcards.model.domain.DictionaryId
import com.gitlab.sszuev.flashcards.repositories.CardDbResponse
import com.gitlab.sszuev.flashcards.repositories.CardsDbResponse
Expand All @@ -22,7 +21,6 @@ class MockDbCardRepository(
private val invokeCreateCard: (AppUserId, CardEntity) -> CardDbResponse = { _, _ -> CardDbResponse.EMPTY },
private val invokeUpdateCard: (AppUserId, CardEntity) -> CardDbResponse = { _, _ -> CardDbResponse.EMPTY },
private val invokeUpdateCards: (AppUserId, Iterable<CardId>, (CardEntity) -> CardEntity) -> CardsDbResponse = { _, _, _ -> CardsDbResponse.EMPTY },
private val invokeLearnCards: (AppUserId, List<CardLearn>) -> CardsDbResponse = { _, _ -> CardsDbResponse.EMPTY },
private val invokeResetCard: (AppUserId, CardId) -> CardDbResponse = { _, _ -> CardDbResponse.EMPTY },
private val invokeDeleteCard: (AppUserId, CardId) -> RemoveCardDbResponse = { _, _ -> RemoveCardDbResponse.EMPTY },
) : DbCardRepository {
Expand Down Expand Up @@ -55,10 +53,6 @@ class MockDbCardRepository(
return invokeUpdateCards(userId, cardIds, update)
}

override fun learnCards(userId: AppUserId, cardLearns: List<CardLearn>): CardsDbResponse {
return invokeLearnCards(userId, cardLearns)
}

override fun resetCard(userId: AppUserId, cardId: CardId): CardDbResponse {
return invokeResetCard(userId, cardId)
}
Expand Down
33 changes: 0 additions & 33 deletions db-mem/src/main/kotlin/MemDbCardRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,18 @@ import com.gitlab.sszuev.flashcards.common.status
import com.gitlab.sszuev.flashcards.common.systemNow
import com.gitlab.sszuev.flashcards.common.validateCardEntityForCreate
import com.gitlab.sszuev.flashcards.common.validateCardEntityForUpdate
import com.gitlab.sszuev.flashcards.common.validateCardLearns
import com.gitlab.sszuev.flashcards.dbmem.dao.MemDbCard
import com.gitlab.sszuev.flashcards.dbmem.dao.MemDbDictionary
import com.gitlab.sszuev.flashcards.model.Id
import com.gitlab.sszuev.flashcards.model.common.AppError
import com.gitlab.sszuev.flashcards.model.common.AppUserId
import com.gitlab.sszuev.flashcards.model.domain.CardEntity
import com.gitlab.sszuev.flashcards.model.domain.CardFilter
import com.gitlab.sszuev.flashcards.model.domain.CardId
import com.gitlab.sszuev.flashcards.model.domain.CardLearn
import com.gitlab.sszuev.flashcards.model.domain.DictionaryId
import com.gitlab.sszuev.flashcards.repositories.CardDbResponse
import com.gitlab.sszuev.flashcards.repositories.CardsDbResponse
import com.gitlab.sszuev.flashcards.repositories.DbCardRepository
import com.gitlab.sszuev.flashcards.repositories.RemoveCardDbResponse
import java.time.LocalDateTime
import kotlin.random.Random

class MemDbCardRepository(
Expand Down Expand Up @@ -160,17 +156,6 @@ class MemDbCardRepository(
)
}

override fun learnCards(userId: AppUserId, cardLearns: List<CardLearn>): CardsDbResponse {
validateCardLearns(cardLearns)
val timestamp = systemNow()
val errors = mutableListOf<AppError>()
val cards = cardLearns.mapNotNull { learnCard(it, userId, errors, timestamp) }
if (errors.isNotEmpty()) {
return CardsDbResponse(errors = errors)
}
return CardsDbResponse(cards = cards.map { it.toCardEntity() }, errors = errors)
}

override fun resetCard(userId: AppUserId, cardId: CardId): CardDbResponse {
val timestamp = systemNow()
val card =
Expand Down Expand Up @@ -199,24 +184,6 @@ class MemDbCardRepository(
return RemoveCardDbResponse(card = card.copy(changedAt = timestamp).toCardEntity())
}

private fun learnCard(
learn: CardLearn,
userId: AppUserId,
errors: MutableList<AppError>,
timestamp: LocalDateTime,
): MemDbCard? {
val cardId = learn.cardId
val card = database.findCardById(cardId.asLong())
if (card == null) {
errors.add(noCardFoundDbError("learnCard", cardId))
return null
}
if (checkDictionaryUser("learnCard", userId, card.dictionaryId.asDictionaryId(), cardId, errors) == null) {
return null
}
return database.saveCard(card.copy(details = learn.details.toMemDbCardDetails(), changedAt = timestamp))
}

@Suppress("DuplicatedCode")
private fun checkDictionaryUser(
operation: String,
Expand Down
6 changes: 1 addition & 5 deletions db-mem/src/main/kotlin/MemDbEntityMapper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import com.gitlab.sszuev.flashcards.common.parseUserDetailsJson
import com.gitlab.sszuev.flashcards.common.toCardEntityDetails
import com.gitlab.sszuev.flashcards.common.toCardEntityStats
import com.gitlab.sszuev.flashcards.common.toCardWordEntity
import com.gitlab.sszuev.flashcards.common.toCommonCardDtoDetails
import com.gitlab.sszuev.flashcards.common.toCommonWordDtoList
import com.gitlab.sszuev.flashcards.common.toDocumentExamples
import com.gitlab.sszuev.flashcards.common.toDocumentTranslations
Expand All @@ -41,7 +40,6 @@ import com.gitlab.sszuev.flashcards.model.domain.DictionaryEntity
import com.gitlab.sszuev.flashcards.model.domain.DictionaryId
import com.gitlab.sszuev.flashcards.model.domain.LangEntity
import com.gitlab.sszuev.flashcards.model.domain.LangId
import com.gitlab.sszuev.flashcards.model.domain.Stage
import java.util.UUID

internal fun MemDbUser.detailsAsJsonString(): String {
Expand All @@ -65,7 +63,7 @@ internal fun MemDbCard.detailsAsJsonString(): String {
}

internal fun fromJsonStringToMemDbCardDetails(json: String): Map<String, String> {
return parseCardDetailsJson(json).mapValues { it.toString() }
return parseCardDetailsJson(json).mapValues { it.value.toString() }
}

internal fun MemDbCard.wordsAsJsonString(): String {
Expand Down Expand Up @@ -216,8 +214,6 @@ internal fun MemDbCard.detailsAsCommonCardDetailsDto(): CommonCardDetailsDto = C

private fun CommonCardDetailsDto.toMemDbCardDetails(): Map<String, String> = this.mapValues { it.value.toString() }

internal fun Map<Stage, Long>.toMemDbCardDetails(): Map<String, String> = toCommonCardDtoDetails().toMemDbCardDetails()

private fun Long.asUserId(): AppUserId = AppUserId(toString())

private fun String.asLangId(): LangId = LangId(this)
Expand Down
Loading

0 comments on commit 2bca710

Please sign in to comment.