From fc56b4a64bf9adbda82a358f6fa354766aa63524 Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Tue, 22 Feb 2022 13:06:22 +0700 Subject: [PATCH] updatePlayer, achievements, and find player queries --- Bot/HackerBattle.fs | 10 +++-- Bot/PlayerInteractions.fs | 2 +- Bot/SlotMachine.fs | 6 ++- Bot/Store.fs | 6 ++- Bot/Thief.fs | 9 ++-- Bot/Trainer.fs | 6 ++- DbService/DbService.fs | 93 +++++++++++++++++++-------------------- 7 files changed, 70 insertions(+), 62 deletions(-) diff --git a/Bot/HackerBattle.fs b/Bot/HackerBattle.fs index 97b51fa..7eb4ea0 100644 --- a/Bot/HackerBattle.fs +++ b/Bot/HackerBattle.fs @@ -82,8 +82,8 @@ let updateCombatants successfulHack (attacker : PlayerData) (defender : PlayerDa | false , false -> PlayerEventResult.Negative } - [ DbService.updatePlayer <| updatePlayer prize (event false) attacker - DbService.updatePlayer <| updatePlayer -prize (event true) defender ] + [ DbService.updatePlayer GuildEnvironment.pgDb <| updatePlayer prize (event false) attacker + DbService.updatePlayer GuildEnvironment.pgDb <| updatePlayer -prize (event true) defender ] |> Async.Parallel |> Async.Ignore @@ -190,7 +190,8 @@ let handleDefense (ctx : IDiscordContext) = IsInstigator = true Adversary = DiscordPlayer.empty } - do! DbService.updatePlayer <| { p with Events = Array.append [| defense |] p.Events } + do! DbService.updatePlayer GuildEnvironment.pgDb <| { p with Events = Array.append [| defense |] p.Events } + |> Async.Ignore let builder = DiscordMessageBuilder() builder.WithContent($"{ctx.GetDiscordMember().Username} has protected their system!") |> ignore let channel = ctx.GetGuild().GetChannel(GuildEnvironment.channelEventsHackerBattle) @@ -209,7 +210,8 @@ let arsenal (ctx : IDiscordContext) = builder.AddEmbed(embed) |> ignore builder.IsEphemeral <- true do! ctx.FollowUp(builder) |> Async.AwaitTask - do! DbService.updatePlayer updatedPlayer + do! DbService.updatePlayer GuildEnvironment.pgDb updatedPlayer + |> Async.Ignore }) let handleButtonEvent (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) = diff --git a/Bot/PlayerInteractions.fs b/Bot/PlayerInteractions.fs index 29f763f..817006c 100644 --- a/Bot/PlayerInteractions.fs +++ b/Bot/PlayerInteractions.fs @@ -29,7 +29,7 @@ module Commands = | Some _ -> async.Return false | None -> async { - do! newPlayer "" discordId |> DbService.insertNewPlayer +// do! newPlayer "" discordId |> DbService.insertNewPlayer return true } return newPlayer diff --git a/Bot/SlotMachine.fs b/Bot/SlotMachine.fs index 456db2d..5c1a2be 100644 --- a/Bot/SlotMachine.fs +++ b/Bot/SlotMachine.fs @@ -24,9 +24,11 @@ type SlotMachine() = || (results.[0] <> results.[1] && results.[1] <> results.[2] && results.[0] <> results.[2]) if winConditions then - do! DbService.updatePlayer { player with Bank = player.Bank + 10 } + do! DbService.updatePlayer GuildEnvironment.pgDb { player with Bank = player.Bank + 10 } + |> Async.Ignore else - do! DbService.updatePlayer { player with Bank = max (player.Bank - 1) 0 } + do! DbService.updatePlayer GuildEnvironment.pgDb { player with Bank = max (player.Bank - 1) 0 } + |> Async.Ignore do! ctx.Interaction.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource) diff --git a/Bot/Store.fs b/Bot/Store.fs index aa2e731..6449de9 100644 --- a/Bot/Store.fs +++ b/Bot/Store.fs @@ -52,7 +52,8 @@ let handleBuyItem (ctx : IDiscordContext) itemId = |> handleResultWithResponse ctx (fun player -> async { let newBalance = player.Bank - item.Price let p = { player with Bank = newBalance ; Inventory = Array.append [| item |] player.Inventory } - do! DbService.updatePlayer p + do! DbService.updatePlayer GuildEnvironment.pgDb p + |> Async.Ignore do! sendFollowUpMessage ctx $"Successfully purchased {item.Name}! You now have {newBalance} 💰$GBT remaining" }) }) @@ -72,7 +73,8 @@ let handleSell (ctx : IDiscordContext) itemId = then player.Events |> Array.filter (fun a -> a.ItemId <> itemId) else player.Events } - do! DbService.updatePlayer updatedPlayer + do! DbService.updatePlayer GuildEnvironment.pgDb updatedPlayer + |> Async.Ignore do! sendFollowUpMessage ctx $"Sold {item.Type} {item.Name} for {item.Price}! Current Balance: {updatedPlayer.Bank}" }) }) diff --git a/Bot/Thief.fs b/Bot/Thief.fs index 4a5bf7e..87018b7 100644 --- a/Bot/Thief.fs +++ b/Bot/Thief.fs @@ -176,7 +176,8 @@ let handleSteal (ctx : IDiscordContext) = Cooldown = VictimRecovery.Minutes * 1 } let actions = t |> Player.removeExpiredActions |> fun p -> Array.append [| mugged |] p.Events - do! DbService.updatePlayer { t with Bank = max (t.Bank - prize) 0 ; Events = actions } + do! DbService.updatePlayer GuildEnvironment.pgDb { t with Bank = max (t.Bank - prize) 0 ; Events = actions } + |> Async.Ignore | None -> () let stole = { @@ -189,10 +190,12 @@ let handleSteal (ctx : IDiscordContext) = Cooldown = ThiefCooldown.Minutes * 1 } let actions = thief |> Player.removeExpiredActions |> fun p -> Array.append [| stole |] p.Events - do! DbService.updatePlayer { thief with Bank = thief.Bank + prize ; Events = actions } + do! DbService.updatePlayer GuildEnvironment.pgDb { thief with Bank = thief.Bank + prize ; Events = actions } + |> Async.Ignore | false -> let embed = getResultEmbed' WentToPrison - do! DbService.updatePlayer { thief with Events = Array.append [| stealAction PlayerEventResult.Neutral |] thief.Events } + do! DbService.updatePlayer GuildEnvironment.pgDb { thief with Events = Array.append [| stealAction PlayerEventResult.Neutral |] thief.Events } + |> Async.Ignore do! Messaging.sendFollowUpEmbed ctx (embed.Build()) do! Async.Sleep 2000 let role = ctx.GetGuild().GetRole(GuildEnvironment.rolePrisoner) diff --git a/Bot/Trainer.fs b/Bot/Trainer.fs index a07fc8b..b45693a 100644 --- a/Bot/Trainer.fs +++ b/Bot/Trainer.fs @@ -152,7 +152,8 @@ let handleHack (ctx : IDiscordContext) = // let isFirstTrainer = player.Achievements |> Seq.contains trainerAchievement |> not let isFirstTrainer = true if isFirstTrainer then - do! DbService.addAchievement player.DiscordId trainerAchievement + do! DbService.addAchievement GuildEnvironment.pgDb player.DiscordId trainerAchievement + |> Async.Ignore sb.Append($"I'm going to gift you a hack,`{defaultHack.Name}` and a shield, `{defaultShield.Name}`") |> ignore sb.Append(", you'll need em to survive\n\n") |> ignore @@ -179,7 +180,8 @@ let handleArsenal (ctx : IDiscordContext) = else Player.removeExpiredActions player if not hasStockWeapons then - do! DbService.updatePlayer updatedPlayer + do! DbService.updatePlayer GuildEnvironment.pgDb updatedPlayer + |> Async.Ignore let embed = Embeds.getArsenalEmbed updatedPlayer do! ctx.FollowUp(embed) |> Async.AwaitTask // TODO DB: diff --git a/DbService/DbService.fs b/DbService/DbService.fs index 3c2a800..e1dbc2e 100644 --- a/DbService/DbService.fs +++ b/DbService/DbService.fs @@ -3,9 +3,8 @@ open Degenz.Types open System -open MongoDB.Bson -open MongoDB.Bson.Serialization -open MongoDB.Driver +//open MongoDB.Bson +//open MongoDB.Driver open Npgsql.FSharp type User = { @@ -16,17 +15,7 @@ type User = { Inventory : int array } -let mongo = MongoClient(Environment.GetEnvironmentVariable("CONN_STRING")) -let db = mongo.GetDatabase("degenz") -let players = db.GetCollection("players") - -let tryWithDefault (bson : BsonDocument) field (defaultValue : 'a) (map : BsonValue -> 'a) = - try - let result , bval = bson.TryGetValue(field) - if result then map bval else defaultValue - with _ -> defaultValue - -let mapBack user (bson : BsonDocument) : PlayerData = +let mapBack user : PlayerData = { DiscordId = user.DiscordId Name = user.Name Inventory = @@ -38,11 +27,7 @@ let mapBack user (bson : BsonDocument) : PlayerData = | Some i -> [| i |] | None -> [||]) |> Array.concat - Events = tryWithDefault bson "Events" [||] (fun v -> - v.AsBsonArray - |> Seq.map (fun (bv : BsonValue) -> - BsonSerializer.Deserialize(bv.ToBsonDocument())) - |> Seq.toArray) + Events = [||] Traits = { PlayerTraits.empty with Strength = user.Strength } // Achievements = // tryWithDefault bson "Achievements" [||] (fun v -> @@ -53,47 +38,59 @@ let mapBack user (bson : BsonDocument) : PlayerData = let tryFindPlayer connStr (id : uint64) = async { - let filter = Builders.Filter.Eq("Player.DiscordId", id) - let! player = players.FindAsync(filter) |> Async.AwaitTask let! user = connStr |> Sql.connect - |> Sql.query "SELECT * FROM users WHERE discordId = @did" - |> Sql.parameters [ "did", Sql.int64 (int64 id) ] + |> Sql.query "SELECT * FROM users WHERE discord_id = @did" + |> Sql.parameters [ "did", Sql.string (string id) ] |> Sql.executeAsync (fun read -> { - DiscordId = read.int64 "discordId" |> uint64 - Name = read.string "displayName" + DiscordId = read.string "discord_id" |> uint64 + Name = read.string "display_name" Bank = read.int "gbt" * 1 Strength = read.int "strength" Inventory = read.intArray "inventory" }) |> Async.AwaitTask - match player.FirstOrDefault() , List.tryHead user with - | null , _ - | _ , None -> return None - | p , Some u -> - let v = p.GetValue("Player") - let playerData = mapBack u (v.ToBsonDocument()) - return Some playerData + match List.tryHead user with + | None -> return None + | Some u -> return Some (mapBack u) } -let insertNewPlayer (player : PlayerData) = - async { - do! BsonDocument("Player", player.ToBsonDocument()) |> players.InsertOneAsync |> Async.AwaitTask - } +//let insertNewPlayer (player : PlayerData) = +// async { +// do! BsonDocument("Player", player.ToBsonDocument()) |> players.InsertOneAsync |> Async.AwaitTask +// } -let updatePlayer (player : PlayerData) = - async { - let filter = Builders.Filter.Eq("Player.DiscordId", player.DiscordId) - let update = Builders.Update.Set("Player", player.ToBsonDocument()) - do! players.UpdateOneAsync(filter, update) |> Async.AwaitTask |> Async.Ignore - } +let updatePlayer connStr (player : PlayerData) = + connStr + |> Sql.connect + |> Sql.query ("UPDATE users " + + "SET bank = @bank, strength = @str, inventory = @inv " + + "WHERE discordId = @did") + |> Sql.parameters [ + "did", Sql.string (string player.DiscordId) + "bank", Sql.int (int player.Bank) + "str", Sql.int (int player.Traits.Strength) + "inv", Sql.intArray (player.Inventory |> Array.map (fun i -> i.Id)) + ] + |> Sql.executeNonQueryAsync + |> Async.AwaitTask -let addAchievement (id : uint64) (achievement : string) = - async { - let filter = Builders.Filter.Eq("Player.DiscordId", id) - let update = Builders.Update.Push("Player.Achievements", achievement) - return! players.UpdateOneAsync(filter, update) |> Async.AwaitTask |> Async.Ignore - } \ No newline at end of file +//let addAchievement (id : uint64) (achievement : string) = +// async { +// let filter = Builders.Filter.Eq("Player.DiscordId", id) +// let update = Builders.Update.Push("Player.Achievements", achievement) +// return! players.UpdateOneAsync(filter, update) |> Async.AwaitTask |> Async.Ignore +// } + +let addAchievement connStr (did : uint64) (achievement : string) = + connStr + |> Sql.connect + |> Sql.query ("WITH ach_id AS (INSERT INTO achievement (symbol) VALUES (@symbol)), " + + " usr_id AS (SELECT id FROM user WHERE discord_id = @did" + + "INSERT INTO user_achievements_achievement (user_id, achievement_id) VALUES (usr_id, ach_id) ") + |> Sql.parameters [ ( "did" , Sql.string (string did) ) ; ( "achievement", Sql.string achievement ) ] + |> Sql.executeNonQueryAsync + |> Async.AwaitTask