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}