return this.users.length >= Group.MAX_PER_GROUP;
}
+ isEmpty(): boolean {
+ return this.users.length <= 1;
+ }
+
join(user: UserInterface): void
{
// Broadcast on the right event
return stillIn;
}
- removeFromGroup(users: UserInterface[]): void
+ /*removeFromGroup(users: UserInterface[]): void
{
for(let i = 0; i < users.length; i++){
let user = users[i];
this.users.splice(index, 1);
}
}
+ }*/
+
+ leave(user: UserInterface): void
+ {
+ const index = this.users.indexOf(user, 0);
+ if (index === -1) {
+ throw new Error("Could not find user in the group");
+ }
+
+ this.users.splice(index, 1);
+ user.group = undefined;
+
+ // Broadcast on the right event
+ this.users.forEach((groupUser: UserInterface) => {
+ this.disconnectCallback(user.id, groupUser.id);
+ });
+ }
+
+ /**
+ * Let's kick everybody out.
+ * Usually used when there is only one user left.
+ */
+ destroy(): void
+ {
+ this.users.forEach((user: UserInterface) => {
+ this.leave(user);
+ })
}
}
id: userPosition.userId,
position: userPosition.position
});
+ // Let's call update position to trigger the join / leave room
+ this.updatePosition(userPosition);
}
public leave(user : ExSocketInterface){
user,
closestUser
], this.connectCallback, this.disconnectCallback);
+ this.groups.push(group);
}
}
} else {
// If the user is part of a group:
- // should we split the group?
+ // should he leave the group?
+ let distance = World.computeDistanceBetweenPositions(user.position, user.group.getPosition());
+ if (distance > World.MIN_DISTANCE) {
+ this.leaveGroup(user);
+ }
+ }
+ }
- // TODO: analyze the group of the user:
- // => take one user. "walk the tree of users, each branch being a link<MIN_DISTANCE"
- // If some users are not in the subgroup, take the other user and loop
- // At the end, we will have a list of subgroups. From this list, we can send disconnect messages
+ /**
+ * Makes a user leave a group and closes and destroy the group if the group contains only one remaining person.
+ *
+ * @param user
+ */
+ private leaveGroup(user: UserInterface): void {
+ let group = user.group;
+ if (typeof group === 'undefined') {
+ throw new Error("The user is part of no group");
+ }
+ group.leave(user);
+ if (group.isEmpty()) {
+ group.destroy();
+ const index = this.groups.indexOf(group, 0);
+ if (index === -1) {
+ throw new Error("Could not find group");
+ }
+ this.groups.splice(index, 1);
}
}
return;
}
let distance = World.computeDistanceBetweenPositions(user.position, group.getPosition());
-
if(distance <= minimumDistanceFound) {
minimumDistanceFound = distance;
matchingItem = group;
expect(connectCalled).toBe(false);
});
+ it("should connect 3 users", () => {
+ let connectCalled: boolean = false;
+ let connect = (user1: string, user2: string): void => {
+ connectCalled = true;
+ }
+ let disconnect = (user1: string, user2: string): void => {
+
+ }
+
+ let world = new World(connect, disconnect);
+
+ world.join(new MessageUserPosition({
+ userId: "foo",
+ roomId: 1,
+ position: new Point(100, 100)
+ }));
+
+ world.join(new MessageUserPosition({
+ userId: "bar",
+ roomId: 1,
+ position: new Point(200, 100)
+ }));
+
+ expect(connectCalled).toBe(true);
+ connectCalled = false;
+
+ // baz joins at the outer limit of the group
+ world.join(new MessageUserPosition({
+ userId: "baz",
+ roomId: 1,
+ position: new Point(311, 100)
+ }));
+
+ expect(connectCalled).toBe(false);
+
+ world.updatePosition(new MessageUserPosition({
+ userId: "baz",
+ roomId: 1,
+ position: new Point(309, 100)
+ }));
+
+ expect(connectCalled).toBe(true);
+ });
+
it("should disconnect user1 and user2", () => {
let connectCalled: boolean = false;
let disconnectCalled: boolean = false;
position: new Point(259, 100)
}));
- expect(connectCalled).toBe(false);
+ expect(connectCalled).toBe(true);
+ expect(disconnectCalled).toBe(false);
world.updatePosition(new MessageUserPosition({
userId: "bar",
roomId: 1,
- position: new Point(261, 100)
+ position: new Point(100+160+160+1, 100)
}));
expect(disconnectCalled).toBe(true);