module Degenz.DbService open Degenz.Types open System //open MongoDB.Bson //open MongoDB.Driver open Npgsql.FSharp type User = { Name : string DiscordId : uint64 Bank : int Strength : int Inventory : int array } let mapBack user : PlayerData = { DiscordId = user.DiscordId Name = user.Name Inventory = user.Inventory |> Array.choose (fun id -> Armory.battleItems |> Array.tryFind (fun i -> i.Id = id)) Events = [||] Traits = { PlayerTraits.empty with Strength = user.Strength } // Achievements = // tryWithDefault bson "Achievements" [||] (fun v -> // v.AsBsonArray |> Seq.map (fun (bv : BsonValue) -> bv.AsString) |> Seq.toArray) // XP = tryWithDefault bson "XP" 0 (fun v -> v.AsInt32) Bank = user.Bank } let tryFindPlayer connStr (discordId : uint64) = async { try let! user = connStr |> Sql.connect |> Sql.query """ SELECT discord_id, display_name, gbt, strength, inventory FROM "user" WHERE discord_id = @did") """ |> Sql.parameters [ "did", Sql.string (string discordId) ] |> Sql.executeAsync (fun read -> { 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 List.tryHead user with | None -> return None | Some u -> return Some (mapBack u) with e -> printfn $"{e.Message}" return None } let updatePlayer connStr (player : PlayerData) = connStr |> Sql.connect |> Sql.parameters [ "did", Sql.string (string player.DiscordId) "gbt", Sql.int (int player.Bank) "str", Sql.int (int player.Traits.Strength) "inv", Sql.intArray (player.Inventory |> Array.map (fun i -> i.Id)) ] |> Sql.query """ UPDATE "user" SET gbt = @gbt, strength = @str, inventory = @inv WHERE discord_id = @did") """ |> Sql.executeNonQueryAsync |> Async.AwaitTask let addAchievement connStr (did : uint64) (achievement : string) = connStr |> Sql.connect |> Sql.query """ WITH ach AS (INSERT INTO achievement (symbol) VALUES (@symbol) RETURNING id), usr AS (SELECT id FROM "user" WHERE discord_id = @did) INSERT INTO user_achievements_achievement (user_id, achievement_id) SELECT usr.id, ach.id FROM usr, ach") """ |> Sql.parameters [ ( "did" , Sql.string (string did) ) ; ( "achievement", Sql.string achievement ) ] |> Sql.executeNonQueryAsync |> Async.AwaitTask let addPlayerEvent connStr (did : uint64) (playerEvent : PlayerEvent) = let sqlParams , query = match playerEvent.Type with | Hacking h -> [ ( "did", Sql.string (string did) ) ( "success" , Sql.bool h.Success ) ( "is_instigator", Sql.bool h.IsInstigator ) ( "item_id", Sql.int h.HackId ) ( "cooldown", Sql.int (int playerEvent.Cooldown) ) ( "adversary_id", Sql.string (string h.Adversary.Id) ) ( "adversary_name", Sql.string (string h.Adversary.Name) ) ] , """ WITH usr AS (SELECT id FROM "user" WHERE discord_id = @did) INSERT INTO player_event (event_type, success, is_instigator, item_id, cooldown, adversary_id, adversary_name, user_id) SELECT 'Hacking', @success, @is_instigator, @item_id, @cooldown, @adversary_id, @adversary_name, usr.id FROM usr """ | Shielding id -> [ ( "did" , Sql.string (string did) ) ( "item_id", Sql.int id ) ( "cooldown", Sql.int (int playerEvent.Cooldown) ) ] , """ WITH usr AS (SELECT id FROM "user" WHERE discord_id = @did) INSERT INTO player_event (event_type, item_id, cooldown, user_id) SELECT 'Shielding', @item_id, @cooldown, usr.id FROM usr """ | Stealing(instigator, victim) -> [ ( "did" , Sql.string (string did) ) ( "is_instigator", Sql.bool instigator ) ( "adversary_id", Sql.string (string victim.Id) ) ( "adversary_name", Sql.string (string victim.Name) ) ( "cooldown", Sql.int (int playerEvent.Cooldown) ) ] , """ WITH usr AS (SELECT id FROM "user" WHERE discord_id = @did) INSERT INTO player_event (event_type, is_instigator, adversary_id, adversary_name, cooldown, user_id) SELECT 'Stealing', @is_instigator, @adversary_id, @adversary_name, @cooldown, usr.id FROM usr """ | Imprison -> [ ( "did" , Sql.string (string did) ) ( "cooldown", Sql.int (int playerEvent.Cooldown) ) ] , """ WITH usr AS (SELECT id FROM "user" WHERE discord_id = @did) INSERT INTO player_event (event_type, cooldown, user_id) SELECT 'Stealing', @cooldown, usr.id FROM usr """ connStr |> Sql.connect |> Sql.parameters sqlParams |> Sql.query query |> Sql.executeNonQueryAsync |> Async.AwaitTask