Fix entities usages
continuous-integration/drone/push Build is passing Details

pull/12/head
avalin 11 months ago
parent cae02af684
commit af013b6666

@ -9,12 +9,13 @@ import java.time.ZonedDateTime
interface BetDataSource { interface BetDataSource {
fun getAllBets(): List<Bet> fun getAllBets(): List<Bet>
fun getBetById(id: String): Bet? fun getBetById(id: String): Bet?
fun getBetDetailById(id: String, username: String): BetDetail?
fun getBetsNotFinished(): List<Bet> fun getBetsNotFinished(): List<Bet>
fun addBet(bet: Bet) fun addBet(bet: Bet)
fun removeBet(id: String): Boolean fun removeBet(id: String): Boolean
fun updateBet(data: UpdatedBetData): Boolean fun updateBet(data: UpdatedBetData): Boolean
fun updateBetStatuses(date: ZonedDateTime) fun updateBetStatuses(date: ZonedDateTime)
fun getToConfirm(username: String): List<Bet> fun getToConfirm(username: String): List<BetDetail>
fun confirmBet(betId: String, result: String) fun confirmBet(betId: String, result: String)
fun getWonNotifications(username: String): List<BetResultDetail> fun getWonNotifications(username: String): List<BetResultDetail>
fun getHistory(username: String): List<BetResultDetail> fun getHistory(username: String): List<BetResultDetail>

@ -4,20 +4,29 @@ import allin.data.BetDataSource
import allin.model.* import allin.model.*
import allin.model.BetStatus.* import allin.model.BetStatus.*
import java.time.ZonedDateTime import java.time.ZonedDateTime
import kotlin.math.roundToInt
class MockBetDataSource(mockData: MockDataSource.MockData) : BetDataSource { class MockBetDataSource(private val mockData: MockDataSource.MockData) : BetDataSource {
private val bets by lazy { mockData.bets } private val bets get() = mockData.bets
private val results by lazy { mockData.results } private val results get() = mockData.results
private val users by lazy { mockData.users } private val users get() = mockData.users
private val participations by lazy { mockData.participations } private val participations get() = mockData.participations
private val resultNotifications by lazy { mockData.resultNotifications } private val resultNotifications get() = mockData.resultNotifications
private val betInfos get() = mockData.betInfos
private val answerInfos get() = mockData.answerInfos
override fun getAllBets(): List<Bet> = bets override fun getAllBets(): List<Bet> = bets
override fun getBetById(id: String): Bet? = override fun getBetById(id: String): Bet? =
bets.find { it.id == id } bets.find { it.id == id }
override fun removeBet(id: String): Boolean = override fun getBetDetailById(id: String, username: String): BetDetail? =
bets.removeIf { it.id == id } bets.find { it.id == id }?.toBetDetail(username)
override fun removeBet(id: String): Boolean {
betInfos.removeIf { it.id == id }
answerInfos.removeIf { it.betId == id }
return bets.removeIf { it.id == id }
}
override fun updateBet(data: UpdatedBetData): Boolean { override fun updateBet(data: UpdatedBetData): Boolean {
return bets.find { it.id == data.id }?.let { return bets.find { it.id == data.id }?.let {
@ -30,6 +39,15 @@ class MockBetDataSource(mockData: MockDataSource.MockData) : BetDataSource {
override fun addBet(bet: Bet) { override fun addBet(bet: Bet) {
bets += bet bets += bet
betInfos += BetInfo(id = bet.id, totalStakes = 0)
bet.response.forEach {
answerInfos += BetAnswerInfo(
betId = bet.id,
response = it,
totalStakes = 0,
odds = 1f
)
}
} }
override fun updateBetStatuses(date: ZonedDateTime) { override fun updateBetStatuses(date: ZonedDateTime) {
@ -46,8 +64,9 @@ class MockBetDataSource(mockData: MockDataSource.MockData) : BetDataSource {
} }
} }
override fun getToConfirm(username: String): List<Bet> = override fun getToConfirm(username: String): List<BetDetail> =
bets.filter { it.createdBy == username && it.status == CLOSING } bets.filter { it.createdBy == username && it.status == CLOSING }
.map { it.toBetDetail(username) }
override fun confirmBet(betId: String, result: String) { override fun confirmBet(betId: String, result: String) {
results.add( results.add(
@ -82,11 +101,12 @@ class MockBetDataSource(mockData: MockDataSource.MockData) : BetDataSource {
if (participation.answer == result.result) { if (participation.answer == result.result) {
resultNotifications.remove(notification) resultNotifications.remove(notification)
val answerInfo = answerInfos.find { it.betId == bet.id && it.response == participation.answer }
BetResultDetail( BetResultDetail(
betResult = result, betResult = result,
bet = bet, bet = bet,
participation = participation, participation = participation,
amount = participation.stake, amount = (participation.stake * (answerInfo?.odds ?: 1f)).roundToInt(),
won = true won = true
) )
} else null } else null
@ -99,35 +119,49 @@ class MockBetDataSource(mockData: MockDataSource.MockData) : BetDataSource {
val participation = participations.find { it.username == username && it.betId == bet.id } val participation = participations.find { it.username == username && it.betId == bet.id }
?: return@map null ?: return@map null
val won = participation.answer == result.result
val answerInfo = answerInfos.find {
it.betId == bet.id && it.response == participation.answer
}
BetResultDetail( BetResultDetail(
betResult = result, betResult = result,
bet = bet, bet = bet,
participation = participation, participation = participation,
amount = participation.stake, amount = if (won) {
won = participation.answer == result.result (participation.stake * (answerInfo?.odds ?: 1f)).roundToInt()
} else participation.stake,
won = won
) )
}.mapNotNull { it } }.mapNotNull { it }
} }
override fun getCurrent(username: String): List<BetDetail> { override fun getCurrent(username: String): List<BetDetail> {
return bets.map { bet -> return bets.mapNotNull { bet ->
when (bet.status) { when (bet.status) {
CANCELLED, FINISHED -> return@map null CANCELLED, FINISHED -> return@mapNotNull null
else -> { else -> {
val participation = participations.find { it.username == username && it.betId == bet.id } val userParticipation = participations.find { it.username == username && it.betId == bet.id }
?: return@map null if (userParticipation == null) return@mapNotNull null
return@mapNotNull bet.toBetDetail(username)
val participations = participations.filter { it.betId == bet.id } }
}
}
}
private fun Bet.toBetDetail(username: String): BetDetail {
val participation = participations.find { it.username == username && it.betId == this.id }
val participations = participations.filter { it.betId == this.id }
BetDetail( return BetDetail(
bet = bet, bet = this,
answers = getBetAnswerDetail(bet, participations), answers = getBetAnswerDetail(
bet = this,
participations = participations,
infos = answerInfos.filter { it.betId == this.id }
),
participations = participations, participations = participations,
userParticipation = participation userParticipation = participation
) )
} }
}
}.mapNotNull { it }
}
} }

@ -4,10 +4,7 @@ import allin.data.AllInDataSource
import allin.data.BetDataSource import allin.data.BetDataSource
import allin.data.ParticipationDataSource import allin.data.ParticipationDataSource
import allin.data.UserDataSource import allin.data.UserDataSource
import allin.model.Bet import allin.model.*
import allin.model.BetResult
import allin.model.Participation
import allin.model.User
import java.time.ZonedDateTime import java.time.ZonedDateTime
class MockDataSource : AllInDataSource() { class MockDataSource : AllInDataSource() {
@ -18,6 +15,8 @@ class MockDataSource : AllInDataSource() {
class MockData { class MockData {
val bets by lazy { mutableListOf<Bet>() } val bets by lazy { mutableListOf<Bet>() }
val betInfos by lazy { mutableListOf<BetInfo>() }
val answerInfos by lazy { mutableListOf<BetAnswerInfo>() }
val results by lazy { mutableListOf<BetResult>() } val results by lazy { mutableListOf<BetResult>() }
val resultNotifications by lazy { mutableListOf<Pair<String, String>>() } val resultNotifications by lazy { mutableListOf<Pair<String, String>>() }
val users by lazy { mutableListOf<User>() } val users by lazy { mutableListOf<User>() }

@ -3,11 +3,41 @@ package allin.data.mock
import allin.data.ParticipationDataSource import allin.data.ParticipationDataSource
import allin.model.Participation import allin.model.Participation
class MockParticipationDataSource(mockData: MockDataSource.MockData) : ParticipationDataSource { class MockParticipationDataSource(private val mockData: MockDataSource.MockData) : ParticipationDataSource {
private val participations by lazy { mockData.participations } private val participations get() = mockData.participations
private val betInfos get() = mockData.betInfos
private val answerInfos get() = mockData.answerInfos
override fun addParticipation(participation: Participation) { override fun addParticipation(participation: Participation) {
participations += participation participations += participation
var betTotalStakes = 0
betInfos.replaceAll {
if (participation.betId == it.id) {
betTotalStakes = it.totalStakes + participation.stake
it.copy(totalStakes = betTotalStakes)
} else {
it
}
}
answerInfos.replaceAll {
if (participation.betId == it.betId) {
if (participation.answer == it.response) {
val answerTotalStakes = it.totalStakes + participation.stake
val probability = answerTotalStakes / betTotalStakes.toFloat()
it.copy(
totalStakes = answerTotalStakes,
odds = 1 / probability
)
} else {
val probability = it.totalStakes / betTotalStakes.toFloat()
it.copy(odds = 1 / probability)
}
} else {
it
}
}
} }
override fun getParticipationFromBetId(betid: String): List<Participation> = override fun getParticipationFromBetId(betid: String): List<Participation> =
@ -16,6 +46,39 @@ class MockParticipationDataSource(mockData: MockDataSource.MockData) : Participa
override fun getParticipationFromUserId(username: String, betid: String): List<Participation> = override fun getParticipationFromUserId(username: String, betid: String): List<Participation> =
participations.filter { it.betId == betid && it.username == username } participations.filter { it.betId == betid && it.username == username }
override fun deleteParticipation(id: String): Boolean = override fun deleteParticipation(id: String): Boolean {
participations.removeIf { it.id == id } val participation = participations.find { it.id == id }
val result = participations.remove(participation)
var betTotalStakes = 0
betInfos.replaceAll {
if (participation?.betId == it.id) {
betTotalStakes = it.totalStakes - participation.stake
it.copy(totalStakes = betTotalStakes)
} else {
it
}
}
answerInfos.replaceAll {
if (participation?.betId == it.betId) {
if (participation.answer == it.response) {
val answerTotalStakes = it.totalStakes - participation.stake
val probability = answerTotalStakes / betTotalStakes.toFloat()
it.copy(
totalStakes = answerTotalStakes,
odds = 1 / probability
)
} else {
val probability = it.totalStakes / betTotalStakes.toFloat()
it.copy(odds = 1 / probability)
}
} else {
it
}
}
return result
}
} }

@ -5,9 +5,9 @@ import allin.dto.UserDTO
import allin.model.User import allin.model.User
import java.time.ZonedDateTime import java.time.ZonedDateTime
class MockUserDataSource(mockData: MockDataSource.MockData) : UserDataSource { class MockUserDataSource(private val mockData: MockDataSource.MockData) : UserDataSource {
private val users by lazy { mockData.users } private val users get() = mockData.users
private val lastGifts by lazy { mockData.lastGifts } private val lastGifts get() = mockData.lastGifts
override fun getUserByUsername(username: String): Pair<UserDTO?, String?> = override fun getUserByUsername(username: String): Pair<UserDTO?, String?> =
users.find { it.username == username }?.let { users.find { it.username == username }?.let {

@ -2,193 +2,146 @@ package allin.data.postgres
import allin.data.BetDataSource import allin.data.BetDataSource
import allin.data.postgres.entities.* import allin.data.postgres.entities.*
import allin.data.postgres.entities.ResponsesEntity.response
import allin.model.* import allin.model.*
import org.ktorm.database.Database import org.ktorm.database.Database
import org.ktorm.dsl.* import org.ktorm.dsl.*
import org.ktorm.entity.*
import java.time.ZoneId import java.time.ZoneId
import java.time.ZonedDateTime import java.time.ZonedDateTime
class PostgresBetDataSource(private val database: Database) : BetDataSource { class PostgresBetDataSource(private val database: Database) : BetDataSource {
private fun QueryRowSet.toBet() =
Bet(
id = this[BetsEntity.id].toString(),
theme = this[BetsEntity.theme].toString(),
sentenceBet = this[BetsEntity.sentenceBet].toString(),
endRegistration = this[BetsEntity.endRegistration]!!.atZone(ZoneId.of("Europe/Paris")),
endBet = this[BetsEntity.endBet]!!.atZone(ZoneId.of("Europe/Paris")),
isPrivate = this[BetsEntity.isPrivate] ?: false,
status = this[BetsEntity.status] ?: BetStatus.IN_PROGRESS,
type = this[BetsEntity.type] ?: BetType.CUSTOM,
createdBy = this[BetsEntity.createdBy].toString(),
response = let {
val idBet = this[BetsEntity.id].toString()
val type = this[BetsEntity.type] ?: BetType.CUSTOM
if (type == BetType.CUSTOM) {
database.from(ResponsesEntity)
.select(response)
.where { ResponsesEntity.id eq idBet }
.map { it[response].toString() }
} else {
listOf(YES_VALUE, NO_VALUE)
}
}
)
private fun QueryRowSet.toParticipation() =
Participation(
id = this[ParticipationsEntity.id]?.toString() ?: "",
betId = this[ParticipationsEntity.betId]?.toString() ?: "",
username = this[ParticipationsEntity.username] ?: "",
answer = this[ParticipationsEntity.answer] ?: "",
stake = this[ParticipationsEntity.stake] ?: 0
)
private fun QueryRowSet.toBetResultDetail() =
BetResultDetail(
betResult = BetResult(
betId = this[BetResultsEntity.betId]?.toString() ?: "",
result = this[BetResultsEntity.result] ?: ""
),
bet = this.toBet(),
participation = this.toParticipation(),
amount = this[ParticipationsEntity.stake] ?: 0,
won = this[ParticipationsEntity.answer] == this[BetResultsEntity.result]
)
private fun Query.mapToBet() = this.map { it.toBet() }
private fun Query.mapToBetResultDetail() = this.map { it.toBetResultDetail() }
override fun getAllBets(): List<Bet> = override fun getAllBets(): List<Bet> =
database.from(BetsEntity).select().mapToBet() database.bets.map { it.toBet(database) }
override fun getBetById(id: String): Bet? = override fun getBetById(id: String): Bet? =
database.from(BetsEntity).select().where { database.bets.find { it.id eq id }?.toBet(database)
BetsEntity.id eq id
}.mapToBet().firstOrNull() override fun getBetDetailById(id: String, username: String): BetDetail? =
database.bets.find { it.id eq id }?.toBetDetail(database, username)
override fun getBetsNotFinished(): List<Bet> { override fun getBetsNotFinished(): List<Bet> {
val currentTime = ZonedDateTime.now(ZoneId.of("Europe/Paris")) val currentTime = ZonedDateTime.now(ZoneId.of("Europe/Paris"))
return database.from(BetsEntity) return database.bets
.select() .filter { it.endBet greaterEq currentTime.toInstant() }
.where { BetsEntity.endBet greaterEq currentTime.toInstant() } .map { it.toBet(database) }
.mapToBet()
} }
override fun getToConfirm(username: String): List<Bet> { override fun getToConfirm(username: String): List<BetDetail> {
return database.from(BetsEntity) return database.bets
.select() .filter {
.where { (it.createdBy eq username) and (BetsEntity.status eq BetStatus.CLOSING)
(BetsEntity.createdBy eq username) and }
(BetsEntity.status eq BetStatus.CLOSING) .map { it.toBetDetail(database, username) }
}.mapToBet()
} }
override fun confirmBet(betId: String, result: String) { override fun confirmBet(betId: String, result: String) {
database.insert(BetResultsEntity) { database.bets.find { it.id eq betId }?.let { bet ->
set(it.betId, betId) bet.status = BetStatus.FINISHED
set(it.result, result) bet.flushChanges()
}
database.update(BetsEntity) { database.betResults.add(
where { BetsEntity.id eq betId } BetResultEntity {
set(BetsEntity.status, BetStatus.FINISHED) this.bet = bet
this.result = result
}
)
} }
database.from(ParticipationsEntity) database.participations.filter {
.select()
.where {
(ParticipationsEntity.betId eq betId) and (ParticipationsEntity.betId eq betId) and
(ParticipationsEntity.answer eq result) (ParticipationsEntity.answer eq result)
}.forEach {
database.betResultNotifications.add(
BetResultNotificationEntity {
this.betId = betId
this.username = it.username
} }
.forEach { participation -> )
database.insert(BetResultNotificationsEntity) {
set(it.betId, betId)
set(it.username, participation[ParticipationsEntity.username])
}
} }
} }
override fun getWonNotifications(username: String): List<BetResultDetail> { override fun getWonNotifications(username: String): List<BetResultDetail> {
return database.from(BetsEntity) return database.betResultNotifications
.innerJoin(ParticipationsEntity, on = BetsEntity.id eq ParticipationsEntity.betId) .filter { it.username eq username }
.innerJoin(BetResultsEntity, on = BetsEntity.id eq BetResultsEntity.betId) .flatMap { notif ->
.innerJoin(BetResultNotificationsEntity, on = BetsEntity.id eq BetResultNotificationsEntity.betId) notif.delete()
.select()
.where { database.participations
(BetResultsEntity.result eq ParticipationsEntity.answer) and .filter {
(ParticipationsEntity.username eq username) (it.username eq username) and
}.let { (it.betId eq notif.betId)
it.forEach { row -> }
row[BetsEntity.id]?.let { betId -> .mapNotNull { participation ->
database.delete(BetResultNotificationsEntity) { database.betResults
(it.betId eq betId) and (it.username eq username) .find { it.betId eq participation.bet.id }
} ?.toBetResultDetail(
database,
participation
)
} }
} }
it
}.mapToBetResultDetail()
} }
override fun getHistory(username: String): List<BetResultDetail> { override fun getHistory(username: String): List<BetResultDetail> {
return database.from(BetsEntity) return database.participations
.innerJoin(ParticipationsEntity, on = BetsEntity.id eq ParticipationsEntity.betId) .filter { it.username eq username }
.innerJoin(BetResultsEntity, on = BetsEntity.id eq BetResultsEntity.betId) .mapNotNull { participation ->
.select() database.betResults
.where { ParticipationsEntity.username eq username }.mapToBetResultDetail() .find { it.betId eq participation.bet.id }
?.toBetResultDetail(
database,
participation
)
}
} }
override fun getCurrent(username: String): List<BetDetail> { override fun getCurrent(username: String): List<BetDetail> {
return database.from(BetsEntity) return database.participations
.innerJoin(ParticipationsEntity, on = BetsEntity.id eq ParticipationsEntity.betId) .filter { it.username eq username }
.select() .mapNotNull {
.where { if (it.bet.status !in listOf(BetStatus.FINISHED, BetStatus.CANCELLED)) {
(BetsEntity.status notEq BetStatus.FINISHED) and it.bet.toBetDetail(
(BetsEntity.status notEq BetStatus.CANCELLED) and database = database,
(ParticipationsEntity.username eq username) username = username
}.map {
val participations = it[BetsEntity.id]?.let { betId ->
database.from(ParticipationsEntity)
.select().where { ParticipationsEntity.betId eq betId }.map { it.toParticipation() }
} ?: emptyList()
val bet = it.toBet()
BetDetail(
bet = bet,
answers = getBetAnswerDetail(bet, participations),
participations = participations,
userParticipation = it.toParticipation()
) )
} else null
} }
} }
override fun addBet(bet: Bet) { override fun addBet(bet: Bet) {
database.insert(BetsEntity) { database.bets.add(
set(it.id, bet.id) BetEntity {
set(it.endBet, bet.endBet.toInstant()) this.id = bet.id
set(it.endRegistration, bet.endRegistration.toInstant()) this.endBet = bet.endBet.toInstant()
set(it.sentenceBet, bet.sentenceBet) this.endRegistration = bet.endRegistration.toInstant()
set(it.theme, bet.theme) this.zoneId = bet.endBet.zone.id
set(it.isPrivate, bet.isPrivate) this.sentenceBet = bet.sentenceBet
set(it.createdBy, bet.createdBy) this.theme = bet.theme
set(it.status, bet.status) this.isPrivate = bet.isPrivate
set(it.type, bet.type) this.createdBy = bet.createdBy
this.status = bet.status
this.type = bet.type
} }
)
if (bet.type == BetType.CUSTOM) { if (bet.type == BetType.CUSTOM) {
bet.response.forEach { selected -> bet.response.forEach { selected ->
database.insert(ResponsesEntity) { database.responses.add(
set(it.id, bet.id) ResponseEntity {
set(it.response, selected) this.betId = bet.id
this.response = selected
} }
)
} }
} }
} }
override fun removeBet(id: String): Boolean { override fun removeBet(id: String): Boolean {
return database.delete(BetsEntity) { it.id eq id } > 0 database.betInfos.removeIf { it.id eq id }
database.betAnswerInfos.removeIf { it.betId eq id }
return database.bets.removeIf { it.id eq id } > 0
} }
override fun updateBet(data: UpdatedBetData): Boolean { override fun updateBet(data: UpdatedBetData): Boolean {

@ -28,7 +28,7 @@ class PostgresDataSource : AllInDataSource() {
database.execute( database.execute(
""" """
CREATE TABLE IF not exists utilisateur ( CREATE TABLE IF not exists users (
id VARCHAR(255) PRIMARY KEY, id VARCHAR(255) PRIMARY KEY,
username VARCHAR(255), username VARCHAR(255),
password VARCHAR(255), password VARCHAR(255),
@ -46,6 +46,7 @@ class PostgresDataSource : AllInDataSource() {
theme VARCHAR(255), theme VARCHAR(255),
endregistration timestamp, endregistration timestamp,
endbet timestamp, endbet timestamp,
zoneid varchar(500),
sentencebet varchar(500), sentencebet varchar(500),
isprivate boolean, isprivate boolean,
createdby varchar(250), createdby varchar(250),
@ -89,9 +90,30 @@ class PostgresDataSource : AllInDataSource() {
database.execute( database.execute(
""" """
CREATE TABLE IF NOT EXISTS response ( CREATE TABLE IF NOT EXISTS response (
id VARCHAR(255), betId VARCHAR(255),
response VARCHAR(250), response VARCHAR(250),
CONSTRAINT pk_response_id PRIMARY KEY (id, response) CONSTRAINT pk_response_id PRIMARY KEY (betId, response)
)
""".trimIndent()
)
database.execute(
"""
CREATE TABLE IF not exists betInfo (
id VARCHAR(255) PRIMARY KEY,
totalStakes int
)
""".trimIndent()
)
database.execute(
"""
CREATE TABLE IF not exists betAnswerInfo (
betId VARCHAR(255),
response VARCHAR(255),
totalStakes int,
odds float,
CONSTRAINT pk_bet_answer_info_id PRIMARY KEY (betId, response)
) )
""".trimIndent() """.trimIndent()
) )

@ -1,24 +1,16 @@
package allin.data.postgres package allin.data.postgres
import allin.data.ParticipationDataSource import allin.data.ParticipationDataSource
import allin.data.postgres.entities.ParticipationsEntity import allin.data.postgres.entities.*
import allin.model.Participation import allin.model.Participation
import org.ktorm.database.Database import org.ktorm.database.Database
import org.ktorm.dsl.* import org.ktorm.dsl.and
import org.ktorm.dsl.eq
import org.ktorm.dsl.insert
import org.ktorm.entity.*
class PostgresParticipationDataSource(private val database: Database) : ParticipationDataSource { class PostgresParticipationDataSource(private val database: Database) : ParticipationDataSource {
private fun QueryRowSet.toParticipation() =
Participation(
id = this[ParticipationsEntity.id].toString(),
betId = this[ParticipationsEntity.betId].toString(),
username = this[ParticipationsEntity.username].toString(),
answer = this[ParticipationsEntity.answer].toString(),
stake = this[ParticipationsEntity.stake] ?: 0,
)
private fun Query.mapToParticipation() = this.map { it.toParticipation() }
override fun addParticipation(participation: Participation) { override fun addParticipation(participation: Participation) {
database.insert(ParticipationsEntity) { database.insert(ParticipationsEntity) {
set(it.id, participation.id) set(it.id, participation.id)
@ -27,25 +19,50 @@ class PostgresParticipationDataSource(private val database: Database) : Particip
set(it.answer, participation.answer) set(it.answer, participation.answer)
set(it.stake, participation.stake) set(it.stake, participation.stake)
} }
val betInfo = database.betInfos.find { it.id eq participation.betId } ?: BetInfoEntity {
this.id = participation.betId
this.totalStakes = 0
}
betInfo.totalStakes += participation.stake
database.betInfos.update(betInfo)
database.betAnswerInfos.filter { it.betId eq participation.betId }.forEach {
if (it.response == participation.answer) {
it.totalStakes += participation.stake
}
val probability = it.totalStakes / betInfo.totalStakes.toFloat()
it.odds = 1 / probability
it.flushChanges()
}
} }
override fun getParticipationFromBetId(betid: String): List<Participation> = override fun getParticipationFromBetId(betid: String): List<Participation> =
database.from(ParticipationsEntity) database.participations.filter { it.betId eq betid }.map { it.toParticipation() }
.select()
.where { ParticipationsEntity.betId eq betid }
.mapToParticipation()
override fun getParticipationFromUserId(username: String, betid: String): List<Participation> = override fun getParticipationFromUserId(username: String, betid: String): List<Participation> =
database.from(ParticipationsEntity) database.participations.filter {
.select() (ParticipationsEntity.betId eq betid) and (ParticipationsEntity.username eq username)
.where { (ParticipationsEntity.betId eq betid) and (ParticipationsEntity.username eq username) } }.map { it.toParticipation() }
.mapToParticipation()
override fun deleteParticipation(id: String): Boolean {
fun getParticipationEntity(): List<Participation> = val participation = database.participations.find { it.id eq id } ?: return false
database.from(ParticipationsEntity).select().mapToParticipation() database.betInfos.find { it.id eq participation.bet.id }?.let { betInfo ->
betInfo.totalStakes -= participation.stake
override fun deleteParticipation(id: String): Boolean =
database.delete(ParticipationsEntity) { database.betAnswerInfos.filter { it.betId eq participation.bet.id }.forEach {
it.id eq id if (it.response == participation.answer) {
} > 0 it.totalStakes -= participation.stake
}
val probability = it.totalStakes / betInfo.totalStakes.toFloat()
it.odds = 1 / probability
it.flushChanges()
}
betInfo.flushChanges()
}
return participation.delete() > 0
}
} }

@ -1,70 +1,60 @@
package allin.data.postgres package allin.data.postgres
import allin.data.UserDataSource import allin.data.UserDataSource
import allin.data.postgres.entities.UserEntity
import allin.data.postgres.entities.UsersEntity import allin.data.postgres.entities.UsersEntity
import allin.data.postgres.entities.users
import allin.dto.UserDTO import allin.dto.UserDTO
import allin.ext.executeWithResult import allin.ext.executeWithResult
import allin.model.User import allin.model.User
import org.ktorm.database.Database import org.ktorm.database.Database
import org.ktorm.database.use import org.ktorm.database.use
import org.ktorm.dsl.* import org.ktorm.dsl.*
import org.ktorm.entity.add
import org.ktorm.entity.filter
import org.ktorm.entity.find
import org.ktorm.entity.removeIf
import java.time.Instant.now import java.time.Instant.now
class PostgresUserDataSource(private val database: Database) : UserDataSource { class PostgresUserDataSource(private val database: Database) : UserDataSource {
override fun getUserByUsername(username: String): Pair<UserDTO?, String?> = override fun getUserByUsername(username: String): Pair<UserDTO?, String?> =
database.from(UsersEntity) database.users
.select() .find { it.username eq username }
.where { UsersEntity.username eq username } ?.let { it.toUserDTO() to it.password }
.map { row -> ?: (null to null)
Pair(
UserDTO(
row[UsersEntity.id].toString(),
row[UsersEntity.username].toString(),
row[UsersEntity.email].toString(),
row[UsersEntity.nbCoins] ?: 0,
null
),
row[UsersEntity.password].toString()
)
}
.firstOrNull() ?: Pair(null, null)
override fun addUser(user: User) { override fun addUser(user: User) {
database.insert(UsersEntity) { database.users.add(
set(it.id, user.id) UserEntity {
set(it.nbCoins, user.nbCoins) this.id = user.id
set(it.username, user.username) this.nbCoins = user.nbCoins
set(it.password, user.password) this.username = user.username
set(it.email, user.email) this.password = user.password
set(it.lastGift, now()) this.email = user.email
this.lastGift = now()
} }
)
} }
override fun deleteUser(username: String): Boolean { override fun deleteUser(username: String): Boolean =
val deletedCount = database.delete(UsersEntity) { database.users.removeIf { it.username eq username } > 0
it.username eq username
}
return deletedCount > 0
}
override fun userExists(username: String, email: String): Boolean { override fun userExists(username: String, email: String): Boolean {
return database.from(UsersEntity).select(UsersEntity.username, UsersEntity.email).where { return database.users.filter {
(UsersEntity.username eq username) and (UsersEntity.email eq email) (it.username eq username) and (it.email eq email)
}.totalRecords > 0 }.totalRecords > 0
} }
override fun addCoins(username: String, amount: Int) { override fun addCoins(username: String, amount: Int) {
database.update(UsersEntity) { database.users
set(UsersEntity.nbCoins, UsersEntity.nbCoins + amount) .find { it.username eq username }
where { UsersEntity.username eq username } ?.set(UsersEntity.nbCoins.name, UsersEntity.nbCoins + amount)
}
} }
override fun removeCoins(username: String, amount: Int) { override fun removeCoins(username: String, amount: Int) {
database.update(UsersEntity) { database.users
set(UsersEntity.nbCoins, UsersEntity.nbCoins - amount) .find { it.username eq username }
where { UsersEntity.username eq username } ?.set(UsersEntity.nbCoins.name, UsersEntity.nbCoins - amount)
}
} }
override fun canHaveDailyGift(username: String): Boolean { override fun canHaveDailyGift(username: String): Boolean {

@ -0,0 +1,36 @@
package allin.data.postgres.entities
import allin.model.BetAnswerInfo
import org.ktorm.database.Database
import org.ktorm.entity.Entity
import org.ktorm.entity.sequenceOf
import org.ktorm.schema.Table
import org.ktorm.schema.float
import org.ktorm.schema.int
import org.ktorm.schema.varchar
interface BetAnswerInfoEntity : Entity<BetAnswerInfoEntity> {
companion object : Entity.Factory<BetAnswerInfoEntity>()
var betId: String
var response: String
var totalStakes: Int
var odds: Float
fun toBetAnswerInfo() =
BetAnswerInfo(
betId = betId,
response = response,
totalStakes = totalStakes,
odds = odds
)
}
object BetAnswerInfosEntity : Table<BetAnswerInfoEntity>("betanswerinfo") {
val betId = varchar("betid").primaryKey().bindTo { it.betId }
val response = varchar("response").primaryKey().bindTo { it.response }
val totalStakes = int("totalstakes").bindTo { it.totalStakes }
val odds = float("odds").bindTo { it.odds }
}
val Database.betAnswerInfos get() = this.sequenceOf(BetAnswerInfosEntity)

@ -1,31 +1,78 @@
package allin.data.postgres.entities package allin.data.postgres.entities
import allin.model.BetStatus import allin.model.*
import allin.model.BetType import org.ktorm.database.Database
import org.ktorm.entity.Entity import org.ktorm.dsl.eq
import org.ktorm.entity.*
import org.ktorm.schema.* import org.ktorm.schema.*
import java.time.Instant
import java.time.ZoneId
import java.time.ZonedDateTime import java.time.ZonedDateTime
interface BetEntity : Entity<BetEntity> { interface BetEntity : Entity<BetEntity> {
val theme: String companion object : Entity.Factory<BetEntity>()
val sentenceBet: String
val endRegistration: ZonedDateTime var id: String
val endBet: ZonedDateTime var theme: String
val isPrivate: Boolean var sentenceBet: String
val status: BetStatus var endRegistration: Instant
val type: BetType var endBet: Instant
val createdBy: String var zoneId: String
var isPrivate: Boolean
var status: BetStatus
var type: BetType
var createdBy: String
fun toBet(database: Database) =
Bet(
id = id,
theme = theme,
sentenceBet = sentenceBet,
status = status,
type = type,
endRegistration = ZonedDateTime.ofInstant(endRegistration, ZoneId.of(zoneId)),
endBet = ZonedDateTime.ofInstant(endBet, ZoneId.of(zoneId)),
isPrivate = isPrivate,
response = if (type == BetType.BINARY) {
listOf(YES_VALUE, NO_VALUE)
} else {
database.responses.filter { it.betId eq id }.map { it.response }
},
createdBy = createdBy
)
fun toBetDetail(database: Database, username: String): BetDetail {
val bet = this.toBet(database)
val participations = database.participations.filter { it.betId eq bet.id }
val userParticipation = participations.find { it.username eq username }
val participationEntities = participations.map { it.toParticipation() }
val answerInfos = database.betAnswerInfos
.filter { it.betId eq bet.id }
.map { it.toBetAnswerInfo() }
return BetDetail(
bet = bet,
answers = getBetAnswerDetail(bet, participationEntities, answerInfos),
participations = participationEntities,
userParticipation = userParticipation?.toParticipation()
)
}
} }
object BetsEntity : Table<BetEntity>("bet") { object BetsEntity : Table<BetEntity>("bet") {
val id = varchar("id").primaryKey() val id = varchar("id").primaryKey().bindTo { it.id }
val theme = varchar("theme").bindTo { it.theme } val theme = varchar("theme").bindTo { it.theme }
val sentenceBet = varchar("sentencebet").bindTo { it.sentenceBet } val sentenceBet = varchar("sentencebet").bindTo { it.sentenceBet }
val endRegistration = timestamp("endregistration") val endRegistration = timestamp("endregistration").bindTo { it.endRegistration }
val endBet = timestamp("endbet") val endBet = timestamp("endbet").bindTo { it.endBet }
val zoneId = varchar("zoneid").bindTo { it.zoneId }
val isPrivate = boolean("isprivate").bindTo { it.isPrivate } val isPrivate = boolean("isprivate").bindTo { it.isPrivate }
val status = enum<BetStatus>("status").bindTo { it.status } val status = enum<BetStatus>("status").bindTo { it.status }
val type = enum<BetType>("type").bindTo { it.type } val type = enum<BetType>("type").bindTo { it.type }
val createdBy = varchar("createdby").bindTo { it.createdBy } val createdBy = varchar("createdby").bindTo { it.createdBy }
} }
val Database.bets get() = this.sequenceOf(BetsEntity)

@ -0,0 +1,23 @@
package allin.data.postgres.entities
import org.ktorm.database.Database
import org.ktorm.entity.Entity
import org.ktorm.entity.sequenceOf
import org.ktorm.schema.Table
import org.ktorm.schema.int
import org.ktorm.schema.varchar
interface BetInfoEntity : Entity<BetInfoEntity> {
companion object : Entity.Factory<BetInfoEntity>()
var id: String
var totalStakes: Int
}
object BetInfosEntity : Table<BetInfoEntity>("betinfo") {
val id = varchar("id").primaryKey().bindTo { it.id }
val totalStakes = int("totalstakes").bindTo { it.totalStakes }
}
val Database.betInfos get() = this.sequenceOf(BetInfosEntity)

@ -1,13 +1,37 @@
package allin.data.postgres.entities package allin.data.postgres.entities
import allin.model.BetResult
import allin.model.BetResultDetail
import org.ktorm.database.Database
import org.ktorm.entity.Entity import org.ktorm.entity.Entity
import org.ktorm.entity.sequenceOf
import org.ktorm.schema.Table import org.ktorm.schema.Table
import org.ktorm.schema.varchar import org.ktorm.schema.varchar
interface BetResultEntity : Entity<BetResultEntity> { interface BetResultEntity : Entity<BetResultEntity> {
val bet: BetEntity companion object : Entity.Factory<BetResultEntity>()
val result: String
var bet: BetEntity
var result: String
fun toBetResult() =
BetResult(
betId = bet.id,
result = result
)
fun toBetResultDetail(
database: Database,
participationEntity: ParticipationEntity
) =
BetResultDetail(
betResult = this.toBetResult(),
bet = bet.toBet(database),
participation = participationEntity.toParticipation(),
amount = participationEntity.stake,
won = participationEntity.answer == result
)
} }
object BetResultsEntity : Table<BetResultEntity>("betresult") { object BetResultsEntity : Table<BetResultEntity>("betresult") {
@ -15,12 +39,4 @@ object BetResultsEntity : Table<BetResultEntity>("betresult") {
val result = varchar("result").bindTo { it.result } val result = varchar("result").bindTo { it.result }
} }
interface BetResultNotificationEntity : Entity<BetResultNotificationEntity> { val Database.betResults get() = this.sequenceOf(BetResultsEntity)
val betId: String
val username: String
}
object BetResultNotificationsEntity : Table<BetResultNotificationEntity>("betresult") {
val betId = varchar("betid").primaryKey()
val username = varchar("username").primaryKey()
}

@ -0,0 +1,21 @@
package allin.data.postgres.entities
import org.ktorm.database.Database
import org.ktorm.entity.Entity
import org.ktorm.entity.sequenceOf
import org.ktorm.schema.Table
import org.ktorm.schema.varchar
interface BetResultNotificationEntity : Entity<BetResultNotificationEntity> {
companion object : Entity.Factory<BetResultNotificationEntity>()
var betId: String
var username: String
}
object BetResultNotificationsEntity : Table<BetResultNotificationEntity>("betresultnotification") {
val betId = varchar("betid").primaryKey()
val username = varchar("username").primaryKey()
}
val Database.betResultNotifications get() = this.sequenceOf(BetResultNotificationsEntity)

@ -1,23 +1,38 @@
package allin.data.postgres.entities package allin.data.postgres.entities
import allin.model.Participation
import org.ktorm.database.Database
import org.ktorm.entity.Entity import org.ktorm.entity.Entity
import org.ktorm.entity.sequenceOf
import org.ktorm.schema.Table import org.ktorm.schema.Table
import org.ktorm.schema.int import org.ktorm.schema.int
import org.ktorm.schema.varchar import org.ktorm.schema.varchar
interface ParticipationEntity : Entity<ParticipationEntity> { interface ParticipationEntity : Entity<ParticipationEntity> {
val id: String companion object : Entity.Factory<ParticipationEntity>()
val bet: BetEntity
val username: String var id: String
val answer: String var bet: BetEntity
val stake: Int var username: String
} var answer: String
var stake: Int
fun toParticipation() =
Participation(
id = id,
betId = bet.id,
username = username,
answer = answer,
stake = stake
)
}
object ParticipationsEntity : Table<ParticipationEntity>("participation") { object ParticipationsEntity : Table<ParticipationEntity>("participation") {
val id = varchar("id").primaryKey() val id = varchar("id").primaryKey()
val betId = varchar("bet").references(BetsEntity) { it.bet } val betId = varchar("bet").references(BetsEntity) { it.bet }
val username = varchar("username") val username = varchar("username").bindTo { it.username }
val answer = varchar("answer") val answer = varchar("answer").bindTo { it.answer }
val stake = int("stake") val stake = int("stake").bindTo { it.stake }
} }
val Database.participations get() = this.sequenceOf(ParticipationsEntity)

@ -1,19 +1,21 @@
package allin.data.postgres.entities package allin.data.postgres.entities
import org.ktorm.database.Database
import org.ktorm.entity.Entity import org.ktorm.entity.Entity
import org.ktorm.entity.sequenceOf
import org.ktorm.schema.Table import org.ktorm.schema.Table
import org.ktorm.schema.varchar import org.ktorm.schema.varchar
const val YES_VALUE = "Yes"
const val NO_VALUE = "No"
interface ResponseEntity : Entity<ResponseEntity> { interface ResponseEntity : Entity<ResponseEntity> {
val betId: String companion object : Entity.Factory<ResponseEntity>()
val response: String
var betId: String
var response: String
} }
object ResponsesEntity : Table<ResponseEntity>("response") { object ResponsesEntity : Table<ResponseEntity>("response") {
val id = varchar("id").primaryKey() val betId = varchar("betid").primaryKey().bindTo { it.betId }
val response = varchar("response").primaryKey() val response = varchar("response").primaryKey().bindTo { it.response }
} }
val Database.responses get() = this.sequenceOf(ResponsesEntity)

@ -1,24 +1,43 @@
package allin.data.postgres.entities package allin.data.postgres.entities
import allin.dto.UserDTO
import org.ktorm.database.Database
import org.ktorm.entity.Entity import org.ktorm.entity.Entity
import org.ktorm.entity.sequenceOf
import org.ktorm.schema.Table import org.ktorm.schema.Table
import org.ktorm.schema.int import org.ktorm.schema.int
import org.ktorm.schema.timestamp import org.ktorm.schema.timestamp
import org.ktorm.schema.varchar import org.ktorm.schema.varchar
import java.time.Instant
interface UserEntity : Entity<UserEntity> { interface UserEntity : Entity<UserEntity> {
val username: String companion object : Entity.Factory<UserEntity>()
var id: String
var username: String
var email: String var email: String
var password: String var password: String
var nbCoins: Int var nbCoins: Int
var lastGift: Instant
fun toUserDTO() =
UserDTO(
id = id,
username = username,
email = email,
nbCoins = nbCoins,
token = null
)
} }
object UsersEntity : Table<UserEntity>("utilisateur") { object UsersEntity : Table<UserEntity>("users") {
val id = varchar("id").primaryKey() val id = varchar("id").primaryKey().bindTo { it.id }
val username = varchar("username").bindTo { it.username } val username = varchar("username").bindTo { it.username }
val password = varchar("password").bindTo { it.password } val password = varchar("password").bindTo { it.password }
val nbCoins = int("coins").bindTo { it.nbCoins } val nbCoins = int("coins").bindTo { it.nbCoins }
val email = varchar("email").bindTo { it.email } val email = varchar("email").bindTo { it.email }
val lastGift = timestamp("lastgift") val lastGift = timestamp("lastgift").bindTo { it.lastGift }
} }
val Database.users get() = this.sequenceOf(UsersEntity)

@ -20,7 +20,7 @@ suspend fun PipelineContext<*, ApplicationCall>.verifyUserFromToken(
content: suspend (user: UserDTO, password: String) -> Unit content: suspend (user: UserDTO, password: String) -> Unit
) { ) {
val username = principal.payload.getClaim(USERNAME).asString() val username = principal.payload.getClaim(USERNAME).asString()
val userPassword = userDataSource.getUserByUsername(username) val user = userDataSource.getUserByUsername(username)
userPassword.first?.let { content(it, userPassword.second ?: "") } user.first?.let { content(it, user.second ?: "") }
?: call.respond(HttpStatusCode.NotFound, ApiMessage.TOKEN_USER_NOT_FOUND) ?: call.respond(HttpStatusCode.NotFound, ApiMessage.TOKEN_USER_NOT_FOUND)
} }

@ -5,6 +5,9 @@ import allin.serializer.ZonedDateTimeSerializer
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import java.time.ZonedDateTime import java.time.ZonedDateTime
const val YES_VALUE = "Yes"
const val NO_VALUE = "No"
@Serializable @Serializable
data class Bet( data class Bet(
val id: String = "", val id: String = "",

@ -19,16 +19,21 @@ data class BetDetail(
val userParticipation: Participation? // La participation du User current val userParticipation: Participation? // La participation du User current
) )
fun getBetAnswerDetail(bet: Bet, participations: List<Participation>): List<BetAnswerDetail> { fun getBetAnswerDetail(
bet: Bet,
participations: List<Participation>,
infos: List<BetAnswerInfo>
): List<BetAnswerDetail> {
return bet.response.map { response -> return bet.response.map { response ->
val responseParticipations = participations.filter { it.answer == response } val responseParticipations = participations.filter { it.answer == response }
val answerInfo = infos.find { it.response == response }
BetAnswerDetail( BetAnswerDetail(
response = response, response = response,
totalStakes = responseParticipations.sumOf { it.stake }, totalStakes = answerInfo?.totalStakes ?: 0,
totalParticipants = responseParticipations.size, totalParticipants = responseParticipations.size,
highestStake = responseParticipations.maxOfOrNull { it.stake } ?: 0, highestStake = responseParticipations.maxOfOrNull { it.stake } ?: 0,
odds = if (participations.isEmpty()) 1f else responseParticipations.size / participations.size.toFloat() odds = answerInfo?.odds ?: 1f
) )
} }
} }

@ -0,0 +1,17 @@
package allin.model
import kotlinx.serialization.Serializable
@Serializable
data class BetInfo(
val id: String,
val totalStakes: Int,
)
@Serializable
data class BetAnswerInfo(
val betId: String,
val response: String,
val totalStakes: Int,
val odds: Float
)

@ -5,7 +5,6 @@ import allin.ext.hasToken
import allin.ext.verifyUserFromToken import allin.ext.verifyUserFromToken
import allin.model.ApiMessage import allin.model.ApiMessage
import allin.model.BetDetail import allin.model.BetDetail
import allin.model.getBetAnswerDetail
import io.github.smiley4.ktorswaggerui.dsl.get import io.github.smiley4.ktorswaggerui.dsl.get
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.application.* import io.ktor.server.application.*
@ -19,7 +18,6 @@ import java.util.*
fun Application.betDetailRouter() { fun Application.betDetailRouter() {
val userDataSource = this.dataSource.userDataSource val userDataSource = this.dataSource.userDataSource
val betDataSource = this.dataSource.betDataSource val betDataSource = this.dataSource.betDataSource
val participationDataSource = this.dataSource.participationDataSource
routing { routing {
authenticate { authenticate {
@ -43,17 +41,11 @@ fun Application.betDetailRouter() {
hasToken { principal -> hasToken { principal ->
verifyUserFromToken(userDataSource, principal) { user, _ -> verifyUserFromToken(userDataSource, principal) { user, _ ->
val id = call.parameters["id"].toString() val id = call.parameters["id"].toString()
val participations = participationDataSource.getParticipationFromBetId(id) val result = betDataSource.getBetDetailById(id, user.username)
val selectedBet = betDataSource.getBetById(id) if (result != null) {
if (selectedBet != null) {
call.respond( call.respond(
HttpStatusCode.Accepted, HttpStatusCode.Accepted,
BetDetail( result
selectedBet,
getBetAnswerDetail(selectedBet, participations),
participations.toList(),
participationDataSource.getParticipationFromUserId(user.username, id).lastOrNull()
)
) )
} else { } else {
call.respond(HttpStatusCode.NotFound, ApiMessage.BET_NOT_FOUND) call.respond(HttpStatusCode.NotFound, ApiMessage.BET_NOT_FOUND)

@ -21,7 +21,6 @@ val tokenManagerBet = AppConfig.tokenManager
fun Application.betRouter() { fun Application.betRouter() {
val userDataSource = this.dataSource.userDataSource val userDataSource = this.dataSource.userDataSource
val betDataSource = this.dataSource.betDataSource val betDataSource = this.dataSource.betDataSource
val participationDataSource = this.dataSource.participationDataSource
routing { routing {
authenticate { authenticate {
@ -36,7 +35,7 @@ fun Application.betRouter() {
response { response {
HttpStatusCode.Created to { HttpStatusCode.Created to {
description = "the bet has been added" description = "the bet has been added"
body<Bet>() { body<Bet> {
description = "Bet with assigned id" description = "Bet with assigned id"
} }
} }
@ -54,7 +53,7 @@ fun Application.betRouter() {
betDataSource.getBetById(id)?.let { betDataSource.getBetById(id)?.let {
call.respond(HttpStatusCode.Conflict, ApiMessage.BET_ALREADY_EXIST) call.respond(HttpStatusCode.Conflict, ApiMessage.BET_ALREADY_EXIST)
} ?: run { } ?: run {
val betWithId = bet.copy(id = id, createdBy = user.first?.id.toString()) val betWithId = bet.copy(id = id, createdBy = user.first?.username.toString())
betDataSource.addBet(betWithId) betDataSource.addBet(betWithId)
call.respond(HttpStatusCode.Created, betWithId) call.respond(HttpStatusCode.Created, betWithId)
} }
@ -70,7 +69,7 @@ fun Application.betRouter() {
response { response {
HttpStatusCode.Accepted to { HttpStatusCode.Accepted to {
description = "The list of bets is available" description = "The list of bets is available"
body<List<Bet>>() { body<List<Bet>> {
description = "List of all bet in the selected source" description = "List of all bet in the selected source"
} }
} }
@ -167,7 +166,7 @@ fun Application.betRouter() {
response { response {
HttpStatusCode.Accepted to { HttpStatusCode.Accepted to {
description = "The list of bets that can be validated is available" description = "The list of bets that can be validated is available"
body<List<BetDetail>>() { body<List<BetDetail>> {
description = "list of bets that can be validated" description = "list of bets that can be validated"
} }
} }
@ -175,15 +174,7 @@ fun Application.betRouter() {
}) { }) {
hasToken { principal -> hasToken { principal ->
verifyUserFromToken(userDataSource, principal) { user, _ -> verifyUserFromToken(userDataSource, principal) { user, _ ->
val response = betDataSource.getToConfirm(user.username).map { val response = betDataSource.getToConfirm(user.username)
val participations = participationDataSource.getParticipationFromBetId(it.id)
BetDetail(
it,
getBetAnswerDetail(it, participations),
participations,
participations.find { it.username == user.username }
)
}
call.respond(HttpStatusCode.Accepted, response) call.respond(HttpStatusCode.Accepted, response)
} }
} }
@ -199,7 +190,7 @@ fun Application.betRouter() {
response { response {
HttpStatusCode.Accepted to { HttpStatusCode.Accepted to {
description = "The list of won bets is available" description = "The list of won bets is available"
body<List<BetResultDetail>>() { body<List<BetResultDetail>> {
description = "List of won bets" description = "List of won bets"
} }
} }
@ -222,7 +213,7 @@ fun Application.betRouter() {
response { response {
HttpStatusCode.Accepted to { HttpStatusCode.Accepted to {
description = "Bet history is available" description = "Bet history is available"
body<List<BetResultDetail>>() { body<List<BetResultDetail>> {
description = "Betting history list" description = "Betting history list"
} }
} }

@ -52,7 +52,7 @@ fun Application.participationRouter() {
Participation( Participation(
id = UUID.randomUUID().toString(), id = UUID.randomUUID().toString(),
betId = participation.betId, betId = participation.betId,
username = user.id, username = user.username,
answer = participation.answer, answer = participation.answer,
stake = participation.stake stake = participation.stake
) )

Loading…
Cancel
Save