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
use chrono::TimeZone;
use serde::{Deserialize, Serialize};

use crate::models::badge_urls::BadgeUrls;

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ClanCapitalRaidSeason {
    pub state: State,
    start_time: String,
    end_time: String,
    pub capital_total_loot: i32,
    pub raids_completed: i32,
    pub total_attacks: i32,
    pub enemy_districts_destroyed: i32,
    pub offensive_reward: i32,
    pub defensive_reward: i32,
    pub attack_log: Vec<AttackLog>,
    pub defense_log: Vec<DefenseLog>,
    pub members: Option<Vec<Member>>,
}

impl ClanCapitalRaidSeason {
    /// Returns the start time of this [`ClanCapitalRaidSeason`].
    ///
    /// # Panics
    ///
    /// Panics if parsing the start time fails, which should never happen.
    #[must_use]
    pub fn start_time(&self) -> chrono::DateTime<chrono::Utc> {
        chrono::Utc.from_utc_datetime(
            &chrono::NaiveDateTime::parse_from_str(&self.start_time, "%Y%m%dT%H%M%S.%fZ").unwrap(),
        )
    }

    /// Returns the end time of this [`ClanCapitalRaidSeason`].
    ///
    /// # Panics
    ///
    /// Panics if parsing the end time fails, which should never happen.
    #[must_use]
    pub fn end_time(&self) -> chrono::DateTime<chrono::Utc> {
        chrono::Utc.from_utc_datetime(
            &chrono::NaiveDateTime::parse_from_str(&self.end_time, "%Y%m%dT%H%M%S.%fZ").unwrap(),
        )
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct District {
    pub id: i32,
    pub name: DistrictName,
    pub destruction_percent: i32,
    pub attack_count: i32,
    pub total_looted: i32,
    pub attacks: Option<Vec<Attack>>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AttackLog {
    pub defender: Clan,
    pub attack_count: i32,
    pub district_count: i32,
    pub districts_destroyed: i32,
    pub districts: Vec<District>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DefenseLog {
    pub attacker: Clan,
    pub attack_count: i32,
    pub district_count: i32,
    pub districts_destroyed: i32,
    pub districts: Vec<District>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Attack {
    pub attacker: Attacker,
    pub destruction_percent: i32,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Attacker {
    pub tag: String,
    pub name: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Clan {
    pub tag: String,
    pub name: String,
    pub level: i32,
    pub badge_urls: BadgeUrls,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Member {
    pub tag: String,
    pub name: String,
    pub attacks: i32,
    pub attack_limit: i32,
    pub bonus_attack_limit: i32,
    pub capital_resources_looted: i32,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum DistrictName {
    #[serde(rename = "Capital Peak")]
    CapitalPeak,
    #[serde(rename = "Barbarian Camp")]
    BarbarianCamp,
    #[serde(rename = "Wizard Valley")]
    WizardValley,
    #[serde(rename = "Balloon Lagoon")]
    BalloonLagoon,
    #[serde(rename = "Builder's Workshop")]
    BuildersWorkshop,
    #[serde(rename = "Dragon Cliffs")]
    DragonCliffs,
    #[serde(rename = "Golem Quarry")]
    GolemQuarry,
    #[serde(rename = "Skeleton Park")]
    SkeletonPark,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum State {
    Ended,
    Ongoing,
}