Merge pull request 'TGD-58' (#4) from features/TGD-58 into 2024edition
Reviewed-on: #4
This commit is contained in:
commit
a50ebed297
3 changed files with 130 additions and 20 deletions
|
|
@ -2,4 +2,5 @@ export class FeatureFlagsConsts {
|
||||||
static EnableEndgamePoints = 'EnableEndgamePoints';
|
static EnableEndgamePoints = 'EnableEndgamePoints';
|
||||||
static DontMarkQuestionsAsCompleted = 'DontMarkQuestionsAsCompleted';
|
static DontMarkQuestionsAsCompleted = 'DontMarkQuestionsAsCompleted';
|
||||||
static DisableVoice = 'DisableVoice';
|
static DisableVoice = 'DisableVoice';
|
||||||
|
static StartVersusIfPlayersAnsweredInSameTime = 'StartVersusIfPlayersAnsweredInSameTime';
|
||||||
}
|
}
|
||||||
|
|
@ -8,16 +8,19 @@ import {GuestsService} from "../guests/guests.service";
|
||||||
import {GuestsServiceMock} from "../mocks/guests-service.mock";
|
import {GuestsServiceMock} from "../mocks/guests-service.mock";
|
||||||
import {SharedService} from "../shared/shared.service";
|
import {SharedService} from "../shared/shared.service";
|
||||||
import {SharedServiceMock} from "../mocks/shared-service.mock";
|
import {SharedServiceMock} from "../mocks/shared-service.mock";
|
||||||
import {CommandBus, EventBus} from "@nestjs/cqrs";
|
import {CommandBus, EventBus, ICommand} from "@nestjs/cqrs";
|
||||||
import {EventbusMock} from "../mocks/eventbus.mock";
|
import {EventbusMock} from "../mocks/eventbus.mock";
|
||||||
import {CommandbusMock} from "../mocks/commandbus.mock";
|
import {CommandbusMock} from "../mocks/commandbus.mock";
|
||||||
import {FeatureflagService} from "../featureflag/featureflag.service";
|
import {FeatureflagService, IFeatureFlagStatus} from "../featureflag/featureflag.service";
|
||||||
import {FeatureflagServiceMock} from "../mocks/featureflag-service.mock";
|
import {FeatureflagServiceMock} from "../mocks/featureflag-service.mock";
|
||||||
import {IncreasePlayerWinningRateCommand} from "../game/commands/increase-player-winning-rate.command";
|
import {IncreasePlayerWinningRateCommand} from "../game/commands/increase-player-winning-rate.command";
|
||||||
import {IncreasePlayerScoreCommand} from "../guests/command/increase-player-score.command";
|
import {IncreasePlayerScoreCommand} from "../guests/command/increase-player-score.command";
|
||||||
import {getRandomInt} from "../helpers/rand-number";
|
import {getRandomInt} from "../helpers/rand-number";
|
||||||
import {CreateNewQueueItemCommand} from "../game/commands/create-new-queue-item.command";
|
import {CreateNewQueueItemCommand} from "../game/commands/create-new-queue-item.command";
|
||||||
import {GameQueueTypes} from "../schemas/game-queue.schema";
|
import {GameQueueTypes} from "../schemas/game-queue.schema";
|
||||||
|
import {BeginVersusCommand} from "../game/commands/begin-versus.command"
|
||||||
|
import spyOn = jest.spyOn;
|
||||||
|
import clearAllMocks = jest.clearAllMocks;
|
||||||
|
|
||||||
jest.mock('../../src/helpers/rand-number');
|
jest.mock('../../src/helpers/rand-number');
|
||||||
|
|
||||||
|
|
@ -25,6 +28,7 @@ describe('QuizService', () => {
|
||||||
let service: QuizService;
|
let service: QuizService;
|
||||||
let cmdBus: CommandBus;
|
let cmdBus: CommandBus;
|
||||||
let guestService: GuestsService;
|
let guestService: GuestsService;
|
||||||
|
let featureFlagService: FeatureflagService;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const module: TestingModule = await Test.createTestingModule({
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
|
@ -43,6 +47,7 @@ describe('QuizService', () => {
|
||||||
service = await module.resolve<QuizService>(QuizService);
|
service = await module.resolve<QuizService>(QuizService);
|
||||||
cmdBus = await module.resolve<CommandBus>(CommandBus);
|
cmdBus = await module.resolve<CommandBus>(CommandBus);
|
||||||
guestService = await module.resolve<GuestsService>(GuestsService);
|
guestService = await module.resolve<GuestsService>(GuestsService);
|
||||||
|
featureFlagService = await module.resolve<FeatureflagService>(FeatureflagService);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be defined', () => {
|
it('should be defined', () => {
|
||||||
|
|
@ -50,6 +55,8 @@ describe('QuizService', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('calculateScore()', () => {
|
describe('calculateScore()', () => {
|
||||||
|
let cmdBusExecSpy: jest.SpyInstance<Promise<unknown>, [command: ICommand], any>;
|
||||||
|
let getSpy;
|
||||||
const questionDocumentMock = {
|
const questionDocumentMock = {
|
||||||
text: 'test question',
|
text: 'test question',
|
||||||
answered: false,
|
answered: false,
|
||||||
|
|
@ -70,16 +77,22 @@ describe('QuizService', () => {
|
||||||
user: 3,
|
user: 3,
|
||||||
time: new Date(),
|
time: new Date(),
|
||||||
valid: true,
|
valid: true,
|
||||||
|
}, {
|
||||||
|
user: 4,
|
||||||
|
time: new Date(),
|
||||||
|
valid: false,
|
||||||
}],
|
}],
|
||||||
scoreCalculated: false,
|
scoreCalculated: false,
|
||||||
save: jest.fn(),
|
save: jest.fn(),
|
||||||
};
|
};
|
||||||
|
beforeEach(() => {
|
||||||
|
cmdBusExecSpy = jest.spyOn(cmdBus, 'execute').mockResolvedValue(null);
|
||||||
|
getSpy = jest.spyOn(service,'get').mockResolvedValue(questionDocumentMock as any);
|
||||||
|
});
|
||||||
|
|
||||||
it('should not calculate score if it is already calculated', async () => {
|
it('should not calculate score if it is already calculated', async () => {
|
||||||
// setup
|
// setup
|
||||||
questionDocumentMock.scoreCalculated = true;
|
questionDocumentMock.scoreCalculated = true;
|
||||||
const getSpy = jest.spyOn(service,'get').mockResolvedValue(questionDocumentMock as any);
|
|
||||||
const cmdBusExecSpy = jest.spyOn(cmdBus, 'execute').mockResolvedValue(null);
|
|
||||||
|
|
||||||
// act
|
// act
|
||||||
await service.calculateScore();
|
await service.calculateScore();
|
||||||
|
|
@ -92,8 +105,6 @@ describe('QuizService', () => {
|
||||||
it('should assign points to winner', async () => {
|
it('should assign points to winner', async () => {
|
||||||
//setup
|
//setup
|
||||||
questionDocumentMock.scoreCalculated = false;
|
questionDocumentMock.scoreCalculated = false;
|
||||||
const getSpy = jest.spyOn(service, 'get').mockResolvedValue(questionDocumentMock as any);
|
|
||||||
const cmdBusExecSpy = jest.spyOn(cmdBus, 'execute');
|
|
||||||
|
|
||||||
// act
|
// act
|
||||||
await service.calculateScore();
|
await service.calculateScore();
|
||||||
|
|
@ -110,8 +121,6 @@ describe('QuizService', () => {
|
||||||
// setup
|
// setup
|
||||||
(getRandomInt as jest.Mock).mockReturnValue(65);
|
(getRandomInt as jest.Mock).mockReturnValue(65);
|
||||||
questionDocumentMock.scoreCalculated = false;
|
questionDocumentMock.scoreCalculated = false;
|
||||||
const getSpy = jest.spyOn(service, 'get').mockResolvedValue(questionDocumentMock as any);
|
|
||||||
const cmdBusExecSpy = jest.spyOn(cmdBus, 'execute');
|
|
||||||
const whoShouldGetPenalty = questionDocumentMock.userAnswers.find(x => x.user == 2);
|
const whoShouldGetPenalty = questionDocumentMock.userAnswers.find(x => x.user == 2);
|
||||||
|
|
||||||
//act
|
//act
|
||||||
|
|
@ -127,8 +136,6 @@ describe('QuizService', () => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
(getRandomInt as jest.Mock).mockReturnValue(10);
|
(getRandomInt as jest.Mock).mockReturnValue(10);
|
||||||
questionDocumentMock.scoreCalculated = false;
|
questionDocumentMock.scoreCalculated = false;
|
||||||
jest.spyOn(service, 'get').mockResolvedValue(questionDocumentMock as any);
|
|
||||||
const cmdBusExecSpy = jest.spyOn(cmdBus, 'execute');
|
|
||||||
const whoShouldGetPenalty = questionDocumentMock.userAnswers.find(x => x.user == 2);
|
const whoShouldGetPenalty = questionDocumentMock.userAnswers.find(x => x.user == 2);
|
||||||
|
|
||||||
//act
|
//act
|
||||||
|
|
@ -141,16 +148,15 @@ describe('QuizService', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should set score calculated after calculation', async () => {
|
it('should set score calculated after calculation', async () => {
|
||||||
|
// setup
|
||||||
questionDocumentMock.scoreCalculated = false;
|
questionDocumentMock.scoreCalculated = false;
|
||||||
const saveSpy = jest.spyOn(questionDocumentMock,'save').mockResolvedValue(true);
|
const saveSpy = jest.spyOn(questionDocumentMock,'save').mockResolvedValue(true);
|
||||||
jest.spyOn(service, 'get').mockResolvedValue(questionDocumentMock as any);
|
|
||||||
|
|
||||||
// act
|
// act
|
||||||
await service.calculateScore();
|
await service.calculateScore();
|
||||||
|
|
||||||
//validate
|
//validate
|
||||||
expect(saveSpy).toHaveBeenCalled();
|
expect(saveSpy).toHaveBeenCalled();
|
||||||
})
|
});
|
||||||
|
|
||||||
it('should add show results in queue', async () => {
|
it('should add show results in queue', async () => {
|
||||||
// setup
|
// setup
|
||||||
|
|
@ -165,6 +171,90 @@ describe('QuizService', () => {
|
||||||
|
|
||||||
// validate
|
// validate
|
||||||
expect(cmdBusExecSpy).toHaveBeenCalledWith(new CreateNewQueueItemCommand(expect.anything(), GameQueueTypes.showresults));
|
expect(cmdBusExecSpy).toHaveBeenCalledWith(new CreateNewQueueItemCommand(expect.anything(), GameQueueTypes.showresults));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should start versus if user replied in less than 5 seconds if ff enabled', async () => {
|
||||||
|
// setup
|
||||||
|
questionDocumentMock.scoreCalculated = false;
|
||||||
|
const ffstate: IFeatureFlagStatus = {
|
||||||
|
name: '',
|
||||||
|
state: true,
|
||||||
|
}
|
||||||
|
spyOn(featureFlagService,'getFeatureFlag').mockResolvedValue(ffstate);
|
||||||
|
questionDocumentMock.userAnswers = [{
|
||||||
|
user: 1,
|
||||||
|
time: new Date(new Date().setSeconds(new Date().getSeconds() - 5)),
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
user: 2,
|
||||||
|
time: new Date(),
|
||||||
|
valid: true,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
getSpy = jest.spyOn(service,'get').mockResolvedValue(questionDocumentMock as any);
|
||||||
|
|
||||||
|
// act
|
||||||
|
await service.calculateScore();
|
||||||
|
|
||||||
|
// validate
|
||||||
|
expect(cmdBusExecSpy).toHaveBeenCalledWith(new BeginVersusCommand(expect.anything(), expect.anything()));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not start versus if FF is off and gap less than 5', async () => {
|
||||||
|
// setup
|
||||||
|
jest.clearAllMocks();
|
||||||
|
questionDocumentMock.scoreCalculated = false;
|
||||||
|
const ffstate: IFeatureFlagStatus = {
|
||||||
|
name: '',
|
||||||
|
state: false,
|
||||||
|
}
|
||||||
|
spyOn(featureFlagService,'getFeatureFlag').mockResolvedValue(ffstate);
|
||||||
|
questionDocumentMock.userAnswers = [{
|
||||||
|
user: 1,
|
||||||
|
time: new Date(new Date().setSeconds(new Date().getSeconds() - 3)),
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
user: 2,
|
||||||
|
time: new Date(),
|
||||||
|
valid: true,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
getSpy = jest.spyOn(service,'get').mockResolvedValue(questionDocumentMock as any);
|
||||||
|
|
||||||
|
// act
|
||||||
|
await service.calculateScore();
|
||||||
|
|
||||||
|
// validate
|
||||||
|
expect(cmdBusExecSpy).not.toHaveBeenCalledWith(new BeginVersusCommand(expect.anything(), expect.anything()));
|
||||||
|
|
||||||
|
});
|
||||||
|
it('should not start versus if gap more than 5 seconds', async () => {
|
||||||
|
// setup
|
||||||
|
questionDocumentMock.scoreCalculated = false;
|
||||||
|
questionDocumentMock.userAnswers = [{
|
||||||
|
user: 1,
|
||||||
|
time: new Date(new Date().setSeconds(new Date().getSeconds() - 7)),
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
user: 2,
|
||||||
|
time: new Date(),
|
||||||
|
valid: true,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
getSpy = jest.spyOn(service,'get').mockResolvedValue(questionDocumentMock as any);
|
||||||
|
|
||||||
|
// act
|
||||||
|
await service.calculateScore();
|
||||||
|
// validate
|
||||||
|
expect(cmdBusExecSpy).not.toHaveBeenCalledWith(new BeginVersusCommand(expect.anything(), expect.anything()));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not start versus if only one player answered correctly', () => {
|
||||||
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import {FeatureflagService} from "../featureflag/featureflag.service";
|
||||||
import {FeatureFlagsConsts} from "../Consts/FeatureFlags.consts";
|
import {FeatureFlagsConsts} from "../Consts/FeatureFlags.consts";
|
||||||
import {QuizEndGameResults} from "./quiz.types";
|
import {QuizEndGameResults} from "./quiz.types";
|
||||||
import {ClientNotificationType} from "../socket/socket.gateway";
|
import {ClientNotificationType} from "../socket/socket.gateway";
|
||||||
|
import {BeginVersusCommand} from "../game/commands/begin-versus.command";
|
||||||
|
|
||||||
@Injectable({ scope: Scope.TRANSIENT })
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
export class QuizService {
|
export class QuizService {
|
||||||
|
|
@ -120,6 +121,14 @@ export class QuizService {
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private checkIfWeShouldStartVersus(answers: { valid: boolean; time: number; user: number }[]) {
|
||||||
|
if(answers.length === 0 && answers.length <= 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const diff = Math.abs(new Date(answers[0].time).getTime() - new Date(answers[1].time).getTime()) / 1000;
|
||||||
|
return diff <= 5;
|
||||||
|
}
|
||||||
|
|
||||||
async calculateScore() {
|
async calculateScore() {
|
||||||
const question = await this.get();
|
const question = await this.get();
|
||||||
if(question.scoreCalculated) {
|
if(question.scoreCalculated) {
|
||||||
|
|
@ -148,6 +157,16 @@ export class QuizService {
|
||||||
totalWinningScore / sortedAnswers.filter((answer) => answer.valid).length));
|
totalWinningScore / sortedAnswers.filter((answer) => answer.valid).length));
|
||||||
this.commandBus.execute(new IncreasePlayerScoreCommand(answer.user,1));
|
this.commandBus.execute(new IncreasePlayerScoreCommand(answer.user,1));
|
||||||
});
|
});
|
||||||
|
const ffState = await this.featureFlagService.getFeatureFlag(FeatureFlagsConsts.StartVersusIfPlayersAnsweredInSameTime)
|
||||||
|
if(ffState.state) {
|
||||||
|
if(this.checkIfWeShouldStartVersus(sortedAnswers.filter(x => x.valid))) {
|
||||||
|
await this.commandBus.execute(
|
||||||
|
new BeginVersusCommand(
|
||||||
|
sortedAnswers.filter(x => x.valid)[0].user,
|
||||||
|
sortedAnswers.filter(x => x.valid)[1].user,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
await this.commandBus.execute(new IncreasePlayerWinningRateCommand(sortedAnswers[0].user, 15));
|
await this.commandBus.execute(new IncreasePlayerWinningRateCommand(sortedAnswers[0].user, 15));
|
||||||
this.logger.debug(`Giving 1 point to first`);
|
this.logger.debug(`Giving 1 point to first`);
|
||||||
await this.commandBus.execute(new IncreasePlayerScoreCommand(winner.user,1));
|
await this.commandBus.execute(new IncreasePlayerScoreCommand(winner.user,1));
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue