use serde::{self, Serialize, Deserialize};
#[cfg(feature = "async")]
#[cfg(feature = "async")]
use crate::util::a_fetch_route;
#[cfg(feature = "async")]
use async_trait::async_trait;
use crate::traits::{FetchFrom, PropFetchable, GetFetchProp};
use crate::error::{Result};
#[cfg(feature = "clubs")]
use super::super::clubs::ClubMember;
use crate::http::Client;
use crate::http::routes::Route;
use crate::util::{auto_hashtag, fetch_route};
use crate::serde::{deserialize_number_from_string, one_default, oxffffff_default};
use super::super::common::StarPower;
use super::battlelog::{BattlePlayer};
#[cfg(feature = "rankings")]
use crate::PlayerRanking;
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Player {
#[serde(default)]
pub club: Option<PlayerClub>,
#[serde(default = "false_default")]
pub is_qualified_from_championship_challenge: bool,
#[serde(rename = "3vs3Victories")]
pub tvt_victories: usize,
#[serde(default)]
pub tag: String,
#[serde(default)]
pub name: String,
#[serde(default)] pub trophies: usize,
#[serde(default)] pub highest_trophies: usize,
#[serde(default = "one_default")]
pub exp_level: usize,
#[serde(default)] pub exp_points: usize,
#[serde(default)] pub power_play_points: usize,
#[serde(default)] pub highest_power_play_points: usize,
#[serde(default)] pub solo_victories: usize,
#[serde(default)] pub duo_victories: usize,
#[serde(default)] pub best_robo_rumble_time: usize,
#[serde(default)] pub best_time_as_big_brawler: usize,
#[serde(default)]
pub brawlers: Vec<PlayerBrawlerStat>,
#[serde(default = "oxffffff_default")]
#[serde(deserialize_with = "deserialize_number_from_string")] pub name_color: u64,
}
fn false_default() -> bool { false }
impl Default for Player {
fn default() -> Player {
Player {
club: None,
is_qualified_from_championship_challenge: false,
tvt_victories: 0,
tag: String::from(""),
name: String::from(""),
trophies: 0,
highest_trophies: 0,
exp_level: 1,
exp_points: 0,
power_play_points: 0,
highest_power_play_points: 0,
solo_victories: 0,
duo_victories: 0,
best_robo_rumble_time: 0,
best_time_as_big_brawler: 0,
brawlers: Vec::<PlayerBrawlerStat>::new(),
name_color: 0xff_ff_ff,
}
}
}
impl GetFetchProp for Player {
type Property = str;
fn get_fetch_prop(&self) -> &str { &*self.tag }
fn get_route(tag: &str) -> Route { Route::Player(auto_hashtag(tag)) }
}
#[cfg_attr(feature = "async", async_trait)]
impl PropFetchable for Player {
type Property = str;
fn fetch(client: &Client, tag: &str) -> Result<Player> {
let route = Self::get_route(tag);
fetch_route::<Player>(client, &route)
}
#[cfg(feature="async")]
async fn a_fetch(client: &Client, tag: &'async_trait str) -> Result<Player>
where Self: 'async_trait,
Self::Property: 'async_trait,
{
let route = Player::get_route(&tag);
a_fetch_route::<Player>(client, &route).await
}
}
#[cfg_attr(feature = "async", async_trait)]
#[cfg(feature = "clubs")]
impl FetchFrom<ClubMember> for Player {
fn fetch_from(client: &Client, member: &ClubMember) -> Result<Player> {
Player::fetch(client, &member.tag)
}
#[cfg(feature = "async")]
async fn a_fetch_from(client: &Client, member: &ClubMember) -> Result<Player> {
Player::a_fetch(client, &member.tag).await
}
}
#[cfg_attr(feature = "async", async_trait)]
impl FetchFrom<BattlePlayer> for Player {
fn fetch_from(client: &Client, b_player: &BattlePlayer) -> Result<Player> {
Player::fetch(client, &b_player.tag)
}
#[cfg(feature = "async")]
async fn a_fetch_from(client: &Client, b_player: &BattlePlayer) -> Result<Player> {
Player::a_fetch(client, &b_player.tag).await
}
}
#[cfg_attr(feature = "async", async_trait)]
#[cfg(feature = "rankings")]
impl FetchFrom<PlayerRanking> for Player {
fn fetch_from(client: &Client, p_ranking: &PlayerRanking) -> Result<Player> {
Player::fetch(client, &p_ranking.tag)
}
#[cfg(feature = "async")]
async fn a_fetch_from(client: &Client, p_ranking: &PlayerRanking) -> Result<Player> {
Player::a_fetch(client, &p_ranking.tag).await
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
pub struct PlayerClub {
#[serde(default)]
pub tag: String,
#[serde(default)]
pub name: String
}
impl Default for PlayerClub {
fn default() -> PlayerClub {
PlayerClub {
tag: String::from(""),
name: String::from("")
}
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlayerBrawlerStat {
#[serde(default)]
pub star_powers: Vec<StarPower>,
#[serde(default)] pub id: usize,
#[serde(default = "one_default")]
pub rank: u16,
#[serde(default)]
pub trophies: usize,
#[serde(default)] pub highest_trophies: usize,
#[serde(default = "one_default")]
pub power: u8,
#[serde(default)]
pub name: String,
}
impl Default for PlayerBrawlerStat {
fn default() -> PlayerBrawlerStat {
PlayerBrawlerStat {
star_powers: vec![],
id: 0,
rank: 1,
trophies: 0,
highest_trophies: 0,
power: 1,
name: String::from(""),
}
}
}
#[cfg(test)]
mod tests {
use std::result::Result as StdResult;
use super::{Player, PlayerClub, PlayerBrawlerStat, StarPower};
use crate::error::Error as BrawlError;
use serde_json;
#[test]
fn players_deser() -> StdResult<(), Box<dyn ::std::error::Error>> {
let player_json_s = r##"{
"tag": "#CCCCCC",
"name": "User",
"nameColor": "0xff1ba5f5",
"trophies": 13370,
"highestTrophies": 30000,
"powerPlayPoints": 200,
"highestPowerPlayPoints": 900,
"expLevel": 100,
"expPoints": 70000,
"isQualifiedFromChampionshipChallenge": false,
"3vs3Victories": 3333,
"soloVictories": 999,
"duoVictories": 333,
"bestRoboRumbleTime": 350,
"bestTimeAsBigBrawler": 250,
"club": {
"tag": "#888888",
"name": "Club"
},
"brawlers": [
{
"id": 16000000,
"name": "SHELLY",
"power": 9,
"rank": 20,
"trophies": 500,
"highestTrophies": 549,
"starPowers": []
},
{
"id": 16000001,
"name": "COLT",
"power": 10,
"rank": 18,
"trophies": 420,
"highestTrophies": 440,
"starPowers": [
{
"id": 23000138,
"name": "Magnum Special"
},
{
"id": 23000077,
"name": "Slick Boots"
}
]
}
]
}"##;
let player: Player = serde_json::from_str::<Player>(player_json_s)
.map_err(BrawlError::Json)?;
assert_eq!(
player,
Player {
tag: String::from("#CCCCCC"),
name: String::from("User"),
name_color: 0xff1ba5f5,
trophies: 13370,
highest_trophies: 30000,
power_play_points: 200,
highest_power_play_points: 900,
exp_level: 100,
exp_points: 70000,
is_qualified_from_championship_challenge: false,
tvt_victories: 3333,
solo_victories: 999,
duo_victories: 333,
best_robo_rumble_time: 350,
best_time_as_big_brawler: 250,
club: Some(PlayerClub {
tag: String::from("#888888"),
name: String::from("Club")
}),
brawlers: vec![
PlayerBrawlerStat {
id: 16000000,
name: String::from("SHELLY"),
power: 9,
rank: 20,
trophies: 500,
highest_trophies: 549,
star_powers: vec![]
},
PlayerBrawlerStat {
id: 16000001,
name: String::from("COLT"),
power: 10,
rank: 18,
trophies: 420,
highest_trophies: 440,
star_powers: vec![
StarPower {
id: 23000138,
name: String::from("Magnum Special")
},
StarPower {
id: 23000077,
name: String::from("Slick Boots")
}
]
},
]
}
);
Ok(())
}
}