236 lines
9.7 KiB
Forth
236 lines
9.7 KiB
Forth
module Degenz.DbService
|
|
|
|
open System
|
|
open Npgsql.FSharp
|
|
open Degenz
|
|
|
|
let connStr = GuildEnvironment.connectionString
|
|
|
|
type User = {
|
|
Name : string
|
|
DiscordId : uint64
|
|
Bank : int<GBT>
|
|
Inventory : int list
|
|
Strength : int
|
|
Focus : int
|
|
Charisma : int
|
|
Luck : int
|
|
}
|
|
|
|
let getPlayerEvents (did : uint64) =
|
|
connStr
|
|
|> Sql.connect
|
|
|> Sql.parameters [ "did", Sql.string (string did) ]
|
|
|> Sql.query """
|
|
WITH usr AS (SELECT id FROM "user" WHERE discord_id = @did)
|
|
SELECT event_type, success, is_instigator, item_id, cooldown, adversary_id, adversary_name, created_at
|
|
FROM player_event ,usr WHERE user_id = usr.id and created_at > NOW() at time zone 'utc' - INTERVAL '24 HOURS';
|
|
"""
|
|
|> Sql.executeAsync (fun read ->
|
|
match read.string "event_type" with
|
|
| "Hacking" ->
|
|
Hacking {
|
|
IsInstigator = read.bool "is_instigator"
|
|
Success = read.bool "success"
|
|
Adversary = { Id = read.string "adversary_id" |> uint64 ; Name = read.string "adversary_name" }
|
|
HackId = read.int "item_id"
|
|
}
|
|
| "Shielding" -> Shielding (read.int "item_id")
|
|
| "Stealing" -> Stealing ( read.bool "is_instigator" , { Id = read.string "adversary_id" |> uint64 ; Name = read.string "adversary_name" } )
|
|
| _ -> Imprison
|
|
|> fun t ->
|
|
let date = read.dateTimeOrNone "created_at" |> Option.defaultValue DateTime.UtcNow
|
|
{ Type = t ; Cooldown = read.int "cooldown" * 1<mins> ; Timestamp = date }
|
|
)
|
|
|> Async.AwaitTask
|
|
|
|
let updatePlayerStats (player : PlayerData) =
|
|
connStr
|
|
|> Sql.connect
|
|
|> Sql.parameters
|
|
[ ( "did" , Sql.string (string player.DiscordId) )
|
|
( "strength", Sql.int player.Stats.Strength.Amount )
|
|
( "focus", Sql.int player.Stats.Focus.Amount )
|
|
( "charisma", Sql.int player.Stats.Charisma.Amount )
|
|
( "luck", Sql.int player.Stats.Luck.Amount ) ]
|
|
|> Sql.query """
|
|
WITH usr AS (SELECT id FROM "user" WHERE discord_id = @did)
|
|
UPDATE player_stat SET strength = @strength, focus = @focus, charisma = @charisma, luck = @luck,
|
|
updated_at = now() at time zone 'utc'
|
|
FROM usr WHERE usr.id = user_id;
|
|
"""
|
|
|> Sql.executeNonQueryAsync
|
|
|> Async.AwaitTask
|
|
|
|
let tryFindPlayer (discordId : uint64) = async {
|
|
try
|
|
let! user =
|
|
// use cert = new X509Certificate2("~/Downloads/ca-certificate.crt")
|
|
// (Uri connStr)
|
|
// |> Sql.fromUriToConfig
|
|
// |> Sql.requireSslMode
|
|
// |> Sql.formatConnectionString
|
|
// |> Sql.clientCertificate cert
|
|
connStr
|
|
|> Sql.connect
|
|
|> Sql.parameters [ "did", Sql.string (string discordId) ]
|
|
|> Sql.query """
|
|
SELECT discord_id, display_name, gbt, inventory, strength, focus, charisma, luck FROM "user"
|
|
WHERE discord_id = @did
|
|
"""
|
|
|> Sql.executeAsync (fun read ->
|
|
let inv = read.intArray "inventory"
|
|
{
|
|
DiscordId = read.string "discord_id" |> uint64
|
|
Name = read.string "display_name"
|
|
Bank = read.int "gbt" * 1<GBT>
|
|
Inventory = inv |> Array.toList
|
|
Strength = read.int "strength"
|
|
Focus = read.int "focus"
|
|
Charisma = read.int "charisma"
|
|
Luck = read.int "luck"
|
|
})
|
|
|> Async.AwaitTask
|
|
match List.tryHead user with
|
|
| None -> return None
|
|
| Some u ->
|
|
let! events = getPlayerEvents u.DiscordId
|
|
let inventory = u.Inventory |> List.choose (fun id -> Armory.weapons |> List.tryFind (fun item -> item.Id = id))
|
|
let strength = PlayerStats.calculateActiveStat StatId.Strength u.Strength inventory
|
|
let focus = PlayerStats.calculateActiveStat StatId.Focus u.Focus inventory
|
|
let charisma = PlayerStats.calculateActiveStat StatId.Charisma u.Charisma inventory
|
|
let luck = PlayerStats.calculateActiveStat StatId.Luck u.Luck inventory
|
|
return Some
|
|
{ DiscordId = u.DiscordId
|
|
Name = u.Name
|
|
Inventory = inventory
|
|
Events = events
|
|
Stats = { Strength = strength ; Focus = focus ; Charisma = charisma ; Luck = luck }
|
|
Bank = u.Bank }
|
|
with e ->
|
|
printfn $"Got an error{e.Message}"
|
|
return None
|
|
}
|
|
|
|
let updatePlayer (player : PlayerData) =
|
|
connStr
|
|
|> Sql.connect
|
|
|> Sql.parameters [
|
|
"did", Sql.string (string player.DiscordId)
|
|
"gbt", Sql.int (int player.Bank)
|
|
"inv", Sql.intArray (player.Inventory |> Array.ofList |> Array.map (fun item -> item.Id))
|
|
"strength", Sql.int player.Stats.Strength.Amount
|
|
"focus", Sql.int player.Stats.Focus.Amount
|
|
"charisma", Sql.int player.Stats.Charisma.Amount
|
|
"luck", Sql.int player.Stats.Luck.Amount
|
|
] |> Sql.query """
|
|
UPDATE "user" SET gbt = @gbt, inventory = @inv,
|
|
strength = @strength, focus = @focus, charisma = @charisma, luck = @luck
|
|
WHERE discord_id = @did
|
|
"""
|
|
|> Sql.executeNonQueryAsync
|
|
|> Async.AwaitTask
|
|
|
|
let addAchievement (did : uint64) (achievement : string) =
|
|
connStr
|
|
|> Sql.connect
|
|
|> Sql.parameters
|
|
[ ( "did" , Sql.string (string did) )
|
|
( "symbol", Sql.string achievement ) ]
|
|
|> Sql.query """
|
|
WITH ach AS (SELECT id FROM achievement WHERE symbol = cast(@symbol AS achievement_symbol_enum)),
|
|
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.executeNonQueryAsync
|
|
|> Async.AwaitTask
|
|
|
|
let checkHasAchievement (did : uint64) (achievement : string) = async {
|
|
let! result =
|
|
connStr
|
|
|> Sql.connect
|
|
|> Sql.parameters
|
|
[ ( "did" , Sql.string (string did) )
|
|
( "symbol", Sql.string achievement ) ]
|
|
|> Sql.query """
|
|
WITH ach AS (SELECT id FROM achievement WHERE symbol = cast(@symbol AS achievement_symbol_enum)),
|
|
usr AS (SELECT id FROM "user" WHERE discord_id = @did)
|
|
SELECT achievement_id FROM user_achievements_achievement, ach, usr WHERE user_id = usr.id and achievement_id = ach.id;
|
|
"""
|
|
|> Sql.executeAsync (fun read -> read.int "achievement_id")
|
|
|> Async.AwaitTask
|
|
return List.isEmpty result |> not
|
|
}
|
|
|
|
let removeShieldEvent (did : uint64) shieldId =
|
|
connStr
|
|
|> Sql.connect
|
|
|> Sql.parameters
|
|
[ ( "did" , Sql.string (string did) )
|
|
( "shield_id", Sql.int shieldId ) ]
|
|
|> Sql.query """
|
|
WITH usr AS (SELECT id FROM "user" WHERE discord_id = @did)
|
|
DELETE FROM player_event USING usr WHERE user_id = usr.id and event_type = 'Shielding' and item_id = @shield_id
|
|
"""
|
|
|> Sql.executeNonQueryAsync
|
|
|> Async.AwaitTask
|
|
|
|
let addPlayerEvent (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 'Imprison', @cooldown, usr.id FROM usr
|
|
"""
|
|
connStr
|
|
|> Sql.connect
|
|
|> Sql.parameters sqlParams
|
|
|> Sql.query query
|
|
|> Sql.executeNonQueryAsync
|
|
|> Async.AwaitTask
|