Skip to content

Commit

Permalink
feat(prejudiced-manipulator): prejudiced manipulator role (#699)
Browse files Browse the repository at this point in the history
Closes #678
  • Loading branch information
antoinezanardi committed Dec 1, 2023
1 parent 4f67f80 commit f5c8f3c
Show file tree
Hide file tree
Showing 59 changed files with 52,746 additions and 45,600 deletions.
13 changes: 13 additions & 0 deletions .run/Prejudiced Manipulator Role.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Prejudiced Manipulator Role" type="js.build_tools.npm" folderName="Cucumber Tags">
<package-json value="$PROJECT_DIR$/package.json" />
<command value="run" />
<scripts>
<script value="test:cucumber" />
</scripts>
<arguments value="-- --tags &quot;@prejudiced-manipulator-role&quot;" />
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
</component>
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,16 @@ This is the **next** version of the current **[Werewolves Assistant API](https:/

## <a name="available-roles">🃏 Available roles</a>

**27 different official roles** are available to play :

| <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/werewolf/werewolf-small.jpeg?raw=true" width="40"/><br/>**Werewolf** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/big-bad-wolf/big-bad-wolf-small.jpeg?raw=true" width="40"/><br/>**Big Bad Wolf** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/accursed-wolf-father/accursed-wolf-father-small.jpeg?raw=true" width="40"/><br/>**Accursed Wolf-Father** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/white-werewolf/white-werewolf-small.jpeg?raw=true" width="40"/><br/>**White Werewolf** |
|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/villager/villager-small.jpeg?raw=true" width="40"/><br/>**Villager** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/villager/villager-small.jpeg?raw=true" width="40"/><br/> **Villager-Villager** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/seer/seer-small.jpeg?raw=true" width="40"/><br/>**Seer** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/cupid/cupid-small.jpeg?raw=true" width="40"/><br/>**Cupid** |
| <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/witch/witch-small.jpeg?raw=true" width="40"/><br/>**Witch** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/hunter/hunter-small.jpeg?raw=true" width="40"/><br/>**Hunter** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/little-girl/little-girl-small.jpeg?raw=true" width="40"/><br/>**Little Girl** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/defender/defender-small.jpeg?raw=true" width="40"/><br/>**Defender** |
| <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/elder/elder-small.jpeg?raw=true" width="40"/><br/>**Elder** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/scapegoat/scapegoat-small.jpeg?raw=true" width="40"/><br/>**Scapegoat** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/idiot/idiot-small.jpeg?raw=true" width="40"/><br/>**Idiot** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/two-sisters/two-sisters-small.jpeg?raw=true" width="40"/><br/>**Two Sisters** |
| <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/three-brothers/three-brothers-small.jpeg?raw=true" width="40"/><br/>**Three Brothers** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/fox/fox-small.jpeg?raw=true" width="40"/><br/>**Fox** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/bear-tamer/bear-tamer-small.jpeg?raw=true" width="40"/><br/>**Bear Tamer** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/stuttering-judge/stuttering-judge-small.jpeg?raw=true" width="40"/><br/>**Stuttering Judge** |
| <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/rusty-sword-knight/rusty-sword-knight-small.jpeg?raw=true" width="40"/><br/>**Rusty Sword Knight** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/wild-child/wild-child-small.jpeg?raw=true" width="40"/><br/>**Wild Child** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/wolf-hound/wolf-hound-small.jpeg?raw=true" width="40"/><br/>**Wolf-Hound** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/thief/thief-small.jpeg?raw=true" width="40"/><br/>**Thief** |
| <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/angel/angel-small.jpeg?raw=true" width="40"/><br/>**Angel** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/pied-piper/pied-piper-small.jpeg?raw=true" width="40"/><br/>**Pied Piper** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/scandalmonger/scandalmonger-small.jpeg?raw=true" width="40"/><br/>**Scandalmonger** |
**28 different official roles** are available to play :

| <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/werewolf/werewolf-small.jpeg?raw=true" width="40"/><br/>**Werewolf** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/big-bad-wolf/big-bad-wolf-small.jpeg?raw=true" width="40"/><br/>**Big Bad Wolf** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/accursed-wolf-father/accursed-wolf-father-small.jpeg?raw=true" width="40"/><br/>**Accursed Wolf-Father** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/white-werewolf/white-werewolf-small.jpeg?raw=true" width="40"/><br/>**White Werewolf** |
|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/villager/villager-small.jpeg?raw=true" width="40"/><br/>**Villager** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/villager/villager-small.jpeg?raw=true" width="40"/><br/> **Villager-Villager** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/seer/seer-small.jpeg?raw=true" width="40"/><br/>**Seer** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/cupid/cupid-small.jpeg?raw=true" width="40"/><br/>**Cupid** |
| <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/witch/witch-small.jpeg?raw=true" width="40"/><br/>**Witch** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/hunter/hunter-small.jpeg?raw=true" width="40"/><br/>**Hunter** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/little-girl/little-girl-small.jpeg?raw=true" width="40"/><br/>**Little Girl** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/defender/defender-small.jpeg?raw=true" width="40"/><br/>**Defender** |
| <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/elder/elder-small.jpeg?raw=true" width="40"/><br/>**Elder** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/scapegoat/scapegoat-small.jpeg?raw=true" width="40"/><br/>**Scapegoat** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/idiot/idiot-small.jpeg?raw=true" width="40"/><br/>**Idiot** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/two-sisters/two-sisters-small.jpeg?raw=true" width="40"/><br/>**Two Sisters** |
| <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/three-brothers/three-brothers-small.jpeg?raw=true" width="40"/><br/>**Three Brothers** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/fox/fox-small.jpeg?raw=true" width="40"/><br/>**Fox** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/bear-tamer/bear-tamer-small.jpeg?raw=true" width="40"/><br/>**Bear Tamer** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/stuttering-judge/stuttering-judge-small.jpeg?raw=true" width="40"/><br/>**Stuttering Judge** |
| <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/rusty-sword-knight/rusty-sword-knight-small.jpeg?raw=true" width="40"/><br/>**Rusty Sword Knight** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/wild-child/wild-child-small.jpeg?raw=true" width="40"/><br/>**Wild Child** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/wolf-hound/wolf-hound-small.jpeg?raw=true" width="40"/><br/>**Wolf-Hound** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/thief/thief-small.jpeg?raw=true" width="40"/><br/>**Thief** |
| <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/angel/angel-small.jpeg?raw=true" width="40"/><br/>**Angel** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/pied-piper/pied-piper-small.jpeg?raw=true" width="40"/><br/>**Pied Piper** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/scandalmonger/scandalmonger-small.jpeg?raw=true" width="40"/><br/>**Scandalmonger** | <img src="https://github.com/antoinezanardi/werewolves-assistant-api-next/blob/main/public/assets/images/roles/prejudiced-manipulator/prejudiced-manipulator-small.jpeg?raw=true" width="40"/><br/>**Prejudiced Manipulator** |


## <a name="installation">🔨 Installation</a>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { ValidationOptions, ValidationArguments } from "class-validator";
import { registerDecorator } from "class-validator";
import { has } from "lodash";

import type { CreateGameDto } from "@/modules/game/dto/create-game/create-game.dto";
import { RoleNames } from "@/modules/role/enums/role.enum";

function isCompositionGroupsExistenceRespected(value: unknown): boolean {
if (!Array.isArray(value) || value.some(player => !has(player, ["role", "name"]))) {
return false;
}
const players = value as { role: { name: RoleNames }; group?: string }[];
const doesCompositionHasPrejudicedManipulator = players.some(({ role }) => role.name === RoleNames.PREJUDICED_MANIPULATOR);
const doesSomePlayerHaveAGroup = players.some(({ group }) => group !== undefined);
const doesEveryPlayerHaveAGroup = players.every(({ group }) => group !== undefined);
return doesCompositionHasPrejudicedManipulator && doesEveryPlayerHaveAGroup || !doesCompositionHasPrejudicedManipulator && !doesSomePlayerHaveAGroup;
}

function getCompositionGroupsPresenceDefaultMessage(validationArguments: ValidationArguments): string {
const { players } = validationArguments.object as Partial<CreateGameDto>;
const doesCompositionHasPrejudicedManipulator = players?.some(({ role }) => role.name === RoleNames.PREJUDICED_MANIPULATOR) === true;
if (doesCompositionHasPrejudicedManipulator) {
return `each player must have a group if there is a player with role \`${RoleNames.PREJUDICED_MANIPULATOR}\``;
}
return `any player can't have a group if there is no player with role \`${RoleNames.PREJUDICED_MANIPULATOR}\``;
}

function CompositionGroupsPresence(validationOptions?: ValidationOptions) {
return (object: object, propertyName: string): void => {
registerDecorator({
name: "CompositionGroupsConsistency",
target: object.constructor,
propertyName,
options: validationOptions,
validator: {
validate: isCompositionGroupsExistenceRespected,
defaultMessage: getCompositionGroupsPresenceDefaultMessage,
},
});
};
}

export {
CompositionGroupsPresence,
isCompositionGroupsExistenceRespected,
getCompositionGroupsPresenceDefaultMessage,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { ValidationOptions } from "class-validator";
import { registerDecorator } from "class-validator";
import { has } from "lodash";

import { RoleNames } from "@/modules/role/enums/role.enum";

function doesCompositionHasTwoGroupsWithPrejudicedManipulator(value: unknown): boolean {
if (!Array.isArray(value) || value.some(player => !has(player, ["role", "name"]))) {
return false;
}
const players = value as { role: { name: RoleNames }; group?: string }[];
const doesCompositionHasPrejudicedManipulator = players.some(({ role }) => role.name === RoleNames.PREJUDICED_MANIPULATOR);
const distinctGroups = [...new Set(players.map(({ group }) => group))];
const expectedDistinctGroupsCount = 2;
return !doesCompositionHasPrejudicedManipulator || distinctGroups.length === expectedDistinctGroupsCount;
}

function getCompositionHasTwoGroupsWithPrejudicedManipulatorDefaultMessage(): string {
return `there must be exactly two groups among players when \`${RoleNames.PREJUDICED_MANIPULATOR}\` in the game`;
}

function CompositionHasTwoGroupsWithPrejudicedManipulator(validationOptions?: ValidationOptions) {
return (object: object, propertyName: string): void => {
registerDecorator({
name: "CompositionHasTwoGroupsWithPrejudicedManipulator",
target: object.constructor,
propertyName,
options: validationOptions,
validator: {
validate: doesCompositionHasTwoGroupsWithPrejudicedManipulator,
defaultMessage: getCompositionHasTwoGroupsWithPrejudicedManipulatorDefaultMessage,
},
});
};
}

export {
CompositionHasTwoGroupsWithPrejudicedManipulator,
doesCompositionHasTwoGroupsWithPrejudicedManipulator,
getCompositionHasTwoGroupsWithPrejudicedManipulatorDefaultMessage,
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { registerDecorator } from "class-validator";
import isObject from "isobject";
import { has } from "lodash";
import type { ValidationOptions } from "class-validator";

Expand All @@ -8,7 +7,7 @@ import type { RoleNames } from "@/modules/role/enums/role.enum";
import { RoleSides } from "@/modules/role/enums/role.enum";

function doesCompositionHaveAtLeastOneVillager(value?: unknown): boolean {
if (!Array.isArray(value) || value.some(player => !isObject(player) || !has(player, ["role", "name"]))) {
if (!Array.isArray(value) || value.some(player => !has(player, ["role", "name"]))) {
return false;
}
const players = value as { role: { name: RoleNames } }[];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { registerDecorator } from "class-validator";
import isObject from "isobject";
import { has } from "lodash";
import type { ValidationOptions } from "class-validator";

Expand All @@ -8,7 +7,7 @@ import type { RoleNames } from "@/modules/role/enums/role.enum";
import { RoleSides } from "@/modules/role/enums/role.enum";

function doesCompositionHaveAtLeastOneWerewolf(value?: unknown): boolean {
if (!Array.isArray(value) || value.some(player => !isObject(player) || !has(player, ["role", "name"]))) {
if (!Array.isArray(value) || value.some(player => !has(player, ["role", "name"]))) {
return false;
}
const players = value as { role: { name: RoleNames } }[];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { registerDecorator } from "class-validator";
import isObject from "isobject";
import { has } from "lodash";
import type { ValidationOptions } from "class-validator";

import { ROLES } from "@/modules/role/constants/role.constant";
import type { RoleNames } from "@/modules/role/enums/role.enum";

function areCompositionRolesMaxInGameRespected(value?: unknown): boolean {
if (!Array.isArray(value) || value.some(player => !isObject(player) || !has(player, ["role", "name"]))) {
if (!Array.isArray(value) || value.some(player => !has(player, ["role", "name"]))) {
return false;
}
const players = value as { role: { name: RoleNames } }[];
Expand Down

0 comments on commit f5c8f3c

Please sign in to comment.