Skip to content

Commit

Permalink
Use Cinnamon/Pudding transactions in Loritta Legacy (#2516)
Browse files Browse the repository at this point in the history
* Use Cinnamon's transaction system

* Use Cinnamon's transaction system
  • Loading branch information
MrPowerGamerBR authored Mar 12, 2022
1 parent e86b992 commit 1cbcf6e
Show file tree
Hide file tree
Showing 8 changed files with 257 additions and 22 deletions.
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
object Versions {
const val LORITTA = "2021-SNAPSHOT"
const val PUDDING = "0.0.2-20220309.031217-180"
const val PUDDING = "0.0.2-20220312.190907-190"
const val KOTLIN = "1.6.20-M1"
const val KTOR = "1.6.7"
const val JDA = "4.3.0_324"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import net.dv8tion.jda.api.entities.User
import net.perfectdreams.loritta.api.commands.ArgumentType
import net.perfectdreams.loritta.api.commands.arguments
import net.perfectdreams.loritta.api.messages.LorittaReply
import net.perfectdreams.loritta.cinnamon.pudding.tables.CoinFlipBetMatchmakingResults
import net.perfectdreams.loritta.cinnamon.pudding.tables.CoinFlipBetSonhosTransactionsLog
import net.perfectdreams.loritta.cinnamon.pudding.tables.SonhosTransactionsLog
import net.perfectdreams.loritta.common.commands.CommandCategory
import net.perfectdreams.loritta.platform.discord.legacy.commands.DiscordAbstractCommandBase
import net.perfectdreams.loritta.plugin.helpinghands.HelpingHandsPlugin
Expand All @@ -29,6 +32,9 @@ import net.perfectdreams.loritta.utils.UserPremiumPlans
import net.perfectdreams.loritta.utils.extensions.refreshInDeferredTransaction
import net.perfectdreams.loritta.utils.extensions.toJDA
import net.perfectdreams.loritta.utils.sendStyledReply
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.insertAndGetId
import java.time.Instant

class CoinFlipBetCommand(val plugin: HelpingHandsPlugin) : DiscordAbstractCommandBase(
plugin.loritta,
Expand Down Expand Up @@ -73,27 +79,37 @@ class CoinFlipBetCommand(val plugin: HelpingHandsPlugin) : DiscordAbstractComman
val hasNoTax: Boolean
val whoHasTheNoTaxReward: User?
val plan: UserPremiumPlans?
val tax: Long?
val taxPercentage: Double?
val quantityAfterTax: Long
val money: Long

val number = NumberUtils.convertShortenedNumberToLong(args[1])
?: GenericReplies.invalidNumber(this, args[1].stripCodeMarks())

if (selfPlan.totalCoinFlipReward == 1.0) {
whoHasTheNoTaxReward = discordMessage.author
hasNoTax = true
plan = selfPlan
taxPercentage = 0.0
tax = null
money = number
} else if (otherPlan.totalCoinFlipReward == 1.0) {
whoHasTheNoTaxReward = invitedUser
hasNoTax = true
plan = otherPlan
taxPercentage = 0.0
tax = null
money = number
} else {
whoHasTheNoTaxReward = null
hasNoTax = false
plan = UserPremiumPlans.Essential
taxPercentage = (1.0.toBigDecimal() - selfPlan.totalCoinFlipReward.toBigDecimal()).toDouble() // Avoid rounding errors
tax = (number * taxPercentage).toLong()
money = number - tax
}

val number = NumberUtils.convertShortenedNumberToLong(args[1])
?: GenericReplies.invalidNumber(this, args[1].stripCodeMarks())

val tax = (number * (1.0 - plan.totalCoinFlipReward)).toLong()
val money = number - tax

if (!hasNoTax && tax == 0L)
fail(locale["commands.command.flipcoinbet.youNeedToBetMore"], Constants.ERROR)

Expand Down Expand Up @@ -204,6 +220,7 @@ class CoinFlipBetCommand(val plugin: HelpingHandsPlugin) : DiscordAbstractComman

val winner: User
val loser: User
val now = Instant.now()

if (isTails) {
winner = user
Expand All @@ -218,6 +235,37 @@ class CoinFlipBetCommand(val plugin: HelpingHandsPlugin) : DiscordAbstractComman
givenBy = invitedUserProfile.id.value,
receivedBy = selfUserProfile.id.value
)

// Cinnamon transaction system
val mmResult = CoinFlipBetMatchmakingResults.insertAndGetId {
it[CoinFlipBetMatchmakingResults.timestamp] = now
it[CoinFlipBetMatchmakingResults.winner] = selfUserProfile.id.value
it[CoinFlipBetMatchmakingResults.loser] = invitedUserProfile.id.value
it[CoinFlipBetMatchmakingResults.quantity] = number
it[CoinFlipBetMatchmakingResults.quantityAfterTax] = money
it[CoinFlipBetMatchmakingResults.tax] = tax
it[CoinFlipBetMatchmakingResults.taxPercentage] = taxPercentage
}

val winnerTransactionLogId = SonhosTransactionsLog.insertAndGetId {
it[SonhosTransactionsLog.user] = selfUserProfile.id.value
it[SonhosTransactionsLog.timestamp] = now
}

CoinFlipBetSonhosTransactionsLog.insert {
it[CoinFlipBetSonhosTransactionsLog.timestampLog] = winnerTransactionLogId
it[CoinFlipBetSonhosTransactionsLog.matchmakingResult] = mmResult
}

val loserTransactionLogId = SonhosTransactionsLog.insertAndGetId {
it[SonhosTransactionsLog.user] = invitedUserProfile.id.value
it[SonhosTransactionsLog.timestamp] = now
}

CoinFlipBetSonhosTransactionsLog.insert {
it[CoinFlipBetSonhosTransactionsLog.timestampLog] = loserTransactionLogId
it[CoinFlipBetSonhosTransactionsLog.matchmakingResult] = mmResult
}
}
} else {
winner = invitedUser
Expand All @@ -232,6 +280,37 @@ class CoinFlipBetCommand(val plugin: HelpingHandsPlugin) : DiscordAbstractComman
givenBy = selfUserProfile.id.value,
receivedBy = invitedUserProfile.id.value
)

// Cinnamon transaction system
val mmResult = CoinFlipBetMatchmakingResults.insertAndGetId {
it[CoinFlipBetMatchmakingResults.timestamp] = Instant.now()
it[CoinFlipBetMatchmakingResults.winner] = invitedUserProfile.id.value
it[CoinFlipBetMatchmakingResults.loser] = selfUserProfile.id.value
it[CoinFlipBetMatchmakingResults.quantity] = number
it[CoinFlipBetMatchmakingResults.quantityAfterTax] = money
it[CoinFlipBetMatchmakingResults.tax] = tax
it[CoinFlipBetMatchmakingResults.taxPercentage] = taxPercentage
}

val winnerTransactionLogId = SonhosTransactionsLog.insertAndGetId {
it[SonhosTransactionsLog.user] = invitedUserProfile.id.value
it[SonhosTransactionsLog.timestamp] = now
}

CoinFlipBetSonhosTransactionsLog.insert {
it[CoinFlipBetSonhosTransactionsLog.timestampLog] = winnerTransactionLogId
it[CoinFlipBetSonhosTransactionsLog.matchmakingResult] = mmResult
}

val loserTransactionLogId = SonhosTransactionsLog.insertAndGetId {
it[SonhosTransactionsLog.user] = selfUserProfile.id.value
it[SonhosTransactionsLog.timestamp] = now
}

CoinFlipBetSonhosTransactionsLog.insert {
it[CoinFlipBetSonhosTransactionsLog.timestampLog] = loserTransactionLogId
it[CoinFlipBetSonhosTransactionsLog.matchmakingResult] = mmResult
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,22 @@ import net.dv8tion.jda.api.EmbedBuilder
import net.dv8tion.jda.api.entities.Message
import net.dv8tion.jda.api.entities.MessageEmbed
import net.dv8tion.jda.api.entities.User
import net.perfectdreams.loritta.cinnamon.pudding.tables.CoinFlipBetSonhosTransactionsLog
import net.perfectdreams.loritta.cinnamon.pudding.tables.EmojiFightMatches
import net.perfectdreams.loritta.cinnamon.pudding.tables.EmojiFightMatchmakingResults
import net.perfectdreams.loritta.cinnamon.pudding.tables.EmojiFightParticipants
import net.perfectdreams.loritta.cinnamon.pudding.tables.EmojiFightSonhosTransactionsLog
import net.perfectdreams.loritta.cinnamon.pudding.tables.SonhosTransactionsLog
import net.perfectdreams.loritta.platform.discord.legacy.commands.DiscordCommandContext
import net.perfectdreams.loritta.plugin.helpinghands.HelpingHandsPlugin
import net.perfectdreams.loritta.utils.AccountUtils
import net.perfectdreams.loritta.utils.Emotes
import net.perfectdreams.loritta.utils.PaymentUtils
import net.perfectdreams.loritta.utils.SonhosPaymentReason
import net.perfectdreams.loritta.utils.UserPremiumPlans
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.insertAndGetId
import java.time.Instant
import java.util.concurrent.ConcurrentHashMap

/**
Expand All @@ -38,13 +47,14 @@ class EmojiFight(
private val addingUserToEventMutex = Mutex()
private val finishingEventMutex = Mutex()
private var eventFinished = false
val startedAt = Instant.now()

/**
* Starts the Emoji Fight
*/
suspend fun start() {
if (entryPrice != null) {
val tax = (entryPrice * (1.0 * UserPremiumPlans.Free.totalCoinFlipReward)).toLong()
val tax = (entryPrice * (1.0 - UserPremiumPlans.Free.totalCoinFlipReward)).toLong()

if (tax == 0L)
context.fail(context.locale["commands.command.flipcoinbet.youNeedToBetMore"], Constants.ERROR)
Expand Down Expand Up @@ -211,6 +221,8 @@ class EmojiFight(
eventFinished = true

val result = loritta.newSuspendedTransaction {
val now = Instant.now()

// We need to filter the "real" valid users.
// Since some may have lost sonhos since the event start, so we are going to remove all of them.
val realValidParticipatingUsers = mutableMapOf<User, String>()
Expand All @@ -235,29 +247,68 @@ class EmojiFight(
if (2 > realValidParticipatingUsers.size)
return@newSuspendedTransaction null

// Cinnamon emoji fight match stats
val emojiFightMatch = EmojiFightMatches.insertAndGetId {
it[EmojiFightMatches.createdBy] = context.user.idLong
it[EmojiFightMatches.createdAt] = startedAt
it[EmojiFightMatches.finishedAt] = now
it[EmojiFightMatches.maxPlayers] = maxPlayers
}

val databaseParticipatingUserEntries = realValidParticipatingUsers.map { (user, emoji) ->
user to EmojiFightParticipants.insertAndGetId {
it[EmojiFightParticipants.match] = emojiFightMatch
it[EmojiFightParticipants.user] = user.idLong
it[EmojiFightParticipants.emoji] = emoji
}
}.toMap()

val winner = realValidParticipatingUsers.entries.random()
val losers = realValidParticipatingUsers.entries.apply {
this.remove(winner)
}

if (entryPrice != null) {
val realPrize = entryPrice * losers.size

val selfActiveDonations = loritta._getActiveMoneyFromDonations(winner.key.idLong)

val selfPlan = UserPremiumPlans.getPlanFromValue(selfActiveDonations)

val winnerProfile = userProfiles[winner.key]!!
val taxPercentage = (1.0.toBigDecimal() - selfPlan.totalCoinFlipReward.toBigDecimal()).toDouble() // Avoid rounding errors
val tax = (entryPrice * taxPercentage).toLong()
val taxedEntryPrice = entryPrice - tax

val realBeforeTaxesPrize = entryPrice * losers.size
val realAfterTaxesPrize = taxedEntryPrice * losers.size

val resultId = EmojiFightMatchmakingResults.insertAndGetId {
it[EmojiFightMatchmakingResults.winner] = databaseParticipatingUserEntries[winner.key] ?: error("Participating user is null! This should never happen!!")
it[EmojiFightMatchmakingResults.entryPrice] = this@EmojiFight.entryPrice
it[EmojiFightMatchmakingResults.entryPriceAfterTax] = taxedEntryPrice
if (taxPercentage != 0.0) {
it[EmojiFightMatchmakingResults.tax] = tax
it[EmojiFightMatchmakingResults.taxPercentage] = taxPercentage
}
}

val taxedRealPrize = (selfPlan.totalCoinFlipReward * realPrize).toLong()

winnerProfile.addSonhosNested(taxedRealPrize)
winnerProfile.addSonhosNested(realAfterTaxesPrize)
PaymentUtils.addToTransactionLogNested(
taxedRealPrize,
realAfterTaxesPrize,
SonhosPaymentReason.EMOJI_FIGHT,
receivedBy = winnerProfile.id.value
)

// Cinnamon transaction system
val winnerTransactionLogId = SonhosTransactionsLog.insertAndGetId {
it[SonhosTransactionsLog.user] = winnerProfile.id
it[SonhosTransactionsLog.timestamp] = now
}

EmojiFightSonhosTransactionsLog.insert {
it[EmojiFightSonhosTransactionsLog.timestampLog] = winnerTransactionLogId
it[EmojiFightSonhosTransactionsLog.matchmakingResult] = resultId
}

for (loser in losers) {
val loserProfile = userProfiles[loser.key]!!
loserProfile.takeSonhosNested(entryPrice)
Expand All @@ -266,10 +317,29 @@ class EmojiFight(
SonhosPaymentReason.EMOJI_FIGHT,
givenBy = loserProfile.id.value
)

// Cinnamon transaction system
val loserTransactionLogId = SonhosTransactionsLog.insertAndGetId {
it[SonhosTransactionsLog.user] = loserProfile.id
it[SonhosTransactionsLog.timestamp] = now
}

EmojiFightSonhosTransactionsLog.insert {
it[CoinFlipBetSonhosTransactionsLog.timestampLog] = loserTransactionLogId
it[CoinFlipBetSonhosTransactionsLog.matchmakingResult] = resultId
}
}

DbResponse(winner, losers, realPrize, taxedRealPrize)
DbResponse(winner, losers, realBeforeTaxesPrize, realAfterTaxesPrize)
} else {
val resultId = EmojiFightMatchmakingResults.insertAndGetId {
it[EmojiFightMatchmakingResults.winner] = databaseParticipatingUserEntries[winner.key] ?: error("Participating user is null! This should never happen!!")
it[EmojiFightMatchmakingResults.entryPrice] = 0
it[EmojiFightMatchmakingResults.entryPriceAfterTax] = 0
it[EmojiFightMatchmakingResults.tax] = null
it[EmojiFightMatchmakingResults.taxPercentage] = null
}

DbResponse(winner, losers, 0, 0)
}
}
Expand Down
2 changes: 1 addition & 1 deletion loritta-serializable-commons/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ kotlin {
dependencies {
implementation(kotlin("stdlib-common"))
implementation(project(":common-legacy"))
api("net.perfectdreams.loritta.cinnamon.pudding:data:0.0.2-20220309.031215-180")
api("net.perfectdreams.loritta.cinnamon.pudding:data:${Versions.PUDDING}")
}
}

Expand Down
3 changes: 2 additions & 1 deletion platforms/discord/legacy/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ dependencies {
api("org.jetbrains.exposed:exposed-dao:${Versions.EXPOSED}")
api("org.jetbrains.exposed:exposed-jdbc:${Versions.EXPOSED}")
api("pw.forst:exposed-upsert:1.1.0")
api("net.perfectdreams.loritta.cinnamon.pudding:data:0.0.2-20220309.031215-180")
api("net.perfectdreams.loritta.cinnamon:common:${Versions.PUDDING}")
api("net.perfectdreams.loritta.cinnamon.pudding:data:${Versions.PUDDING}")
api("net.perfectdreams.loritta.cinnamon.pudding:client:${Versions.PUDDING}")

// DreamStorageService
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,27 @@ import com.mrpowergamerbr.loritta.utils.lorittaSupervisor
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import net.perfectdreams.loritta.common.commands.CommandCategory
import net.perfectdreams.loritta.api.messages.LorittaReply
import net.perfectdreams.loritta.cinnamon.pudding.tables.DivineInterventionSonhosTransactionsLog
import net.perfectdreams.loritta.cinnamon.pudding.tables.SonhosTransactionsLog
import net.perfectdreams.loritta.cinnamon.common.utils.DivineInterventionTransactionEntryAction
import net.perfectdreams.loritta.common.commands.CommandCategory
import net.perfectdreams.loritta.common.locale.BaseLocale
import net.perfectdreams.loritta.dao.Payment
import net.perfectdreams.loritta.dao.servers.moduleconfigs.EconomyConfig
import net.perfectdreams.loritta.tables.BlacklistedGuilds
import net.perfectdreams.loritta.utils.ClusterOfflineException
import net.perfectdreams.loritta.common.locale.BaseLocale
import net.perfectdreams.loritta.utils.payments.PaymentGateway
import net.perfectdreams.loritta.utils.payments.PaymentReason
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.sql.SqlExpressionBuilder
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.deleteWhere
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.insertAndGetId
import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update
import java.time.Instant

class LoriServerListConfigCommand : AbstractCommand("lslc", category = CommandCategory.MAGIC) {
override fun getDescription(locale: BaseLocale): String {
Expand Down Expand Up @@ -146,6 +151,18 @@ class LoriServerListConfigCommand : AbstractCommand("lslc", category = CommandCa
it.update(money, money + arg1.toLong())
}
}

val transactionLogId = SonhosTransactionsLog.insertAndGetId {
it[SonhosTransactionsLog.user] = user.idLong
it[SonhosTransactionsLog.timestamp] = Instant.now()
}

DivineInterventionSonhosTransactionsLog.insert {
it[DivineInterventionSonhosTransactionsLog.timestampLog] = transactionLogId
it[DivineInterventionSonhosTransactionsLog.editedBy] = context.userHandle.idLong
it[DivineInterventionSonhosTransactionsLog.action] = DivineInterventionTransactionEntryAction.ADDED_SONHOS
it[DivineInterventionSonhosTransactionsLog.sonhos] = arg1.toLong()
}
}

context.reply(
Expand All @@ -164,6 +181,18 @@ class LoriServerListConfigCommand : AbstractCommand("lslc", category = CommandCa
it.update(money, money - arg1.toLong())
}
}

val transactionLogId = SonhosTransactionsLog.insertAndGetId {
it[SonhosTransactionsLog.user] = user.idLong
it[SonhosTransactionsLog.timestamp] = Instant.now()
}

DivineInterventionSonhosTransactionsLog.insert {
it[DivineInterventionSonhosTransactionsLog.timestampLog] = transactionLogId
it[DivineInterventionSonhosTransactionsLog.editedBy] = context.userHandle.idLong
it[DivineInterventionSonhosTransactionsLog.action] = DivineInterventionTransactionEntryAction.REMOVED_SONHOS
it[DivineInterventionSonhosTransactionsLog.sonhos] = arg1.toLong()
}
}

context.reply(
Expand Down
Loading

0 comments on commit 1cbcf6e

Please sign in to comment.