152 lines
5.2 KiB
Forth

module Degenz.DbService
open System
open System.Collections.Generic
open MongoDB.Bson
open MongoDB.Bson.Serialization
open MongoDB.Driver
open Degenz.Types
[<CLIMutable>]
type AttackAction =
{ ActionId : int
Result : bool
Target : DiscordPlayer
Timestamp : DateTime }
[<CLIMutable>]
type DefenseAction =
{ ActionId : int
Timestamp : DateTime }
[<CLIMutable>]
type PlayerEntry =
{ DiscordId : uint64
Name : string
XP : int
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
XP = player.XP
Bank = int player.Bank
}
let tryWithDefault (bson : BsonDocument) field (defaultValue : 'a) (map : BsonValue -> 'a) =
let result , bval = bson.TryGetValue(field)
if result then map bval else defaultValue
let private mapBack (bson : BsonDocument) : PlayerData =
{ DiscordId = tryWithDefault bson "Player.DiscordId" 0uL (fun v -> v.AsInt64 |> uint64)
Name = tryWithDefault bson "Player.Name" "Empty" (fun v -> v.AsString)
Arsenal =
tryWithDefault bson "Inventory" [||] (fun v ->
v.AsBsonArray
|> Seq.map (fun (bv : BsonValue) -> bv.AsInt32)
|> Seq.map (fun w -> Armory.battleItems |> Array.find (fun w' -> w = w'.Id))
|> Seq.toArray)
Actions = tryWithDefault bson "Events" [||] (fun _ -> [||])
Traits = tryWithDefault bson "Traits" PlayerTraits.empty (fun _ -> PlayerTraits.empty)
Achievements = tryWithDefault bson "Achievements" [||] (fun _ -> [||])
XP = tryWithDefault bson "XP" 0 (fun _ -> 0)
Bank = tryWithDefault bson "Player.Bank" 0<GBT> (fun v -> v.AsInt32 * 1<GBT>)
}
let mongo = MongoClient(Environment.GetEnvironmentVariable("CONN_STRING"))
let db = mongo.GetDatabase("degenz")
let players = db.GetCollection<BsonDocument>("players")
let tryFindPlayer (id : uint64) =
async {
let filter = Builders<BsonDocument>.Filter.Eq("Player.DiscordId", id)
let! player = players.FindAsync<BsonDocument>(filter) |> Async.AwaitTask
match player.FirstOrDefault() with
| null -> return None
| p -> return p
.GetValue("Player")
.ToBsonDocument()
|> mapBack
|> Some
}
let updatePlayer (player : PlayerData) =
async {
let filter = Builders<BsonDocument>.Filter.Eq("Player.DiscordId", player.DiscordId)
let update = Builders<BsonDocument>.Update
.Set("Player", playerMap player)
.AddToSet("Traits", player.Traits)
.AddToSet("Events", player.Actions)
.AddToSet("Achievements", player.Achievements)
.AddToSet("Inventory", player.Arsenal)
return! players.UpdateOneAsync(filter, update) |> Async.AwaitTask |> Async.Ignore
}
let getAchievements (id : uint64) =
async {
let filter = Builders<BsonDocument>.Filter.Eq("Player.DiscordId", id)
try
let! player = players.FindAsync<BsonDocument>(filter) |> Async.AwaitTask
match player.FirstOrDefault() with
| null -> return None
| p -> return p
.GetValue("achievements")
.AsBsonArray
|> Seq.map (fun (bv : BsonValue) -> bv.AsString)
|> Some
with ex -> return None
}
let addAchievement (id : uint64) (achievement : string) =
async {
let filter = Builders<BsonDocument>.Filter.Eq("Player.DiscordId", id)
let update = Builders<BsonDocument>.Update.Push("Achievements", achievement)
return! players.UpdateOneAsync(filter, update) |> Async.AwaitTask |> Async.Ignore
}
let insertNewPlayer (player : PlayerData) =
async {
let dict = [
KeyValuePair("Player" , (playerMap player).ToBsonDocument() :> Object)
KeyValuePair("Events" , [||] :> Object)
KeyValuePair("Inventory" , [||] :> Object)
KeyValuePair("Traits" , PlayerTraits.empty.ToBsonDocument() :> Object)
KeyValuePair("XP" , 0 :> 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 getTopPlayers amount =
// async {
// return! players.FindAsync()
// }