use crate::body::{Body, ClothesItemC};
use crate::error::{RequestClothesOffErr, RequestClothesOnErr};
use crate::inventory::items::ClothesDescription;
use crate::utils::ClothesGroupC;
use crate::utils::event::{MessageQueue, Event};
use std::collections::HashMap;
use std::fmt;
use std::hash::{Hash, Hasher};
mod warmth;
mod wetness;
pub mod fluent;
impl Body {
pub fn register_clothes_groups(&self, groups: Vec<ClothesGroup>) {
for group in groups {
self.clothes_groups.borrow_mut().insert(group.name.to_string(), group);
}
}
pub(crate) fn request_clothes_on(&self, item_name: &String, data: &dyn ClothesDescription) -> Result<(), RequestClothesOnErr> {
{
let mut clothes = self.clothes.borrow_mut();
if clothes.contains(item_name) {
return Err(RequestClothesOnErr::AlreadyHaveThisItemOn);
}
clothes.push(item_name.to_string());
let mut cdata = self.clothes_data.borrow_mut();
cdata.insert(item_name.to_string(), ClothesItemC {
cold_resistance: data.cold_resistance(),
water_resistance: data.water_resistance()
});
}
self.refresh_clothes_group();
self.recalculate_warmth_level();
self.queue_message(Event::ClothesOn(item_name.to_string()));
Ok(())
}
pub(crate) fn request_clothes_off(&self, item_name: &String) -> Result<(), RequestClothesOffErr> {
{
let mut clothes = self.clothes.borrow_mut();
match clothes.iter().position(|x| x == item_name) {
Some(ind) => {
clothes.remove(ind);
},
None => {
return Err(RequestClothesOffErr::ItemIsNotOn);
}
}
let mut cdata = self.clothes_data.borrow_mut();
if cdata.contains_key(item_name) {
cdata.remove(item_name);
}
}
self.refresh_clothes_group();
self.recalculate_warmth_level();
self.queue_message(Event::ClothesOff(item_name.to_string()));
Ok(())
}
fn refresh_clothes_group(&self) {
match self.clothes_groups.borrow_mut().iter().find(|(_, group)|
(*group).has_complete(self.clothes.borrow().clone())) {
Some((key, g)) => {
self.clothes_group.replace(Some(ClothesGroupC {
name: key.to_string(),
bonus_cold_resistance: g.bonus_cold_resistance,
bonus_water_resistance: g.bonus_water_resistance
}))
},
None => self.clothes_group.replace(None)
};
}
}
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Default)]
pub struct ClothesItem {
pub name: String,
pub water_resistance: usize,
pub cold_resistance: usize
}
impl fmt::Display for ClothesItem {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name)
}
}
impl ClothesItem {
pub fn new(name: String, water_resistance: usize, cold_resistance: usize) -> Self {
ClothesItem {
name,
water_resistance,
cold_resistance
}
}
}
#[derive(Clone, PartialEq, Eq, Debug, Default)]
pub struct ClothesGroup {
pub name: String,
pub items: HashMap<String, ClothesItem>,
pub bonus_cold_resistance: usize,
pub bonus_water_resistance: usize
}
impl fmt::Display for ClothesGroup {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {} items", self.name, self.items.len())
}
}
impl Hash for ClothesGroup {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
self.items.iter().for_each(|(key, _)| key.hash(state));
self.bonus_cold_resistance.hash(state);
self.bonus_water_resistance.hash(state);
}
}
impl ClothesGroup {
pub fn new(name: String, items: Vec<ClothesItem>, bonus_cold_resistance: usize, bonus_water_resistance: usize) -> Self {
let mut items_map = HashMap::new();
for item in items {
items_map.insert(item.name.to_string(), item.clone());
}
ClothesGroup {
name,
items: items_map,
bonus_cold_resistance,
bonus_water_resistance
}
}
pub fn contains(&self, item_name: &String) -> bool { self.items.contains_key(item_name) }
pub fn has_complete(&self, items: Vec<String>) -> bool {
if items.len() == 0 { return false; }
for (key, _) in self.items.iter() {
if items.iter().all(|x| x != key) {
return false;
}
}
return true;
}
}