Better semantics for MemberActivity
Some checks failed
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/push/all-checks-complete Pipeline was successful
ci/woodpecker/pr/build Pipeline failed
ci/woodpecker/pr/all-checks-complete unknown status

This commit is contained in:
Smaug123
2023-10-14 17:29:15 +01:00
parent 42eb1f7726
commit f5a6a6644c
5 changed files with 80 additions and 24 deletions

View File

@@ -5,24 +5,45 @@ open System
open PureGym
type GetTokenArg =
| [<ExactlyOnce>] User_Email of string
| [<ExactlyOnce>] Pin of string
| [<Unique ; EqualsAssignmentOrSpaced>] User_Email of string
| [<Unique ; EqualsAssignmentOrSpaced>] Pin of string
| [<Unique>] StdIn
interface IArgParserTemplate with
member s.Usage =
match s with
| GetTokenArg.Pin _ -> "Eight-digit PureGym user's PIN"
| GetTokenArg.User_Email _ -> "PureGym user's email address"
| GetTokenArg.StdIn _ -> "Read anything not specified on the command line from stdin"
static member Parse (args : ParseResults<GetTokenArg>) : Result<UsernamePin, ArguParseException> =
try
{
Username = args.GetResult GetTokenArg.User_Email
Pin = args.GetResult GetTokenArg.Pin
}
|> Ok
with :? ArguParseException as e ->
Error e
let canUseStdin = args.TryGetResult(GetTokenArg.StdIn).IsSome
let username =
match args.TryGetResult GetTokenArg.User_Email, canUseStdin with
| None, true ->
Console.Error.Write "Enter username: "
Console.ReadLine ()
| None, false ->
// TODO: proper exception handling, this should be surfaced through the Error
failwith "You must supply --user-email or --stdin"
| Some s, _ -> s
let pin =
match args.TryGetResult GetTokenArg.Pin, canUseStdin with
| None, true ->
Console.Error.Write "Enter eight-digit PIN: "
Console.ReadLine ()
| None, false ->
// TODO: proper exception handling, this should be surfaced through the Error
failwith "You must supply --pin or --stdin"
| Some s, _ -> s
{
Username = username
Pin = pin
}
|> Ok
[<RequireQualifiedAccess>]
module Authenticate =

View File

@@ -4,9 +4,9 @@ open Argu
open PureGym
type FullnessArgsFragment =
| [<Unique>] Gym_Id of int
| [<Unique>] Gym_Name of string
| [<Unique>] Terse of bool
| [<Unique ; EqualsAssignmentOrSpaced>] Gym_Id of int
| [<Unique ; EqualsAssignmentOrSpaced>] Gym_Name of string
| [<Unique ; EqualsAssignmentOrSpaced>] Terse of bool
interface IArgParserTemplate with
member s.Usage =

View File

@@ -4,8 +4,8 @@ open Argu
open PureGym
type LookupGymArgsFragment =
| [<Unique>] Gym_Id of int
| [<Unique>] Gym_Name of string
| [<Unique ; EqualsAssignmentOrSpaced>] Gym_Id of int
| [<Unique ; EqualsAssignmentOrSpaced>] Gym_Name of string
interface IArgParserTemplate with
member s.Usage =

View File

@@ -33,6 +33,7 @@ module MemberActivity =
task {
let! client = Api.make args.Creds
let! activity = client.GetMemberActivity ()
System.Console.WriteLine (string<MemberActivity> activity)
let activity = activity.ToMemberActivity ()
System.Console.WriteLine (string<MemberActivityThisMonth> activity)
return 0
}

View File

@@ -168,6 +168,7 @@ type Member =
/// Statistics for how many people are currently at a gym
type GymAttendance =
{
/// This appears always to be just equal to TotalPeopleInGym, but a string.
[<JsonRequired>]
Description : string
/// How many people are in the gym as of this statistics snapshot
@@ -207,25 +208,55 @@ type GymAttendance =
$"\n%i{this.TotalPeopleInClasses} in classes"
$"""%i{this.TotalPeopleInGym} in gym%s{capacity} (is exact: %c{Char.emoji (not this.IsApproximate)})%s{classes}
Query made at %s{this.AttendanceTime.ToString ("s")}%s{this.AttendanceTime.ToString ("zzz")}
Snapshot correct as of %s{this.LastRefreshed.ToString ("s")}%s{this.LastRefreshed.ToString ("zzz")}
Classes info correct as of %s{this.LastRefreshedPeopleInClasses.ToString ("s")}%s{this.LastRefreshedPeopleInClasses.ToString ("zzz")}"""
Query made at %s{this.AttendanceTime.ToString "s"}%s{this.AttendanceTime.ToString "zzz"}
Snapshot correct as of %s{this.LastRefreshed.ToString "s"}%s{this.LastRefreshed.ToString "zzz"}
Classes info correct as of %s{this.LastRefreshedPeopleInClasses.ToString "s"}%s{this.LastRefreshedPeopleInClasses.ToString "zzz"}"""
/// The visit statistics for a particular human to a particular gym.
/// The semantics of this class are basically unknown.
type MemberActivity =
type MemberActivityThisMonth =
{
/// ??? semantics unknown; this was 2852 for me
[<JsonPropertyName "totalDuration">]
/// How many minutes, including classes, have been logged so far this month
TotalDurationMinutes : int
[<JsonPropertyName "averageDuration">]
/// How long, in minutes, each visit has been on average this month
AverageDurationMinutes : int
/// How many visits have been made this month, excluding classes
TotalVisits : int
/// How many classes have been attended this month
TotalClasses : int
/// Whether this block of statistics is estimated rather than exact
IsEstimated : bool
/// When this data was constructed
LastRefreshed : DateTime
}
/// Don't use this type. It's public because System.Text.Json can't do private types.
type MemberActivityDto =
{
[<JsonRequired>]
TotalDuration : int
[<JsonRequired>]
AverageDuration : int
[<JsonRequired>]
TotalVisits : int
[<JsonRequired>]
TotalClasses : int
[<JsonRequired>]
IsEstimated : bool
[<JsonRequired>]
LastRefreshed : DateTime
}
member this.ToMemberActivity () =
{
TotalDurationMinutes = this.TotalDuration
AverageDurationMinutes = this.AverageDuration
TotalVisits = this.TotalVisits
TotalClasses = this.TotalClasses
IsEstimated = this.IsEstimated
LastRefreshed = this.LastRefreshed
}
/// The PureGym REST API. You probably want to instantiate one of these with `Api.make`.
[<Header("User-Agent", "PureGym/1523 CFNetwork/1312 Darwin/21.0.0")>]
type IPureGymApi =
@@ -247,7 +278,10 @@ type IPureGymApi =
/// Get information about the activities logged against the currently authenticated PureGym human.
[<Get "v1/member/activity">]
abstract GetMemberActivity : unit -> Task<MemberActivity>
abstract GetMemberActivity : unit -> Task<MemberActivityDto>
// [<Get "v1/member/activity/history">]
// abstract GetMemberActivityAll : unit -> Task<string>
/// Methods for interacting with the PureGym REST API.
[<RequireQualifiedAccess>]