83 lines
2.2 KiB
JavaScript
83 lines
2.2 KiB
JavaScript
class GroupManager {
|
|
constructor() {
|
|
this.groups = new Map(); // groupId -> Set<pieceId>
|
|
this.pieceToGroup = new Map(); // pieceId -> groupId
|
|
this._nextId = 1;
|
|
}
|
|
|
|
createSingletonGroup(pieceId) {
|
|
const gid = this._nextId++;
|
|
this.groups.set(gid, new Set([pieceId]));
|
|
this.pieceToGroup.set(pieceId, gid);
|
|
return gid;
|
|
}
|
|
|
|
getGroupId(pieceId) {
|
|
return this.pieceToGroup.get(pieceId) ?? null;
|
|
}
|
|
|
|
/** Returns the Set<pieceId> for the group containing pieceId, or null. */
|
|
getGroup(pieceId) {
|
|
const gid = this.getGroupId(pieceId);
|
|
if (gid === null) return null;
|
|
return this.groups.get(gid) ?? null;
|
|
}
|
|
|
|
/** Returns all piece IDs in the same group as pieceId (including itself). */
|
|
getPeersOf(pieceId) {
|
|
return this.getGroup(pieceId) ?? new Set([pieceId]);
|
|
}
|
|
|
|
/**
|
|
* Merge the groups containing pieceIdA and pieceIdB into a single new group.
|
|
* @returns {number} the new group ID
|
|
*/
|
|
merge(pieceIdA, pieceIdB) {
|
|
const gidA = this.getGroupId(pieceIdA);
|
|
const gidB = this.getGroupId(pieceIdB);
|
|
if (gidA === null || gidB === null) return gidA ?? gidB;
|
|
if (gidA === gidB) return gidA; // already in the same group
|
|
|
|
const newGid = this._nextId++;
|
|
const members = new Set([...this.groups.get(gidA), ...this.groups.get(gidB)]);
|
|
this.groups.delete(gidA);
|
|
this.groups.delete(gidB);
|
|
this.groups.set(newGid, members);
|
|
members.forEach(id => this.pieceToGroup.set(id, newGid));
|
|
return newGid;
|
|
}
|
|
|
|
/** Total number of distinct locked groups. */
|
|
get groupCount() {
|
|
return this.groups.size;
|
|
}
|
|
|
|
/** Total number of tracked pieces. */
|
|
get pieceCount() {
|
|
return this.pieceToGroup.size;
|
|
}
|
|
|
|
/**
|
|
* Serialize to a plain array of arrays for localStorage.
|
|
* @returns {number[][]}
|
|
*/
|
|
serialize() {
|
|
return Array.from(this.groups.values()).map(set => Array.from(set));
|
|
}
|
|
|
|
/**
|
|
* Rebuild from serialized data.
|
|
* @param {number[][]} groupsList
|
|
*/
|
|
static deserialize(groupsList) {
|
|
const gm = new GroupManager();
|
|
groupsList.forEach(members => {
|
|
const gid = gm._nextId++;
|
|
const set = new Set(members);
|
|
gm.groups.set(gid, set);
|
|
members.forEach(id => gm.pieceToGroup.set(id, gid));
|
|
});
|
|
return gm;
|
|
}
|
|
}
|