mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-03 02:25:55 +00:00
Configurations: a design keeps up to 2048 rules (#6221)
* Test: a design keeps several hundred configuration rules An assembly that switches a few hundred parts on and off, by two rules each, needs hundreds of rules; the saved-rule budget refused more than 128. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PsiqyXWBFGTCX9J51bhysc * Configurations: a design keeps up to 2048 rules Problem: a configuration table kept at most 128 rules. A rule drives one feature's suppression, so an assembly that switches a few hundred parts on and off (by two rules each) could not keep its rules. Copying rules for an independent component copy looked up each new id by scanning all rules, which a larger table makes slow. Solution: MAX_RULES is 2048; a copy looks its new ids up in a set of the ids taken. The docs say the new limit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PsiqyXWBFGTCX9J51bhysc --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
//! Configuration graph remapping for independent component copies.
|
||||
use super::{Column, ConfigTable};
|
||||
use crate::{DocError, Result};
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ConfigCloneMaps {
|
||||
@@ -102,6 +102,9 @@ impl ConfigTable {
|
||||
}
|
||||
}
|
||||
}
|
||||
// The ids taken so far, looked up rather than scanned: copies of rules whose ids share
|
||||
// their first 40 characters try one id after another.
|
||||
let mut taken: BTreeSet<String> = next.rules.iter().map(|rule| rule.id.clone()).collect();
|
||||
for rule in &self.rules {
|
||||
if let Some(mut copied) = rule.clone_for_targets(maps) {
|
||||
if next.rules.len() >= super::MAX_RULES {
|
||||
@@ -110,8 +113,9 @@ impl ConfigTable {
|
||||
let stem: String = rule.id.chars().take(40).collect();
|
||||
copied.id = (1..=super::MAX_RULES + 1)
|
||||
.map(|i| format!("{stem}_copy{i}"))
|
||||
.find(|id| !next.rules.iter().any(|rule| rule.id == *id))
|
||||
.find(|id| !taken.contains(id))
|
||||
.ok_or_else(|| DocError::Invalid("no configuration rule ID available".into()))?;
|
||||
taken.insert(copied.id.clone());
|
||||
copied.name = format!("{} (copy)", rule.name.chars().take(120).collect::<String>());
|
||||
next.rules.push(copied);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,9 @@ use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
pub const MAX_RULES: usize = 128;
|
||||
/// Most configuration rules a design keeps. A rule drives one feature's suppression, so an
|
||||
/// assembly that switches a few hundred parts on and off, by two rules each, needs hundreds.
|
||||
pub const MAX_RULES: usize = 2048;
|
||||
const MAX_NODES: usize = 64;
|
||||
const MAX_DEPTH: usize = 8;
|
||||
|
||||
@@ -626,7 +628,16 @@ mod tests {
|
||||
.unwrap();
|
||||
assert!(validate_rules_json(&serde_json::json!({"configs":{"rules":[valid.clone()]}})).is_ok());
|
||||
assert!(validate_rules_json(&serde_json::json!({"configs":{"rules":null}})).is_err());
|
||||
assert!(validate_rules_json(&serde_json::json!({"configs":{"rules":vec![valid.clone();129]}})).is_err());
|
||||
// An assembly that switches a few hundred parts on and off, by two rules each, keeps them.
|
||||
let many: Vec<Value> = (0..600)
|
||||
.map(|i| {
|
||||
let mut r = valid.clone();
|
||||
r["id"] = serde_json::json!(format!("r{i}"));
|
||||
r
|
||||
})
|
||||
.collect();
|
||||
assert!(validate_rules_json(&serde_json::json!({"configs":{"rules":many}})).is_ok());
|
||||
assert!(validate_rules_json(&serde_json::json!({"configs":{"rules":vec![valid.clone();MAX_RULES + 1]}})).is_err());
|
||||
let mut condition = serde_json::json!({"type":"always"});
|
||||
for _ in 0..8 {
|
||||
condition = serde_json::json!({"type":"not","condition":condition});
|
||||
@@ -690,7 +701,7 @@ mod tests {
|
||||
Value::Null,
|
||||
serde_json::json!([deep]),
|
||||
serde_json::json!([wide]),
|
||||
serde_json::json!(vec![valid; 129]),
|
||||
serde_json::json!(vec![valid; MAX_RULES + 1]),
|
||||
serde_json::json!([invalid_context]),
|
||||
] {
|
||||
let mut saved = serde_json::to_value(design()).unwrap();
|
||||
|
||||
@@ -147,7 +147,7 @@ or restrictions leave the previous document intact and explain the failure. Dele
|
||||
before removing the last row. Parameter renames update rule targets and expressions; rule
|
||||
references prevent parameter deletion until removed.
|
||||
|
||||
Tables support at most 128 rules; conditions allow eight levels and 64 nodes, and allowed
|
||||
Tables support at most 2048 rules; conditions allow eight levels and 64 nodes, and allowed
|
||||
value lists support up to 128 expressions. These bounds are checked before saved rules are
|
||||
decoded. Driven appearance/material rules and repeated fixed-point evaluation are outside
|
||||
the current rule scope.
|
||||
|
||||
Reference in New Issue
Block a user