diff --git a/Bot/Analytics.fs b/Bot/Analytics.fs index 932122d..ebd95de 100644 --- a/Bot/Analytics.fs +++ b/Bot/Analytics.fs @@ -155,13 +155,13 @@ let prizeTableViewed (discordMember : DiscordMember) = let data = [ "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 data = [ "user_display_name" , discordMember.Username "play_amount" , string amount - "result" , string result - "prize" , string result + "result" , result + "prize" , string prize ] - track "Shield Button Clicked" discordMember.Id data + track "Slots Played" discordMember.Id data diff --git a/Bot/Bot.fs b/Bot/Bot.fs index 4f0e06c..69cde6c 100644 --- a/Bot/Bot.fs +++ b/Bot/Bot.fs @@ -76,6 +76,7 @@ inviterBot.add_GuildMemberAdded(AsyncEventHandler(InviteTracker.handleGuildMembe inviterBot.add_ComponentInteractionCreated(AsyncEventHandler(InviteTracker.handleButtonEvent)) slotsBot.add_ComponentInteractionCreated(AsyncEventHandler(SlotMachine.handleButton)) slotsBot.add_GuildDownloadCompleted(AsyncEventHandler(SlotMachine.handleGuildDownloadCompleted)) +slotsBot.add_MessageCreated(AsyncEventHandler(SlotMachine.handleMessageCreated)) adminBot.add_GuildDownloadCompleted(AsyncEventHandler(Admin.handleGuildDownloadReady)) let asdf (_ : DiscordClient) (event : DSharpPlus.EventArgs.InteractionCreateEventArgs) = diff --git a/Bot/Games/SlotMachine.fs b/Bot/Games/SlotMachine.fs index ed8a37e..4cf50e7 100644 --- a/Bot/Games/SlotMachine.fs +++ b/Bot/Games/SlotMachine.fs @@ -18,24 +18,6 @@ type SlotSymbol = { 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 = | Money of int | Jackpot @@ -44,51 +26,79 @@ type Slot = | Symbol of SlotSymbol | 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 = [| Symbol BigBrother , Symbol BigBrother , Symbol BigBrother , Jackpot Symbol Eye , Symbol Eye , Symbol Eye , Money 500 + Symbol Eye , Symbol Eye , Symbol AnonMask , Money 500 Symbol AnonMask , Symbol AnonMask , Symbol AnonMask , Money 250 - Symbol Obey , Symbol Obey , Symbol Obey , Money 200 + Symbol Obey , Symbol Obey , Symbol Obey , Money 250 + Symbol Obey , Symbol Obey , Symbol AnonMask , Money 200 + Symbol Sushi , Symbol Sushi , Symbol Sushi , Money 200 Symbol Ramen , Symbol Ramen , Symbol Ramen , Money 150 - Symbol Alcohol , Symbol Alcohol , Symbol Alcohol , Money 100 - Symbol OldTv , Symbol OldTv , Symbol OldTv , Money 100 - Symbol Pills , Symbol Pills , Symbol Pills , Money 100 +// Symbol Alcohol , Symbol Alcohol , Symbol Alcohol , Money 100 +// Symbol OldTv , Symbol OldTv , Symbol OldTv , Money 100 +// Symbol Pills , Symbol Pills , Symbol Pills , Money 100 Symbol Rat , Symbol Rat , Symbol Rat , Money 100 Symbol Sushi , Symbol Sushi , Any , Money 50 - Symbol Pizza , Any , Any , Money 20 |] + Any , Any , Symbol Pizza , Money 20 |] -let totalPerReel (reel : SlotSymbol -> int) = List.sumBy reel symbols -let calculateOdds prizeIndex = - 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 calculateOdds (prizeTable : PrizeEntry array) prizeIndex = + 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 getTotalCombinations () = +let getTotalCombinations symbols = (List.sumBy (fun s -> s.reel1Count) symbols) * (List.sumBy (fun s -> s.reel2Count) symbols) * (List.sumBy (fun s -> s.reel3Count) symbols) -let getOddsForPrize prizeIndex = - let odds = calculateOdds prizeIndex - let total = getTotalCombinations () +let getOddsForPrize symbols prizeTable prizeIndex = + let odds = calculateOdds prizeTable prizeIndex + let total = getTotalCombinations symbols $"{odds} in {total }" -// getOddsForPrize 0 -// getOddsForPrize 1 -// getOddsForPrize 5 -// getOddsForPrize 10 - -let getTotalWaysOfWinning () = +let getTotalWaysOfWinning (prizeTable : PrizeEntry array) = [0..prizeTable.Length - 1] - |> List.sumBy calculateOdds + |> List.sumBy (calculateOdds prizeTable) + +let printOddsTable symbols (prizeTable : PrizeEntry array) = + ([0..prizeTable.Length - 1] + |> 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 -//totalPerReel (fun s -> s.reel1Count) -//totalPerReel (fun s -> s.reel2Count) -//totalPerReel (fun s -> s.reel3Count) +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 reel2 = getReel (fun s -> s.reel2Count) let reel3 = getReel (fun s -> s.reel3Count) @@ -168,29 +178,23 @@ let handlePrizeTable (ctx : IDiscordContext) = let embed = DiscordEmbedBuilder() match guildEmojis , anyEmoji with | Some emojis , Some any -> - let folder (i,acc,b) elem = + let folder (i,acc) elem = let s1,s2,s3,prize = elem let prizeTxt = match prize with Money m -> $"**{m}** $GBT" | Jackpot -> $"**JACKPOT**" let line = - match s1 , s2 , s3 with - | Symbol s1' , Symbol s2' , Symbol 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 getEmoji = function Symbol s -> Formatter.Emoji(emojis.[s.emojiName]) | Any -> Formatter.Emoji(any) + $"{getEmoji s1}{getEmoji s2}{getEmoji s3}" let text = if prizeTxt.Contains("100") then acc else $"{acc}\n{line} | {prizeTxt}" - (i + 1) , text , ( b || prizeTxt.Contains("100") ) + (i + 1) , text let! jackpot = getJackpotAmount () - let _ , rows , _ = Array.fold folder (0, "", false) prizeTable + let _ , rows = Array.fold folder (0, "") prizeTable embed.Color <- DiscordColor.Green 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! Analytics.prizeTableViewed (ctx.GetDiscordMember()) | _ , _ -> return () @@ -230,23 +234,29 @@ let spin multiplier (ctx : IDiscordContext) = | _ -> PlayPricex3 let execute player = async { do! DbService.updatePlayerCurrency -playAmount player |> Async.Ignore - let random = Random(Guid.NewGuid().GetHashCode()) - let symbols = [| reel1.[random.Next(0, reel1.Length)] ; reel2.[random.Next(0, reel2.Length)] ; reel3.[random.Next(0, reel3.Length)] |] + let random = System.Random(System.Guid.NewGuid().GetHashCode()) + 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 |> Array.tryPick (fun (s1,s2,s3,prize) -> - match s1 , s2 , s3 with - | Symbol s1' , Symbol s2' , Symbol s3' when s1'.index = symbols.[0].index && s2'.index = symbols.[1].index && s3'.index = symbols.[2].index -> Some prize - | Symbol s1' , Symbol s2' , Any when s1'.index = symbols.[0].index && s2'.index = symbols.[1].index -> Some prize - | Symbol s1' , Any , Any when s1'.index = symbols.[0].index -> Some prize - | _ -> None) + let getIndex = function Symbol s -> s.index | Any -> -1 + let indices = [ s1 ; s2 ; s3 ] |> List.map getIndex + let compare i1 i2 = i1 = i2 || i1 = -1 + let s1Result = compare indices.[0] results.[0].index + 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() builder.IsEphemeral <- true let itx = ctx.GetInteraction() - let! followUpMessage , slotsContent = spinEmojis builder symbols itx + let! followUpMessage , slotsContent = spinEmojis builder results itx do! Async.Sleep 2000 let embed = DiscordEmbedBuilder() @@ -342,6 +352,13 @@ let handleGuildDownloadCompleted (_ : DiscordClient) (event : GuildDownloadCompl return () } :> 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 updateFn (ctx : IDiscordContext) (message : DiscordMessage option) = async { let channel = ctx.GetGuild().GetChannel(GuildEnvironment.channelSlots)