Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Cinnamon/Pudding transactions in Loritta Legacy #2516

Merged
merged 2 commits into from
Mar 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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