Switching connection to a barycenter approach
This commit is contained in:
parent
5ffc5a420e
commit
2a8e3ea323
@ -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;
|
||||||
}
|
}
|
||||||
|
4
back/src/Model/PositionInterface.ts
Normal file
4
back/src/Model/PositionInterface.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export interface PositionInterface {
|
||||||
|
x: number,
|
||||||
|
y: number
|
||||||
|
}
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user