2020-10-06 15:37:00 +02:00
|
|
|
import { ConnectCallback, DisconnectCallback } from "./GameRoom";
|
2020-09-16 16:06:43 +02:00
|
|
|
import { User } from "./User";
|
2020-04-29 22:41:48 +02:00
|
|
|
import {PositionInterface} from "_Model/PositionInterface";
|
2020-09-16 16:06:43 +02:00
|
|
|
import {Movable} from "_Model/Movable";
|
2020-09-25 13:48:02 +02:00
|
|
|
import {PositionNotifier} from "_Model/PositionNotifier";
|
2020-04-09 23:26:19 +02:00
|
|
|
|
2020-09-16 16:06:43 +02:00
|
|
|
export class Group implements Movable {
|
2020-04-07 10:08:04 +02:00
|
|
|
static readonly MAX_PER_GROUP = 4;
|
2020-04-28 22:40:54 +02:00
|
|
|
|
2020-09-18 13:57:38 +02:00
|
|
|
private static nextId: number = 1;
|
|
|
|
|
|
|
|
private id: number;
|
2020-09-16 16:06:43 +02:00
|
|
|
private users: Set<User>;
|
2020-09-21 11:24:03 +02:00
|
|
|
private x!: number;
|
|
|
|
private y!: number;
|
2020-04-09 23:26:19 +02:00
|
|
|
|
2020-04-07 10:08:04 +02:00
|
|
|
|
2020-09-25 13:48:02 +02:00
|
|
|
constructor(users: User[], private connectCallback: ConnectCallback, private disconnectCallback: DisconnectCallback, private positionNotifier: PositionNotifier) {
|
2020-09-16 16:06:43 +02:00
|
|
|
this.users = new Set<User>();
|
2020-09-18 13:57:38 +02:00
|
|
|
this.id = Group.nextId;
|
|
|
|
Group.nextId++;
|
2020-04-28 22:40:54 +02:00
|
|
|
|
2020-09-16 16:06:43 +02:00
|
|
|
users.forEach((user: User) => {
|
2020-04-09 23:26:19 +02:00
|
|
|
this.join(user);
|
|
|
|
});
|
2020-09-21 11:24:03 +02:00
|
|
|
|
|
|
|
this.updatePosition();
|
2020-04-07 10:08:04 +02:00
|
|
|
}
|
|
|
|
|
2020-09-16 16:06:43 +02:00
|
|
|
getUsers(): User[] {
|
2020-06-29 22:10:23 +02:00
|
|
|
return Array.from(this.users.values());
|
2020-04-07 10:08:04 +02:00
|
|
|
}
|
|
|
|
|
2020-09-18 13:57:38 +02:00
|
|
|
getId() : number {
|
2020-05-01 21:15:00 +02:00
|
|
|
return this.id;
|
|
|
|
}
|
|
|
|
|
2020-04-29 22:41:48 +02:00
|
|
|
/**
|
|
|
|
* Returns the barycenter of all users (i.e. the center of the group)
|
|
|
|
*/
|
|
|
|
getPosition(): PositionInterface {
|
2020-09-21 11:24:03 +02:00
|
|
|
return {
|
|
|
|
x: this.x,
|
|
|
|
y: this.y
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Computes the barycenter of all users (i.e. the center of the group)
|
|
|
|
*/
|
|
|
|
updatePosition(): void {
|
2020-09-25 13:48:02 +02:00
|
|
|
const oldX = this.x;
|
|
|
|
const oldY = this.y;
|
|
|
|
|
2020-04-29 22:41:48 +02:00
|
|
|
let x = 0;
|
|
|
|
let y = 0;
|
|
|
|
// Let's compute the barycenter of all users.
|
2020-09-16 16:06:43 +02:00
|
|
|
this.users.forEach((user: User) => {
|
2020-09-25 15:25:06 +02:00
|
|
|
const position = user.getPosition();
|
|
|
|
x += position.x;
|
|
|
|
y += position.y;
|
2020-04-29 22:41:48 +02:00
|
|
|
});
|
2020-06-29 22:10:23 +02:00
|
|
|
x /= this.users.size;
|
|
|
|
y /= this.users.size;
|
2020-09-21 11:24:03 +02:00
|
|
|
if (this.users.size === 0) {
|
|
|
|
throw new Error("EMPTY GROUP FOUND!!!");
|
|
|
|
}
|
|
|
|
this.x = x;
|
|
|
|
this.y = y;
|
2020-09-25 13:48:02 +02:00
|
|
|
|
|
|
|
if (oldX === undefined) {
|
2020-09-25 15:25:06 +02:00
|
|
|
this.positionNotifier.enter(this);
|
2020-09-25 13:48:02 +02:00
|
|
|
} else {
|
|
|
|
this.positionNotifier.updatePosition(this, {x, y}, {x: oldX, y: oldY});
|
|
|
|
}
|
2020-04-29 22:41:48 +02:00
|
|
|
}
|
|
|
|
|
2020-04-07 10:08:04 +02:00
|
|
|
isFull(): boolean {
|
2020-06-29 22:10:23 +02:00
|
|
|
return this.users.size >= Group.MAX_PER_GROUP;
|
2020-04-07 10:08:04 +02:00
|
|
|
}
|
2020-04-08 20:40:44 +02:00
|
|
|
|
2020-04-29 23:12:55 +02:00
|
|
|
isEmpty(): boolean {
|
2020-06-29 22:10:23 +02:00
|
|
|
return this.users.size <= 1;
|
2020-04-29 23:12:55 +02:00
|
|
|
}
|
|
|
|
|
2020-09-16 16:06:43 +02:00
|
|
|
join(user: User): void
|
2020-04-09 23:26:19 +02:00
|
|
|
{
|
|
|
|
// Broadcast on the right event
|
2020-09-29 16:01:22 +02:00
|
|
|
this.connectCallback(user, this);
|
2020-06-29 22:10:23 +02:00
|
|
|
this.users.add(user);
|
2020-04-09 23:26:19 +02:00
|
|
|
user.group = this;
|
|
|
|
}
|
|
|
|
|
2020-09-16 16:06:43 +02:00
|
|
|
leave(user: User): void
|
2020-04-29 23:12:55 +02:00
|
|
|
{
|
2020-06-29 22:13:07 +02:00
|
|
|
const success = this.users.delete(user);
|
2020-06-29 22:10:23 +02:00
|
|
|
if (success === false) {
|
|
|
|
throw new Error("Could not find user "+user.id+" in the group "+this.id);
|
2020-04-29 23:12:55 +02:00
|
|
|
}
|
|
|
|
user.group = undefined;
|
|
|
|
|
2020-09-25 13:48:02 +02:00
|
|
|
if (this.users.size !== 0) {
|
|
|
|
this.updatePosition();
|
|
|
|
}
|
|
|
|
|
2020-04-29 23:12:55 +02:00
|
|
|
// Broadcast on the right event
|
2020-09-29 16:01:22 +02:00
|
|
|
this.disconnectCallback(user, this);
|
2020-04-29 23:12:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Let's kick everybody out.
|
|
|
|
* Usually used when there is only one user left.
|
|
|
|
*/
|
|
|
|
destroy(): void
|
|
|
|
{
|
2020-06-29 22:13:07 +02:00
|
|
|
for (const user of this.users) {
|
2020-04-29 23:12:55 +02:00
|
|
|
this.leave(user);
|
2020-06-29 22:10:23 +02:00
|
|
|
}
|
2020-04-08 20:40:44 +02:00
|
|
|
}
|
2020-04-28 22:40:54 +02:00
|
|
|
}
|