nil_core/infrastructure/building/academy/
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;
15use nil_core_macros::Building;
16use recruit_queue::{AcademyRecruitOrder, AcademyRecruitQueue};
17use serde::{Deserialize, Serialize};
18
19#[derive(Building, Clone, Debug, Deserialize, Serialize)]
20#[serde(rename_all = "camelCase")]
21pub struct Academy {
22 level: BuildingLevel,
23 enabled: bool,
24 recruit_queue: AcademyRecruitQueue,
25}
26
27impl Academy {
28 pub const ID: BuildingId = BuildingId::Academy;
29
30 pub const MIN_LEVEL: BuildingLevel = BuildingLevel::ZERO;
31 pub const MAX_LEVEL: BuildingLevel = BuildingLevel::new(25);
32
33 pub const MIN_COST: Cost = Cost::new(500);
34 pub const MAX_COST: Cost = Cost::new(50_000);
35
36 pub const WOOD_RATIO: ResourceRatio = ResourceRatio::new(0.3);
37 pub const STONE_RATIO: ResourceRatio = ResourceRatio::new(0.4);
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(100);
43
44 pub const MIN_SCORE: Score = Score::new(16);
45 pub const MAX_SCORE: Score = Score::new(1272);
46
47 pub const INFRASTRUCTURE_REQUIREMENTS: InfrastructureRequirements =
48 InfrastructureRequirements::none();
49
50 pub fn recruit_queue(&self) -> &AcademyRecruitQueue {
51 &self.recruit_queue
52 }
53
54 pub(crate) fn recruit_queue_mut(&mut self) -> &mut AcademyRecruitQueue {
55 &mut self.recruit_queue
56 }
57
58 #[must_use]
59 pub(crate) fn process_queue(&mut self) -> Option<Vec<AcademyRecruitOrder>> {
60 if self.enabled {
61 let orders = self.recruit_queue.process(self.level.into());
62 (!orders.is_empty()).then_some(orders)
63 } else {
64 None
65 }
66 }
67
68 #[inline]
69 pub fn workforce(&self) -> Workforce {
70 Workforce::from(self.level)
71 }
72
73 pub fn turns_in_recruit_queue(&self) -> Option<f64> {
74 if self.level > 0u8 {
75 let turn = self.workforce();
76 let in_queue = self.recruit_queue.sum_pending_workforce();
77 Some(f64::from(in_queue) / f64::from(turn))
78 } else {
79 None
80 }
81 }
82}
83
84impl Default for Academy {
85 fn default() -> Self {
86 Self {
87 level: BuildingLevel::ZERO,
88 enabled: true,
89 recruit_queue: AcademyRecruitQueue::default(),
90 }
91 }
92}
93
94check_total_resource_ratio!(
95 Academy::WOOD_RATIO,
96 Academy::STONE_RATIO,
97 Academy::IRON_RATIO,
98);