From 2a8e3ea3238682fd22319991f51ef37ee7ec0760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Wed, 29 Apr 2020 22:41:48 +0200 Subject: [PATCH] Switching connection to a barycenter approach --- back/src/Model/Group.ts | 21 ++++++++- back/src/Model/PositionInterface.ts | 4 ++ back/src/Model/World.ts | 71 +++++++++++++++-------------- 3 files changed, 60 insertions(+), 36 deletions(-) create mode 100644 back/src/Model/PositionInterface.ts diff --git a/back/src/Model/Group.ts b/back/src/Model/Group.ts index 795c0e8e..9f5c48c5 100644 --- a/back/src/Model/Group.ts +++ b/back/src/Model/Group.ts @@ -1,6 +1,6 @@ -import {MessageUserPosition} from "./Websocket/MessageUserPosition"; import { World } from "./World"; import { UserInterface } from "./UserInterface"; +import {PositionInterface} from "_Model/PositionInterface"; export class Group { static readonly MAX_PER_GROUP = 4; @@ -24,6 +24,25 @@ export class Group { return this.users; } + /** + * Returns the barycenter of all users (i.e. the center of the group) + */ + getPosition(): PositionInterface { + let x = 0; + let y = 0; + // Let's compute the barycenter of all users. + this.users.forEach((user: UserInterface) => { + x += user.position.x; + y += user.position.y; + }); + x /= this.users.length; + y /= this.users.length; + return { + x, + y + }; + } + isFull(): boolean { return this.users.length >= Group.MAX_PER_GROUP; } diff --git a/back/src/Model/PositionInterface.ts b/back/src/Model/PositionInterface.ts new file mode 100644 index 00000000..d3b0dd47 --- /dev/null +++ b/back/src/Model/PositionInterface.ts @@ -0,0 +1,4 @@ +export interface PositionInterface { + x: number, + y: number +} diff --git a/back/src/Model/World.ts b/back/src/Model/World.ts index 4a31e49b..32e1b383 100644 --- a/back/src/Model/World.ts +++ b/back/src/Model/World.ts @@ -4,6 +4,7 @@ import {Group} from "./Group"; import {Distance} from "./Distance"; import {UserInterface} from "./UserInterface"; import {ExSocketInterface} from "_Model/Websocket/ExSocketInterface"; +import {PositionInterface} from "_Model/PositionInterface"; export class World { static readonly MIN_DISTANCE = 160; @@ -47,17 +48,18 @@ export class World { if (typeof user.group === 'undefined') { // If the user is not part of a group: // should he join a group? - let closestUser: UserInterface|null = this.searchClosestAvailableUser(user); + let closestItem: UserInterface|Group|null = this.searchClosestAvailableUserOrGroup(user); - if (closestUser !== null) { - // Is the closest user part of a group? - if (typeof closestUser.group === 'undefined') { + if (closestItem !== null) { + if (closestItem instanceof Group) { + // Let's join the group! + closestItem.join(user); + } else { + let closestUser : UserInterface = closestItem; let group: Group = new Group([ user, closestUser ], this.connectCallback, this.disconnectCallback); - } else { - closestUser.group.join(user); } } @@ -78,32 +80,16 @@ export class World { * - close enough (distance <= MIN_DISTANCE) * - not in a group OR in a group that is not full */ - private searchClosestAvailableUser(user: UserInterface): UserInterface|null + private searchClosestAvailableUserOrGroup(user: UserInterface): UserInterface|Group|null { -/* - let sortedUsersByDistance: UserInteface[] = Array.from(this.users.values()).sort((user1: UserInteface, user2: UserInteface): number => { - let distance1 = World.computeDistance(user, user1); - let distance2 = World.computeDistance(user, user2); - return distance1 - distance2; - }); - - // The first element should be the current user (distance 0). Let's remove it. - if (sortedUsersByDistance[0] === user) { - sortedUsersByDistance.shift(); - } - - for(let i = 0; i < sortedUsersByDistance.length; i++) { - let currentUser = sortedUsersByDistance[i]; - let distance = World.computeDistance(currentUser, user); - if(distance > World.MIN_DISTANCE) { - return; - } - } -*/ let usersToBeGroupedWith: Distance[] = []; let minimumDistanceFound: number = World.MIN_DISTANCE; - let matchingUser: UserInterface | null = null; + let matchingItem: UserInterface | Group | null = null; this.users.forEach(function(currentUser, userId) { + // Let's only check users that are not part of a group + if (typeof currentUser.group !== 'undefined') { + return; + } if(currentUser === user) { return; } @@ -111,13 +97,13 @@ export class World { let distance = World.computeDistance(user, currentUser); // compute distance between peers. if(distance <= minimumDistanceFound) { - - if (typeof currentUser.group === 'undefined' || !currentUser.group.isFull()) { + minimumDistanceFound = distance; + matchingItem = currentUser; + } + /*if (typeof currentUser.group === 'undefined' || !currentUser.group.isFull()) { // We found a user we can bind to. - minimumDistanceFound = distance; - matchingUser = currentUser; return; - } + }*/ /* if(context.groups.length > 0) { @@ -148,11 +134,21 @@ export class World { usersToBeGroupedWith.push(dist); } */ + }); + + this.groups.forEach(function(group: Group) { + if (group.isFull()) { + return; } + let distance = World.computeDistanceBetweenPositions(user.position, group.getPosition()); - }, this.users); + if(distance <= minimumDistanceFound) { + minimumDistanceFound = distance; + matchingItem = group; + } + }); - return matchingUser; + return matchingItem; } public static computeDistance(user1: UserInterface, user2: UserInterface): number @@ -160,6 +156,11 @@ export class World { return Math.sqrt(Math.pow(user2.position.x - user1.position.x, 2) + Math.pow(user2.position.y - user1.position.y, 2)); } + public static computeDistanceBetweenPositions(position1: PositionInterface, position2: PositionInterface): number + { + return Math.sqrt(Math.pow(position2.x - position1.x, 2) + Math.pow(position2.y - position1.y, 2)); + } + /*getDistancesBetweenGroupUsers(group: Group): Distance[] { let i = 0;