Skip to main content

pfx_steam/
board.rs

1use crate::User;
2
3pub const DETAILS_MAX: usize = 64;
4pub const RUN_MARK: i32 = 0x5255_4e31;
5pub const RUN_FIELDS: usize = 3;
6const RANK_MAX: u32 = i32::MAX as u32;
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
9pub struct Board(pub u64);
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
12pub struct Ugc(pub u64);
13
14#[derive(Clone, Copy, Debug, PartialEq, Eq)]
15pub enum Sort {
16    Ascending,
17    Descending,
18}
19
20#[derive(Clone, Copy, Debug, PartialEq, Eq)]
21pub enum Display {
22    Numeric,
23    Seconds,
24    Milliseconds,
25}
26
27#[derive(Clone, Copy, Debug, PartialEq, Eq)]
28pub enum Upload {
29    KeepBest,
30    Force,
31}
32
33#[derive(Clone, Copy, Debug, PartialEq, Eq)]
34pub enum Range {
35    Global { first: u32, last: u32 },
36    AroundUser { before: u32, after: u32 },
37    Friends,
38}
39
40#[derive(Clone, Debug, PartialEq, Eq)]
41pub struct BoardInfo {
42    pub board: Board,
43    pub name: String,
44    pub sort: Sort,
45    pub display: Display,
46    pub entries: u32,
47}
48
49#[derive(Clone, Debug, PartialEq, Eq)]
50pub struct Entry {
51    pub user: User,
52    pub rank: u32,
53    pub score: i32,
54    pub details: Vec<i32>,
55    pub run: Option<Ugc>,
56}
57
58#[derive(Clone, Copy, Debug, PartialEq, Eq)]
59pub struct Uploaded {
60    pub score: i32,
61    pub changed: bool,
62    pub rank: u32,
63    pub previous_rank: u32,
64}
65
66impl Sort {
67    pub fn better(self, score: i32, than: i32) -> bool {
68        match self {
69            Sort::Ascending => score < than,
70            Sort::Descending => score > than,
71        }
72    }
73}
74
75impl Range {
76    pub(crate) fn valid(self) -> bool {
77        match self {
78            Range::Global { first, last } => first >= 1 && last >= first && last <= RANK_MAX,
79            Range::AroundUser { before, after } => before <= RANK_MAX && after <= RANK_MAX,
80            Range::Friends => true,
81        }
82    }
83}
84
85pub fn run_details(run: Ugc, details: &[i32]) -> Vec<i32> {
86    let mut out = Vec::with_capacity(RUN_FIELDS + details.len());
87    out.push(RUN_MARK);
88    out.push(run.0 as u32 as i32);
89    out.push((run.0 >> 32) as u32 as i32);
90    out.extend_from_slice(details);
91    out
92}
93
94pub fn split_run(details: &[i32], keep: usize) -> (Option<Ugc>, Vec<i32>) {
95    match details {
96        [RUN_MARK, low, high, rest @ ..] => {
97            let run = u64::from(*low as u32) | (u64::from(*high as u32) << 32);
98            (Some(Ugc(run)), rest.iter().take(keep).copied().collect())
99        }
100        _ => (None, details.iter().take(keep).copied().collect()),
101    }
102}