Switching connection to a barycenter approach

This commit is contained in:
David Négrier 2020-04-29 22:41:48 +02:00
parent 5ffc5a420e
commit 2a8e3ea323
3 changed files with 60 additions and 36 deletions

View file

@ -1,6 +1,6 @@
import {MessageUserPosition} from "./Websocket/MessageUserPosition";
import { World } from "./World"; import { World } from "./World";
import { UserInterface } from "./UserInterface"; import { UserInterface } from "./UserInterface";
import {PositionInterface} from "_Model/PositionInterface";
export class Group { export class Group {
static readonly MAX_PER_GROUP = 4; static readonly MAX_PER_GROUP = 4;
@ -24,6 +24,25 @@ export class Group {
return this.users; 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 { isFull(): boolean {
return this.users.length >= Group.MAX_PER_GROUP; return this.users.length >= Group.MAX_PER_GROUP;
} }

View file

@ -0,0 +1,4 @@
export interface PositionInterface {
x: number,
y: number
}

View file

@ -4,6 +4,7 @@ import {Group} from "./Group";
import {Distance} from "./Distance"; import {Distance} from "./Distance";
import {UserInterface} from "./UserInterface"; import {UserInterface} from "./UserInterface";
import {ExSocketInterface} from "_Model/Websocket/ExSocketInterface"; import {ExSocketInterface} from "_Model/Websocket/ExSocketInterface";
import {PositionInterface} from "_Model/PositionInterface";
export class World { export class World {
static readonly MIN_DISTANCE = 160; static readonly MIN_DISTANCE = 160;
@ -47,17 +48,18 @@ export class World {
if (typeof user.group === 'undefined') { if (typeof user.group === 'undefined') {
// If the user is not part of a group: // If the user is not part of a group:
// should he join 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) { if (closestItem !== null) {
// Is the closest user part of a group? if (closestItem instanceof Group) {
if (typeof closestUser.group === 'undefined') { // Let's join the group!
closestItem.join(user);
} else {
let closestUser : UserInterface = closestItem;
let group: Group = new Group([ let group: Group = new Group([
user, user,
closestUser closestUser
], this.connectCallback, this.disconnectCallback); ], this.connectCallback, this.disconnectCallback);
} else {
closestUser.group.join(user);
} }
} }
@ -78,32 +80,16 @@ export class World {
* - close enough (distance <= MIN_DISTANCE) * - close enough (distance <= MIN_DISTANCE)
* - not in a group OR in a group that is not full * - 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 usersToBeGroupedWith: Distance[] = [];
let minimumDistanceFound: number = World.MIN_DISTANCE; let minimumDistanceFound: number = World.MIN_DISTANCE;
let matchingUser: UserInterface | null = null; let matchingItem: UserInterface | Group | null = null;
this.users.forEach(function(currentUser, userId) { 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) { if(currentUser === user) {
return; return;
} }
@ -111,13 +97,13 @@ export class World {
let distance = World.computeDistance(user, currentUser); // compute distance between peers. let distance = World.computeDistance(user, currentUser); // compute distance between peers.
if(distance <= minimumDistanceFound) { if(distance <= minimumDistanceFound) {
minimumDistanceFound = distance;
if (typeof currentUser.group === 'undefined' || !currentUser.group.isFull()) { matchingItem = currentUser;
}
/*if (typeof currentUser.group === 'undefined' || !currentUser.group.isFull()) {
// We found a user we can bind to. // We found a user we can bind to.
minimumDistanceFound = distance;
matchingUser = currentUser;
return; return;
} }*/
/* /*
if(context.groups.length > 0) { if(context.groups.length > 0) {
@ -148,11 +134,21 @@ export class World {
usersToBeGroupedWith.push(dist); 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 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)); 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[] /*getDistancesBetweenGroupUsers(group: Group): Distance[]
{ {
let i = 0; let i = 0;