Rename cluster -> net
This commit is contained in:
parent
a1966cfc70
commit
5d063859d9
2 changed files with 52 additions and 60 deletions
|
|
@ -12,13 +12,13 @@ use std::{
|
||||||
/// An in-memory representation of a Sandbox that is easy to modify.
|
/// An in-memory representation of a Sandbox that is easy to modify.
|
||||||
pub struct Sandbox {
|
pub struct Sandbox {
|
||||||
next_component: u32,
|
next_component: u32,
|
||||||
next_cluster: u32,
|
next_net: u32,
|
||||||
next_wire: u32,
|
next_wire: u32,
|
||||||
next_type: u16,
|
next_type: u16,
|
||||||
root_components: HashSet<ComponentId>,
|
root_components: HashSet<ComponentId>,
|
||||||
components: HashMap<ComponentId, ComponentInfo>,
|
components: HashMap<ComponentId, ComponentInfo>,
|
||||||
wires: HashMap<WireId, WireInfo>,
|
wires: HashMap<WireId, WireInfo>,
|
||||||
clusters: HashMap<ClusterId, ClusterInfo>,
|
nets: HashMap<NetId, NetInfo>,
|
||||||
component_types: HashMap<String, u16>,
|
component_types: HashMap<String, u16>,
|
||||||
mods: Vec<ModInfo>,
|
mods: Vec<ModInfo>,
|
||||||
}
|
}
|
||||||
|
|
@ -33,13 +33,13 @@ impl Sandbox {
|
||||||
fn with_meta_info(component_types: HashMap<String, u16>, mods: Vec<ModInfo>) -> Self {
|
fn with_meta_info(component_types: HashMap<String, u16>, mods: Vec<ModInfo>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
next_component: 1,
|
next_component: 1,
|
||||||
next_cluster: 0,
|
next_net: 0,
|
||||||
next_wire: 0,
|
next_wire: 0,
|
||||||
next_type: component_types.values().copied().max().unwrap_or(0),
|
next_type: component_types.values().copied().max().unwrap_or(0),
|
||||||
root_components: HashSet::new(),
|
root_components: HashSet::new(),
|
||||||
components: HashMap::new(),
|
components: HashMap::new(),
|
||||||
wires: HashMap::new(),
|
wires: HashMap::new(),
|
||||||
clusters: HashMap::new(),
|
nets: HashMap::new(),
|
||||||
component_types,
|
component_types,
|
||||||
mods,
|
mods,
|
||||||
}
|
}
|
||||||
|
|
@ -53,13 +53,13 @@ impl Sandbox {
|
||||||
rotation: component.rotation,
|
rotation: component.rotation,
|
||||||
children: HashSet::new(),
|
children: HashSet::new(),
|
||||||
inputs: repeat_with(|| PegInfo {
|
inputs: repeat_with(|| PegInfo {
|
||||||
cluster_id: self.make_cluster(),
|
net_id: self.make_net(),
|
||||||
wires: HashSet::new(),
|
wires: HashSet::new(),
|
||||||
})
|
})
|
||||||
.take(component.num_inputs as usize)
|
.take(component.num_inputs as usize)
|
||||||
.collect(),
|
.collect(),
|
||||||
outputs: repeat_with(|| PegInfo {
|
outputs: repeat_with(|| PegInfo {
|
||||||
cluster_id: self.make_cluster(),
|
net_id: self.make_net(),
|
||||||
wires: HashSet::new(),
|
wires: HashSet::new(),
|
||||||
})
|
})
|
||||||
.take(component.num_outputs as usize)
|
.take(component.num_outputs as usize)
|
||||||
|
|
@ -72,7 +72,7 @@ impl Sandbox {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal logic of `add_component` that is shared with savefile loading.
|
/// Internal logic of `add_component` that is shared with savefile loading.
|
||||||
/// Savefiles store the component and cluster IDs, so they can be directly
|
/// Savefiles store the component and net IDs, so they can be directly
|
||||||
/// passed instead of being allocated (as is done by `add_component`).
|
/// passed instead of being allocated (as is done by `add_component`).
|
||||||
fn insert_component(&mut self, id: ComponentId, info: ComponentInfo) {
|
fn insert_component(&mut self, id: ComponentId, info: ComponentInfo) {
|
||||||
// TODO bubble this error (could be triggered by an invalid savefile).
|
// TODO bubble this error (could be triggered by an invalid savefile).
|
||||||
|
|
@ -119,7 +119,7 @@ impl Sandbox {
|
||||||
addr_a: PegAddress,
|
addr_a: PegAddress,
|
||||||
addr_b: PegAddress,
|
addr_b: PegAddress,
|
||||||
rotation: f32,
|
rotation: f32,
|
||||||
cluster_id: Option<ClusterId>,
|
net_id: Option<NetId>,
|
||||||
) -> Result<WireId, AddWireError> {
|
) -> Result<WireId, AddWireError> {
|
||||||
// It is illegal to directly connect output pegs.
|
// It is illegal to directly connect output pegs.
|
||||||
if addr_a.peg_type == PegType::Output && addr_b.peg_type == PegType::Output {
|
if addr_a.peg_type == PegType::Output && addr_b.peg_type == PegType::Output {
|
||||||
|
|
@ -138,21 +138,21 @@ impl Sandbox {
|
||||||
return Ok(wire_id);
|
return Ok(wire_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
let cluster_id = match cluster_id {
|
let net_id = match net_id {
|
||||||
Some(id) => {
|
Some(id) => {
|
||||||
// If cluster ID is specified (i.e. from an existing savefile),
|
// If net ID is specified (i.e. from an existing savefile),
|
||||||
// check savefile validity: ensure that both endpoints and the
|
// check savefile validity: ensure that both endpoints and the
|
||||||
// wire all have the same cluster.
|
// wire all have the same net.
|
||||||
|
|
||||||
//TODO bubble this error
|
//TODO bubble this error
|
||||||
assert!(id == peg_a.cluster_id && id == peg_b.cluster_id);
|
assert!(id == peg_a.net_id && id == peg_b.net_id);
|
||||||
|
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// If no cluster ID is given (i.e. caller is `add_wire`), then
|
// If no net ID is given (i.e. caller is `add_wire`), then
|
||||||
// obtain one from merging the two endpoints.
|
// obtain one from merging the two endpoints.
|
||||||
self.merge_clusters(peg_a.cluster_id, peg_b.cluster_id)
|
self.merge_nets(peg_a.net_id, peg_b.net_id)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -164,19 +164,15 @@ impl Sandbox {
|
||||||
WireInfo {
|
WireInfo {
|
||||||
a: addr_a,
|
a: addr_a,
|
||||||
b: addr_b,
|
b: addr_b,
|
||||||
cluster_id,
|
net_id,
|
||||||
rotation,
|
rotation,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Register wire references in pegs and cluster.
|
// Register wire references in pegs and net.
|
||||||
self.get_peg_mut(&addr_a).unwrap().wires.insert(wire_id);
|
self.get_peg_mut(&addr_a).unwrap().wires.insert(wire_id);
|
||||||
self.get_peg_mut(&addr_b).unwrap().wires.insert(wire_id);
|
self.get_peg_mut(&addr_b).unwrap().wires.insert(wire_id);
|
||||||
self.clusters
|
self.nets.get_mut(&net_id).unwrap().wires.insert(wire_id);
|
||||||
.get_mut(&cluster_id)
|
|
||||||
.unwrap()
|
|
||||||
.wires
|
|
||||||
.insert(wire_id);
|
|
||||||
|
|
||||||
Ok(wire_id)
|
Ok(wire_id)
|
||||||
}
|
}
|
||||||
|
|
@ -186,7 +182,7 @@ impl Sandbox {
|
||||||
|
|
||||||
// TODO Remove component.
|
// TODO Remove component.
|
||||||
|
|
||||||
// TODO Remove peg-cluster cross-references. Remove clusters if empty.
|
// TODO Remove peg-net cross-references. Remove nets if empty.
|
||||||
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
@ -201,16 +197,12 @@ impl Sandbox {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove wire-cluster and wire-peg cross-references.
|
// Remove wire-net and wire-peg cross-references.
|
||||||
self.clusters
|
self.nets.get_mut(&wire.net_id).unwrap().wires.remove(&id);
|
||||||
.get_mut(&wire.cluster_id)
|
|
||||||
.unwrap()
|
|
||||||
.wires
|
|
||||||
.remove(&id);
|
|
||||||
self.get_peg_mut(&wire.a).unwrap().wires.remove(&id);
|
self.get_peg_mut(&wire.a).unwrap().wires.remove(&id);
|
||||||
self.get_peg_mut(&wire.b).unwrap().wires.remove(&id);
|
self.get_peg_mut(&wire.b).unwrap().wires.remove(&id);
|
||||||
|
|
||||||
// Split cluster if necessary.
|
// Split net if necessary.
|
||||||
self.check_split(&wire.a, &wire.b);
|
self.check_split(&wire.a, &wire.b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -226,38 +218,38 @@ impl Sandbox {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_cluster(&mut self) -> ClusterId {
|
fn make_net(&mut self) -> NetId {
|
||||||
let id = ClusterId(self.next_cluster);
|
let id = NetId(self.next_net);
|
||||||
self.next_cluster += 1;
|
self.next_net += 1;
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge_clusters(&mut self, id_a: ClusterId, id_b: ClusterId) -> ClusterId {
|
fn merge_nets(&mut self, id_a: NetId, id_b: NetId) -> NetId {
|
||||||
// Nothing needs to be done if the two clusters are the same.
|
// Nothing needs to be done if the two nets are the same.
|
||||||
if id_a == id_b {
|
if id_a == id_b {
|
||||||
return id_a;
|
return id_a;
|
||||||
}
|
}
|
||||||
|
|
||||||
let a = &self.clusters[&id_a];
|
let a = &self.nets[&id_a];
|
||||||
let b = &self.clusters[&id_b];
|
let b = &self.nets[&id_b];
|
||||||
// Merge the smaller cluster into the larger cluster.
|
// Merge the smaller net into the larger net.
|
||||||
let (id_dest, id_src) = if a.size() >= b.size() {
|
let (id_dest, id_src) = if a.size() >= b.size() {
|
||||||
(id_a, id_b)
|
(id_a, id_b)
|
||||||
} else {
|
} else {
|
||||||
(id_b, id_a)
|
(id_b, id_a)
|
||||||
};
|
};
|
||||||
|
|
||||||
let src = self.clusters.remove(&id_src).unwrap();
|
let src = self.nets.remove(&id_src).unwrap();
|
||||||
// Update cluster cross-references:
|
// Update net cross-references:
|
||||||
for wire_id in &src.wires {
|
for wire_id in &src.wires {
|
||||||
self.wires.get_mut(wire_id).unwrap().cluster_id = id_dest;
|
self.wires.get_mut(wire_id).unwrap().net_id = id_dest;
|
||||||
}
|
}
|
||||||
for peg_id in &src.pegs {
|
for peg_id in &src.pegs {
|
||||||
self.get_peg_mut(peg_id).unwrap().cluster_id = id_dest;
|
self.get_peg_mut(peg_id).unwrap().net_id = id_dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move references from src into dest:
|
// Move references from src into dest:
|
||||||
let dest = self.clusters.get_mut(&id_dest).unwrap();
|
let dest = self.nets.get_mut(&id_dest).unwrap();
|
||||||
dest.pegs.extend(src.pegs);
|
dest.pegs.extend(src.pegs);
|
||||||
dest.wires.extend(src.wires);
|
dest.wires.extend(src.wires);
|
||||||
|
|
||||||
|
|
@ -265,9 +257,9 @@ impl Sandbox {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_split(&mut self, addr_a: &PegAddress, addr_b: &PegAddress) {
|
fn check_split(&mut self, addr_a: &PegAddress, addr_b: &PegAddress) {
|
||||||
// Traverse the whole cluster connected to addr_a.
|
// Traverse the whole net connected to addr_a.
|
||||||
// If addr_b is in that set, then they are connected.
|
// If addr_b is in that set, then they are connected.
|
||||||
// If not, a new cluster needs to be created.
|
// If not, a new net needs to be created.
|
||||||
|
|
||||||
let mut frontier = Vec::new();
|
let mut frontier = Vec::new();
|
||||||
let mut visited_pegs = HashSet::new();
|
let mut visited_pegs = HashSet::new();
|
||||||
|
|
@ -297,14 +289,14 @@ impl Sandbox {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// B is not connected to A; make a new cluster and update all the
|
// B is not connected to A; make a new net and update all the
|
||||||
// pegs and wires found connected to A.
|
// pegs and wires found connected to A.
|
||||||
let cluster_id = self.make_cluster();
|
let net_id = self.make_net();
|
||||||
for peg_addr in visited_pegs {
|
for peg_addr in visited_pegs {
|
||||||
self.get_peg_mut(&peg_addr).unwrap().cluster_id = cluster_id;
|
self.get_peg_mut(&peg_addr).unwrap().net_id = net_id;
|
||||||
}
|
}
|
||||||
for wire_id in visited_wires {
|
for wire_id in visited_wires {
|
||||||
self.wires.get_mut(&wire_id).unwrap().cluster_id = cluster_id;
|
self.wires.get_mut(&wire_id).unwrap().net_id = net_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -390,9 +382,9 @@ impl ComponentId {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct ClusterId(u32);
|
pub struct NetId(u32);
|
||||||
|
|
||||||
impl ClusterId {
|
impl NetId {
|
||||||
fn into_raw(self) -> i32 {
|
fn into_raw(self) -> i32 {
|
||||||
self.0.try_into().unwrap()
|
self.0.try_into().unwrap()
|
||||||
}
|
}
|
||||||
|
|
@ -451,7 +443,7 @@ impl ComponentInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PegInfo {
|
struct PegInfo {
|
||||||
cluster_id: ClusterId,
|
net_id: NetId,
|
||||||
wires: HashSet<WireId>,
|
wires: HashSet<WireId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -459,16 +451,16 @@ struct PegInfo {
|
||||||
struct WireInfo {
|
struct WireInfo {
|
||||||
a: PegAddress,
|
a: PegAddress,
|
||||||
b: PegAddress,
|
b: PegAddress,
|
||||||
cluster_id: ClusterId,
|
net_id: NetId,
|
||||||
rotation: f32,
|
rotation: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ClusterInfo {
|
struct NetInfo {
|
||||||
wires: HashSet<WireId>,
|
wires: HashSet<WireId>,
|
||||||
pegs: HashSet<PegAddress>,
|
pegs: HashSet<PegAddress>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClusterInfo {
|
impl NetInfo {
|
||||||
fn size(&self) -> usize {
|
fn size(&self) -> usize {
|
||||||
self.wires.len() + self.pegs.len()
|
self.wires.len() + self.pegs.len()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ impl From<&blotter::BlotterFile> for super::Sandbox {
|
||||||
wire.start_peg.into(),
|
wire.start_peg.into(),
|
||||||
wire.end_peg.into(),
|
wire.end_peg.into(),
|
||||||
wire.rotation,
|
wire.rotation,
|
||||||
Some(super::ClusterId::from_raw(wire.circuit_state_id)),
|
Some(super::NetId::from_raw(wire.circuit_state_id)),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
@ -117,7 +117,7 @@ impl From<&blotter::Component> for (super::ComponentId, super::ComponentInfo) {
|
||||||
impl From<&super::PegInfo> for blotter::Input {
|
impl From<&super::PegInfo> for blotter::Input {
|
||||||
fn from(peg: &super::PegInfo) -> Self {
|
fn from(peg: &super::PegInfo) -> Self {
|
||||||
Self {
|
Self {
|
||||||
circuit_state_id: peg.cluster_id.into_raw(),
|
circuit_state_id: peg.net_id.into_raw(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -125,7 +125,7 @@ impl From<&super::PegInfo> for blotter::Input {
|
||||||
impl From<&blotter::Input> for super::PegInfo {
|
impl From<&blotter::Input> for super::PegInfo {
|
||||||
fn from(input: &blotter::Input) -> Self {
|
fn from(input: &blotter::Input) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cluster_id: super::ClusterId::from_raw(input.circuit_state_id),
|
net_id: super::NetId::from_raw(input.circuit_state_id),
|
||||||
wires: HashSet::new(),
|
wires: HashSet::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -134,7 +134,7 @@ impl From<&blotter::Input> for super::PegInfo {
|
||||||
impl From<&super::PegInfo> for blotter::Output {
|
impl From<&super::PegInfo> for blotter::Output {
|
||||||
fn from(peg: &super::PegInfo) -> Self {
|
fn from(peg: &super::PegInfo) -> Self {
|
||||||
Self {
|
Self {
|
||||||
circuit_state_id: peg.cluster_id.into_raw(),
|
circuit_state_id: peg.net_id.into_raw(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -142,7 +142,7 @@ impl From<&super::PegInfo> for blotter::Output {
|
||||||
impl From<&blotter::Output> for super::PegInfo {
|
impl From<&blotter::Output> for super::PegInfo {
|
||||||
fn from(input: &blotter::Output) -> Self {
|
fn from(input: &blotter::Output) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cluster_id: super::ClusterId::from_raw(input.circuit_state_id),
|
net_id: super::NetId::from_raw(input.circuit_state_id),
|
||||||
wires: HashSet::new(),
|
wires: HashSet::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -153,7 +153,7 @@ impl From<&super::WireInfo> for blotter::Wire {
|
||||||
Self {
|
Self {
|
||||||
start_peg: wire.a.into(),
|
start_peg: wire.a.into(),
|
||||||
end_peg: wire.b.into(),
|
end_peg: wire.b.into(),
|
||||||
circuit_state_id: wire.cluster_id.into_raw(),
|
circuit_state_id: wire.net_id.into_raw(),
|
||||||
rotation: wire.rotation,
|
rotation: wire.rotation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue