This commit is contained in:
Kirill Ivlev 2024-11-20 14:24:46 +04:00
parent 7030a19b03
commit d18d12a458
25 changed files with 249 additions and 194 deletions

View file

@ -0,0 +1,5 @@
export class GameStateConsts {
static Main = 'main';
static EndgamePoints = 'endgamepoints';
static Finish = 'finish';
}

65
src/Consts/types.d.ts vendored Normal file
View file

@ -0,0 +1,65 @@
import {GameQueueTypes} from "../schemas/game-queue.schema";
export interface IStateInfo {
state:string;
value:string;
}
export interface IValidAnswerReceivedSocketEvent {
telegramId: number;
validAnswer: string;
note: string;
}
export interface IUserInfoMinimal {
telegramId: number;
}
export interface IUserBasicInfo extends IUserInfoMinimal {
name: string;
}
export interface IVersusBeginSocketEvent {
player1: number;
player2: number;
player1name: string;
player2name: string;
}
export interface IVersusEndSocketEvent {
winner: number;
}
export interface IScoreChangedSocketEvent extends IUserInfoMinimal {
newScore: number;
}
export interface IUserCardChangedEvent extends IUserInfoMinimal {
cards: string[];
}
export interface IEmptyNotification {}
export interface ISocketNotificationEvent {
text: string;
timeout: number;
}
export interface IUserPropertyChangedEvent {
user: number;
property: string;
value: string;
}
export interface ICardPlayedSocketEvent extends IUserInfoMinimal{
card: string;
name: string;
timeout: number;
}
export interface IGameQueueSocketEvent {
_id: any;
completed: boolean;
target: number;
type: GameQueueTypes;
text: string;
}

View file

