From 410027296536bf5dff561af91f03507da7a8c3b7 Mon Sep 17 00:00:00 2001 From: avalin Date: Tue, 28 May 2024 15:20:41 +0200 Subject: [PATCH] Fix winnings and add a bet cancellation system after 1 week of no confirmation --- .../allin/data/mock/MockBetDataSource.kt | 22 ++++++- .../data/postgres/PostgresBetDataSource.kt | 60 +++++++++++++------ .../data/postgres/entities/BetResultEntity.kt | 15 ++++- 3 files changed, 72 insertions(+), 25 deletions(-) diff --git a/Sources/src/main/kotlin/allin/data/mock/MockBetDataSource.kt b/Sources/src/main/kotlin/allin/data/mock/MockBetDataSource.kt index 3946ba7..1a29763 100644 --- a/Sources/src/main/kotlin/allin/data/mock/MockBetDataSource.kt +++ b/Sources/src/main/kotlin/allin/data/mock/MockBetDataSource.kt @@ -90,7 +90,21 @@ class MockBetDataSource(private val mockData: MockDataSource.MockData) : BetData if (bet.status != CANCELLED && bet.status != FINISHED) { if (date >= bet.endRegistration) { if (date >= bet.endBet) { - bets[idx] = bet.copy(status = CLOSING) + if (date.plusWeeks(1) >= bet.endBet) { + bets[idx] = bet.copy(status = CANCELLED) + + participations + .filter { it.betId == bets[idx].id } + .forEach { p -> + users.replaceAll { + if (it.username == p.username) { + it.copy(nbCoins = it.nbCoins + p.stake) + } else it + } + } + } else { + bets[idx] = bet.copy(status = CLOSING) + } } else { bets[idx] = bet.copy(status = WAITING) } @@ -115,12 +129,14 @@ class MockBetDataSource(private val mockData: MockDataSource.MockData) : BetData it.copy(status = FINISHED) } else it } - + val resultAnswerInfo = answerInfos.find { it.betId == betId && it.response == result } participations.filter { it.betId == betId && it.answer == result } .forEach { participation -> + + val amount = (participation.stake * (resultAnswerInfo?.odds ?: 1f)).roundToInt() users.replaceAll { if (it.username == participation.username) { - it.copy(nbCoins = it.nbCoins + participation.stake) + it.copy(nbCoins = it.nbCoins + amount) } else it } resultNotifications.add(Pair(betId, participation.username)) diff --git a/Sources/src/main/kotlin/allin/data/postgres/PostgresBetDataSource.kt b/Sources/src/main/kotlin/allin/data/postgres/PostgresBetDataSource.kt index 6b28d09..f68cccc 100644 --- a/Sources/src/main/kotlin/allin/data/postgres/PostgresBetDataSource.kt +++ b/Sources/src/main/kotlin/allin/data/postgres/PostgresBetDataSource.kt @@ -8,6 +8,8 @@ import org.ktorm.dsl.* import org.ktorm.entity.* import java.time.ZoneId import java.time.ZonedDateTime +import java.time.temporal.ChronoUnit +import kotlin.math.roundToInt class PostgresBetDataSource(private val database: Database) : BetDataSource { @@ -60,12 +62,12 @@ class PostgresBetDataSource(private val database: Database) : BetDataSource { .map { it.toBet(database) } } - override fun getToConfirm(id: String): List { + override fun getToConfirm(username: String): List { return database.bets .filter { - (it.createdBy eq id) and (BetsEntity.status eq BetStatus.CLOSING) + (it.createdBy eq username) and (BetsEntity.status eq BetStatus.CLOSING) } - .map { it.toBetDetail(database, id) } + .map { it.toBetDetail(database, username) } } override fun confirmBet(betId: String, result: String) { @@ -81,16 +83,26 @@ class PostgresBetDataSource(private val database: Database) : BetDataSource { ) } + val resultAnswerInfo = database.betAnswerInfos + .find { (it.betId eq betId) and (it.response eq result) } + ?.toBetAnswerInfo() + database.participations.filter { (ParticipationsEntity.betId eq betId) and (ParticipationsEntity.answer eq result) - }.forEach { + }.forEach { participation -> database.betResultNotifications.add( BetResultNotificationEntity { this.betId = betId - this.username = it.username + this.username = participation.username } ) + + val amount = (participation.stake * (resultAnswerInfo?.odds ?: 1f)).roundToInt() + database.update(UsersEntity) { usr -> + set(usr.nbCoins, usr.nbCoins + amount) + where { usr.username eq participation.username } + } } } @@ -203,25 +215,35 @@ class PostgresBetDataSource(private val database: Database) : BetDataSource { } override fun updateBetStatuses(date: ZonedDateTime) { - database.update(BetsEntity) { - set(BetsEntity.status, BetStatus.WAITING) - where { + database.bets + .filter { (date.toInstant() greaterEq BetsEntity.endRegistration) and - (date.toInstant() less BetsEntity.endBet) and (BetsEntity.status notEq BetStatus.FINISHED) and (BetsEntity.status notEq BetStatus.CANCELLED) - } - } + }.let { + it.filter { date.toInstant() less BetsEntity.endBet }.forEach { bet -> + bet.status = BetStatus.WAITING + bet.flushChanges() + } - database.update(BetsEntity) { - set(BetsEntity.status, BetStatus.CLOSING) - where { - (date.toInstant() greaterEq BetsEntity.endRegistration) and - (date.toInstant() greaterEq BetsEntity.endBet) and - (BetsEntity.status notEq BetStatus.FINISHED) and - (BetsEntity.status notEq BetStatus.CANCELLED) + it.filter { date.toInstant() greaterEq BetsEntity.endBet }.forEach { bet -> + if (date.toInstant() >= bet.endBet.plus(7, ChronoUnit.DAYS)) { + database.participations + .filter { it.betId eq bet.id } + .forEach { participation -> + database.users.find { it.username eq participation.username }?.let { user -> + user.nbCoins += participation.stake + user.flushChanges() + } + } + bet.status = BetStatus.CANCELLED + bet.flushChanges() + } else { + bet.status = BetStatus.CLOSING + bet.flushChanges() + } + } } - } } } \ No newline at end of file diff --git a/Sources/src/main/kotlin/allin/data/postgres/entities/BetResultEntity.kt b/Sources/src/main/kotlin/allin/data/postgres/entities/BetResultEntity.kt index f26412f..c2a90fa 100644 --- a/Sources/src/main/kotlin/allin/data/postgres/entities/BetResultEntity.kt +++ b/Sources/src/main/kotlin/allin/data/postgres/entities/BetResultEntity.kt @@ -3,10 +3,14 @@ package allin.data.postgres.entities import allin.model.BetResult import allin.model.BetResultDetail import org.ktorm.database.Database +import org.ktorm.dsl.and +import org.ktorm.dsl.eq import org.ktorm.entity.Entity +import org.ktorm.entity.find import org.ktorm.entity.sequenceOf import org.ktorm.schema.Table import org.ktorm.schema.varchar +import kotlin.math.roundToInt interface BetResultEntity : Entity { @@ -24,14 +28,19 @@ interface BetResultEntity : Entity { fun toBetResultDetail( database: Database, participationEntity: ParticipationEntity - ) = - BetResultDetail( + ): BetResultDetail { + val answerInfo = database.betAnswerInfos.find { + (it.betId eq bet.id) and (it.response eq participationEntity.answer) + }?.toBetAnswerInfo() + + return BetResultDetail( betResult = this.toBetResult(), bet = bet.toBet(database), participation = participationEntity.toParticipation(), - amount = participationEntity.stake, + amount = (participationEntity.stake * (answerInfo?.odds ?: 1f)).roundToInt(), won = participationEntity.answer == result ) + } } object BetResultsEntity : Table("betresult") {