fish_lib/models/
fishing_history_entry.rs1use crate::config::ConfigInterface;
2use crate::game::errors::resource::GameResourceError;
3use crate::game::errors::GameResult;
4use crate::traits::model::Model;
5use crate::utils::math::float_interpolate;
6use chrono::{DateTime, Utc};
7use diesel::{AsChangeset, Insertable, Queryable, Selectable};
8use serde::{Deserialize, Serialize};
9use std::sync::Arc;
10
11#[derive(
12 Debug, Default, Serialize, Deserialize, Clone, PartialEq, Queryable, Selectable, AsChangeset,
13)]
14#[diesel(table_name = crate::schema::fish_fishing_history_entries)]
15#[diesel(check_for_backend(diesel::pg::Pg))]
16pub struct FishingHistoryEntry {
17 pub id: i64,
19 pub user_id: i64,
21 pub species_id: i32,
23 pub created_at: DateTime<Utc>,
25 pub updated_at: DateTime<Utc>,
27 pub caught_count: i32,
29 pub sold_count: i32,
31 pub smallest_catch_size_ratio: f32,
33 pub largest_catch_size_ratio: f32,
35 pub last_catch: DateTime<Utc>,
37 pub first_sell: Option<DateTime<Utc>>,
39 pub last_sell: Option<DateTime<Utc>>,
41}
42
43impl FishingHistoryEntry {
44 pub fn get_first_catch(&self) -> DateTime<Utc> {
45 self.created_at
46 }
47
48 pub fn register_catch(&mut self, total_size_ratio: f32, catch_time: DateTime<Utc>) {
49 if total_size_ratio < self.smallest_catch_size_ratio {
50 self.smallest_catch_size_ratio = total_size_ratio;
51 } else if total_size_ratio > self.largest_catch_size_ratio {
52 self.largest_catch_size_ratio = total_size_ratio;
53 }
54 self.last_catch = catch_time;
55 self.caught_count = self.caught_count.saturating_add(1);
56 }
57
58 pub fn register_sell(&mut self, sell_time: DateTime<Utc>) {
59 if self.sold_count == 0 {
60 self.first_sell = Some(sell_time);
61 }
62 self.last_sell = Some(sell_time);
63 self.sold_count = self.sold_count.saturating_add(1);
64 }
65
66 pub fn get_smallest_size_mm(&self, config: Arc<dyn ConfigInterface>) -> GameResult<f32> {
67 let data = config
68 .get_species_data(self.species_id)
69 .ok_or_else(|| GameResourceError::species_not_found(self.species_id))?;
70 Ok(float_interpolate(
71 data.min_size_baby_mm as f32,
72 data.max_size_adult_mm as f32,
73 self.smallest_catch_size_ratio,
74 ))
75 }
76
77 pub fn get_largest_size_mm(&self, config: Arc<dyn ConfigInterface>) -> GameResult<f32> {
78 let data = config
79 .get_species_data(self.species_id)
80 .ok_or_else(|| GameResourceError::species_not_found(self.species_id))?;
81 Ok(float_interpolate(
82 data.min_size_baby_mm as f32,
83 data.max_size_adult_mm as f32,
84 self.largest_catch_size_ratio,
85 ))
86 }
87
88 pub fn get_smallest_weight_g(&self, config: Arc<dyn ConfigInterface>) -> GameResult<f32> {
89 let data = config
90 .get_species_data(self.species_id)
91 .ok_or_else(|| GameResourceError::species_not_found(self.species_id))?;
92 Ok(float_interpolate(
93 data.min_weight_baby_g as f32,
94 data.max_weight_adult_g as f32,
95 self.smallest_catch_size_ratio,
96 ))
97 }
98
99 pub fn get_largest_weight_g(&self, config: Arc<dyn ConfigInterface>) -> GameResult<f32> {
100 let data = config
101 .get_species_data(self.species_id)
102 .ok_or_else(|| GameResourceError::species_not_found(self.species_id))?;
103 Ok(float_interpolate(
104 data.min_weight_baby_g as f32,
105 data.max_weight_adult_g as f32,
106 self.largest_catch_size_ratio,
107 ))
108 }
109}
110
111impl Model for FishingHistoryEntry {
112 type Table = crate::schema::fish_fishing_history_entries::table;
113 type PrimaryKeyType = i64;
114 type InsertType = NewFishingHistoryEntry;
115
116 fn table() -> Self::Table {
117 crate::schema::fish_fishing_history_entries::table
118 }
119
120 fn id(&self) -> Self::PrimaryKeyType {
121 self.id
122 }
123}
124
125#[derive(Insertable)]
126#[diesel(table_name = crate::schema::fish_fishing_history_entries)]
127#[diesel(check_for_backend(diesel::pg::Pg))]
128pub struct NewFishingHistoryEntry {
129 pub user_id: i64,
130 pub species_id: i32,
131 pub caught_count: i32,
132 pub sold_count: i32,
133 pub smallest_catch_size_ratio: f32,
134 pub largest_catch_size_ratio: f32,
135}