Fix analytics, better odds, delete messages, clean up

This commit is contained in:
Joseph Ferano 2022-04-20 22:38:17 +07:00
parent df7b72f0c4
commit 1d9dddfec0
3 changed files with 87 additions and 69 deletions

View File

@ -155,13 +155,13 @@ let prizeTableViewed (discordMember : DiscordMember) =
let data = [ let data = [
"user_display_name" , discordMember.Username "user_display_name" , discordMember.Username
] ]
track "Shield Button Clicked" discordMember.Id data track "Prize Table Button Clicked" discordMember.Id data
let slotPlayed (discordMember : DiscordMember) amount result prize = let slotPlayed (discordMember : DiscordMember) amount result prize =
let data = [ let data = [
"user_display_name" , discordMember.Username "user_display_name" , discordMember.Username
"play_amount" , string amount "play_amount" , string amount
"result" , string result "result" , result
"prize" , string result "prize" , string prize
] ]
track "Shield Button Clicked" discordMember.Id data track "Slots Played" discordMember.Id data

View File

@ -76,6 +76,7 @@ inviterBot.add_GuildMemberAdded(AsyncEventHandler(InviteTracker.handleGuildMembe
inviterBot.add_ComponentInteractionCreated(AsyncEventHandler(InviteTracker.handleButtonEvent)) inviterBot.add_ComponentInteractionCreated(AsyncEventHandler(InviteTracker.handleButtonEvent))
slotsBot.add_ComponentInteractionCreated(AsyncEventHandler(SlotMachine.handleButton)) slotsBot.add_ComponentInteractionCreated(AsyncEventHandler(SlotMachine.handleButton))
slotsBot.add_GuildDownloadCompleted(AsyncEventHandler(SlotMachine.handleGuildDownloadCompleted)) slotsBot.add_GuildDownloadCompleted(AsyncEventHandler(SlotMachine.handleGuildDownloadCompleted))
slotsBot.add_MessageCreated(AsyncEventHandler(SlotMachine.handleMessageCreated))
adminBot.add_GuildDownloadCompleted(AsyncEventHandler(Admin.handleGuildDownloadReady)) adminBot.add_GuildDownloadCompleted(AsyncEventHandler(Admin.handleGuildDownloadReady))
let asdf (_ : DiscordClient) (event : DSharpPlus.EventArgs.InteractionCreateEventArgs) = let asdf (_ : DiscordClient) (event : DSharpPlus.EventArgs.InteractionCreateEventArgs) =

View File

@ -18,24 +18,6 @@ type SlotSymbol = {
reel3Count : int reel3Count : int
} }
let BigBrother = { index = 0 ; reel1Count = 1 ; reel2Count = 1 ; reel3Count = 1 ; emojiName = "bigbrother" }
let Eye = { index = 1 ; reel1Count = 3 ; reel2Count = 2 ; reel3Count = 1 ; emojiName = "aneye" }
let Obey = { index = 2 ; reel1Count = 2 ; reel2Count = 2 ; reel3Count = 2 ; emojiName = "obey" }
let AnonMask = { index = 3 ; reel1Count = 1 ; reel2Count = 2 ; reel3Count = 4 ; emojiName = "anonmask" }
let Ramen = { index = 5 ; reel1Count = 3 ; reel2Count = 3 ; reel3Count = 1 ; emojiName = "ramen" }
let Sushi = { index = 4 ; reel1Count = 3 ; reel2Count = 2 ; reel3Count = 2 ; emojiName = "sushi" }
let Pizza = { index = 6 ; reel1Count = 2 ; reel2Count = 4 ; reel3Count = 0 ; emojiName = "pizza" }
let Alcohol = { index = 7 ; reel1Count = 1 ; reel2Count = 1 ; reel3Count = 1 ; emojiName = "alcohol" }
let Circuit = { index = 0 ; reel1Count = 0 ; reel2Count = 0 ; reel3Count = 2 ; emojiName = "circuitboard" }
let OldTv = { index = 9 ; reel1Count = 1 ; reel2Count = 2 ; reel3Count = 2 ; emojiName = "oldtv" }
let Pills = { index = 10 ; reel1Count = 2 ; reel2Count = 1 ; reel3Count = 2 ; emojiName = "pills" }
let Rat = { index = 11 ; reel1Count = 2 ; reel2Count = 1 ; reel3Count = 1 ; emojiName = "rat" }
let symbols = [ BigBrother ; Eye ; Obey ; AnonMask ; Sushi ; Ramen ; Pizza ; Alcohol ; Circuit ; OldTv ; Pills ; Rat ]
//let symbols = [ BigBrother ; Eye ; Obey ; AnonMask ; Sushi ; Ramen ; Pizza ; Alcohol ]
let getReel fn = List.fold (fun acc elem -> (List.replicate (fn elem) elem) @ acc) [] symbols |> List.toArray
type Prize = type Prize =
| Money of int<GBT> | Money of int<GBT>
| Jackpot | Jackpot
@ -44,51 +26,79 @@ type Slot =
| Symbol of SlotSymbol | Symbol of SlotSymbol
| Any | Any
let BigBrother = { index = 0 ; reel1Count = 2 ; reel2Count = 2 ; reel3Count = 2 ; emojiName = "bigbrother" }
let Eye = { index = 1 ; reel1Count = 2 ; reel2Count = 3 ; reel3Count = 2 ; emojiName = "aneye" }
let Obey = { index = 2 ; reel1Count = 3 ; reel2Count = 3 ; reel3Count = 3 ; emojiName = "obey" }
let AnonMask = { index = 3 ; reel1Count = 2 ; reel2Count = 2 ; reel3Count = 4 ; emojiName = "anonmask" }
let Rat = { index = 4 ; reel1Count = 4 ; reel2Count = 4 ; reel3Count = 3 ; emojiName = "rat" }
let Ramen = { index = 5 ; reel1Count = 5 ; reel2Count = 5 ; reel3Count = 5 ; emojiName = "ramen" }
let Sushi = { index = 6 ; reel1Count = 6 ; reel2Count = 6 ; reel3Count = 3 ; emojiName = "sushi" }
let Pizza = { index = 7 ; reel1Count = 0 ; reel2Count = 3 ; reel3Count = 7 ; emojiName = "pizza" }
//let Alcohol = { index = 8 ; reel1Count = 1 ; reel2Count = 1 ; reel3Count = 1 ; emojiName = "alcohol" }
//let Circuit = { index = 9 ; reel1Count = 0 ; reel2Count = 0 ; reel3Count = 2 ; emojiName = "circuitboard" }
//let OldTv = { index = 10 ; reel1Count = 1 ; reel2Count = 2 ; reel3Count = 2 ; emojiName = "oldtv" }
//let Pills = { index = 11 ; reel1Count = 2 ; reel2Count = 1 ; reel3Count = 2 ; emojiName = "pills" }
//let symbols = [ BigBrother ; Eye ; Obey ; AnonMask ; Sushi ; Ramen ; Pizza ; Alcohol ; Circuit ; OldTv ; Pills ; Rat ]
let symbols = [ BigBrother ; Eye ; Obey ; AnonMask ; Sushi ; Ramen ; Pizza ; Rat ]
type PrizeEntry = Slot * Slot * Slot * Prize
let prizeTable = let prizeTable =
[| Symbol BigBrother , Symbol BigBrother , Symbol BigBrother , Jackpot [| Symbol BigBrother , Symbol BigBrother , Symbol BigBrother , Jackpot
Symbol Eye , Symbol Eye , Symbol Eye , Money 500<GBT> Symbol Eye , Symbol Eye , Symbol Eye , Money 500<GBT>
Symbol Eye , Symbol Eye , Symbol AnonMask , Money 500<GBT>
Symbol AnonMask , Symbol AnonMask , Symbol AnonMask , Money 250<GBT> Symbol AnonMask , Symbol AnonMask , Symbol AnonMask , Money 250<GBT>
Symbol Obey , Symbol Obey , Symbol Obey , Money 200<GBT> Symbol Obey , Symbol Obey , Symbol Obey , Money 250<GBT>
Symbol Obey , Symbol Obey , Symbol AnonMask , Money 200<GBT>
Symbol Sushi , Symbol Sushi , Symbol Sushi , Money 200<GBT>
Symbol Ramen , Symbol Ramen , Symbol Ramen , Money 150<GBT> Symbol Ramen , Symbol Ramen , Symbol Ramen , Money 150<GBT>
Symbol Alcohol , Symbol Alcohol , Symbol Alcohol , Money 100<GBT> // Symbol Alcohol , Symbol Alcohol , Symbol Alcohol , Money 100<GBT>
Symbol OldTv , Symbol OldTv , Symbol OldTv , Money 100<GBT> // Symbol OldTv , Symbol OldTv , Symbol OldTv , Money 100<GBT>
Symbol Pills , Symbol Pills , Symbol Pills , Money 100<GBT> // Symbol Pills , Symbol Pills , Symbol Pills , Money 100<GBT>
Symbol Rat , Symbol Rat , Symbol Rat , Money 100<GBT> Symbol Rat , Symbol Rat , Symbol Rat , Money 100<GBT>
Symbol Sushi , Symbol Sushi , Any , Money 50<GBT> Symbol Sushi , Symbol Sushi , Any , Money 50<GBT>
Symbol Pizza , Any , Any , Money 20<GBT> |] Any , Any , Symbol Pizza , Money 20<GBT> |]
let calculateOdds (prizeTable : PrizeEntry array) prizeIndex =
let totalPerReel (reel : SlotSymbol -> int) = List.sumBy reel symbols let totalPerReel (reel : SlotSymbol -> int) = List.sumBy reel symbols
let r1 s = s.reel1Count
let r2 s = s.reel2Count
let r3 s = s.reel3Count
let totalForReel1 = function Symbol sym -> r1 sym | Any -> totalPerReel (fun s -> s.reel1Count)
let totalForReel2 = function Symbol sym -> r2 sym | Any -> totalPerReel (fun s -> s.reel2Count)
let totalForReel3 = function Symbol sym -> r3 sym | Any -> totalPerReel (fun s -> s.reel3Count)
let s1 , s2 , s3 , _ = prizeTable.[prizeIndex]
totalForReel1 s1 * totalForReel2 s2 * totalForReel3 s3
let calculateOdds prizeIndex = let getTotalCombinations symbols =
match prizeTable.[prizeIndex] with
| Symbol s1 , Symbol s2 , Symbol s3 , _ -> s1.reel1Count * s2.reel2Count * s3.reel3Count
| Symbol s1 , Symbol s2 , Any , _ -> s1.reel1Count * s2.reel2Count * totalPerReel (fun s -> s.reel3Count)
| Symbol s1 , Any , Any , _ -> s1.reel1Count * totalPerReel (fun s -> s.reel2Count) * totalPerReel (fun s -> s.reel3Count)
| _ -> 0
let getTotalCombinations () =
(List.sumBy (fun s -> s.reel1Count) symbols) (List.sumBy (fun s -> s.reel1Count) symbols)
* (List.sumBy (fun s -> s.reel2Count) symbols) * (List.sumBy (fun s -> s.reel2Count) symbols)
* (List.sumBy (fun s -> s.reel3Count) symbols) * (List.sumBy (fun s -> s.reel3Count) symbols)
let getOddsForPrize prizeIndex = let getOddsForPrize symbols prizeTable prizeIndex =
let odds = calculateOdds prizeIndex let odds = calculateOdds prizeTable prizeIndex
let total = getTotalCombinations () let total = getTotalCombinations symbols
$"{odds} in {total }" $"{odds} in {total }"
// getOddsForPrize 0 let getTotalWaysOfWinning (prizeTable : PrizeEntry array) =
// getOddsForPrize 1
// getOddsForPrize 5
// getOddsForPrize 10
let getTotalWaysOfWinning () =
[0..prizeTable.Length - 1] [0..prizeTable.Length - 1]
|> List.sumBy calculateOdds |> List.sumBy (calculateOdds prizeTable)
//totalPerReel (fun s -> s.reel1Count) let printOddsTable symbols (prizeTable : PrizeEntry array) =
//totalPerReel (fun s -> s.reel2Count) ([0..prizeTable.Length - 1]
//totalPerReel (fun s -> s.reel3Count) |> List.fold (fun acc elem ->
let name = function Symbol s -> s.emojiName | Any -> "Any"
let s1 , s2, s3, _ = prizeTable.[elem]
acc + $"{name s1} | {name s2} | {name s3} --- {getOddsForPrize symbols prizeTable elem}\n") "")
+ "-----------------------------\n"
+ $"Odds of winning something:{getTotalWaysOfWinning prizeTable} out of {getTotalCombinations symbols}"
//printOddsTable symbols prizeTable
let getReel fn = List.fold (fun acc elem -> (List.replicate (fn elem) elem) @ acc) [] symbols |> List.toArray
let reel1 = getReel (fun s -> s.reel1Count) let reel1 = getReel (fun s -> s.reel1Count)
let reel2 = getReel (fun s -> s.reel2Count) let reel2 = getReel (fun s -> s.reel2Count)
let reel3 = getReel (fun s -> s.reel3Count) let reel3 = getReel (fun s -> s.reel3Count)
@ -168,29 +178,23 @@ let handlePrizeTable (ctx : IDiscordContext) =
let embed = DiscordEmbedBuilder() let embed = DiscordEmbedBuilder()
match guildEmojis , anyEmoji with match guildEmojis , anyEmoji with
| Some emojis , Some any -> | Some emojis , Some any ->
let folder (i,acc,b) elem = let folder (i,acc) elem =
let s1,s2,s3,prize = elem let s1,s2,s3,prize = elem
let prizeTxt = match prize with Money m -> $"**{m}** $GBT" | Jackpot -> $"**JACKPOT**" let prizeTxt = match prize with Money m -> $"**{m}** $GBT" | Jackpot -> $"**JACKPOT**"
let line = let line =
match s1 , s2 , s3 with let getEmoji = function Symbol s -> Formatter.Emoji(emojis.[s.emojiName]) | Any -> Formatter.Emoji(any)
| Symbol s1' , Symbol s2' , Symbol s3' -> $"{getEmoji s1}{getEmoji s2}{getEmoji s3}"
$"{Formatter.Emoji(emojis.[s1'.emojiName])}{Formatter.Emoji(emojis.[s2'.emojiName])}{Formatter.Emoji(emojis.[s3'.emojiName])}"
| Symbol s1' , Symbol s2' , Any ->
$"{Formatter.Emoji(emojis.[s1'.emojiName])}{Formatter.Emoji(emojis.[s2'.emojiName])}{Formatter.Emoji(any)}"
| Symbol s1' , Any , Any ->
$"{Formatter.Emoji(emojis.[s1'.emojiName])}{Formatter.Emoji(any)}{Formatter.Emoji(any)}"
| _ -> ""
let text = let text =
if prizeTxt.Contains("100") then if prizeTxt.Contains("100") then
acc acc
else else
$"{acc}\n{line} {prizeTxt}" $"{acc}\n{line} {prizeTxt}"
(i + 1) , text , ( b || prizeTxt.Contains("100") ) (i + 1) , text
let! jackpot = getJackpotAmount () let! jackpot = getJackpotAmount ()
let _ , rows , _ = Array.fold folder (0, "", false) prizeTable let _ , rows = Array.fold folder (0, "") prizeTable
embed.Color <- DiscordColor.Green embed.Color <- DiscordColor.Green
embed.Title <- $"CURRENT JACKPOT: `{jackpot} 💰 $GBT`" embed.Title <- $"CURRENT JACKPOT: `{jackpot} 💰 $GBT`"
embed.Description <- embed.Description + $"\n\n**PRIZE TABLE **\n{rows}\n\n**ANY 3** | **100** $GBT" embed.Description <- embed.Description + $"\n\n**PRIZE TABLE **\n{rows}\n\n**ANY SAME 3** | **100** $GBT"
do! ctx.FollowUp(DiscordFollowupMessageBuilder().AsEphemeral().AddEmbed(embed)) do! ctx.FollowUp(DiscordFollowupMessageBuilder().AsEphemeral().AddEmbed(embed))
do! Analytics.prizeTableViewed (ctx.GetDiscordMember()) do! Analytics.prizeTableViewed (ctx.GetDiscordMember())
| _ , _ -> return () | _ , _ -> return ()
@ -230,23 +234,29 @@ let spin multiplier (ctx : IDiscordContext) =
| _ -> PlayPricex3 | _ -> PlayPricex3
let execute player = async { let execute player = async {
do! DbService.updatePlayerCurrency -playAmount player |> Async.Ignore do! DbService.updatePlayerCurrency -playAmount player |> Async.Ignore
let random = Random(Guid.NewGuid().GetHashCode()) let random = System.Random(System.Guid.NewGuid().GetHashCode())
let symbols = [| reel1.[random.Next(0, reel1.Length)] ; reel2.[random.Next(0, reel2.Length)] ; reel3.[random.Next(0, reel3.Length)] |] let results = [| reel1.[random.Next(0, reel1.Length)] ; reel2.[random.Next(0, reel2.Length)] ; reel3.[random.Next(0, reel3.Length)] |]
let prize = let getPrize (results : SlotSymbol array) =
prizeTable prizeTable
|> Array.tryPick (fun (s1,s2,s3,prize) -> |> Array.tryPick (fun (s1,s2,s3,prize) ->
match s1 , s2 , s3 with let getIndex = function Symbol s -> s.index | Any -> -1
| Symbol s1' , Symbol s2' , Symbol s3' when s1'.index = symbols.[0].index && s2'.index = symbols.[1].index && s3'.index = symbols.[2].index -> Some prize let indices = [ s1 ; s2 ; s3 ] |> List.map getIndex
| Symbol s1' , Symbol s2' , Any when s1'.index = symbols.[0].index && s2'.index = symbols.[1].index -> Some prize let compare i1 i2 = i1 = i2 || i1 = -1
| Symbol s1' , Any , Any when s1'.index = symbols.[0].index -> Some prize let s1Result = compare indices.[0] results.[0].index
| _ -> None) let s2Result = compare indices.[1] results.[1].index
let s3Result = compare indices.[2] results.[2].index
if s1Result && s2Result && s3Result
then Some prize
else None)
let prize = getPrize results
let builder = DiscordFollowupMessageBuilder() let builder = DiscordFollowupMessageBuilder()
builder.IsEphemeral <- true builder.IsEphemeral <- true
let itx = ctx.GetInteraction() let itx = ctx.GetInteraction()
let! followUpMessage , slotsContent = spinEmojis builder symbols itx let! followUpMessage , slotsContent = spinEmojis builder results itx
do! Async.Sleep 2000 do! Async.Sleep 2000
let embed = DiscordEmbedBuilder() let embed = DiscordEmbedBuilder()
@ -342,6 +352,13 @@ let handleGuildDownloadCompleted (_ : DiscordClient) (event : GuildDownloadCompl
return () return ()
} :> Task } :> Task
let handleMessageCreated (_ : DiscordClient) (event : MessageCreateEventArgs) =
task {
if event.Channel.Id = GuildEnvironment.channelSlots && event.Author.Id <> GuildEnvironment.botClientSlots.Value.CurrentUser.Id then
do! Async.Sleep 1000
do! event.Message.DeleteAsync()
} :> Task
let sendInitialEmbed (ctx : IDiscordContext) = let sendInitialEmbed (ctx : IDiscordContext) =
let updateFn (ctx : IDiscordContext) (message : DiscordMessage option) = async { let updateFn (ctx : IDiscordContext) (message : DiscordMessage option) = async {
let channel = ctx.GetGuild().GetChannel(GuildEnvironment.channelSlots) let channel = ctx.GetGuild().GetChannel(GuildEnvironment.channelSlots)