Skip to content

Commit

Permalink
feat(game-queue): game initial upcoming night plays (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
antoinezanardi committed Mar 27, 2023
1 parent 4df092f commit d457b02
Show file tree
Hide file tree
Showing 114 changed files with 22,575 additions and 8,836 deletions.
2 changes: 1 addition & 1 deletion sonar-project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ sonar.test.inclusions=**/*.spec.*s, **/*.e2e-spec.*s
sonar.javascript.lcov.reportPaths=./tests/coverage/lcov.info

# Coverage
sonar.coverage.exclusions=./src/main.ts
sonar.coverage.exclusions=./src/main.ts, ./src/**/*.schema.ts, ./src/**/*.dto.*s

# Encoding
sonar.sourceEncoding=UTF-8
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { CompositionGameOptions } from "../schemas/composition-game-options.schema";
import type { CompositionGameOptions } from "../../schemas/game-options/composition-game-options.schema";
import { defaultGameOptions } from "./game-options.constant";

const compositionGameOptionsFieldsSpecs = Object.freeze({ isHidden: { default: defaultGameOptions.composition.isHidden } });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import { GAME_PHASES } from "../../../enums/game.enum";
import type { GameOptions } from "../schemas/game-options.schema";
import { GAME_PHASES } from "../../enums/game.enum";
import type { GameOptions } from "../../schemas/game-options/game-options.schema";

const defaultGameOptions: GameOptions = Object.freeze({
composition: { isHidden: true },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { AncientGameOptions } from "../../schemas/roles-game-options/ancient-game-options.schema";
import type { AncientGameOptions } from "../../../schemas/game-options/roles-game-options/ancient-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const ancientGameOptionsFieldsSpecs = Object.freeze({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { BearTamerGameOptions } from "../../schemas/roles-game-options/bear-tamer-game-options.schema";
import type { BearTamerGameOptions } from "../../../schemas/game-options/roles-game-options/bear-tamer-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const bearTamerGameOptionsFieldsSpecs = Object.freeze({ doesGrowlIfInfected: { default: defaultGameOptions.roles.bearTamer.doesGrowlIfInfected } });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { BigBadWolfGameOptions } from "../../schemas/roles-game-options/big-bad-wolf-game-options.schema";
import type { BigBadWolfGameOptions } from "../../../schemas/game-options/roles-game-options/big-bad-wolf-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const bigBadWolfGameOptionsFieldsSpecs = Object.freeze({ isPowerlessIfWerewolfDies: { default: defaultGameOptions.roles.bigBadWolf.isPowerlessIfWerewolfDies } });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { DogWolfGameOptions } from "../../schemas/roles-game-options/dog-wolf-game-options.schema";
import type { DogWolfGameOptions } from "../../../schemas/game-options/roles-game-options/dog-wolf-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const dogWolfGameOptionsFieldsSpecs = Object.freeze({ isChosenSideRevealed: { default: defaultGameOptions.roles.dogWolf.isChosenSideRevealed } });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { FoxGameOptions } from "../../schemas/roles-game-options/fox-game-options.schema";
import type { FoxGameOptions } from "../../../schemas/game-options/roles-game-options/fox-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const foxGameOptionsFieldsSpecs = Object.freeze({ isPowerlessIfMissesWerewolf: { default: defaultGameOptions.roles.fox.isPowerlessIfMissesWerewolf } });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { GuardGameOptions } from "../../schemas/roles-game-options/guard-game-options.schema";
import type { GuardGameOptions } from "../../../schemas/game-options/roles-game-options/guard-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const guardGameOptionsFieldsSpecs = Object.freeze({ canProtectTwice: { default: defaultGameOptions.roles.guard.canProtectTwice } });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { IdiotGameOptions } from "../../schemas/roles-game-options/idiot-game-options.schema";
import type { IdiotGameOptions } from "../../../schemas/game-options/roles-game-options/idiot-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const idiotGameOptionsFieldsSpecs = Object.freeze({ doesDieOnAncientDeath: { default: defaultGameOptions.roles.idiot.doesDieOnAncientDeath } });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { LittleGirlGameOptions } from "../../schemas/roles-game-options/little-girl-game-options.schema";
import type { LittleGirlGameOptions } from "../../../schemas/game-options/roles-game-options/little-girl-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const littleGirlGameOptionsFieldsSpecs = Object.freeze({ isProtectedByGuard: { default: defaultGameOptions.roles.littleGirl.isProtectedByGuard } });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { PiedPiperGameOptions } from "../../schemas/roles-game-options/pied-piper-game-options.schema";
import type { PiedPiperGameOptions } from "../../../schemas/game-options/roles-game-options/pied-piper-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const piedPiperGameOptionsFieldsSpecs = Object.freeze({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { RavenGameOptions } from "../../schemas/roles-game-options/raven-game-options.schema";
import type { RavenGameOptions } from "../../../schemas/game-options/roles-game-options/raven-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const ravenGameOptionsFieldsSpecs = Object.freeze({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { RolesGameOptions } from "../../schemas/roles-game-options/roles-game-options.schema";
import type { RolesGameOptions } from "../../../schemas/game-options/roles-game-options/roles-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const rolesGameOptionsFieldsSpecs = Object.freeze({ areRevealedOnDeath: { default: defaultGameOptions.roles.areRevealedOnDeath } });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { SeerGameOptions } from "../../schemas/roles-game-options/seer-game-options.schema";
import type { SeerGameOptions } from "../../../schemas/game-options/roles-game-options/seer-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const seerGameOptionsFieldsSpecs = Object.freeze({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { SheriffElectionGameOptions } from "../../../schemas/roles-game-options/sheriff-game-options/sheriff-election-game-options.schema";
import type { SheriffElectionGameOptions } from "../../../../schemas/game-options/roles-game-options/sheriff-game-options/sheriff-election-game-options.schema";
import { defaultGameOptions } from "../../game-options.constant";

const sheriffElectionGameOptionsFieldsSpecs = Object.freeze({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { SheriffGameOptions } from "../../../schemas/roles-game-options/sheriff-game-options/sheriff-game-options.schema";
import type { SheriffGameOptions } from "../../../../schemas/game-options/roles-game-options/sheriff-game-options/sheriff-game-options.schema";
import { defaultGameOptions } from "../../game-options.constant";

const sheriffGameOptionsFieldsSpecs = Object.freeze({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { StutteringJudgeGameOptions } from "../../schemas/roles-game-options/stuttering-judge-game-options.schema";
import type { StutteringJudgeGameOptions } from "../../../schemas/game-options/roles-game-options/stuttering-judge-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const stutteringJudgeGameOptionsFieldsSpecs = Object.freeze({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { ThiefGameOptions } from "../../schemas/roles-game-options/thief-game-options.schema";
import type { ThiefGameOptions } from "../../../schemas/game-options/roles-game-options/thief-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const thiefGameOptionsFieldsSpecs = Object.freeze({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { ThreeBrothersGameOptions } from "../../schemas/roles-game-options/three-brothers-game-options.schema";
import type { ThreeBrothersGameOptions } from "../../../schemas/game-options/roles-game-options/three-brothers-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const threeBrothersGameOptionsFieldsSpecs = Object.freeze({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { TwoSistersGameOptions } from "../../schemas/roles-game-options/two-sisters-game-options.schema";
import type { TwoSistersGameOptions } from "../../../schemas/game-options/roles-game-options/two-sisters-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const twoSistersGameOptionsFieldsSpecs = Object.freeze({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { WhiteWerewolfGameOptions } from "../../schemas/roles-game-options/white-werewolf-game-options.schema";
import type { WhiteWerewolfGameOptions } from "../../../schemas/game-options/roles-game-options/white-werewolf-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const whiteWerewolfGameOptionsFieldsSpecs = Object.freeze({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { WildChildGameOptions } from "../../schemas/roles-game-options/wild-child-game-options.schema";
import type { WildChildGameOptions } from "../../../schemas/game-options/roles-game-options/wild-child-game-options.schema";
import { defaultGameOptions } from "../game-options.constant";

const wildChildGameOptionsFieldsSpecs = Object.freeze({ isTransformationRevealed: { default: defaultGameOptions.roles.wildChild.isTransformationRevealed } });
Expand Down
111 changes: 111 additions & 0 deletions src/modules/game/constants/game-play.constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import { ROLE_NAMES } from "../../role/enums/role.enum";
import { GAME_PLAY_ACTIONS } from "../enums/game-play.enum";
import { PLAYER_GROUPS } from "../enums/player.enum";
import type { GamePlay } from "../schemas/game-play.schema";
import { gameSourceValues } from "./game.constant";

const gamePlayApiProperties: Record<keyof GamePlay, ApiPropertyOptions> = Object.freeze({
source: {
description: "Which role or group of people need to perform this action",
enum: gameSourceValues,
},
action: {
description: "What action need to be performed for this play",
example: GAME_PLAY_ACTIONS.VOTE,
},
cause: { description: "Why this play needs to be performed" },
});

const gamePlaysNightOrder: readonly (GamePlay & { isFirstNightOnly?: boolean })[] = Object.freeze([
{
source: PLAYER_GROUPS.ALL,
action: GAME_PLAY_ACTIONS.VOTE,
isFirstNightOnly: true,
},
{
source: ROLE_NAMES.THIEF,
action: GAME_PLAY_ACTIONS.CHOOSE_CARD,
isFirstNightOnly: true,
},
{
source: ROLE_NAMES.DOG_WOLF,
action: GAME_PLAY_ACTIONS.CHOOSE_SIDE,
isFirstNightOnly: true,
},
{
source: ROLE_NAMES.CUPID,
action: GAME_PLAY_ACTIONS.CHARM,
isFirstNightOnly: true,
},
{
source: ROLE_NAMES.SEER,
action: GAME_PLAY_ACTIONS.LOOK,
},
{
source: ROLE_NAMES.FOX,
action: GAME_PLAY_ACTIONS.SNIFF,
},
{
source: PLAYER_GROUPS.LOVERS,
action: GAME_PLAY_ACTIONS.MEET_EACH_OTHER,
isFirstNightOnly: true,
},
{
source: ROLE_NAMES.STUTTERING_JUDGE,
action: GAME_PLAY_ACTIONS.CHOOSE_SIGN,
isFirstNightOnly: true,
},
{
source: ROLE_NAMES.TWO_SISTERS,
action: GAME_PLAY_ACTIONS.MEET_EACH_OTHER,
},
{
source: ROLE_NAMES.THREE_BROTHERS,
action: GAME_PLAY_ACTIONS.MEET_EACH_OTHER,
},
{
source: ROLE_NAMES.WILD_CHILD,
action: GAME_PLAY_ACTIONS.CHOOSE_MODEL,
isFirstNightOnly: true,
},
{
source: ROLE_NAMES.RAVEN,
action: GAME_PLAY_ACTIONS.MARK,
},
{
source: ROLE_NAMES.GUARD,
action: GAME_PLAY_ACTIONS.PROTECT,
},
{
source: PLAYER_GROUPS.WEREWOLVES,
action: GAME_PLAY_ACTIONS.EAT,
},
{
source: ROLE_NAMES.WHITE_WEREWOLF,
action: GAME_PLAY_ACTIONS.EAT,
},
{
source: ROLE_NAMES.BIG_BAD_WOLF,
action: GAME_PLAY_ACTIONS.EAT,
},
{
source: ROLE_NAMES.WITCH,
action: GAME_PLAY_ACTIONS.USE_POTIONS,
},
{
source: ROLE_NAMES.PIED_PIPER,
action: GAME_PLAY_ACTIONS.CHARM,
},
{
source: PLAYER_GROUPS.CHARMED,
action: GAME_PLAY_ACTIONS.MEET_EACH_OTHER,
},
]);

const sheriffElectionPlay: GamePlay = Object.freeze({
source: PLAYER_GROUPS.ALL,
action: GAME_PLAY_ACTIONS.ELECT_SHERIFF,
});

export { gamePlayApiProperties, gamePlaysNightOrder, sheriffElectionPlay };
8 changes: 7 additions & 1 deletion src/modules/game/constants/game.constant.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import { ROLE_NAMES } from "../../role/enums/role.enum";
import { GAME_PHASES, GAME_STATUSES } from "../enums/game.enum";
import { PLAYER_ATTRIBUTE_NAMES, PLAYER_GROUPS } from "../enums/player.enum";
import type { Game } from "../schemas/game.schema";
import type { GameSource } from "../types/game.type";

const gameFieldsSpecs = Object.freeze({
players: {
Expand Down Expand Up @@ -38,9 +41,12 @@ const gameApiProperties: Record<keyof Game, ApiPropertyOptions> = Object.freeze(
description: "Players of the game",
...gameFieldsSpecs.players,
},
upcomingPlays: { description: "Queue of upcoming plays that needs to be performed to continue the game" },
options: { description: "Game's options" },
createdAt: { description: "When the game was created" },
updatedAt: { description: "When the game was updated" },
});

export { gameFieldsSpecs, gameApiProperties };
const gameSourceValues: readonly GameSource[] = Object.freeze([...Object.values(PLAYER_GROUPS), ...Object.values(ROLE_NAMES), PLAYER_ATTRIBUTE_NAMES.SHERIFF]);

export { gameFieldsSpecs, gameApiProperties, gameSourceValues };
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { PlayerAttributeActivation } from "../schemas/player-attribute-activation.schema";
import type { PlayerAttributeActivation } from "../../../schemas/player/player-attribute/player-attribute-activation.schema";

const playerAttributeActivationFieldsSpecs = Object.freeze({ turn: { minimum: 1 } });

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import { ROLE_NAMES } from "../../../../../../role/enums/role.enum";
import { PLAYER_GROUPS } from "../../../enums/player-enum";
import { PLAYER_ATTRIBUTE_NAMES } from "../enums/player-attribute.enum";
import type { PlayerAttribute } from "../schemas/player-attribute.schema";
import type { PlayerAttribute } from "../../../schemas/player/player-attribute/player-attribute.schema";
import { gameSourceValues } from "../../game.constant";

const playerAttributeFieldsSpecs = Object.freeze({ remainingPhases: { minimum: 1 } });

const playerAttributeApiProperties: Record<keyof PlayerAttribute, ApiPropertyOptions> = Object.freeze({
name: { description: "Attribute's name on the player." },
source: {
description: "Which entity gave this attribute to the player",
enum: [...Object.values(PLAYER_GROUPS), ...Object.values(ROLE_NAMES), PLAYER_ATTRIBUTE_NAMES.SHERIFF],
enum: gameSourceValues,
},
remainingPhases: {
description: "Remaining time for this attribute before disappear. If not set, the attribute will remain forever on the player. Else, decreases after each `phase` if `activeAt` conditions are met or if `activeAt` is not set",
Expand Down
13 changes: 13 additions & 0 deletions src/modules/game/constants/player/player-death.constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { PlayerDeath } from "../../schemas/player/player-death.schema";
import { gameSourceValues } from "../game.constant";

const playerDeathApiProperties: Record<keyof PlayerDeath, ApiPropertyOptions> = Object.freeze({
source: {
description: "Which entity killed the player",
enum: gameSourceValues,
},
cause: { description: "Death's cause of the player" },
});

export { playerDeathApiProperties };
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { PlayerRole } from "../schemas/player-role.schema";
import type { PlayerRole } from "../../schemas/player/player-role.schema";

const playerRoleApiProperties: Record<keyof PlayerRole, ApiPropertyOptions> = Object.freeze({
original: { description: "Player's original role when the game started" },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { PlayerSide } from "../schemas/player-side.schema";
import type { PlayerSide } from "../../schemas/player/player-side.schema";

const playerSideApiProperties: Record<keyof PlayerSide, ApiPropertyOptions> = Object.freeze({
original: { description: "Player's original side when the game started" },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ApiPropertyOptions } from "@nestjs/swagger";
import type { Player } from "../schemas/player.schema";
import type { Player } from "../../schemas/player/player.schema";

const playersFieldsSpecs = Object.freeze({
name: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ApiProperty } from "@nestjs/swagger";
import { IsBoolean, IsEnum } from "class-validator";
import { ROLE_NAMES } from "../../../../../role/enums/role.enum";
import { playerApiProperties } from "../../../../schemas/player/constants/player.constant";
import { playerRoleApiProperties } from "../../../../schemas/player/schemas/player-role/constants/player-role.constant";
import { playerRoleApiProperties } from "../../../../constants/player/player-role.constant";
import { playerApiProperties } from "../../../../constants/player/player.constant";

class GamePlayerRoleBaseDto {
@ApiProperty(playerApiProperties.role)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ApiProperty } from "@nestjs/swagger";
import { IsEnum } from "class-validator";
import { ROLE_SIDES } from "../../../../../role/enums/role.enum";
import { playerSideApiProperties } from "../../../../schemas/player/schemas/player-side/constants/player-side.constant";
import { playerSideApiProperties } from "../../../../constants/player/player-side.constant";

class GamePlayerSideBaseDto {
@ApiProperty(playerSideApiProperties.original)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ApiProperty } from "@nestjs/swagger";
import { Transform, Type } from "class-transformer";
import { IsInt, IsString, MaxLength, Min, MinLength, ValidateNested } from "class-validator";
import { playerApiProperties, playersFieldsSpecs } from "../../../schemas/player/constants/player.constant";
import { playerApiProperties, playersFieldsSpecs } from "../../../constants/player/player.constant";
import { GamePlayerRoleBaseDto } from "./game-player-role/game-player-role.base.dto";
import { GamePlayerSideBaseDto } from "./game-player-side/game-player-side.base.dto";
import { playerRoleTransformer } from "./transformers/player-role.transformer";
Expand Down

0 comments on commit d457b02

Please sign in to comment.