module Degenz.DbService open System open System.Collections.Generic open System.Threading.Tasks open Degenz.Types open MongoDB.Bson open MongoDB.Bson.Serialization open MongoDB.Driver [] type AttackAction = { ActionId : int Result : bool Target : DiscordPlayer Timestamp : DateTime } [] type DefenseAction = { ActionId : int Timestamp : DateTime } [] type PlayerEntry = { DiscordId : uint64 Name : string Arsenal : int array Attacks : AttackAction array Defenses : DefenseAction array Bank : int } let private actionToAttack (action : Action) (hack : AttackResult) = { ActionId = action.ActionId Result = hack.Result Target = hack.Target Timestamp = action.Timestamp } let private actionToDefense (action : Action) = { ActionId = action.ActionId Timestamp = action.Timestamp } let private attackToAction (attack : AttackAction) = { ActionId = attack.ActionId Type = Attack { Target = attack.Target ; Result = attack.Result } Timestamp = attack.Timestamp } let private defenseToAction (action : DefenseAction) = { ActionId = action.ActionId Type = Defense Timestamp = action.Timestamp } let private playerMap (player : PlayerData) = { DiscordId = player.DiscordId Name = player.Name Arsenal = player.Arsenal |> Array.map (fun w -> w.Id) Attacks = player.Actions |> Array.choose (fun a -> match a.Type with Attack ar -> Some (actionToAttack a ar) | _ -> None) Defenses = player.Actions |> Array.choose (fun a -> match a.Type with Defense -> Some (actionToDefense a) | _ -> None) Bank = int player.Bank } let private mapBack (player : PlayerEntry) : PlayerData = { DiscordId = player.DiscordId Name = player.Name Arsenal = player.Arsenal |> Array.map (fun w -> Armory.battleItems |> Array.find (fun w' -> w = w'.Id)) Actions = let atks = player.Attacks |> Array.map attackToAction let dfns = player.Defenses |> Array.map defenseToAction Array.append atks dfns Bank = player.Bank * 1 } let mongo = MongoClient(Environment.GetEnvironmentVariable("CONN_STRING")) let db = mongo.GetDatabase("degenz") let players = db.GetCollection("players") let tryFindPlayer (id : uint64) = async { let filter = Builders.Filter.Eq("Player.DiscordId", id) let! player = players.FindAsync(filter) |> Async.AwaitTask match player.FirstOrDefault() with | null -> return None | p -> return p .GetValue("Player") .ToBsonDocument() |> BsonSerializer.Deserialize |> mapBack |> Some } let insertNewPlayer (player : PlayerData) = async { let p = playerMap player let dict = [ KeyValuePair("Player" , p.ToBsonDocument() :> Object) ] do! BsonDocument(dict) |> players.InsertOneAsync |> Async.AwaitTask } //let deletePlayer (player : PlayerData) = // async { // let dict = [ KeyValuePair("Player" , player.ToBsonDocument() :> Object) ] // do! BsonDocument(dict) // |> players.InsertOneAsync // |> Async.AwaitTask // } // let updatePlayer (player : PlayerData) = async { let filter = Builders.Filter.Eq("Player.DiscordId", player.DiscordId) let update = Builders.Update.Set("Player", playerMap player) return! players.UpdateOneAsync(filter, update) |> Async.AwaitTask |> Async.Ignore } //let getTopPlayers amount = // async { // return! players.FindAsync() // }