Compare commits
2 commits
27310bbb2f
...
d5e6cbc95f
Author | SHA1 | Date | |
---|---|---|---|
d5e6cbc95f | |||
616a4b5476 |
22 changed files with 308 additions and 107 deletions
|
@ -11,8 +11,8 @@ gleam_stdlib = ">= 0.60.0 and < 1.0.0"
|
||||||
gleam_json = ">= 3.0.1 and < 4.0.0"
|
gleam_json = ">= 3.0.1 and < 4.0.0"
|
||||||
gleam_http = ">= 4.0.0 and < 5.0.0"
|
gleam_http = ">= 4.0.0 and < 5.0.0"
|
||||||
gleam_httpc = ">= 4.1.1 and < 5.0.0"
|
gleam_httpc = ">= 4.1.1 and < 5.0.0"
|
||||||
birl = ">= 1.8.0 and < 2.0.0"
|
gleam_time = ">= 1.2.0 and < 2.0.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
gleeunit = ">= 1.5.1 and < 2.0.0"
|
gleeunit = ">= 1.5.1 and < 2.0.0"
|
||||||
dot_env = ">= 1.2.0 and < 2.0.0"
|
envoy = ">= 1.0.2 and < 2.0.0"
|
||||||
|
|
|
@ -2,26 +2,21 @@
|
||||||
# You typically do not need to edit this file
|
# You typically do not need to edit this file
|
||||||
|
|
||||||
packages = [
|
packages = [
|
||||||
{ name = "birl", version = "1.8.0", build_tools = ["gleam"], requirements = ["gleam_regexp", "gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "2AC7BA26F998E3DFADDB657148BD5DDFE966958AD4D6D6957DD0D22E5B56C400" },
|
{ name = "envoy", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "95FD059345AA982E89A0B6E2A3BF1CF43E17A7048DCD85B5B65D3B9E4E39D359" },
|
||||||
{ name = "dot_env", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "simplifile"], otp_app = "dot_env", source = "hex", outer_checksum = "F2B4815F1B5AF8F20A6EADBB393E715C4C35203EBD5BE8200F766EA83A0B18DE" },
|
|
||||||
{ name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" },
|
|
||||||
{ name = "gleam_erlang", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "7E6A5234F927C4B24F8054AB1E4572206C41F9E6D5C6C02273CB7531E7E5CED0" },
|
{ name = "gleam_erlang", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "7E6A5234F927C4B24F8054AB1E4572206C41F9E6D5C6C02273CB7531E7E5CED0" },
|
||||||
{ name = "gleam_http", version = "4.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "0A62451FC85B98062E0907659D92E6A89F5F3C0FBE4AB8046C99936BF6F91DBC" },
|
{ name = "gleam_http", version = "4.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "0A62451FC85B98062E0907659D92E6A89F5F3C0FBE4AB8046C99936BF6F91DBC" },
|
||||||
{ name = "gleam_httpc", version = "4.1.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gleam_httpc", source = "hex", outer_checksum = "C670EBD46FC1472AD5F1F74F1D3938D1D0AC1C7531895ED1D4DDCB6F07279F43" },
|
{ name = "gleam_httpc", version = "4.1.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gleam_httpc", source = "hex", outer_checksum = "C670EBD46FC1472AD5F1F74F1D3938D1D0AC1C7531895ED1D4DDCB6F07279F43" },
|
||||||
{ name = "gleam_json", version = "3.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "5BA154440B22D9800955B1AB854282FA37B97F30F409D76B0824D0A60C934188" },
|
{ name = "gleam_json", version = "3.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "5BA154440B22D9800955B1AB854282FA37B97F30F409D76B0824D0A60C934188" },
|
||||||
{ name = "gleam_regexp", version = "1.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "9C215C6CA84A5B35BB934A9B61A9A306EC743153BE2B0425A0D032E477B062A9" },
|
|
||||||
{ name = "gleam_stdlib", version = "0.60.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "621D600BB134BC239CB2537630899817B1A42E60A1D46C5E9F3FAE39F88C800B" },
|
{ name = "gleam_stdlib", version = "0.60.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "621D600BB134BC239CB2537630899817B1A42E60A1D46C5E9F3FAE39F88C800B" },
|
||||||
{ name = "gleam_yielder", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_yielder", source = "hex", outer_checksum = "8E4E4ECFA7982859F430C57F549200C7749823C106759F4A19A78AEA6687717A" },
|
{ name = "gleam_time", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_time", source = "hex", outer_checksum = "D71F1AFF7FEB534FF55E5DC58E534E9201BA75A444619788A2E4DEA4EBD87D16" },
|
||||||
{ name = "gleeunit", version = "1.5.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "D33B7736CF0766ED3065F64A1EBB351E72B2E8DE39BAFC8ADA0E35E92A6A934F" },
|
{ name = "gleeunit", version = "1.5.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "D33B7736CF0766ED3065F64A1EBB351E72B2E8DE39BAFC8ADA0E35E92A6A934F" },
|
||||||
{ name = "ranger", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_yielder"], otp_app = "ranger", source = "hex", outer_checksum = "C8988E8F8CDBD3E7F4D8F2E663EF76490390899C2B2885A6432E942495B3E854" },
|
|
||||||
{ name = "simplifile", version = "2.2.1", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "C88E0EE2D509F6D86EB55161D631657675AA7684DAB83822F7E59EB93D9A60E3" },
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[requirements]
|
[requirements]
|
||||||
birl = { version = ">= 1.8.0 and < 2.0.0" }
|
envoy = { version = ">= 1.0.2 and < 2.0.0" }
|
||||||
dot_env = { version = ">= 1.2.0 and < 2.0.0" }
|
|
||||||
gleam_http = { version = ">= 4.0.0 and < 5.0.0" }
|
gleam_http = { version = ">= 4.0.0 and < 5.0.0" }
|
||||||
gleam_httpc = { version = ">= 4.1.1 and < 5.0.0" }
|
gleam_httpc = { version = ">= 4.1.1 and < 5.0.0" }
|
||||||
gleam_json = { version = ">= 3.0.1 and < 4.0.0" }
|
gleam_json = { version = ">= 3.0.1 and < 4.0.0" }
|
||||||
gleam_stdlib = { version = ">= 0.60.0 and < 1.0.0" }
|
gleam_stdlib = { version = ">= 0.60.0 and < 1.0.0" }
|
||||||
|
gleam_time = { version = ">= 1.2.0 and < 2.0.0" }
|
||||||
gleeunit = { version = ">= 1.5.1 and < 2.0.0" }
|
gleeunit = { version = ">= 1.5.1 and < 2.0.0" }
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/dict.{type Dict}
|
import gleam/dict.{type Dict}
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
import gleam/json
|
import gleam/json
|
||||||
import gleam/list
|
import gleam/list
|
||||||
import gleam/option.{type Option}
|
import gleam/option.{type Option}
|
||||||
|
import gleam/time/calendar.{type Date}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import gleam/uri.{type Uri}
|
import gleam/uri.{type Uri}
|
||||||
import spacetraders_models/account.{type Account}
|
import spacetraders_models/account.{type Account}
|
||||||
import spacetraders_models/agent.{type Agent}
|
import spacetraders_models/agent.{type Agent}
|
||||||
|
@ -1409,14 +1410,14 @@ fn stats_decoder() -> Decoder(Stats) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Health {
|
pub type Health {
|
||||||
Health(last_market_update: Option(Time))
|
Health(last_market_update: Option(Timestamp))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn health_decoder() -> Decoder(Health) {
|
fn health_decoder() -> Decoder(Health) {
|
||||||
use last_market_update <- decode.optional_field(
|
use last_market_update <- decode.optional_field(
|
||||||
"lastMarketUpdate",
|
"lastMarketUpdate",
|
||||||
option.None,
|
option.None,
|
||||||
decode.optional(time.datetime_decoder()),
|
decode.optional(time.rfc3339_timestamp_decoder()),
|
||||||
)
|
)
|
||||||
decode.success(Health(last_market_update:))
|
decode.success(Health(last_market_update:))
|
||||||
}
|
}
|
||||||
|
@ -1461,11 +1462,11 @@ fn leaderboards_decoder() -> Decoder(Leaderboards) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ServerResets {
|
pub type ServerResets {
|
||||||
ServerResets(next: Time, frequency: String)
|
ServerResets(next: Timestamp, frequency: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn server_resets_decoder() -> Decoder(ServerResets) {
|
fn server_resets_decoder() -> Decoder(ServerResets) {
|
||||||
use next <- decode.field("next", time.datetime_decoder())
|
use next <- decode.field("next", time.rfc3339_timestamp_decoder())
|
||||||
use frequency <- decode.field("frequency", decode.string)
|
use frequency <- decode.field("frequency", decode.string)
|
||||||
decode.success(ServerResets(next:, frequency:))
|
decode.success(ServerResets(next:, frequency:))
|
||||||
}
|
}
|
||||||
|
@ -1500,7 +1501,7 @@ pub type ServerStatus {
|
||||||
ServerStatus(
|
ServerStatus(
|
||||||
status: String,
|
status: String,
|
||||||
version: String,
|
version: String,
|
||||||
reset_date: Time,
|
reset_date: Date,
|
||||||
description: String,
|
description: String,
|
||||||
stats: Stats,
|
stats: Stats,
|
||||||
health: Health,
|
health: Health,
|
||||||
|
@ -1514,7 +1515,7 @@ pub type ServerStatus {
|
||||||
fn server_status_decoder() -> Decoder(ServerStatus) {
|
fn server_status_decoder() -> Decoder(ServerStatus) {
|
||||||
use status <- decode.field("status", decode.string)
|
use status <- decode.field("status", decode.string)
|
||||||
use version <- decode.field("version", decode.string)
|
use version <- decode.field("version", decode.string)
|
||||||
use reset_date <- decode.field("resetDate", time.date_decoder())
|
use reset_date <- decode.field("resetDate", time.rfc3339_date_decoder())
|
||||||
use description <- decode.field("description", decode.string)
|
use description <- decode.field("description", decode.string)
|
||||||
use stats <- decode.field("stats", stats_decoder())
|
use stats <- decode.field("stats", stats_decoder())
|
||||||
use health <- decode.field("health", health_decoder())
|
use health <- decode.field("health", health_decoder())
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
import gleam/option.{type Option}
|
import gleam/option.{type Option}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import spacetraders_models/account_id.{type AccountId}
|
import spacetraders_models/account_id.{type AccountId}
|
||||||
import spacetraders_sdk/internal/time
|
import spacetraders_sdk/internal/time
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ pub type Account {
|
||||||
id: AccountId,
|
id: AccountId,
|
||||||
email: Option(String),
|
email: Option(String),
|
||||||
token: Option(String),
|
token: Option(String),
|
||||||
created_at: Time,
|
created_at: Timestamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,6 @@ pub fn decoder() -> Decoder(Account) {
|
||||||
option.None,
|
option.None,
|
||||||
decode.optional(decode.string),
|
decode.optional(decode.string),
|
||||||
)
|
)
|
||||||
use created_at <- decode.field("createdAt", time.datetime_decoder())
|
use created_at <- decode.field("createdAt", time.rfc3339_timestamp_decoder())
|
||||||
decode.success(Account(id:, email:, token:, created_at:))
|
decode.success(Account(id:, email:, token:, created_at:))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/dynamic.{type Dynamic}
|
import gleam/dynamic.{type Dynamic}
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
import gleam/option.{type Option}
|
import gleam/option.{type Option}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import spacetraders_models/agent_event_id.{type AgentEventId}
|
import spacetraders_models/agent_event_id.{type AgentEventId}
|
||||||
import spacetraders_sdk/internal/time
|
import spacetraders_sdk/internal/time
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ pub type AgentEvent {
|
||||||
type_: String,
|
type_: String,
|
||||||
message: String,
|
message: String,
|
||||||
data: Option(Dynamic),
|
data: Option(Dynamic),
|
||||||
created_at: Time,
|
created_at: Timestamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,6 @@ pub fn decoder() -> Decoder(AgentEvent) {
|
||||||
option.None,
|
option.None,
|
||||||
decode.optional(decode.dynamic),
|
decode.optional(decode.dynamic),
|
||||||
)
|
)
|
||||||
use created_at <- decode.field("createdAt", time.datetime_decoder())
|
use created_at <- decode.field("createdAt", time.rfc3339_timestamp_decoder())
|
||||||
decode.success(AgentEvent(id:, type_:, message:, data:, created_at:))
|
decode.success(AgentEvent(id:, type_:, message:, data:, created_at:))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import spacetraders_models/agent_symbol.{type AgentSymbol}
|
import spacetraders_models/agent_symbol.{type AgentSymbol}
|
||||||
import spacetraders_models/waypoint_symbol.{type WaypointSymbol}
|
import spacetraders_models/waypoint_symbol.{type WaypointSymbol}
|
||||||
import spacetraders_sdk/internal/time
|
import spacetraders_sdk/internal/time
|
||||||
|
@ -8,7 +8,7 @@ pub type Chart {
|
||||||
Chart(
|
Chart(
|
||||||
waypoint_symbol: WaypointSymbol,
|
waypoint_symbol: WaypointSymbol,
|
||||||
submitted_by: AgentSymbol,
|
submitted_by: AgentSymbol,
|
||||||
submitted_on: Time,
|
submitted_on: Timestamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,9 @@ pub fn decoder() -> Decoder(Chart) {
|
||||||
waypoint_symbol.decoder(),
|
waypoint_symbol.decoder(),
|
||||||
)
|
)
|
||||||
use submitted_by <- decode.field("submittedBy", agent_symbol.decoder())
|
use submitted_by <- decode.field("submittedBy", agent_symbol.decoder())
|
||||||
use submitted_on <- decode.field("submittedOn", time.datetime_decoder())
|
use submitted_on <- decode.field(
|
||||||
|
"submittedOn",
|
||||||
|
time.rfc3339_timestamp_decoder(),
|
||||||
|
)
|
||||||
decode.success(Chart(waypoint_symbol:, submitted_by:, submitted_on:))
|
decode.success(Chart(waypoint_symbol:, submitted_by:, submitted_on:))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import spacetraders_models/ship_symbol.{type ShipSymbol}
|
import spacetraders_models/ship_symbol.{type ShipSymbol}
|
||||||
import spacetraders_models/waypoint_symbol.{type WaypointSymbol}
|
import spacetraders_models/waypoint_symbol.{type WaypointSymbol}
|
||||||
import spacetraders_sdk/internal/time
|
import spacetraders_sdk/internal/time
|
||||||
|
@ -9,7 +9,7 @@ pub type ChartTransaction {
|
||||||
waypoint_symbol: WaypointSymbol,
|
waypoint_symbol: WaypointSymbol,
|
||||||
ship_symbol: ShipSymbol,
|
ship_symbol: ShipSymbol,
|
||||||
total_price: Int,
|
total_price: Int,
|
||||||
timestamp: Time,
|
timestamp: Timestamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ pub fn decoder() -> Decoder(ChartTransaction) {
|
||||||
)
|
)
|
||||||
use ship_symbol <- decode.field("shipSymbol", ship_symbol.decoder())
|
use ship_symbol <- decode.field("shipSymbol", ship_symbol.decoder())
|
||||||
use total_price <- decode.field("totalPrice", decode.int)
|
use total_price <- decode.field("totalPrice", decode.int)
|
||||||
use timestamp <- decode.field("timestamp", time.datetime_decoder())
|
use timestamp <- decode.field("timestamp", time.rfc3339_timestamp_decoder())
|
||||||
decode.success(ChartTransaction(
|
decode.success(ChartTransaction(
|
||||||
waypoint_symbol:,
|
waypoint_symbol:,
|
||||||
ship_symbol:,
|
ship_symbol:,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
import gleam/option.{type Option}
|
import gleam/option.{type Option}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import spacetraders_models/contract_id.{type ContractId}
|
import spacetraders_models/contract_id.{type ContractId}
|
||||||
import spacetraders_models/contract_terms.{type ContractTerms}
|
import spacetraders_models/contract_terms.{type ContractTerms}
|
||||||
import spacetraders_models/contract_type.{type ContractType}
|
import spacetraders_models/contract_type.{type ContractType}
|
||||||
|
@ -15,7 +15,7 @@ pub type Contract {
|
||||||
terms: ContractTerms,
|
terms: ContractTerms,
|
||||||
accepted: Bool,
|
accepted: Bool,
|
||||||
fulfilled: Bool,
|
fulfilled: Bool,
|
||||||
deadline_to_accept: Option(Time),
|
deadline_to_accept: Option(Timestamp),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ pub fn decoder() -> Decoder(Contract) {
|
||||||
use deadline_to_accept <- decode.optional_field(
|
use deadline_to_accept <- decode.optional_field(
|
||||||
"deadlineToAccept",
|
"deadlineToAccept",
|
||||||
option.None,
|
option.None,
|
||||||
decode.optional(time.datetime_decoder()),
|
decode.optional(time.rfc3339_timestamp_decoder()),
|
||||||
)
|
)
|
||||||
decode.success(Contract(
|
decode.success(Contract(
|
||||||
id:,
|
id:,
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
import gleam/option.{type Option}
|
import gleam/option.{type Option}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import spacetraders_models/contract_deliver_good.{type ContractDeliverGood}
|
import spacetraders_models/contract_deliver_good.{type ContractDeliverGood}
|
||||||
import spacetraders_models/contract_payment.{type ContractPayment}
|
import spacetraders_models/contract_payment.{type ContractPayment}
|
||||||
import spacetraders_sdk/internal/time
|
import spacetraders_sdk/internal/time
|
||||||
|
|
||||||
pub type ContractTerms {
|
pub type ContractTerms {
|
||||||
ContractTerms(
|
ContractTerms(
|
||||||
deadline: Time,
|
deadline: Timestamp,
|
||||||
payment: ContractPayment,
|
payment: ContractPayment,
|
||||||
deliver: Option(List(ContractDeliverGood)),
|
deliver: Option(List(ContractDeliverGood)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decoder() -> Decoder(ContractTerms) {
|
pub fn decoder() -> Decoder(ContractTerms) {
|
||||||
use deadline <- decode.field("deadline", time.datetime_decoder())
|
use deadline <- decode.field("deadline", time.rfc3339_timestamp_decoder())
|
||||||
use payment <- decode.field("payment", contract_payment.decoder())
|
use payment <- decode.field("payment", contract_payment.decoder())
|
||||||
use deliver <- decode.optional_field(
|
use deliver <- decode.optional_field(
|
||||||
"deliver",
|
"deliver",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
import gleam/option.{type Option}
|
import gleam/option.{type Option}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import spacetraders_models/ship_symbol.{type ShipSymbol}
|
import spacetraders_models/ship_symbol.{type ShipSymbol}
|
||||||
import spacetraders_sdk/internal/time
|
import spacetraders_sdk/internal/time
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ pub type Cooldown {
|
||||||
ship_symbol: ShipSymbol,
|
ship_symbol: ShipSymbol,
|
||||||
total_seconds: Int,
|
total_seconds: Int,
|
||||||
remaining_seconds: Int,
|
remaining_seconds: Int,
|
||||||
expiration: Option(Time),
|
expiration: Option(Timestamp),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ pub fn decoder() -> Decoder(Cooldown) {
|
||||||
use expiration <- decode.optional_field(
|
use expiration <- decode.optional_field(
|
||||||
"expiration",
|
"expiration",
|
||||||
option.None,
|
option.None,
|
||||||
decode.optional(time.datetime_decoder()),
|
decode.optional(time.rfc3339_timestamp_decoder()),
|
||||||
)
|
)
|
||||||
decode.success(Cooldown(
|
decode.success(Cooldown(
|
||||||
ship_symbol:,
|
ship_symbol:,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import spacetraders_models/ship_symbol.{type ShipSymbol}
|
import spacetraders_models/ship_symbol.{type ShipSymbol}
|
||||||
import spacetraders_models/trade_symbol.{type TradeSymbol}
|
import spacetraders_models/trade_symbol.{type TradeSymbol}
|
||||||
import spacetraders_models/transaction_type.{type TransactionType}
|
import spacetraders_models/transaction_type.{type TransactionType}
|
||||||
|
@ -15,7 +15,7 @@ pub type MarketTransaction {
|
||||||
units: Int,
|
units: Int,
|
||||||
price_per_unit: Int,
|
price_per_unit: Int,
|
||||||
total_price: Int,
|
total_price: Int,
|
||||||
timestamp: Time,
|
timestamp: Timestamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ pub fn decoder() -> Decoder(MarketTransaction) {
|
||||||
use units <- decode.field("units", decode.int)
|
use units <- decode.field("units", decode.int)
|
||||||
use price_per_unit <- decode.field("pricePerUnit", decode.int)
|
use price_per_unit <- decode.field("pricePerUnit", decode.int)
|
||||||
use total_price <- decode.field("totalPrice", decode.int)
|
use total_price <- decode.field("totalPrice", decode.int)
|
||||||
use timestamp <- decode.field("timestamp", time.datetime_decoder())
|
use timestamp <- decode.field("timestamp", time.rfc3339_timestamp_decoder())
|
||||||
decode.success(MarketTransaction(
|
decode.success(MarketTransaction(
|
||||||
waypoint_symbol:,
|
waypoint_symbol:,
|
||||||
ship_symbol:,
|
ship_symbol:,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import spacetraders_models/ship_symbol.{type ShipSymbol}
|
import spacetraders_models/ship_symbol.{type ShipSymbol}
|
||||||
import spacetraders_models/waypoint_symbol.{type WaypointSymbol}
|
import spacetraders_models/waypoint_symbol.{type WaypointSymbol}
|
||||||
import spacetraders_sdk/internal/time
|
import spacetraders_sdk/internal/time
|
||||||
|
@ -9,7 +9,7 @@ pub type RepairTransaction {
|
||||||
waypoint_symbol: WaypointSymbol,
|
waypoint_symbol: WaypointSymbol,
|
||||||
ship_symbol: ShipSymbol,
|
ship_symbol: ShipSymbol,
|
||||||
total_price: Int,
|
total_price: Int,
|
||||||
timestamp: Time,
|
timestamp: Timestamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ pub fn decoder() -> Decoder(RepairTransaction) {
|
||||||
)
|
)
|
||||||
use ship_symbol <- decode.field("shipSymbol", ship_symbol.decoder())
|
use ship_symbol <- decode.field("shipSymbol", ship_symbol.decoder())
|
||||||
use total_price <- decode.field("totalPrice", decode.int)
|
use total_price <- decode.field("totalPrice", decode.int)
|
||||||
use timestamp <- decode.field("timestamp", time.datetime_decoder())
|
use timestamp <- decode.field("timestamp", time.rfc3339_timestamp_decoder())
|
||||||
decode.success(RepairTransaction(
|
decode.success(RepairTransaction(
|
||||||
waypoint_symbol:,
|
waypoint_symbol:,
|
||||||
ship_symbol:,
|
ship_symbol:,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import spacetraders_models/ship_symbol.{type ShipSymbol}
|
import spacetraders_models/ship_symbol.{type ShipSymbol}
|
||||||
import spacetraders_models/waypoint_symbol.{type WaypointSymbol}
|
import spacetraders_models/waypoint_symbol.{type WaypointSymbol}
|
||||||
import spacetraders_sdk/internal/time
|
import spacetraders_sdk/internal/time
|
||||||
|
@ -9,7 +9,7 @@ pub type ScrapTransaction {
|
||||||
waypoint_symbol: WaypointSymbol,
|
waypoint_symbol: WaypointSymbol,
|
||||||
ship_symbol: ShipSymbol,
|
ship_symbol: ShipSymbol,
|
||||||
total_price: Int,
|
total_price: Int,
|
||||||
timestamp: Time,
|
timestamp: Timestamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ pub fn decoder() -> Decoder(ScrapTransaction) {
|
||||||
)
|
)
|
||||||
use ship_symbol <- decode.field("shipSymbol", ship_symbol.decoder())
|
use ship_symbol <- decode.field("shipSymbol", ship_symbol.decoder())
|
||||||
use total_price <- decode.field("totalPrice", decode.int)
|
use total_price <- decode.field("totalPrice", decode.int)
|
||||||
use timestamp <- decode.field("timestamp", time.datetime_decoder())
|
use timestamp <- decode.field("timestamp", time.rfc3339_timestamp_decoder())
|
||||||
decode.success(ScrapTransaction(
|
decode.success(ScrapTransaction(
|
||||||
waypoint_symbol:,
|
waypoint_symbol:,
|
||||||
ship_symbol:,
|
ship_symbol:,
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import spacetraders_sdk/internal/time
|
import spacetraders_sdk/internal/time
|
||||||
|
|
||||||
pub type ShipFuelConsumed {
|
pub type ShipFuelConsumed {
|
||||||
ShipFuelConsumed(amount: Int, timestamp: Time)
|
ShipFuelConsumed(amount: Int, timestamp: Timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decoder() -> Decoder(ShipFuelConsumed) {
|
pub fn decoder() -> Decoder(ShipFuelConsumed) {
|
||||||
use amount <- decode.field("amount", decode.int)
|
use amount <- decode.field("amount", decode.int)
|
||||||
use timestamp <- decode.field("timestamp", time.datetime_decoder())
|
use timestamp <- decode.field("timestamp", time.rfc3339_timestamp_decoder())
|
||||||
decode.success(ShipFuelConsumed(amount:, timestamp:))
|
decode.success(ShipFuelConsumed(amount:, timestamp:))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import spacetraders_models/ship_symbol.{type ShipSymbol}
|
import spacetraders_models/ship_symbol.{type ShipSymbol}
|
||||||
import spacetraders_models/trade_symbol.{type TradeSymbol}
|
import spacetraders_models/trade_symbol.{type TradeSymbol}
|
||||||
import spacetraders_models/waypoint_symbol.{type WaypointSymbol}
|
import spacetraders_models/waypoint_symbol.{type WaypointSymbol}
|
||||||
|
@ -11,7 +11,7 @@ pub type ShipModificationTransaction {
|
||||||
ship_symbol: ShipSymbol,
|
ship_symbol: ShipSymbol,
|
||||||
trade_symbol: TradeSymbol,
|
trade_symbol: TradeSymbol,
|
||||||
total_price: Int,
|
total_price: Int,
|
||||||
timestamp: Time,
|
timestamp: Timestamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ pub fn decoder() -> Decoder(ShipModificationTransaction) {
|
||||||
use ship_symbol <- decode.field("shipSymbol", ship_symbol.decoder())
|
use ship_symbol <- decode.field("shipSymbol", ship_symbol.decoder())
|
||||||
use trade_symbol <- decode.field("tradeSymbol", trade_symbol.decoder())
|
use trade_symbol <- decode.field("tradeSymbol", trade_symbol.decoder())
|
||||||
use total_price <- decode.field("totalPrice", decode.int)
|
use total_price <- decode.field("totalPrice", decode.int)
|
||||||
use timestamp <- decode.field("timestamp", time.datetime_decoder())
|
use timestamp <- decode.field("timestamp", time.rfc3339_timestamp_decoder())
|
||||||
decode.success(ShipModificationTransaction(
|
decode.success(ShipModificationTransaction(
|
||||||
waypoint_symbol:,
|
waypoint_symbol:,
|
||||||
ship_symbol:,
|
ship_symbol:,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import spacetraders_models/ship_nav_route_waypoint.{type ShipNavRouteWaypoint}
|
import spacetraders_models/ship_nav_route_waypoint.{type ShipNavRouteWaypoint}
|
||||||
import spacetraders_sdk/internal/time
|
import spacetraders_sdk/internal/time
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@ pub type ShipNavRoute {
|
||||||
ShipNavRoute(
|
ShipNavRoute(
|
||||||
destination: ShipNavRouteWaypoint,
|
destination: ShipNavRouteWaypoint,
|
||||||
origin: ShipNavRouteWaypoint,
|
origin: ShipNavRouteWaypoint,
|
||||||
departure_time: Time,
|
departure_time: Timestamp,
|
||||||
arrival: Time,
|
arrival: Timestamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,10 @@ pub fn decoder() -> Decoder(ShipNavRoute) {
|
||||||
ship_nav_route_waypoint.decoder(),
|
ship_nav_route_waypoint.decoder(),
|
||||||
)
|
)
|
||||||
use origin <- decode.field("origin", ship_nav_route_waypoint.decoder())
|
use origin <- decode.field("origin", ship_nav_route_waypoint.decoder())
|
||||||
use departure_time <- decode.field("departureTime", time.datetime_decoder())
|
use departure_time <- decode.field(
|
||||||
use arrival <- decode.field("arrival", time.datetime_decoder())
|
"departureTime",
|
||||||
|
time.rfc3339_timestamp_decoder(),
|
||||||
|
)
|
||||||
|
use arrival <- decode.field("arrival", time.rfc3339_timestamp_decoder())
|
||||||
decode.success(ShipNavRoute(destination:, origin:, departure_time:, arrival:))
|
decode.success(ShipNavRoute(destination:, origin:, departure_time:, arrival:))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import spacetraders_models/agent_symbol.{type AgentSymbol}
|
import spacetraders_models/agent_symbol.{type AgentSymbol}
|
||||||
import spacetraders_models/ship_type.{type ShipType}
|
import spacetraders_models/ship_type.{type ShipType}
|
||||||
import spacetraders_models/waypoint_symbol.{type WaypointSymbol}
|
import spacetraders_models/waypoint_symbol.{type WaypointSymbol}
|
||||||
|
@ -11,7 +11,7 @@ pub type ShipyardTransaction {
|
||||||
ship_type: ShipType,
|
ship_type: ShipType,
|
||||||
price: Int,
|
price: Int,
|
||||||
agent_symbol: AgentSymbol,
|
agent_symbol: AgentSymbol,
|
||||||
timestamp: Time,
|
timestamp: Timestamp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ pub fn decoder() -> Decoder(ShipyardTransaction) {
|
||||||
use ship_type <- decode.field("shipType", ship_type.decoder())
|
use ship_type <- decode.field("shipType", ship_type.decoder())
|
||||||
use price <- decode.field("price", decode.int)
|
use price <- decode.field("price", decode.int)
|
||||||
use agent_symbol <- decode.field("agentSymbol", agent_symbol.decoder())
|
use agent_symbol <- decode.field("agentSymbol", agent_symbol.decoder())
|
||||||
use timestamp <- decode.field("timestamp", time.datetime_decoder())
|
use timestamp <- decode.field("timestamp", time.rfc3339_timestamp_decoder())
|
||||||
decode.success(ShipyardTransaction(
|
decode.success(ShipyardTransaction(
|
||||||
waypoint_symbol:,
|
waypoint_symbol:,
|
||||||
ship_type:,
|
ship_type:,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
import gleam/json.{type Json}
|
import gleam/json.{type Json}
|
||||||
|
import gleam/time/calendar
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import spacetraders_models/survey_deposit.{type SurveyDeposit}
|
import spacetraders_models/survey_deposit.{type SurveyDeposit}
|
||||||
import spacetraders_models/survey_signature.{type SurveySignature}
|
import spacetraders_models/survey_signature.{type SurveySignature}
|
||||||
import spacetraders_models/survey_size.{type SurveySize}
|
import spacetraders_models/survey_size.{type SurveySize}
|
||||||
|
@ -12,7 +13,7 @@ pub type Survey {
|
||||||
signature: SurveySignature,
|
signature: SurveySignature,
|
||||||
symbol: WaypointSymbol,
|
symbol: WaypointSymbol,
|
||||||
deposits: List(SurveyDeposit),
|
deposits: List(SurveyDeposit),
|
||||||
expiration: Time,
|
expiration: Timestamp,
|
||||||
size: SurveySize,
|
size: SurveySize,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -24,7 +25,7 @@ pub fn decoder() -> Decoder(Survey) {
|
||||||
"deposits",
|
"deposits",
|
||||||
decode.list(survey_deposit.decoder()),
|
decode.list(survey_deposit.decoder()),
|
||||||
)
|
)
|
||||||
use expiration <- decode.field("expiration", time.datetime_decoder())
|
use expiration <- decode.field("expiration", time.rfc3339_timestamp_decoder())
|
||||||
use size <- decode.field("size", survey_size.decoder())
|
use size <- decode.field("size", survey_size.decoder())
|
||||||
decode.success(Survey(signature:, symbol:, deposits:, expiration:, size:))
|
decode.success(Survey(signature:, symbol:, deposits:, expiration:, size:))
|
||||||
}
|
}
|
||||||
|
@ -34,7 +35,10 @@ pub fn encode(survey: Survey) -> Json {
|
||||||
#("signature", survey_signature.encode(survey.signature)),
|
#("signature", survey_signature.encode(survey.signature)),
|
||||||
#("symbol", waypoint_symbol.encode(survey.symbol)),
|
#("symbol", waypoint_symbol.encode(survey.symbol)),
|
||||||
#("deposits", json.array(survey.deposits, survey_deposit.encode)),
|
#("deposits", json.array(survey.deposits, survey_deposit.encode)),
|
||||||
#("expiration", json.string(birl.to_iso8601(survey.expiration))),
|
#(
|
||||||
|
"expiration",
|
||||||
|
json.string(timestamp.to_rfc3339(survey.expiration, calendar.utc_offset)),
|
||||||
|
),
|
||||||
#("size", survey_size.encode(survey.size)),
|
#("size", survey_size.encode(survey.size)),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import birl.{type Time}
|
|
||||||
import gleam/bit_array
|
import gleam/bit_array
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
import gleam/json
|
import gleam/json
|
||||||
import gleam/option.{type Option}
|
import gleam/option.{type Option}
|
||||||
import gleam/result
|
import gleam/result
|
||||||
import gleam/string
|
import gleam/string
|
||||||
|
import gleam/time/calendar.{type Date}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
import spacetraders_sdk/internal/time
|
import spacetraders_sdk/internal/time
|
||||||
|
|
||||||
pub type JwtDecodeError {
|
pub type JwtDecodeError {
|
||||||
|
@ -78,8 +79,8 @@ pub type JwtPayload {
|
||||||
JwtPayload(
|
JwtPayload(
|
||||||
identifier: String,
|
identifier: String,
|
||||||
version: String,
|
version: String,
|
||||||
reset_date: Option(Time),
|
reset_date: Option(Date),
|
||||||
issued_at: Time,
|
issued_at: Timestamp,
|
||||||
subject: String,
|
subject: String,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -90,10 +91,10 @@ fn jwt_payload_decoder() -> Decoder(JwtPayload) {
|
||||||
use reset_date <- decode.optional_field(
|
use reset_date <- decode.optional_field(
|
||||||
"reset_date",
|
"reset_date",
|
||||||
option.None,
|
option.None,
|
||||||
decode.optional(time.date_decoder()),
|
decode.optional(time.rfc3339_date_decoder()),
|
||||||
)
|
)
|
||||||
use issued_at_int <- decode.field("iat", decode.int)
|
use issued_at_int <- decode.field("iat", decode.int)
|
||||||
let issued_at = birl.from_unix(issued_at_int)
|
let issued_at = timestamp.from_unix_seconds(issued_at_int)
|
||||||
use subject <- decode.field("sub", decode.string)
|
use subject <- decode.field("sub", decode.string)
|
||||||
decode.success(JwtPayload(
|
decode.success(JwtPayload(
|
||||||
identifier:,
|
identifier:,
|
||||||
|
|
|
@ -1,18 +1,219 @@
|
||||||
import birl.{type Time}
|
import gleam/bit_array
|
||||||
import gleam/dynamic/decode.{type Decoder}
|
import gleam/dynamic/decode.{type Decoder}
|
||||||
|
import gleam/pair
|
||||||
|
import gleam/result
|
||||||
|
import gleam/time/calendar.{
|
||||||
|
type Date, type Month, type TimeOfDay, April, August, Date, December, February,
|
||||||
|
January, July, June, March, May, November, October, September, TimeOfDay,
|
||||||
|
}
|
||||||
|
import gleam/time/timestamp.{type Timestamp}
|
||||||
|
|
||||||
pub fn datetime_decoder() -> Decoder(Time) {
|
pub fn rfc3339_timestamp_decoder() -> Decoder(Timestamp) {
|
||||||
use value <- decode.then(decode.string)
|
use value <- decode.then(decode.string)
|
||||||
case birl.parse(value) {
|
case timestamp.parse_rfc3339(value) {
|
||||||
Ok(time) -> decode.success(time)
|
Ok(timestamp) -> decode.success(timestamp)
|
||||||
Error(Nil) -> decode.failure(birl.now(), "DateTime")
|
Error(Nil) -> decode.failure(timestamp.from_unix_seconds(0), "Timestamp")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn date_decoder() -> Decoder(Time) {
|
pub fn parse_rfc3339_date(input: String) -> Result(Date, Nil) {
|
||||||
|
let bytes = bit_array.from_string(input)
|
||||||
|
use #(year, bytes) <- result.try(parse_year(from: bytes))
|
||||||
|
use bytes <- result.try(accept_byte(from: bytes, value: byte_minus))
|
||||||
|
use #(month, bytes) <- result.try(parse_month_calendar(from: bytes))
|
||||||
|
use bytes <- result.try(accept_byte(from: bytes, value: byte_minus))
|
||||||
|
use #(day, bytes) <- result.try(parse_day_calendar(from: bytes, year:, month:))
|
||||||
|
use Nil <- result.try(accept_empty(bytes))
|
||||||
|
Ok(Date(year:, month:, day:))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rfc3339_date_decoder() -> Decoder(Date) {
|
||||||
use value <- decode.then(decode.string)
|
use value <- decode.then(decode.string)
|
||||||
case birl.from_naive(value) {
|
case parse_rfc3339_date(value) {
|
||||||
Ok(time) -> decode.success(time)
|
Ok(date) -> decode.success(date)
|
||||||
Error(Nil) -> decode.failure(birl.now(), "Date")
|
Error(Nil) -> decode.failure(Date(1970, January, 1), "Date")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_rfc3339_time_of_day(input: String) -> Result(TimeOfDay, Nil) {
|
||||||
|
let bytes = bit_array.from_string(input)
|
||||||
|
use #(hours, bytes) <- result.try(parse_hours(from: bytes))
|
||||||
|
use bytes <- result.try(accept_byte(from: bytes, value: byte_colon))
|
||||||
|
use #(minutes, bytes) <- result.try(parse_minutes(from: bytes))
|
||||||
|
use bytes <- result.try(accept_byte(from: bytes, value: byte_colon))
|
||||||
|
use #(seconds, bytes) <- result.try(parse_seconds(from: bytes))
|
||||||
|
use #(nanoseconds, bytes) <- result.try(parse_second_fraction_as_nanoseconds(
|
||||||
|
from: bytes,
|
||||||
|
))
|
||||||
|
use Nil <- result.try(accept_empty(bytes))
|
||||||
|
Ok(TimeOfDay(hours:, minutes:, seconds:, nanoseconds:))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rfc3339_time_of_day_decoder() -> Decoder(TimeOfDay) {
|
||||||
|
use value <- decode.then(decode.string)
|
||||||
|
case parse_rfc3339_time_of_day(value) {
|
||||||
|
Ok(date) -> decode.success(date)
|
||||||
|
Error(Nil) -> decode.failure(TimeOfDay(0, 0, 0, 0), "TimeOfDay")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte_zero: Int = 0x30
|
||||||
|
|
||||||
|
const byte_nine: Int = 0x39
|
||||||
|
|
||||||
|
const byte_colon: Int = 0x3A
|
||||||
|
|
||||||
|
const byte_minus: Int = 0x2D
|
||||||
|
|
||||||
|
const nanoseconds_per_second: Int = 1_000_000_000
|
||||||
|
|
||||||
|
fn accept_byte(from bytes: BitArray, value value: Int) -> Result(BitArray, Nil) {
|
||||||
|
case bytes {
|
||||||
|
<<byte, remaining_bytes:bytes>> if byte == value -> Ok(remaining_bytes)
|
||||||
|
_ -> Error(Nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn accept_empty(from bytes: BitArray) -> Result(Nil, Nil) {
|
||||||
|
case bytes {
|
||||||
|
<<>> -> Ok(Nil)
|
||||||
|
_ -> Error(Nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_digits(
|
||||||
|
from bytes: BitArray,
|
||||||
|
count count: Int,
|
||||||
|
) -> Result(#(Int, BitArray), Nil) {
|
||||||
|
do_parse_digits(from: bytes, count:, acc: 0, k: 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_parse_digits(
|
||||||
|
from bytes: BitArray,
|
||||||
|
count count: Int,
|
||||||
|
acc acc: Int,
|
||||||
|
k k: Int,
|
||||||
|
) -> Result(#(Int, BitArray), Nil) {
|
||||||
|
case bytes {
|
||||||
|
_ if k >= count -> Ok(#(acc, bytes))
|
||||||
|
<<byte, remaining_bytes:bytes>> if byte_zero <= byte && byte <= byte_nine ->
|
||||||
|
do_parse_digits(
|
||||||
|
from: remaining_bytes,
|
||||||
|
count:,
|
||||||
|
acc: acc * 10 + { byte - 0x30 },
|
||||||
|
k: k + 1,
|
||||||
|
)
|
||||||
|
_ -> Error(Nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_year(from bytes: BitArray) -> Result(#(Int, BitArray), Nil) {
|
||||||
|
parse_digits(from: bytes, count: 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
// slightly modified version of parse_month that returns calendar.Month instead of Int
|
||||||
|
fn parse_month_calendar(from bytes: BitArray) -> Result(#(Month, BitArray), Nil) {
|
||||||
|
use #(month, bytes) <- result.try(parse_digits(from: bytes, count: 2))
|
||||||
|
calendar.month_from_int(month) |> result.map(pair.new(_, bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// slightly modified version of parse_day that takes calendar.Month instead of Int
|
||||||
|
fn parse_day_calendar(
|
||||||
|
from bytes: BitArray,
|
||||||
|
year year: Int,
|
||||||
|
month month: Month,
|
||||||
|
) -> Result(#(Int, BitArray), Nil) {
|
||||||
|
use #(day, bytes) <- result.try(parse_digits(from: bytes, count: 2))
|
||||||
|
let max_day = case month {
|
||||||
|
January | March | May | July | August | October | December -> 31
|
||||||
|
April | June | September | November -> 30
|
||||||
|
February -> {
|
||||||
|
case is_leap_year(year) {
|
||||||
|
True -> 29
|
||||||
|
False -> 28
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 1 <= day && day <= max_day {
|
||||||
|
True -> Ok(#(day, bytes))
|
||||||
|
False -> Error(Nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_leap_year(year: Int) -> Bool {
|
||||||
|
year % 4 == 0 && { year % 100 != 0 || year % 400 == 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_hours(from bytes: BitArray) -> Result(#(Int, BitArray), Nil) {
|
||||||
|
use #(hours, bytes) <- result.try(parse_digits(from: bytes, count: 2))
|
||||||
|
case 0 <= hours && hours <= 23 {
|
||||||
|
True -> Ok(#(hours, bytes))
|
||||||
|
False -> Error(Nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_minutes(from bytes: BitArray) -> Result(#(Int, BitArray), Nil) {
|
||||||
|
use #(minutes, bytes) <- result.try(parse_digits(from: bytes, count: 2))
|
||||||
|
case 0 <= minutes && minutes <= 59 {
|
||||||
|
True -> Ok(#(minutes, bytes))
|
||||||
|
False -> Error(Nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_seconds(from bytes: BitArray) -> Result(#(Int, BitArray), Nil) {
|
||||||
|
use #(seconds, bytes) <- result.try(parse_digits(from: bytes, count: 2))
|
||||||
|
case 0 <= seconds && seconds <= 60 {
|
||||||
|
True -> Ok(#(seconds, bytes))
|
||||||
|
False -> Error(Nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_second_fraction_as_nanoseconds(from bytes: BitArray) {
|
||||||
|
case bytes {
|
||||||
|
<<".", byte, remaining_bytes:bytes>>
|
||||||
|
if byte_zero <= byte && byte <= byte_nine
|
||||||
|
-> {
|
||||||
|
do_parse_second_fraction_as_nanoseconds(
|
||||||
|
from: <<byte, remaining_bytes:bits>>,
|
||||||
|
acc: 0,
|
||||||
|
power: nanoseconds_per_second,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<<".", _:bytes>> -> Error(Nil)
|
||||||
|
_ -> Ok(#(0, bytes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_parse_second_fraction_as_nanoseconds(
|
||||||
|
from bytes: BitArray,
|
||||||
|
acc acc: Int,
|
||||||
|
power power: Int,
|
||||||
|
) -> Result(#(Int, BitArray), a) {
|
||||||
|
// Each digit place to the left in the fractional second is 10x fewer
|
||||||
|
// nanoseconds.
|
||||||
|
let power = power / 10
|
||||||
|
|
||||||
|
case bytes {
|
||||||
|
<<byte, remaining_bytes:bytes>>
|
||||||
|
if byte_zero <= byte && byte <= byte_nine && power < 1
|
||||||
|
-> {
|
||||||
|
// We already have the max precision for nanoseconds. Truncate any
|
||||||
|
// remaining digits.
|
||||||
|
do_parse_second_fraction_as_nanoseconds(
|
||||||
|
from: remaining_bytes,
|
||||||
|
acc:,
|
||||||
|
power:,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<<byte, remaining_bytes:bytes>> if byte_zero <= byte && byte <= byte_nine -> {
|
||||||
|
// We have not yet reached the precision limit. Parse the next digit.
|
||||||
|
let digit = byte - 0x30
|
||||||
|
do_parse_second_fraction_as_nanoseconds(
|
||||||
|
from: remaining_bytes,
|
||||||
|
acc: acc + digit * power,
|
||||||
|
power:,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ -> Ok(#(acc, bytes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub fn error_codes_test() {
|
||||||
|
|
||||||
pub fn account_test() {
|
pub fn account_test() {
|
||||||
let assert Ok(_) =
|
let assert Ok(_) =
|
||||||
spacetraders_api.get_account(env.load_dotenv_unsafe().agent_token)
|
spacetraders_api.get_account(env.load_env_unsafe().agent_token)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn supply_chain_test() {
|
pub fn supply_chain_test() {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import dot_env
|
import envoy
|
||||||
import dot_env/env
|
|
||||||
import gleam/result
|
import gleam/result
|
||||||
import spacetraders_sdk.{type AccountToken, type AgentToken}
|
import spacetraders_sdk.{
|
||||||
|
type AccountToken, type AgentToken, type TokenParseError,
|
||||||
|
}
|
||||||
|
|
||||||
pub type Env {
|
pub type Env {
|
||||||
Env(account_token: AccountToken, agent_token: AgentToken)
|
Env(account_token: AccountToken, agent_token: AgentToken)
|
||||||
|
@ -9,25 +10,27 @@ pub type Env {
|
||||||
|
|
||||||
pub type EnvError {
|
pub type EnvError {
|
||||||
MissingVar(name: String)
|
MissingVar(name: String)
|
||||||
InvalidVar(name: String)
|
InvalidTokenVar(name: String, error: TokenParseError)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(name: String) -> Result(String, EnvError) {
|
||||||
|
envoy.get(name)
|
||||||
|
|> result.replace_error(MissingVar(name:))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_token(name: String, parse: fn(String) -> Result(token, TokenParseError)) {
|
||||||
|
get(name)
|
||||||
|
|> result.then(fn(value) {
|
||||||
|
parse(value) |> result.map_error(InvalidTokenVar(name:, error: _))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_account_token() -> Result(AccountToken, EnvError) {
|
pub fn get_account_token() -> Result(AccountToken, EnvError) {
|
||||||
env.get_string("ACCOUNT_TOKEN")
|
get_token("ACCOUNT_TOKEN", spacetraders_sdk.parse_account_token)
|
||||||
|> result.replace_error(MissingVar("ACCOUNT_TOKEN"))
|
|
||||||
|> result.then(fn(value) {
|
|
||||||
spacetraders_sdk.parse_account_token(value)
|
|
||||||
|> result.replace_error(InvalidVar("ACCOUNT_TOKEN"))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_agent_token() -> Result(AgentToken, EnvError) {
|
pub fn get_agent_token() -> Result(AgentToken, EnvError) {
|
||||||
env.get_string("AGENT_TOKEN")
|
get_token("AGENT_TOKEN", spacetraders_sdk.parse_agent_token)
|
||||||
|> result.replace_error(MissingVar("AGENT_TOKEN"))
|
|
||||||
|> result.then(fn(value) {
|
|
||||||
spacetraders_sdk.parse_agent_token(value)
|
|
||||||
|> result.replace_error(InvalidVar("AGENT_TOKEN"))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_env() -> Result(Env, EnvError) {
|
pub fn load_env() -> Result(Env, EnvError) {
|
||||||
|
@ -36,11 +39,6 @@ pub fn load_env() -> Result(Env, EnvError) {
|
||||||
Ok(Env(account_token:, agent_token:))
|
Ok(Env(account_token:, agent_token:))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_dotenv() -> Result(Env, EnvError) {
|
|
||||||
dot_env.load_default()
|
|
||||||
load_env()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load_env_unsafe() -> Env {
|
pub fn load_env_unsafe() -> Env {
|
||||||
let assert Ok(account_token) = get_account_token()
|
let assert Ok(account_token) = get_account_token()
|
||||||
as "Missing or invalid account token"
|
as "Missing or invalid account token"
|
||||||
|
@ -48,8 +46,3 @@ pub fn load_env_unsafe() -> Env {
|
||||||
as "Missing or invalid agent token"
|
as "Missing or invalid agent token"
|
||||||
Env(account_token:, agent_token:)
|
Env(account_token:, agent_token:)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_dotenv_unsafe() -> Env {
|
|
||||||
dot_env.load_default()
|
|
||||||
load_env_unsafe()
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue