fish_lib/game/services/
specimen_service.rs

1use crate::data::species_data::SpeciesData;
2use crate::game::errors::resource::GameResourceError;
3use crate::game::errors::GameResult;
4use crate::game::repositories::specimen_repository::SpecimenRepositoryInterface;
5use crate::models::specimen::{NewSpecimen, Specimen};
6use crate::models::user::User;
7use std::sync::Arc;
8
9pub trait SpecimenServiceInterface: Send + Sync {
10    fn generate_and_save_specimen(
11        &self,
12        owner_user: &User,
13        species_data: Arc<SpeciesData>,
14    ) -> GameResult<Specimen>;
15
16    fn process_catch(&self, user: &User, species_data: Arc<SpeciesData>) -> GameResult<Specimen>;
17}
18
19pub struct SpecimenService {
20    specimen_repository: Arc<dyn SpecimenRepositoryInterface>,
21}
22
23impl SpecimenService {
24    pub fn new(specimen_repository: Arc<dyn SpecimenRepositoryInterface>) -> Self {
25        Self {
26            specimen_repository,
27        }
28    }
29}
30
31impl SpecimenServiceInterface for SpecimenService {
32    fn generate_and_save_specimen(
33        &self,
34        owner_user: &User,
35        species_data: Arc<SpeciesData>,
36    ) -> GameResult<Specimen> {
37        let new_fish = NewSpecimen::generate(owner_user.id, species_data.id);
38        self.specimen_repository
39            .create(new_fish)
40            .map_err(|e| match e.get_database_error() {
41                Some(db_error) if db_error.is_foreign_key_violation() => {
42                    GameResourceError::user_not_found(owner_user.external_id).into()
43                }
44                _ => e.into(),
45            })
46    }
47
48    fn process_catch(&self, user: &User, species_data: Arc<SpeciesData>) -> GameResult<Specimen> {
49        let fish = self.generate_and_save_specimen(user, species_data)?;
50        Ok(fish)
51    }
52}