@ -1,6 +1,6 @@
import {Injectable, Logger} from '@nestjs/common';
import {SharedService} from "../shared/shared.service";
import {SocketEvents} from "../shared/events.consts";
import {ClientNotificationType} from "../socket/socket.gateway";
export interface IFeatureFlagStatus {
name: string;
@ -32,11 +32,12 @@ export class FeatureflagService {
async setFeatureFlag(id: string, status: boolean) : Promise<IFeatureFlagStatus> {
this.logger.verbose(`Setting feature flag status for ${id} to ${status} `);
const result = await this.sharedService.setConfig(`featureflag/${id}`, status.toString());
this.sharedService.sendSocketNotificationToAllClients(SocketEvents.FEATURE_FLAG_CHANGED, {});
return {
const ffStatus: IFeatureFlagStatus = {
name: id,
state: result.value !== 'false',
}
this.sharedService.notifyAllClients<IFeatureFlagStatus>(ClientNotificationType.FeatureFlagChanged, ffStatus);
return ffStatus;
}
}

View file

@ -1,13 +1,14 @@
import { CommandBus, CommandHandler, EventBus, ICommandHandler } from '@nestjs/cqrs';
import { ProceedGameQueueCommand } from '../commands/proceed-game-queue.command';
import { GameService } from '../game.service';
import { NextQuestionCommand } from '../commands/next-question.command';
import { SharedService } from '../../shared/shared.service';
import { SocketEvents } from '../../shared/events.consts';
import { Logger } from '@nestjs/common';
import { GameQueueTypes } from '../../schemas/game-queue.schema';
import { QuizAnswerStateChangedEvent } from '../events/quiz-answer-state-changed.event';
import { QuizAnswerStateEnum } from '../entities/quiz-answer-state.enum';
import {CommandBus, CommandHandler, EventBus, ICommandHandler} from '@nestjs/cqrs';
import {ProceedGameQueueCommand} from '../commands/proceed-game-queue.command';
import {GameService} from '../game.service';
import {NextQuestionCommand} from '../commands/next-question.command';
import {SharedService} from '../../shared/shared.service';
import {Logger} from '@nestjs/common';
import {GameQueueTypes} from '../../schemas/game-queue.schema';
import {QuizAnswerStateChangedEvent} from '../events/quiz-answer-state-changed.event';
import {QuizAnswerStateEnum} from '../entities/quiz-answer-state.enum';
import {IGameQueueSocketEvent} from "../../Consts/types";
import {ClientNotificationType} from "../../socket/socket.gateway";
@CommandHandler(ProceedGameQueueCommand)
export class GameProceedGameQueueCommandHandler
@ -25,16 +26,13 @@ export class GameProceedGameQueueCommandHandler
if (!item) {
return this.cmdBus.execute(new NextQuestionCommand());
}
this.sharedService.sendSocketNotificationToAllClients(
SocketEvents.GameQueueItem,
{
_id: item.id,
completed: item.completed,
target: item.target,
type: item.type,
text: item.text
},
);
this.sharedService.notifyAllClients<IGameQueueSocketEvent>(ClientNotificationType.GameQueueItem, {
_id: item.id,
completed: item.completed,
target: item.target,
type: item.type,
text: item.text
});
switch (item.type) {
case GameQueueTypes.giveOutAPrize:
this.eventBus.publish(

View file

@ -1,19 +1,15 @@
import {Injectable, InternalServerErrorException, Logger, OnApplicationBootstrap} from '@nestjs/common';
import {CommandBus, EventBus, QueryBus} from '@nestjs/cqrs';
import { CardSelectionTimeExceedCommand } from './commands/card-selection-time-exceed.command';
import { InjectModel } from '@nestjs/mongoose';
import {
GameQueue,
GameQueueDocument,
GameQueueTypes,
} from '../schemas/game-queue.schema';
import {CardSelectionTimeExceedCommand} from './commands/card-selection-time-exceed.command';
import {InjectModel} from '@nestjs/mongoose';
import {GameQueue, GameQueueDocument, GameQueueTypes,} from '../schemas/game-queue.schema';
import {Model, Promise} from 'mongoose';
import { ProceedGameQueueCommand } from './commands/proceed-game-queue.command';
import { SharedService } from '../shared/shared.service';
import { SocketEvents } from '../shared/events.consts';
import {ProceedGameQueueCommand} from './commands/proceed-game-queue.command';
import {SharedService} from '../shared/shared.service';
import {ConfigService} from "@nestjs/config";
import {gameCards} from "./entities/cards.entities";
import {GuestsService} from "../guests/guests.service";
import {IEmptyNotification} from "../Consts/types";
import {ClientNotificationType} from "../socket/socket.gateway";
@Injectable()
export class GameService implements OnApplicationBootstrap{
@ -27,7 +23,6 @@ export class GameService implements OnApplicationBootstrap{
private sharedService: SharedService,
private commandBus: CommandBus,
private queryBus: QueryBus,
private guestService: GuestsService,
) {
}
@ -72,29 +67,20 @@ export class GameService implements OnApplicationBootstrap{
}
qItem.completed = true;
await qItem.save();
this.sharedService.sendSocketNotificationToAllClients(
SocketEvents.QUEUE_COMPLETED,
{},
);
this.sharedService.notifyAllClients<IEmptyNotification>(ClientNotificationType.QueueCompleted, {});
await this.cmdBus.execute(new ProceedGameQueueCommand());
return qItem;
}
async pauseGame() {
await this.sharedService.setConfig('game_state', 'paused');
await this.sharedService.sendSocketNotificationToAllClients(
SocketEvents.GAME_PAUSED,
{},
);
this.sharedService.notifyAllClients<IEmptyNotification>(ClientNotificationType.GamePaused, {});
return Promise.resolve({ result: true });
}
async resumeGame() {
await this.sharedService.setConfig('game_state', 'running');
await this.sharedService.sendSocketNotificationToAllClients(
SocketEvents.GAME_RESUMED,
{},
);
this.sharedService.notifyAllClients<IEmptyNotification>(ClientNotificationType.GameResumed,{});
return Promise.resolve({ result: true });
}

View file

@ -1,18 +1,18 @@
import {Injectable, Logger} from '@nestjs/common';
import {SocketEvents} from "../../shared/events.consts";
import {GuestsService} from "../../guests/guests.service";
import {SharedService} from "../../shared/shared.service";
import {InjectModel} from "@nestjs/mongoose";
import {Versus, VersusDocument} from "../../schemas/versus.schema";
import {Model, Query} from "mongoose";
import {Model} from "mongoose";
import {VersusDto} from "./versus.types";
import {CommandBus, QueryBus} from "@nestjs/cqrs";
import {IncreasePlayerScoreCommand} from "../../guests/command/increase-player-score.command";
import {IncreasePlayerWinningRateCommand} from "../commands/increase-player-winning-rate.command";
import {GetGuestQuery} from "../../guests/queries/getguest.query";
import {GetGuestPropertyQuery} from "../../guests/command/get-guest-property.handler";
import {GuestPropertyNamesConsts} from "../../Consts/guest-property-names.consts";
import {SetGuestPropertyCommand} from "../../guests/command/set-guest-property.command";
import {IVersusBeginSocketEvent, IVersusEndSocketEvent} from "../../Consts/types";
import {ClientNotificationType} from "../../socket/socket.gateway";
@Injectable()
export class VersusService {
@ -51,10 +51,12 @@ export class VersusService {
player2name: p2data.name,
}
}));
this.sharedService.sendSocketNotificationToAllClients(
SocketEvents.BEGIN_VERSUS,
{ player1, player2, player1name: p1data.name, player2name: p2data.name }
)
this.sharedService.notifyAllClients<IVersusBeginSocketEvent>(ClientNotificationType.BeginVersus, {
player1,
player2,
player1name: p1data.name,
player2name: p2data.name
});
}
async importVersus(data: VersusDto[]) {
@ -111,11 +113,10 @@ export class VersusService {
this.logger.verbose(`Set win count for ${winner} to ${wonCount}`);
tasks.push(await this.cmdBus.execute(new SetGuestPropertyCommand(winner, GuestPropertyNamesConsts.VersusWonCount, wonCount.toString)));
await Promise.all(tasks);
this.sharedService.sendSocketNotificationToAllClients(
SocketEvents.END_VERSUS,
{ winner: winner }
)
this.sharedService.notifyAllClients<IVersusEndSocketEvent>(ClientNotificationType.EndVersus, {
winner: winner
}
);
return item;
}

View file

@ -1,15 +1,15 @@
import {Controller, Logger} from "@nestjs/common";
import {Ctx, EventPattern, MessagePattern, Payload, RmqContext} from "@nestjs/microservices";
import {Ctx, MessagePattern, Payload, RmqContext} from "@nestjs/microservices";
import {GetGuestInfoModel} from "./models/get-guest-info.model";
import {GuestsService} from "../guests/guests.service";
import {RegisterUserModel} from "./models/register-user.model";
import {SharedService} from "../shared/shared.service";
import {SocketEvents} from "../shared/events.consts";
import {CommandsConsts} from "../Consts/commands.consts";
import {EventBus} from "@nestjs/cqrs";
import {PlayerCardSelectedEvent} from "../game/events/player-card-selected.event";
import {getCard} from "../helpers/card-parser";
import {QuizService} from "../quiz/quiz.service";
import {ClientNotificationType} from "../socket/socket.gateway";
@Controller()
export class GuestsMessageController {
@ -49,7 +49,7 @@ export class GuestsMessageController {
@MessagePattern({ cmd: CommandsConsts.PhotoUpdated })
async photoUpdated(@Payload() data: { id: number}) {
this.logger.verbose(`Photo updated event, send notification`);
this.sharedService.sendSocketNotificationToAllClients(SocketEvents.PHOTOS_UPDATED_EVENT, data);
this.sharedService.notifyAllClients<{id: number}>(ClientNotificationType.PhotosUpdated, data)
}
@MessagePattern({ cmd: CommandsConsts.CardPlayed })

View file

@ -1,5 +1,5 @@
export const SharedServiceMock = {
setConfig: jest.fn(),
getConfig: jest.fn(),
sendSocketNotificationToAllClients: jest.fn(),
notifyAllClients: jest.fn(),
}

View file

@ -51,7 +51,7 @@ export class QuizController {
return this.quizService.dealPrize();
}
@Get('endgame-extrapoints')
@Post('calculate-endgame-extrapoints')
async endgameExtrapoints()
{
return await this.quizService.calculateEndgamePoints();

View file

@ -19,6 +19,7 @@ import {IncreasePlayerScoreCommand} from "../guests/command/increase-player-scor
import {FeatureflagService} from "../featureflag/featureflag.service";
import {FeatureFlagsConsts} from "../Consts/FeatureFlags.consts";
import {QuizEndGameResults} from "./quiz.types";
import {ClientNotificationType} from "../socket/socket.gateway";
@Injectable({ scope: Scope.TRANSIENT })
export class QuizService {
@ -48,10 +49,7 @@ export class QuizService {
await item.save();
this.logger.verbose(`Question updated`);
await this.guestService.postQuestion(questionDto, target);
this.sharedService.sendSocketNotificationToAllClients(
'question_changed',
questionDto,
);
this.sharedService.notifyAllClients<QuestionDto>(ClientNotificationType.QuestionChanged, questionDto);
return item.save();
}
@ -171,7 +169,7 @@ export class QuizService {
//const { maxRewards, maxInvalidAnswers } = Promise.all([maxRewardsPromise, maxInvalidAnswersPromise]);
const [maxRewards, maxInvalidAnswers, maxPenaltiesReceived] = await Promise.all([maxRewardsPromise, maxInvalidAnswersPromise, maxPenaltiesPromise]);
return {
const result = {
maxInvalidAnswers: {
id: maxInvalidAnswers[0].id,
count: maxInvalidAnswers[0].invalidAnswers,
@ -188,6 +186,8 @@ export class QuizService {
name: maxPenaltiesReceived[0].name,
}
}
await this.sharedService.setConfig('endgame-points', JSON.stringify(result));
return result;
}
private async getNextQuestion() {

View file

@ -49,7 +49,7 @@ describe('SchedulerService', () => {
it('should finish game if prizes count is 0', async () => {
const getRemainingPrizeCountFn = jest.spyOn(giftService, 'getRemainingPrizeCount').mockImplementation(() => Promise.resolve(0));
const notificationFn = jest.spyOn(sharedService,'sendSocketNotificationToAllClients').mockImplementation();
const notificationFn = jest.spyOn(sharedService,'notifyAllClients').mockImplementation();
const setStateFn = jest.spyOn(stateService,'setState').mockImplementation((name,newstate) => Promise.resolve({ state: name, value: newstate}));
await service.gameStatus();
expect(getRemainingPrizeCountFn).toHaveBeenCalled();
@ -59,7 +59,7 @@ describe('SchedulerService', () => {
it('should not finish game if prizes count above 0', async () => {
const getRemainingPrizeCountFn = jest.spyOn(giftService, 'getRemainingPrizeCount').mockImplementation(() => Promise.resolve(5));
const notificationFn = jest.spyOn(sharedService,'sendSocketNotificationToAllClients').mockImplementation()
const notificationFn = jest.spyOn(sharedService,'notifyAllClients').mockImplementation()
await service.gameStatus();
expect(notificationFn).not.toHaveBeenCalled();
});

View file

@ -7,9 +7,9 @@ import {SharedService} from '../shared/shared.service';
import {FeatureflagService} from "../featureflag/featureflag.service";
import {FeatureFlagsConsts} from "../Consts/FeatureFlags.consts";
import {CommandBus} from "@nestjs/cqrs";
import {EndgameDict} from "../voice/dicts/endgame.dict";
import {CreateNewQueueItemCommand} from "../game/commands/create-new-queue-item.command";
import {GameQueueTypes} from "../schemas/game-queue.schema";
import {GameStateConsts} from "../Consts/game-state.consts";
import {IStateInfo} from "../Consts/types";
import {ClientNotificationType} from "../socket/socket.gateway";
@Injectable()
export class SchedulerService {
@ -37,24 +37,11 @@ export class SchedulerService {
if(await this.featureFlagService.getFeatureFlag(FeatureFlagsConsts.EnableEndgamePoints)) {
this.logger.verbose(`Feature flag ${FeatureFlagsConsts.EnableEndgamePoints} is enabled`);
const endgamePoints = await this.quizService.calculateEndgamePoints();
await Promise.all([
this.commandBus.execute(
new CreateNewQueueItemCommand(endgamePoints.maxInvalidAnswers.id,
GameQueueTypes.extra_points,
EndgameDict.maxAmountOfInvalidQuestions)),
new CreateNewQueueItemCommand(endgamePoints.maxPenalties.id,
GameQueueTypes.extra_points,
EndgameDict.maxPenalties),
new CreateNewQueueItemCommand(endgamePoints.maxRewards.id,
GameQueueTypes.extra_points,
EndgameDict.maxAmountOfRewards)
]);
const state = await this.stateService.setState(GameStateConsts.Main, GameStateConsts.EndgamePoints);
this.sharedService.notifyAllClients<IStateInfo>(ClientNotificationType.StateChanged, state);
} else {
const state = await this.stateService.setState('main', 'finish');
this.sharedService.sendSocketNotificationToAllClients(
'state_changed',
state,
);
this.sharedService.notifyAllClients<IStateInfo>(ClientNotificationType.StateChanged, state);
this.logger.warn(`Gifts is ended, finishing game`);
}
}

View file

@ -1,18 +0,0 @@
export enum SocketEvents {
PHOTOS_UPDATED_EVENT = 'photos_updated',
VALID_ANSWER_RECEIVED = 'answer_received',
WRONG_ANSWER_RECEIVED = 'wrong_answer_received',
USER_ADDED = 'user_added',
USER_PROPERTY_CHANGED = 'user_property_changed',
CARDS_CHANGED_EVENT = 'cards_changed',
CARD_PLAYED = 'card_played',
SCORE_CHANGED = 'score_changed',
GameQueueItem = 'game_queue',
QUEUE_COMPLETED = 'queue_completed',
GAME_PAUSED = 'game_paused',
GAME_RESUMED = 'game_resumed',
NOTIFICATION = 'notification',
FEATURE_FLAG_CHANGED = 'feature_flag_changed',
BEGIN_VERSUS = 'begin_versus',
END_VERSUS = 'end_versus',
}

View file

@ -1,4 +1,4 @@
import { SocketGateway } from '../socket/socket.gateway';
import {ClientNotificationType, SocketGateway} from '../socket/socket.gateway';
import { Injectable, Logger } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Config, ConfigDocument } from '../schemas/config.schema';
@ -55,14 +55,19 @@ export class SharedService {
}
/**
* Notifies all connected socket about changes
* @deprecated Use specific handlers in this class
* @param event
* @param payload
* Notifies all connected clients via the socket gateway with the given event and payload.
*
* @template T - The type of the payload.
*
* @param event - The event name to be sent to the clients.
* @param payload - The data to be sent along with the event.
*
* @returns {void} - This function does not return any value.
*/
sendSocketNotificationToAllClients(event: string, payload?: any) {
notifyAllClients<T>(event: ClientNotificationType, payload: T): void {
this.logger.verbose(`Sending notification to client: ${event}, ${JSON.stringify(payload)}`);
this.socketGateway.notifyAllClients(event, payload);
}
}

View file

@ -1,8 +1,9 @@
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
import { NotifyCardOnScreenCommand } from '../../../game/commands/notify-card-on-screen-command';
import { SharedService } from '../../../shared/shared.service';
import { SocketEvents } from '../../../shared/events.consts';
import { Logger } from '@nestjs/common';
import {CommandHandler, ICommandHandler} from '@nestjs/cqrs';
import {NotifyCardOnScreenCommand} from '../../../game/commands/notify-card-on-screen-command';
import {SharedService} from '../../../shared/shared.service';
import {Logger} from '@nestjs/common';
import {ICardPlayedSocketEvent} from "../../../Consts/types";
import {ClientNotificationType} from "../../socket.gateway";
@CommandHandler(NotifyCardOnScreenCommand)
export class NotifyCardPlayedCommandHandler
@ -12,8 +13,7 @@ export class NotifyCardPlayedCommandHandler
}
async execute(command: NotifyCardOnScreenCommand): Promise<any> {
this.logger.log(`Notify about card`);
this.sharedService.sendSocketNotificationToAllClients(
SocketEvents.CARD_PLAYED, {
this.sharedService.notifyAllClients<ICardPlayedSocketEvent>(ClientNotificationType.CardPlayed, {
telegramId: command.telegramId,
card: command.card.description,
name: command.card.name,

View file

@ -1,8 +1,9 @@
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
import { SendToastCommand } from '../../../game/commands/send-toast.command';
import { SharedService } from '../../../shared/shared.service';
import { SocketEvents } from '../../../shared/events.consts';
import {CommandHandler, ICommandHandler} from '@nestjs/cqrs';
import {SendToastCommand} from '../../../game/commands/send-toast.command';
import {SharedService} from '../../../shared/shared.service';
import {Logger} from "@nestjs/common";
import {ISocketNotificationEvent} from "../../../Consts/types";
import {ClientNotificationType} from "../../socket.gateway";
@CommandHandler(SendToastCommand)
export class SendToastCommandHandler implements ICommandHandler<SendToastCommand> {
@ -11,12 +12,9 @@ export class SendToastCommandHandler implements ICommandHandler<SendToastCommand
}
async execute(command: SendToastCommand) {
this.logger.verbose(`send notification: ${command.text}`);
await this.sharedService.sendSocketNotificationToAllClients(
SocketEvents.NOTIFICATION,
{
text: command.text,
timeout: command.timeout,
},
);
this.sharedService.notifyAllClients<ISocketNotificationEvent>(ClientNotificationType.Notification, {
text: command.text,
timeout: command.timeout,
});
}
}

View file

@ -1,17 +1,16 @@
import { EventsHandler, IEventHandler } from '@nestjs/cqrs';
import { CardsSetChangedEvent } from '../../../game/events/cards-events/cards-set-changed.event';
import { SharedService } from '../../../shared/shared.service';
import { SocketEvents } from '../../../shared/events.consts';
import {EventsHandler, IEventHandler} from '@nestjs/cqrs';
import {CardsSetChangedEvent} from '../../../game/events/cards-events/cards-set-changed.event';
import {SharedService} from '../../../shared/shared.service';
import {IUserInfoMinimal} from "../../../Consts/types";
import {ClientNotificationType} from "../../socket.gateway";
@EventsHandler(CardsSetChangedEvent)
export class CardsSetChangedEventHandler
implements IEventHandler<CardsSetChangedEvent>
{
constructor(private sharedService: SharedService) {}
handle(event: CardsSetChangedEvent): any {
this.sharedService.sendSocketNotificationToAllClients(
SocketEvents.CARDS_CHANGED_EVENT,
{ telegramId: event.telegramId },
);
handle(event: CardsSetChangedEvent): void {
this.sharedService
.notifyAllClients<IUserInfoMinimal>(ClientNotificationType.CardsChanged, { telegramId: event.telegramId})
}
}

View file

@ -1,18 +1,17 @@
import { EventsHandler, IEventHandler } from '@nestjs/cqrs';
import { CardsDealedEvent } from '../../../game/events/cards-dealed.event';
import { SharedService } from '../../../shared/shared.service';
import { SocketEvents } from '../../../shared/events.consts';
import {EventsHandler, IEventHandler} from '@nestjs/cqrs';
import {CardsDealedEvent} from '../../../game/events/cards-dealed.event';
import {SharedService} from '../../../shared/shared.service';
import {IUserCardChangedEvent} from "../../../Consts/types";
import {ClientNotificationType} from "../../socket.gateway";
@EventsHandler(CardsDealedEvent)
export class CardsUpdatedEventHandler implements IEventHandler<CardsDealedEvent> {
constructor(private sharedService: SharedService) {
}
handle(event: CardsDealedEvent): any {
this.sharedService.sendSocketNotificationToAllClients(
SocketEvents.CARDS_CHANGED_EVENT,
{
telegramId: event.telegramId,
cards: event.cards,
handle(event: CardsDealedEvent): void {
this.sharedService.notifyAllClients<IUserCardChangedEvent>(ClientNotificationType.CardsChanged, {
telegramId: event.telegramId,
cards: event.cards,
});
}
}

View file

@ -1,7 +1,8 @@
import { EventsHandler, IEventHandler } from '@nestjs/cqrs';
import { ScoreChangedEvent } from '../../../game/events/score-changed.event';
import { SharedService } from '../../../shared/shared.service';
import { SocketEvents } from '../../../shared/events.consts';
import {EventsHandler, IEventHandler} from '@nestjs/cqrs';
import {ScoreChangedEvent} from '../../../game/events/score-changed.event';
import {SharedService} from '../../../shared/shared.service';
import {IScoreChangedSocketEvent} from "../../../Consts/types";
import {ClientNotificationType} from "../../socket.gateway";
@EventsHandler(ScoreChangedEvent)
export class SocketScoreChangedEventHandler
@ -9,12 +10,9 @@ export class SocketScoreChangedEventHandler
constructor(private sharedService: SharedService) {
}
async handle(event: ScoreChangedEvent) {
this.sharedService.sendSocketNotificationToAllClients(
SocketEvents.SCORE_CHANGED,
{
telegramId: event.telegramId,
newScore: event.newScore,
},
);
this.sharedService.notifyAllClients<IScoreChangedSocketEvent>(ClientNotificationType.ScoreChanged, {
telegramId: event.telegramId,
newScore: event.newScore,
});
}
}

View file

@ -1,17 +1,19 @@
import {EventsHandler, IEventHandler} from "@nestjs/cqrs";
import {UserPropertyChangedEvent} from "../../../guests/event-handlers/user-property-changed.event";
import {SharedService} from "../../../shared/shared.service";
import {SocketEvents} from "../../../shared/events.consts";
import {IUserPropertyChangedEvent} from "../../../Consts/types";
import {ClientNotificationType} from "../../socket.gateway";
@EventsHandler(UserPropertyChangedEvent)
export class UserPropertyChangedEventHandler implements IEventHandler<UserPropertyChangedEvent> {
constructor(private sharedService: SharedService) {
}
handle(event: UserPropertyChangedEvent): any {
this.sharedService.sendSocketNotificationToAllClients(
SocketEvents.USER_PROPERTY_CHANGED,
{ user: event.user, property: event.property, value: event.propertyValue }
);
handle(event: UserPropertyChangedEvent): void {
this.sharedService.notifyAllClients<IUserPropertyChangedEvent>(ClientNotificationType.UserPropertyChanged, {
user: event.user,
property: event.property,
value: event.propertyValue
});
}
}

View file

@ -1,17 +1,17 @@
import { EventsHandler, IEventHandler } from '@nestjs/cqrs';
import { UserRegisteredEvent } from '../../../game/events/user-registered.event';
import { SharedService } from '../../../shared/shared.service';
import { SocketEvents } from '../../../shared/events.consts';
import {EventsHandler, IEventHandler} from '@nestjs/cqrs';
import {UserRegisteredEvent} from '../../../game/events/user-registered.event';
import {SharedService} from '../../../shared/shared.service';
import {IUserBasicInfo} from "../../../Consts/types";
import {ClientNotificationType} from "../../socket.gateway";
@EventsHandler(UserRegisteredEvent)
export class UserRegisteredEventHandler implements IEventHandler<UserRegisteredEvent> {
constructor(private sharedService: SharedService) {
}
handle(event: UserRegisteredEvent): any {
this.sharedService.sendSocketNotificationToAllClients(
SocketEvents.USER_ADDED,
{
telegramId: event.telegramId,
name: event.name,
handle(event: UserRegisteredEvent): void {
this.sharedService.notifyAllClients<IUserBasicInfo>(ClientNotificationType.UserAdded, {
telegramId: event.telegramId,
name: event.name,
});
}
}

View file

@ -1,7 +1,8 @@
import { EventsHandler, IEventHandler } from '@nestjs/cqrs';
import { ValidAnswerReceivedEvent } from '../../../game/events/valid-answer.recieved';
import { SharedService } from '../../../shared/shared.service';
import { SocketEvents } from '../../../shared/events.consts';
import {EventsHandler, IEventHandler} from '@nestjs/cqrs';
import {ValidAnswerReceivedEvent} from '../../../game/events/valid-answer.recieved';
import {SharedService} from '../../../shared/shared.service';
import {ClientNotificationType} from "../../socket.gateway";
import {IValidAnswerReceivedSocketEvent} from "../../../Consts/types";
@EventsHandler(ValidAnswerReceivedEvent)
export class SocketValidAnswerReceivedEventHandler
@ -11,9 +12,12 @@ export class SocketValidAnswerReceivedEventHandler
}
handle(event: ValidAnswerReceivedEvent): any {
this.sharedService.sendSocketNotificationToAllClients(
SocketEvents.VALID_ANSWER_RECEIVED,
{ telegramId: event.tId, validAnswer: event.validAnswer, note: event.extraDetails },
);
const notification : IValidAnswerReceivedSocketEvent = {
telegramId: event.tId,
validAnswer: event.validAnswer,
note: event.extraDetails
};
this.sharedService
.notifyAllClients<IValidAnswerReceivedSocketEvent>(ClientNotificationType.ValidAnswerReceived, notification);
}
}

View file

@ -10,6 +10,28 @@ import { Server, Socket } from 'socket.io';
import { Injectable, Logger } from "@nestjs/common";
import { from, map, Observable } from 'rxjs';
export const enum ClientNotificationType {
StateChanged = 'state_changed',
PhotosUpdated = 'photos_updated',
ValidAnswerReceived = 'answer_received',
WrongAnswerReceived = 'wrong_answer_received',
UserAdded = 'user_added',
UserPropertyChanged = 'user_property_changed',
CardsChanged = 'cards_changed',
CardPlayed = 'card_played',
ScoreChanged = 'score_changed',
GameQueueItem = 'game_queue',
QueueCompleted = 'queue_completed',
GamePaused = 'game_paused',
GameResumed = 'game_resumed',
Notification = 'notification',
FeatureFlagChanged = 'feature_flag_changed',
BeginVersus = 'begin_versus',
EndVersus = 'end_versus',
QuestionChanged = 'question_changed'
}
@WebSocketGateway({ cors: true, transports: ['websocket']})
@Injectable()
export class SocketGateway implements OnGatewayConnection, OnGatewayDisconnect{
@ -47,7 +69,7 @@ export class SocketGateway implements OnGatewayConnection, OnGatewayDisconnect{
}
notifyAllClients(event: string, payload: any) {
notifyAllClients(event: ClientNotificationType, payload: any) {
this.server.emit("events", { event, data: payload});
// this.logger.warn(`send notification to all clients ${event}`);
// this.clients.forEach((c) => {

View file

@ -1,11 +1,13 @@
import {Body, Controller, Get, Inject, Logger, Param, Post} from '@nestjs/common';
import { StateService } from './state.service';
import { SharedService } from '../shared/shared.service';
import { EventBus } from '@nestjs/cqrs';
import { GameStartedEvent } from '../game/events/game-started.event';
import {StateService} from './state.service';
import {SharedService} from '../shared/shared.service';
import {EventBus} from '@nestjs/cqrs';
import {GameStartedEvent} from '../game/events/game-started.event';
import {ClientProxy} from "@nestjs/microservices";
import {CommandsConsts} from "../Consts/commands.consts";
import {MqtMessageModel} from "../messaging/models/mqt-message.model";
import {ClientNotificationType} from "../socket/socket.gateway";
import {IStateInfo} from "../Consts/types";
interface SetStateDTO {
state: string;
@ -50,7 +52,7 @@ export class StateController {
this.logger.verbose('reset commands');
this.telegramService.emit({ cmd: CommandsConsts.ResetCommands }, {});
}
this.sharedService.sendSocketNotificationToAllClients('state_changed', res);
this.sharedService.notifyAllClients<IStateInfo>(ClientNotificationType.StateChanged, res);
return res;
}
}

View file

@ -4,6 +4,7 @@ import { State, StateDocument } from '../schemas/state.schema';
import { Model } from 'mongoose';
import { EventBus } from '@nestjs/cqrs';
import { PrepareGameEvent } from '../game/events/prepare-game.event';
import {IStateInfo} from "../Consts/types";
interface StateDTO {
name: string;
@ -30,7 +31,7 @@ export class StateService {
return state;
}
async setState(name: string, newValue: string) {
async setState(name: string, newValue: string): Promise<IStateInfo> {
if (newValue === 'onboarding') {
this.eventBus.publish(new PrepareGameEvent());
}
@ -40,6 +41,6 @@ export class StateService {
return {
state: stateEntity.state,
value: stateEntity.value,
}
} as IStateInfo
}
}