diff --git a/ui/source/css/basics/headings.css b/ui/source/css/basics/headings.css index 657b08d..25020bd 100644 --- a/ui/source/css/basics/headings.css +++ b/ui/source/css/basics/headings.css @@ -25,4 +25,8 @@ h6 { .site-title { font-size: 1.75rem; font-weight: var(--font-weight-bold); +} + +.lobby__title { + font-size: 1.5rem; } \ No newline at end of file diff --git a/ui/source/css/basics/icons.css b/ui/source/css/basics/icons.css index 2779fe1..4af4133 100644 --- a/ui/source/css/basics/icons.css +++ b/ui/source/css/basics/icons.css @@ -1,13 +1,17 @@ .icon { - display: inline-block; - width: 1em; - height: 1em; - stroke-width: 0; - stroke: currentColor; - fill: currentColor; - transition: transform var(--anim-duration-fast) var(--anim-easing); - svg { - max-width: 100%; - max-height: 100%; + &::after { + content: ''; + display: inline-block; + margin-left: 0.5rem; + width: 1rem; + height: 1rem; + vertical-align: -2px; } +} + +.icon--master { + &::after { + background: transparent url('../images/eye.svg') 50% 50% no-repeat; + background-size: 1rem 1rem; + } } \ No newline at end of file diff --git a/ui/source/css/basics/inputs.css b/ui/source/css/basics/inputs.css index a3ffd62..03076b6 100644 --- a/ui/source/css/basics/inputs.css +++ b/ui/source/css/basics/inputs.css @@ -1,5 +1,12 @@ .input { + display: inline-block; + appearance: none; + padding: 0.5rem 0.75rem; + font-size: 1rem; font-family: var(--font-family-primary); + box-shadow: 0 0.25rem 0.25rem 0 rgba(0,0,0,0.15); + border: 1px solid var(--color-border); + border-radius: var(--border-radius); } .input--select { diff --git a/ui/source/css/basics/labels.css b/ui/source/css/basics/labels.css index ddc5592..3af836f 100644 --- a/ui/source/css/basics/labels.css +++ b/ui/source/css/basics/labels.css @@ -2,6 +2,11 @@ legend { } -.label { +label[for] { + cursor: pointer; +} +.label { + font-size: 0.8rem; + font-weight: var(--font-weight-light); } \ No newline at end of file diff --git a/ui/source/css/basics/switch.css b/ui/source/css/basics/switch.css index 1356b64..f1f51fa 100644 --- a/ui/source/css/basics/switch.css +++ b/ui/source/css/basics/switch.css @@ -1,36 +1,69 @@ -.switch { +.switch, +.switch-toggle { + margin: 0.5rem auto 1rem auto; + border: 2px solid var(--color-border); + border-radius: var(--border-radius); +} + +.switch-toggle { display: flex; } -.switch__item { - &:first-child { - .switch__label { - border-radius: 0.5rem 0 0 0.5rem; - } - } - &:last-child { - .switch__label { - border-radius: 0 0.5rem 0.5rem 0; - } - } - & + .switch__item { - .switch__label { - border-left: 0; +.switch { + display: block; + position: relative; + text-align: center; +} + +.switch__label, +.switch-toggle__label { + display: block; + color: var(--color-text); + background-color: transparent; + transition: background-color var(--anim-duration); +} + +.switch__control, +.switch-toggle__control { + display: none; + overflow: hidden; + height: 0; + width: 0; + visibility: hidden; +} + +.switch__control { + &:checked { + & + .switch__label { + background-color: var(--color-white); } } } -.switch__label { - padding: 0.25rem 1rem; - box-shadow: 0.25rem 0.25rem rgba(0, 0, 0, 0.25); - border: 1px solid var(--color-gray-30); - background: linear-gradient(to bottom, var(--color-gray-40) 0%, var(--color-gray-50) 100%); +.switch-toggle__item { + flex-grow: 1; + text-align: center; + & + & { + border-left: 1px solid var(--color-border); + } + &:first-child { + border-radius: var(--border-radius) 0 0 var(--border-radius); + } + &:last-child { + border-radius: 0 var(--border-radius) var(--border-radius) 0; + } } -.switch__input:checked + .switch__label { - color: var(--color-white); - background: linear-gradient(to bottom, var(--color-green-10) 0%, var(--color-green-20) 100%); - .sub-label { - font-weight: var(--font-weight-normal); +.switch-toggle__control { + &:checked { + & + .switch-toggle__label { + color: var(--color-white); + &.switch--blue { + background-color: var(--color-team-blue); + } + &.switch--red { + background-color: var(--color-team-red); + } + } } } \ No newline at end of file diff --git a/ui/source/css/basics/text.css b/ui/source/css/basics/text.css index fae60e7..1a76829 100644 --- a/ui/source/css/basics/text.css +++ b/ui/source/css/basics/text.css @@ -8,4 +8,8 @@ body { p { margin: 0 0 var(--spacing-vertical) 0; +} + +.text-center { + text-align: center; } \ No newline at end of file diff --git a/ui/source/css/components/frame/sidebar.css b/ui/source/css/components/frame/sidebar.css index d2e464f..9a0bfbc 100644 --- a/ui/source/css/components/frame/sidebar.css +++ b/ui/source/css/components/frame/sidebar.css @@ -3,6 +3,15 @@ margin: 1rem 0; border: solid; background-color: rgba(255,255,255,0.5); + .team-list { + & + .team-list { + margin-top: 1rem; + } + } + .switch__label, + .switch-toggle__label { + background-color: var(--color-gray-30); + } } @media (--large) { diff --git a/ui/source/css/components/lobby/entry.css b/ui/source/css/components/lobby/entry.css new file mode 100644 index 0000000..5781d4e --- /dev/null +++ b/ui/source/css/components/lobby/entry.css @@ -0,0 +1,31 @@ +.entry-prompt__form { + display: grid; + grid-template-columns: 1fr; + grid-gap: 1rem; + max-width: 45rem; + & > * { + display: block; + } + .label { + align-self: center; + } + +} + +@media (--small) { + .entry-prompt__form { + grid-template-columns: 1fr 1fr; + } +} + +@media (--medium) { + .entry-prompt__form { + grid-template-columns: 1fr 2fr 1fr; + input[type='submit'] { + grid-column: 1 / 4; + } + input[name='nameInput'] { + grid-column: 2/4; + } + } +} \ No newline at end of file diff --git a/ui/source/css/components/lobby/lobby.css b/ui/source/css/components/lobby/lobby.css new file mode 100644 index 0000000..3ba1a55 --- /dev/null +++ b/ui/source/css/components/lobby/lobby.css @@ -0,0 +1,15 @@ +.lobby-prompt__form { + +} + +@media (--medium) { + .lobby-prompt__form { + .teams-list { + display: flex; + justify-content: center; + } + .team-list { + margin: 0 1rem; + } + } +} \ No newline at end of file diff --git a/ui/source/css/components/player/team-list.css b/ui/source/css/components/player/team-list.css index bb3270a..bd93e43 100644 --- a/ui/source/css/components/player/team-list.css +++ b/ui/source/css/components/player/team-list.css @@ -2,16 +2,6 @@ margin: 1rem 0; } -.team-list { - & + & { - margin-top: 1rem; - } -} - -.team-list__item { - -} - .team-list__item--title { font-weight: var(--font-weight-light); border-bottom: 1px dotted var(--color-text); @@ -40,4 +30,15 @@ background: transparent url('../images/eye.svg') 50% 50% no-repeat; background-size: 1rem 1rem; } +} + +.team-list__item--ready { + &::before { + content: '✓'; + color: var(--color-positive); + } +} + +.team-list__item--current-player { + font-weight: var(--font-weight-bold); } \ No newline at end of file diff --git a/ui/source/css/components/status/status-list.css b/ui/source/css/components/status/status-list.css index 683ba37..a71f523 100644 --- a/ui/source/css/components/status/status-list.css +++ b/ui/source/css/components/status/status-list.css @@ -25,4 +25,8 @@ .text-outline { text-shadow: 1px 1px 0 rgba(255,255,255,1), 1px 1px 0 rgba(0,0,0,1); +} + +.display-score { + font-size: 1.8rem; } \ No newline at end of file diff --git a/ui/source/css/utilities/00-variables.css b/ui/source/css/utilities/00-variables.css index bddfd5e..af7572d 100644 --- a/ui/source/css/utilities/00-variables.css +++ b/ui/source/css/utilities/00-variables.css @@ -1,11 +1,21 @@ :root { --color-black: #000; --color-white: #fff; + --color-gray-10: #333; + --color-gray-20: #666; + --color-gray-30: #999; + --color-gray-40: #ccc; - --color-team-blue: rgb(0,0,255); - --color-team-red: rgb(255,0,0); + --color-team-blue: rgb(10,10,255); + --color-team-red: rgb(255,10,10); + + --color-green: rgb(25,150,25); + --color-positive: var(--color-green); + --color-red: rgb(255,0,0); + --color-negative: var(--color-red); --color-text: var(--color-black); + --color-border: var(--color-gray-30); --font-family-primary: 'Montserrat', sans-serif; --font-size-base: 1rem; diff --git a/ui/source/js/components/app.js b/ui/source/js/components/app.js new file mode 100644 index 0000000..80f8a97 --- /dev/null +++ b/ui/source/js/components/app.js @@ -0,0 +1,87 @@ +import React, {Component} from 'react'; +import Start from './start.js'; +import Lobby from './lobby.js'; +import Game from './game.js'; + +import {setSeed} from '../helpers/seedUtilities.js'; +import {setPlayerIsMaster} from '../helpers/teamUtilities.js'; +import router from '../helpers/router.js'; + +class App extends React.Component { + constructor(props) { + super(props); + this.state = { + page: 'start', + seed: null, + teams: null, + currentPlayerId: null, + currentPlayerName: null, + currentLobbyName: null + }; + this.handleEntrySubmit = this.handleEntrySubmit.bind(this); + this.handleLobbySubmit = this.handleLobbySubmit.bind(this); + this.updateTeams = this.updateTeams.bind(this); + } + + updateTeams(newTeams) { + this.setState({ teams: newTeams }); + } + + getPage(pageId) { + let pageRoute; + switch(pageId) { + case 'start': + pageRoute = ; + break; + case 'lobby': + pageRoute = ; + break; + case 'game': + pageRoute = ; + break; + default: + console.error('Invalid Page Id'); + } + return pageRoute; + } + + handleEntrySubmit(currentPlayerName, currentLobbyName) { + setSeed(currentLobbyName); + this.setState({ + page: 'lobby', + currentPlayerName: currentPlayerName, + currentLobbyName: currentLobbyName, + seed: currentLobbyName + }); + } + + handleLobbySubmit(lobbyTeams, currentPlayerId) { + this.setState({ + page: 'game', + teams: lobbyTeams, + currentPlayerId: currentPlayerId + }); + } + + render() { + return ( +
+ { this.getPage(this.state.page) } +
+ ); + } +} + +export default App; \ No newline at end of file diff --git a/ui/source/js/components/board.js b/ui/source/js/components/board.js index c6c4fc2..1e7a441 100644 --- a/ui/source/js/components/board.js +++ b/ui/source/js/components/board.js @@ -5,7 +5,8 @@ function Board(props) { function renderPiece(i) { return props.onClick(i)} />; diff --git a/ui/source/js/components/changePlayer.js b/ui/source/js/components/changePlayer.js new file mode 100644 index 0000000..47e53c2 --- /dev/null +++ b/ui/source/js/components/changePlayer.js @@ -0,0 +1,67 @@ +import React from 'react'; +import {getPlayerTeam, setPlayerTeam, getPlayerIsMaster, setPlayerIsMaster} from '../helpers/teamUtilities.js'; + +function ChangePlayer(props) { + + let playerIsMaster = getPlayerIsMaster(props.teams, props.currentPlayerId); + let masterIcon = generateMasterIcon(); + + function generateMasterIcon() { + return playerIsMaster ? Master : Player; + } + + function updatePlayerTeam(players, currentPlayerId, teamId) { + const updatedTeams = setPlayerTeam(players, currentPlayerId, teamId); + props.updateTeams(updatedTeams); + } + + function togglePlayerIsMaster(players, currentPlayerId, toggleStatus) { + const updatedTeams = setPlayerIsMaster(players, currentPlayerId, toggleStatus); + props.updateTeams(updatedTeams); + } + + return ( +
+ I'm a... +
+
+ updatePlayerTeam(props.teams, props.currentPlayerId, 1)} + className="switch-toggle__control" + /> + +
+
+ updatePlayerTeam(props.teams, props.currentPlayerId, 2)} + className="switch-toggle__control" + /> + +
+
+
+ togglePlayerIsMaster(props.teams, props.currentPlayerId, e.target.checked)} + className="switch__control" + /> + +
+
+ ); +} + +export default ChangePlayer; \ No newline at end of file diff --git a/ui/source/js/components/controls.js b/ui/source/js/components/controls.js index 47da6a0..6dd47c9 100644 --- a/ui/source/js/components/controls.js +++ b/ui/source/js/components/controls.js @@ -1,58 +1,40 @@ import React from 'react'; +import ChangePlayer from './changePlayer.js'; + +import {getPlayerTeam, getPlayerIsMaster} from '../helpers/teamUtilities.js'; function Controls(props) { - function getViewerState(viewerId, controlId) { - return viewerId === controlId; + let playerIsMaster = getPlayerIsMaster(props.teams, props.playerId); + let masterIcon = generateMasterIcon(); + + function isOtherTeamsTurn(teamArray, playerId, isBlueTurn) { + return getPlayerTeam(teamArray, playerId) === 1 ? !isBlueTurn : true; + } + + function isGameOver(winnerName) { + return winnerName !== null ? true : false; } - function isWinner(winnerName) { - if (winnerName !== null) { - return true; - } - return false; + function generateMasterIcon() { + return playerIsMaster ? Master : Player; } return ( ); diff --git a/ui/source/js/components/game.js b/ui/source/js/components/game.js index 594f508..cad7feb 100644 --- a/ui/source/js/components/game.js +++ b/ui/source/js/components/game.js @@ -2,9 +2,10 @@ import React, {Component} from 'react'; import Board from './board.js'; import Stats from './stats.js'; import Controls from './controls.js'; +import {getSeed} from '../helpers/seedUtilities.js'; import getWordlist from '../helpers/generateWordList.js'; import getOwnershipList from '../helpers/generateOwners.js'; -import generateTeams from '../helpers/teams.js'; +import {generateTeams, setPlayerTeam, setPlayerIsMaster} from '../helpers/teamUtilities.js'; import switchTurns from '../helpers/switchTurns.js'; import keepScore from '../helpers/keepScore.js'; import calculateWinner from '../helpers/winner.js'; @@ -36,26 +37,23 @@ class Game extends React.Component { super(props); this.state = { isBlueTurn: true, + seed: this.props.seed, score: { black: blackPieceCount, blue: bluePiecesCount, red: redPiecesCount }, pieces: buildPieceArray(), - viewer: 0, winner: null, - teams: generateTeams() + teams: this.props.teams, + currentPlayerId: this.props.currentPlayerId }; } - switchTeamsClick() { + switchTeamTurnClick() { this.setState({ isBlueTurn: !this.state.isBlueTurn }); } - setViewer(i) { - this.setState({ viewer: i }); - } - pieceChosenClick(i) { if (this.state.winner === null) { let updatedPieces = Array.from(this.state.pieces); @@ -84,6 +82,7 @@ class Game extends React.Component { newGame() { this.setState({ + seed: getSeed(), winner: null, isBlueTurn: true, pieces: buildPieceArray() @@ -103,25 +102,25 @@ class Game extends React.Component { this.pieceChosenClick(i)} /> this.switchTeamsClick()} - onClickViewMaster={() => this.setViewer(0)} - onClickViewBlue={() => this.setViewer(1)} - onClickViewRed={() => this.setViewer(2)} + teams={this.state.teams} + playerId={this.state.currentPlayerId} + isBlueTurn={this.state.isBlueTurn} + onClickSwitchTeams={() => this.switchTeamTurnClick()} onClickPromptNewGame={() => this.promptNewGame()} + updateTeams={this.props.updateTeams} /> ); diff --git a/ui/source/js/components/lobby.js b/ui/source/js/components/lobby.js new file mode 100644 index 0000000..7f22b59 --- /dev/null +++ b/ui/source/js/components/lobby.js @@ -0,0 +1,90 @@ +import React, {Component} from 'react'; +import TeamList from './teamList.js'; +import ChangePlayer from './changePlayer.js'; + +import {generateTeams, getPlayerPositionInArray, getAllPlayersReady} from '../helpers/teamUtilities.js'; + +const maxPlayers = 16; +const currentPlayerId = 1; + +class Lobby extends React.Component { + constructor(props) { + super(props); + this.state = { + teams: this.populateTeams(), + currentPlayerId: currentPlayerId, + currentPlayerIsReady: false, + allPlayersReady: false + }; + } + + togglePlayerReady(currentTeams, playerId) { + const playerIndex = getPlayerPositionInArray(currentTeams, playerId); + if (playerIndex >= 0) { + currentTeams[playerIndex].isReady = !currentTeams[playerIndex].isReady; + const isAllPlayersReady = getAllPlayersReady(currentTeams); + this.setState({ + teams: currentTeams, + currentPlayerIsReady: currentTeams[playerIndex].isReady, + allPlayersReady: isAllPlayersReady + }); + } else { + console.error('Player not found'); + } + } + + populateTeams() { + const players = generateTeams(); + if (players.length < maxPlayers) { + const currentPlayer = { + id: currentPlayerId, + name: this.props.currentPlayerName, + isMaster: false, + team: 1, + isReady: false + }; + players.push(currentPlayer); + return players; + } + console.error('Too many people'); + return players; + } + + render() { + const buttonReadyText = this.state.currentPlayerIsReady ? 'Ready' : 'Unready'; + + return ( +
+
this.props.handleLobbySubmit(this.state.teams, this.state.currentPlayerId)} className="lobby-prompt__form"> +

#{this.props.currentLobbyName}

+ + +
+ ...who is... + + ...to... + +
+ +
+ ); + } +} + +export default Lobby; \ No newline at end of file diff --git a/ui/source/js/components/piece.js b/ui/source/js/components/piece.js index ccdb771..ff2ef8e 100644 --- a/ui/source/js/components/piece.js +++ b/ui/source/js/components/piece.js @@ -1,9 +1,11 @@ import React from 'react'; +import {getPlayerIsMaster} from '../helpers/teamUtilities.js'; function Piece(props) { function getVisibleClass() { - return (props.isChosen || props.viewer === 0) ? `piece--${props.owner}` : 'piece--neutral'; + return (props.isChosen || getPlayerIsMaster(props.teams, props.playerId) === true) + ? `piece--${props.owner}` : 'piece--neutral'; } return ( diff --git a/ui/source/js/components/player.js b/ui/source/js/components/player.js index 4bd78b9..556812f 100644 --- a/ui/source/js/components/player.js +++ b/ui/source/js/components/player.js @@ -1,10 +1,35 @@ import React from 'react'; function Player(props) { + function playerIsCurrentPlayer() { + if (props.player.id === props.currentPlayerId) { + return 'team-list__item--current-player ' + } + return ''; + } + + function playerIsReady() { + if (props.player.isReady === true) { + return 'team-list__item--ready ' + } + return ''; + } + + function playerIsMaster() { + if (props.player.isMaster) { + return 'team-list__item--master '; + } + return ''; + } + return (
  • {props.player.name}
  • diff --git a/ui/source/js/components/start.js b/ui/source/js/components/start.js new file mode 100644 index 0000000..42c6e81 --- /dev/null +++ b/ui/source/js/components/start.js @@ -0,0 +1,77 @@ +import React, {Component} from 'react'; +import {getSeed, createSeed, setSeed} from '../helpers/seedUtilities.js'; +import {getPlayerName, setPlayerName} from '../helpers/playerUtilities.js'; +import {stripSpecialCharacters} from '../helpers/stringUtilities.js'; + +class Start extends React.Component { + constructor(props) { + super(props); + this.state = { + currentPlayerName: getPlayerName(), + currentLobbyName: getSeed() + }; + this.handleLobbyChange = this.handleLobbyChange.bind(this); + this.handleNameChange = this.handleNameChange.bind(this); + this.handleRandomClick = this.handleRandomClick.bind(this); + } + + handleLobbyChange(event) { + this.setState({ currentLobbyName: event.target.value.toLowerCase().substr(0,20) }); + } + + handleNameChange(event) { + this.setState({ currentPlayerName: stripSpecialCharacters(event.target.value).substr(0,20) }); + } + + handleRandomClick(event) { + this.setState({ currentLobbyName: createSeed() }); + } + + render() { + return ( +
    +
    this.props.handleEntrySubmit(this.state.currentPlayerName, this.state.currentLobbyName) + } className="entry-prompt__form"> + + + + + + +
    +
    + ); + } +} + +export default Start; \ No newline at end of file diff --git a/ui/source/js/components/stats.js b/ui/source/js/components/stats.js index e9cff79..89f55e1 100644 --- a/ui/source/js/components/stats.js +++ b/ui/source/js/components/stats.js @@ -1,32 +1,29 @@ import React from 'react'; import TeamList from './teamlist.js'; -import {getActiveTeamColorCSS, getViewerColorCSS, getViewerName} from '../helpers/decodeViewersAndWinners.js'; -import capitalizeFirstLetter from '../helpers/stringFunctions.js'; +import {getActiveTeamColorCSS} from '../helpers/classNames.js'; +import {capitalizeFirstLetter} from '../helpers/stringUtilities.js'; function Stats(props) { function getStatus(winner, isBlueTurn) { if (winner === null) { - return `Current Turn: ${(isBlueTurn ? 'Blue' : 'Red')}`; + return `${(isBlueTurn ? 'Blue' : 'Red')} Turn`; } winner = capitalizeFirstLetter(winner); - return `${winner} team wins.`; + return `${winner} Wins`; } return ( diff --git a/ui/source/js/components/teamlist.js b/ui/source/js/components/teamlist.js index 813dd29..8c12834 100644 --- a/ui/source/js/components/teamlist.js +++ b/ui/source/js/components/teamlist.js @@ -7,24 +7,29 @@ function TeamList(props) { return ; } - function generateList(teamArray) { + function generateList(teamArray, teamId) { let listItemsArray = []; - teamArray.forEach((player,i) => listItemsArray.push(renderPlayer(player, i))); - return listItemsArray; + if (teamArray) { + return teamArray.filter(player => player.team === teamId) + .map((player,i) => (renderPlayer(player, i))); + } + console.error('No team array provided'); + return Error; } return (
    • Blue
    • - {generateList(props.teams.blue)} + {generateList(props.teams, 1)}
    • Red
    • - {generateList(props.teams.red)} + {generateList(props.teams, 2)}
    ); diff --git a/ui/source/js/helpers/decodeViewersAndWinners.js b/ui/source/js/helpers/classNames.js similarity index 100% rename from ui/source/js/helpers/decodeViewersAndWinners.js rename to ui/source/js/helpers/classNames.js diff --git a/ui/source/js/helpers/generateWordList.js b/ui/source/js/helpers/generateWordList.js index e1f4121..5516587 100644 --- a/ui/source/js/helpers/generateWordList.js +++ b/ui/source/js/helpers/generateWordList.js @@ -2,20 +2,70 @@ import {shuffleArray} from './random.js'; function getWordlist(count) { const wordList = [ - 'press', 'fan', 'pyramid', 'torch', 'fall', - 'Himalayas', 'staff', 'pupil', 'drop', 'cotton', - 'bottle', 'belt', 'stadium', 'glove', 'robot', - 'glass', 'concert', 'bill', 'dress', 'pilot', - 'green', 'turkey', 'ketchup', 'crown', 'cliff', - 'bed', 'mass', 'Washington', 'box', 'dice', - 'honey', 'hole', 'olive', 'star', 'litter', - 'opera', 'shot', 'scientist', 'horn', 'time', - 'apple', 'Olympus', 'telescope', 'snow', 'pan', - 'princess', 'ivory', 'death', 'bugle', 'bark', - 'duck', 'dinosaur', 'paste', 'orange', 'bow', - 'straw', 'bug', 'doctor', 'cover', 'crane', - 'point', 'pool', 'pirate', 'eagle', 'teacher', - 'tie', 'cap', 'check', 'vacuum', 'shadow' + 'air', 'ambulance', 'ammonia', 'apple', 'appendix', 'archipelago', + + 'ball', 'banana', 'bark', 'baron', 'barrier', 'bed', 'belt', 'bill', 'bingo', 'blackberry', 'bonus', + 'bottle', 'bow', 'box', 'broccoli', 'brunch', 'bug', 'bugle', + + 'cap', 'cartridge', 'cassette', 'catfish', 'cemetery', 'check', 'Chihuahua', 'cilantro', 'circus', + 'cliff', 'coaster', 'coconut', 'code', 'command', 'concert', 'cover', 'conflict', 'cotton', 'coyote', + 'cracker', 'crane', 'crown', 'curfew', 'cursor', + + 'dad', 'dawn', 'death', 'demon', 'dentist', 'diagnosis', 'dice', 'dinosaur', 'discovery', 'doctor', + 'donkey', 'dress', 'drop', 'duchess', 'duck', + + 'Easter', 'eagle', 'editor', 'epilepsy', 'equator', 'error', 'espionage', + + 'fall', 'fan', 'flask', 'flora', 'fox', 'fries', 'fundraiser', 'fusion', + + 'glass', 'glove', 'glucose', 'google', 'green', 'gun', + + 'hallway', 'hamburger', 'hammock', 'hand', 'head', 'heart', 'Himalayas', 'hole', 'honey', 'horn', + 'horseman', 'hurricane', 'hydra', + + 'iceberg', 'illness', 'intersection', 'ivory', + + 'Jabberwocky', 'jack', 'jerky', 'joker', 'juror', + + 'kangaroo', 'ketchup', 'kingdom', + + 'leopard', 'ligament', 'litter', 'logic', 'lookout', + + 'mango', 'mass', 'matrix', 'medic', 'mirth', 'molasses', 'morale', 'motto', 'murder', + + 'network', 'nexus', 'nightmare', 'noodle', + + 'oasis', 'offense', 'olive', 'Olympus', 'opera', 'oracle', 'orange', 'oxygen', + + 'pan', 'panther', 'pasta', 'paste', 'patriotism', 'pilot', 'pirate', 'plaza', 'point', 'poker', + 'pool', 'potassium', 'pottery', 'poultry', 'press', 'princess', 'prisoner', 'privacy', 'processor', + 'protein', 'prototype', 'puberty', 'pupil', 'pyramid', + + 'quart', 'quartz', 'queen', + + 'racism', 'ranger', 'recipe', 'recreation', 'refrigerator', 'reins', 'repository', 'republic', 'restaurant', 'roadblock', + 'robber', 'robot', 'rodeo', 'rocks', + + 'saloon', 'Saturday', 'scenario', 'scholarship', 'scientist', 'scissors', 'scrum', 'seduction', 'senator', 'sesame', + 'setup', 'shadow', 'shop', 'shot', 'siding', 'sister', 'skate', 'snack', 'snail', 'snapshot', + 'snow', 'soccer', 'spaghetti', 'spoiler', 'squad', 'staff', 'stadium', 'stage', 'stairway', 'straw', + 'statement', 'star', 'stocks', 'subscription', 'suburb', 'success', 'sweater', 'syndrome', 'syntax', + + 'tavern', 'teacher', 'technology', 'telescope', 'telephone', 'terror', 'theater', 'therapy', 'thunder', 'tie', + 'tiger', 'time', 'today', 'touchdown', 'torch', 'tourist', 'tractor', 'transmission', 'trauma', 'treadmill', + 'trilogy', 'trout', 'turkey', 'tyrant', + + 'underdog', 'underwear', 'university', + + 'vaccination', 'vacuum', 'vampire', 'vanguard', 'victory', 'viewpoint', 'villa', 'vista', 'vocalist', 'volcano', + 'voltage', + + 'waistcoat', 'waitress', 'wardrobe', 'warmth', 'Washington', 'watchdog', 'wealth', 'werewolf', 'whisky', 'widget', + 'width', 'windfall', 'wiring', 'witchcraft', 'words', 'workman', + + 'yak', 'yogurt', 'youngster', + + 'Zanzibar', 'zibra', 'zoo' ]; return shuffleArray(wordList).slice(0, count); } diff --git a/ui/source/js/helpers/playerUtilities.js b/ui/source/js/helpers/playerUtilities.js new file mode 100644 index 0000000..72d75ad --- /dev/null +++ b/ui/source/js/helpers/playerUtilities.js @@ -0,0 +1,13 @@ +function getPlayerName() { + const playerName = window.localStorage.getItem('playerName'); + return playerName ? playerName : ''; +} + +function setPlayerName(playerName) { + console.log(playerName); + if (playerName) { + window.localStorage.setItem('playerName', playerName); + } +} + +export {getPlayerName, setPlayerName}; \ No newline at end of file diff --git a/ui/source/js/helpers/router.js b/ui/source/js/helpers/router.js new file mode 100644 index 0000000..54d9071 --- /dev/null +++ b/ui/source/js/helpers/router.js @@ -0,0 +1,7 @@ +import React from 'react'; + +function router(route) { + console.log("Router online", route); +} + +export default router; \ No newline at end of file diff --git a/ui/source/js/helpers/seedUtilities.js b/ui/source/js/helpers/seedUtilities.js new file mode 100644 index 0000000..8fb609e --- /dev/null +++ b/ui/source/js/helpers/seedUtilities.js @@ -0,0 +1,25 @@ +import getWordlist from './generateWordList.js'; +import {stripSpecialCharacters} from './stringUtilities.js'; + +function getSeed() { + let seed = stripSpecialCharacters(window.location.hash).toLowerCase().substr(0,20); + if (!seed) { + seed = createSeed(); + } + setSeed(seed); + return seed; +} + +function createSeed(newSeed) { + if (!newSeed) { + return getWordlist(2).join('-').toLowerCase(); + } else { + return newSeed.toLowerCase(); + } +} + +function setSeed(newSeed) { + window.location.hash = newSeed; +} + +export {getSeed, setSeed, createSeed}; \ No newline at end of file diff --git a/ui/source/js/helpers/stringFunctions.js b/ui/source/js/helpers/stringFunctions.js deleted file mode 100644 index 6206bfa..0000000 --- a/ui/source/js/helpers/stringFunctions.js +++ /dev/null @@ -1,5 +0,0 @@ -function capitalizeFirstLetter(string) { - return string.charAt(0).toUpperCase() + string.slice(1); -} - -export default capitalizeFirstLetter; \ No newline at end of file diff --git a/ui/source/js/helpers/stringUtilities.js b/ui/source/js/helpers/stringUtilities.js new file mode 100644 index 0000000..eb0a38d --- /dev/null +++ b/ui/source/js/helpers/stringUtilities.js @@ -0,0 +1,9 @@ +function capitalizeFirstLetter(string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} + +function stripSpecialCharacters(string) { + return string.replace(/[^a-zA-Z-]/g, ''); +} + +export {capitalizeFirstLetter, stripSpecialCharacters}; \ No newline at end of file diff --git a/ui/source/js/helpers/teamUtilities.js b/ui/source/js/helpers/teamUtilities.js new file mode 100644 index 0000000..b582cd9 --- /dev/null +++ b/ui/source/js/helpers/teamUtilities.js @@ -0,0 +1,76 @@ +function setPlayerTeam(playerArray, playerId, newPlayerTeam) { + const position = getPlayerPositionInArray(playerArray, playerId); + playerArray[position].team = newPlayerTeam; + return playerArray; +} + +function setPlayerIsMaster(playerArray, playerId, newPlayerIsMaster) { + const position = getPlayerPositionInArray(playerArray, playerId); + playerArray[position].isMaster = newPlayerIsMaster; + return playerArray; +} + +function getPlayerPositionInArray(playerArray, playerId) { + if (!playerArray) { + console.error('No team array'); + } + return playerArray.map(player => player.id).indexOf(playerId); +} + +function getPlayerTeam(playerArray, playerId) { + const position = getPlayerPositionInArray(playerArray, playerId); + return playerArray[position].team; +} + +function getPlayerIsMaster(playerArray, playerId) { + const position = getPlayerPositionInArray(playerArray, playerId); + return playerArray[position].isMaster; +} + +function getAllPlayersReady(playerArray) { + const readyPlayersArray = playerArray.filter(player => player.isReady); + const allPlayersReady = (playerArray.length === readyPlayersArray.length); + return allPlayersReady; +} + +function generateTeams() { + return [ + { + id: 2, + name: 'Jac', + isMaster: false, + team: 1, + isReady: true + }, + { + id: 3, + name: 'Jeff', + isMaster: false, + team: 1, + isReady: true + }, + { + id: 4, + name: 'Aaron', + isMaster: true, + team: 2, + isReady: true + }, + { + id: 5, + name: 'Anna', + isMaster: false, + team: 2, + isReady: true + }, + { + id: 6, + name: 'Andy', + isMaster: false, + team: 2, + isReady: true + } + ]; +} + +export {generateTeams, setPlayerTeam, setPlayerIsMaster, getPlayerTeam, getPlayerIsMaster, getPlayerPositionInArray, getAllPlayersReady}; \ No newline at end of file diff --git a/ui/source/js/helpers/teams.js b/ui/source/js/helpers/teams.js deleted file mode 100644 index 5894c40..0000000 --- a/ui/source/js/helpers/teams.js +++ /dev/null @@ -1,34 +0,0 @@ -function generateTeams() { - return { - blue: [ - { - name: 'Joseph', - isMaster: true - }, - { - name: 'Jac', - isMaster: false - }, - { - name: 'Jeff', - isMaster: false - } - ], - red: [ - { - name: 'Aaron', - isMaster: true - }, - { - name: 'Anna', - isMaster: false - }, - { - name: 'Andy', - isMaster: false - } - ] - }; -} - -export default generateTeams; \ No newline at end of file diff --git a/ui/source/js/main.js b/ui/source/js/main.js index a00b355..0b1fcae 100644 --- a/ui/source/js/main.js +++ b/ui/source/js/main.js @@ -1,10 +1,10 @@ import React from 'react'; import {render} from 'react-dom'; -import Game from './components/game.js'; +import App from './components/app.js'; const rootEl = document.getElementById('app'); render( - , + , rootEl ); \ No newline at end of file