mirror of
https://github.com/AlecM33/Werewolf.git
synced 2025-12-26 07:47:50 +01:00
remove magic numbers, update how to use page styling
This commit is contained in:
@@ -3,6 +3,8 @@ export const PRIMITIVES = {
|
|||||||
USER_SIGNATURE_LENGTH: 75,
|
USER_SIGNATURE_LENGTH: 75,
|
||||||
CLOCK_TICK_INTERVAL_MILLIS: 50,
|
CLOCK_TICK_INTERVAL_MILLIS: 50,
|
||||||
MAX_CUSTOM_ROLE_NAME_LENGTH: 50,
|
MAX_CUSTOM_ROLE_NAME_LENGTH: 50,
|
||||||
|
MAX_PERSON_NAME_LENGTH: 40,
|
||||||
|
MAX_DECK_SIZE: 50,
|
||||||
MAX_CUSTOM_ROLE_DESCRIPTION_LENGTH: 1000,
|
MAX_CUSTOM_ROLE_DESCRIPTION_LENGTH: 1000,
|
||||||
TOAST_DURATION_DEFAULT: 6,
|
TOAST_DURATION_DEFAULT: 6,
|
||||||
ACCESS_CODE_LENGTH: 4,
|
ACCESS_CODE_LENGTH: 4,
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 357 KiB After Width: | Height: | Size: 417 KiB |
@@ -1,7 +1,7 @@
|
|||||||
import { Game } from '../../model/Game.js';
|
import { Game } from '../../model/Game.js';
|
||||||
import { cancelCurrentToast, toast } from '../front_end_components/Toast.js';
|
import { cancelCurrentToast, toast } from '../front_end_components/Toast.js';
|
||||||
import { ModalManager } from '../front_end_components/ModalManager.js';
|
import { ModalManager } from '../front_end_components/ModalManager.js';
|
||||||
import { ALIGNMENT } from '../../config/globals.js';
|
import { ALIGNMENT, PRIMITIVES } from '../../config/globals.js';
|
||||||
import { HTMLFragments } from '../front_end_components/HTMLFragments.js';
|
import { HTMLFragments } from '../front_end_components/HTMLFragments.js';
|
||||||
import { UserUtility } from '../utility/UserUtility.js';
|
import { UserUtility } from '../utility/UserUtility.js';
|
||||||
import { RoleBox } from './RoleBox.js';
|
import { RoleBox } from './RoleBox.js';
|
||||||
@@ -35,7 +35,7 @@ export class GameCreationStepManager {
|
|||||||
2: {
|
2: {
|
||||||
title: 'Create your deck (you can edit this later):',
|
title: 'Create your deck (you can edit this later):',
|
||||||
forwardHandler: () => {
|
forwardHandler: () => {
|
||||||
if (this.deckManager.getDeckSize() > 50) {
|
if (this.deckManager.getDeckSize() > PRIMITIVES.MAX_DECK_SIZE) {
|
||||||
toast('Your deck is too large. The max is 50 cards.', 'error', true);
|
toast('Your deck is too large. The max is 50 cards.', 'error', true);
|
||||||
} else {
|
} else {
|
||||||
this.currentGame.deck = this.deckManager.deck.filter((card) => card.quantity > 0);
|
this.currentGame.deck = this.deckManager.deck.filter((card) => card.quantity > 0);
|
||||||
@@ -569,11 +569,11 @@ function initializeRemainingEventListeners (deckManager, roleBox) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function processNewCustomRoleSubmission (name, description, team, deckManager, isUpdate, roleBox, option = null) {
|
function processNewCustomRoleSubmission (name, description, team, deckManager, isUpdate, roleBox, option = null) {
|
||||||
if (name.length > 50) {
|
if (name.length > PRIMITIVES.MAX_CUSTOM_ROLE_NAME_LENGTH) {
|
||||||
toast('Your name is too long (max 50 characters).', 'error', true);
|
toast('Your name is too long (max 50 characters).', 'error', true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (description.length > 500) {
|
if (description.length > PRIMITIVES.MAX_CUSTOM_ROLE_DESCRIPTION_LENGTH) {
|
||||||
toast('Your description is too long (max 500 characters).', 'error', true);
|
toast('Your description is too long (max 500 characters).', 'error', true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -596,5 +596,5 @@ function hasTimer (hours, minutes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function validateName (name) {
|
function validateName (name) {
|
||||||
return typeof name === 'string' && name.length > 0 && name.length <= 40;
|
return typeof name === 'string' && name.length > 0 && name.length <= PRIMITIVES.MAX_PERSON_NAME_LENGTH;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { QRCode } from '../../third_party/qrcode.js';
|
import { QRCode } from '../../third_party/qrcode.js';
|
||||||
import { toast } from '../../front_end_components/Toast.js';
|
import { toast } from '../../front_end_components/Toast.js';
|
||||||
import { EVENT_IDS, SOCKET_EVENTS, USER_TYPE_ICONS, USER_TYPES } from '../../../config/globals.js';
|
import { EVENT_IDS, PRIMITIVES, SOCKET_EVENTS, USER_TYPE_ICONS, USER_TYPES } from '../../../config/globals.js';
|
||||||
import { HTMLFragments } from '../../front_end_components/HTMLFragments.js';
|
import { HTMLFragments } from '../../front_end_components/HTMLFragments.js';
|
||||||
import { Confirmation } from '../../front_end_components/Confirmation.js';
|
import { Confirmation } from '../../front_end_components/Confirmation.js';
|
||||||
import { SharedStateUtil } from './shared/SharedStateUtil.js';
|
import { SharedStateUtil } from './shared/SharedStateUtil.js';
|
||||||
@@ -79,7 +79,7 @@ export class Lobby {
|
|||||||
roleEditPrompt.setAttribute('id', 'role-edit-prompt');
|
roleEditPrompt.setAttribute('id', 'role-edit-prompt');
|
||||||
roleEditPrompt.innerHTML = HTMLFragments.ROLE_EDIT_BUTTONS;
|
roleEditPrompt.innerHTML = HTMLFragments.ROLE_EDIT_BUTTONS;
|
||||||
roleEditPrompt.querySelector('#save-role-changes-button').addEventListener('click', () => {
|
roleEditPrompt.querySelector('#save-role-changes-button').addEventListener('click', () => {
|
||||||
if (this.gameCreationStepManager.deckManager.getDeckSize() > 50) {
|
if (this.gameCreationStepManager.deckManager.getDeckSize() > PRIMITIVES.MAX_DECK_SIZE) {
|
||||||
toast('Your deck is too large. The max is 50 cards.', 'error', true);
|
toast('Your deck is too large. The max is 50 cards.', 'error', true);
|
||||||
} else {
|
} else {
|
||||||
document.querySelector('#mid-game-role-editor')?.remove();
|
document.querySelector('#mid-game-role-editor')?.remove();
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ function resetJoinButtonState (e, joinHandler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function validateName (name) {
|
function validateName (name) {
|
||||||
return typeof name === 'string' && name.length > 0 && name.length <= 40;
|
return typeof name === 'string' && name.length > 0 && name.length <= PRIMITIVES.MAX_PERSON_NAME_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
|
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#how-to-use-container h1 {
|
#how-to-use-container h1 {
|
||||||
color: #d7d7d7;
|
color: #21ba45;
|
||||||
font-family: signika-negative, sans-serif;
|
font-family: signika-negative, sans-serif;
|
||||||
background-color: #1e1b26;
|
background-color: #1e1b26;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
@@ -376,6 +376,11 @@ input {
|
|||||||
#how-to-use-container h3 {
|
#how-to-use-container h3 {
|
||||||
color: #b1afcd;
|
color: #b1afcd;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
font-family: signika-negative, sans-serif;
|
||||||
|
background-color: #1e1b26;
|
||||||
|
width: fit-content;
|
||||||
|
padding: 0 5px;
|
||||||
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#tutorial-links {text-align: left;
|
#tutorial-links {text-align: left;
|
||||||
@@ -829,7 +834,7 @@ input {
|
|||||||
|
|
||||||
@media(max-width: 550px) {
|
@media(max-width: 550px) {
|
||||||
.how-to-use-header {
|
.how-to-use-header {
|
||||||
font-size: 25px;
|
font-size: 30px;
|
||||||
}
|
}
|
||||||
#how-to-use-container h3 {
|
#how-to-use-container h3 {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
<div id="tutorial-links">
|
<div id="tutorial-links">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href="#purpose-of-the-app">Purpose of the App</a>
|
<a href="#purpose-of-the-app">Purpose</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#creating-a-game">Creating a Game</a>
|
<a href="#creating-a-game">Creating a Game</a>
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<h1 class="how-to-use-header" id="purpose-of-the-app">Purpose of the Application</h1>
|
<h1 class="how-to-use-header" id="purpose-of-the-app">Purpose</h1>
|
||||||
<div class="how-to-use-section">This app serves as a means of running games in a social setting where a traditional
|
<div class="how-to-use-section">This app serves as a means of running games in a social setting where a traditional
|
||||||
running of the game is hindered. This might be when people are meeting virtually, and thus roles can't be handed
|
running of the game is hindered. This might be when people are meeting virtually, and thus roles can't be handed
|
||||||
out in-person, or when people are in-person but don't have Werewolf/Mafia cards with them. You can use a deck of regular
|
out in-person, or when people are in-person but don't have Werewolf/Mafia cards with them. You can use a deck of regular
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
<div class="how-to-use-section">
|
<div class="how-to-use-section">
|
||||||
Creating a game through the app has 3 main components:
|
Creating a game through the app has 3 main components:
|
||||||
<br>
|
<br>
|
||||||
<h3>Step One: Choosing a method of moderation</h3>
|
<h3>- Step One: Choosing a method of moderation</h3>
|
||||||
<br>
|
<br>
|
||||||
You have two options for moderation during the game. If the moderator isn't playing, you can choose the <span class="emphasized">Dedicated
|
You have two options for moderation during the game. If the moderator isn't playing, you can choose the <span class="emphasized">Dedicated
|
||||||
Moderator</span> option. Dedicated Moderators are not dealt into the game. Once they start the game, they will know
|
Moderator</span> option. Dedicated Moderators are not dealt into the game. Once they start the game, they will know
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
or to a spectator. That way, if the current Dedicated Moderator has to leave, or simply does not want to moderate
|
or to a spectator. That way, if the current Dedicated Moderator has to leave, or simply does not want to moderate
|
||||||
anymore, they can easily delegate.
|
anymore, they can easily delegate.
|
||||||
<br><br>
|
<br><br>
|
||||||
<h3>Step Two: Build your deck</h3>
|
<h3>- Step Two: Build your deck</h3>
|
||||||
<br>
|
<br>
|
||||||
There is a role box on this page that includes a list of <span class="emphasized">Default Roles</span> and a list
|
There is a role box on this page that includes a list of <span class="emphasized">Default Roles</span> and a list
|
||||||
of <span class="emphasized">Custom Roles</span>, which can be displayed by selecting the appropriate button within the box.
|
of <span class="emphasized">Custom Roles</span>, which can be displayed by selecting the appropriate button within the box.
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
<br><br>
|
<br><br>
|
||||||
Here I add 3 villagers to the game, and then remove them:
|
Here I add 3 villagers to the game, and then remove them:
|
||||||
<br><br>
|
<br><br>
|
||||||
<img class='tutorial-image-small' src="../images/tutorial/add-role-to-deck.gif"/>
|
<img alt="adding a role to the deck" class='tutorial-image-small' src="../images/tutorial/add-role-to-deck.gif"/>
|
||||||
<br><br>
|
<br><br>
|
||||||
You can add, edit, and remove Custom Roles. You can also import and export them via a formatted text file. Click
|
You can add, edit, and remove Custom Roles. You can also import and export them via a formatted text file. Click
|
||||||
the hamburger menu on the role box to see the import/export options. Here I create a new Custom Role and observe
|
the hamburger menu on the role box to see the import/export options. Here I create a new Custom Role and observe
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
<br><br>
|
<br><br>
|
||||||
<img alt="create-custom-role" class='tutorial-image-small' src="../images/tutorial/create-custom-role.gif"/>
|
<img alt="create-custom-role" class='tutorial-image-small' src="../images/tutorial/create-custom-role.gif"/>
|
||||||
<br><br>
|
<br><br>
|
||||||
<h3>Step Three: Set an optional timer</h3>
|
<h3>- Step Three: Set an optional timer</h3>
|
||||||
<br>
|
<br>
|
||||||
If you don't fill in these fields, the game will be untimed. If you do, you can use a time between 1 minute
|
If you don't fill in these fields, the game will be untimed. If you do, you can use a time between 1 minute
|
||||||
and 5 hours. The timer can be played and paused by the current moderator. Importantly, when the timer expires,
|
and 5 hours. The timer can be played and paused by the current moderator. Importantly, when the timer expires,
|
||||||
@@ -96,7 +96,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<h1 class="how-to-use-header" id="being-the-moderator">Being the Moderator</h1>
|
<h1 class="how-to-use-header" id="being-the-moderator">Being the Moderator</h1>
|
||||||
<div class="how-to-use-section">
|
<div class="how-to-use-section">
|
||||||
<h3>In the Lobby</h3>
|
<h3>- In the Lobby</h3>
|
||||||
<br>
|
<br>
|
||||||
In the Lobby, moderators can manage the people in the room and the cards in the game. By clicking
|
In the Lobby, moderators can manage the people in the room and the cards in the game. By clicking
|
||||||
the <span class="emphasized">three vertical dots (AKA the "kebab menu")</span> next to a given player (<span class="emphasized">point A</span>
|
the <span class="emphasized">three vertical dots (AKA the "kebab menu")</span> next to a given player (<span class="emphasized">point A</span>
|
||||||
@@ -107,9 +107,9 @@
|
|||||||
Saving any changes to the roles may affect the player count. If you wish to <span class="emphasized">start the game (point B)</span>, the number
|
Saving any changes to the roles may affect the player count. If you wish to <span class="emphasized">start the game (point B)</span>, the number
|
||||||
of Players in the Lobby must equal the number of cards in the game.
|
of Players in the Lobby must equal the number of cards in the game.
|
||||||
<br><br>
|
<br><br>
|
||||||
<img class='tutorial-image-small-portrait' src="../images/tutorial/dedicated-mod-lobby-mobile.webp"/>
|
<img alt="moderator view in the lobby" class='tutorial-image-small-portrait' src="../images/tutorial/dedicated-mod-lobby-mobile.webp"/>
|
||||||
<br><br>
|
<br><br>
|
||||||
<h3>During the Game</h3>
|
<h3>- During the Game</h3>
|
||||||
<br>
|
<br>
|
||||||
<span class="emphasized">Dedicated Moderators</span> can see who is on which team and who is which role. The moderator
|
<span class="emphasized">Dedicated Moderators</span> can see who is on which team and who is which role. The moderator
|
||||||
Kills and Reveals players (<span class="emphasized">Point A</span> below). They are separate actions. So, if you
|
Kills and Reveals players (<span class="emphasized">Point A</span> below). They are separate actions. So, if you
|
||||||
@@ -120,33 +120,33 @@
|
|||||||
play and pause the Timer (<span class="emphasized">Point B</span>), and can end the game (revealing everyone's role)
|
play and pause the Timer (<span class="emphasized">Point B</span>), and can end the game (revealing everyone's role)
|
||||||
or return the game to the Lobby (<span class="emphasized">Point C</span>), where it can be started anew with different settings.
|
or return the game to the Lobby (<span class="emphasized">Point C</span>), where it can be started anew with different settings.
|
||||||
<br><br>
|
<br><br>
|
||||||
<img class='tutorial-image-small-portrait' src="../images/tutorial/dedicated-mod-in-progress-mobile.webp"/>
|
<img alt="moderator view during the game" class='tutorial-image-small-portrait' src="../images/tutorial/dedicated-mod-in-progress-mobile.webp"/>
|
||||||
<br><br>
|
<br><br>
|
||||||
Similarly, the <span class="emphasized">Temporary Moderator view</span> looks like the below image. They have
|
Similarly, the <span class="emphasized">Temporary Moderator view</span> looks like the below image. They have
|
||||||
much the same abilities as a dedicated moderator, except they don't know role or alignment information and cannot
|
much the same abilities as a dedicated moderator, except they don't know role or alignment information and cannot
|
||||||
transfer their powers. Their powers will be transferred automatically to the first person they remove from the game
|
transfer their powers. Their powers will be transferred automatically to the first person they remove from the game
|
||||||
(which can be themselves).
|
(which can be themselves).
|
||||||
<br><br>
|
<br><br>
|
||||||
<img class='tutorial-image-small-portrait' src="../images/tutorial/temp-mod-in-progress-mobile.webp"/>
|
<img alt="temporary moderator view during the game" class='tutorial-image-small-portrait' src="../images/tutorial/temp-mod-in-progress-mobile.webp"/>
|
||||||
<br><br>
|
<br><br>
|
||||||
<h3>Transferring your moderator powers</h3>
|
<h3>- Transferring your moderator powers</h3>
|
||||||
<br>
|
<br>
|
||||||
You can transfer your moderator abilities to anyone that has been removed from the game, or to anyone that happens
|
You can transfer your moderator abilities to anyone that has been removed from the game, or to anyone that happens
|
||||||
to be spectating. Here we select a killed player and transfer our powers to them:
|
to be spectating. Here we select a killed player and transfer our powers to them:
|
||||||
<br><br>
|
<br><br>
|
||||||
<img class='tutorial-image-small-portrait' src="../images/tutorial/mod-transfer.gif"/>
|
<img alt="transferring your moderator powers" class='tutorial-image-small-portrait' src="../images/tutorial/mod-transfer.gif"/>
|
||||||
<br><br>
|
<br><br>
|
||||||
</div>
|
</div>
|
||||||
<h1 class="how-to-use-header" id="being-a-player">Being a Player</h1>
|
<h1 class="how-to-use-header" id="being-a-player">Being a Player</h1>
|
||||||
<div class="how-to-use-section">
|
<div class="how-to-use-section">
|
||||||
This is an example of what a <span class="emphasized">Player</span> is seeing. The timer is running, and they view their
|
This is an example of what a <span class="emphasized">Player</span> is seeing, including the running timer,
|
||||||
role by double-clicking it:
|
their role card, and the player list. You can also edit your name for the Room by clicking the pencil next to it.
|
||||||
|
Below, we flip our role card up and down by double-clicking it, and then we bring up the prompt to edit our name:
|
||||||
<br><br>
|
<br><br>
|
||||||
<img class='tutorial-image-small-portrait' src="../images/tutorial/player-view.gif"/>
|
<img alt='player-view' class='tutorial-image-small-portrait' src="../images/tutorial/player-view.gif"/>
|
||||||
<br><br>
|
<br><br>
|
||||||
There are three main things - the <span class="emphasized">Timer</span>, your <span class="emphasized">Role Card</span>
|
Players can view the timer, but only the current moderator can play and pause it. Your role card starts flipped over
|
||||||
and the <span class="emphasized">Player List</span>. Players can view the timer, but only the current moderator can play and pause it.
|
- this is useful if you are in-person and don't want someone else accidentally seeing your role as
|
||||||
Your role card starts flipped over - this is useful if you are in-person and don't want someone else accidentally seeing your role as
|
|
||||||
it is dealt. You can view your role at any time by double-clicking/double-tapping it. Requiring a double-click guards against the possibility
|
it is dealt. You can view your role at any time by double-clicking/double-tapping it. Requiring a double-click guards against the possibility
|
||||||
of accidentally flipping your role when tapping other things. Within the Player List, you can see who is alive or
|
of accidentally flipping your role when tapping other things. Within the Player List, you can see who is alive or
|
||||||
dead and who has had their role revealed. There is also a <span class="emphasized">role info button</span> that,
|
dead and who has had their role revealed. There is also a <span class="emphasized">role info button</span> that,
|
||||||
|
|||||||
@@ -7,25 +7,23 @@ This timer is accurate to within a few ms for any amount of time provided.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function stepFn (serverTimerInstance, expected) {
|
function stepFn (serverTimerInstance, expected) {
|
||||||
const now = Date.now(); //
|
serverTimerInstance.currentTimeInMillis = serverTimerInstance.totalTime - (Date.now() - serverTimerInstance.start);
|
||||||
serverTimerInstance.currentTimeInMillis = serverTimerInstance.totalTime - (now - serverTimerInstance.start);
|
if (Date.now() - serverTimerInstance.start >= serverTimerInstance.totalTime) { // check if the time has elapsed
|
||||||
if (now - serverTimerInstance.start >= serverTimerInstance.totalTime) { // check if the time has elapsed
|
|
||||||
serverTimerInstance.logger.debug(
|
serverTimerInstance.logger.debug(
|
||||||
'ELAPSED: ' + (now - serverTimerInstance.start) + 'ms (~' +
|
'ELAPSED: ' + (Date.now() - serverTimerInstance.start) + 'ms (~' +
|
||||||
(Math.abs(serverTimerInstance.totalTime - (now - serverTimerInstance.start)) / serverTimerInstance.totalTime).toFixed(3) + '% error).'
|
(Math.abs(serverTimerInstance.totalTime - (Date.now() - serverTimerInstance.start)) / serverTimerInstance.totalTime).toFixed(3) + '% error).'
|
||||||
);
|
);
|
||||||
serverTimerInstance.timesUpResolver(); // this is a reference to the callback defined in the construction of the promise in runTimer()
|
serverTimerInstance.timesUpResolver(); // this is a reference to the callback defined in the construction of the promise in runTimer()
|
||||||
clearTimeout(serverTimerInstance.ticking);
|
clearTimeout(serverTimerInstance.ticking);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const delta = now - expected;
|
|
||||||
expected += serverTimerInstance.interval;
|
expected += serverTimerInstance.interval;
|
||||||
serverTimerInstance.ticking = setTimeout(function () {
|
serverTimerInstance.ticking = setTimeout(function () {
|
||||||
stepFn(
|
stepFn(
|
||||||
serverTimerInstance,
|
serverTimerInstance,
|
||||||
expected
|
expected
|
||||||
);
|
);
|
||||||
}, Math.max(0, serverTimerInstance.interval - delta)); // take into account drift
|
}, Math.max(0, serverTimerInstance.interval - (Date.now() - expected))); // take into account drift
|
||||||
}
|
}
|
||||||
|
|
||||||
class ServerTimer {
|
class ServerTimer {
|
||||||
|
|||||||
Reference in New Issue
Block a user