diff --git a/Sources/src/main/kotlin/allin/data/FriendDataSource.kt b/Sources/src/main/kotlin/allin/data/FriendDataSource.kt index 5436116..71a25ac 100644 --- a/Sources/src/main/kotlin/allin/data/FriendDataSource.kt +++ b/Sources/src/main/kotlin/allin/data/FriendDataSource.kt @@ -6,6 +6,7 @@ import allin.model.FriendStatus interface FriendDataSource { fun addFriend(sender: String, receiver: String) fun getFriendFromUserId(id: String): List + fun getFriendRequestsFromUserId(id: String): List fun deleteFriend(senderId: String, receiverId: String): Boolean fun isFriend(firstUser: String, secondUser: String): Boolean fun filterUsersByUsername(fromUserId: String, search: String): List 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/mock/MockFriendDataSource.kt b/Sources/src/main/kotlin/allin/data/mock/MockFriendDataSource.kt index 40c2122..d41c74e 100644 --- a/Sources/src/main/kotlin/allin/data/mock/MockFriendDataSource.kt +++ b/Sources/src/main/kotlin/allin/data/mock/MockFriendDataSource.kt @@ -26,6 +26,15 @@ class MockFriendDataSource(private val mockData: MockDataSource.MockData) : Frie ) } + override fun getFriendRequestsFromUserId(id: String): List { + return friends + .filter { (it.receiver == id) && !isFriend(id, it.sender) } + .mapNotNull { + users.find { usr -> usr.id == it.sender } + ?.toDto(friendStatus = FriendStatus.NOT_FRIEND) + } + } + override fun deleteFriend(senderId: String, receiverId: String) = friends.removeIf { (it.sender == senderId) && (it.receiver == receiverId) } 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/PostgresFriendDataSource.kt b/Sources/src/main/kotlin/allin/data/postgres/PostgresFriendDataSource.kt index 4c2eefd..c42df7c 100644 --- a/Sources/src/main/kotlin/allin/data/postgres/PostgresFriendDataSource.kt +++ b/Sources/src/main/kotlin/allin/data/postgres/PostgresFriendDataSource.kt @@ -37,10 +37,26 @@ class PostgresFriendDataSource(private val database: Database) : FriendDataSourc ) } + override fun getFriendRequestsFromUserId(id: String): List { + return database.friends + .filter { it.receiver eq id } + .mapNotNull { + if (isFriend(firstUser = id, secondUser = it.sender)) { + null + } else { + database.users.find { usr -> + usr.id eq it.sender + }?.toUserDTO(friendStatus = FriendStatus.NOT_FRIEND) + } + } + } + override fun deleteFriend(senderId: String, receiverId: String): Boolean { - database.friends.removeIf { (it.sender eq receiverId) and (it.receiver eq senderId) } - return database.friends.removeIf { (it.sender eq senderId) and (it.receiver eq receiverId) } > 0 + val result = database.friends.removeIf { (it.sender eq receiverId) and (it.receiver eq senderId) } + + database.friends.removeIf { (it.sender eq senderId) and (it.receiver eq receiverId) } + + return result > 0 } override fun isFriend(firstUser: String, secondUser: String) = 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") { diff --git a/Sources/src/main/kotlin/allin/routing/friendRouter.kt b/Sources/src/main/kotlin/allin/routing/friendRouter.kt index 6b747a9..3c39bd9 100644 --- a/Sources/src/main/kotlin/allin/routing/friendRouter.kt +++ b/Sources/src/main/kotlin/allin/routing/friendRouter.kt @@ -45,6 +45,32 @@ fun Application.friendRouter() { } } + } + get("/friends/requests", { + description = "Allows you to recover all friend requests of a JWT Token" + request { + headerParameter("JWT token of the logged user") + } + response { + HttpStatusCode.Accepted to { + description = "The list of friend requests is available" + body> { + description = "List of friend requests" + } + } + } + }) { + hasToken { principal -> + verifyUserFromToken(userDataSource, principal) { _, _ -> + val username = tokenManagerBet.getUsernameFromToken(principal) + val user = userDataSource.getUserByUsername(username).first + call.respond( + HttpStatusCode.Accepted, + friendDataSource.getFriendRequestsFromUserId(user?.id.toString()) + ) + } + } + } post("/friends/add", { description = "Allows a user to add a friend" @@ -128,12 +154,10 @@ fun Application.friendRouter() { if (user == null || userFriend == null) { call.respond(HttpStatusCode.Conflict, ApiMessage.USER_NOT_FOUND) } else { - val friendlist = friendDataSource.getFriendFromUserId(user.id) - if (!friendlist.map { it.id }.contains(userFriend.id)) { - call.respond(HttpStatusCode.Conflict, ApiMessage.FRIENDS_DOESNT_EXISTS) - } else { - friendDataSource.deleteFriend(user.id, userFriend.id) + if (friendDataSource.deleteFriend(user.id, userFriend.id)) { call.respond(HttpStatusCode.Created, usernameFriend) + } else { + call.respond(HttpStatusCode.Conflict, ApiMessage.FRIENDS_DOESNT_EXISTS) } } }