use std::collections::BTreeMap; use crate::entity::account::*; use crate::entity::character::*; use crate::entity::gateway::EntityGateway; use crate::entity::item::*; use std::sync::{Arc, Mutex}; #[derive(Clone)] pub struct InMemoryGateway { users: Arc>>, user_settings: Arc>>, characters: Arc>>, items: Arc>>, mag_feedings: Arc>>>, } impl InMemoryGateway { pub fn new() -> InMemoryGateway { InMemoryGateway { users: Arc::new(Mutex::new(BTreeMap::new())), user_settings: Arc::new(Mutex::new(BTreeMap::new())), characters: Arc::new(Mutex::new(BTreeMap::new())), items: Arc::new(Mutex::new(BTreeMap::new())), mag_feedings: Arc::new(Mutex::new(BTreeMap::new())), } } } #[async_trait::async_trait] impl EntityGateway for InMemoryGateway { async fn create_user(&mut self, user: NewUserAccountEntity) -> Option { let mut users = self.users.lock().unwrap(); let id = users .iter() .fold(0, |sum, (i, _)| std::cmp::max(sum, i.0)) + 1; let user = UserAccountEntity { id: UserAccountId(id), username: user.username, password: user.password, guildcard: user.guildcard, team_id: user.team_id, banned: user.banned, muted_until: user.muted_until, created_at: user.created_at, flags: user.flags, }; users.insert(user.id, user.clone()); Some(user) } async fn get_user_by_id(&self, id: UserAccountId) -> Option { let users = self.users.lock().unwrap(); users.get(&id).map(|k| k.clone()) } async fn get_user_by_name(&self, username: String) -> Option { let users = self.users.lock().unwrap(); users .iter() .find(|(_, k)| k.username == username) .map(|(_, k)| k.clone()) } async fn save_user(&mut self, user: &UserAccountEntity) { let mut users = self.users.lock().unwrap(); users.insert(user.id, user.clone()); } async fn create_user_settings(&mut self, settings: NewUserSettingsEntity) -> Option { let mut user_settings = self.user_settings.lock().unwrap(); let id = user_settings .iter() .fold(0, |sum, (i, _)| std::cmp::max(sum, i.0)) + 1; let new_settings = UserSettingsEntity { id: UserSettingsId(id), user_id: settings.user_id, settings: settings.settings, }; user_settings.insert(new_settings.id, new_settings.clone()); Some(new_settings) } async fn get_user_settings_by_user(&self, user: &UserAccountEntity) -> Option { let user_settings = self.user_settings.lock().unwrap(); user_settings .iter() .find(|(_, k)| k.user_id == user.id) .map(|(_, k)| k.clone()) } async fn get_characters_by_user(&self, user: &UserAccountEntity) -> [Option; 4] { let characters = self.characters.lock().unwrap(); let mut chars = [None; 4]; characters .iter() .filter(|(_, c)| c.user_id == user.id) .for_each(|(_, c)| chars[c.slot as usize] = Some(c.clone())); chars } async fn create_character(&mut self, character: NewCharacterEntity) -> Option { let mut characters = self.characters.lock().unwrap(); let id = characters .iter() .fold(0, |sum, (i, _)| std::cmp::max(sum, i.0)) + 1; let new_character = CharacterEntity { id: CharacterEntityId(id), user_id: character.user_id, slot: character.slot, name: character.name, exp: character.exp, char_class: character.char_class, section_id: character.section_id, appearance: character.appearance, techs: character.techs, config: character.config, info_board: character.info_board, guildcard: character.guildcard, materials: character.materials, tech_menu: character.tech_menu, meseta: character.meseta, bank_meseta: character.bank_meseta, }; characters.insert(new_character.id, new_character.clone()); Some(new_character) } async fn save_character(&mut self, char: &CharacterEntity) { let mut characters = self.characters.lock().unwrap(); characters.insert(char.id, char.clone()); } async fn get_guild_card_data_by_user(&self, user: &UserAccountEntity) -> GuildCardDataEntity { GuildCardDataEntity::new(user.id) } async fn create_item(&mut self, item: NewItemEntity) -> Option { let mut items = self.items.lock().unwrap(); let id = items .iter() .fold(0, |sum, (i, _)| std::cmp::max(sum, i.0)) + 1; let new_item = ItemEntity { id: ItemEntityId(id), location: item.location, item: item.item, }; items.insert(ItemEntityId(id), new_item.clone()); Some(new_item) } async fn save_item(&mut self, item: &ItemEntity) { let mut items = self.items.lock().unwrap(); items.insert(item.id, item.clone()); } async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) { self.items.lock().unwrap().get_mut(&item_id) .map(|item_entity| { item_entity.location = item_location }); } async fn feed_mag(&mut self, mag_item_id: &ItemEntityId, tool_item_id: &ItemEntityId) { self.mag_feedings.lock().unwrap() .entry(*mag_item_id) .or_insert(Vec::new()) .push(*tool_item_id); } async fn get_items_by_character(&self, character: &CharacterEntity) -> Vec { let items = self.items.lock().unwrap(); items .iter() .filter(|(_, k)| { match k.location { ItemLocation::Inventory{character_id, ..} => character_id == character.id, ItemLocation::Bank{character_id, ..} => character_id == character.id, _ => false } }) .map(|(_, k)| { k.clone() }) .map(|mut item| { item.item = match item.item { ItemDetail::Mag(mut mag) => { self.mag_feedings.lock().unwrap().get(&item.id).map(|mag_feedings| { for mag_feed_id in mag_feedings.iter() { items.get(&mag_feed_id).map(|mag_feed| { match mag_feed.item { ItemDetail::Tool(mag_feed) => mag.feed(mag_feed.tool), _ => {} } }); } }); ItemDetail::Mag(mag) } _ => item.item }; item }) .collect() } }