2025-06-26 01:08:13 +03:00
|
|
|
use std::{collections::HashMap, fmt::Display};
|
2025-06-25 02:15:27 +03:00
|
|
|
|
2025-06-24 19:56:47 +03:00
|
|
|
use serde::Deserialize;
|
|
|
|
|
|
2025-06-26 01:08:13 +03:00
|
|
|
use super::enemy::{Enemy, EnemyDrop};
|
2025-06-24 19:56:47 +03:00
|
|
|
|
2025-06-26 01:08:13 +03:00
|
|
|
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
|
|
|
|
pub struct MaterialDetails {
|
|
|
|
|
pub category: String,
|
|
|
|
|
pub kind: MaterialKind,
|
2025-06-24 19:56:47 +03:00
|
|
|
}
|
|
|
|
|
|
2025-06-26 01:08:13 +03:00
|
|
|
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
|
|
|
|
#[serde(rename_all = "lowercase")]
|
|
|
|
|
pub enum MaterialKind {
|
|
|
|
|
Shard,
|
|
|
|
|
Stone,
|
|
|
|
|
Gem,
|
|
|
|
|
Crystal,
|
2025-06-25 02:15:27 +03:00
|
|
|
}
|
|
|
|
|
|
2025-06-26 01:08:13 +03:00
|
|
|
impl Display for MaterialKind {
|
2025-06-25 02:15:27 +03:00
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
match self {
|
2025-06-26 01:08:13 +03:00
|
|
|
MaterialKind::Shard => f.write_str("shard"),
|
|
|
|
|
MaterialKind::Stone => f.write_str("stone"),
|
|
|
|
|
MaterialKind::Gem => f.write_str("gem"),
|
|
|
|
|
MaterialKind::Crystal => f.write_str("crystal"),
|
2025-06-25 02:15:27 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-26 01:08:13 +03:00
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
2025-06-24 19:56:47 +03:00
|
|
|
pub struct MaterialDrops {
|
2025-06-26 01:08:13 +03:00
|
|
|
pub name: String,
|
|
|
|
|
pub icon: String,
|
|
|
|
|
pub category: String,
|
|
|
|
|
pub kind: MaterialKind,
|
|
|
|
|
pub drops: Vec<EnemyDrop>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PartialOrd for MaterialDrops {
|
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
|
|
|
if self.category.cmp(&other.category) == std::cmp::Ordering::Equal {
|
|
|
|
|
return Some(self.kind.cmp(&other.kind));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Some(self.category.cmp(&other.category))
|
|
|
|
|
}
|
2025-06-24 19:56:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl MaterialDrops {
|
2025-06-26 01:08:13 +03:00
|
|
|
pub fn new(enemies: Vec<Enemy>) -> Vec<MaterialDrops> {
|
|
|
|
|
let mut mat_map = HashMap::<(String, MaterialKind), MaterialDrops>::new();
|
|
|
|
|
|
|
|
|
|
for enemy in enemies {
|
|
|
|
|
for drop in &enemy.drops {
|
|
|
|
|
let Some(material) = &drop.material else {
|
|
|
|
|
continue;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let key = (material.category.clone(), material.kind.clone());
|
|
|
|
|
|
|
|
|
|
mat_map
|
|
|
|
|
.entry(key)
|
|
|
|
|
.and_modify(|d| d.drops.push(drop.clone()))
|
|
|
|
|
.or_insert(MaterialDrops {
|
|
|
|
|
name: drop.name.to_string(),
|
|
|
|
|
icon: "".to_string(),
|
|
|
|
|
category: material.category.clone(),
|
|
|
|
|
kind: material.kind.clone(),
|
|
|
|
|
drops: vec![drop.clone()],
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-06-25 02:15:27 +03:00
|
|
|
}
|
|
|
|
|
|
2025-06-26 01:08:13 +03:00
|
|
|
let mut values: Vec<MaterialDrops> = mat_map.into_values().collect();
|
|
|
|
|
|
|
|
|
|
values.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
|
|
|
|
|
|
|
|
|
values
|
2025-06-25 02:15:27 +03:00
|
|
|
}
|
|
|
|
|
|
2025-06-26 01:08:13 +03:00
|
|
|
pub fn drops(&self, kind: &str) -> Vec<&EnemyDrop> {
|
2025-06-24 19:56:47 +03:00
|
|
|
match kind {
|
2025-06-26 01:08:13 +03:00
|
|
|
"shard" => self.get_drop_kind(MaterialKind::Shard),
|
|
|
|
|
"stone" => self.get_drop_kind(MaterialKind::Stone),
|
|
|
|
|
"gem" => self.get_drop_kind(MaterialKind::Gem),
|
|
|
|
|
"crystal" => self.get_drop_kind(MaterialKind::Crystal),
|
|
|
|
|
_ => vec![],
|
2025-06-24 19:56:47 +03:00
|
|
|
}
|
|
|
|
|
}
|
2025-06-26 01:08:13 +03:00
|
|
|
|
|
|
|
|
fn get_drop_kind(&self, kind: MaterialKind) -> Vec<&EnemyDrop> {
|
|
|
|
|
self.drops
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|d| d.material.as_ref().map(|m| m.kind == kind).unwrap_or(false))
|
|
|
|
|
.collect::<Vec<&EnemyDrop>>()
|
|
|
|
|
}
|
2025-06-24 19:56:47 +03:00
|
|
|
}
|