Skip to main content

nil_core/infrastructure/building/stable/
mod.rs

1// Copyright (C) Call of Nil contributors
2// SPDX-License-Identifier: AGPL-3.0-only
3
4pub 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;
15use nil_core_macros::Building;
16use recruit_queue::{StableRecruitOrder, StableRecruitQueue};
17use serde::{Deserialize, Serialize};
18
19#[derive(Building, Clone, Debug, Deserialize, Serialize)]
20#[serde(rename_all = "camelCase")]
21pub struct Stable {
22  level: BuildingLevel,
23  enabled: bool,
24  recruit_queue: StableRecruitQueue,
25}
26
27impl Stable {
28  pub const ID: BuildingId = BuildingId::Stable;
29
30  pub const MIN_LEVEL: BuildingLevel = BuildingLevel::ZERO;
31  pub const MAX_LEVEL: BuildingLevel = BuildingLevel::new(20);
32
33  pub const MIN_COST: Cost = Cost::new(1_500);
34  pub const MAX_COST: Cost = Cost::new(50_000);
35
36  pub const WOOD_RATIO: ResourceRatio = ResourceRatio::new(0.4);
37  pub const STONE_RATIO: ResourceRatio = ResourceRatio::new(0.3);
38  pub const IRON_RATIO: ResourceRatio = ResourceRatio::new(0.3);
39  pub const MAINTENANCE_RATIO: MaintenanceRatio = MaintenanceRatio::new(0.005);
40
41  pub const MIN_WORKFORCE: Workforce = Workforce::new(1);
42  pub const MAX_WORKFORCE: Workforce = Workforce::new(150);
43
44  pub const MIN_SCORE: Score = Score::new(20);
45  pub const MAX_SCORE: Score = Score::new(639);
46
47  pub const INFRASTRUCTURE_REQUIREMENTS: InfrastructureRequirements =
48    InfrastructureRequirements::builder()
49      .prefecture(BuildingLevel::new(3))
50      .academy(BuildingLevel::new(1))
51      .build();
52
53  pub fn recruit_queue(&self) -> &StableRecruitQueue {
54    &self.recruit_queue
55  }
56
57  pub(crate) fn recruit_queue_mut(&mut self) -> &mut StableRecruitQueue {
58    &mut self.recruit_queue
59  }
60
61  #[must_use]
62  pub(crate) fn process_queue(&mut self) -> Option<Vec<StableRecruitOrder>> {
63    if self.enabled {
64      let orders = self.recruit_queue.process(self.level.into());
65      (!orders.is_empty()).then_some(orders)
66    } else {
67      None
68    }
69  }
70
71  #[inline]
72  pub fn workforce(&self) -> Workforce {
73    Workforce::from(self.level)
74  }
75
76  pub fn turns_in_recruit_queue(&self) -> Option<f64> {
77    if self.level > 0u8 {
78      let turn = self.workforce();
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 Default for Stable {
88  fn default() -> Self {
89    Self {
90      level: BuildingLevel::ZERO,
91      enabled: true,
92      recruit_queue: StableRecruitQueue::default(),
93    }
94  }
95}
96
97check_total_resource_ratio!(Stable::WOOD_RATIO, Stable::STONE_RATIO, Stable::IRON_RATIO);