1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
//! Interpreting rooms in which PvP recently occurred. This is an "experimental" endpoint.
use crate::{
data,
error::{ApiError, Result},
EndpointResult,
};
/// Call parameters for requesting recent pvp
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum RecentPvpArgs {
/// Retrieves rooms where pvp has occurred recently, with a given number of game ticks.
WithinLast {
/// The interval of game ticks to request. It is unknown the maximum interval that may be requested.
ticks: u32,
},
/// Retrieves rooms where pvp has occurred since a given game time.
Since {
/// The game "time" (tick number) to request PvP since. It is unknown how far back of a time may be requested.
time: u32,
},
}
impl RecentPvpArgs {
/// Creates a new PvP call parameter to request any PvP occurring since the given game tick.
pub fn since(tick: u32) -> RecentPvpArgs {
RecentPvpArgs::Since { time: tick }
}
/// Creates a new PvP call parameter to request any PvP occurring within the last x ticks.
pub fn within(ticks: u32) -> RecentPvpArgs {
RecentPvpArgs::WithinLast { ticks: ticks }
}
}
/// Recent PvP raw result.
#[derive(serde_derive::Deserialize, Clone, Hash, Debug)]
pub(crate) struct Response {
ok: i32,
#[serde(with = "::tuple_vec_map")]
pvp: Vec<(String, InnerShard)>,
}
#[derive(serde_derive::Deserialize, Clone, Hash, Debug)]
struct InnerShard {
rooms: Vec<InnerRoom>,
time: u32,
}
#[derive(serde_derive::Deserialize, Clone, Hash, Debug)]
struct InnerRoom {
_id: String,
#[serde(rename = "lastPvpTime")]
last_pvp_time: u32,
}
/// Result storing recent pvp matches for the entire world.
pub struct RecentPvp {
/// A list of shard names and the recent pvp within that shard.
pub shards: Vec<(String, ShardRecentPvp)>,
/// Phantom data in order to allow adding any additional fields in the future.
_non_exhaustive: (),
}
/// Result storing recent pvp matches for a particular shard.
#[derive(Clone, Hash, Debug)]
pub struct ShardRecentPvp {
/// A list of room names in which pvp has recently occurred, and the time at which pvp last occurred.
pub rooms: Vec<(data::RoomName, u32)>,
/// The current game time of the server when the call was completed, the tick up to which pvp has been reported.
pub reported_up_to: u32,
/// Phantom data in order to allow adding any additional fields in the future.
_non_exhaustive: (),
}
impl EndpointResult for RecentPvp {
type RequestResult = Response;
type ErrorResult = data::ApiError;
fn from_raw(raw: Response) -> Result<RecentPvp> {
let Response { ok, pvp } = raw;
if ok != 1 {
return Err(ApiError::NotOk(ok).into());
}
Ok(RecentPvp {
shards: pvp
.into_iter()
.map(|(name, data)| {
Ok((
name,
ShardRecentPvp {
rooms: data
.rooms
.into_iter()
.map(|r| Ok((data::RoomName::new(&r._id)?, r.last_pvp_time)))
.collect::<Result<_>>()?,
reported_up_to: data.time,
_non_exhaustive: (),
},
))
})
.collect::<Result<_>>()?,
_non_exhaustive: (),
})
}
}
#[cfg(test)]
mod tests {
use super::RecentPvp;
use crate::EndpointResult;
use serde_json;
fn test_parse(json: serde_json::Value) {
let response = serde_json::from_value(json).unwrap();
let _ = RecentPvp::from_raw(response).unwrap();
}
#[test]
fn parse_sample_pvp() {
test_parse(json! ({
"ok": 1,
"pvp": {
"shard0": {
"time": 20656327,
"rooms": [
{
"_id": "E5N39",
"lastPvpTime": 20656327,
},
{
"_id": "W15S23",
"lastPvpTime": 20656326,
},
{
"_id": "W63S12",
"lastPvpTime": 20656326,
},
{
"_id": "W1N20",
"lastPvpTime": 20656323,
},
{
"_id": "W54N97",
"lastPvpTime": 20656322,
}
]
},
"shard1": {
"time": 265413,
"rooms": [
{
"_id": "E2S3",
"lastPvpTime": 265412,
}
]
}
}
}));
}
}