diff --git a/README.md b/README.md index 1f5996d..5a08ffe 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,30 @@ -# 2020 L4 Application Programming coursework +# Scrabble (Multiplayer) +## 2020/21 L4 Application Programming coursework SEE BELOW FOR CONFIGURATION GUIDE -## Product Description +### Product Description https://scrabble.hasbro.com/en-us/rules https://www.zapsplat.com/?s=scrabble https://www.scrabble3d.info/t2342f139-Default-rules.html -## Configuration Guide + +If the scope allowed for it, every function would be (reasonably) unit tested. + +The solution to locale-ise language in HTML is extremely naive and there are a lot better ways to do it, i did what i could in the time without a full refractor and SSR. +However it is not at much detriment of readability and maintainability of the code so i diddn't deem it neccesary. + +The locales are stored in different language files so it is easier for people to contribute and thus more maintanable. + +### Configuration Guide +### Contributing -## Acknowledgements +To contribute a translation + +### Acknowledgements Inês Filipa Baiõa Antunes - Tranlations (Portuguese, Spanish) diff --git a/client/public/game/index.html b/client/public/game/index.html index 5f54dc5..89f3031 100644 --- a/client/public/game/index.html +++ b/client/public/game/index.html @@ -12,8 +12,9 @@ Lobby - -

Game Lobby

+ + +

