142 lines
5.1 KiB
C#
142 lines
5.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace NanoBrain {
|
|
|
|
[Serializable]
|
|
public class ClusterArray : Nucleus {
|
|
|
|
public ClusterPrefab prefab;
|
|
public Cluster[] clusters;
|
|
|
|
public Dictionary<int, Cluster> thingClusters = new();
|
|
|
|
public ClusterArray(ClusterPrefab prefab, Cluster parent, int size, Nucleus receiver = null) {
|
|
this.prefab = prefab;
|
|
this.name = prefab.name;
|
|
this.clusters = new Cluster[size];
|
|
for (int ix = 0; ix < size; ix++) {
|
|
Cluster cluster = new(prefab, parent);
|
|
cluster.defaultOutput.AddReceiver(receiver);
|
|
cluster.clusterArray = this;
|
|
this.clusters[ix] = cluster;
|
|
}
|
|
}
|
|
|
|
public ClusterArray(ClusterPrefab prefab, ClusterPrefab parent, int size, Nucleus receiver = null) {
|
|
this.prefab = prefab;
|
|
this.name = prefab.name;
|
|
this.clusters = new Cluster[size];
|
|
for (int ix = 0; ix < size; ix++) {
|
|
Cluster cluster = new(prefab, parent);
|
|
cluster.defaultOutput.AddReceiver(receiver);
|
|
cluster.clusterArray = this;
|
|
this.clusters[ix] = cluster;
|
|
}
|
|
}
|
|
|
|
public override Nucleus ShallowCloneTo(Cluster parent) {
|
|
ClusterArray clone = new(this.prefab, parent, this.clusters.Length) {
|
|
clusterPrefab = this.clusterPrefab,
|
|
};
|
|
|
|
return clone;
|
|
}
|
|
|
|
public override Nucleus Clone(ClusterPrefab parent) {
|
|
ClusterArray clone = new(this.prefab, parent, this.clusters.Length) {
|
|
};
|
|
|
|
return clone;
|
|
}
|
|
|
|
public void Add(ClusterPrefab prefab) {
|
|
if (this.clusters.Length == 0) {
|
|
Debug.LogError("Empty perceptoid array, cannot add");
|
|
return;
|
|
}
|
|
int newLength = this.clusters.Length + 1;
|
|
Cluster[] newClusters = new Cluster[newLength];
|
|
|
|
string baseName = this.name;
|
|
int colonPos = baseName.IndexOf(":");
|
|
if (colonPos > 0)
|
|
baseName = baseName[..colonPos];
|
|
|
|
for (int i = 0; i < this.clusters.Length; i++)
|
|
newClusters[i] = this.clusters[i];
|
|
Cluster sourceCluster = this.clusters[0];
|
|
Cluster newCluster = sourceCluster.Clone(prefab) as Cluster;
|
|
newCluster.name = $"{baseName}: {newLength - 1}";
|
|
newCluster.clusterArray = this;
|
|
newClusters[newLength - 1] = newCluster;
|
|
this.clusters = newClusters;
|
|
}
|
|
|
|
public void Remove() {
|
|
int newLength = this.clusters.Length - 1;
|
|
if (newLength == 0) {
|
|
Debug.LogWarning("Perceptoid array cannot be empty");
|
|
return;
|
|
}
|
|
Cluster[] newClusters = new Cluster[newLength];
|
|
for (int i = 0; i < newLength; i++)
|
|
newClusters[i] = this.clusters[i];
|
|
// Delete the last perception
|
|
//Cluster.Delete(nucleus);
|
|
this.clusters = newClusters;
|
|
}
|
|
|
|
public override void UpdateStateIsolated() {
|
|
// Clusters don't do anything,
|
|
// The nuclei in them do the work
|
|
// and should be called directly, not from the cluster
|
|
}
|
|
|
|
public virtual Cluster GetThingCluster() {
|
|
Cluster selectedCluster = SelectCluster();
|
|
return selectedCluster;
|
|
}
|
|
public virtual Cluster GetThingCluster(int thingId, string thingName = null) {
|
|
if (thingClusters.TryGetValue(thingId, out Cluster cluster))
|
|
return cluster;
|
|
|
|
Cluster selectedCluster = SelectCluster();
|
|
thingClusters[thingId] = selectedCluster;
|
|
return selectedCluster;
|
|
}
|
|
|
|
private Cluster SelectCluster() {
|
|
// Find a sleeping cluster
|
|
foreach (Cluster cluster in clusters) {
|
|
if (cluster.defaultOutput.isSleeping) {
|
|
RemoveThingCluster(cluster);
|
|
return cluster;
|
|
}
|
|
}
|
|
|
|
// Otherwise find the stalest cluster?
|
|
Cluster stalestCluster = clusters[0];
|
|
for (int ix = 1; ix < clusters.Length; ix++) {
|
|
if (clusters[ix].defaultOutput.stale > stalestCluster.defaultOutput.stale)
|
|
stalestCluster = clusters[ix];
|
|
}
|
|
|
|
RemoveThingCluster(stalestCluster);
|
|
return stalestCluster;
|
|
}
|
|
|
|
private void RemoveThingCluster(Cluster cluster) {
|
|
List<int> keysToRemove = new();
|
|
foreach (KeyValuePair<int, Cluster> kvp in thingClusters) {
|
|
if (kvp.Value == cluster)
|
|
keysToRemove.Add(kvp.Key);
|
|
}
|
|
|
|
foreach (int thingId in keysToRemove)
|
|
thingClusters.Remove(thingId);
|
|
}
|
|
}
|
|
|
|
} |