270 lines
11 KiB
TypeScript
270 lines
11 KiB
TypeScript
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,
|
||
];
|