use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SchemaResponse {
pub agents: Option<serde_json::Value>,
pub collectibles: Option<serde_json::Value>,
pub collections: Vec<Collection>,
pub containers: Option<serde_json::Value>,
pub custom_stickers: Option<serde_json::Value>,
pub highlight_reels: Option<serde_json::Value>,
pub keychains: Option<serde_json::Value>,
pub music_kits: Option<serde_json::Value>,
pub rarities: Option<serde_json::Value>,
pub stickers: Option<serde_json::Value>,
pub weapons: HashMap<String, Weapon>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Collection {
pub key: String,
pub name: String,
pub has_souvenir: Option<bool>,
pub has_crate: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Weapon {
pub name: String,
pub sticker_amount: u32,
#[serde(rename = "type")]
pub weapon_type: String,
pub faction: Option<String>,
pub paints: HashMap<String, Paint>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Paint {
pub index: u32,
pub max: f64,
pub min: f64,
pub rarity: u32,
pub name: String,
pub collection: Option<String>,
pub image: String,
pub stattrak: Option<bool>,
pub souvenir: Option<bool>,
pub normal_prices: Vec<u64>,
pub normal_volume: Vec<u64>,
pub stattrak_prices: Option<Vec<u64>>,
pub stattrak_volume: Option<Vec<u64>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WearCondition {
FactoryNew = 0,
MinimalWear = 1,
FieldTested = 2,
WellWorn = 3,
BattleScarred = 4,
}
impl WearCondition {
pub fn index(self) -> usize {
self as usize
}
pub fn as_str(self) -> &'static str {
match self {
WearCondition::FactoryNew => "Factory New",
WearCondition::MinimalWear => "Minimal Wear",
WearCondition::FieldTested => "Field-Tested",
WearCondition::WellWorn => "Well-Worn",
WearCondition::BattleScarred => "Battle-Scarred",
}
}
}
impl Paint {
pub fn price_for_wear(&self, wear: WearCondition) -> Option<u64> {
self.normal_prices.get(wear.index()).copied()
}
pub fn volume_for_wear(&self, wear: WearCondition) -> Option<u64> {
self.normal_volume.get(wear.index()).copied()
}
pub fn stattrak_price_for_wear(&self, wear: WearCondition) -> Option<u64> {
self.stattrak_prices
.as_ref()
.and_then(|prices| prices.get(wear.index()).copied())
}
pub fn stattrak_volume_for_wear(&self, wear: WearCondition) -> Option<u64> {
self.stattrak_volume
.as_ref()
.and_then(|volumes| volumes.get(wear.index()).copied())
}
pub fn has_stattrak(&self) -> bool {
self.stattrak.unwrap_or(false)
}
pub fn has_souvenir(&self) -> bool {
self.souvenir.unwrap_or(false)
}
pub fn float_range(&self) -> (f64, f64) {
(self.min, self.max)
}
}
impl Weapon {
pub fn get_paint_by_index(&self, index: u32) -> Option<&Paint> {
self.paints.values().find(|paint| paint.index == index)
}
pub fn get_paint_by_name(&self, name: &str) -> Option<&Paint> {
self.paints
.values()
.find(|paint| paint.name.to_lowercase() == name.to_lowercase())
}
pub fn paints_by_rarity(&self) -> Vec<&Paint> {
let mut paints: Vec<&Paint> = self.paints.values().collect();
paints.sort_by(|a, b| b.rarity.cmp(&a.rarity));
paints
}
}
impl SchemaResponse {
pub fn get_weapon(&self, weapon_id: &str) -> Option<&Weapon> {
self.weapons.get(weapon_id)
}
pub fn get_weapon_by_name(&self, name: &str) -> Option<(String, &Weapon)> {
self.weapons
.iter()
.find(|(_, weapon)| weapon.name.to_lowercase() == name.to_lowercase())
.map(|(id, weapon)| (id.clone(), weapon))
}
pub fn weapons_by_name(&self) -> Vec<(String, &Weapon)> {
let mut weapons: Vec<(String, &Weapon)> =
self.weapons.iter().map(|(id, weapon)| (id.clone(), weapon)).collect();
weapons.sort_by(|a, b| a.1.name.cmp(&b.1.name));
weapons
}
pub fn find_paint(&self, weapon_name: &str, paint_name: &str) -> Option<(&Weapon, &Paint)> {
self.get_weapon_by_name(weapon_name)
.and_then(|(_, weapon)| {
weapon.get_paint_by_name(paint_name)
.map(|paint| (weapon, paint))
})
}
}