1use std::collections::HashMap;
4
5use nms_core::biome::Biome;
6use nms_graph::GalaxyModel;
7
8#[derive(Debug, Clone, Default)]
10pub struct StatsQuery {
11 pub biomes: bool,
13 pub discoveries: bool,
15}
16
17#[derive(Debug, Clone)]
19pub struct StatsResult {
20 pub system_count: usize,
22 pub planet_count: usize,
24 pub base_count: usize,
26 pub biome_counts: HashMap<Biome, usize>,
28 pub unknown_biome_count: usize,
30 pub named_planet_count: usize,
32 pub named_system_count: usize,
34 pub infested_count: usize,
36}
37
38pub fn execute_stats(model: &GalaxyModel, _query: &StatsQuery) -> StatsResult {
40 let mut biome_counts: HashMap<Biome, usize> = HashMap::new();
41 let mut unknown_biome_count = 0;
42 let mut named_planet_count = 0;
43 let mut infested_count = 0;
44
45 for planet in model.planets.values() {
46 match planet.biome {
47 Some(biome) => *biome_counts.entry(biome).or_default() += 1,
48 None => unknown_biome_count += 1,
49 }
50 if planet.name.is_some() {
51 named_planet_count += 1;
52 }
53 if planet.infested {
54 infested_count += 1;
55 }
56 }
57
58 let named_system_count = model.systems.values().filter(|s| s.name.is_some()).count();
59
60 StatsResult {
61 system_count: model.system_count(),
62 planet_count: model.planet_count(),
63 base_count: model.base_count(),
64 biome_counts,
65 unknown_biome_count,
66 named_planet_count,
67 named_system_count,
68 infested_count,
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 fn test_model() -> GalaxyModel {
77 let json = r#"{
78 "Version": 4720, "Platform": "Mac|Final", "ActiveContext": "Main",
79 "CommonStateData": {"SaveName": "Test", "TotalPlayTime": 100},
80 "BaseContext": {"GameMode": 1, "PlayerStateData": {"UniverseAddress": {"RealityIndex": 0, "GalacticAddress": {"VoxelX": 0, "VoxelY": 0, "VoxelZ": 0, "SolarSystemIndex": 1, "PlanetIndex": 0}}, "Units": 0, "Nanites": 0, "Specials": 0, "PersistentPlayerBases": []}},
81 "ExpeditionContext": {"GameMode": 6, "PlayerStateData": {"UniverseAddress": {"RealityIndex": 0, "GalacticAddress": {"VoxelX": 0, "VoxelY": 0, "VoxelZ": 0, "SolarSystemIndex": 0, "PlanetIndex": 0}}, "Units": 0, "Nanites": 0, "Specials": 0, "PersistentPlayerBases": []}},
82 "DiscoveryManagerData": {"DiscoveryData-v1": {"ReserveStore": 0, "ReserveManaged": 0, "Store": {"Record": [
83 {"DD": {"UA": "0x001000000064", "DT": "SolarSystem", "VP": []}, "DM": {}, "OWS": {"LID":"","UID":"1","USN":"A","PTK":"ST","TS":0}, "FL": {"U": 1}},
84 {"DD": {"UA": "0x101000000064", "DT": "Planet", "VP": ["0xAB", 0]}, "DM": {}, "OWS": {"LID":"","UID":"1","USN":"A","PTK":"ST","TS":0}, "FL": {"U": 1}},
85 {"DD": {"UA": "0x201000000064", "DT": "Planet", "VP": ["0xCD", 0]}, "DM": {}, "OWS": {"LID":"","UID":"1","USN":"A","PTK":"ST","TS":0}, "FL": {"U": 1}}
86 ]}}}
87 }"#;
88 nms_save::parse_save(json.as_bytes())
89 .map(|save| GalaxyModel::from_save(&save))
90 .unwrap()
91 }
92
93 #[test]
94 fn test_stats_basic_counts() {
95 let model = test_model();
96 let query = StatsQuery {
97 biomes: true,
98 discoveries: true,
99 };
100 let stats = execute_stats(&model, &query);
101 assert_eq!(stats.system_count, 1);
102 assert_eq!(stats.planet_count, 2);
103 }
104
105 #[test]
106 fn test_stats_biome_counts_sum() {
107 let model = test_model();
108 let stats = execute_stats(&model, &StatsQuery::default());
109 let total: usize = stats.biome_counts.values().sum::<usize>() + stats.unknown_biome_count;
110 assert_eq!(total, stats.planet_count);
111 }
112}