Skip to content

Commit f43f541

Browse files
committed
rework name autogeneration to consistently use tags and support quality
1 parent 31f892f commit f43f541

1 file changed

Lines changed: 154 additions & 71 deletions

File tree

src/save.rs

Lines changed: 154 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -5,96 +5,152 @@ use std::{
55
path::{Path, PathBuf},
66
};
77

8-
pub fn save(mut json: serde_json::Value, dir: Option<&Path>) {
8+
fn format_tag(
9+
typ: &str,
10+
name: Option<&serde_json::Value>,
11+
quality: Option<&serde_json::Value>,
12+
) -> Option<String> {
13+
let name = name?.as_str()?;
14+
let quality_suffix = if let Some(quality) = quality
15+
&& let Some(quality) = quality.as_str()
16+
&& quality != "normal"
17+
{
18+
format!(",quality={quality}")
19+
} else {
20+
String::new()
21+
};
22+
Some(format!("[{typ}={name}{quality_suffix}]"))
23+
}
24+
25+
fn format_entity_tag(entity: &serde_json::Value) -> Option<String> {
26+
format_tag("entity", entity.get("name"), entity.get("quality"))
27+
}
28+
29+
fn format_icon_tag(icon: &serde_json::Value) -> Option<String> {
30+
format_tag("icon", icon.get("name"), icon.get("quality"))
31+
}
32+
33+
fn format_tile_tag(tile: &serde_json::Value) -> Option<String> {
34+
format_tag("tile", tile.get("name"), tile.get("quality"))
35+
}
36+
37+
fn unique_strings(iter: impl Iterator<Item = String>) -> impl Iterator<Item = String> {
38+
let mut seen: std::collections::HashSet<String> = std::collections::HashSet::new();
39+
iter.flat_map(move |s| {
40+
if seen.contains(&s) {
41+
None
42+
} else {
43+
seen.insert(s.clone());
44+
Some(s)
45+
}
46+
})
47+
}
48+
49+
fn compute_name(json: &serde_json::Value) -> String {
950
let mut name = String::new();
1051
if let Some(thing) = json
1152
.get("blueprint")
1253
.or(json.get("blueprint_book"))
1354
.or(json.get("upgrade_planner"))
1455
.or(json.get("deconstruction_planner"))
15-
&& let Some(label) = thing.get("label")
16-
&& let Some(label) = label.as_str()
1756
{
18-
name = label.to_owned();
19-
} else if let Some(blueprint) = json.get("blueprint")
20-
&& let Some(icons) = blueprint.get("icons")
21-
&& let Some(icons) = icons.as_array()
22-
{
23-
for icon in icons {
24-
if let Some(signal) = icon.get("signal")
25-
&& let Some(signal_name) = signal.get("name")
26-
&& let Some(signal_name) = signal_name.as_str()
27-
{
57+
if let Some(label) = thing.get("label")
58+
&& let Some(label) = label.as_str()
59+
{
60+
name = label.to_owned();
61+
} else if let Some(icons) = thing.get("icons").or(thing
62+
.get("settings")
63+
.and_then(|settings| settings.get("icons")))
64+
&& let Some(icons) = icons.as_array()
65+
{
66+
for icon in icons {
67+
if let Some(signal) = icon.get("signal")
68+
&& let Some(signal_name) = format_icon_tag(signal)
69+
{
70+
if !name.is_empty() {
71+
name.push(' ');
72+
}
73+
name.push_str(&signal_name);
74+
}
75+
}
76+
} else if let Some(blueprint) = json.get("deconstruction_planner")
77+
&& let Some(settings) = blueprint.get("settings")
78+
{
79+
let entities = settings.get("entity_filters");
80+
let entities = entities
81+
.iter()
82+
.flat_map(|e| e.as_array())
83+
.flatten()
84+
.flat_map(format_entity_tag);
85+
86+
let tiles = settings.get("tile_filters");
87+
let tiles = tiles
88+
.iter()
89+
.flat_map(|e| e.as_array())
90+
.flatten()
91+
.flat_map(format_tile_tag);
92+
93+
let mut iter = entities.chain(tiles).fuse();
94+
95+
for name_part in (&mut iter).take(4) {
2896
if !name.is_empty() {
2997
name.push(' ');
3098
}
31-
name.push_str(signal_name);
99+
name.push_str(&name_part);
32100
}
33-
}
34-
} else if let Some(blueprint) = json.get("deconstruction_planner")
35-
&& let Some(settings) = blueprint.get("settings")
36-
{
37-
let entities = settings.get("entity_filters");
38-
let entities = entities
39-
.iter()
40-
.flat_map(|e| e.as_array())
41-
.flatten()
42-
.flat_map(|e| e.get("name"))
43-
.flat_map(|e| e.as_str())
44-
.map(|entity_name| format!("[entity={entity_name}]"));
45-
46-
let tiles = settings.get("tile_filters");
47-
let tiles = tiles
48-
.iter()
49-
.flat_map(|e| e.as_array())
50-
.flatten()
51-
.flat_map(|e| e.get("name"))
52-
.flat_map(|e| e.as_str())
53-
.map(|tile_name| format!("[tile={tile_name}]"));
54-
55-
let mut iter = entities.chain(tiles).fuse();
56-
57-
for name_part in (&mut iter).take(4) {
58-
if !name.is_empty() {
59-
name.push(' ');
101+
if iter.next().is_some() {
102+
name.push_str(" …");
60103
}
61-
name.push_str(&name_part);
62-
}
63-
if iter.next().is_some() {
64-
name.push_str(" …");
65-
}
66-
} else if let Some(blueprint) = json.get("upgrade_planner")
67-
&& let Some(settings) = blueprint.get("settings")
68-
&& let Some(mappers) = settings.get("mappers")
69-
&& let Some(mappers) = mappers.as_array()
70-
{
71-
let mut iter = mappers.iter().fuse();
72-
for mapper in (&mut iter).take(4) {
73-
if let Some(to) = mapper.get("to")
74-
&& let Some(name_part) = to.get("name")
75-
&& let Some(name_part) = name_part.as_str()
76-
{
104+
} else if let Some(blueprint) = json.get("upgrade_planner")
105+
&& let Some(settings) = blueprint.get("settings")
106+
&& let Some(mappers) = settings.get("mappers")
107+
&& let Some(mappers) = mappers.as_array()
108+
{
109+
let mut iter = unique_strings(
110+
mappers
111+
.iter()
112+
.flat_map(|mapper| mapper.get("to"))
113+
.flat_map(|to| {
114+
let typ = to.get("type");
115+
if let Some(typ) = typ
116+
&& let Some(typ) = typ.as_str()
117+
&& let Some(name_part) =
118+
format_tag(typ, to.get("name"), to.get("quality"))
119+
{
120+
Some(name_part)
121+
} else if let Some(name_part) = to.get("name")
122+
&& let Some(name_part) = name_part.as_str()
123+
{
124+
Some(name_part.to_owned())
125+
} else {
126+
None
127+
}
128+
}),
129+
)
130+
.fuse();
131+
for name_part in (&mut iter).take(4) {
77132
if !name.is_empty() {
78133
name.push(' ');
79134
}
80-
if let Some(typ) = to.get("type")
81-
&& let Some(typ) = typ.as_str()
82-
&& typ == "entity"
83-
{
84-
name.push_str(&format!("[entity={name_part}]"));
85-
} else {
86-
name.push_str(&name_part);
87-
}
135+
name.push_str(&name_part);
136+
}
137+
if iter.next().is_some() {
138+
name.push_str(" …");
139+
}
140+
if !name.is_empty() {
141+
name = format!("Upgrade {name}");
88142
}
89-
}
90-
if !name.is_empty() {
91-
name = format!("Upgrade {name}");
92143
}
93144
}
94145

95146
if name.is_empty() {
96147
name = "Untitled".to_owned()
97148
};
149+
name
150+
}
151+
152+
pub fn save(mut json: serde_json::Value, dir: Option<&Path>) {
153+
let mut name = compute_name(&json);
98154

99155
if let Some(index) = json.get_mut("index")
100156
&& let Some(index) = index.as_number()
@@ -173,9 +229,9 @@ mod tests {
173229
let json = serde_json::Value::from_str(&json).expect("should contain valid json");
174230
save(json.clone(), Some(dir.path()));
175231
let files = read_dir_unwrap(dir.path());
176-
assert_eq!(files, &["selector-combinator.json"]);
232+
assert_eq!(files, &["[icon=selector-combinator].json"]);
177233
let written_json =
178-
std::fs::read_to_string(dir.path().join("selector-combinator.json")).unwrap();
234+
std::fs::read_to_string(dir.path().join("[icon=selector-combinator].json")).unwrap();
179235
let written_json = serde_json::Value::from_str(&written_json).unwrap();
180236
assert_eq!(written_json, json);
181237
}
@@ -192,7 +248,7 @@ mod tests {
192248
let subfiles = read_dir_unwrap(&dir.path().join("Untitled"));
193249
assert_eq!(subfiles, ["0 BP Name 1.json", "1 Nested Book", "book.json"]);
194250
let subsubfiles = read_dir_unwrap(&dir.path().join("Untitled/1 Nested Book"));
195-
assert_eq!(subsubfiles, ["6 bulk-inserter.json", "book.json"]);
251+
assert_eq!(subsubfiles, ["6 [icon=bulk-inserter].json", "book.json"]);
196252

197253
// TODO: when load is implemented, test that it can load everything back properly.
198254
}
@@ -229,4 +285,31 @@ mod tests {
229285
let written_json = serde_json::Value::from_str(&written_json).unwrap();
230286
assert_eq!(written_json, json);
231287
}
288+
289+
#[test]
290+
fn test_dedupe_names_upgrade_planner() {
291+
let bp = "0eNq1UMsKwjAQ/Jc9V5A+LA34JSIS2rUGmt2YbNVS8u8mYK968jaPZXaYFWY3ej3gxU2aCD2oFQKKGBpDxlY7hz7B0wpXzzZrsjgEBUhiZIECSNvMn8wD0q6/YZCk3mc9ZV8Bsbd6SlLP1mmvhdMbOEIsQPhLYBDE6ZOXbg0N+AK1j8XPKsbz/4vU8ZyJYGqyzbjbZizgkWYzTKCaQ9nVXde0VVPVbRnjGw8nfKM=";
292+
let json = crate::blueprint::blueprint_to_json(bp);
293+
let json = serde_json::Value::from_str(&json).expect("should contain valid json");
294+
assert_eq!(compute_name(&json), "Upgrade [entity=steel-chest]")
295+
}
296+
297+
#[test]
298+
fn test_upgrade_remove_module() {
299+
let bp = "0eNp1js0KwjAQhN9lzy1IfywN+CQiEsxaAtlkTbZiKXl3E7BHbzPfDrOzw8pL1Abv7LT3GEHtkFDE+iVVTZoZY5HXHZ4xUGWyMYICK0jQgNdUXWJE01Iwq8NCX6t2VrZy8CGSdgU9ArGOWkJ5AhfIDUj4W4fEsv3q2uSC1Lz1Bj+gTvlWTc2rY3977G/gXfba4EGN524e5nmc+rEfpi7nL1TiT8I=";
300+
let json = crate::blueprint::blueprint_to_json(bp);
301+
let json = serde_json::Value::from_str(&json).expect("should contain valid json");
302+
assert_eq!(compute_name(&json), "Upgrade [item=empty-module-slot]")
303+
}
304+
305+
#[test]
306+
fn test_upgrade_quality() {
307+
let bp = "0eNqVT1sKwjAQvMt+V5A+LA14EhHZtmsNdDcx3Yql5O4miAfwbx7M7M4Oq58CjnTzM4pQALPDQqpWpiVjRu8pJHjZ4R4cZ003T2CARK1uUIAgZ95bNzyQ+1RSwHPFObsGxAXGOUmDY48B1aUjcIZYgLr/61ZJPewk562M9AZzjNdMlDj73z2H354CXul/mwKmOZVd3XVNWzVV3ZYxfgDMH1WE";
308+
let json = crate::blueprint::blueprint_to_json(bp);
309+
let json = serde_json::Value::from_str(&json).expect("should contain valid json");
310+
assert_eq!(
311+
compute_name(&json),
312+
"Upgrade [entity=biochamber,quality=uncommon]"
313+
)
314+
}
232315
}

0 commit comments

Comments
 (0)