From 0434e141e71004130394d4116d13261e6a1c185e Mon Sep 17 00:00:00 2001 From: David MAECHLER Date: Sat, 4 Apr 2020 21:00:59 +0200 Subject: [PATCH 1/9] WIP : created a position.js file with all util methods, now needs to implement it in typescript --- back/src/Controller/PositionController.ts | 1 + back/src/Controller/position.js | 88 +++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 back/src/Controller/PositionController.ts create mode 100644 back/src/Controller/position.js diff --git a/back/src/Controller/PositionController.ts b/back/src/Controller/PositionController.ts new file mode 100644 index 00000000..0ffdd02f --- /dev/null +++ b/back/src/Controller/PositionController.ts @@ -0,0 +1 @@ +// TODO \ No newline at end of file diff --git a/back/src/Controller/position.js b/back/src/Controller/position.js new file mode 100644 index 00000000..8c445b14 --- /dev/null +++ b/back/src/Controller/position.js @@ -0,0 +1,88 @@ +// Constants +let MIN_DISTANCE = 80; +let MAX_PER_GROUP = 3; +let NB_USERS = 10; + +// Utils +let rand = function(min, max) { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min + 1)) + min; +}; + +// Test Data +let users = []; +for(let i = 1; i <= NB_USERS; i++) { + let user = {}; + user.id = rand(0,99999); + user.X = rand(0, 60); + user.Y = rand(0, 60); + users.push(user); +} + +// Compute distance between each user +let computeDistance = function(users) { + let i = 0; + let distances = []; + + users.forEach(function(user1, key1) { + users.forEach(function(user2, key2) { + if(key1 !== key2 && key1 < key2) { + let distanceObj = {}; + distanceObj.distance = Math.sqrt(Math.pow(user2.X - user1.X, 2) + Math.pow(user2.Y - user1.Y, 2)); + distanceObj.first = user1; + distanceObj.second = user2; + + distances[i] = distanceObj; + i++; + } + }); + }); + + return distances; +}; + +// Organise groups +let createGroups = function(distances) { + let i = 0; + let groups = []; + let alreadyInGroup = []; + + for(let j = 0; j < distances.length; j++) { + let dist = distances[i]; + if(dist.distance <= MIN_DISTANCE) { + if(typeof groups[i] === 'undefined') { + groups[i] = []; + } + + if(groups[i].indexOf(dist.first) && typeof alreadyInGroup[dist.first.id] === 'undefined') { + groups[i].push(dist.first); + alreadyInGroup [dist.first.id] = true; + } + + if(groups[i].length === MAX_PER_GROUP) { + i++; // on créé un nouveau groupe + if(i > (NB_USERS / MAX_PER_GROUP)) { + console.log('There is no room left for user ID : ' + dist.second.id + ' !'); + break; + } + continue; + } + + if(groups[i].indexOf(dist.second) && typeof alreadyInGroup[dist.second.id] === 'undefined') { + groups[i].push(dist.second); + alreadyInGroup [dist.second.id] = true; + } + } + } + + return groups; +}; + +let distances = computeDistance(users); +let groups = createGroups(distances); +// TODO : Créer une méthode pour checker la distance entre les membres du groupes pour savoir s'il faut les dissoudre ou non + +console.log(distances); +console.log(groups); + From 98be16708b14f6b7caa9ce89c89fe6f6500d436d Mon Sep 17 00:00:00 2001 From: David MAECHLER Date: Sat, 4 Apr 2020 21:06:34 +0200 Subject: [PATCH 2/9] fix a little error in logic of createGroups() method --- back/src/Controller/position.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/back/src/Controller/position.js b/back/src/Controller/position.js index 8c445b14..d8f6affa 100644 --- a/back/src/Controller/position.js +++ b/back/src/Controller/position.js @@ -55,7 +55,7 @@ let createGroups = function(distances) { groups[i] = []; } - if(groups[i].indexOf(dist.first) && typeof alreadyInGroup[dist.first.id] === 'undefined') { + if(!groups[i].indexOf(dist.first) && typeof alreadyInGroup[dist.first.id] === 'undefined') { groups[i].push(dist.first); alreadyInGroup [dist.first.id] = true; } @@ -69,7 +69,7 @@ let createGroups = function(distances) { continue; } - if(groups[i].indexOf(dist.second) && typeof alreadyInGroup[dist.second.id] === 'undefined') { + if(!groups[i].indexOf(dist.second) && typeof alreadyInGroup[dist.second.id] === 'undefined') { groups[i].push(dist.second); alreadyInGroup [dist.second.id] = true; } From 88f231bd1f00f1201d384d0366adf935e138a728 Mon Sep 17 00:00:00 2001 From: David MAECHLER Date: Mon, 6 Apr 2020 00:39:36 +0200 Subject: [PATCH 3/9] fix conditions logic and make the script work. Needs to implement it in node/TS now. --- back/src/Controller/position.js | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/back/src/Controller/position.js b/back/src/Controller/position.js index d8f6affa..b47f9aed 100644 --- a/back/src/Controller/position.js +++ b/back/src/Controller/position.js @@ -1,7 +1,7 @@ // Constants -let MIN_DISTANCE = 80; +let MIN_DISTANCE = 15; let MAX_PER_GROUP = 3; -let NB_USERS = 10; +let NB_USERS = 4; // Utils let rand = function(min, max) { @@ -15,11 +15,13 @@ let users = []; for(let i = 1; i <= NB_USERS; i++) { let user = {}; user.id = rand(0,99999); - user.X = rand(0, 60); - user.Y = rand(0, 60); + user.X = rand(0, 40); + user.Y = rand(0, 40); users.push(user); } +console.log(users); + // Compute distance between each user let computeDistance = function(users) { let i = 0; @@ -27,7 +29,7 @@ let computeDistance = function(users) { users.forEach(function(user1, key1) { users.forEach(function(user2, key2) { - if(key1 !== key2 && key1 < key2) { + if(key1 < key2) { let distanceObj = {}; distanceObj.distance = Math.sqrt(Math.pow(user2.X - user1.X, 2) + Math.pow(user2.Y - user1.Y, 2)); distanceObj.first = user1; @@ -46,18 +48,19 @@ let computeDistance = function(users) { let createGroups = function(distances) { let i = 0; let groups = []; - let alreadyInGroup = []; + let alreadyInAGroup = []; for(let j = 0; j < distances.length; j++) { - let dist = distances[i]; + let dist = distances[j]; + if(dist.distance <= MIN_DISTANCE) { if(typeof groups[i] === 'undefined') { groups[i] = []; } - if(!groups[i].indexOf(dist.first) && typeof alreadyInGroup[dist.first.id] === 'undefined') { + if(groups[i].indexOf(dist.first) === -1 && typeof alreadyInAGroup[dist.first.id] == 'undefined') { groups[i].push(dist.first); - alreadyInGroup [dist.first.id] = true; + alreadyInAGroup[dist.first.id] = true; } if(groups[i].length === MAX_PER_GROUP) { @@ -69,9 +72,9 @@ let createGroups = function(distances) { continue; } - if(!groups[i].indexOf(dist.second) && typeof alreadyInGroup[dist.second.id] === 'undefined') { + if(groups[i].indexOf(dist.second) === -1 && typeof alreadyInAGroup[dist.second.id] == 'undefined') { groups[i].push(dist.second); - alreadyInGroup [dist.second.id] = true; + alreadyInAGroup [dist.second.id] = true; } } } @@ -81,6 +84,7 @@ let createGroups = function(distances) { let distances = computeDistance(users); let groups = createGroups(distances); + // TODO : Créer une méthode pour checker la distance entre les membres du groupes pour savoir s'il faut les dissoudre ou non console.log(distances); From 21d7fb733ad5ff8cd5a935673d0f954975932c49 Mon Sep 17 00:00:00 2001 From: David MAECHLER Date: Mon, 6 Apr 2020 01:27:20 +0200 Subject: [PATCH 4/9] Fix logic in group creation since i only checked the distance between the two first users and not rechecked the distance between a new memember with the ones already present in the group. Also sort the array of distances to group the ones closer first. --- back/src/Controller/position.js | 60 +++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/back/src/Controller/position.js b/back/src/Controller/position.js index b47f9aed..95a55134 100644 --- a/back/src/Controller/position.js +++ b/back/src/Controller/position.js @@ -1,5 +1,5 @@ // Constants -let MIN_DISTANCE = 15; +let MIN_DISTANCE = 12; let MAX_PER_GROUP = 3; let NB_USERS = 4; @@ -10,6 +10,20 @@ let rand = function(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }; +let compareDistances = function(distA, distB) { + if (distA.distance < distB.distance) { + return -1; + } + if (distA.distance > distB.distance) { + return 1; + } + return 0; +}; + +let computeDistance = function (user1, user2) { + return Math.sqrt(Math.pow(user2.X - user1.X, 2) + Math.pow(user2.Y - user1.Y, 2)); +}; + // Test Data let users = []; for(let i = 1; i <= NB_USERS; i++) { @@ -23,7 +37,7 @@ for(let i = 1; i <= NB_USERS; i++) { console.log(users); // Compute distance between each user -let computeDistance = function(users) { +let getDistanceOfEachUser = function(users) { let i = 0; let distances = []; @@ -31,7 +45,7 @@ let computeDistance = function(users) { users.forEach(function(user2, key2) { if(key1 < key2) { let distanceObj = {}; - distanceObj.distance = Math.sqrt(Math.pow(user2.X - user1.X, 2) + Math.pow(user2.Y - user1.Y, 2)); + distanceObj.distance = computeDistance(user1, user2); distanceObj.first = user1; distanceObj.second = user2; @@ -58,9 +72,20 @@ let createGroups = function(distances) { groups[i] = []; } - if(groups[i].indexOf(dist.first) === -1 && typeof alreadyInAGroup[dist.first.id] == 'undefined') { - groups[i].push(dist.first); - alreadyInAGroup[dist.first.id] = true; + if(groups[i].indexOf(dist.first) === -1 && typeof alreadyInAGroup[dist.first.id] === 'undefined') { + if(groups[i].length > 1) { + for(let l = 0; groups[i].length; l++) { + let userTotest = groups[i][l]; + if(computeDistance(dist.first, userTotest) <= MIN_DISTANCE) { + groups[i].push(dist.first); + alreadyInAGroup[dist.first.id] = true; + break; + } + } + } else { + groups[i].push(dist.first); + alreadyInAGroup[dist.first.id] = true; + } } if(groups[i].length === MAX_PER_GROUP) { @@ -72,9 +97,20 @@ let createGroups = function(distances) { continue; } - if(groups[i].indexOf(dist.second) === -1 && typeof alreadyInAGroup[dist.second.id] == 'undefined') { - groups[i].push(dist.second); - alreadyInAGroup [dist.second.id] = true; + if(groups[i].indexOf(dist.second) === -1 && typeof alreadyInAGroup[dist.second.id] === 'undefined') { + if(groups[i].length > 1) { + for(let l = 0; groups[i].length; l++) { + let userTotest = groups[i][l]; + if(computeDistance(dist.second, userTotest) <= MIN_DISTANCE) { + groups[i].push(dist.second); + alreadyInAGroup[dist.second.id] = true; + break; + } + } + } else { + groups[i].push(dist.second); + alreadyInAGroup[dist.second.id] = true; + } } } } @@ -82,7 +118,11 @@ let createGroups = function(distances) { return groups; }; -let distances = computeDistance(users); +let distances = getDistanceOfEachUser(users); + +// ordonner par distance pour prioriser l'association en groupe des utilisateurs les plus proches +distances.sort(compareDistances); + let groups = createGroups(distances); // TODO : Créer une méthode pour checker la distance entre les membres du groupes pour savoir s'il faut les dissoudre ou non From 886477cddf09d893a0be230f7157681a375a313a Mon Sep 17 00:00:00 2001 From: David MAECHLER Date: Mon, 6 Apr 2020 01:45:51 +0200 Subject: [PATCH 5/9] fix stupid error in for loop --- back/src/Controller/position.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/back/src/Controller/position.js b/back/src/Controller/position.js index 95a55134..605c1163 100644 --- a/back/src/Controller/position.js +++ b/back/src/Controller/position.js @@ -1,7 +1,7 @@ // Constants let MIN_DISTANCE = 12; let MAX_PER_GROUP = 3; -let NB_USERS = 4; +let NB_USERS = 10; // Utils let rand = function(min, max) { @@ -34,8 +34,6 @@ for(let i = 1; i <= NB_USERS; i++) { users.push(user); } -console.log(users); - // Compute distance between each user let getDistanceOfEachUser = function(users) { let i = 0; @@ -74,7 +72,7 @@ let createGroups = function(distances) { if(groups[i].indexOf(dist.first) === -1 && typeof alreadyInAGroup[dist.first.id] === 'undefined') { if(groups[i].length > 1) { - for(let l = 0; groups[i].length; l++) { + for(let l = 0; l < groups[i].length; l++) { let userTotest = groups[i][l]; if(computeDistance(dist.first, userTotest) <= MIN_DISTANCE) { groups[i].push(dist.first); @@ -99,7 +97,7 @@ let createGroups = function(distances) { if(groups[i].indexOf(dist.second) === -1 && typeof alreadyInAGroup[dist.second.id] === 'undefined') { if(groups[i].length > 1) { - for(let l = 0; groups[i].length; l++) { + for(let l = 0; l < groups[i].length; l++) { let userTotest = groups[i][l]; if(computeDistance(dist.second, userTotest) <= MIN_DISTANCE) { groups[i].push(dist.second); @@ -127,6 +125,7 @@ let groups = createGroups(distances); // TODO : Créer une méthode pour checker la distance entre les membres du groupes pour savoir s'il faut les dissoudre ou non +console.log(users); console.log(distances); console.log(groups); From 3bcb12b3efcdeeb975594a8efebb225089690d34 Mon Sep 17 00:00:00 2001 From: David MAECHLER Date: Mon, 6 Apr 2020 02:00:21 +0200 Subject: [PATCH 6/9] add stub method for recheck on group members proximity --- back/src/Controller/position.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/back/src/Controller/position.js b/back/src/Controller/position.js index 605c1163..01fb5cdf 100644 --- a/back/src/Controller/position.js +++ b/back/src/Controller/position.js @@ -72,6 +72,7 @@ let createGroups = function(distances) { if(groups[i].indexOf(dist.first) === -1 && typeof alreadyInAGroup[dist.first.id] === 'undefined') { if(groups[i].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 l = 0; l < groups[i].length; l++) { let userTotest = groups[i][l]; if(computeDistance(dist.first, userTotest) <= MIN_DISTANCE) { @@ -97,6 +98,7 @@ let createGroups = function(distances) { if(groups[i].indexOf(dist.second) === -1 && typeof alreadyInAGroup[dist.second.id] === 'undefined') { if(groups[i].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 l = 0; l < groups[i].length; l++) { let userTotest = groups[i][l]; if(computeDistance(dist.second, userTotest) <= MIN_DISTANCE) { @@ -123,7 +125,22 @@ distances.sort(compareDistances); let groups = createGroups(distances); -// TODO : Créer une méthode pour checker la distance entre les membres du groupes pour savoir s'il faut les dissoudre ou non +// Compute distance between each user of a already existing group +let checkGroupDistance = function(groups) { + for(let i = 0; i < groups.length; i++) { + let group = groups[i]; + group.forEach(function(user1, key1) { + group.forEach(function(user2, key2) { + if(key1 < key2) { + let distance = computeDistance(user1, user2); + if(distance > MIN_DISTANCE) { + // TODO : message a user1 et user2 + } + } + }); + }); + } +}; console.log(users); console.log(distances); From fbfc208129cfe6c6048b04e40623c079bd1b013f Mon Sep 17 00:00:00 2001 From: David MAECHLER Date: Tue, 7 Apr 2020 10:08:04 +0200 Subject: [PATCH 7/9] BIG WIP of refactoring my work in TS --- .../position.js => position-test.js} | 0 back/src/Controller/IoSocketController.ts | 3 +- back/src/Controller/PositionController.ts | 131 +++++++++++++++++- back/src/Model/Distance.ts | 7 + back/src/Model/Group.ts | 18 +++ back/src/Model/UserInterface.ts | 7 + back/src/Model/Websocket/Group.ts | 18 +++ back/src/Model/Websocket/Message.ts | 3 +- .../Model/Websocket/MessageUserPosition.ts | 5 +- back/src/Model/World.ts | 46 ++++++ back/tests/MessageTest.ts | 8 +- back/tests/WorldTest.ts | 39 ++++++ 12 files changed, 274 insertions(+), 11 deletions(-) rename back/{src/Controller/position.js => position-test.js} (100%) create mode 100644 back/src/Model/Distance.ts create mode 100644 back/src/Model/Group.ts create mode 100644 back/src/Model/UserInterface.ts create mode 100644 back/src/Model/Websocket/Group.ts create mode 100644 back/src/Model/World.ts create mode 100644 back/tests/WorldTest.ts diff --git a/back/src/Controller/position.js b/back/position-test.js similarity index 100% rename from back/src/Controller/position.js rename to back/position-test.js diff --git a/back/src/Controller/IoSocketController.ts b/back/src/Controller/IoSocketController.ts index aa5dfdc9..06e0cb11 100644 --- a/back/src/Controller/IoSocketController.ts +++ b/back/src/Controller/IoSocketController.ts @@ -87,7 +87,8 @@ export class IoSocketController{ //Hydrate and manage error hydrateMessageReceive(message : string) : MessageUserPosition | Error{ try { - return new MessageUserPosition(message); + let data = JSON.parse(message); + return new MessageUserPosition(data); }catch (err) { //TODO log error return new Error(err); diff --git a/back/src/Controller/PositionController.ts b/back/src/Controller/PositionController.ts index 0ffdd02f..f22f0917 100644 --- a/back/src/Controller/PositionController.ts +++ b/back/src/Controller/PositionController.ts @@ -1 +1,130 @@ -// TODO \ No newline at end of file +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 diff --git a/back/src/Model/Distance.ts b/back/src/Model/Distance.ts new file mode 100644 index 00000000..0abde384 --- /dev/null +++ b/back/src/Model/Distance.ts @@ -0,0 +1,7 @@ +import {MessageUserPosition} from "../Model/Websocket/MessageUserPosition"; + +export interface Distance { + distance: number, + user1: MessageUserPosition, + user2: MessageUserPosition, +} \ No newline at end of file diff --git a/back/src/Model/Group.ts b/back/src/Model/Group.ts new file mode 100644 index 00000000..208615da --- /dev/null +++ b/back/src/Model/Group.ts @@ -0,0 +1,18 @@ +import {MessageUserPosition} from "./Websocket/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 diff --git a/back/src/Model/UserInterface.ts b/back/src/Model/UserInterface.ts new file mode 100644 index 00000000..c75d3f3a --- /dev/null +++ b/back/src/Model/UserInterface.ts @@ -0,0 +1,7 @@ +import { Group } from "./Group"; +import { PointInterface } from "./Websocket/PointInterface"; + +export interface Userinteface { + group: Group, + pointInterface: PointInterface +} \ No newline at end of file diff --git a/back/src/Model/Websocket/Group.ts b/back/src/Model/Websocket/Group.ts new file mode 100644 index 00000000..1daa8d66 --- /dev/null +++ b/back/src/Model/Websocket/Group.ts @@ -0,0 +1,18 @@ +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 diff --git a/back/src/Model/Websocket/Message.ts b/back/src/Model/Websocket/Message.ts index 8e6f2c9a..d726968f 100644 --- a/back/src/Model/Websocket/Message.ts +++ b/back/src/Model/Websocket/Message.ts @@ -2,8 +2,7 @@ export class Message { userId: string; roomId: string; - constructor(message: string) { - let data = JSON.parse(message); + constructor(data: any) { if(!data.userId || !data.roomId){ throw Error("userId or roomId cannot be null"); } diff --git a/back/src/Model/Websocket/MessageUserPosition.ts b/back/src/Model/Websocket/MessageUserPosition.ts index 493f1457..2e79f5ef 100644 --- a/back/src/Model/Websocket/MessageUserPosition.ts +++ b/back/src/Model/Websocket/MessageUserPosition.ts @@ -24,9 +24,8 @@ export class Point implements PointInterface{ export class MessageUserPosition extends Message{ position: PointInterface; - constructor(message: string) { - super(message); - let data = JSON.parse(message); + constructor(data: any) { + super(data); this.position = new Point(data.position.x, data.position.y); } diff --git a/back/src/Model/World.ts b/back/src/Model/World.ts new file mode 100644 index 00000000..e9bd5474 --- /dev/null +++ b/back/src/Model/World.ts @@ -0,0 +1,46 @@ +import {MessageUserPosition} from "./Websocket/MessageUserPosition"; +import {PointInterface} from "./Websocket/PointInterface"; +import {Group} from "./Group"; + +export class World { + // Users, sorted by ID + private users: Map; + private groups: Group[] + private connectCallback: (user1: string, user2: string) => void; + private disconnectCallback: (user1: string, user2: string) => void; + + constructor(connectCallback: (user1: string, user2: string) => void, disconnectCallback: (user1: string, user2: string) => void) + { + this.users = new Map(); + this.groups = []; + this.connectCallback = connectCallback; + this.disconnectCallback = disconnectCallback; + } + + public join(userPosition: MessageUserPosition): void { + this.users.set(userPosition.userId, userPosition.position); + } + + public updatePosition(userPosition: MessageUserPosition): void { + if(typeof userPosition.userId === 'undefined') { + throw new Error('unkown id'); + } + //this.users.get(userPosition.userId).x; + + // TODO: compute distance between peers. + + // Is the user in a group? + + // 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 + + // If the user is in no group + // is there someone in a group close enough and with room in the group? + } + +} \ No newline at end of file diff --git a/back/tests/MessageTest.ts b/back/tests/MessageTest.ts index 69d57fce..070ddf57 100644 --- a/back/tests/MessageTest.ts +++ b/back/tests/MessageTest.ts @@ -3,27 +3,27 @@ import {Message} from "../src/Model/Websocket/Message"; describe("Message Model", () => { it("should find userId and roomId", () => { - let message = JSON.stringify({userId: "test1", roomId: "test2"}); + let message = {userId: "test1", roomId: "test2"}; let messageObject = new Message(message); expect(messageObject.userId).toBe("test1"); expect(messageObject.roomId).toBe("test2"); }) it("should expose a toJson method", () => { - let message = JSON.stringify({userId: "test1", roomId: "test2"}); + let message = {userId: "test1", roomId: "test2"}; let messageObject = new Message(message); expect(messageObject.toJson()).toEqual({userId: "test1", roomId: "test2"}); }) it("should find throw error when no userId", () => { - let message = JSON.stringify({roomId: "test2"}); + let message = {roomId: "test2"}; expect(() => { let messageObject = new Message(message); }).toThrow(new Error("userId or roomId cannot be null")); }) it("should find throw error when no roomId", () => { - let message = JSON.stringify({userId: "test1"}); + let message = {userId: "test1"}; expect(() => { let messageObject = new Message(message); }).toThrow(new Error("userId or roomId cannot be null")); diff --git a/back/tests/WorldTest.ts b/back/tests/WorldTest.ts new file mode 100644 index 00000000..7b8c167b --- /dev/null +++ b/back/tests/WorldTest.ts @@ -0,0 +1,39 @@ +import "jasmine"; +import {Message} from "../src/Model/Websocket/Message"; +import {World} from "../src/Model/World"; +import {MessageUserPosition, Point} from "../src/Model/Websocket/MessageUserPosition"; + +describe("World", () => { + it("should connect user1 and user2", () => { + 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(500, 100) + })); + + world.updatePosition(new MessageUserPosition({ + userId: "bar", + roomId: 1, + position: new Point(101, 100) + })); + + expect(connectCalled).toBe(true); + + }) +}) \ No newline at end of file From e3b0f99f04a97a8ed4c82bcf5d1aa35af6fe7f57 Mon Sep 17 00:00:00 2001 From: David MAECHLER Date: Wed, 8 Apr 2020 20:40:44 +0200 Subject: [PATCH 8/9] blocked on some logic...WIP commit --- back/src/Controller/PositionController.ts | 130 ---------------------- back/src/Model/Distance.ts | 4 +- back/src/Model/Group.ts | 34 ++++++ back/src/Model/Websocket/Group.ts | 18 --- back/src/Model/World.ts | 124 ++++++++++++++++++--- back/tests/WorldTest.ts | 49 +++++++- 6 files changed, 191 insertions(+), 168 deletions(-) delete mode 100644 back/src/Controller/PositionController.ts delete mode 100644 back/src/Model/Websocket/Group.ts diff --git a/back/src/Controller/PositionController.ts b/back/src/Controller/PositionController.ts deleted file mode 100644 index f22f0917..00000000 --- a/back/src/Controller/PositionController.ts +++ /dev/null @@ -1,130 +0,0 @@ -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 diff --git a/back/src/Model/Distance.ts b/back/src/Model/Distance.ts index 0abde384..150c144f 100644 --- a/back/src/Model/Distance.ts +++ b/back/src/Model/Distance.ts @@ -2,6 +2,6 @@ import {MessageUserPosition} from "../Model/Websocket/MessageUserPosition"; export interface Distance { distance: number, - user1: MessageUserPosition, - user2: MessageUserPosition, + first: MessageUserPosition, + second: MessageUserPosition, } \ No newline at end of file diff --git a/back/src/Model/Group.ts b/back/src/Model/Group.ts index 208615da..ed57e473 100644 --- a/back/src/Model/Group.ts +++ b/back/src/Model/Group.ts @@ -1,4 +1,5 @@ import {MessageUserPosition} from "./Websocket/MessageUserPosition"; +import { World } from "./World"; export class Group { static readonly MAX_PER_GROUP = 4; @@ -15,4 +16,37 @@ export class Group { 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 diff --git a/back/src/Model/Websocket/Group.ts b/back/src/Model/Websocket/Group.ts deleted file mode 100644 index 1daa8d66..00000000 --- a/back/src/Model/Websocket/Group.ts +++ /dev/null @@ -1,18 +0,0 @@ -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 diff --git a/back/src/Model/World.ts b/back/src/Model/World.ts index e9bd5474..dd4ec3a9 100644 --- a/back/src/Model/World.ts +++ b/back/src/Model/World.ts @@ -1,11 +1,15 @@ -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; - private groups: Group[] + private groups: Group[]; + private connectCallback: (user1: string, user2: string) => void; private disconnectCallback: (user1: string, user2: string) => void; @@ -22,25 +26,111 @@ export class World { } 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 - // TODO: compute distance between peers. + } + } else { + // If the user is in no group + // Is there someone in a group close enough and with room in the group ? + } + }); - // Is the user in a 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); - // Is the user leaving the group? (is the user at more than max distance of each player) + usersToBeGroupedWith.sort(World.compareDistances); + // TODO : vérifier qu'ils ne sont pas déja dans un groupe plein - // 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 - - // If the user is in no group - // is there someone in a group close enough and with room in the group? } + 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)); + } + + 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); + + 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; + } + }); + + if(usersToRemove) { + // Detecte le ou les users qui se sont fait sortir du groupe + let difference = users.filter(x => !groupTmp.includes(x)); + + // TODO : Notify users un difference that they have left 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 diff --git a/back/tests/WorldTest.ts b/back/tests/WorldTest.ts index 7b8c167b..a0cced43 100644 --- a/back/tests/WorldTest.ts +++ b/back/tests/WorldTest.ts @@ -2,6 +2,8 @@ import "jasmine"; 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", () => { @@ -33,7 +35,52 @@ describe("World", () => { 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 From 4bc23ede905b9859be1b4d20bab10cd51aa4cf23 Mon Sep 17 00:00:00 2001 From: David MAECHLER Date: Thu, 9 Apr 2020 23:26:19 +0200 Subject: [PATCH 9/9] unit test on connect is working, lets start the worst .... --- back/src/Model/Group.ts | 37 ++++++++--- back/src/Model/UserInterface.ts | 7 ++- back/src/Model/World.ts | 108 +++++++++++++++++++++++++++----- back/tests/WorldTest.ts | 21 ++++++- 4 files changed, 143 insertions(+), 30 deletions(-) diff --git a/back/src/Model/Group.ts b/back/src/Model/Group.ts index ed57e473..38b91257 100644 --- a/back/src/Model/Group.ts +++ b/back/src/Model/Group.ts @@ -1,15 +1,26 @@ import {MessageUserPosition} from "./Websocket/MessageUserPosition"; import { World } from "./World"; +import { UserInterface } from "./UserInterface"; + export class Group { static readonly MAX_PER_GROUP = 4; - users: MessageUserPosition[]; + private users: UserInterface[]; + private connectCallback: (user1: string, user2: string) => void; + private disconnectCallback: (user1: string, user2: string) => void; - constructor(users: MessageUserPosition[]) { - this.users = users; + + constructor(users: UserInterface[], connectCallback: (user1: string, user2: string) => void, disconnectCallback: (user1: string, user2: string) => void) { + this.users = []; + this.connectCallback = connectCallback; + this.disconnectCallback = disconnectCallback; + + users.forEach((user: UserInterface) => { + this.join(user); + }); } - getUsers(): MessageUserPosition[] { + getUsers(): UserInterface[] { return this.users; } @@ -17,12 +28,22 @@ export class Group { return this.users.length >= Group.MAX_PER_GROUP; } - isPartOfGroup(user: MessageUserPosition): boolean + join(user: UserInterface): void + { + // Broadcast on the right event + this.users.forEach((groupUser: UserInterface) => { + this.connectCallback(user.id, groupUser.id); + }); + this.users.push(user); + user.group = this; + } + + isPartOfGroup(user: UserInterface): boolean { return this.users.indexOf(user) !== -1; } - isStillIn(user: MessageUserPosition): boolean + isStillIn(user: UserInterface): boolean { if(!this.isPartOfGroup(user)) { return false; @@ -30,7 +51,7 @@ export class Group { 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); + let distance = World.computeDistance(user, userInGroup); if(distance > World.MIN_DISTANCE) { stillIn = false; break; @@ -39,7 +60,7 @@ export class Group { return stillIn; } - removeFromGroup(users: MessageUserPosition[]): void + removeFromGroup(users: UserInterface[]): void { for(let i = 0; i < users.length; i++) { let user = users[i]; diff --git a/back/src/Model/UserInterface.ts b/back/src/Model/UserInterface.ts index c75d3f3a..743f8b4d 100644 --- a/back/src/Model/UserInterface.ts +++ b/back/src/Model/UserInterface.ts @@ -1,7 +1,8 @@ import { Group } from "./Group"; import { PointInterface } from "./Websocket/PointInterface"; -export interface Userinteface { - group: Group, - pointInterface: PointInterface +export interface UserInterface { + id: string, + group?: Group, + position: PointInterface } \ No newline at end of file diff --git a/back/src/Model/World.ts b/back/src/Model/World.ts index dd4ec3a9..804a176b 100644 --- a/back/src/Model/World.ts +++ b/back/src/Model/World.ts @@ -2,12 +2,13 @@ import {MessageUserPosition, Point} from "./Websocket/MessageUserPosition"; import {PointInterface} from "./Websocket/PointInterface"; import {Group} from "./Group"; import {Distance} from "./Distance"; +import {UserInterface} from "./UserInterface"; export class World { - static readonly MIN_DISTANCE = 12; + static readonly MIN_DISTANCE = 160; // Users, sorted by ID - private users: Map; + private users: Map; private groups: Group[]; private connectCallback: (user1: string, user2: string) => void; @@ -15,22 +16,96 @@ export class World { constructor(connectCallback: (user1: string, user2: string) => void, disconnectCallback: (user1: string, user2: string) => void) { - this.users = new Map(); + this.users = new Map(); this.groups = []; this.connectCallback = connectCallback; this.disconnectCallback = disconnectCallback; } public join(userPosition: MessageUserPosition): void { - this.users.set(userPosition.userId, userPosition.position); + this.users.set(userPosition.userId, { + id: userPosition.userId, + position: userPosition.position + }); } public updatePosition(userPosition: MessageUserPosition): void { let context = this; + let user = this.users.get(userPosition.userId); + if(typeof user === 'undefined') { + return; + } + + user.position.x = userPosition.position.x; + user.position.y = userPosition.position.y; + + 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); + + if (closestUser !== null) { + // Is the closest user part of a group? + if (typeof closestUser.group === 'undefined') { + let group: Group = new Group([ + user, + closestUser + ], this.connectCallback, this.disconnectCallback); + } else { + closestUser.group.join(user); + } + } + + } + // TODO : vérifier qu'ils ne sont pas déja dans un groupe plein + } + + /** + * Looks for the closest user that is: + * - close enough (distance <= MIN_DISTANCE) + * - not in a group OR in a group that is not full + */ + private searchClosestAvailableUser(user: UserInterface): UserInterface|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[] = []; - this.users.forEach(function(user, userId) { - let distance = World.computeDistance(userPosition.position, user); // compute distance between peers. - if(distance <= World.MIN_DISTANCE) { + let minimumDistanceFound: number = World.MIN_DISTANCE; + let matchingUser: UserInterface | null = null; + this.users.forEach(function(currentUser, userId) { + if(currentUser === user) { + return; + } + + let distance = World.computeDistance(user, currentUser); // compute distance between peers. + + if(distance <= minimumDistanceFound) { + + 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) { context.groups.forEach(group => { @@ -52,28 +127,27 @@ export class World { } else { // Aucun groupe n'existe donc je stock les users assez proches de moi - let dist = { + let dist: Distance = { 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 + }, this.users); + return matchingUser; } - public static computeDistance(user1: PointInterface, user2: PointInterface): number + public static computeDistance(user1: UserInterface, user2: UserInterface): number { - return Math.sqrt(Math.pow(user2.x - user1.x, 2) + Math.pow(user2.y - user1.y, 2)); + return Math.sqrt(Math.pow(user2.position.x - user1.position.x, 2) + Math.pow(user2.position.y - user1.position.y, 2)); } - getDistancesBetweenGroupUsers(group: Group): Distance[] + /*getDistancesBetweenGroupUsers(group: Group): Distance[] { let i = 0; let users = group.getUsers(); @@ -82,7 +156,7 @@ export class World { users.forEach(function(user2, key2) { if(key1 < key2) { distances[i] = { - distance: World.computeDistance(user1.position, user2.position), + distance: World.computeDistance(user1, user2), first: user1, second: user2 }; @@ -132,5 +206,5 @@ export class World { return 1; } return 0; - } + }*/ } \ No newline at end of file diff --git a/back/tests/WorldTest.ts b/back/tests/WorldTest.ts index a0cced43..1f5affc8 100644 --- a/back/tests/WorldTest.ts +++ b/back/tests/WorldTest.ts @@ -29,15 +29,31 @@ describe("World", () => { position: new Point(500, 100) })); + world.updatePosition(new MessageUserPosition({ + userId: "bar", + roomId: 1, + position: new Point(261, 100) + })); + + expect(connectCalled).toBe(false); + world.updatePosition(new MessageUserPosition({ userId: "bar", roomId: 1, position: new Point(101, 100) })); - //expect(connectCalled).toBe(true); + expect(connectCalled).toBe(true); - }), + connectCalled = false; + world.updatePosition(new MessageUserPosition({ + userId: "bar", + roomId: 1, + position: new Point(102, 100) + })); + expect(connectCalled).toBe(false); + }); + /** it('Should return the distances between all users', () => { let connectCalled: boolean = false; let connect = (user1: string, user2: string): void => { @@ -83,4 +99,5 @@ describe("World", () => { //expect(distances).toBe([]); }) + **/ }) \ No newline at end of file