First working version with disconnection

This commit is contained in:
David Négrier 2020-04-29 23:12:55 +02:00
parent 2a8e3ea323
commit bf0fa516d4
3 changed files with 107 additions and 9 deletions

View File

@ -47,6 +47,10 @@ export class Group {
return this.users.length >= Group.MAX_PER_GROUP; return this.users.length >= Group.MAX_PER_GROUP;
} }
isEmpty(): boolean {
return this.users.length <= 1;
}
join(user: UserInterface): void join(user: UserInterface): void
{ {
// Broadcast on the right event // Broadcast on the right event
@ -79,7 +83,7 @@ export class Group {
return stillIn; return stillIn;
} }
removeFromGroup(users: UserInterface[]): void /*removeFromGroup(users: UserInterface[]): void
{ {
for(let i = 0; i < users.length; i++){ for(let i = 0; i < users.length; i++){
let user = users[i]; let user = users[i];
@ -88,5 +92,32 @@ export class Group {
this.users.splice(index, 1); 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);
})
} }
} }

View File

@ -29,6 +29,8 @@ export class World {
id: userPosition.userId, id: userPosition.userId,
position: userPosition.position position: userPosition.position
}); });
// Let's call update position to trigger the join / leave room
this.updatePosition(userPosition);
} }
public leave(user : ExSocketInterface){ public leave(user : ExSocketInterface){
@ -60,18 +62,39 @@ export class World {
user, user,
closestUser closestUser
], this.connectCallback, this.disconnectCallback); ], this.connectCallback, this.disconnectCallback);
this.groups.push(group);
} }
} }
} else { } else {
// If the user is part of a group: // 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" * Makes a user leave a group and closes and destroy the group if the group contains only one remaining person.
// 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 * @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);
} }
} }
@ -141,7 +164,6 @@ export class World {
return; return;
} }
let distance = World.computeDistanceBetweenPositions(user.position, group.getPosition()); let distance = World.computeDistanceBetweenPositions(user.position, group.getPosition());
if(distance <= minimumDistanceFound) { if(distance <= minimumDistanceFound) {
minimumDistanceFound = distance; minimumDistanceFound = distance;
matchingItem = group; matchingItem = group;

View File

@ -54,6 +54,50 @@ describe("World", () => {
expect(connectCalled).toBe(false); 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", () => { it("should disconnect user1 and user2", () => {
let connectCalled: boolean = false; let connectCalled: boolean = false;
let disconnectCalled: boolean = false; let disconnectCalled: boolean = false;
@ -78,12 +122,13 @@ describe("World", () => {
position: new Point(259, 100) position: new Point(259, 100)
})); }));
expect(connectCalled).toBe(false); expect(connectCalled).toBe(true);
expect(disconnectCalled).toBe(false);
world.updatePosition(new MessageUserPosition({ world.updatePosition(new MessageUserPosition({
userId: "bar", userId: "bar",
roomId: 1, roomId: 1,
position: new Point(261, 100) position: new Point(100+160+160+1, 100)
})); }));
expect(disconnectCalled).toBe(true); expect(disconnectCalled).toBe(true);