mirror of
https://github.com/AlecM33/Werewolf.git
synced 2026-02-10 04:03:33 +01:00
Add independent alignment for custom roles (#217)
* Initial plan * Add independent alignment: constants, validation, UI, and CSS Co-authored-by: AlecM33 <24642328+AlecM33@users.noreply.github.com> * Add unit tests for independent alignment validation Co-authored-by: AlecM33 <24642328+AlecM33@users.noreply.github.com> * Fix remaining binary alignment checks in role display Co-authored-by: AlecM33 <24642328+AlecM33@users.noreply.github.com> * Add independent player container and game-role-independent CSS Co-authored-by: AlecM33 <24642328+AlecM33@users.noreply.github.com> * fix a couple bugs, tweak colors * remove import * remove duplicate tag --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: AlecM33 <24642328+AlecM33@users.noreply.github.com> Co-authored-by: AlecM33 <leohfx@gmail.com>
This commit is contained in:
@@ -21,7 +21,8 @@ export const STATUS = {
|
|||||||
|
|
||||||
export const ALIGNMENT = {
|
export const ALIGNMENT = {
|
||||||
GOOD: 'good',
|
GOOD: 'good',
|
||||||
EVIL: 'evil'
|
EVIL: 'evil',
|
||||||
|
INDEPENDENT: 'independent'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MESSAGES = {
|
export const MESSAGES = {
|
||||||
|
|||||||
@@ -194,11 +194,15 @@ export const HTMLFragments = {
|
|||||||
<label id='players-alive-label'></label>
|
<label id='players-alive-label'></label>
|
||||||
<div id="spectator-count" tabindex="0"></div>
|
<div id="spectator-count" tabindex="0"></div>
|
||||||
<div id='game-player-list'>
|
<div id='game-player-list'>
|
||||||
<div class='evil-players'>
|
<div id="independent-players" class='independent-players' style="display: none;">
|
||||||
|
<label class='independent'>Team Independent</label>
|
||||||
|
<div id='player-list-moderator-team-independent'></div>
|
||||||
|
</div>
|
||||||
|
<div id="evil-players" class='evil-players' style="display: none;">
|
||||||
<label class='evil'>Team Evil</label>
|
<label class='evil'>Team Evil</label>
|
||||||
<div id='player-list-moderator-team-evil'></div>
|
<div id='player-list-moderator-team-evil'></div>
|
||||||
</div>
|
</div>
|
||||||
<div class='good-players'>
|
<div id="good-players" class='good-players' style="display: none;">
|
||||||
<label class='good'>Team Good</label>
|
<label class='good'>Team Good</label>
|
||||||
<div id='player-list-moderator-team-good'></div>
|
<div id='player-list-moderator-team-good'></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -147,7 +147,8 @@ export class DeckStateManager {
|
|||||||
}
|
}
|
||||||
const sortedDeck = this.deck.sort((a, b) => {
|
const sortedDeck = this.deck.sort((a, b) => {
|
||||||
if (a.team !== b.team) {
|
if (a.team !== b.team) {
|
||||||
return a.team === ALIGNMENT.GOOD ? -1 : 1;
|
const order = { good: 0, evil: 1, independent: 2 };
|
||||||
|
return order[a.team] - order[b.team];
|
||||||
}
|
}
|
||||||
return a.role.localeCompare(b.role);
|
return a.role.localeCompare(b.role);
|
||||||
});
|
});
|
||||||
@@ -187,11 +188,7 @@ export class DeckStateManager {
|
|||||||
roleEl.dataset.roleId = sortedDeck[i].id;
|
roleEl.dataset.roleId = sortedDeck[i].id;
|
||||||
roleEl.classList.add('added-role');
|
roleEl.classList.add('added-role');
|
||||||
roleEl.innerHTML = HTMLFragments.DECK_SELECT_ROLE_ADDED_TO_DECK;
|
roleEl.innerHTML = HTMLFragments.DECK_SELECT_ROLE_ADDED_TO_DECK;
|
||||||
if (sortedDeck[i].team === ALIGNMENT.GOOD) {
|
roleEl.classList.add(sortedDeck[i].team);
|
||||||
roleEl.classList.add(ALIGNMENT.GOOD);
|
|
||||||
} else {
|
|
||||||
roleEl.classList.add(ALIGNMENT.EVIL);
|
|
||||||
}
|
|
||||||
populateRoleElementInfo(roleEl, sortedDeck, i);
|
populateRoleElementInfo(roleEl, sortedDeck, i);
|
||||||
document.getElementById('deck-list').appendChild(roleEl);
|
document.getElementById('deck-list').appendChild(roleEl);
|
||||||
const minusOneHandler = (e) => {
|
const minusOneHandler = (e) => {
|
||||||
@@ -237,8 +234,10 @@ export class DeckStateManager {
|
|||||||
const nameEl = document.getElementById('custom-role-info-modal-name');
|
const nameEl = document.getElementById('custom-role-info-modal-name');
|
||||||
alignmentEl.classList.remove(ALIGNMENT.GOOD);
|
alignmentEl.classList.remove(ALIGNMENT.GOOD);
|
||||||
alignmentEl.classList.remove(ALIGNMENT.EVIL);
|
alignmentEl.classList.remove(ALIGNMENT.EVIL);
|
||||||
|
alignmentEl.classList.remove(ALIGNMENT.INDEPENDENT);
|
||||||
nameEl.classList.remove(ALIGNMENT.GOOD);
|
nameEl.classList.remove(ALIGNMENT.GOOD);
|
||||||
nameEl.classList.remove(ALIGNMENT.EVIL);
|
nameEl.classList.remove(ALIGNMENT.EVIL);
|
||||||
|
nameEl.classList.remove(ALIGNMENT.INDEPENDENT);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
nameEl.innerText = sortedDeck[i].role;
|
nameEl.innerText = sortedDeck[i].role;
|
||||||
nameEl.classList.add(sortedDeck[i].team);
|
nameEl.classList.add(sortedDeck[i].team);
|
||||||
@@ -256,6 +255,7 @@ export class DeckStateManager {
|
|||||||
function populateRoleElementInfo (roleEl, sortedDeck, i) {
|
function populateRoleElementInfo (roleEl, sortedDeck, i) {
|
||||||
roleEl.classList.remove(ALIGNMENT.GOOD);
|
roleEl.classList.remove(ALIGNMENT.GOOD);
|
||||||
roleEl.classList.remove(ALIGNMENT.EVIL);
|
roleEl.classList.remove(ALIGNMENT.EVIL);
|
||||||
|
roleEl.classList.remove(ALIGNMENT.INDEPENDENT);
|
||||||
roleEl.classList.add(sortedDeck[i].team);
|
roleEl.classList.add(sortedDeck[i].team);
|
||||||
roleEl.querySelector('.role-name').innerHTML =
|
roleEl.querySelector('.role-name').innerHTML =
|
||||||
`<span class="role-quantity"></span>
|
`<span class="role-quantity"></span>
|
||||||
|
|||||||
@@ -463,11 +463,7 @@ function renderReviewAndCreateStep (containerId, stepNumber, game, deckManager)
|
|||||||
for (const card of game.deck) {
|
for (const card of game.deck) {
|
||||||
const roleEl = document.createElement('div');
|
const roleEl = document.createElement('div');
|
||||||
roleEl.innerText = card.quantity + 'x ' + card.role;
|
roleEl.innerText = card.quantity + 'x ' + card.role;
|
||||||
if (card.team === ALIGNMENT.GOOD) {
|
roleEl.classList.add(card.team);
|
||||||
roleEl.classList.add(ALIGNMENT.GOOD);
|
|
||||||
} else {
|
|
||||||
roleEl.classList.add(ALIGNMENT.EVIL);
|
|
||||||
}
|
|
||||||
div.querySelector('#roles-option').appendChild(roleEl);
|
div.querySelector('#roles-option').appendChild(roleEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ export class RoleBox {
|
|||||||
loadDefaultRoles = () => {
|
loadDefaultRoles = () => {
|
||||||
this.defaultRoles = defaultRoles.sort((a, b) => {
|
this.defaultRoles = defaultRoles.sort((a, b) => {
|
||||||
if (a.team !== b.team) {
|
if (a.team !== b.team) {
|
||||||
return a.team === ALIGNMENT.GOOD ? -1 : 1;
|
const order = { good: 0, evil: 1, independent: 2 };
|
||||||
|
return order[a.team] - order[b.team];
|
||||||
}
|
}
|
||||||
return a.role.localeCompare(b.role);
|
return a.role.localeCompare(b.role);
|
||||||
}).map((role) => {
|
}).map((role) => {
|
||||||
@@ -174,10 +175,7 @@ export class RoleBox {
|
|||||||
defaultRole.innerHTML = HTMLFragments.DECK_SELECT_ROLE_DEFAULT;
|
defaultRole.innerHTML = HTMLFragments.DECK_SELECT_ROLE_DEFAULT;
|
||||||
defaultRole.classList.add('default-role');
|
defaultRole.classList.add('default-role');
|
||||||
defaultRole.dataset.roleId = this.defaultRoles[i].id;
|
defaultRole.dataset.roleId = this.defaultRoles[i].id;
|
||||||
const alignmentClass = this.defaultRoles[i].team === ALIGNMENT.GOOD
|
defaultRole.classList.add(this.defaultRoles[i].team);
|
||||||
? ALIGNMENT.GOOD
|
|
||||||
: ALIGNMENT.EVIL;
|
|
||||||
defaultRole.classList.add(alignmentClass);
|
|
||||||
defaultRole.querySelector('.role-name').innerText = this.defaultRoles[i].role;
|
defaultRole.querySelector('.role-name').innerText = this.defaultRoles[i].role;
|
||||||
selectEl.appendChild(defaultRole);
|
selectEl.appendChild(defaultRole);
|
||||||
}
|
}
|
||||||
@@ -202,7 +200,8 @@ export class RoleBox {
|
|||||||
}
|
}
|
||||||
this.customRoles.sort((a, b) => {
|
this.customRoles.sort((a, b) => {
|
||||||
if (a.team !== b.team) {
|
if (a.team !== b.team) {
|
||||||
return a.team === ALIGNMENT.GOOD ? -1 : 1;
|
const order = { good: 0, evil: 1, independent: 2 };
|
||||||
|
return order[a.team] - order[b.team];
|
||||||
}
|
}
|
||||||
return a.role.localeCompare(b.role);
|
return a.role.localeCompare(b.role);
|
||||||
});
|
});
|
||||||
@@ -212,8 +211,7 @@ export class RoleBox {
|
|||||||
customRole.innerHTML = HTMLFragments.DECK_SELECT_ROLE;
|
customRole.innerHTML = HTMLFragments.DECK_SELECT_ROLE;
|
||||||
customRole.classList.add('custom-role');
|
customRole.classList.add('custom-role');
|
||||||
customRole.dataset.roleId = this.customRoles[i].id;
|
customRole.dataset.roleId = this.customRoles[i].id;
|
||||||
const alignmentClass = this.customRoles[i].team === ALIGNMENT.GOOD ? ALIGNMENT.GOOD : ALIGNMENT.EVIL;
|
customRole.classList.add(this.customRoles[i].team);
|
||||||
customRole.classList.add(alignmentClass);
|
|
||||||
customRole.querySelector('.role-name').innerText = this.customRoles[i].role;
|
customRole.querySelector('.role-name').innerText = this.customRoles[i].role;
|
||||||
selectEl.appendChild(customRole);
|
selectEl.appendChild(customRole);
|
||||||
}
|
}
|
||||||
@@ -282,8 +280,10 @@ export class RoleBox {
|
|||||||
const nameEl = document.getElementById('custom-role-info-modal-name');
|
const nameEl = document.getElementById('custom-role-info-modal-name');
|
||||||
alignmentEl.classList.remove(ALIGNMENT.GOOD);
|
alignmentEl.classList.remove(ALIGNMENT.GOOD);
|
||||||
alignmentEl.classList.remove(ALIGNMENT.EVIL);
|
alignmentEl.classList.remove(ALIGNMENT.EVIL);
|
||||||
|
alignmentEl.classList.remove(ALIGNMENT.INDEPENDENT);
|
||||||
nameEl.classList.remove(ALIGNMENT.GOOD);
|
nameEl.classList.remove(ALIGNMENT.GOOD);
|
||||||
nameEl.classList.remove(ALIGNMENT.EVIL);
|
nameEl.classList.remove(ALIGNMENT.EVIL);
|
||||||
|
nameEl.classList.remove(ALIGNMENT.INDEPENDENT);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
let role;
|
let role;
|
||||||
if (isCustom) {
|
if (isCustom) {
|
||||||
@@ -391,7 +391,7 @@ function validateCustomRoleCookie (cookie) {
|
|||||||
for (const entry of cookieJSON) {
|
for (const entry of cookieJSON) {
|
||||||
if (entry !== null && typeof entry === 'object') {
|
if (entry !== null && typeof entry === 'object') {
|
||||||
if (typeof entry.role !== 'string' || entry.role.length > PRIMITIVES.MAX_CUSTOM_ROLE_NAME_LENGTH
|
if (typeof entry.role !== 'string' || entry.role.length > PRIMITIVES.MAX_CUSTOM_ROLE_NAME_LENGTH
|
||||||
|| typeof entry.team !== 'string' || (entry.team !== ALIGNMENT.GOOD && entry.team !== ALIGNMENT.EVIL)
|
|| typeof entry.team !== 'string' || (entry.team !== ALIGNMENT.GOOD && entry.team !== ALIGNMENT.EVIL && entry.team !== ALIGNMENT.INDEPENDENT)
|
||||||
|| typeof entry.description !== 'string' || entry.description.length > PRIMITIVES.MAX_CUSTOM_ROLE_DESCRIPTION_LENGTH
|
|| typeof entry.description !== 'string' || entry.description.length > PRIMITIVES.MAX_CUSTOM_ROLE_DESCRIPTION_LENGTH
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -295,26 +295,49 @@ export class InProgress {
|
|||||||
&& ((p.userType !== USER_TYPES.MODERATOR && p.userType !== USER_TYPES.SPECTATOR)
|
&& ((p.userType !== USER_TYPES.MODERATOR && p.userType !== USER_TYPES.SPECTATOR)
|
||||||
|| p.killed)
|
|| p.killed)
|
||||||
);
|
);
|
||||||
this.renderGroupOfPlayers(
|
const teamIndependent = this.stateBucket.currentGameState.people.filter((p) => p.alignment === ALIGNMENT.INDEPENDENT
|
||||||
teamEvil,
|
&& ((p.userType !== USER_TYPES.MODERATOR && p.userType !== USER_TYPES.SPECTATOR)
|
||||||
this.killPlayerHandlers,
|
|| p.killed)
|
||||||
this.revealRoleHandlers,
|
|
||||||
this.stateBucket.currentGameState.accessCode,
|
|
||||||
ALIGNMENT.EVIL,
|
|
||||||
this.stateBucket.currentGameState.people.find(person =>
|
|
||||||
person.id === this.stateBucket.currentGameState.currentModeratorId).userType,
|
|
||||||
this.socket
|
|
||||||
);
|
|
||||||
this.renderGroupOfPlayers(
|
|
||||||
teamGood,
|
|
||||||
this.killPlayerHandlers,
|
|
||||||
this.revealRoleHandlers,
|
|
||||||
this.stateBucket.currentGameState.accessCode,
|
|
||||||
ALIGNMENT.GOOD,
|
|
||||||
this.stateBucket.currentGameState.people.find(person =>
|
|
||||||
person.id === this.stateBucket.currentGameState.currentModeratorId).userType,
|
|
||||||
this.socket
|
|
||||||
);
|
);
|
||||||
|
if (teamEvil.length > 0) {
|
||||||
|
document.getElementById(`${ALIGNMENT.EVIL}-players`).style.display = 'block';
|
||||||
|
this.renderGroupOfPlayers(
|
||||||
|
teamEvil,
|
||||||
|
this.killPlayerHandlers,
|
||||||
|
this.revealRoleHandlers,
|
||||||
|
this.stateBucket.currentGameState.accessCode,
|
||||||
|
ALIGNMENT.EVIL,
|
||||||
|
this.stateBucket.currentGameState.people.find(person =>
|
||||||
|
person.id === this.stateBucket.currentGameState.currentModeratorId).userType,
|
||||||
|
this.socket
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (teamGood.length > 0) {
|
||||||
|
document.getElementById(`${ALIGNMENT.GOOD}-players`).style.display = 'block';
|
||||||
|
this.renderGroupOfPlayers(
|
||||||
|
teamGood,
|
||||||
|
this.killPlayerHandlers,
|
||||||
|
this.revealRoleHandlers,
|
||||||
|
this.stateBucket.currentGameState.accessCode,
|
||||||
|
ALIGNMENT.GOOD,
|
||||||
|
this.stateBucket.currentGameState.people.find(person =>
|
||||||
|
person.id === this.stateBucket.currentGameState.currentModeratorId).userType,
|
||||||
|
this.socket
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (teamIndependent.length > 0) {
|
||||||
|
document.getElementById(`${ALIGNMENT.INDEPENDENT}-players`).style.display = 'block';
|
||||||
|
this.renderGroupOfPlayers(
|
||||||
|
teamIndependent,
|
||||||
|
this.killPlayerHandlers,
|
||||||
|
this.revealRoleHandlers,
|
||||||
|
this.stateBucket.currentGameState.accessCode,
|
||||||
|
ALIGNMENT.INDEPENDENT,
|
||||||
|
this.stateBucket.currentGameState.people.find(person =>
|
||||||
|
person.id === this.stateBucket.currentGameState.currentModeratorId).userType,
|
||||||
|
this.socket
|
||||||
|
);
|
||||||
|
}
|
||||||
document.getElementById('players-alive-label').innerText =
|
document.getElementById('players-alive-label').innerText =
|
||||||
'Players: ' + this.stateBucket.currentGameState.people.filter((person) => !person.out).length + ' / ' +
|
'Players: ' + this.stateBucket.currentGameState.people.filter((person) => !person.out).length + ' / ' +
|
||||||
this.stateBucket.currentGameState.gameSize + ' Alive';
|
this.stateBucket.currentGameState.gameSize + ' Alive';
|
||||||
@@ -460,9 +483,12 @@ function renderPlayerRole (gameState) {
|
|||||||
if (gameState.client.alignment === ALIGNMENT.GOOD) {
|
if (gameState.client.alignment === ALIGNMENT.GOOD) {
|
||||||
document.getElementById('game-role').classList.add('game-role-good');
|
document.getElementById('game-role').classList.add('game-role-good');
|
||||||
name.classList.add('good');
|
name.classList.add('good');
|
||||||
} else {
|
} else if (gameState.client.alignment === ALIGNMENT.EVIL) {
|
||||||
document.getElementById('game-role').classList.add('game-role-evil');
|
document.getElementById('game-role').classList.add('game-role-evil');
|
||||||
name.classList.add('evil');
|
name.classList.add('evil');
|
||||||
|
} else if (gameState.client.alignment === ALIGNMENT.INDEPENDENT) {
|
||||||
|
document.getElementById('game-role').classList.add('game-role-independent');
|
||||||
|
name.classList.add('independent');
|
||||||
}
|
}
|
||||||
name.setAttribute('title', gameState.client.gameRole);
|
name.setAttribute('title', gameState.client.gameRole);
|
||||||
if (gameState.client.out) {
|
if (gameState.client.out) {
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ import {
|
|||||||
ENVIRONMENTS,
|
ENVIRONMENTS,
|
||||||
SOCKET_EVENTS,
|
SOCKET_EVENTS,
|
||||||
USER_TYPE_ICONS,
|
USER_TYPE_ICONS,
|
||||||
USER_TYPES,
|
USER_TYPES
|
||||||
ALIGNMENT
|
|
||||||
} from '../../../../config/globals.js';
|
} from '../../../../config/globals.js';
|
||||||
import { toast } from '../../../front_end_components/Toast.js';
|
import { toast } from '../../../front_end_components/Toast.js';
|
||||||
import { Confirmation } from '../../../front_end_components/Confirmation.js';
|
import { Confirmation } from '../../../front_end_components/Confirmation.js';
|
||||||
@@ -149,7 +148,11 @@ export const SharedStateUtil = {
|
|||||||
document.getElementById('role-info-button').addEventListener('click', (e) => {
|
document.getElementById('role-info-button').addEventListener('click', (e) => {
|
||||||
const deck = stateBucket.currentGameState.deck;
|
const deck = stateBucket.currentGameState.deck;
|
||||||
deck.sort((a, b) => {
|
deck.sort((a, b) => {
|
||||||
return a.team === ALIGNMENT.GOOD ? -1 : 1;
|
if (a.team !== b.team) {
|
||||||
|
const order = { good: 0, evil: 1, independent: 2 };
|
||||||
|
return order[a.team] - order[b.team];
|
||||||
|
}
|
||||||
|
return a.role.localeCompare(b.role);
|
||||||
});
|
});
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
document.getElementById('role-info-prompt').innerHTML = HTMLFragments.ROLE_INFO_MODAL;
|
document.getElementById('role-info-prompt').innerHTML = HTMLFragments.ROLE_INFO_MODAL;
|
||||||
@@ -168,11 +171,7 @@ export const SharedStateUtil = {
|
|||||||
roleName.innerText = card.role;
|
roleName.innerText = card.role;
|
||||||
roleQuantity.innerText = card.quantity + 'x';
|
roleQuantity.innerText = card.quantity + 'x';
|
||||||
|
|
||||||
if (card.team === ALIGNMENT.GOOD) {
|
roleName.classList.add(card.team);
|
||||||
roleName.classList.add(ALIGNMENT.GOOD);
|
|
||||||
} else {
|
|
||||||
roleName.classList.add(ALIGNMENT.EVIL);
|
|
||||||
}
|
|
||||||
|
|
||||||
roleNameDiv.appendChild(roleQuantity);
|
roleNameDiv.appendChild(roleQuantity);
|
||||||
roleNameDiv.appendChild(roleName);
|
roleNameDiv.appendChild(roleName);
|
||||||
|
|||||||
@@ -608,6 +608,15 @@ input {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.independent, .compact-card.independent .card-role {
|
||||||
|
color: #af8523 !important;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.independent-players, #deck-independent {
|
||||||
|
border: 2px solid rgba(212, 160, 39, 0.39);
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes placeholder {
|
@keyframes placeholder {
|
||||||
0%{
|
0%{
|
||||||
background-position: 50% 0
|
background-position: 50% 0
|
||||||
|
|||||||
@@ -424,7 +424,7 @@ h1 {
|
|||||||
display: none;
|
display: none;
|
||||||
position: relative;
|
position: relative;
|
||||||
border: 5px solid transparent;
|
border: 5px solid transparent;
|
||||||
background-color: #e3e3e3;
|
background-color: #efefef;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -462,6 +462,10 @@ h1 {
|
|||||||
border: 4px solid #c55454 !important;
|
border: 4px solid #c55454 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.game-role-independent {
|
||||||
|
border: 4px solid #af8523 !important;
|
||||||
|
}
|
||||||
|
|
||||||
#game-role-back {
|
#game-role-back {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -547,6 +551,10 @@ h1 {
|
|||||||
color: #e15656 !important;
|
color: #e15656 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#game-role #role-name.independent {
|
||||||
|
color: #af8523 !important;
|
||||||
|
}
|
||||||
|
|
||||||
#role-image {
|
#role-image {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
-ms-user-select: none;
|
-ms-user-select: none;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export const hiddenMenus =
|
|||||||
<select id="role-alignment" required>
|
<select id="role-alignment" required>
|
||||||
<option value="good">good</option>
|
<option value="good">good</option>
|
||||||
<option value="evil">evil</option>
|
<option value="evil">evil</option>
|
||||||
|
<option value="independent">independent</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ const LOG_LEVEL = {
|
|||||||
|
|
||||||
const ALIGNMENT = {
|
const ALIGNMENT = {
|
||||||
GOOD: 'good',
|
GOOD: 'good',
|
||||||
EVIL: 'evil'
|
EVIL: 'evil',
|
||||||
|
INDEPENDENT: 'independent'
|
||||||
};
|
};
|
||||||
|
|
||||||
const REDIS_CHANNELS = {
|
const REDIS_CHANNELS = {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class GameCreationRequest {
|
|||||||
&& entry.role.length > 0
|
&& entry.role.length > 0
|
||||||
&& entry.role.length <= PRIMITIVES.MAX_CUSTOM_ROLE_NAME_LENGTH
|
&& entry.role.length <= PRIMITIVES.MAX_CUSTOM_ROLE_NAME_LENGTH
|
||||||
&& typeof entry.team === 'string'
|
&& typeof entry.team === 'string'
|
||||||
&& (entry.team === ALIGNMENT.GOOD || entry.team === ALIGNMENT.EVIL)
|
&& (entry.team === ALIGNMENT.GOOD || entry.team === ALIGNMENT.EVIL || entry.team === ALIGNMENT.INDEPENDENT)
|
||||||
&& typeof entry.description === 'string'
|
&& typeof entry.description === 'string'
|
||||||
&& entry.description.length > 0
|
&& entry.description.length > 0
|
||||||
&& entry.description.length <= PRIMITIVES.MAX_CUSTOM_ROLE_DESCRIPTION_LENGTH
|
&& entry.description.length <= PRIMITIVES.MAX_CUSTOM_ROLE_DESCRIPTION_LENGTH
|
||||||
|
|||||||
104
spec/unit/server/model/GameCreationRequest_Spec.js
Normal file
104
spec/unit/server/model/GameCreationRequest_Spec.js
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
const GameCreationRequest = require('../../../../server/model/GameCreationRequest');
|
||||||
|
const { ALIGNMENT } = require('../../../../server/config/globals');
|
||||||
|
|
||||||
|
describe('GameCreationRequest', () => {
|
||||||
|
describe('#deckIsValid', () => {
|
||||||
|
it('should accept a deck with good, evil, and independent roles', () => {
|
||||||
|
const deck = [
|
||||||
|
{
|
||||||
|
role: 'Villager',
|
||||||
|
team: ALIGNMENT.GOOD,
|
||||||
|
description: 'A simple villager',
|
||||||
|
custom: false,
|
||||||
|
quantity: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'Werewolf',
|
||||||
|
team: ALIGNMENT.EVIL,
|
||||||
|
description: 'A werewolf',
|
||||||
|
custom: false,
|
||||||
|
quantity: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: 'Tanner',
|
||||||
|
team: ALIGNMENT.INDEPENDENT,
|
||||||
|
description: 'An independent role',
|
||||||
|
custom: true,
|
||||||
|
quantity: 1
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(GameCreationRequest.deckIsValid(deck)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept a deck with only good roles', () => {
|
||||||
|
const deck = [
|
||||||
|
{
|
||||||
|
role: 'Villager',
|
||||||
|
team: ALIGNMENT.GOOD,
|
||||||
|
description: 'A simple villager',
|
||||||
|
custom: false,
|
||||||
|
quantity: 3
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(GameCreationRequest.deckIsValid(deck)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept a deck with only evil roles', () => {
|
||||||
|
const deck = [
|
||||||
|
{
|
||||||
|
role: 'Werewolf',
|
||||||
|
team: ALIGNMENT.EVIL,
|
||||||
|
description: 'A werewolf',
|
||||||
|
custom: false,
|
||||||
|
quantity: 2
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(GameCreationRequest.deckIsValid(deck)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept a deck with only independent roles', () => {
|
||||||
|
const deck = [
|
||||||
|
{
|
||||||
|
role: 'Tanner',
|
||||||
|
team: ALIGNMENT.INDEPENDENT,
|
||||||
|
description: 'An independent role',
|
||||||
|
custom: true,
|
||||||
|
quantity: 1
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(GameCreationRequest.deckIsValid(deck)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reject a deck with invalid team values', () => {
|
||||||
|
const deck = [
|
||||||
|
{
|
||||||
|
role: 'InvalidRole',
|
||||||
|
team: 'invalid',
|
||||||
|
description: 'Invalid team',
|
||||||
|
custom: true,
|
||||||
|
quantity: 1
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(GameCreationRequest.deckIsValid(deck)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reject a deck with missing required fields', () => {
|
||||||
|
const deck = [
|
||||||
|
{
|
||||||
|
role: 'Villager',
|
||||||
|
// missing team
|
||||||
|
description: 'A simple villager',
|
||||||
|
custom: false,
|
||||||
|
quantity: 1
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(GameCreationRequest.deckIsValid(deck)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user