Switching connection to a barycenter approach
authorDavid Négrier <d.negrier@thecodingmachine.com>
Wed, 29 Apr 2020 20:41:48 +0000 (22:41 +0200)
committerDavid Négrier <d.negrier@thecodingmachine.com>
Wed, 29 Apr 2020 20:41:48 +0000 (22:41 +0200)
back/src/Model/Group.ts
back/src/Model/PositionInterface.ts [new file with mode: 0644]
back/src/Model/World.ts

index 795c0e8ec1b397e52082a8329f26e5dc8b000cf5..9f5c48c5203a094db88718d45b0269a47e07e27d 100644 (file)
@@ -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 (file)
index 0000000..d3b0dd4
--- /dev/null
@@ -0,0 +1,4 @@
+export interface PositionInterface {
+    x: number,
+    y: number
+}
index 4a31e49bf1a614689abf72fa72922e90d9a11f62..32e1b383e8dc9e0a142316b13a5a984d02ccb088 100644 (file)
@@ -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;