@@ -22,9 +23,12 @@ diff --git a/client/public/index.js b/client/public/index.js index f3d4d43..3846239 100644 --- a/client/public/index.js +++ b/client/public/index.js @@ -8,7 +8,7 @@ UsernameForm.addEventListener('submit', onUsernameSubmit); function playSingleplayer() { - document.location.href += '/scrabble'; + window.location.pathname = "/scrabble"; } // User submits their desired username @@ -38,7 +38,7 @@ async function onUsernameSubmit(e) if (body.errors) { ConnectionState.classList.add('red'); - ConnectionState.innerHTML = `ERROR: ${body.errors[body.errors.length - 1].desc}`; + ConnectionState.innerHTML = `${localeString('error-bold')}: ${localeString(body.errors[body.errors.length - 1].desc)}`; return; } @@ -51,6 +51,6 @@ async function onUsernameSubmit(e) { sessionStorage.setItem('user', JSON.stringify(body.login.user)); console.log(sessionStorage.user) - document.location.href += 'game'; + window.location.pathname = "/game"; } } diff --git a/client/public/scrabble/board.js b/client/public/scrabble/board.js index fa2272d..7bf17c3 100644 --- a/client/public/scrabble/board.js +++ b/client/public/scrabble/board.js @@ -58,7 +58,15 @@ window.onload = e => { const boardLocation = document.querySelector(`#row-${y}`).querySelector(`#col-${x}`); boardLocation.classList.add(BoardLookup[BoardLocations[location]]); - boardLocation.innerHTML = BoardLocations[location]; + let localeThing = BoardLocations[location]; + + // hacky but it works + if (localStorage.getItem('locale') === "es" || localStorage.getItem('locale') === "pt") + { + localeThing = localeThing.replace('W', 'P'); + } + + boardLocation.innerHTML = localeThing; } // flip it @@ -73,6 +81,13 @@ window.onload = e => { const boardLocation = document.querySelector(`#row-${y}`).querySelector(`#col-${x}`); boardLocation.classList.add(BoardLookup[BoardLocations[location]]); - boardLocation.innerHTML = BoardLocations[location]; + let localeThing = BoardLocations[location]; + + if (localStorage.getItem('locale') === "es" || localStorage.getItem('locale') === "pt") + { + localeThing = localeThing.replace('W', 'P'); + } + + boardLocation.innerHTML = localeThing; } }; diff --git a/data/locale.json b/data/locale.json new file mode 100644 index 0000000..d11ec75 --- /dev/null +++ b/data/locale.json @@ -0,0 +1,288 @@ +{ + "scrabble-name": { + "en": "Scrabble", + "es": "Scrabble", + "pt": "Scrabble" + }, + "game-lobby": { + "en": "create or join a game", + "es": "Crea o conecta a un juego", + "pt": "Crie ou entre em um jogo" + }, + "name": { + "en": "name", + "es": "nombre", + "pt": "nome" + }, + "username": { + "en": "Username", + "es": "Nombre de usuario", + "pt": "Nome de usuàrio" + }, + "players": { + "en": "Players", + "es": "Jugadores", + "pt": "Jogadores" + }, + "button-singleplayer": { + "en": "Play singleplayer", + "es": "Jugar a un(a) jugador(a)", + "pt": "Jogar singleplayer" + }, + "button-submit": { + "en": "Submit", + "es": "Enviar", + "pt": "Enviar" + }, + "button-create": { + "en": "create", + "es": "crear", + "pt": "criar" + }, + "button-join": { + "en": "join", + "es": "participar", + "pt": "entrar" + }, + "button-back": { + "en": "back", + "es": "regresar", + "pt": "voltar" + }, + + "status-connected": { + "en": "Connected", + "es": "Conectado(a)", + "pt": "Conectado(a)" + }, + "status-connected-as": { + "en": "Connected as ", + "es": "Conectado/a como ", + "pt": "Conectado/a como " + }, + "status-disconnected": { + "en": "Disconnected", + "es": "Desconectado/a", + "pt": "Desconectado/a" + }, + "connection-waiting": { + "en": "Waiting for connection", + "es": "Esperando la conexión", + "pt": "Aguardando conexão" + }, + + "message": { + "en": "message", + "es": "mensaje", + "pt": "mensagem" + }, + "log-console": { + "en": "log console", + "es": "consola de log", + "pt": "console de log" + }, + "button-send": { + "en": "send", + "es": "enviar", + "pt": "enviar" + }, + + "lobby": { + "en": "Lobby", + "es": "Lobby", + "pt": "Lobby" + }, + "lobby-create": { + "en": "Create Lobby", + "es": "Crear Lobby", + "pt": "Criar Lobby" + }, + "lobby-join": { + "en": "Join Lobby", + "es": "Conectarse al Lobby", + "pt": "Conectar ao Lobby" + }, + "lobby-join-code": { + "en": "Join Code", + "es": "Código para Conectar", + "pt": "Código para Conectar" + }, + "lobby-code": { + "en": "lobby code", + "es": "código de lobby", + "pt": "código do lobby" + }, + "lobby-private": { + "en": "private lobby", + "es": "lobby privado", + "pt": "lobby privado" + }, + "lobby-allow-spectators": { + "en": "allow spectators", + "es": "permitir espectadores", + "pt": "permitir espectadores" + }, + "lobby-join-spectator": { + "en": "join as spectator", + "es": "conectar como espectador(a)", + "pt": "junte-se como espectador" + }, + "lobby-created-joining": { + "en": "Lobby created, Joining...", + "es": "Lobby creado, Conectando...", + "pt": "Lobby criaso, Juntando-se..." + }, + "lobby-created": { + "en": "created lobby", + "es": "lobby creado", + "pt": "Lobby criado" + }, + "lobby-joining": { + "en": "joining lobby", + "es": "entrando al lobby", + "pt": "entrando no lobby" + }, + "lobby-joined": { + "en": "joined lobby", + "es": "entró en el lobby", + "pt": "entrou no lobby" + }, + "lobby-deleted": { + "en": "deleted lobby", + "es": "lobby eliminado", + "pt": "lobby apagado" + }, + "joined": { + "en": "joined", + "es": "conectado(a)", + "pt": "juntou" + }, + "left": { + "en": "left", + "es": "salió", + "pt": "saiu" + }, + "left-lobby": { + "en": "left lobby", + "es": "salió del lobby", + "pt": "saiu do lobby" + }, + + "spectators": { + "en": "Spectators", + "es": "Espectadores", + "pt": "Espectadores" + }, + "visibility": { + "en": "Visibility", + "es": "Visibilidad", + "pt": "Visibilidade" + }, + "status": { + "en": "Status", + "es": "Status", + "pt": "Status" + }, + "button-start-game": { + "en": "Start Game", + "es": "Empezar Juego", + "pt": "Começar Jogo" + }, + "button-leave-lobby": { + "en": "Leave Lobby", + "es": "Salir del Lobby", + "pt": "Sair do Lobby" + }, + + + "error-bold": { + "en": "ERROR", + "es": "ERRO", + "pt": "ERROR" + }, + "error-no-username": { + "en": "Username not present", + "es": "Nombre de usuario no esta presente", + "pt": "Nome de usuário não esta presente" + }, + "error-invalid-username": { + "en": "Invalid username", + "es": "Nombre de usuario no es válido", + "pt": "Nome de usuário Inválido" + }, + "error-taken-username": { + "en": "Username taken", + "es": "Nombre de usuario no esta disponible", + "pt": "Nome de usuário já está em uso" + }, + "error-too-many-clients": { + "en": "Too many connections", + "es": "Demasiadas conexiones", + "pt": "Demasiadas conexões" + }, + "error-bad-intent": { + "en": "Client has no intent", + "es": "Cliente no tiene intención", + "pt": "Cliente não tem intenção" + }, + "error-unknown-uid": { + "en": "Unknown user ID", + "es": "ID de usuario desconocido", + "pt": "ID de usuário desconhecido" + }, + "error-taken-user-connection": { + "en": "User already connected", + "es": "Usuario ya está conectado/a", + "pt": "Usuário já está conectado/a" + }, + "error-illegal-user": { + "en": "Illegal user", + "es": "Usuario ilegal", + "pt": "Usuário ilegal" + }, + "error-malformed-lobby": { + "en": "Lobby malformed", + "es": "Lobby malformado", + "pt": "Lobby malformado" + }, + "error-taken-lobby-ownership": { + "en": "User already owns lobby", + "es": "Usuario ya tiene lobby", + "pt": "Usuário já tem um lobby" + }, + "error-illegal-lobby": { + "en": "Illegal lobby", + "es": "Lobby ilegal", + "pt": "Lobby ilegal" + }, + "error-cannot-join-lobby": { + "en": "Cannot join lobby", + "es": "No se puede unir al lobby", + "pt": "Não é possível entrar no lobby" + }, + "error-lobby-not-exist": { + "en": "Lobby does not exist", + "es": "Lobby no existe", + "pt": "Lobby não existe" + }, + "error-lobby-name-required": { + "en": "A name is requred", + "es": "Se requiere un nombre", + "pt": "Um nome é obrigatório" + }, + "error-creating-lobby": { + "en": "An error occurred while creating the lobby ", + "es": "Ocurrió un error al crear el lobby ", + "pt": "Ocorreu um erro ao criar o lobby " + }, + "error-lobby-id-required": { + "en": "A lobby ID is required", + "es": "Se requiere un lobby ID", + "pt": "É necessário um lobby ID" + }, + "error-lobby-joining": { + "en": "An error occurred while joining the lobby ", + "es": "Ocurrió un error al conectarse al lobby ", + "pt": "Ocorreu um erro ao entrar no lobby " + } +} diff --git a/scripts/deploy.js b/scripts/deploy.js new file mode 100644 index 0000000..e69de29 diff --git a/scripts/langParser.js b/scripts/langParser.js new file mode 100644 index 0000000..e69de29 diff --git a/scripts/localeToLang.js b/scripts/localeToLang.js new file mode 100644 index 0000000..e69de29 diff --git a/server/locale.json b/server/locale.json deleted file mode 100644 index d2bc235..0000000 --- a/server/locale.json +++ /dev/null @@ -1,110 +0,0 @@ -{ - "scrabble-name": { - "en": "Scrabble", - "es": "Scrabble", - "pt": "Scrabble" - }, - "username": { - "en": "Username", - "es": "Nombre de usuario", - "pt": "Nome de usuàrio" - }, - "button-singleplayer": { - "en": "Play singleplayer", - "es": "Jugar a un(a) jugador(a)", - "pt": "Jogar singleplayer" - }, - "button-submit": { - "en": "Submit", - "es": "Enviar", - "pt": "Enviar" - }, - "status-connected": { - "en": "Connected", - "es": "Conectado(a)", - "pt": "Conectado(a)" - }, - - - "error-bold": { - "en": "ERROR", - "es": "ERRO", - "pt": "ERROR" - }, - "error-no-username": { - "en": "Username not present", - "es": "Nombre de usuario no esta presente", - "pt": "Nome de usuário não esta presente" - }, - "error-invalid-username": { - "en": "Invalid username", - "es": "Nombre de usuario no es válido", - "pt": "Nome de usuário Inválido" - }, - "error-taken-username": { - "en": "Username taken", - "es": "Nombre de usuario no esta disponible", - "pt": "Nome de usuário já está em uso" - }, - "error-too-many-clients": { - "en": "Too many connections", - "es": "Demasiadas conexiones", - "pt": "Demasiadas conexões" - }, - "error-bad-intent": { - "en": "Client has no intent", - "es": "Cliente no tiene intención", - "pt": "Cliente não tem intenção" - }, - "error-unknown-uid": { - "en": "Unknown user ID", - "es": "", - "pt": "" - }, - "error-taken-user-connection": { - "en": "User already connected", - "es": "", - "pt": "" - }, - "error-illegal-user": { - "en": "Illegal user", - "es": "", - "pt": "" - }, - "error-malformed-lobby": { - "en": "Lobby malformed", - "es": "", - "pt": "" - }, - "error-taken-lobby-ownership": { - "en": "User already owns lobby", - "es": "", - "pt": "" - }, - "error-illegal-lobby": { - "en": "Illegal lobby", - "es": "", - "pt": "" - }, - "error-cannot-join-lobby": { - "en": "Cannot join lobby", - "es": "", - "pt": "" - }, - "error-lobby-not-exist": { - "en": "Lobby does not exist", - "es": "", - "pt": "" - }, - "error-lobby-join": { - "en": "Cannot join lobby", - "es": "", - "pt": "" - }, - - - - "en": "", - "es": "", - "pt": "" -} diff --git a/server/src/locale.js b/server/src/locale.js index 36b262d..a908723 100644 --- a/server/src/locale.js +++ b/server/src/locale.js @@ -1,10 +1,13 @@ +const Logger = require('./logger.js'); + const FS = require('fs'); let locales = {}; -function init() +async function init() { - locales = JSON.parse(FS.readFileSync('./locale.json')); + locales = JSON.parse(FS.readFileSync('../data/locale.json')); + Logger.info('LOCALES LOADED'); } function GetLocaleListJSON() diff --git a/server/src/socketserver.js b/server/src/socketserver.js index 2faaa87..46d5dcb 100644 --- a/server/src/socketserver.js +++ b/server/src/socketserver.js @@ -101,6 +101,8 @@ function ClientIdentify(socket, args) } } +// if i use a database in the future i need to consider that the lobby +// name is not yet sanatised function LobbyCreate(socket, args) { const err = new Error; @@ -201,7 +203,7 @@ function LobbyJoin(socket, args) // Make sure user isn't already in a lobby if (!Game.Lobbies.CheckUserAvailability(useruid)) { - err.addError(400, 'Bad Request', 'Uerror-taken-lobby-ownership'); + err.addError(400, 'Bad Request', 'error-taken-lobby-ownership'); socket.emit('lobby-join-error', err.toError); return; } @@ -223,7 +225,7 @@ function LobbyJoin(socket, args) if (!status) { - err.addError(403, 'Forbidden', 'error-lobby-join'); + err.addError(403, 'Forbidden', 'error-cannot-join-lobby'); socket.emit('lobby-join-error', err.toError); return; }