Skip to content
4 changes: 2 additions & 2 deletions src/EStimLibrary/Core/Haptics/HapticSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public class HapticSession
/// <summary>
/// The global contact IDs that are currently wired to one or more leads.
/// </summary>
public SortedSet<int> WiredContacts => this._leadManager._WiredContacts;
public SortedSet<int> WiredContacts => this._leadManager.WiredContacts;
/// <summary>
/// The global contact IDs that are currently not wired to any leads.
/// </summary>
Expand All @@ -60,7 +60,7 @@ public class HapticSession
/// <summary>
/// The global output IDs that are currently wired to one or more leads.
/// </summary>
public SortedSet<int> WiredOutputs => this._leadManager._WiredOutputs;
public SortedSet<int> WiredOutputs => this._leadManager.WiredOutputs;
/// <summary>
/// The global output IDs that are currently not wired to any leads.
/// </summary>
Expand Down
80 changes: 46 additions & 34 deletions src/EStimLibrary/Core/HardwareInterfaces/LeadManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,30 @@ public class LeadManager : ResourceManager<Lead>
/// The global contact IDs that are currently wired to one or more leads.
/// Only valid IDs are added.
/// </summary>
internal SortedSet<int> _WiredContacts { get; private set; }
public SortedSet<int> WiredContacts => new(this._ContactLeadIdMap.Keys);
/// <summary>
/// The global output IDs that are currently wired to one or more leads.
/// Only valid IDs are added.
/// </summary>
internal SortedSet<int> _WiredOutputs { get; private set; }

public SortedSet<int> WiredOutputs => new(this._OutputLeadIdMap.Keys);
/// <summary>
/// A map of global contact IDs to the set of global lead IDs they are
/// involved in.
/// </summary>
protected Dictionary<int, SortedSet<int>> _ContactLeadIdMap;
/// <summary>
/// A map of global output IDs to the set of global lead IDs they are
/// involved in.
/// </summary>
protected Dictionary<int, SortedSet<int>> _OutputLeadIdMap;

//TODO? public Dictionary<int, int> ContactOutputMap { get; protected set; }

/// <summary>
/// Initialize an empty lead manager with no values initially stored.
/// </summary>
public LeadManager()
{
// Initialize wired ID sets.
this._WiredContacts = new();
this._WiredOutputs = new();

// Initialize empty dictionaries and a zero total count of contacts.
this._ContactLeadIdMap = new();
this._OutputLeadIdMap = new();
Expand All @@ -52,9 +58,8 @@ public LeadManager()
/// False if invalid or not wired.</returns>
public bool IsWiredContact(int contactId)
{
// Inherent ID validation bc only valid IDs will be added to
// WiredContacts.
return this._WiredContacts.Contains(contactId);
// Inherent ID validation bc only valid IDs will be in WiredContacts.
return this.WiredContacts.Contains(contactId);
}

/// <summary>
Expand All @@ -66,7 +71,8 @@ public bool IsWiredContact(int contactId)
/// False if invalid or not wired.</returns>
public bool IsWiredOutput(int outputId)
{
return this._WiredOutputs.Contains(outputId);
// Inherent ID validation bc only valid IDs will be in WiredOutputs.
return this.WiredOutputs.Contains(outputId);
}

/// <summary>
Expand All @@ -81,23 +87,25 @@ public bool IsWiredOutput(int outputId)
/// <returns>True if the lead could be added, False if not.</returns>
public bool TryAddLead(Lead lead, out int leadId)
{
// Get the next available lead ID and try adding the lead to the
// resource pool.
if (!this.TryGetNextAvailableId(out leadId) ||
!this.TryAddResource(leadId, lead))
// First lets check if the lead already has been given an Id
// If the lead has already been added return true and the lead's Id
if (this.Resources.ContainsValue(lead))
{
// Return early if failed.
// This is guaranteed to be the same as in the Resources since
// Leads are compared based on values and Id is a value.
leadId = lead.Id;
return true;
}
if (!(this.TryGetNextAvailableId(out leadId) &&
this.TryAddResource(leadId, lead)))
{
// We return early if this fails
return false;
}

// Actually set the lead's ID.
// Update the lead Id
lead._Id = leadId;

// Update extra internal structs. For all contacts and outputs:
// a) Mark as wired.
this._WiredContacts.UnionWith(lead.ContactSet);
this._WiredOutputs.UnionWith(lead.OutputSet);
// b) Add the lead ID to their list of leads.
// Update extra internal structs. For all contacts and outputs, add the
// lead ID to their list of leads.
// TODO: why need to make a copy to avoid collection mod? no mod tho...
// AND only an issue during debug
foreach (var contactId in lead.ContactSet.ToList())
Expand Down Expand Up @@ -203,21 +211,23 @@ public bool TryRemoveLead(int leadId, out Lead removedLead)
// Remove the lead ID from the contact's lead set.
var leadSet = this._ContactLeadIdMap[contactId];
leadSet.Remove(leadId);
// Remove the contact from the "wired" set if no leads left on it.
// If the contact is no longer connected to any leads, remove the
// contact entry entirely.
if (leadSet.Count == 0)
{
this._WiredContacts.Remove(contactId);
this._ContactLeadIdMap.Remove(contactId);
}
}
foreach (var outputId in removedLead.OutputSet)
{
// Remove the lead ID from the output's lead set.
var leadSet = this._OutputLeadIdMap[outputId];
leadSet.Remove(leadId);
// Remove the output from the "wired" set if no leads left on it.
// If the output is no longer connected to any leads, remove the
// output entry entirely.
if (leadSet.Count == 0)
{
this._WiredOutputs.Remove(outputId);
this._OutputLeadIdMap.Remove(outputId);
}
}

Expand All @@ -239,12 +249,13 @@ public bool TryRemoveLead(int leadId, out Lead removedLead)
/// not.</returns>
public bool TryRemoveLead(Lead lead, out int leadId, out Lead removedLead)
{
// Try to get the ID of the Lead (Leads are records: Equals by value).
// TODO: actually test if this int? and FirstOrDefault strategy works.
// Was having some troubles with it in another class where HasValue
// returned true but only because the default value (stored upon lookup
// failure) was technically a valid value by that check --> TEST TEST!!!
int? id = this.Resources.FirstOrDefault(kv => kv.Value.Equals(lead)).Key;
// Check if this Id is in the resources pool.
int? id = null;
if (this.Resources.ContainsKey(lead.Id))
{
// Set the Id of the lead to be removed.
id = lead.Id;
}
if (id.HasValue)
{
// Store the ID of the lead to be removed.
Expand All @@ -268,6 +279,7 @@ public bool TryRemoveLead(Lead lead, out int leadId, out Lead removedLead)
// so I/O calls can be handled by another class
public static void SaveMapToCSV(string outfile)
{

}

public static LeadManager LoadMapFromCSV(string infile)
Expand Down
Loading