nil_core/infrastructure/building/impl/stable/
mod.rs1pub mod recruit_catalog;
5pub mod recruit_queue;
6
7use crate::check_total_resource_ratio;
8use crate::infrastructure::building::{BuildingId, BuildingLevel};
9use crate::infrastructure::queue::InfrastructureQueue;
10use crate::infrastructure::requirements::InfrastructureRequirements;
11use crate::ranking::score::Score;
12use crate::resources::cost::{Cost, ResourceRatio};
13use crate::resources::maintenance::MaintenanceRatio;
14use crate::resources::workforce::{Workforce, WorkforceSource};
15use crate::world::config::WorldConfig;
16use nil_core_macros::Building;
17use recruit_queue::{StableRecruitOrder, StableRecruitQueue};
18use serde::{Deserialize, Serialize};
19
20#[derive(Building, Clone, Debug, Deserialize, Serialize)]
21#[serde(rename_all = "camelCase")]
22#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
23pub struct Stable {
24 level: BuildingLevel,
25 enabled: bool,
26 recruit_queue: StableRecruitQueue,
27}
28
29impl Stable {
30 pub const ID: BuildingId = BuildingId::Stable;
31
32 pub const MIN_LEVEL: BuildingLevel = BuildingLevel::ZERO;
33 pub const MAX_LEVEL: BuildingLevel = BuildingLevel::new(20);
34
35 pub const MIN_COST: Cost = Cost::new(1_500);
36 pub const MAX_COST: Cost = Cost::new(50_000);
37
38 pub const FOOD_RATIO: ResourceRatio = ResourceRatio::new(0.0);
39 pub const IRON_RATIO: ResourceRatio = ResourceRatio::new(0.3);
40 pub const STONE_RATIO: ResourceRatio = ResourceRatio::new(0.3);
41 pub const WOOD_RATIO: ResourceRatio = ResourceRatio::new(0.4);
42
43 pub const MAINTENANCE_RATIO: MaintenanceRatio = MaintenanceRatio::new(0.005);
44
45 pub const MIN_WORKFORCE: Workforce = Workforce::new(1);
46 pub const MAX_WORKFORCE: Workforce = Workforce::new(150);
47
48 pub const MIN_SCORE: Score = Score::new(20);
49 pub const MAX_SCORE: Score = Score::new(639);
50
51 pub const INFRASTRUCTURE_REQUIREMENTS: InfrastructureRequirements =
52 InfrastructureRequirements::builder()
53 .prefecture(BuildingLevel::new(3))
54 .academy(BuildingLevel::new(1))
55 .build();
56
57 pub fn recruit_queue(&self) -> &StableRecruitQueue {
58 &self.recruit_queue
59 }
60
61 pub(crate) fn recruit_queue_mut(&mut self) -> &mut StableRecruitQueue {
62 &mut self.recruit_queue
63 }
64
65 #[must_use]
66 pub(crate) fn process_queue(&mut self, config: &WorldConfig) -> Option<Vec<StableRecruitOrder>> {
67 if self.enabled {
68 let workforce = self.workforce(config);
69 let orders = self.recruit_queue.process(workforce);
70 (!orders.is_empty()).then_some(orders)
71 } else {
72 None
73 }
74 }
75
76 pub(crate) fn turns_in_recruit_queue(&self, config: &WorldConfig) -> Option<f64> {
77 if self.level > 0u8 {
78 let turn = self.workforce(config);
79 let in_queue = self.recruit_queue.sum_pending_workforce();
80 Some(f64::from(in_queue) / f64::from(turn))
81 } else {
82 None
83 }
84 }
85}
86
87impl WorkforceSource for Stable {}
88
89impl Default for Stable {
90 fn default() -> Self {
91 Self {
92 level: BuildingLevel::ZERO,
93 enabled: true,
94 recruit_queue: StableRecruitQueue::default(),
95 }
96 }
97}
98
99check_total_resource_ratio!(
100 Stable::FOOD_RATIO,
101 Stable::IRON_RATIO,
102 Stable::STONE_RATIO,
103 Stable::WOOD_RATIO
104);