tgd-backend/src/game/entities/cards.entities.ts
2024-11-15 11:46:07 +04:00

270 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { QuizAnswerStateEnum } from './quiz-answer-state.enum';
import {CommandBus, EventBus, ofType, QueryBus} from '@nestjs/cqrs';
import {Injectable, Logger} from '@nestjs/common';
import { IncreasePlayerWinningRateCommand } from '../commands/increase-player-winning-rate.command';
import { CreateNewQueueItemCommand } from '../commands/create-new-queue-item.command';
import { GameQueueTypes } from '../../schemas/game-queue.schema';
import { NotifyCardOnScreenCommand } from '../commands/notify-card-on-screen-command';
import { SendToastCommand } from '../commands/send-toast.command';
import { getRandomInt } from '../../helpers/rand-number';
import { GiveOutAPrizeCommand } from '../commands/give-out-a-prize.command';
import {SelectTargetPlayerCommand} from "../commands/select-target-player.command";
import {DebuffsConsts} from "./debuffs.consts";
import {NextQuestionEvent} from "../events/next-question.event";
import {FilterGuestsWithPropertyQuery} from "../../guests/queries/filterguestswithproperty.query";
import {DebuffCardPlayedEvent} from "../events/debuff-card-played.event";
import {filter} from "rxjs";
import {SetGuestPropertyCommand} from "../../guests/command/set-guest-property.command";
import {StringHelper} from "../../helpers/stringhelper";
import {GetGuestQuery} from "../../guests/queries/getguest.query";
import {CardsSetChangedEvent} from "../events/cards-events/cards-set-changed.event";
import {GuestPropertiesConsts} from "../../schemas/properties.consts";
import {BeginVersusCommand} from "../commands/begin-versus.command";
import {CheckIfAnotherVersusInProgressQuery} from "../queries/check-if-another-versus-in-progress.query";
export interface IGameCard {
setupHandlers(eventBus: EventBus, commandBus: CommandBus, queryBus: QueryBus): void;
}
export class GameCard implements IGameCard{
protected readonly logger = new Logger(GameCard.name);
protected commandBus: CommandBus;
protected eventBus: EventBus;
protected queryBus: QueryBus;
protected telegramId: number;
protected destinationTelegramId: number;
public handlers: { event: any, commands: any[]}[] = [];
name: string;
description: string;
protected emoji: string;
public dealOnStart = false;
chance = 0;
getEmoji() {
return this.emoji;
}
setup(eb: EventBus, cb: CommandBus, qb: QueryBus, tId: number, destTId: number) {
this.eventBus = eb;
this.commandBus = cb;
this.telegramId = tId;
this.destinationTelegramId = destTId;
this.queryBus = qb;
}
async handle() {
this.logger.verbose(`Card has no handler`);
}
mightBePlayed: QuizAnswerStateEnum;
setupHandlers(eventBus: EventBus, commandBus: CommandBus, queryBus: QueryBus) {
}
}
export class DoubleTreasureCard extends GameCard {
name = DoubleTreasureCard.name;
description = 'Удвоить приз';
chance = 4;
emoji = '💰';
mightBePlayed = QuizAnswerStateEnum.playerGettingReward;
async handle(): Promise<void> {
await this.commandBus.execute(
new NotifyCardOnScreenCommand(this.telegramId, this),
);
await this.commandBus.execute(
new GiveOutAPrizeCommand(this.telegramId),
);
const userSrc = await this.queryBus.execute(new GetGuestQuery(this.telegramId));
const subjcaseFrom = userSrc.get(StringHelper.getPropertyName(GuestPropertiesConsts.NameSubjectiveCase));
const message = `${subjcaseFrom} решает удвоить приз!`;
await this.commandBus.execute(new SendToastCommand(message, 8000));
}
}
export class StolePrizeCard extends GameCard {
name = StolePrizeCard.name;
description = 'Украсть приз';
chance = 15;
emoji = '🥷🏽';
mightBePlayed = QuizAnswerStateEnum.someoneGettingReward;
async handle(): Promise<void> {
this.logger.verbose(`StolePrize from player ${this.telegramId} to player ${this.destinationTelegramId}`);
await this.commandBus.execute(
new NotifyCardOnScreenCommand(this.telegramId, this),
);
const userSrc = await this.queryBus.execute(new GetGuestQuery(this.telegramId));
const userDst = await this.queryBus.execute(new GetGuestQuery(this.destinationTelegramId));
const subjcaseFrom = userSrc.get(StringHelper.getPropertyName(GuestPropertiesConsts.NameSubjectiveCase));
const genitiveTo = userDst.get(StringHelper.getPropertyName(GuestPropertiesConsts.NameGenitiveCase));
const message = `${subjcaseFrom} крадет приз у ${genitiveTo}`;
await this.commandBus.execute(new SendToastCommand(message, 8000));
}
}
export class ShitCard extends GameCard {
name = ShitCard.name;
description = 'Говнокарта';
chance = 50;
emoji = '💩';
mightBePlayed = QuizAnswerStateEnum.someoneAnsweredCorrectly;
async handle(): Promise<void> {
this.logger.verbose(`Shit card from player ${this.telegramId} to player ${this.destinationTelegramId}`);
await this.commandBus.execute(
new NotifyCardOnScreenCommand(this.telegramId, this),
);
await this.commandBus.execute(
new CreateNewQueueItemCommand(
this.destinationTelegramId,
GameQueueTypes.additionalQuestion,
),
);
const userSrc = await this.queryBus.execute(new GetGuestQuery(this.telegramId));
const userDst = await this.queryBus.execute(new GetGuestQuery(this.destinationTelegramId));
const subjcaseFrom = userSrc.get(StringHelper.getPropertyName(GuestPropertiesConsts.NameSubjectiveCase));
const accusativeTo = userDst.get(StringHelper.getPropertyName(GuestPropertiesConsts.NameAccusativeCase));
const message = `${subjcaseFrom} кидает говно-карту в ${accusativeTo}`;
await this.commandBus.execute(new SendToastCommand(message, 8000));
}
}
export class LuckyCard extends GameCard {
name = LuckyCard.name;
description = 'Лаки-карта';
chance = 32;
mightBePlayed = QuizAnswerStateEnum.playerAnsweredCorrectly;
emoji = '🍀';
async handle() {
this.logger.verbose(`Handling card`);
const user = await this.queryBus.execute(new GetGuestQuery(this.telegramId));
const subjcase = user.get(StringHelper.getPropertyName(GuestPropertiesConsts.NameSubjectiveCase));
const message = `${subjcase} использует лаки карту`;
this.logger.verbose(`message: ${message}`);
await this.commandBus.execute(new SendToastCommand(message, 8000));
await this.commandBus.execute(
new NotifyCardOnScreenCommand(this.telegramId, this),
);
await this.commandBus.execute(
new IncreasePlayerWinningRateCommand(
this.telegramId,
getRandomInt(8, 20),
),
);
}
}
export class AvoidPenaltyCard extends GameCard {
dealOnStart = true;
name = AvoidPenaltyCard.name;
description = 'Избежать наказание';
chance = 25;
emoji = '🏃‍';
mightBePlayed = QuizAnswerStateEnum.playerGotPenalty;
async handle() {
const user = await this.queryBus.execute(new GetGuestQuery(this.telegramId));
const subjcase = user.get(StringHelper.getPropertyName(GuestPropertiesConsts.NameSubjectiveCase));
const message = `${subjcase} избегает наказания`;
this.logger.verbose(`message: ${message}`);
await this.commandBus.execute(new SendToastCommand(message, 8000));
await this.commandBus.execute(
new NotifyCardOnScreenCommand(this.telegramId, this),
);
}
}
@Injectable()
export class VersusCard extends GameCard {
dealOnStart = true;
name = VersusCard.name;
chance = 10;
emoji = '🆚';
description = 'Поединок';
mightBePlayed = QuizAnswerStateEnum.betweenRounds;
async setupHandlers(eventBus: EventBus, commandBus: CommandBus, queryBus: QueryBus) {
super.setupHandlers(eventBus, commandBus, queryBus);
eventBus.pipe(
ofType(DebuffCardPlayedEvent),
filter(x => x.debufName == DebuffsConsts.versus))
.subscribe(async (r) =>{
const versusInProgress = await queryBus.execute(new CheckIfAnotherVersusInProgressQuery());
this.logger.verbose(`versusInProgress ${versusInProgress}`);
if(versusInProgress) {
this.logger.warn(`another versus in progress`);
return;
}
const destUser = await queryBus.execute(new GetGuestQuery(r.dest))
const sourceUser = await queryBus.execute(new GetGuestQuery(r.from));
await commandBus.execute(new BeginVersusCommand(sourceUser.telegramId, destUser.telegramId));
});
}
async handle() {
await this.commandBus.execute(
new SelectTargetPlayerCommand(this.telegramId, DebuffsConsts.versus, 0, false)
)
await this.queryBus.execute(new FilterGuestsWithPropertyQuery(null,null,null));
this.eventBus.subscribe((data) =>{
this.logger.verbose(`Response from cmdBus: ${data}`);
});
}
}
@Injectable()
export class BanPlayer extends GameCard {
dealOnStart = true;
name = BanPlayer.name;
description = 'Забанить игрока';
chance = 10;
emoji = '🚷';
mightBePlayed = QuizAnswerStateEnum.betweenRounds;
async setupHandlers(eventBus: EventBus, commandBus: CommandBus, queryBus: QueryBus) {
super.setupHandlers(eventBus, commandBus, queryBus);
eventBus.pipe(ofType(DebuffCardPlayedEvent),filter(x => x.debufName == DebuffsConsts.bannedFor)).subscribe(async (r) => {
const destUser = await queryBus.execute(new GetGuestQuery(r.dest))
const sourceUser = await queryBus.execute(new GetGuestQuery(r.from));
const subjectiveSource = sourceUser.get(StringHelper.getPropertyName(GuestPropertiesConsts.NameSubjectiveCase));
const accusativeDest = destUser.get(StringHelper.getPropertyName(GuestPropertiesConsts.NameAccusativeCase));
const message = `Игрок ${subjectiveSource} забанил ${accusativeDest} `;
await commandBus.execute(new SetGuestPropertyCommand(r.dest, DebuffsConsts.bannedFor, r.data, true));
await commandBus.execute(new SendToastCommand(message, 8000));
await commandBus.execute(new NotifyCardOnScreenCommand(sourceUser.telegramId, this,0 ));
eventBus.publish(new CardsSetChangedEvent(sourceUser.telegramId));
})
eventBus.pipe(ofType(NextQuestionEvent)).subscribe(async (r)=> {
const players = await queryBus.execute(new FilterGuestsWithPropertyQuery(DebuffsConsts.bannedFor, '$gt', 0))
this.logger.verbose(`enter: ban card handler, banned players count ${players.length}`);
players.map(async (player) => {
const newBannedFor = parseInt(player.get(StringHelper.getPropertyName(DebuffsConsts.bannedFor))) - 1;
await commandBus.execute(
new SetGuestPropertyCommand(
player.telegramId, DebuffsConsts.bannedFor,
newBannedFor.toString()
));
});
})
}
async handle() {
await this.commandBus.execute(
new SelectTargetPlayerCommand(this.telegramId, DebuffsConsts.bannedFor, 2,false)
)
await this.queryBus.execute(new FilterGuestsWithPropertyQuery(null,null,null));
this.eventBus.subscribe((data) =>{
this.logger.verbose(`Response from cmdBus: ${data}`);
});
}
}
export const gameCards: typeof GameCard[] = [
DoubleTreasureCard,
StolePrizeCard,
ShitCard,
LuckyCard,
AvoidPenaltyCard,
BanPlayer,
VersusCard,
];