merge from master

This commit is contained in:
simplonco
2023-01-03 20:03:26 +01:00
81 changed files with 2624 additions and 4454 deletions

12
.gitignore vendored
View File

@@ -15,13 +15,11 @@ Thumbs.db
*.log *.log
# compiled output # compiled output
/dist
node_modules node_modules
./srcs/requirement/api_back/node_modules ./srcs/requirement/nestjs/api_back/dist
./srcs/requirement/api_back/dist ./srcs/requirements/svelte/api_front/public/build/
./srcs/requirement/api_front/node_modules
./srcs/requirement/api_front/public/build
# Logs # Logs
logs logs
*.log *.log
@@ -53,3 +51,7 @@ lerna-debug.log*
!.vscode/tasks.json !.vscode/tasks.json
!.vscode/launch.json !.vscode/launch.json
!.vscode/extensions.json !.vscode/extensions.json
.env
memo.txt

View File

@@ -1,3 +1,6 @@
- CONFLICT srcs/requirements/svelte/api_front/public/build/bundle.js
- CONFLICT srcs/requirements/svelte/api_front/public/build/bundle.js.map
### Pour lancer le docker : ### Pour lancer le docker :

156
make_env.sh Normal file → Executable file
View File

@@ -1,6 +1,12 @@
#! /usr/bin/env bash #! /usr/bin/env bash
ENV_FILE_DOCKER=./srcs/.env
ENV_FILE_SVELTE=./srcs/requirements/svelte/api_front/.env
NGINX_CONF_FILE=./srcs/requirements/nginx/conf/default.conf
BOLD_RED="\033[1;31m"
BOLD_GREEN="\033[1;32m"
BOLD_BLUE="\033[1;34m"
RESET="\033[0m"
# Function to generate passwords # Function to generate passwords
# #
@@ -12,34 +18,25 @@
echo $(openssl rand -base64 32 | tr "/" "_" ); echo $(openssl rand -base64 32 | tr "/" "_" );
} }
function make_env_for_svelte
{
echo -e "${BOLD_BLUE}Creating a new environment for svelte${RESET}"
grep "^WEBSITE_" "$ENV_FILE_DOCKER" > "$ENV_FILE_SVELTE"
}
function update_nginx_conf
{
echo -e "${BOLD_BLUE}Updating the nginx conf${RESET}"
echo -e "${BOLD_RED}WARNING : If for some reason you've changed the port, you MUST change it inside the nginx conf file. It's not supposed to change.${RESET}"
HOST=$(grep "^WEBSITE_HOST" $ENV_FILE_DOCKER | cut -d "=" -f 2)
sed -i "s/server_name.*/server_name $HOST;/g" "$NGINX_CONF_FILE"
}
# This script is used to create a new environment for the project. function make_env_for_docker_and_svelte
# {
ENV_FILE_DOCKER=./srcs/.env docker rm -f postgresql
ENV_FILE_NESTJS=./srcs/requirements/nestjs/api_back/.env docker volume rm -f srcs_data_nest_postgresql
# Check for existing .env echo -e "${BOLD_BLUE}Creating a new environment for docker${RESET}"
if [ -f "$ENV_FILE_DOCKER" ] && [ -f "$ENV_FILE_NESTJS" ]; then
echo "The file $ENV_FILE_DOCKER and $ENV_FILE_NESTJS already exists. Do you want to overwrite them ? (y/n)"
OVERWRITE=""
# Ask to overwrite the .env files
while [ "$OVERWRITE" != "y" ] && [ "$OVERWRITE" != "n" ]; do
read -p "Enter your choice : " OVERWRITE
done
if [ "$OVERWRITE" = "y" ]; then
rm "$ENV_FILE_DOCKER" && rm "$ENV_FILE_NESTJS"
docker rmi -f postgres
else
echo "The file $ENV_FILE_DOCKER and $ENV_FILE_NESTJS will not be overwritten. The script will exit."
exit 0
fi
fi
# Create a new environment for docker
#
echo "Creating a new environment for docker"
NODE_ENV="" NODE_ENV=""
# Ask if dev or prod environment # Ask if dev or prod environment
while [ "$NODE_ENV" != "1" ] && [ "$NODE_ENV" != "2" ]; do while [ "$NODE_ENV" != "1" ] && [ "$NODE_ENV" != "2" ]; do
@@ -50,7 +47,6 @@
else else
echo "NODE_ENV=production" > "$ENV_FILE_DOCKER" echo "NODE_ENV=production" > "$ENV_FILE_DOCKER"
fi fi
# Env variables
read -p "Enter the name of the host like \"localhost\" : " PROJECT_HOST read -p "Enter the name of the host like \"localhost\" : " PROJECT_HOST
echo "WEBSITE_HOST=$PROJECT_HOST" >> "$ENV_FILE_DOCKER" echo "WEBSITE_HOST=$PROJECT_HOST" >> "$ENV_FILE_DOCKER"
echo "WEBSITE_PORT=8080" >> "$ENV_FILE_DOCKER" echo "WEBSITE_PORT=8080" >> "$ENV_FILE_DOCKER"
@@ -63,36 +59,90 @@
echo "REDIS_HOST=redis" >> "$ENV_FILE_DOCKER" echo "REDIS_HOST=redis" >> "$ENV_FILE_DOCKER"
echo "REDIS_PORT=6379" >> "$ENV_FILE_DOCKER" echo "REDIS_PORT=6379" >> "$ENV_FILE_DOCKER"
echo "REDIS_PASSWORD=$(generate_password)" >> "$ENV_FILE_DOCKER" echo "REDIS_PASSWORD=$(generate_password)" >> "$ENV_FILE_DOCKER"
# Create a new environment for nestjs
#
echo "Creating a new environment for nestjs"
echo "NODE_ENV=\$NODE_ENV" > "$ENV_FILE_NESTJS"
echo "WEBSITE_HOST=\$WEBSITE_HOST" >> "$ENV_FILE_NESTJS"
echo "WEBSITE_PORT=\$WEBSITE_PORT" >> "$ENV_FILE_NESTJS"
echo "POSTGRES_USER=\$POSTGRES_USER" >> "$ENV_FILE_NESTJS"
echo "POSTGRES_PASSWORD=\$POSTGRES_PASSWORD" >> "$ENV_FILE_NESTJS"
echo "POSTGRES_DB=\$POSTGRES_DB" >> "$ENV_FILE_NESTJS"
echo "POSTGRES_HOST=\$POSTGRES_HOST" >> "$ENV_FILE_NESTJS"
echo "POSTGRES_PORT=\$POSTGRES_PORT" >> "$ENV_FILE_NESTJS"
# Connection to 42 # Connection to 42
echo "In the next steps, we'll need to enter the client secret and client id of the 42 api" echo -e "${BOLD_BLUE}In the next steps, we'll need to enter the client secret and client id of the 42 api${RESET}"
read -p "Enter the client id of the 42 api : " CLIENT_ID read -p "Enter the client id of the 42 api : " CLIENT_ID
echo "FORTYTWO_CLIENT_ID=$CLIENT_ID" >> "$ENV_FILE_NESTJS" echo "FORTYTWO_CLIENT_ID=$CLIENT_ID" >> "$ENV_FILE_DOCKER"
read -p "Enter the client secret of the 42 api : " CLIENT_SECRET read -p "Enter the client secret of the 42 api : " CLIENT_SECRET
echo "FORTYTWO_CLIENT_SECRET=$CLIENT_SECRET" >> "$ENV_FILE_NESTJS" echo "FORTYTWO_CLIENT_SECRET=$CLIENT_SECRET" >> "$ENV_FILE_DOCKER"
FT_CALLBACK="http://\$WEBSITE_HOST:\$WEBSITE_PORT/api/v2/auth/redirect" FT_CALLBACK="http://$PROJECT_HOST:8080/api/v2/auth/redirect"
echo "FORTYTWO_CALLBACK_URL=$FT_CALLBACK" >> "$ENV_FILE_NESTJS" echo "FORTYTWO_CALLBACK_URL=$FT_CALLBACK" >> "$ENV_FILE_DOCKER"
# Other configs # Other configs
echo "COOKIE_SECRET=$(generate_password)" >> "$ENV_FILE_NESTJS" echo "COOKIE_SECRET=$(generate_password)" >> "$ENV_FILE_DOCKER"
echo "PORT=3000" >> "$ENV_FILE_NESTJS" echo "PORT=3000" >> "$ENV_FILE_DOCKER"
echo "TWO_FACTOR_AUTHENTICATION_APP_NAME=Transcendance" >> "$ENV_FILE_NESTJS" echo "TWO_FACTOR_AUTHENTICATION_APP_NAME=Transcendance" >> "$ENV_FILE_DOCKER"
echo "TICKET_FOR_PLAYING_GAME_SECRET=$(generate_password)" >> "$ENV_FILE_NESTJS" echo "TICKET_FOR_PLAYING_GAME_SECRET=$(generate_password)" >> "$ENV_FILE_DOCKER"
make_env_for_svelte
update_nginx_conf
echo -e "${BOLD_GREEN}Environment created.${RESET}"
echo -e "${BOLD_GREEN}The script will exit${RESET}"
exit 0
}
function change_host_and_port_api
{
if [ -f "$ENV_FILE_DOCKER" ]
then
echo -e "${BOLD_BLUE}Changing the host and the port of the api${RESET}"
read -p "Enter the name of the host like \"localhost\" : " PROJECT_HOST
sed -i "s/WEBSITE_HOST=.*/WEBSITE_HOST=$PROJECT_HOST/g" "$ENV_FILE_DOCKER"
read -p "Enter the port of the api : " PROJECT_PORT
sed -i "s/WEBSITE_PORT=.*/WEBSITE_PORT=$PROJECT_PORT/g" "$ENV_FILE_DOCKER"
make_env_for_svelte
update_nginx_conf
else
echo -e "${BOLD_RED}No environment file found. We will regenerate the entire env files.${RESET}"
fi
}
function change_api_fields_for_42_auth_api
{
if [ -f "$ENV_FILE_DOCKER" ]
then
echo -e "${BOLD_BLUE}Changing the secret for the 42 api${RESET}"
read -p "Enter the client id of the 42 api : " CLIENT_ID
sed -i "s/FORTYTWO_CLIENT_ID=.*/FORTYTWO_CLIENT_ID=$CLIENT_ID/g" "$ENV_FILE_DOCKER"
read -p "Enter the client secret of the 42 api : " CLIENT_SECRET
sed -i "s/FORTYTWO_CLIENT_SECRET=.*/FORTYTWO_CLIENT_SECRET=$CLIENT_SECRET/g" "$ENV_FILE_DOCKER"
echo -e "${BOLD_GREEN}The fields concerning the 42 api have been changed.${RESET}"
else
echo -e "${BOLD_RED}No environment file found. We will regenerate the entire env files.${RESET}"
make_env_for_docker_and_svelte
fi
}
# it's finished ! function choose_options_and_process {
# if [ ! -f "$ENV_FILE_DOCKER" ]; then
make_env_for_docker_and_svelte
elif [ ! -f "$ENV_FILE_SVELTE" && -f "$ENV_FILE_DOCKER" ]; then
make_env_for_svelte
fi
echo -e "${BOLD_RED}An environment already exists.${RESET}"
echo -e "${BOLD_GREEN}What do you want to do ?${RESET}"
echo -e "${BOLD_GREEN}1. Regenerate entire environment${RESET}"
echo -e "${BOLD_GREEN}2. Only change the fields about the HOSTNAME and the PORT of the API${RESET}"
echo -e "${BOLD_GREEN}3. Only change the fields concerning the 42 API (id and secret)${RESET}"
echo -e "${BOLD_GREEN}4. Exit${RESET}"
CHOICE=""
while [ "$CHOICE" != "1" ] && [ "$CHOICE" != "2" ] && [ "$CHOICE" != "3" ] && [ "$CHOICE" != "4" ]; do
read -p "Enter your choice : " CHOICE
done
if [ "$CHOICE" = "1" ]; then
make_env_for_docker_and_svelte
elif [ "$CHOICE" = "2" ]; then
change_host_and_port_api
elif [ "$CHOICE" = "3" ]; then
change_api_fields_for_42_auth_api
else
echo -e "${BOLD_GREEN}The script will exit.${RESET}"
exit 0
fi
}
# Create a new environment for docker
choose_options_and_process
echo "The environment has been created successfully. You can now wait for the docker to build the project." echo "The environment has been created successfully. You can now wait for the docker to build the project."

View File

@@ -1,12 +0,0 @@
NODE_ENV=development
WEBSITE_HOST=transcendance
WEBSITE_PORT=8080
POSTGRES_USER=postgres
#if change postgres pswd, do make destroy
POSTGRES_PASSWORD=m7V8CkL+wl+SU1GagenTWP3oyPJx8JJG+tHRiENxoZQ=
POSTGRES_DB=transcendance_db
POSTGRES_HOST=postgresql
POSTGRES_PORT=5432
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=JKDf9vhE4bb5+JW0CvRXVJ2rcV33Bs1MGcQmCxdL+Qs=

View File

@@ -5,23 +5,28 @@ services:
context: ./requirements/nestjs context: ./requirements/nestjs
target: development target: development
dockerfile: Dockerfile dockerfile: Dockerfile
args: environment:
- NODE_ENV=${NODE_ENV} POSTGRES_USER: "${POSTGRES_USER}"
- WEBSITE_HOST=${WEBSITE_HOST} POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
- WEBSITE_PORT=${WEBSITE_PORT} POSTGRES_DB: "${POSTGRES_DB}"
- POSTGRES_USER=${POSTGRES_USER} POSTGRES_HOST: "${POSTGRES_HOST}"
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD} POSTGRES_PORT: "${POSTGRES_PORT}"
- POSTGRES_DB=${POSTGRES_DB} NODE_ENV: "${NODE_ENV}"
- POSTGRES_HOST=${POSTGRES_HOST} WEBSITE_HOST: "${WEBSITE_HOST}"
- POSTGRES_PORT=${POSTGRES_PORT} WEBSITE_PORT: "${WEBSITE_PORT}"
REDIS_HOST: "${REDIS_HOST}"
REDIS_PORT: "${REDIS_PORT}"
FORTYTWO_CLIENT_ID: "${FORTYTWO_CLIENT_ID}"
FORTYTWO_CLIENT_SECRET : "${FORTYTWO_CLIENT_SECRET}"
FORTYTWO_CALLBACK_URL: "${FORTYTWO_CALLBACK_URL}"
COOKIE_SECRET: "${COOKIE_SECRET}"
TWO_FACTOR_AUTHENTICATION_APP_NAME : "${TWO_FACTOR_AUTHENTICATION_APP_NAME}"
TICKET_FOR_PLAYING_GAME_SECRET : "${TICKET_FOR_PLAYING_GAME_SECRET}"
PORT: "${PORT}"
volumes: volumes:
- ./requirements/nestjs/api_back/src:/usr/app/src - ./requirements/nestjs/api_back/src:/usr/app/src
- ./requirements/nestjs/api_back/test:/usr/app/test/ - ./requirements/nestjs/api_back/test:/usr/app/test/
- nestjs_photos_volume:/usr/app/src/uploads/avatars - nestjs_photos_volume:/usr/app/src/uploads/avatars
env_file:
- .env
environment:
NODE_ENV: "${NODE_ENV}"
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- postgresql - postgresql
@@ -34,6 +39,8 @@ services:
dockerfile: Dockerfile dockerfile: Dockerfile
environment: environment:
NODE_ENV: "${NODE_ENV}" NODE_ENV: "${NODE_ENV}"
WEBSITE_HOST: "${WEBSITE_HOST}"
WEBSITE_PORT: "${WEBSITE_PORT}"
restart: unless-stopped restart: unless-stopped
ports: ports:
- "8042:8042" - "8042:8042"
@@ -51,9 +58,9 @@ services:
- ./requirements/svelte/api_front/public:/usr/app/public/ - ./requirements/svelte/api_front/public:/usr/app/public/
ports: ports:
- "35729:35729" - "35729:35729"
env_file:
- .env
environment: environment:
WEBSITE_HOST: "${WEBSITE_HOST}"
WEBSITE_PORT: "${WEBSITE_PORT}"
NODE_ENV: "${NODE_ENV}" NODE_ENV: "${NODE_ENV}"
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:

View File

@@ -48,7 +48,10 @@ export class GameSession {
timeout += c.newRoundDelay*0.5; timeout += c.newRoundDelay*0.5;
}); });
} }
resume(s: GameSession) { resume(s?: GameSession)
{
if (!s) { s = this; }
s.playersMap.forEach( (client) => { s.playersMap.forEach( (client) => {
client.socket.on("message", clientInputListener); client.socket.on("message", clientInputListener);
}); });
@@ -59,7 +62,10 @@ export class GameSession {
s.playersUpdateInterval = setInterval(s._playersUpdate, c.playersUpdateIntervalMS, s); s.playersUpdateInterval = setInterval(s._playersUpdate, c.playersUpdateIntervalMS, s);
s.spectatorsUpdateInterval = setInterval(s._spectatorsUpdate, c.spectatorsUpdateIntervalMS, s); s.spectatorsUpdateInterval = setInterval(s._spectatorsUpdate, c.spectatorsUpdateIntervalMS, s);
} }
pause(s: GameSession) { pause(s?: GameSession)
{
if (!s) { s = this; }
s.playersMap.forEach( (client) => { s.playersMap.forEach( (client) => {
client.socket.off("message", clientInputListener); client.socket.off("message", clientInputListener);
}); });
@@ -68,6 +74,19 @@ export class GameSession {
clearInterval(s.playersUpdateInterval); clearInterval(s.playersUpdateInterval);
clearInterval(s.spectatorsUpdateInterval); clearInterval(s.spectatorsUpdateInterval);
} }
destroy(s?: GameSession)
{
if (!s) { s = this; }
s.pause();
s.spectatorsMap.forEach((client) => {
clientTerminate(client);
});
s.playersMap.forEach((client) => {
clientTerminate(client);
});
}
instantInputDebug(client: ClientPlayer) { instantInputDebug(client: ClientPlayer) {
this._handleInput(c.fixedDeltaTime, client); this._handleInput(c.fixedDeltaTime, client);
} }
@@ -135,11 +154,12 @@ export class GameSession {
else if (ball.pos.x < 0 - ball.width) { else if (ball.pos.x < 0 - ball.width) {
++gc.scoreRight; ++gc.scoreRight;
} }
const scoreUpdate = new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight);
this.playersMap.forEach( (client) => { this.playersMap.forEach( (client) => {
client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight))); client.socket.send(JSON.stringify(scoreUpdate));
}); });
this.spectatorsMap.forEach( (client) => { this.spectatorsMap.forEach( (client) => {
client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight))); client.socket.send(JSON.stringify(scoreUpdate));
}); });
} }
private _playersUpdate(s: GameSession) { private _playersUpdate(s: GameSession) {
@@ -148,9 +168,9 @@ export class GameSession {
s.lastStateSnapshot.lastInputId = client.lastInputId; s.lastStateSnapshot.lastInputId = client.lastInputId;
client.socket.send(JSON.stringify(s.lastStateSnapshot)); client.socket.send(JSON.stringify(s.lastStateSnapshot));
}); });
s.lastStateSnapshot.lastInputId = 0;
} }
private _spectatorsUpdate(s: GameSession) { private _spectatorsUpdate(s: GameSession) {
s.lastStateSnapshot.lastInputId = 0;
s.spectatorsMap.forEach( (client) => { s.spectatorsMap.forEach( (client) => {
client.socket.send(JSON.stringify(s.lastStateSnapshot)); client.socket.send(JSON.stringify(s.lastStateSnapshot));
}); });
@@ -200,12 +220,25 @@ export class GameSession {
ball.speed = ball.baseSpeed; ball.speed = ball.baseSpeed;
ball.ballInPlay = true; ball.ballInPlay = true;
} }
private _checkDisconnexions() { private _checkDisconnexions()
{
if (this.playersMap.size !== 2) if (this.playersMap.size !== 2)
{ {
this.matchEnded = true; this.matchEnded = true;
if (this.playersMap.size != 0) if (this.playersMap.size != 0) {
this._forfeit();
}
else {
// WIP: envoyer un truc à Nest ? Genre "match draw"
this.destroy();
}
return true;
}
return false;
}
private _forfeit()
{ {
this.matchEnded = true;
console.log("Forfeit Ending"); console.log("Forfeit Ending");
const gc = this.components; const gc = this.components;
const luckyWinner: ClientPlayer = this.playersMap.values().next().value; const luckyWinner: ClientPlayer = this.playersMap.values().next().value;
@@ -216,15 +249,11 @@ export class GameSession {
this._matchEnd(en.PlayerSide.right, true); this._matchEnd(en.PlayerSide.right, true);
} }
} }
return true;
}
return false;
}
private async _matchEnd(winner: en.PlayerSide, forfeit_flag: boolean = false) private async _matchEnd(winner: en.PlayerSide, forfeit_flag: boolean = false)
{ {
this.matchEnded = true; this.matchEnded = true;
let eventEnd: ev.EventMatchEnd; const eventEnd = new ev.EventMatchEnd(winner, forfeit_flag);
eventEnd = new ev.EventMatchEnd(winner, forfeit_flag);
this.playersMap.forEach( (client) => { this.playersMap.forEach( (client) => {
client.socket.send(JSON.stringify(eventEnd)); client.socket.send(JSON.stringify(eventEnd));
}); });
@@ -232,7 +261,21 @@ export class GameSession {
client.socket.send(JSON.stringify(eventEnd)); client.socket.send(JSON.stringify(eventEnd));
}); });
// TODO: mettre à jour la route pour gerer les forfaits (actuellement le plus haut score gagne par defaut)
const gc = this.components; const gc = this.components;
console.log("================================= MATCH ENDED");
if (forfeit_flag) {
if (winner === en.PlayerSide.left)
{
gc.scoreLeft = 3
gc.scoreRight = 0
}
else
{
gc.scoreLeft = 0
gc.scoreRight = 3
}
}
await fetch(c.addressBackEnd + "/game/gameserver/updategame", await fetch(c.addressBackEnd + "/game/gameserver/updategame",
{ {
method: "POST", method: "POST",
@@ -246,15 +289,7 @@ export class GameSession {
}) })
}); });
const gameSession = this; setTimeout(this.destroy, 15000, this);
setTimeout(function kickRemainingClients() {
gameSession.spectatorsMap.forEach((client) => {
clientTerminate(client);
});
gameSession.playersMap.forEach((client) => {
clientTerminate(client);
});
}, 15000);
// logs // logs
if (winner === en.PlayerSide.left) { if (winner === en.PlayerSide.left) {

View File

@@ -14,7 +14,6 @@ import * as c from "./constants.js"
import { Client, ClientPlayer, ClientSpectator } from "./class/Client.js" import { Client, ClientPlayer, ClientSpectator } from "./class/Client.js"
import { GameSession } from "./class/GameSession.js" import { GameSession } from "./class/GameSession.js"
import { shortId } from "./utils.js"; import { shortId } from "./utils.js";
import { gameSessionIdPLACEHOLDER } from "./constants.js";
const wsPort = 8042; const wsPort = 8042;
export const wsServer = new WebSocketServer<WebSocket>({host: "0.0.0.0", port: wsPort, path: "/pong"}); export const wsServer = new WebSocketServer<WebSocket>({host: "0.0.0.0", port: wsPort, path: "/pong"});
@@ -23,12 +22,12 @@ const matchmakingMap: Map<string, ClientPlayer> = new Map; // socket.id/ClientPl
const privateMatchmakingMap: Map<string, ClientPlayer> = new Map; // socket.id/ClientPlayer (duplicates with clientsMap) const privateMatchmakingMap: Map<string, ClientPlayer> = new Map; // socket.id/ClientPlayer (duplicates with clientsMap)
const gameSessionsMap: Map<string, GameSession> = new Map; // GameSession.id(url)/GameSession const gameSessionsMap: Map<string, GameSession> = new Map; // GameSession.id(url)/GameSession
wsServer.on("connection", connectionListener); wsServer.on("connection", serverConnectionListener);
wsServer.on("error", errorListener); wsServer.on("error", serverErrorListener);
wsServer.on("close", closeListener); wsServer.on("close", serverCloseListener);
function connectionListener(socket: WebSocket, request: IncomingMessage) function serverConnectionListener(socket: WebSocket, request: IncomingMessage)
{ {
const id = uuidv4(); const id = uuidv4();
const client = new Client(socket, id); const client = new Client(socket, id);
@@ -40,7 +39,19 @@ function connectionListener(socket: WebSocket, request: IncomingMessage)
console.log(`client ${shortId(client.id)} is alive`); console.log(`client ${shortId(client.id)} is alive`);
}); });
socket.on("message", function log(data: string) { socket.on("close", function removeClient() {
clientTerminate(client);
});
socket.on("error", function errorLog(this: WebSocket, err: Error) {
console.log(`error socket ${shortId(this.id)}:`);
console.log(`${err.name}: ${err.message}`);
if (err.stack) {
console.log(`err.stack: ${err.stack}`);
}
});
socket.on("message", function messageLog(data: string) {
try { try {
const event: ev.ClientEvent = JSON.parse(data); const event: ev.ClientEvent = JSON.parse(data);
if (event.type === en.EventTypes.clientInput) { if (event.type === en.EventTypes.clientInput) {
@@ -61,13 +72,11 @@ async function clientAnnounceListener(this: WebSocket, data: string)
const msg : ev.ClientAnnounce = JSON.parse(data); const msg : ev.ClientAnnounce = JSON.parse(data);
if (msg.type === en.EventTypes.clientAnnounce) if (msg.type === en.EventTypes.clientAnnounce)
{ {
// TODO: reconnection with msg.clientId ? // BONUS: reconnection with msg.clientId ?
// "/pong" to play, "/pong?ID_OF_A_GAMESESSION" to spectate (or something like that)
if (msg.role === en.ClientRole.player) if (msg.role === en.ClientRole.player)
{ {
const announce: ev.ClientAnnouncePlayer = <ev.ClientAnnouncePlayer>msg; const announce: ev.ClientAnnouncePlayer = <ev.ClientAnnouncePlayer>msg;
// WIP nest, fetch token validation
const body = { const body = {
playerOneUsername: announce.username, playerOneUsername: announce.username,
playerTwoUsername: "", playerTwoUsername: "",
@@ -88,7 +97,7 @@ async function clientAnnounceListener(this: WebSocket, data: string)
}); });
if (!response.ok) if (!response.ok)
{ {
this.send(JSON.stringify( new ev.EventError((await response.json()).message))); this.send(JSON.stringify( new ev.EventError((await response.json()).message) ));
clientTerminate(clientsMap.get(this.id)); clientTerminate(clientsMap.get(this.id));
return; return;
} }
@@ -96,10 +105,13 @@ async function clientAnnounceListener(this: WebSocket, data: string)
const player = clientsMap.get(this.id) as ClientPlayer; const player = clientsMap.get(this.id) as ClientPlayer;
player.matchOptions = announce.matchOptions; player.matchOptions = announce.matchOptions;
player.token = announce.token; player.token = announce.token;
announce.isInvitedPerson ? player.username = announce.playerTwoUsername : player.username = announce.username; player.username = announce.username;
this.send(JSON.stringify( new ev.EventAssignId(this.id) )); // unused this.send(JSON.stringify( new ev.EventAssignId(this.id) )); // unused
this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchmakingInProgress) )); this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchmakingInProgress) ));
if (announce.privateMatch) { if (announce.privateMatch) {
if (announce.isInvitedPerson) {
player.username = announce.playerTwoUsername;
}
privateMatchmaking(player); privateMatchmaking(player);
} }
else { else {
@@ -111,13 +123,14 @@ async function clientAnnounceListener(this: WebSocket, data: string)
const announce: ev.ClientAnnounceSpectator = <ev.ClientAnnounceSpectator>msg; const announce: ev.ClientAnnounceSpectator = <ev.ClientAnnounceSpectator>msg;
const gameSession = gameSessionsMap.get(announce.gameSessionId); const gameSession = gameSessionsMap.get(announce.gameSessionId);
if (!gameSession) { if (!gameSession) {
this.send(JSON.stringify( new ev.EventError("invalid gameSessionId"))); this.send(JSON.stringify( new ev.EventError("invalid gameSessionId") ));
clientTerminate(clientsMap.get(this.id)); clientTerminate(clientsMap.get(this.id));
return; return;
} }
const spectator = clientsMap.get(this.id) as ClientSpectator; const spectator = clientsMap.get(this.id) as ClientSpectator;
spectator.gameSession = gameSession; spectator.gameSession = gameSession;
gameSession.spectatorsMap.set(spectator.id, spectator); gameSession.spectatorsMap.set(spectator.id, spectator);
spectator.socket.once("message", spectatorReadyConfirmationListener);
this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchStart) )); this.send(JSON.stringify( new ev.ServerEvent(en.EventTypes.matchStart) ));
} }
} }
@@ -213,7 +226,7 @@ function privateMatchmaking(player: ClientPlayer)
function createGameSession(playersArr: ClientPlayer[], matchOptions: en.MatchOptions) function createGameSession(playersArr: ClientPlayer[], matchOptions: en.MatchOptions)
{ {
// const id = gameSessionIdPLACEHOLDER; // Force ID, TESTING SPECTATOR // const id = c.gameSessionIdPLACEHOLDER; // Force ID, TESTING SPECTATOR
const id = uuidv4(); const id = uuidv4();
const gameSession = new GameSession(id, matchOptions); const gameSession = new GameSession(id, matchOptions);
gameSessionsMap.set(id, gameSession); gameSessionsMap.set(id, gameSession);
@@ -263,7 +276,6 @@ async function playerReadyConfirmationListener(this: WebSocket, data: string)
gameSession.unreadyPlayersMap.delete(this.id); gameSession.unreadyPlayersMap.delete(this.id);
if (gameSession.unreadyPlayersMap.size === 0) if (gameSession.unreadyPlayersMap.size === 0)
{ {
// WIP nest , send gameSession.id
const gameSessionPlayersIterator = gameSession.playersMap.values(); const gameSessionPlayersIterator = gameSession.playersMap.values();
const body = { const body = {
gameServerIdOfTheMatch : gameSession.id, gameServerIdOfTheMatch : gameSession.id,
@@ -330,6 +342,28 @@ export function clientInputListener(this: WebSocket, data: string)
} }
} }
function spectatorReadyConfirmationListener(this: WebSocket, data: string)
{
try {
const msg : ev.ClientEvent = JSON.parse(data);
if (msg.type === en.EventTypes.clientSpectatorReady)
{
const client = clientsMap.get(this.id);
const gameSession = client.gameSession;
const scoreUpdate = new ev.EventScoreUpdate(gameSession.components.scoreLeft, gameSession.components.scoreRight);
this.send(JSON.stringify(scoreUpdate));
}
else {
console.log("Invalid spectatorReadyConfirmation");
}
return;
}
catch (e) {
console.log("Invalid JSON (spectatorReadyConfirmationListener)");
}
this.once("message", spectatorReadyConfirmationListener);
}
//////////// ////////////
//////////// ////////////
@@ -363,11 +397,10 @@ export function clientTerminate(client: Client)
if (client.gameSession) if (client.gameSession)
{ {
client.gameSession.playersMap.delete(client.id); client.gameSession.playersMap.delete(client.id);
client.gameSession.spectatorsMap.delete(client.id);
if (client.gameSession.playersMap.size === 0) if (client.gameSession.playersMap.size === 0)
{ {
clearInterval(client.gameSession.playersUpdateInterval); client.gameSession.destroy();
clearInterval(client.gameSession.spectatorsUpdateInterval);
clearInterval(client.gameSession.gameLoopInterval);
gameSessionsMap.delete(client.gameSession.id); gameSessionsMap.delete(client.gameSession.id);
} }
} }
@@ -381,13 +414,13 @@ export function clientTerminate(client: Client)
} }
function closeListener() function serverCloseListener()
{ {
clearInterval(pingInterval); clearInterval(pingInterval);
} }
function errorListener(error: Error) function serverErrorListener(error: Error)
{ {
console.log("Error: " + JSON.stringify(error)); console.log("Error: " + JSON.stringify(error));
} }

View File

@@ -26,5 +26,5 @@ export const movingWallPosMax = Math.floor(w*0.12);
export const movingWallSpeed = Math.floor(w*0.08); export const movingWallSpeed = Math.floor(w*0.08);
export const gameSessionIdPLACEHOLDER = "42"; // TESTING SPECTATOR PLACEHOLDER export const gameSessionIdPLACEHOLDER = "match-id-test-42"; // TESTING SPECTATOR PLACEHOLDER
// for testing, force gameSession.id in wsServer.ts->matchmaking() // for testing, force gameSession.id in wsServer.ts->createGameSession()

View File

@@ -19,6 +19,7 @@ export enum EventTypes {
// Client // Client
clientAnnounce, clientAnnounce,
clientPlayerReady, clientPlayerReady,
clientSpectatorReady,
clientInput, clientInput,
} }

View File

@@ -2,28 +2,9 @@ FROM node:alpine AS development
WORKDIR /usr/app WORKDIR /usr/app
ARG NODE_ENV
ARG WEBSITE_HOST
ARG WEBSITE_PORT
ARG POSTGRES_USER
ARG POSTGRES_PASSWORD
ARG POSTGRES_DB
ARG POSTGRES_HOST
ARG POSTGRES_PORT
COPY ./api_back ./ COPY ./api_back ./
COPY ./api_back/src/uploads/avatars/default.png ./uploads/avatars/default.png COPY ./api_back/src/uploads/avatars/default.png ./uploads/avatars/default.png
COPY ./api_back/.env ./.env
RUN npm install
RUN sed -i "s/\$NODE_ENV/${NODE_ENV}/g" ./.env && \ RUN npm i
sed -i "s/\$WEBSITE_HOST/${WEBSITE_HOST}/g" ./.env && \
sed -i "s/\$WEBSITE_PORT/${WEBSITE_PORT}/g" ./.env && \
sed -i "s/\$POSTGRES_USER/${POSTGRES_USER}/g" ./.env && \
sed -i "s/\$POSTGRES_PASSWORD/${POSTGRES_PASSWORD}/g" ./.env && \
sed -i "s/\$POSTGRES_DB/${POSTGRES_DB}/g" ./.env && \
sed -i "s/\$POSTGRES_HOST/${POSTGRES_HOST}/g" ./.env && \
sed -i "s/\$POSTGRES_PORT/${POSTGRES_PORT}/g" ./.env
CMD [ "npm", "run", "start:dev" ] CMD [ "npm", "run", "start:dev" ]

View File

@@ -1,15 +0,0 @@
NODE_ENV=$NODE_ENV
WEBSITE_HOST=$WEBSITE_HOST
WEBSITE_PORT=$WEBSITE_PORT
POSTGRES_USER=$POSTGRES_USER
POSTGRES_PASSWORD=$POSTGRES_PASSWORD
POSTGRES_DB=$POSTGRES_DB
POSTGRES_HOST=$POSTGRES_HOST
POSTGRES_PORT=$POSTGRES_PORT
FORTYTWO_CLIENT_ID=u-s4t2ud-49dc7b539bcfe1acb48b928b2b281671c99fc5bfab1faca57a536ab7e0075500
FORTYTWO_CLIENT_SECRET=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
FORTYTWO_CALLBACK_URL=http://$WEBSITE_HOST:$WEBSITE_PORT/api/v2/auth/redirect
COOKIE_SECRET=wABcR5SytbN4kiPa_4Y8IhhdLDb4Yn0EvVvOPZRQf4Q=
PORT=3000
TWO_FACTOR_AUTHENTICATION_APP_NAME=Transcendance
TICKET_FOR_PLAYING_GAME_SECRET=hvt8PQo3o+BHimS0RO5viln65yF9zMIuZFEmhxQGdik=

View File

@@ -19,7 +19,6 @@
"@nestjs/typeorm": "^9.0.1", "@nestjs/typeorm": "^9.0.1",
"@nestjs/websockets": "^9.2.1", "@nestjs/websockets": "^9.2.1",
"@types/express-session": "^1.17.5", "@types/express-session": "^1.17.5",
"@types/redis": "^4.0.11",
"@types/validator": "^13.7.9", "@types/validator": "^13.7.9",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.13.2", "class-validator": "^0.13.2",
@@ -48,7 +47,7 @@
"@types/express": "^4.17.13", "@types/express": "^4.17.13",
"@types/jest": "28.1.8", "@types/jest": "28.1.8",
"@types/multer": "^1.4.7", "@types/multer": "^1.4.7",
"@types/node": "^16.0.0", "@types/node": "^16.18.11",
"@types/passport-local": "^1.0.34", "@types/passport-local": "^1.0.34",
"@types/supertest": "^2.0.11", "@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/eslint-plugin": "^5.0.0",
@@ -1694,65 +1693,6 @@
"@nestjs/core": "^9.0.0" "@nestjs/core": "^9.0.0"
} }
}, },
"node_modules/@nestjs/platform-express/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/@nestjs/platform-express/node_modules/express": {
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
"integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
"body-parser": "1.20.0",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
"cookie": "0.5.0",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "1.2.0",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"merge-descriptors": "1.0.1",
"methods": "~1.1.2",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.7",
"proxy-addr": "~2.0.7",
"qs": "6.10.3",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "0.18.0",
"serve-static": "1.15.0",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"type-is": "~1.6.18",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
},
"engines": {
"node": ">= 0.10.0"
}
},
"node_modules/@nestjs/platform-express/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/@nestjs/platform-express/node_modules/path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
},
"node_modules/@nestjs/platform-socket.io": { "node_modules/@nestjs/platform-socket.io": {
"version": "9.2.1", "version": "9.2.1",
"resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-9.2.1.tgz", "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-9.2.1.tgz",
@@ -1787,11 +1727,6 @@
"node": ">=10.0.0" "node": ">=10.0.0"
} }
}, },
"node_modules/@nestjs/platform-socket.io/node_modules/tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
},
"node_modules/@nestjs/schematics": { "node_modules/@nestjs/schematics": {
"version": "9.0.3", "version": "9.0.3",
"resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.0.3.tgz", "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.0.3.tgz",
@@ -1960,11 +1895,6 @@
} }
} }
}, },
"node_modules/@nestjs/websockets/node_modules/tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
},
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -2381,9 +2311,9 @@
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "16.18.10", "version": "16.18.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.10.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz",
"integrity": "sha512-XU1+v7h81p7145ddPfjv7jtWvkSilpcnON3mQ+bDi9Yuf7OI56efOglXRyXWgQ57xH3fEQgh7WOJMncRHVew5w==" "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA=="
}, },
"node_modules/@types/parse-json": { "node_modules/@types/parse-json": {
"version": "4.0.0", "version": "4.0.0",
@@ -2437,15 +2367,6 @@
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
}, },
"node_modules/@types/redis": {
"version": "4.0.11",
"resolved": "https://registry.npmjs.org/@types/redis/-/redis-4.0.11.tgz",
"integrity": "sha512-bI+gth8La8Wg/QCR1+V1fhrL9+LZUSWfcqpOj2Kc80ZQ4ffbdL173vQd5wovmoV9i071FU9oP2g6etLuEwb6Rg==",
"deprecated": "This is a stub types definition. redis provides its own type definitions, so you do not need this installed.",
"dependencies": {
"redis": "*"
}
},
"node_modules/@types/semver": { "node_modules/@types/semver": {
"version": "7.3.13", "version": "7.3.13",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
@@ -3372,11 +3293,6 @@
"ieee754": "^1.1.13" "ieee754": "^1.1.13"
} }
}, },
"node_modules/buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
},
"node_modules/buffer-from": { "node_modules/buffer-from": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@@ -4070,14 +3986,6 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"dependencies": {
"safe-buffer": "^5.0.1"
}
},
"node_modules/ee-first": { "node_modules/ee-first": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -6533,25 +6441,6 @@
"graceful-fs": "^4.1.6" "graceful-fs": "^4.1.6"
} }
}, },
"node_modules/jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"dependencies": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"node_modules/jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"dependencies": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"node_modules/kleur": { "node_modules/kleur": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
@@ -6630,11 +6519,6 @@
"optional": true, "optional": true,
"peer": true "peer": true
}, },
"node_modules/lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="
},
"node_modules/lodash.isarguments": { "node_modules/lodash.isarguments": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
@@ -6642,31 +6526,6 @@
"optional": true, "optional": true,
"peer": true "peer": true
}, },
"node_modules/lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
},
"node_modules/lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="
},
"node_modules/lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="
},
"node_modules/lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
},
"node_modules/lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
},
"node_modules/lodash.memoize": { "node_modules/lodash.memoize": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -6679,11 +6538,6 @@
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true "dev": true
}, },
"node_modules/lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
},
"node_modules/log-symbols": { "node_modules/log-symbols": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
@@ -6720,6 +6574,7 @@
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"dependencies": { "dependencies": {
"yallist": "^4.0.0" "yallist": "^4.0.0"
}, },
@@ -8300,6 +8155,7 @@
"version": "7.3.8", "version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"dev": true,
"dependencies": { "dependencies": {
"lru-cache": "^6.0.0" "lru-cache": "^6.0.0"
}, },
@@ -11132,11 +10988,6 @@
"socket.io-adapter": "~2.4.0", "socket.io-adapter": "~2.4.0",
"socket.io-parser": "~4.2.0" "socket.io-parser": "~4.2.0"
} }
},
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
} }
} }
}, },
@@ -11250,13 +11101,6 @@
"iterare": "1.2.1", "iterare": "1.2.1",
"object-hash": "3.0.0", "object-hash": "3.0.0",
"tslib": "2.4.1" "tslib": "2.4.1"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA=="
}
} }
}, },
"@nodelib/fs.scandir": { "@nodelib/fs.scandir": {
@@ -11642,9 +11486,9 @@
} }
}, },
"@types/node": { "@types/node": {
"version": "16.18.10", "version": "16.18.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.10.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz",
"integrity": "sha512-XU1+v7h81p7145ddPfjv7jtWvkSilpcnON3mQ+bDi9Yuf7OI56efOglXRyXWgQ57xH3fEQgh7WOJMncRHVew5w==" "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA=="
}, },
"@types/parse-json": { "@types/parse-json": {
"version": "4.0.0", "version": "4.0.0",
@@ -11698,14 +11542,6 @@
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
}, },
"@types/redis": {
"version": "4.0.11",
"resolved": "https://registry.npmjs.org/@types/redis/-/redis-4.0.11.tgz",
"integrity": "sha512-bI+gth8La8Wg/QCR1+V1fhrL9+LZUSWfcqpOj2Kc80ZQ4ffbdL173vQd5wovmoV9i071FU9oP2g6etLuEwb6Rg==",
"requires": {
"redis": "*"
}
},
"@types/semver": { "@types/semver": {
"version": "7.3.13", "version": "7.3.13",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
@@ -12397,11 +12233,6 @@
"ieee754": "^1.1.13" "ieee754": "^1.1.13"
} }
}, },
"buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
},
"buffer-from": { "buffer-from": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@@ -12906,14 +12737,6 @@
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-8.0.3.tgz", "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-8.0.3.tgz",
"integrity": "sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==" "integrity": "sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg=="
}, },
"ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"ee-first": { "ee-first": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -14766,25 +14589,6 @@
"universalify": "^2.0.0" "universalify": "^2.0.0"
} }
}, },
"jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"requires": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"requires": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"kleur": { "kleur": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
@@ -14845,11 +14649,6 @@
"optional": true, "optional": true,
"peer": true "peer": true
}, },
"lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="
},
"lodash.isarguments": { "lodash.isarguments": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
@@ -14857,31 +14656,6 @@
"optional": true, "optional": true,
"peer": true "peer": true
}, },
"lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
},
"lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="
},
"lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="
},
"lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
},
"lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
},
"lodash.memoize": { "lodash.memoize": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -14894,11 +14668,6 @@
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true "dev": true
}, },
"lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
},
"log-symbols": { "log-symbols": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
@@ -14925,6 +14694,7 @@
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"requires": { "requires": {
"yallist": "^4.0.0" "yallist": "^4.0.0"
} }
@@ -16078,6 +15848,7 @@
"version": "7.3.8", "version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"dev": true,
"requires": { "requires": {
"lru-cache": "^6.0.0" "lru-cache": "^6.0.0"
} }

View File

@@ -59,7 +59,7 @@
"@types/express": "^4.17.13", "@types/express": "^4.17.13",
"@types/jest": "28.1.8", "@types/jest": "28.1.8",
"@types/multer": "^1.4.7", "@types/multer": "^1.4.7",
"@types/node": "^16.0.0", "@types/node": "^16.18.11",
"@types/passport-local": "^1.0.34", "@types/passport-local": "^1.0.34",
"@types/supertest": "^2.0.11", "@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/eslint-plugin": "^5.0.0",

View File

@@ -37,10 +37,10 @@ export class AuthenticationController {
const user : User = request.user const user : User = request.user
if (user.isEnabledTwoFactorAuth === false || user.isTwoFactorAuthenticated === true){ if (user.isEnabledTwoFactorAuth === false || user.isTwoFactorAuthenticated === true){
console.log('ON VA VERS PROFILE'); console.log('ON VA VERS PROFILE');
return response.status(200).redirect('http://transcendance:8080/#/profile'); return response.status(200).redirect('http://' + process.env.WEBSITE_HOST + ':' + process.env.WEBSITE_PORT + '/#/profile');
} }
console.log('ON VA VERS 2FA') console.log('ON VA VERS 2FA')
return response.status(200).redirect('http://transcendance:8080/#/2fa'); return response.status(200).redirect('http://' + process.env.WEBSITE_HOST + ':' + process.env.WEBSITE_PORT + '/#/2fa');
} }
/** /**
@@ -83,6 +83,6 @@ export class AuthenticationController {
throw new UnauthorizedException('Wrong Code.'); throw new UnauthorizedException('Wrong Code.');
await this.userService.authenticateUserWith2FA(request.user.id); await this.userService.authenticateUserWith2FA(request.user.id);
console.log('ON REDIRIGE'); console.log('ON REDIRIGE');
return response.status(200).redirect('http://transcendance:8080/#/profile'); return response.status(200).redirect('http://' + process.env.WEBSITE_HOST + ':' + process.env.WEBSITE_PORT + '/#/profile');
} }
} }

View File

@@ -32,9 +32,8 @@ export class ChatGateway
async handleDisconnect(client) { async handleDisconnect(client) {
console.log('---- client disconnected :', client.id); console.log('---- client disconnected :', client.id);
} }
/*
*/ @SubscribeMessage('')
@SubscribeMessage('test_users')
handleMessage(): void { handleMessage(): void {
const paginationQuery = new PaginationQueryDto(); const paginationQuery = new PaginationQueryDto();
const users = this.usersService.findAll(paginationQuery); const users = this.usersService.findAll(paginationQuery);

View File

@@ -1,4 +1,4 @@
import { Module } from '@nestjs/common'; //import { Module } from '@nestjs/common';
//import { TypeOrmModule } from '@nestjs/typeorm'; //import { TypeOrmModule } from '@nestjs/typeorm';
//import { FriendshipService } from './friendship.service'; //import { FriendshipService } from './friendship.service';
//import { FriendshipController } from './friendship.controller'; //import { FriendshipController } from './friendship.controller';
@@ -12,5 +12,5 @@ import { Module } from '@nestjs/common';
// exports: [FriendshipService], // exports: [FriendshipService],
//}) //})
export class FriendshipsModule {} //export class FriendshipsModule {}

View File

@@ -0,0 +1,204 @@
//import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { Injectable } from '@nestjs/common';
//import { InjectRepository } from '@nestjs/typeorm';
//import { User } from 'src/users/entities/user.entity';
//import { Repository } from 'typeorm';
//import { CreateFriendshipDto } from './dto/create-friendship.dto';
//import { Friendship, FriendshipStatus } from './entities/friendship.entity';
/*
@Injectable()
export class FriendshipService {
constructor(
@InjectRepository(Friendship)
private readonly friendshipRepository: Repository<Friendship>,
@InjectRepository(User)
private readonly userRepository: Repository<User>,
) { }
async findOneFriend(friendshipId: string, username: string) {
const friendship = await this.friendshipRepository.find({ where: { id: +friendshipId, senderUsername: username, status: FriendshipStatus.ACCEPTED } });
if (!friendship)
throw new HttpException(`The requested friend not found.`, HttpStatus.NOT_FOUND);
return friendship;
}
async findOneBlocked(friendshipId: string, username: string) {
const friendship = await this.friendshipRepository.find({ where: { id: +friendshipId, senderUsername: username, status: FriendshipStatus.BLOCKED } });
if (!friendship)
throw new HttpException(`The requested blocked not found.`, HttpStatus.NOT_FOUND);
return friendship;
}
async findAllFriends(username: string) {
const friendship = await this.friendshipRepository
.createQueryBuilder('friendship')
.where('friendship.status = :status', { status: FriendshipStatus.ACCEPTED })
.andWhere('friendship.receiverUsername = :addressee', { addressee: username })
.orWhere('friendship.senderUsername = :requester', { requester: username })
.andWhere('friendship.status = :status', { status: FriendshipStatus.ACCEPTED })
.getMany();
for (const friend of friendship)
console.log("FRIENDSHIP : " + friend.status);
return friendship;
}
async findAllBlockedFriends(username: string) {
const friendships : Friendship[] = await this.friendshipRepository
.createQueryBuilder('friendship')
.where('friendship.senderUsername = :requestee', { requestee: username })
.andWhere('friendship.status = :status', { status: FriendshipStatus.BLOCKED })
.getMany();
let partialFriendship : Partial<Friendship>[] = [];
for (const friendship of friendships) {
partialFriendship.push({id: friendship.id, date: friendship.date, senderUsername: friendship.senderUsername, receiverUsername: friendship.receiverUsername, status: friendship.status});
}
return partialFriendship;
}
async findAllPendantRequestsForFriendship(username: string) {
const friendship = await this.friendshipRepository
.createQueryBuilder('friendship')
.where('friendship.senderUsername = :requestee', { requestee: username })
.andWhere('friendship.status = :status', { status: FriendshipStatus.REQUESTED })
.getMany();
let partialFriendship : Partial<Friendship>[] = [];
for (const friend of friendship) {
console.log("FRIENDSHIP : " + friend);
partialFriendship.push({id: friend.id, senderUsername: friend.senderUsername, receiverUsername: friend.receiverUsername, status: friend.status});
}
console.log("Pendant requests : " + partialFriendship);
return partialFriendship;
}
async findAllReceivedRequestsForFriendship(username: string) {
const friendship = await this.friendshipRepository
.createQueryBuilder('friendship')
.where('friendship.receiverUsername = :addressee', { addressee: username })
.andWhere('friendship.status = :status', { status: FriendshipStatus.REQUESTED })
.getMany();
let partialFriendship : Partial<Friendship>[] = [];
for (const friend of friendship) {
partialFriendship.push({id: friend.id, senderUsername: friend.senderUsername, receiverUsername: friend.receiverUsername, status: friend.status});
}
return partialFriendship;
}
async create(createFriendshipDto: CreateFriendshipDto, creator : User) : Promise <Partial<Friendship>> {
console.log("DTO : \n")
console.log({...createFriendshipDto})
const receiver = await this.userRepository.findOneBy({username: createFriendshipDto.receiverUsername});
if (!receiver)
throw new HttpException(`The addressee does not exist.`, HttpStatus.NOT_FOUND);
if (createFriendshipDto.status !== FriendshipStatus.REQUESTED && createFriendshipDto.status !== FriendshipStatus.BLOCKED)
throw new HttpException(`The status is not valid.`, HttpStatus.NOT_FOUND);
const friendship = await this.friendshipRepository.findOneBy({ sender: creator, receiver: receiver });
if (friendship) {
if (friendship.status && friendship.status === FriendshipStatus.ACCEPTED)
throw new HttpException(`The friendship request has already been accepted.`, HttpStatus.OK);
else if (friendship.status && friendship.status === FriendshipStatus.REQUESTED)
throw new HttpException(`The friendship request has already been sent the ${friendship.date}.`, HttpStatus.OK);
else if (friendship.status && friendship.status === FriendshipStatus.BLOCKED)
throw new HttpException(`We can't do that`, HttpStatus.OK);
else if (friendship.status && friendship.status === FriendshipStatus.DECLINED)
throw new HttpException(`The request has been declined.`, HttpStatus.OK);
}
const newFriendship = new Friendship();
newFriendship.sender = creator;
newFriendship.senderUsername = creator.username;
newFriendship.receiver = receiver;
newFriendship.receiverUsername = receiver.username;
newFriendship.status = createFriendshipDto.status;
const savedFriendship = this.friendshipRepository.save(newFriendship);
const partialFriendship : Partial<Friendship> = {
id : (await savedFriendship).id,
date : (await savedFriendship).date,
receiverUsername: (await savedFriendship).receiverUsername,
status : (await savedFriendship).status
}
console.log({...partialFriendship})
return partialFriendship;
}
async acceptFriendship(relationshipId: string, user: User) {
const relation = await this.friendshipRepository.findOneBy({ id: +relationshipId });
if (!relation)
throw new HttpException(`The requested relationship not found.`, HttpStatus.NOT_FOUND);
if (relation.sender.id === user.id) {
throw new HttpException(`You can't accept your own request.`, HttpStatus.NOT_FOUND);
}
relation.status = FriendshipStatus.ACCEPTED;
const savedFriendship = this.friendshipRepository.save(relation);
const partialFriendship : Partial<Friendship> = {
id : (await savedFriendship).id,
date : (await savedFriendship).date,
receiverUsername: (await savedFriendship).receiverUsername,
status : (await savedFriendship).status
}
return partialFriendship;
}
async declineFriendship(relationshipId: string, user: User) {
const relation = await this.friendshipRepository.findOneBy({ id: +relationshipId });
if (!relation)
throw new HttpException(`The requested relationship not found.`, HttpStatus.NOT_FOUND);
if (relation.sender.id === user.id) {
throw new HttpException(`You can't accept your own request.`, HttpStatus.NOT_FOUND);
}
relation.status = FriendshipStatus.DECLINED;
const savedFriendship = this.friendshipRepository.save(relation);
const partialFriendship : Partial<Friendship> = {
id : (await savedFriendship).id,
date : (await savedFriendship).date,
receiverUsername: (await savedFriendship).receiverUsername,
status : (await savedFriendship).status
}
return partialFriendship
}
async blockFriendship(relationshipId: string, user: User) {
const relation = await this.friendshipRepository.findOneBy({ id: +relationshipId });
if (!relation)
throw new HttpException(`The requested relationship not found.`, HttpStatus.NOT_FOUND);
if (relation.sender.id === user.id) {
throw new HttpException(`You can't accept your own request.`, HttpStatus.NOT_FOUND);
}
relation.status = FriendshipStatus.BLOCKED;
const savedFriendship = this.friendshipRepository.save(relation);
const partialFriendship : Partial<Friendship> = {
id : (await savedFriendship).id,
date : (await savedFriendship).date,
receiverUsername: (await savedFriendship).receiverUsername,
status : (await savedFriendship).status
}
return partialFriendship
}
async removeFriendship(relationshipId: string, user : User) {
const friendship = await this.friendshipRepository.findOneBy({ id: +relationshipId });
if (!friendship)
throw new HttpException(`Your friend could not be deleted.`, HttpStatus.NOT_FOUND);
if (friendship.sender.id !== user.id || friendship.receiver.id !== user.id) {
throw new HttpException(`You can't do that.`, HttpStatus.FORBIDDEN);
}
return this.friendshipRepository.remove(friendship);
}
async findIfUserIsBlockedOrHasBlocked(userConnectedId: string, userToFindId: string) {
console.log("finding if user is blocked")
const friendship = await this.friendshipRepository
.createQueryBuilder('friendship')
.where('friendship.senderUsername = :requestee', { requestee: userConnectedId })
.orWhere('friendship.senderUsername = :requesteeBis', { requesteeBis: userToFindId })
.andWhere('friendship.status = :status', { status: FriendshipStatus.BLOCKED })
.getOne();
if (friendship) {
console.log('we are blocked in friendship.service')
return true;
}
return false;
}
}
*/

View File

@@ -24,5 +24,13 @@ export const storageForAvatar = {
const extension : string = MIME_TYPES[file.mimetype]; const extension : string = MIME_TYPES[file.mimetype];
cb(null, `${filename}${extension}`); cb(null, `${filename}${extension}`);
} }
}) }),
fileFilter: (req, file, cb) => {
if (file.mimetype === 'image/png' || file.mimetype === 'image/jpg' || file.mimetype === 'image/jpeg') {
cb(null, true);
}
else {
cb(null, false);
}
}
} }

View File

@@ -17,6 +17,9 @@ export class Game {
@Column({default : 0, nullable : true}) @Column({default : 0, nullable : true})
playerTwoUsernameResult : number playerTwoUsernameResult : number
@Column({default : 0})
gameOptions: number
@Column({unique : true}) @Column({unique : true})
gameServerIdOfTheMatch: string gameServerIdOfTheMatch: string

View File

@@ -13,6 +13,14 @@ export class GameController {
constructor (private readonly gameService : GameService) { } constructor (private readonly gameService : GameService) { }
@Get('match/all')
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
async getMatchesForSpectator()
{
return this.gameService.getMatchesForSpectator();
}
@Get('ranking') @Get('ranking')
@UseGuards(AuthenticateGuard) @UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard) @UseGuards(TwoFactorGuard)

View File

@@ -28,6 +28,21 @@ export class GameService {
private readonly friendShipService : FriendshipService private readonly friendShipService : FriendshipService
) { } ) { }
async getMatchesForSpectator() {
const games = await this.gameRepository.createQueryBuilder("game")
.where('game.isMatchIsFinished = :isMatchIsFinished', {isMatchIsFinished : false})
.getMany();
const gamesToReturn : Partial<Game>[] = []
for (const game of games)
{
gamesToReturn.push({gameServerIdOfTheMatch : game.gameServerIdOfTheMatch,
gameOptions : game.gameOptions, playerOneUsername : game.playerOneUsername,
playerTwoUsername : game.playerTwoUsername})
console.log("Is match is finished : " + game.isMatchIsFinished)
}
return gamesToReturn;
}
async getRankingForAllUsers(currentUser : User) { async getRankingForAllUsers(currentUser : User) {
const users = await this.userRepository.createQueryBuilder("user") const users = await this.userRepository.createQueryBuilder("user")
.leftJoinAndSelect("user.stats", "stats") .leftJoinAndSelect("user.stats", "stats")
@@ -255,6 +270,8 @@ export class GameService {
game.playerOneUsernameResult = updateGameDto.playerOneUsernameResult game.playerOneUsernameResult = updateGameDto.playerOneUsernameResult
game.playerTwoUsernameResult = updateGameDto.playerTwoUsernameResult game.playerTwoUsernameResult = updateGameDto.playerTwoUsernameResult
this.gameRepository.save(game); this.gameRepository.save(game);
console.log("On a sauvegardé la partie. Game :")
console.log(game)
const playerOne = await this.userRepository.findOneBy({username : game.playerOneUsername}) const playerOne = await this.userRepository.findOneBy({username : game.playerOneUsername})
const playerTwo = await this.userRepository.findOneBy({username : game.playerTwoUsername}) const playerTwo = await this.userRepository.findOneBy({username : game.playerTwoUsername})
if (!playerOne || !playerTwo) if (!playerOne || !playerTwo)

View File

@@ -8,7 +8,7 @@ import * as connectRedis from 'connect-redis';
async function bootstrap() { async function bootstrap() {
const app = await NestFactory.create(AppModule, { cors: true }); const app = await NestFactory.create(AppModule, { cors: true });
const port = process.env.PORT || 3001; const port = process.env.PORT || 3000;
const client = redis.createClient( const client = redis.createClient(
{ {
socket: { host: process.env.REDIS_HOST, port: parseInt(process.env.REDIS_PORT) }, socket: { host: process.env.REDIS_HOST, port: parseInt(process.env.REDIS_PORT) },
@@ -50,6 +50,6 @@ async function bootstrap() {
); );
app.use(passport.initialize()); app.use(passport.initialize());
app.use(passport.session()); app.use(passport.session());
await app.listen(port, () => { console.log(`Listening on port ${port}`); }); await app.listen(port, () => { console.log(`Listening on port ${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}}`); });
} }
bootstrap(); bootstrap();

View File

@@ -1,5 +1,5 @@
import { import {
Body, Controller, Delete, Get, NotFoundException, Param, Patch, Post, Query, Redirect, Req, Res, UploadedFile, UseGuards, UseInterceptors Body, Controller, Delete, Get, NotFoundException,HttpStatus, Param, Patch, Post, Query, Redirect, Req, Res, UploadedFile, UseGuards, UseInterceptors
} from '@nestjs/common'; } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express'; import { FileInterceptor } from '@nestjs/platform-express';
import { Response } from 'express'; import { Response } from 'express';
@@ -31,19 +31,6 @@ export class UsersController {
///////////////////////// RUD ////////////////////////// ///////////////////////// RUD //////////////////////////
//////////////////////////////////////////////////////// ////////////////////////////////////////////////////////
/**
* On ne fait de création via une route
* car un utilisateur est crée à la première connexion avec l'Oauth de 42.
*/
// @UseGuards(AuthenticateGuard)
// @UseGuards(TwoFactorGuard)
// @Get()
// findOne(@Req() req) {
// console.log("Backend Getting current user");
// return this.usersService.findOne(req.user.id);
// }
@UseGuards(AuthenticateGuard) @UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard) @UseGuards(TwoFactorGuard)
@Get() @Get()
@@ -100,9 +87,14 @@ export class UsersController {
@UseGuards(TwoFactorGuard) @UseGuards(TwoFactorGuard)
@Post('avatar') @Post('avatar')
@UseInterceptors(FileInterceptor('file', storageForAvatar)) @UseInterceptors(FileInterceptor('file', storageForAvatar))
uploadAvatar(@UploadedFile() file, @Req() request){ uploadAvatar(@UploadedFile() file, @Req() request, @Res() res){
const user : User = request.user; const user : User = request.user;
if (file)
{
this.usersService.updateAvatar(user.id, file.filename); this.usersService.updateAvatar(user.id, file.filename);
return res.status(HttpStatus.OK).json({message : "Avatar updated"});
}
return res.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE).json({message : "Unsupported media type. Please use a valid image file."});
} }
@UseGuards(AuthenticateGuard) @UseGuards(AuthenticateGuard)

View File

@@ -1,7 +1,6 @@
server { server {
listen 8080;
listen 8080 default_server; listen [::]:8080;
listen [::]:8080 default_server;
server_name transcendance; server_name transcendance;
location /api/v2 { location /api/v2 {
@@ -17,7 +16,7 @@ server {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"; proxy_set_header Connection "Upgrade";
proxy_pass http://backend_dev:5000/chat; proxy_pass http://backend_dev:5000/chat;
} }
@@ -43,7 +42,6 @@ server {
} }
server { server {
listen 35729 default_server; listen 35729 default_server;
listen [::]:35729 default_server; listen [::]:35729 default_server;
server_name transcendance; server_name transcendance;

View File

@@ -8,3 +8,4 @@
!api_front/*.json !api_front/*.json
!api_front/*.html !api_front/*.html
!api_front/*.lock !api_front/*.lock
!api_front/.env

View File

@@ -1,107 +0,0 @@
# This repo is no longer maintained. Consider using `npm init vite` and selecting the `svelte` option or — if you want a full-fledged app framework and don't mind using pre-1.0 software — use [SvelteKit](https://kit.svelte.dev), the official application framework for Svelte.
---
# svelte app
This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
```bash
npx degit sveltejs/template svelte-app
cd svelte-app
```
*Note that you will need to have [Node.js](https://nodejs.org) installed.*
## Get started
Install the dependencies...
```bash
cd svelte-app
npm install
```
...then start [Rollup](https://rollupjs.org):
```bash
npm run dev
```
Navigate to [localhost:8080](http://localhost:8080). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense.
## Building and running in production mode
To create an optimised version of the app:
```bash
npm run build
```
You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
## Single-page app mode
By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
```js
"start": "sirv public --single"
```
## Using TypeScript
This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with:
```bash
node scripts/setupTypeScript.js
```
Or remove the script via:
```bash
rm scripts/setupTypeScript.js
```
If you want to use `baseUrl` or `path` aliases within your `tsconfig`, you need to set up `@rollup/plugin-alias` to tell Rollup to resolve the aliases. For more info, see [this StackOverflow question](https://stackoverflow.com/questions/63427935/setup-tsconfig-path-in-svelte).
## Deploying to the web
### With [Vercel](https://vercel.com)
Install `vercel` if you haven't already:
```bash
npm install -g vercel
```
Then, from within your project folder:
```bash
cd public
vercel deploy --name my-project
```
### With [surge](https://surge.sh/)
Install `surge` if you haven't already:
```bash
npm install -g surge
```
Then, from within your project folder:
```bash
npm run build
surge public my-project.surge.sh
```

View File

@@ -1,81 +0,0 @@
<script lang="ts">
// routing
// may not need {link} here
import Router, { link } from "svelte-spa-router";
import { routes } from "../routes.js";
import LoginPage from "./LoginPage.svelte";
import UserPage from "../UserPage.svelte";
import NotFound from "../pages/NotFound.svelte";
// Ideally fuck all this shit in the long run
let pages = ['login', 'user', 'account'];
// make this a $: currentPage ?
let currentPage = 'booba';
// prolly change this? yea idk...
// let userIndex;
// tmp for testing
let userId = 0;
// horrible naming... can be HOME or ACCOUNT
let currentType = 'account';
// this page should handle the SPA history management...
// set to false later for actual security
let loggedIn = true;
// not sure if this is how i want to do this...
// might do differently cuz URL route manangement...
const handleLogin = () => {
currentPage = 'user';
loggedIn = true;
};
// I don't know if i should but i'm tempted to put this here...
// import axios from 'axios';
// import { onMount } from 'svelte';
// import { push } from 'svelte-spa-router';
// let user = {logedIn: false};
// onMount(async () => {
// // console.log('PROFIL SVELTE');
// const {data} = await axios.get('http://transcendance:8080/api/v2/user');
// if (data)
// user.logedIn = true;
// });
// $: submit = async() => {
// window.location.href = 'http://transcendance:8080/api/v2/auth';
// }
// $: logout = async() => {
// await fetch('http://transcendance:8080/api/v2/auth/logout',);
// user.logedIn = false;
// }
</script>
<!-- eventually we will do this with routes, but for now use a prop -->
<!-- {#if currentPage === 'login'}
<LoginPage {pages} {currentPage} {userId} on:loggedIn={handleLogin}/>
{:else if currentPage === 'user'}
<UserPage {pages} {currentPage} {userId} {currentType}/>
{:else}
<NotFound />
{/if} -->
<Router {routes}/>
<style>
/* doesn't work... */
/* body{
background: bisque;
} */
</style>

View File

@@ -1,167 +0,0 @@
<!-- <script lang="ts"> -->
<script>
import { onMount } from 'svelte';
let canvas;
// $: scaleRatio = window.innerWidth / 10;
$: scaleRatio = 30;
onMount(() => {
// we're invoking JS methods of the canvas element
const ctx = canvas.getContext('2d');
ctx.width = window.innerWidth;
ctx.height = window.innerHeight;
// ctx.beginPath();
// ctx.moveTo(50,50);
// ctx.lineTo(70,70);
// ctx.stroke();
// attempting to import an image
const img = new Image();
// we may have to call an onMount or something to make sure the image has loaded...
// doing it in JS for now, ideally in Svelte later..
// img.addEventListener('load', () => {
// // execute drawImage statements here
// }, false);
img.src = 'img/potato_logo.png'; // seems like this does need to be above onload()
img.onload = () => {
// ctx.drawImage(img, 0, 0, img.width * (ctx.width / 15), img.height * (ctx.height / 15));
// ctx.drawImage(img, 0, 0, ctx.width / 15, ctx.height / 15);
// i think i don't want this cuz it'll get in the way?
// ctx.drawImage(img, 0, 0, img.width / scaleRatio, img.height / scaleRatio);
// it would seem you need to redraw the images when you change the Window size, it's not automatically responsive
};
let startX = 200;
let startY = 200;
let dx = 3;
let dy = -1;
// Time for some math
// lets say i want 6 rows
// ok so we're gonna draw all the potatos at the same time and each of them gets animated, like i have it now
// 6 in a row so # of rows aka x = width * 6/height
function Potato(x, y) {
this.x = x;
this.y = y;
// ctx.drawImage(img, x, y, img.width / scaleRatio, img.height / scaleRatio);
this.draw = function() {
ctx.drawImage(img, x, y, img.width / scaleRatio, img.height / scaleRatio);
}
this.animate = function() {
this.x += dx;
this.y += dy;
this.draw();
}
}
// let spacing = canvas.width * ((6 + 1) / canvas.height);
let spacing = 70;
let Potatos = [];
//check the math...
// for (let i = 0; i < 6 * spacing; i++) {
for (let i = 0; i < 2; i++) {
// for (let j = 0; j < 6; j++) {
for (let j = 0; i < 2; j++) {
Potatos.push(new Potato(spacing + (i * spacing), spacing + (j * spacing)));
}
}
// now i'm trying to move 1 potato
let frame = requestAnimationFrame(loop);
// function loop(t) {
// ctx.clearRect(0, 0, canvas.width, canvas.height);
// frame = requestAnimationFrame(loop);
// ctx.drawImage(img, startX, startY, img.width / scaleRatio, img.height / scaleRatio);
// startX += dx;
// startY += dy;
// }
// new Potato(70, 70).animate();
function loop(t) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
frame = requestAnimationFrame(loop);
for (let i = 0; i < Potatos.length; i++) {
Potatos[i].animate();
}
// Potatos[0].animate();
}
loop();
// Lets try again with a single loop
// THis shit makes the cool Gradient
// let frame = requestAnimationFrame(loop);
// function loop(t) {
// frame = requestAnimationFrame(loop);
// // const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// for (let p = 0; p < imageData.data.length; p += 4) {
// const i = p / 4;
// const x = i % canvas.width;
// const y = i / canvas.width >>> 0;
// const r = 64 + (128 * x / canvas.width) + (64 * Math.sin(t / 1000));
// const g = 64 + (128 * y / canvas.height) + (64 * Math.cos(t / 1000));
// const b = 128;
// imageData.data[p + 0] = r;
// imageData.data[p + 1] = g;
// imageData.data[p + 2] = b;
// imageData.data[p + 3] = 255;
// }
// ctx.putImageData(imageData, 0, 0);
// }
return () => {
cancelAnimationFrame(frame);
// prolly something else...
};
});
</script>
<canvas
bind:this={canvas}
width={window.innerWidth}
height={window.innerHeight}
></canvas>
<!-- widht and height were 32, trying stuff -->
<!-- I don't have the /svelte-logo-mask.svg, i guess i'll go get something -->
<style>
canvas {
width: 100%;
height: 100%;
background-color: #666;
/* testing something */
/* -webkit-mask-image: radial-gradient(circle, black 50%, rgba(0, 0, 0, 0.5) 50%);
mask-image: radial-gradient(circle, black 50%, rgba(0, 0, 0, 0.5) 50%); */
/* Holy shit that worked! i got a mask */
/* it also works without a mask! i have a canvas! */
/* -webkit-mask: url(/svelte-logo-mask.svg) 50% 50% no-repeat; */
/* -webkit-mask: url(img/cartoon_potato3.jpg) 50% 50% no-repeat; */
/* mask: url(/svelte-logo-mask.svg) 50% 50% no-repeat; */
/* mask: url(img/cartoon_potato3.jpg) 50% 50% no-repeat; */
}
</style>

View File

@@ -1,45 +0,0 @@
<script lang="ts">
import { onMount, setContext } from "svelte";
let canvas;
// what do i want?
// lets start with an image of my potato
// then get it to move
// then have many displayed in an offset grid
const drawFunctions = [];
setContext('canvas', {
register(drawFn) {
drawFunctions.push(drawFn);
},
unregister(drawFn) {
drawFunctions.splice(drawFunctions.indexOf(drawFn), 1);
}
})
onMount(() => {
// not sure what this does...
const ctx = canvas.getContext('2d');
// no idea what this does...
function update() {
ctx.clearRect()
drawFunctions.forEach(drawFn => {
drawFn(ctx);
});
frameId = requestAnimationFrame(update);
}
let frameId = requestAnimationFrame(update);
return () => {
cancelAnimationFrame(update);
};
});
</script>
<canvas bind:this={canvas} />

View File

@@ -1,112 +0,0 @@
<script lang="ts">
import { onMount } from 'svelte';
import { location } from 'svelte-spa-router';
import GenerateUserDisplay from './GenerateUserDisplay.svelte';
// using location won't work cuz i do a fetch but i don't change the page fragment, so means nothing to location...
// this is how you access /:first for example
// export let params = {}
// <p>Your name is: <b>{params.first}</b> <b>{#if params.last}{params.last}{/if}</b></p>
// If i export these vars, maybe as an nice tidy object, i could pass whatever i like to them
// The current user, some other user, whatever, and thus reuse this Componente for the user and their friends or whatever
// will have to coordinate with Back, will know more once the Game stats are in the back
// wait maybe this won't work, cuz like it's still going through a route, i would have to update a Store Var each time...
// not sure if that's what i want...
// maybe the rank is determined dynamically just in the front based on win loss ratio or something no one cares about
// why bother storing that shit in the back...
// maybe i need a Rank.svelte component
// ohhh i could make above a certain rank glitter! like that CSS tutorial showed me!
export let aUsername;
let user;
let rank = '';
let avatar;
// i think i don't need to do this once i sort out the {wrap} conditions: in theory i could pass values to the Route
// once the async authentication check is done
onMount( async() => {
console.log('Display aUser username: '+ aUsername)
// http://transcendance:8080/api/v2/user?username=NomDuUserATrouver
user = await fetch(`http://transcendance:8080/api/v2/user?username=${aUsername}`)
.then( (x) => x.json() );
console.log('Display a user: ' + user.username)
// console.log('profile display did my fetch')
// should i be updating the userStore or is that unnecessary?
if (user.loseGame > user.winGame) {
rank = 'Bitch Ass Loser!'
} else if (user.loseGame === user.winGame) {
rank = 'Fine i guess...'
} else {
rank = 'Yea you da Boss!'
}
await fetch("http://transcendance:8080/api/v2/user/avatar", {method: "GET"})
.then(response => {return response.blob()})
.then(data => {
const url = URL.createObjectURL(data);
avatar = url;
});
// tmp
// console.log('mounted Profile Display')
// console.log(user);
})
// Glittery Stars and such for Rank
let index = 0, interval = 1000;
const rand = (min, max) =>
Math.floor(Math.random() * (max - min + 1)) + min;
// it's unhappy that "star" isn't typeset, no idea what to do about it...
const animate = (star) => {
// the if seems to have fixed the type issue
if (star) {
star.style.setProperty("--star-left", `${rand(-10, 100)}%`);
star.style.setProperty("--star-top", `${rand(-40, 80)}%`);
star.style.animation = "none";
star.offsetHeight;
star.style.animation = "";
}
}
// This is the part i invented, it was kinda a fucking nightmare...
let stars = [];
for (let i = 0; i < 3; i++) {
setTimeout(() => {
animate(stars[i]);
setInterval(() => animate(stars[i]), 1000);
}, index++ * (interval / 3))
}
</script>
{#if user !== undefined}
<GenerateUserDisplay {user}/>
{:else}
<h2>Sorry</h2>
<div>Failed to load user {aUsername}</div>
{/if}
<style>
</style>

View File

@@ -1,24 +0,0 @@
<script lang="ts">
// might rename...
// no idea what i'm doing...
import { getContext, onMount } from 'svelte';
// here you have to export the vars you need to draw this shit...
const { register, unregister } = getContext('canvas');
onMount(() => {
register(draw);
return () => {
unregister(draw);
}
});
function draw(ctx) {
ctx.beginPath();
ctx.fillStyle = fill;
}
</script>

View File

@@ -1,124 +0,0 @@
<script lang="ts">
// Fucking having a header that can change size, i don't really want the larger one
import { createEventDispatcher } from 'svelte';
let dispatch = createEventDispatcher();
let types: string[] = ['home', 'regular', 'none'];
// let currentType: string = 'regular';
export let currentType = 'regular';
// apparently Regular is the only one i use...
let handleClickHome = () => {
dispatch('clickedHome');
};
let handleClickLogout = () => {
dispatch('clickedLogout');
};
</script>
<!-- Make it so you can have a Big Home page header and a regular header or no header -->
<!-- So far my CSS is super Gross, i guess i'll get Hugo to help me with it -->
<header class={currentType}>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<img class={currentType} src="/img/potato_logo.png" alt="Potato Pong Logo" on:click={handleClickHome}>
<!-- {#if currentType === 'home'} -->
<h1 class={currentType}>Potato Pong</h1>
<!-- {/if} -->
<nav class={currentType}>
<!-- <a href=""></a> -->
<!-- i might change these to links rather than buttons, i kinda hate the buttons -->
<button>My Stats</button>
<button>Stream</button>
<button on:click={handleClickLogout}>Log Out</button>
</nav>
</header>
<style>
/* See "possible_fonts.css" for more font options... */
@font-face {
font-family: 'Bondi';
src:url('/fonts/Bondi.ttf.woff') format('woff'),
url('/fonts/Bondi.ttf.svg#Bondi') format('svg'),
url('/fonts/Bondi.ttf.eot'),
url('/fonts/Bondi.ttf.eot?#iefix') format('embedded-opentype');
font-weight: normal;
font-style: normal;
}
/* There is a bunch of unncessary shit in here... why so many flex grids, why is everything the same class? just seemed easier but... */
header{
/* background: #f7f7f7; */
background: #618174;
/* padding: 20px; */
margin: 0;
/* does nothing so far... */
/* display: flex; */
}
header.home{
/* position: sticky; */
}
header.regular{
/* for some reason this doesn't do shit! */
position: sticky;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
/* Headers */
h1{
font-family: 'Bondi';
}
h1.home {
margin: 0;
text-align: center;
/* max-width: 100px; */
}
h1.regular{
margin: 0;
text-align: left;
/* max-width: 40px; */
/* this helped with the weird extra space under the image... */
display: flex;
justify-self: center;
align-self: center;
}
/* Images */
img.home{
/* text-align: center; */
/* get the image squarely in the middle... */
cursor: pointer;
max-width: 100px;
}
img.regular{
cursor: pointer;
max-width: 40px;
padding: 7px 20px;
justify-self: left;
}
nav{
display: flex;
justify-content: right;
}
nav button{
margin: 7px 20px;
/* padding: 5px; */
border-radius: 4px;
}
/* .none{
} */
</style>

View File

@@ -1,102 +0,0 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
let dispatch = createEventDispatcher();
let types: string[] = ['home', 'regular', 'none'];
// let currentType: string = 'regular';
export let currentType = 'home';
let handleClick = () => {
dispatch('clickedHome');
};
</script>
<!-- Make it so you can have a Big Home page header and a regular header or no header -->
<!-- So far my CSS is super Gross, i guess i'll get Hugo to help me with it -->
<header class={currentType}>
<h1 class={currentType}>
<img class={currentType} src="/img/potato_logo.png" alt="Potato Pong Logo" on:click={handleClick}>
</h1>
<!-- {#if currentType === 'home'} -->
<h1 class={currentType}>Potato Pong</h1>
<!-- {/if} -->
</header>
<style>
/* See "possible_fonts.css" for more font options... */
@font-face {
font-family: 'Bondi';
src:url('/fonts/Bondi.ttf.woff') format('woff'),
url('/fonts/Bondi.ttf.svg#Bondi') format('svg'),
url('/fonts/Bondi.ttf.eot'),
url('/fonts/Bondi.ttf.eot?#iefix') format('embedded-opentype');
font-weight: normal;
font-style: normal;
}
/* There is a bunch of unncessary shit in here... why so many flex grids, why is everything the same class? just seemed easier but... */
header{
/* background: #f7f7f7; */
background: #618174;
/* padding: 20px; */
margin: 0;
font-family: 'Bondi';
/* does nothing so far... */
/* display: flex; */
}
header.home{
/* position: sticky; */
}
header.regular{
position: sticky;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
header.regular > h1:first-child{
justify-self: left;
}
header.regular > h1:nth-child(2){
justify-items: center;
}
/* Headers */
h1.home {
margin: 0;
text-align: center;
/* max-width: 100px; */
}
h1.regular{
margin: 0;
text-align: left;
/* max-width: 40px; */
/* this helped with the weird extra space under the image... */
display: flex;
justify-self: center;
align-self: center;
}
/* Images */
h1 img.home{
/* text-align: center; */
/* get the image squarely in the middle... */
cursor: pointer;
max-width: 100px;
}
h1 img.regular{
cursor: pointer;
max-width: 40px;
padding: 7px 15px;
}
/* .none{
} */
</style>

View File

@@ -1,172 +0,0 @@
<script lang="ts">
// Now called LoginPage
// import Header from "./Header.svelte";
import Footer from "../components/Footer.svelte";
import Login from "./Login.svelte";
import Tabs from "../shared/Tabs.svelte"
import Card from "../pieces/Card.svelte"
// tmp
let login = { username: '', password: ''};
// let's us track any errors in a submited form
let errors = { username: '', password: ''};
let valid:boolean = false;
const loginHandler = () => {
console.log('hi');
};
const createAccountHandler = () => {
console.log('hi');
};
// Tabs
let items: string[] = ['Login', 'Create Account'];
let activeItem: string = 'Login';
const tabChange = (e) => {
activeItem = e.detail;
};
// TMP for switching page, down the line this will be down by modifying url
</script>
<!-- New New Approach -->
<!-- if i were to do all this with CSS Grids how would i do it? -->
<!-- Things i want -->
<!-- A title button, some nav buttons, a giant dope canvas and words over it -->
<!-- not sure if i want: login and create account -->
<!-- let's start with just the canvas -->
<!-- New aproach -->
<!-- just make the html in order you can move it around all you want into special Compoenents later -->
<!-- Ok i think all of this needs to go in a Home Page Component -->
<!-- and then i make another master component for the main page once you're logged in, no idea what that should look like -->
<!-- what if i kept the special canvas header in here and made another generic header for the rest of the site as a component -->
<header class="banner">
<!-- top left corner, sticky -->
<h1>Potato Pong</h1>
<!-- top right but it takes you down the page -->
<h2>Login</h2>
<!-- all this used to be in Welcome Section -->
<!-- the amazing backround! not sure yet if it should scroll with us or be the size of the View Port... -->
<!-- <canvas></canvas> -->
<!-- i think maybe the canvas needs to be in the header -->
<!-- using an image for now as a placehodler for the canvase -->
<img src="/img/tmp_mario_banner.png" alt="tmp Mario banner">
<div class="welcome">
<h2>Welcome to <br><span>Potato Pong</span></h2>
</div>
<!-- I want some sort of arrow pointing down and blinking to indicate you should scroll -->
</header>
<!-- <section class="banner"> -->
<section class="welcome">
</section>
<!-- no nav on home page -->
<section class="register">
<!-- i could have a toggle tab to login or create a new account -->
<Tabs items={items} {activeItem} on:tabChange={tabChange}/>
{#if activeItem === 'Login'}
<div class="card">
<Card>
<h2>Login</h2>
<form on:submit|preventDefault={loginHandler}>
<div class="form-field">
<input type="text" id="username" placeholder="username" bind:value={login.username}>
<div class="error">{ errors.username }</div>
</div>
<div class="form-field">
<input type="password" id="password" placeholder="password" bind:value={login.password}>
<div class="error">{ errors.password }</div>
</div>
<!-- type="" but flat={} cuz type is a string but flat is a bool-->
<!-- <Button type="secondary" flat={true}>Add Poll</Button> -->
<button>Login</button>
</form>
</Card>
</div>
{:else if activeItem = 'Create Account'}
<!-- Create Account -->
<div class="card">
<Card>
<h3>Create Account</h3>
<form on:submit|preventDefault={createAccountHandler}>
<div class="form-field">
<input type="text" id="username" placeholder="username" bind:value={login.username}>
<div class="error">{ errors.username }</div>
</div>
<div class="form-field">
<input type="password" id="password" placeholder="password" bind:value={login.password}>
<div class="error">{ errors.password }</div>
</div>
<!-- type="" but flat={} cuz type is a string but flat is a bool-->
<!-- <Button type="secondary" flat={true}>Add Poll</Button> -->
<button>Login</button>
</form>
</Card>
</div>
{/if}
</section>
<!-- below this i could say, this is where i might have put an explanation of what you can do on this page but fuck you i didn't -->
<!-- or maybe in the end i will, something like: Fun, Game, Colors, enjoy Friendship, or don't, it's your choice! -->
<Footer />
<style>
/* hearder stuff */
/* Clearly i have yet to master floating stuff... */
/* i need to put box-sizing in here somewhere for the login... */
/* starting again with CSS Grid */
/* .banner{
position: relative;
}
.banner img{
max-width: 100%;
}
.banner h1{
position: absolute;
left: 0;
top: 10px;
}
.banner h2{
position: absolute;
left: 90%;
top: 10px;
}
.banner .welcome{
background-color: #feb614;
color:white;
padding: 30px;
position: absolute;
left: 50%;
top: 50%;
}
.banner .welcome h2{
font-size: 58px;
}
.banner .welcome h2 span{
font-size: 1.3em;
}
.register{
} */
</style>

View File

@@ -1,90 +0,0 @@
<script lang="ts">
import { now } from "svelte/internal";
import Card from "../pieces/Card.svelte";
import { createEventDispatcher } from 'svelte';
// import UserStore from './stores/UserStore';
// prolly Typescript-ify
//let fields{question:string, answerA:string, answerB: string} = { question: '', answerA: '', answerB: ''};
let login = { username: '', password: ''};
// let's us track any errors in a submited form
let errors = { username: '', password: ''};
let valid:boolean = false;
const dispatch = createEventDispatcher();
const loginHandler = () => {
valid = true;
if (login.username !== $UserStore.username) {
valid = false;
errors.username = "wrong example username."
} else {
// reseting the value of errors
errors.username = "";
}
if (login.password !== $UserStore.password) {
valid = false;
errors.password = "wrong example password."
} else {
// reseting the value of errors
errors.password = "";
}
if (valid) {
$UserStore.loggedIn = true;
$UserStore.status = 'online';
dispatch('login');
}
};
</script>
<div class="login">
<Card>
<form on:submit|preventDefault={loginHandler}>
<div class="form-field">
<input type="text" id="username" placeholder="username" bind:value={login.username}>
<div class="error">{ errors.username }</div>
</div>
<div class="form-field">
<input type="password" id="password" placeholder="password" bind:value={login.password}>
<div class="error">{ errors.password }</div>
</div>
<!-- type="" but flat={} cuz type is a string but flat is a bool-->
<!-- <Button type="secondary" flat={true}>Add Poll</Button> -->
<button>Login</button>
</form>
</Card>
</div>
<style>
form{
width: 200px;
margin: 0 auto;
text-align: center;
}
.form-field{
margin: 18px auto;
}
input{
width: 100%;
border-radius: 6px;
}
.login{
/* display: grid;
grid-template-columns: 1fr; */
max-width: 350px;
}
.error{
font-weight: bold;
font-size: 12px;
color: #d91b42;
}
</style>

View File

@@ -1,414 +0,0 @@
<script lang="ts">
// import Header from "./Header.svelte";
import Footer from "../components/Footer.svelte";
import Tabs from "../shared/Tabs.svelte";
import Card from "../pieces/Card.svelte";
import Canvas from "../pieces/Canvas.svelte";
import ScrollTo from "../shared/ScrollTo.svelte";
import UserStore from "./UserStore.js";
import { createEventDispatcher } from "svelte";
import {push} from "svelte-spa-router";
let dispatch = createEventDispatcher();
// Tabs
let items: string[] = ['Login', 'Create Account'];
let activeItem: string = 'Login';
const tabChange = (e) => {
activeItem = e.detail;
};
import axios from 'axios';
import { onMount } from 'svelte';
let user = {logedIn: false};
onMount(async () => {
// console.log('PROFIL SVELTE');
const {data} = await axios.get('http://transcendance:8080/api/v2/user');
if (data)
user.logedIn = true;
});
const submit = async() => {
document.body.scrollIntoView();
push
window.location.href = 'http://transcendance:8080/api/v2/auth';
}
const logout = async() => {
await fetch('http://transcendance:8080/api/v2/auth/logout',);
user.logedIn = false;
};
// for toLogin
let bottomHalf;
// console.log(bottomHalf);
// const element = document.body;
// in theory this could be a Store, but for now this will do
// also in future we'll do this with urls
export let pages;
export let currentPage;
// this shit has overstayed it's welcome, fuck having userId all over the place
export let userId;
// maybe we put this in the login Component?
// tmp
let login = { username: '', password: ''};
// let's us track any errors in a submited form
let errors = { username: '', password: ''};
let valid:boolean = false;
const loginHandler = () => {
console.log('hi from loginHandler');
//
// Basic Checks
//
valid = false;
// checkin Username
if (login.username.length < 1)
{
valid = false;
errors.username = 'please enter a username';
} else {
valid = true;
errors.username = '';
}
// Checking Password
if (login.password.length < 1)
{
valid = false;
errors.password = 'please enter your password';
} else {
valid = true;
errors.password = '';
}
//
// Advanded Checks
//
// Comparing to UserStore
let users;
const unsubscribe = UserStore.subscribe(objs => {
users = objs;
console.log('subscribed');
});
// could i do $users.length ? doesn't look like it...
// let len = $users.length;
// userId = 0;
// userId = users.filter(user => user.username === login.username);
// this shit returns an array, it would be nice if it weren't an array
// let user = users.filter(user => user.username === login.username);
let user = users.find(user => user.username === login.username);
console.log(user);
// console.log(user.password);
// all this shit is a bit wordy... maybe a better way to handle this stuff?
// if (userIndex > users.length) {
if (!user) {
valid = false;
errors.username = 'user not found';
// something better?
} else {
valid = true;
errors.username = '';
}
// if (users[userIndex].password !== login.password) {
if (user && user.password !== login.password) {
valid = false;
errors.password = 'Wrong Password';
// Maybe clear the fields?
} else {
valid = true;
errors.password = '';
}
//
// Validation
//
unsubscribe();
if (valid) {
// yea don't modify this here...
currentPage = 'user';
// something like: indicate that userIndex is the one we want...
console.log('valid Credentials');
// making sure we start at the top of the page, way less jarring
// leave for now just in case...
document.body.scrollIntoView();
// may not actually want a dispatch?
// pass data userIndex?
// dispatch('loggedIn');
// from svelte-spa-router
push("/user");
}
};
//
const createAccountHandler = () => {
console.log('hi from accunt handler');
};
</script>
<header class="grid-container">
<!-- <div on:mouseenter={enter} on:mouseleave={leave} class:active > -->
<h1>Potato Pong</h1>
<!-- </div> -->
<nav>
<!-- placeholder links -->
<a href="/">Somewhere</a>
<!-- <a href="/">SomewhereElse</a> -->
{#if !user.logedIn}
<ScrollTo element={bottomHalf}/>
{:else}
<div class="logout" on:click={logout}>Log Out</div>
{/if}
<!-- one of these will be login and it will scroll you down to the login part -->
</nav>
<h2>
<div>Welcome to</div>
<div>Potato Pong</div>
</h2>
<!-- here i want a flashing arrow pointing down to the login part -->
</header>
<!-- <Canvas class=".canvas2"/> -->
<Canvas/>
<section class="register" bind:this={bottomHalf}>
<!-- My beautiful tabs are useless now, whatever, kill your darlings... -->
<!-- i could have a toggle tab to login or create a new account -->
<!-- This shit is kinda unnecessary cuz there is no Create Account option... -->
<Tabs items={items} {activeItem} on:tabChange={tabChange}/>
{#if activeItem === 'Login'}
<div class="card">
<Card>
<h2>Login</h2>
<form on:submit|preventDefault={loginHandler}>
<div class="form-field">
<input type="text" id="username" placeholder="username" bind:value={login.username}>
<div class="error">{ errors.username }</div>
</div>
<div class="form-field">
<input type="password" id="password" placeholder="password" bind:value={login.password}>
<div class="error">{ errors.password }</div>
</div>
<!-- type="" but flat={} cuz type is a string but flat is a bool-->
<!-- <Button type="secondary" flat={true}>Add Poll</Button> -->
<button>Login</button>
</form>
</Card>
</div>
{:else if activeItem = 'Create Account'}
<!-- Create Account -->
<div class="card">
<Card>
<h2>Create Account</h2>
<form on:submit|preventDefault={createAccountHandler}>
<div class="form-field">
<input type="text" id="username" placeholder="username" bind:value={login.username}>
<div class="error">{ errors.username }</div>
</div>
<div class="form-field">
<input type="password" id="password" placeholder="password" bind:value={login.password}>
<div class="error">{ errors.password }</div>
</div>
<!-- type="" but flat={} cuz type is a string but flat is a bool-->
<!-- <Button type="secondary" flat={true}>Add Poll</Button> -->
<button>Login</button>
</form>
</Card>
</div>
{/if}
</section>
<!-- below this i could say, this is where i might have put an explanation of what you can do on this page but fuck you i didn't -->
<!-- or maybe in the end i will, something like: Fun, Game, Colors, enjoy Friendship, or don't, it's your choice! -->
<Footer />
<!-- </div> -->
<style>
/* currently useless */
/* No styles get applied to the canvas from here, maybe i should move them to the Canvas Component... */
/* tho tbh, why bother, i'm gonna change it anyway... */
.canvas{
/* grid-column: 1 / 13;
grid-row: 1 / 3; */
/* don't rely on Z-Index!!!! */
z-index: -1;
position: relative;
width: 100%;
height: 100%;
white-space: nowrap;
/* Tmp? */
/* background-color: #666; */
/* somehow this got rid of they annoying white space under the canvas */
padding-bottom: 0;
margin-bottom: 0px;
overflow: hidden;
}
.canvas2{
z-index: -1;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
white-space: nowrap;
/* Tmp? */
/* background-color: #666; */
/* somehow this got rid of they annoying white space under the canvas */
padding-bottom: 0;
margin-bottom: 0px;
overflow: hidden;
}
/* .canvas .grid-container{ */
.grid-container{
position: absolute;
left: 0;
top: 0;
box-sizing: border-box;
width: 100%;
height: 100%;
white-space: nowrap;
/* padding-bottom: 0; */
margin-bottom: 0px;
overflow: hidden;
padding: 20px 40px;
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 1fr 1fr 1fr 1fr 1fr;
align-items: center;
}
header h1, header nav a{
/* tmp ? well i kinda like it */
color: bisque;
}
header h1{
grid-column: 1 / 7;
grid-row: 1;
/* grid-column: span 6; */
/* tmp? */
padding: 20px;
border: 1px solid bisque;
}
header nav{
/* make it a flexbox? */
grid-column: 7 / 13;
grid-row: 1;
justify-self: end;
/* tmp? */
padding: 20px;
border: 1px solid bisque;
}
header nav a{
margin-left: 10px;
text-decoration: none;
}
/* testing */
header nav a:hover{
font-weight: bold;
background-color: blue;
}
header h2:hover{
background: blue;
}
header h2{
grid-row: 3;
grid-column: 5 / span 4;
justify-self: center;
/* tmp */
border: 1px solid black;
z-index: 3;
}
header h2 div{
font-size: 2em;
}
/* the login / register part */
/* What do i want?
I want it to be the same size as a full screen so you don't see the canvas at all anymore */
/* doesn't work... */
/* body{
background: bisque;
} */
.bottom-half{
/* doesn't quite work... */
background: bisque;
/* also doesn't work... */
/* height: 1vw; */
/* testing */
/* position: absolute; */
}
section.register{
min-height: 400px;
}
.error{
font-size: 0.8em;
font-weight: bold;
color: red;
}
</style>

View File

@@ -1,305 +0,0 @@
<script lang="ts">
import { onMount } from 'svelte';
import { location } from 'svelte-spa-router';
// this is how you access /:first for example
// export let params = {}
// <p>Your name is: <b>{params.first}</b> <b>{#if params.last}{params.last}{/if}</b></p>
// If i export these vars, maybe as an nice tidy object, i could pass whatever i like to them
// The current user, some other user, whatever, and thus reuse this Componente for the user and their friends or whatever
// will have to coordinate with Back, will know more once the Game stats are in the back
// wait maybe this won't work, cuz like it's still going through a route, i would have to update a Store Var each time...
// not sure if that's what i want...
// maybe the rank is determined dynamically just in the front based on win loss ratio or something no one cares about
// why bother storing that shit in the back...
// maybe i need a Rank.svelte component
// ohhh i could make above a certain rank glitter! like that CSS tutorial showed me!
let user;
let rank = '';
let avatar;
// i think i don't need to do this once i sort out the {wrap} conditions: in theory i could pass values to the Route
// once the async authentication check is done
onMount( async() => {
// console.log('mounting profile display')
user = await fetch('http://transcendance:8080/api/v2/user')
.then( (x) => x.json() );
// console.log('profile display did my fetch')
// should i be updating the userStore or is that unnecessary?
if (user.loseGame > user.winGame) {
rank = 'Bitch Ass Loser!'
} else if (user.loseGame === user.winGame) {
rank = 'Fine i guess...'
} else {
rank = 'Yea you da Boss!'
}
await fetch("http://transcendance:8080/api/v2/user/avatar", {method: "GET"})
.then(response => {return response.blob()})
.then(data => {
const url = URL.createObjectURL(data);
avatar = url;
});
// tmp
// console.log('mounted Profile Display')
// console.log(user);
})
// Glittery Stars and such for Rank
let index = 0, interval = 1000;
const rand = (min, max) =>
Math.floor(Math.random() * (max - min + 1)) + min;
// it's unhappy that "star" isn't typeset, no idea what to do about it...
const animate = (star) => {
// the if seems to have fixed the type issue
if (star) {
star.style.setProperty("--star-left", `${rand(-10, 100)}%`);
star.style.setProperty("--star-top", `${rand(-40, 80)}%`);
star.style.animation = "none";
star.offsetHeight;
star.style.animation = "";
}
}
// This is the part i invented, it was kinda a fucking nightmare...
let stars = [];
for (let i = 0; i < 3; i++) {
setTimeout(() => {
animate(stars[i]);
setInterval(() => animate(stars[i]), 1000);
}, index++ * (interval / 3))
}
</script>
<!-- is this if excessive? -->
<div class="outer">
{#if user !== undefined}
<main>
<!-- <img class="icon" src="img/default_user_icon.png" alt="default user icon"> -->
<!-- <img class="icon" src="{user.image_url}" alt="default user icon"> -->
<img class="avatar" src="{avatar}" alt="default user icon">
<div class="username">{user.username}</div>
<div class="rank">Rank:
<span class="glitter">
<span bind:this={stars[0]} class="glitter-star">
<svg viewBox="0 0 512 512">
<path d="M512 255.1c0 11.34-7.406 20.86-18.44 23.64l-171.3 42.78l-42.78 171.1C276.7 504.6 267.2 512 255.9 512s-20.84-7.406-23.62-18.44l-42.66-171.2L18.47 279.6C7.406 276.8 0 267.3 0 255.1c0-11.34 7.406-20.83 18.44-23.61l171.2-42.78l42.78-171.1C235.2 7.406 244.7 0 256 0s20.84 7.406 23.62 18.44l42.78 171.2l171.2 42.78C504.6 235.2 512 244.6 512 255.1z" />
</svg>
</span>
<span bind:this={stars[1]} class="glitter-star">
<svg viewBox="0 0 512 512">
<path d="M512 255.1c0 11.34-7.406 20.86-18.44 23.64l-171.3 42.78l-42.78 171.1C276.7 504.6 267.2 512 255.9 512s-20.84-7.406-23.62-18.44l-42.66-171.2L18.47 279.6C7.406 276.8 0 267.3 0 255.1c0-11.34 7.406-20.83 18.44-23.61l171.2-42.78l42.78-171.1C235.2 7.406 244.7 0 256 0s20.84 7.406 23.62 18.44l42.78 171.2l171.2 42.78C504.6 235.2 512 244.6 512 255.1z" />
</svg>
</span>
<span bind:this={stars[2]} class="glitter-star">
<svg viewBox="0 0 512 512">
<path d="M512 255.1c0 11.34-7.406 20.86-18.44 23.64l-171.3 42.78l-42.78 171.1C276.7 504.6 267.2 512 255.9 512s-20.84-7.406-23.62-18.44l-42.66-171.2L18.47 279.6C7.406 276.8 0 267.3 0 255.1c0-11.34 7.406-20.83 18.44-23.61l171.2-42.78l42.78-171.1C235.2 7.406 244.7 0 256 0s20.84 7.406 23.62 18.44l42.78 171.2l171.2 42.78C504.6 235.2 512 244.6 512 255.1z" />
</svg>
</span>
<span class="glitter-text">{rank}</span>
</span>
</div>
<section class="main-stats">
<h4>Match Statistics</h4>
<p>Total: {user.stats.totalGame}</p>
<p>Victories: {user.stats.winGame}</p>
<p>Losses: {user.stats.loseGame}</p>
<p>Draws: {user.stats.drawGame}</p>
</section>
</main>
{/if}
</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<style>
div.outer{
max-width: 960px;
margin: 40px auto;
}
/* The main part */
main{
max-width: 960px;
margin: 40px auto;
text-align: center;
}
/* Normal CSS stuff */
.avatar{
max-width: 150px;
/* padding: 5px; */
}
/* The variable rich section */
section.main-stats{
max-width: 600px;
margin: 40px auto;
text-align: center;
/* i think i want to use a grid? */
display: grid;
grid-template-columns: repeat(3, 1fr);
/* not sure about this, maybe top should be larger? */
grid-template-rows: repeat(3, 1fr);
}
/* the stuff in the grid*/
section.main-stats h4{
grid-column: 1 / span 3;
}
div.username{
font-size: 1.5em;
font-weight: bold;
padding-bottom: 5px;
}
div.rank {
/* color: black; */
font-size: 1.2em;
font-weight: bold;
}
/* Glittery Star Stuff */
:root {
--purple: rgb(123, 31, 162);
--violet: rgb(103, 58, 183);
--pink: rgb(244, 143, 177);
/* make shit gold? */
}
@keyframes background-pan {
from {
background-position: 0% center;
}
to {
background-position: -200% center;
}
}
@keyframes scale {
from, to {
transform: scale(0);
}
50% {
transform: scale(1);
}
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(180deg);
}
}
div > .glitter {
display: inline-block;
position: relative;
}
div > .glitter > .glitter-star {
--size: clamp(20px, 1.5vw, 30px);
animation: scale 700ms ease forwards;
display: block;
height: var(--size);
left: var(--star-left);
position: absolute;
top: var(--star-top);
width: var(--size);
}
div > .glitter > .glitter-star > svg {
animation: rotate 1000ms linear infinite;
display: block;
opacity: 0.7;
}
div > .glitter > .glitter-star > svg > path {
fill: var(--violet);
}
div > .glitter > .glitter-text {
animation: background-pan 3s linear infinite;
/* background-image: linear-gradient( */
background: linear-gradient(
to right,
var(--purple),
var(--violet),
var(--pink),
var(--purple)
);
background-size: 200%;
/* Keep these for Safari and chrome */
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
/* These are for Firefox */
background-clip: text;
color: transparent;
white-space: nowrap;
}
</style>

View File

@@ -1,137 +0,0 @@
<script lang="ts">
import { onMount } from 'svelte';
import { loginStatus } from '../stores/loginStatusStore';
// Cherif's code
let qrCodeImg;
let qrCode = "";
let wrongCode = "";
let maxTry = 3;
// const fetchQrCodeImg = (async() => {
// await fetch("http://transcendance:8080/api/v2/auth/2fa/generate",
// {
// method: 'POST',
// })
// .then(response => {return response.blob()})
// .then(blob => {
// const url = URL.createObjectURL(blob);
// qrCodeImg = url;
// });
// })()
// $: submit = async() => {
// const response = await fetch("http://transcendance:8080/api/v2/auth/2fa/turn-on",
// {
// method : 'POST',
// headers : {
// "Content-Type": "application/json",
// },
// body : JSON.stringify({
// "twoFaCode" : qrCode,
// }),
// });
// if (response.status === 401)
// {
// qrCode = "";
// wrongCode = `Wrong code, please try again. You have ${maxTry} before end session`;
// maxTry--;
// }
// if (maxTry === 0)
// {
// await fetch("http://transcendance:8080/auth/logout",
// {
// method : 'POST',
// })
// .then(response => response.json())
// .then(push("/login"));
// }
// if (response.status === 200)
// {
// push("/");
// }
// }
// My code
let auth;
// we're expecting secret and otpauth
onMount( async() => {
// auth = await fetch('http://transcendance:8080/api/v2/auth/2fa/generate', {
// method: 'POST'
// })
// .then((resp) => resp.json());
// console.log(auth.secret);
await fetch("http://transcendance:8080/api/v2/auth/2fa/generate", {
method: 'POST',
})
.then(response => {return response.blob()})
.then(blob => {
const url = URL.createObjectURL(blob);
qrCodeImg = url;
});
});
// testing loginStatus Custom Store
const toggleTFA = () => {
loginStatus.toggleTFA();
console.log($loginStatus.tfa);
}
// testing
let auth2
const TFA = async() => {
// ok no idea what goes in here...
auth2 = await fetch('http://transcendance:8080/api/v2/auth/2fa/generate', {
method: 'POST'
})
// .then((resp) => resp.json());
// console.log(auth2.secret);
console.log(auth2);
};
// if ($loginStatus.tfa && $loginStatus.fortyTwo)
</script>
<h1>2FA Test</h1>
<div>
<button on:click={TFA}>TFA</button>
</div>
<div>
{#if auth2}
<p>{auth2.json()}</p>
{/if}
</div>
<img src={qrCodeImg} alt="A QRCodeImg you must scan with google authenticator" id="qrcodeImg" />
<!-- <p>FortyTwo: {$loginStatus.fortyTwo}</p>
<p>TFA: {$loginStatus.tfa}</p>
<p>isLogged: {loginStatus.isLogged}</p>
<div>
<button on:click={toggleTFA}>toggleTFA</button>
</div> -->
<style>
</style>

View File

@@ -1,149 +0,0 @@
<script lang="ts">
// The User Page can have several Flavors ?
// like a HomePage vibe, and an AccountPage vibe or whatever, but we'll still be serving this page just with diff props
import UserStore from "./UserStore";
import Header from "../components/Header.svelte";
import Footer from "../components/Footer.svelte";
import { createEventDispatcher } from "svelte";
import { loginStatus } from '../stores/loginStatusStore';
import { push } from "svelte-spa-router";
let dispatch = createEventDispatcher();
// i fucking hate these vars, the will have to go
export let pages;
export let currentPage;
export let userId;
// This shit is so redundant...
let types = ['home', 'account']
export let currentType = 'account';
// this is also stupid...
let sidebar = true;
// would i prefer to forward this?
let clickedHome = () => {
console.log('clicked home');
// do something...
currentType = 'home';
};
let clickedLogout = async() => {
console.log('clicked logout');
await fetch('http://transcendance:8080/api/v2/auth/logout',);
// $loginStatus = false;
// maybe use replace() ?
push('/');
};
// All the variables that will eventually be replaced by the real values
let username = 'Username';
let games = { total: 7, won: 4, lost: 3};
let rank = 'gold or whatever the fuck who cares...';
</script>
<!-- remove ={clickedHome} if you want to forward the event to App.svelte-->
<!-- god this is some gross code... -->
<Header on:clickedHome={clickedHome} currentType="{currentType === 'home' ? 'home' : 'regular'}" on:clickedLogout={clickedLogout}/>
<!-- The Wave -->
<!-- <div class="spacer layer1"></div> -->
<!-- this is the thing that will let me offset -->
<div class='{sidebar ? "main-grid" : "none"}'>
{#if sidebar}
<section class="sidebar">
<p>i am a sidebar</p>
</section>
{/if}
<main class:offset={sidebar}>
<!-- what the fuck do we even want in here? messges, about the user, STATISTICS!!! -->
<!-- <div>some stuff goes here</div> -->
<img class="icon" src="img/default_user_icon.png" alt="default user icon">
<div>{username}</div>
<div>Rank: {rank}</div>
<section class="main-stats">
<h4>Match Statistics</h4>
<p>Total: {games.total}</p>
<p>Victories: {games.won}</p>
<p>Losses: {games.lost}</p>
</section>
</main>
</div>
<Footer />
<style>
/* from Haikei */
/* for any Haikei image */
.spacer{
aspect-ratio: 900/300;
width: 100%;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
/* the specific image we use, you need both classes */
.layer1{
background-image: url('/img/wave-haikei.svg');
}
div.main-grid{
display: grid;
grid-template-columns: repeat(12, 1fr);
/* max-height: calc(100vh - 30vh); */
height: 85vh;
}
section.sidebar{
grid-column: 1 / span 2;
background: white;
}
/* The main part */
main{
max-width: 960px;
margin: 40px auto;
text-align: center;
}
main.offset{
grid-column: 3 / span 10;
}
/* Normal CSS stuff */
.icon{
max-width: 150px;
}
/* The variable rich section */
section.main-stats{
max-width: 600px;
margin: 40px auto;
text-align: center;
/* i think i want to use a grid? */
display: grid;
grid-template-columns: repeat(3, 1fr);
/* not sure about this, maybe top should be larger? */
grid-template-rows: repeat(3, 1fr);
}
/* the stuff in the grid*/
section.main-stats h4{
grid-column: 1 / span 3;
}
</style>

View File

@@ -1,45 +0,0 @@
import { writable } from "svelte/store";
// ok yea this doesn't make a lot of sense, what am i trying to do?
// have an array of objects that are all the users?
// or an object that is the one user?
// For now as a placeholder i'll have one user in one obj
// should it not be a const? yea seems like it
// export const users = writable(
const UserStore = writable(
[{
// this is an example user
id: 1,
username: 'chaboi',
email: 'nope@fu.com',
// surely there's a better way to do this!
password: '1234',
// maybe an object listing friends' usernames?
friends: 0,
loggedIn: false,
// i imagine the user uploading their Avatare and it being put somehwere in the DB which could be referenced like a URL
// so if this field is empty then use the default avatar
avatar: '',
// online, offline, gaming
status: 'offline',
},
{
id: 2,
username: 'itsame',
email: 'mario@nintendo.com',
// surely there's a better way to do this!
password: '1234',
// maybe an object listing friends' usernames?
friends: 0,
loggedIn: false,
// i imagine the user uploading their Avatare and it being put somehwere in the DB which could be referenced like a URL
// so if this field is empty then use the default avatar
avatar: '',
// online, offline, gaming
status: 'offline',
}]
);
export default UserStore;
// export default users;

View File

@@ -1,24 +0,0 @@
import { writable } from "svelte/store";
// an alternative way of doing things where i have a svelte store connected to localStorage
// do in need to adapt this to work with 2fa?
let _user = localStorage.getItem('42User');
// turns out a simple store is actually the easiest :)
// export const userStore = writable(_user ? JSON.parse(_user) : null); // we start with no user, but go get one if one exists
// export const userStore = writable(null);
// ok so this will happen no matter what, basically we are telling it what to do if the store containing the user changes
userStore.subscribe((value) => {
if (value)
localStorage.setItem('42User', JSON.stringify(value));
else
localStorage.removeItem('42User'); // for logout
});
export const userLogout = () => userStore.set(null);
// export const tmpStore = userStore

View File

@@ -1,129 +0,0 @@
import { writable } from "svelte/store";
// This is a "Custom Store" see that chapter in the Svelte Tutorial, should be fine
// NVM this is definitely overkill
// function createLogin() {
// const { subscribe, update } = writable(false);
// return {
// subscribe,
// login: () => update(s => s = true),
// logout: () => update(s => s = false),
// }
// }
// export const loginStatus = createLogin();
// export const loginStatus = writable({
// 42: false,
// tfa: false,
// });
// function createLoginStatus() {
// //ok it really hated all this
// // const store = writable({
// // fortyTwo: false,
// // tfa: false,
// // });
// // return {
// // ...store,
// // subscribe,
// // // toggle42: () => update( l => l.fortyTwo = !l.fortyTwo ),
// // toggle42: () => store.update( fortyTwo => !fortyTwo ),
// // // toggleTFA: () => update( l => l.tfa = !l.tfa ),
// // toggleTFA: () => store.update( tfa => !tfa ),
// // isLogged: () => store.fortyTwo && store.tfa,
// // // isLogged: this.fortyTwo && this.tfa,
// // // it really doesn't like "this."
// // // isLogged: () => (this.tfa && this.fortyTwo),
// // // this. ? or (l) => l.tfa ... ?
// // }
// // doesn't seem to work...
// const { subscribe, update } = writable({
// fortyTwo: false,
// tfa: false,
// });
// return {
// subscribe,
// // toggle42: () => update( l => l.fortyTwo = !l.fortyTwo ),
// toggle42: () => update( fortyTwo => !fortyTwo ),
// // toggleTFA: () => update( l => l.tfa = !l.tfa ),
// toggleTFA: () => update( tfa => !tfa ),
// // isLogged: () => fortyTwo && tfa,
// // isLogged: this.fortyTwo && this.tfa,
// // it really doesn't like "this."
// // isLogged: () => (this.tfa && this.fortyTwo),
// // this. ? or (l) => l.tfa ... ?
// isLogged() {
// return fortyTwo && tfa;
// },
// }
// // possible other way of doing this
// // const store = writable({
// // fortyTwo: false,
// // tfa: false,
// // });
// // return {
// // ...store,
// // subscribe,
// // // toggle42: () => update( l => l.fortyTwo = !l.fortyTwo ),
// // toggle42: () => store.update( l.fortyTwo => !l.fortyTwo ),
// // toggleTFA: () => store.update( l => l.tfa = !l.tfa ),
// // isLogged: store.fortyTwo && store.tfa,
// // // isLogged: () => (this.tfa && this.fortyTwo),
// // // this. ? or (l) => l.tfa ... ?
// // }
// }
function createLoginStatus() {
const { subscribe, update } = writable({
fortyTwo: false,
tfa: false,
});
function toggle42() {
update( (old) => ({...old, fortyTwo: !old.fortyTwo}) );
};
function toggleTFA() {
// update( () => {
// self.tfa = !self.tfa;
// return self;
// })
// console.log("testing");
update( (old) => ({...old, tfa: !old.tfa}) );
};
function isLogged() {
// return (l) => {l.fortyTwo && l.tfa};
// return self.fortyTwo && self.tfa;
// return fortyTwo && tfa;
};
return { subscribe, update, toggle42, toggleTFA, isLogged };
}
export const loginStatus = createLoginStatus();
// OK let's try a totally new approach
// const _loginStatus = writable({
// fortyTwo: false,
// tfa: false,
// })
// export const loginStatus = {
// subscribe: _loginStatus.subscribe,
// set: _loginStatus.set,
// update: _loginStatus.update,
// toggle42: () =>
// }

View File

@@ -1,54 +0,0 @@
@font-face {
font-family: 'Monocode-Regular-Demo';
src:url('/fonts/Monocode-Regular-Demo.ttf.woff') format('woff'),
url('Monocode-Regular-Demo.ttf.svg#Monocode-Regular-Demo') format('svg'),
url('Monocode-Regular-Demo.ttf.eot'),
url('Monocode-Regular-Demo.ttf.eot?#iefix') format('embedded-opentype');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'Air-Conditioner';
src:url('/fonts/Air-Conditioner.ttf.woff') format('woff'),
url('Air-Conditioner.ttf.svg#Air-Conditioner') format('svg'),
url('Air-Conditioner.ttf.eot'),
url('Air-Conditioner.ttf.eot?#iefix') format('embedded-opentype');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: '1968-Odyssey-3D';
src:url('/fonts/1968-Odyssey-3D.ttf.woff') format('woff'),
url('1968-Odyssey-3D.ttf.svg#1968-Odyssey-3D') format('svg'),
url('1968-Odyssey-3D.ttf.eot'),
url('1968-Odyssey-3D.ttf.eot?#iefix') format('embedded-opentype');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: '1968-Odyssey-Gradient';
src:url('/fonts/1968-Odyssey-Gradient.ttf.woff') format('woff'),
url('1968-Odyssey-Gradient.ttf.svg#1968-Odyssey-Gradient') format('svg'),
url('1968-Odyssey-Gradient.ttf.eot'),
url('1968-Odyssey-Gradient.ttf.eot?#iefix') format('embedded-opentype');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'AddFatMan';
src:url('/fonts/AddFatMan.ttf.woff') format('woff'),
url('/fonts/AddFatMan.ttf.svg#AddFatMan') format('svg'),
url('/fonts/AddFatMan.ttf.eot'),
url('/fonts/AddFatMan.ttf.eot?#iefix') format('embedded-opentype');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'Bondi';
src:url('/fonts/Bondi.ttf.woff') format('woff'),
url('/fonts/Bondi.ttf.svg#Bondi') format('svg'),
url('/fonts/Bondi.ttf.eot'),
url('/fonts/Bondi.ttf.eot?#iefix') format('embedded-opentype');
font-weight: normal;
font-style: normal;
}

View File

@@ -1,177 +0,0 @@
<script lang="ts">
import NotFound from "../src/pages/NotFound.svelte";
import ProfilePage from "../src/pages/profile/ProfilePage.svelte";
import SplashPage from "../src/pages/SplashPage.svelte";
import TwoFactorAuthentication from '../src/pages/TwoFactorAuthentication.svelte';
import UnauthorizedAccessPage from '../src/pages/UnauthorizedAccessPage.svelte';
import { wrap } from 'svelte-spa-router/wrap'
import { get } from 'svelte/store';
import TestPage from '../src/pages/TmpTestPage.svelte';
import { userStore, userLogout } from "../src/stores/loginStatusStore";
// "/article/:title": Article, // this is how you would do parameters!
// "/": LoginPage,
// TMP not using this cuz need to work out how to authentical both 42 and 2FA from the backend
// export const primaryRoutes = {
// '/': SplashPage,
// // '/2fa': TwoFactorAuthentication,
// '/2fa': wrap({
// component: TwoFactorAuthentication,
// conditions: [
// (detail) => {
// // let loggedIn;
// // loginStatus.subscribe(value => {
// // loggedIn = value;
// // });
// const { fortyTwo, tfa } = get(loginStatus);
// console.log('condition in /2fa');
// // return (loginStatus.fortyTwo && loginStatus.tfa);
// // console.log($loginStatus.fortyTwo)
// console.log(fortyTwo);
// console.log(tfa);
// return true;
// }
// ]
// }),
// '/profile': wrap({
// component: ProfilePage,
// conditions: [
// (detail) => {
// const { fortyTwo, tfa } = get(loginStatus);
// // console.log(fortyTwo);
// // console.log(tfa);
// // return true;
// return (fortyTwo && tfa);
// }
// ]
// }),
// '/profile/*': wrap({
// component: ProfilePage,
// conditions: [
// (detail) => {
// const { fortyTwo, tfa } = get(loginStatus);
// // console.log(fortyTwo);
// // console.log(tfa);
// // return true;
// return (fortyTwo && tfa);
// }
// ]
// }),
// '/profile': wrap({
// // Use a dynamically-loaded component for this
// asyncComponent: () => import('./ProfilePage.svelte'),
// // Adding one pre-condition that's an async function
// conditions: [
// async (detail) => {
// // Make a network request, which are async operations
// const response = await fetch('http://transcendance:8080/api/v2/user')
// const data = await response.json()
// // Return true to continue loading the component, or false otherwise
// if (data.isAdmin) {
// return true
// }
// else {
// return false
// }
// }
// ]
// }),
// '/unauthorized-access': UnauthorizedAccessPage,
// '*': NotFound
// };
export const primaryRoutes = {
"/": SplashPage,
'/test': wrap({
component: TestPage,
conditions: [
(detail) => {
// const user = get(userStore); // seems like get(store) is not an option
// // const user = userStore;
// // console.log(fortyTwo);
// // console.log(tfa);
// console.log('in /test what is in user')
// console.log(user)
// you moron $userStore is a Svelte Abreviation, this is .JS, duh
// let user = $userStore;
let user;
const unsub = userStore.subscribe(value => {
user = value;
});
console.log('in /test what is in userStore directly')
console.log(user)
// return true;
// obvi this doesn't work cuz skips to true after no user...
// you gotta make the condition the true and the everything else false
// if (user && user.statusCode && user.statusCode === 403)
// if (user !== null) {
if (user && user.username) {
unsub();
return true;
} else {
unsub();
return false;
}
}
]
}),
// '/test': wrap({
// component: TestPage,
// conditions: [
// async(detail) => {
// // THIS SHIT TOTALLY WORKS
// const user = await fetch('http://transcendance:8080/api/v2/user')
// .then((resp) => resp.json())
// console.log('in /test what is in user')
// console.log(user)
// if (user && user.username)
// return true;
// else
// return false;
// }
// ]
// }),
'/2fa': TwoFactorAuthentication,
"/profile": ProfilePage,
"/profile/*": ProfilePage,
'/unauthorized-access': UnauthorizedAccessPage,
"*": NotFound
};
// export const primaryRoutes = {
// "/": SplashPage,
// "/profile": ProfilePage,
// "/game": GamePage,
// "/chat": ChatPage,
// "*": NotFound
// };
// i might need to add /profile/* and such to make the nested routers work
// ok maybe these need to be in their own files?
// export const gameRoutes = {
// "/": GamePage,
// "*": NotFound
// };
// export const chatRoutes = {
// "/": ChatPage,
// "*": NotFound
// };
</script>

View File

@@ -8,6 +8,8 @@
"name": "svelte-app", "name": "svelte-app",
"version": "1.0.0", "version": "1.0.0",
"dependencies": { "dependencies": {
"@rollup/plugin-replace": "^5.0.2",
"dotenv": "^16.0.3",
"sirv-cli": "^2.0.0", "sirv-cli": "^2.0.0",
"socket.io-client": "^4.5.4", "socket.io-client": "^4.5.4",
"svelte-spa-router": "^3.3.0" "svelte-spa-router": "^3.3.0"
@@ -17,6 +19,7 @@
"@rollup/plugin-node-resolve": "^11.0.0", "@rollup/plugin-node-resolve": "^11.0.0",
"@rollup/plugin-typescript": "^8.0.0", "@rollup/plugin-typescript": "^8.0.0",
"@tsconfig/svelte": "^2.0.0", "@tsconfig/svelte": "^2.0.0",
"@types/node": "^18.11.18",
"rollup": "^2.3.4", "rollup": "^2.3.4",
"rollup-plugin-css-only": "^3.1.0", "rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-livereload": "^2.0.0", "rollup-plugin-livereload": "^2.0.0",
@@ -109,8 +112,7 @@
"node_modules/@jridgewell/sourcemap-codec": { "node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.14", "version": "1.4.14",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
"dev": true
}, },
"node_modules/@jridgewell/trace-mapping": { "node_modules/@jridgewell/trace-mapping": {
"version": "0.3.17", "version": "0.3.17",
@@ -203,6 +205,63 @@
"rollup": "^1.20.0||^2.0.0" "rollup": "^1.20.0||^2.0.0"
} }
}, },
"node_modules/@rollup/plugin-replace": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.2.tgz",
"integrity": "sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==",
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"magic-string": "^0.27.0"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/plugin-replace/node_modules/@rollup/pluginutils": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz",
"integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==",
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/plugin-replace/node_modules/@types/estree": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
"integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ=="
},
"node_modules/@rollup/plugin-replace/node_modules/magic-string": {
"version": "0.27.0",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz",
"integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.13"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@rollup/plugin-typescript": { "node_modules/@rollup/plugin-typescript": {
"version": "8.5.0", "version": "8.5.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.5.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.5.0.tgz",
@@ -267,9 +326,9 @@
"dev": true "dev": true
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "18.11.9", "version": "18.11.18",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz",
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==", "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==",
"dev": true "dev": true
}, },
"node_modules/@types/pug": { "node_modules/@types/pug": {
@@ -522,6 +581,14 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/dotenv": {
"version": "16.0.3",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
"integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==",
"engines": {
"node": ">=12"
}
},
"node_modules/engine.io-client": { "node_modules/engine.io-client": {
"version": "6.2.3", "version": "6.2.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.3.tgz", "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.3.tgz",
@@ -580,8 +647,7 @@
"node_modules/estree-walker": { "node_modules/estree-walker": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
"dev": true
}, },
"node_modules/fast-glob": { "node_modules/fast-glob": {
"version": "3.2.12", "version": "3.2.12",
@@ -1056,7 +1122,6 @@
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"engines": { "engines": {
"node": ">=8.6" "node": ">=8.6"
}, },
@@ -1171,7 +1236,7 @@
"version": "2.79.1", "version": "2.79.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
"integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
"dev": true, "devOptional": true,
"bin": { "bin": {
"rollup": "dist/bin/rollup" "rollup": "dist/bin/rollup"
}, },

View File

@@ -13,6 +13,7 @@
"@rollup/plugin-node-resolve": "^11.0.0", "@rollup/plugin-node-resolve": "^11.0.0",
"@rollup/plugin-typescript": "^8.0.0", "@rollup/plugin-typescript": "^8.0.0",
"@tsconfig/svelte": "^2.0.0", "@tsconfig/svelte": "^2.0.0",
"@types/node": "^18.11.18",
"rollup": "^2.3.4", "rollup": "^2.3.4",
"rollup-plugin-css-only": "^3.1.0", "rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-livereload": "^2.0.0", "rollup-plugin-livereload": "^2.0.0",
@@ -25,6 +26,8 @@
"typescript": "^4.0.0" "typescript": "^4.0.0"
}, },
"dependencies": { "dependencies": {
"@rollup/plugin-replace": "^5.0.2",
"dotenv": "^16.0.3",
"sirv-cli": "^2.0.0", "sirv-cli": "^2.0.0",
"socket.io-client": "^4.5.4", "socket.io-client": "^4.5.4",
"svelte-spa-router": "^3.3.0" "svelte-spa-router": "^3.3.0"

View File

@@ -1,33 +0,0 @@
header.svelte-7t4byu.svelte-7t4byu{overflow-y:hidden}.grid-container.svelte-7t4byu.svelte-7t4byu{position:absolute;left:0;top:0;box-sizing:border-box;width:100%;height:100%;white-space:nowrap;margin-bottom:0px;overflow:hidden;padding:20px 40px;margin:0px;display:grid;grid-template-columns:repeat(12, 1fr);grid-template-rows:1fr 1fr 1fr 1fr 1fr;align-items:center}header.svelte-7t4byu h1.svelte-7t4byu{grid-column:1 / 7;grid-row:1;padding:20px;border:1px solid bisque}header.svelte-7t4byu nav.svelte-7t4byu{grid-column:7 / 13;grid-row:1;justify-self:end;padding:20px;border:1px solid bisque}header.svelte-7t4byu h2.svelte-7t4byu{grid-row:3;grid-column:5 / span 4;justify-self:center;border:1px solid black;z-index:3}header.svelte-7t4byu h2 div.svelte-7t4byu{font-size:2em}nav.svelte-7t4byu div.svelte-7t4byu{display:inline;color:bisque;font-weight:bold}nav.svelte-7t4byu>div.svelte-7t4byu{padding-left:1em}nav.svelte-7t4byu div.svelte-7t4byu:hover{text-decoration:underline;cursor:pointer}main.svelte-1cznfcz.svelte-1cznfcz{text-align:center;padding-top:40px;padding-bottom:40px}form.svelte-1cznfcz.svelte-1cznfcz{padding-top:15px}form.svelte-1cznfcz input.svelte-1cznfcz{max-width:330px}.error.svelte-1cznfcz.svelte-1cznfcz{font-weight:bold;font-size:0.8em;color:red}div.wrapper.svelte-1q8uute{display:flexbox;align-items:center}div.wrapper.svelte-1q8uute{display:flexbox;align-items:center}@font-face{font-family:"Bit5x3";src:url("/fonts/Bit5x3.woff2") format("woff2"),
local("Bit5x3"),
url("/fonts/Bit5x3.woff") format("woff");font-weight:normal;font-style:normal;font-display:swap}#game_page.svelte-y455cj.svelte-y455cj{margin:0;background-color:#222425;position:relative;width:100%;height:100%}#canvas_container.svelte-y455cj.svelte-y455cj{margin-top:20px;text-align:center}#users_name.svelte-y455cj.svelte-y455cj{text-align:center;font-family:"Bit5x3";color:rgb(245, 245, 245);font-size:x-large}#div_game.svelte-y455cj.svelte-y455cj{margin-top:20px;text-align:center;font-family:"Bit5x3";color:rgb(245, 245, 245);font-size:x-large}#error_notification.svelte-y455cj.svelte-y455cj{text-align:center;display:block;font-family:"Bit5x3";color:rgb(143, 19, 19);font-size:x-large}#div_game.svelte-y455cj fieldset.svelte-y455cj{max-width:50vw;width:auto;margin:0 auto}#div_game.svelte-y455cj fieldset div.svelte-y455cj{padding:10px}#pong_button.svelte-y455cj.svelte-y455cj{font-family:"Bit5x3";color:rgb(245, 245, 245);background-color:#333333;font-size:x-large;padding:10px}canvas.svelte-y455cj.svelte-y455cj{background-color:#333333;max-width:75vw;width:80%}canvas.svelte-1bstsd0{width:100%;height:100%;background-color:#666}@font-face{font-family:'Bondi';src:url('/fonts/Bondi.ttf.woff') format('woff'),
url('/fonts/Bondi.ttf.svg#Bondi') format('svg'),
url('/fonts/Bondi.ttf.eot'),
url('/fonts/Bondi.ttf.eot?#iefix') format('embedded-opentype');font-weight:normal;font-style:normal}header.svelte-1aisfio.svelte-1aisfio{background:#618174;margin:0}header.svelte-1aisfio.svelte-1aisfio{position:sticky;display:grid;grid-template-columns:1fr 1fr 1fr}h1.svelte-1aisfio.svelte-1aisfio{font-family:'Bondi'}h1.svelte-1aisfio.svelte-1aisfio{margin:0;text-align:left;display:flex;justify-self:center;align-self:center}img.svelte-1aisfio.svelte-1aisfio{cursor:pointer;max-width:40px;padding:7px 20px;justify-self:left}nav.svelte-1aisfio.svelte-1aisfio{display:flex;justify-content:right}nav.svelte-1aisfio button.svelte-1aisfio{margin:7px 20px;border-radius:4px}div.outer.svelte-1tyjf3q{max-width:960px;margin:40px auto}:root{--purple:rgb(123, 31, 162);--violet:rgb(103, 58, 183);--pink:rgb(244, 143, 177)}@keyframes svelte-1tyjf3q-background-pan{from{background-position:0% center}to{background-position:-200% center}}@keyframes svelte-1tyjf3q-scale{from,to{transform:scale(0)}50%{transform:scale(1)}}@keyframes svelte-1tyjf3q-rotate{from{transform:rotate(0deg)}to{transform:rotate(180deg)}}main.svelte-qtbld7{text-align:center}div.cards.svelte-qtbld7{display:grid;grid-template-columns:1fr 1fr;grid-gap:20px}img.svelte-qtbld7{width:60px}form.svelte-qtbld7{text-align:center}.form-field.svelte-qtbld7{padding:10px}.label.svelte-qtbld7{font-weight:bold}.inline-check.svelte-qtbld7{display:inline}.error.svelte-qtbld7{font-size:0.8em;font-weight:bold;color:red}.success.svelte-qtbld7{font-size:0.8em;font-weight:bold;color:green}div.top-grid.svelte-55f7si{display:grid;grid-template-columns:repeat(12, 1fr);height:85vh}div.all-users-sidebar.svelte-55f7si{grid-column:1 / span 2;background:white}div.a-user.svelte-55f7si{display:inline-block}div.status.svelte-55f7si{font-size:0.6em;font-weight:bold}div[class^="a-user"].svelte-55f7si:hover{text-decoration:underline;font-weight:bold;cursor:pointer}div.main-display.svelte-55f7si{grid-column:3 / span 10}.error.svelte-55f7si{font-size:0.8em;font-weight:bold;color:red}div.outer.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{max-width:960px;margin:40px auto}main.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{max-width:960px;margin:40px auto;text-align:center}.avatar.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{max-width:150px}section.main-stats.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{max-width:600px;margin:40px auto;text-align:center;display:grid;grid-template-columns:repeat(3, 1fr);grid-template-rows:repeat(3, 1fr)}section.main-stats.svelte-16aefqu h4.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{grid-column:1 / span 3}div.username.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{font-size:1.5em;font-weight:bold;padding-bottom:5px}div.rank.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{font-size:1.2em;font-weight:bold}:root{--purple:rgb(123, 31, 162);--violet:rgb(103, 58, 183);--pink:rgb(244, 143, 177)}@keyframes svelte-16aefqu-background-pan{from{background-position:0% center}to{background-position:-200% center}}@keyframes svelte-16aefqu-scale{from,to{transform:scale(0)}50%{transform:scale(1)}}@keyframes svelte-16aefqu-rotate{from{transform:rotate(0deg)}to{transform:rotate(180deg)}}div.svelte-16aefqu>.glitter.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{display:inline-block;position:relative}div.svelte-16aefqu>.glitter.svelte-16aefqu>.glitter-star.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{--size:clamp(20px, 1.5vw, 30px);animation:svelte-16aefqu-scale 700ms ease forwards;display:block;height:var(--size);left:var(--star-left);position:absolute;top:var(--star-top);width:var(--size)}div.svelte-16aefqu>.glitter.svelte-16aefqu>.glitter-star.svelte-16aefqu>svg.svelte-16aefqu.svelte-16aefqu{animation:svelte-16aefqu-rotate 1000ms linear infinite;display:block;opacity:0.7}div.svelte-16aefqu>.glitter.svelte-16aefqu>.glitter-star.svelte-16aefqu>svg.svelte-16aefqu>path.svelte-16aefqu{fill:var(--violet)}div.svelte-16aefqu>.glitter.svelte-16aefqu>.glitter-text.svelte-16aefqu.svelte-16aefqu.svelte-16aefqu{animation:svelte-16aefqu-background-pan 3s linear infinite;background:linear-gradient(
to right,
var(--purple),
var(--violet),
var(--pink),
var(--purple)
);background-size:200%;-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;color:transparent;white-space:nowrap}.card.svelte-8smyff{background:white;padding:20px;border-radius:6px;box-shadow:0px 2px 4px rgba(0,0,0,0.1)}button.svelte-1u0z9cq{border:0;cursor:pointer;border-radius:6px;padding:8px 12px;font-weight:bold;box-shadow:1px 2px 3px rgba(0,0,0,0.2)}.primary.svelte-1u0z9cq{background:#d91b42;color:white}.secondary.svelte-1u0z9cq{background:#45c496;color:white}.flat.svelte-1u0z9cq{box-shadow:none}.primary.inverse.svelte-1u0z9cq{color:#d91b42;background:white;border:2px solid #d91b42}.secondary.inverse.svelte-1u0z9cq{color:#45c496;background:white;border:2px solid #45c496}.chat_box.svelte-6ej1tr{display:flex;position:fixed;bottom:20px;right:20px;padding:0px;width:auto;height:auto;border:1px solid black;z-index:1}.chat_box.svelte-6ej1tr *{-ms-overflow-style:none;scrollbar-width:none}.chat_box.svelte-6ej1tr *::-webkit-scrollbar{display:none}.chat_box.svelte-6ej1tr .grid_box{display:grid;margin:5px;gap:5px;width:300px;height:400px}.chat_box.svelte-6ej1tr .grid_box *{display:flex;flex-direction:column;position:relative;box-sizing:border-box}.chat_box.svelte-6ej1tr .grid_box p{padding:10px;font-size:15px}.chat_box.svelte-6ej1tr .panel{overflow-y:scroll}.chat_box.svelte-6ej1tr .panel > *{margin-top:10px;margin-bottom:10px}.chat_box.svelte-6ej1tr .__show_if_only_child{display:none}.chat_box.svelte-6ej1tr .__show_if_only_child:only-child{display:flex;color:rgb(100, 100, 100)}.chat_box.svelte-6ej1tr .__center{margin-left:auto;margin-right:auto}.chat_box.svelte-6ej1tr .__border_top{border-top:1px solid black}.chat_box.svelte-6ej1tr .__check_change_next:checked ~ .__to_show{display:flex}.chat_box.svelte-6ej1tr .__check_change_next:checked ~ .__to_block,.chat_box.svelte-6ej1tr .__check_change_next:checked ~ .__to_block *{pointer-events:none;color:rgb(100, 100, 100)}.chat_box.svelte-6ej1tr .__to_show{display:none}.grid_box.svelte-fc4a40 .chat{grid-area:chat}.grid_box.svelte-fc4a40{gap:0px;grid:' chat ' auto
/ auto }.chat_box.close .grid_box.svelte-fc4a40{margin:0px;width:auto;height:auto}.grid_box.svelte-1jygwt2 .settings {grid-area:settings}.grid_box.svelte-1jygwt2 .close {grid-area:close}.grid_box.svelte-1jygwt2 .new {grid-area:new}.grid_box.svelte-1jygwt2 .panel_home{grid-area:panel_home}.grid_box.svelte-1jygwt2.svelte-1jygwt2{grid:' settings new close ' auto
' panel_home panel_home panel_home ' 1fr
/ auto 1fr auto }.panel_home.svelte-1jygwt2 p.title.svelte-1jygwt2{margin:10px auto 0px auto}.grid_box.svelte-1quyp80 .back {grid-area:back}.grid_box.svelte-1quyp80 .room_name {grid-area:room_name}.grid_box.svelte-1quyp80 .close {grid-area:close}.grid_box.svelte-1quyp80 .panel_msg {grid-area:panel_msg}.grid_box.svelte-1quyp80 .send {grid-area:send}.grid_box.svelte-1quyp80 .panel_write{grid-area:panel_write}.grid_box.svelte-1quyp80.svelte-1quyp80{grid:' back room_name room_name close ' auto
' panel_msg panel_msg panel_msg panel_msg ' 1fr
' panel_write panel_write send send ' auto
/ auto 1fr auto auto }.grid_box.svelte-1quyp80 .panel_write.svelte-1quyp80{border:none;overflow:visible}.grid_box.svelte-1quyp80 .text_area.svelte-1quyp80{display:block;position:absolute;bottom:0px;left:0px;width:100%;height:100%;overflow-x:hidden;overflow-y:scroll;background-color:white;border:1px solid black}.grid_box.svelte-1quyp80 .text_area.svelte-1quyp80:focus{height:auto;min-height:100%;max-height:300px}.grid_box.svelte-1quyp80 .panel_write .text_area.svelte-1quyp80 *{display:block ruby}.grid_box.svelte-1quyp80 .panel_msg.svelte-1quyp80{flex-direction:column-reverse;border:1px solid black}.grid_box.svelte-1quyp80 .msg_thread.svelte-1quyp80{width:100%;padding:0px 5px}.grid_box.svelte-1b4c0qx .back {grid-area:back}.grid_box.svelte-1b4c0qx .new {grid-area:new}.grid_box.svelte-1b4c0qx .close {grid-area:close}.grid_box.svelte-1b4c0qx .panel_new{grid-area:panel_new}.grid_box.svelte-1b4c0qx{grid:' back new close ' auto
' panel_new panel_new panel_new ' 1fr
/ auto 1fr auto }.grid_box.svelte-1lfmc2m .back {grid-area:back}.grid_box.svelte-1lfmc2m .settings {grid-area:settings}.grid_box.svelte-1lfmc2m .close {grid-area:close}.grid_box.svelte-1lfmc2m .panel_settings{grid-area:panel_settings}.grid_box.svelte-1lfmc2m{grid:' back settings close ' auto
' panel_settings panel_settings panel_settings ' 1fr
/ auto 1fr auto }.grid_box.svelte-1sv7l8q .back {grid-area:back}.grid_box.svelte-1sv7l8q .room_name {grid-area:room_name}.grid_box.svelte-1sv7l8q .close {grid-area:close}.grid_box.svelte-1sv7l8q .panel_room_set{grid-area:panel_room_set}.grid_box.svelte-1sv7l8q{grid:' back room_name close ' auto
' panel_room_set panel_room_set panel_room_set ' 1fr
/ auto 1fr auto }.grid_box.svelte-2tekts .back {grid-area:back}.grid_box.svelte-2tekts .room_name {grid-area:room_name}.grid_box.svelte-2tekts .close {grid-area:close}.grid_box.svelte-2tekts .panel_protected{grid-area:panel_protected}.grid_box.svelte-2tekts.svelte-2tekts{grid:' back room_name close ' auto
' panel_protected panel_protected panel_protected ' 1fr
/ auto 1fr auto }form.svelte-2tekts input[type=submit].svelte-2tekts{margin-top:20px}.grid_box.svelte-1cmnkcw .back {grid-area:back}.grid_box.svelte-1cmnkcw .create {grid-area:create}.grid_box.svelte-1cmnkcw .close {grid-area:close}.grid_box.svelte-1cmnkcw .panel_create{grid-area:panel_create}.grid_box.svelte-1cmnkcw.svelte-1cmnkcw.svelte-1cmnkcw{grid:' back create close ' auto
' panel_create panel_create panel_create ' 1fr
/ auto 1fr auto }form.svelte-1cmnkcw input[type=radio].svelte-1cmnkcw.svelte-1cmnkcw{display:none}form.svelte-1cmnkcw label._radio.svelte-1cmnkcw.svelte-1cmnkcw{margin:0px 20px 0px auto;padding-right:10px;cursor:pointer}form.svelte-1cmnkcw label._radio p.svelte-1cmnkcw.svelte-1cmnkcw{margin-top:0px;margin-bottom:0px}form.svelte-1cmnkcw label._radio.svelte-1cmnkcw.svelte-1cmnkcw::after{content:"";position:absolute;top:calc(50% - 6px);right:0px;width:12px;height:12px;border-radius:6px;border:2px solid rgb(150, 150, 150);box-sizing:border-box;cursor:pointer}form.svelte-1cmnkcw input[type=radio].svelte-1cmnkcw:checked+label._radio.svelte-1cmnkcw::after{background-color:rgb(200, 200, 200)}form.svelte-1cmnkcw input[type=submit].svelte-1cmnkcw.svelte-1cmnkcw{margin-top:20px}.grid_box.svelte-yo0any .back {grid-area:back}.grid_box.svelte-yo0any .back {grid-area:back}.grid_box.svelte-yo0any .user {grid-area:user}.grid_box.svelte-yo0any .close {grid-area:close}.grid_box.svelte-yo0any .panel_mute{grid-area:panel_mute}.grid_box.svelte-yo0any.svelte-yo0any.svelte-yo0any{grid:' back user close ' auto
' panel_mute panel_mute panel_mute ' 1fr
/ auto 1fr auto }form.svelte-yo0any input[type=checkbox].svelte-yo0any.svelte-yo0any{display:none}form.svelte-yo0any label._checkbox.svelte-yo0any.svelte-yo0any{margin:0px auto 0px 10px;padding-left:10px;cursor:pointer}form.svelte-yo0any label._checkbox.svelte-yo0any.svelte-yo0any::after{content:"";position:absolute;top:calc(50% - 6px);left:0px;width:12px;height:12px;border:2px solid rgb(150, 150, 150);box-sizing:border-box;cursor:pointer}form.svelte-yo0any input[type=checkbox].svelte-yo0any:checked+label._checkbox.svelte-yo0any::after{background-color:rgb(200, 200, 200)}form.svelte-yo0any label._select.svelte-yo0any.svelte-yo0any{flex-direction:row}form.svelte-yo0any label._select p.svelte-yo0any.svelte-yo0any{margin:0px}form.svelte-yo0any select.svelte-yo0any.svelte-yo0any{margin:auto auto auto 10px;background-color:rgb(220, 220, 220);border:none;padding:5px;cursor:pointer}form.svelte-yo0any select.svelte-yo0any.svelte-yo0any:hover{background-color:rgb(200, 200, 200)}form.svelte-yo0any input[type=submit].svelte-yo0any.svelte-yo0any{margin-top:20px}.grid_box.svelte-1fj8iha .back {grid-area:back}.grid_box.svelte-1fj8iha .user {grid-area:user}.grid_box.svelte-1fj8iha .close {grid-area:close}.grid_box.svelte-1fj8iha .room_name {grid-area:room_name}.grid_box.svelte-1fj8iha .panel_user{grid-area:panel_user}.grid_box.svelte-1fj8iha{grid:' back user close ' auto
' room_name room_name room_name ' auto
' panel_user panel_user panel_user ' 1fr
/ auto 1fr auto }.panel_user.svelte-1fj8iha{margin-top:-5px}button.svelte-b72wpv.svelte-b72wpv{padding:0px;margin:auto;width:100%;cursor:pointer;outline:none;border:none;background-color:rgb(220, 220, 220)}button.svelte-b72wpv p.svelte-b72wpv{width:100%;margin:auto;text-align:center}button.svelte-b72wpv.svelte-b72wpv:hover{background-color:rgb(200, 200, 200)}button.svelte-b72wpv.svelte-b72wpv:active{background-color:rgb(190, 190, 190)}.list.svelte-b72wpv.svelte-b72wpv:not(:hover){background-color:rgb(240, 240, 240)}.list.svelte-b72wpv p.svelte-b72wpv{text-align:left}.transparent.svelte-b72wpv.svelte-b72wpv:not(:hover){background-color:transparent}.deactivate.svelte-b72wpv.svelte-b72wpv{background-color:transparent;pointer-events:none}.icon.svelte-b72wpv p.svelte-b72wpv{display:none}.icon.svelte-b72wpv.svelte-b72wpv:not(:hover){background-color:transparent}.icon.svelte-b72wpv.svelte-b72wpv{width:30px;height:100%;padding:0px}.dots.svelte-b72wpv.svelte-b72wpv::after{content:'\2807';font-size:20px;position:absolute;top:50%;left:0px;width:100%;height:auto;text-align:center;transform:translateY(-50%);cursor:pointer}.close.svelte-b72wpv.svelte-b72wpv::before{content:"";position:absolute;top:calc(50% - 1px);left:5px;width:20px;height:2px;background-color:black}.back.svelte-b72wpv.svelte-b72wpv::before{content:"";position:absolute;top:calc(50% - 6px - 1px);left:6px;width:14px;height:14px;border-left:1px solid black;border-bottom:1px solid black;transform:rotate(45deg)}.blocked.svelte-b72wpv.svelte-b72wpv{padding-left:30px}.blocked.svelte-b72wpv.svelte-b72wpv::before{content:"";position:absolute;top:calc(50% - 2px);left:10px;cursor:pointer;width:13px;height:10px;border-radius:2px;background-color:rgb(110, 110, 110)}.blocked.svelte-b72wpv.svelte-b72wpv::after{content:"";position:absolute;top:calc(50% - 9px);left:12px;cursor:pointer;width:9px;height:13px;border-radius:5px;box-sizing:border-box;border:3px solid rgb(110, 110, 110)}.chat_msg.svelte-14xxpbz.svelte-14xxpbz{margin:5px auto;padding:5px;border-radius:5px}.chat_msg.svelte-14xxpbz.svelte-14xxpbz{margin-left:0px;background-color:rgb(210, 210, 210);max-width:80%}.chat_msg.svelte-14xxpbz p.svelte-14xxpbz{padding:0px}.chat_msg.svelte-14xxpbz p.name.svelte-14xxpbz{margin:0px;font-size:12px;color:rgb(100, 100, 100)}.chat_msg.svelte-14xxpbz p.msg.svelte-14xxpbz{margin:5px 0px}.chat_msg.svelte-14xxpbz p.msg.svelte-14xxpbz *{display:inline}.chat_msg.me.svelte-14xxpbz.svelte-14xxpbz{margin-right:0px;margin-left:auto;background-color:rgb(210, 110, 10)}.chat_msg.me.svelte-14xxpbz p.name.svelte-14xxpbz{display:none}.chat_msg.SERVER.svelte-14xxpbz.svelte-14xxpbz{margin-left:auto;background-color:transparent}.chat_msg.SERVER.svelte-14xxpbz p.name.svelte-14xxpbz{display:none}.chat_msg.SERVER.svelte-14xxpbz p.msg.svelte-14xxpbz{margin:0px auto;font-size:12px;color:rgb(100, 100, 100)}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -6,8 +6,13 @@ import { terser } from 'rollup-plugin-terser';
import sveltePreprocess from 'svelte-preprocess'; import sveltePreprocess from 'svelte-preprocess';
import typescript from '@rollup/plugin-typescript'; import typescript from '@rollup/plugin-typescript';
import css from 'rollup-plugin-css-only'; import css from 'rollup-plugin-css-only';
import replace from '@rollup/plugin-replace';
import dotenv from 'dotenv';
const production = !process.env.ROLLUP_WATCH; const production = !process.env.ROLLUP_WATCH;
dotenv.config();
function serve() { function serve() {
let server; let server;
@@ -30,6 +35,7 @@ function serve() {
}; };
} }
export default { export default {
input: 'src/main.ts', input: 'src/main.ts',
output: { output: {
@@ -46,6 +52,10 @@ export default {
dev: !production dev: !production
} }
}), }),
replace({
'process.env.WEBSITE_HOST': `'${process.env.WEBSITE_HOST}'`,
'process.env.WEBSITE_PORT': `'${process.env.WEBSITE_PORT}'`,
}),
// we'll extract any component CSS out into // we'll extract any component CSS out into
// a separate file - better for performance // a separate file - better for performance
css({ output: 'bundle.css' }), css({ output: 'bundle.css' }),

View File

@@ -1,5 +0,0 @@
<script context="module">
export const Domain = "transcendance";
export const Port = "8080";
export const PortIo = "8080";
</script>

View File

@@ -1,4 +1,7 @@
import App from './App.svelte'; import App from './App.svelte';
import dotenv from 'dotenv';
dotenv.config();
const app = new App({ const app = new App({
target: document.body, target: document.body,
props: { props: {

View File

@@ -1,35 +0,0 @@
<script lang="ts">
import Header from '../pieces/Header.svelte';
import MatchListElem from "../pieces/MatchListElem.svelte";
let arr = [
{
id: "match-01",
playerOneUsername: "toto",
playerTwoUsername: "bruno",
},
{
id: "match-02",
playerOneUsername: "bertand",
playerTwoUsername: "cassandre",
},
{
id: "match-03",
playerOneUsername: "madeleine",
playerTwoUsername: "jack",
},
];
</script>
<!-- -->
<Header/>
<menu>
{#each arr as match}
<MatchListElem match={match}/>
{/each}
</menu>
<!-- -->
<style>
</style>

View File

@@ -2,14 +2,12 @@
import Canvas from "../pieces/Canvas.svelte"; import Canvas from "../pieces/Canvas.svelte";
import { push } from "svelte-spa-router"; import { push } from "svelte-spa-router";
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { get } from "svelte/store";
import { Domain, Port } from "../Constantes.svelte";
let user; let user;
onMount(async () => { onMount(async () => {
user = await fetch(`http://${Domain}:${Port}/api/v2/user`) user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
.then((resp) => resp.json()) .then((resp) => resp.json())
// i mean i could do a failed to load user or some shit, maybe with a .catch or something? but atm why bother // i mean i could do a failed to load user or some shit, maybe with a .catch or something? but atm why bother
@@ -33,14 +31,14 @@
}); });
const login = async() => { const login = async() => {
window.location.href = `http://${Domain}:${Port}/api/v2/auth`; window.location.href = `http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/auth`;
console.log('you are now logged in'); console.log('you are now logged in');
} }
// i could prolly put this in it's own compoent, i seem to use it in several places... or maybe just some JS? like no need for html // i could prolly put this in it's own compoent, i seem to use it in several places... or maybe just some JS? like no need for html
// we could .then( () => replace('/') ) need the func so TS compatible... // we could .then( () => replace('/') ) need the func so TS compatible...
const logout = async() => { const logout = async() => {
await fetch(`http://${Domain}:${Port}/api/v2/auth/logout`, { await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/auth/logout`, {
method: 'POST', method: 'POST',
}); });
user = undefined; user = undefined;

View File

@@ -1,26 +1,14 @@
<script lang="ts"> <script lang="ts">
import { onMount } from "svelte"; import { onMount } from "svelte";
import { push } from "svelte-spa-router"; import { push } from "svelte-spa-router";
import { Domain, Port } from "../Constantes.svelte";
// onMount( async() => {
// await fetch(`http://${Domain}:${Port}/api/v2/auth/2fa/generate`,
// {
// method: 'POST',
// })
// .then(response => {return response.blob()})
// .then(blob => {
// const url = URL.createObjectURL(blob);
// qrCodeImg = url;
// });
// });
let qrCodeImg; let qrCodeImg;
let qrCode = ""; let qrCode = "";
let wrongCode = ""; let wrongCode = "";
const fetchQrCodeImg = (async() => { const fetchQrCodeImg = (async() => {
await fetch(`http://${Domain}:${Port}/api/v2/auth/2fa/generate`, await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/auth/2fa/generate`,
{ {
method: 'POST', method: 'POST',
}) })
@@ -32,7 +20,7 @@
})() })()
const submitCode = async() => { const submitCode = async() => {
const response = await fetch(`http://${Domain}:${Port}/api/v2/auth/2fa/check`, const response = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/auth/2fa/check`,
{ {
method : 'POST', method : 'POST',
headers : { headers : {

View File

@@ -3,12 +3,10 @@
import { onMount, onDestroy } from "svelte"; import { onMount, onDestroy } from "svelte";
import Header from '../../pieces/Header.svelte'; import Header from '../../pieces/Header.svelte';
import { fade, fly } from 'svelte/transition'; import { fade, fly } from 'svelte/transition';
import { Domain, Port } from "../../Constantes.svelte";
import * as pong from "./client/pong"; import * as pong from "./client/pong";
import { gameState } from "./client/ws";
// Pour Chérif: variables indiquant l'état du match
import { matchEnded, matchAbort } from "./client/ws";
//user's stuff //user's stuff
let user; let user;
@@ -37,39 +35,25 @@
let idOfIntevalCheckTerminationOfTheMatch; let idOfIntevalCheckTerminationOfTheMatch;
onMount( async() => { onMount( async() => {
user = await fetch(`http://${Domain}:${Port}/api/v2/user`) user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
.then( x => x.json() ); .then( x => x.json() );
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/user/all`) allUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/all`)
.then( x => x.json() ); .then( x => x.json() );
options.playerOneUsername = user.username; options.playerOneUsername = user.username;
}) })
onDestroy( async() => { onDestroy( async() => {
options.playerOneUsername = user.username;
showError = false;
showMatchEnded = false;
optionsAreNotSet = true
options.playerTwoUsername = "";
options.isSomeoneIsInvited = false;
options.isInvitedPerson = false;
options.moving_walls = false;
options.multi_balls = false;
errorMessageWhenAttemptingToGetATicket = "";
hiddenGame = true;
isThereAnyInvitation = false;
invitations = [];
pong.destroy();
clearInterval(idOfIntevalCheckTerminationOfTheMatch); clearInterval(idOfIntevalCheckTerminationOfTheMatch);
pong.destroy();
}) })
const initGame = async() => const initGame = async() =>
{ {
optionsAreNotSet = false; optionsAreNotSet = false;
showWaitPage = true; showWaitPage = true;
idOfIntevalCheckTerminationOfTheMatch = setInterval(matchTermitation, 1000);
const matchOptions = pong.computeMatchOptions(options); const matchOptions = pong.computeMatchOptions(options);
const responseWhenGrantToken = fetch(`http://${Domain}:${Port}/api/v2/game/ticket`, { const responseWhenGrantToken = fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/ticket`, {
method : "POST", method : "POST",
headers : {'Content-Type': 'application/json'}, headers : {'Content-Type': 'application/json'},
body : JSON.stringify({ body : JSON.stringify({
@@ -88,40 +72,36 @@
{ {
console.log(responseInjson) console.log(responseInjson)
console.log("On refuse le ticket"); console.log("On refuse le ticket");
clearInterval(idOfIntevalCheckTerminationOfTheMatch);
errorMessageWhenAttemptingToGetATicket = responseInjson.message; errorMessageWhenAttemptingToGetATicket = responseInjson.message;
showError = true; showError = true;
options.playerTwoUsername = ""; options.reset();
options.playerOneUsername = user.username; options.playerOneUsername = user.username;
options.isSomeoneIsInvited = false;
options.isInvitedPerson = false;
options.moving_walls = false;
options.multi_balls = false;
setTimeout(() => { setTimeout(() => {
showError = false;
showWaitPage = false
optionsAreNotSet = true optionsAreNotSet = true
showError = false;
// showWaitPage = false // ???
}, 5000); }, 5000);
} }
else if (token) else if (token)
{ {
options.isInvitedPerson = false idOfIntevalCheckTerminationOfTheMatch = setInterval(matchTermitation, 1000);
// options.isInvitedPerson = false // ???
pong.init(options, gameAreaId, token); pong.init(options, gameAreaId, token);
hiddenGame = false; hiddenGame = false;
} }
// TODO: Un "else" peut-être ? Si pas de token on fait un truc ?
// Si on ne rentre pas dans le else if, du coup il ne se passe rien.
} }
// Pour Cherif: renommer en un truc du genre "initGameForInvitedPlayer" ? const initGameForInvitedPlayer = async(invitation : any) =>
const initGameForPrivateParty = async(invitation : any) =>
{ {
idOfIntevalCheckTerminationOfTheMatch = setInterval(matchTermitation, 1000);
optionsAreNotSet = false optionsAreNotSet = false
showWaitPage = true showWaitPage = true
console.log("invitation : ") console.log("invitation : ")
console.log(invitation) console.log(invitation)
if (invitation.token) if (invitation.token)
{ {
idOfIntevalCheckTerminationOfTheMatch = setInterval(matchTermitation, 1000);
options.playerOneUsername = invitation.playerOneUsername; options.playerOneUsername = invitation.playerOneUsername;
options.playerTwoUsername = invitation.playerTwoUsername; options.playerTwoUsername = invitation.playerTwoUsername;
options.isSomeoneIsInvited = true; options.isSomeoneIsInvited = true;
@@ -134,32 +114,20 @@
const matchTermitation = () => { const matchTermitation = () => {
console.log("Ping matchTermitation") console.log("Ping matchTermitation")
if (matchAbort || matchEnded) if (gameState.matchAbort || gameState.matchEnded)
{ {
clearInterval(idOfIntevalCheckTerminationOfTheMatch); clearInterval(idOfIntevalCheckTerminationOfTheMatch);
console.log("matchTermitation was called") console.log("matchTermitation was called")
showWaitPage = false showWaitPage = false
matchAbort ? gameState.matchAbort ?
errorMessageWhenAttemptingToGetATicket = "The match has been aborted" errorMessageWhenAttemptingToGetATicket = "The match has been aborted"
: errorMessageWhenAttemptingToGetATicket = "The match is finished !" : errorMessageWhenAttemptingToGetATicket = "The match is finished !"
matchAbort ? showError = true : showMatchEnded = true; gameState.matchAbort ? showError = true : showMatchEnded = true;
setTimeout(() => { setTimeout(() => {
hiddenGame = true; resetPage();
showError = false;
showMatchEnded = false;
optionsAreNotSet = true
options.playerTwoUsername = "";
options.playerOneUsername = user.username;
options.isSomeoneIsInvited = false;
options.isInvitedPerson = false;
options.moving_walls = false;
options.multi_balls = false;
errorMessageWhenAttemptingToGetATicket = ""; errorMessageWhenAttemptingToGetATicket = "";
options.playerTwoUsername = "";
hiddenGame = true;
isThereAnyInvitation = false; isThereAnyInvitation = false;
invitations = []; invitations = []; // ???
pong.destroy();
console.log("matchTermitation : setTimeout") console.log("matchTermitation : setTimeout")
}, 5000); }, 5000);
} }
@@ -174,13 +142,13 @@
const showInvitation = async() => { const showInvitation = async() => {
showGameOption = false; showGameOption = false;
showInvitations = true; showInvitations = true;
invitations = await fetch(`http://${Domain}:${Port}/api/v2/game/invitations`) invitations = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/invitations`)
.then(x => x.json()) .then(x => x.json())
invitations.length !== 0 ? isThereAnyInvitation = true : isThereAnyInvitation = false invitations.length !== 0 ? isThereAnyInvitation = true : isThereAnyInvitation = false
} }
const rejectInvitation = async(invitation) => { const rejectInvitation = async(invitation) => {
await fetch(`http://${Domain}:${Port}/api/v2/game/decline`, { await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/decline`, {
method: "POST", method: "POST",
headers: { 'Content-Type': 'application/json'}, headers: { 'Content-Type': 'application/json'},
body: JSON.stringify({ body: JSON.stringify({
@@ -193,7 +161,7 @@
} }
const acceptInvitation = async(invitation : any) => { const acceptInvitation = async(invitation : any) => {
const res = await fetch(`http://${Domain}:${Port}/api/v2/game/accept`, { const res = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/accept`, {
method: "POST", method: "POST",
headers: { 'Content-Type': 'application/json'}, headers: { 'Content-Type': 'application/json'},
body: JSON.stringify({ body: JSON.stringify({
@@ -207,12 +175,27 @@
if (res.status === 200) if (res.status === 200)
{ {
showInvitation() showInvitation()
initGameForPrivateParty(invitation) initGameForInvitedPlayer(invitation)
} }
//Au final c'est utile ! //Au final c'est utile !
initGameForPrivateParty(invitation) initGameForInvitedPlayer(invitation) // Luke: normal de initGameForInvitedPlayer() sur un "res.status" different de 200 ?
} }
function leaveMatch() {
resetPage();
};
function resetPage() {
hiddenGame = true;
optionsAreNotSet = true
showError = false;
showMatchEnded = false;
options.reset();
options.playerOneUsername = user.username;
pong.destroy();
};
</script> </script>
<Header /> <Header />
@@ -233,9 +216,16 @@
</fieldset> </fieldset>
</div> </div>
{/if} {/if}
<div id="canvas_container" hidden={hiddenGame}> <div id="canvas_container" hidden={hiddenGame}>
<canvas id={gameAreaId}/> <canvas id={gameAreaId}/>
</div> </div>
{#if !hiddenGame}
<div id="div_game">
<button id="pong_button" on:click={leaveMatch}>forfeit</button>
</div>
{/if}
{#if showWaitPage === true} {#if showWaitPage === true}
<div id="div_game" in:fly="{{ y: 10, duration: 1000 }}"> <div id="div_game" in:fly="{{ y: 10, duration: 1000 }}">
@@ -251,7 +241,6 @@
{#if optionsAreNotSet} {#if optionsAreNotSet}
{#if showGameOption === true} {#if showGameOption === true}
<div id="game_option"> <div id="game_option">
<form on:submit|preventDefault={() => initGame()}>
<div id="div_game"> <div id="div_game">
<button id="pong_button" on:click={showInvitation}>Show invitations</button> <button id="pong_button" on:click={showInvitation}>Show invitations</button>
<fieldset> <fieldset>
@@ -283,12 +272,10 @@
</select> </select>
{/if} {/if}
<div> <div>
<button id="pong_button" >PLAY</button> <button id="pong_button" on:click={initGame}>PLAY</button>
</div> </div>
</fieldset> </fieldset>
</div> </div>
</form>
</div> </div>
{/if} {/if}
@@ -344,12 +331,12 @@
/* max-height: 80vh; */ /* max-height: 80vh; */
/* overflow: hidden; */ /* overflow: hidden; */
} }
canvas {
#users_name { /* background-color: #ff0000; */
text-align: center; background-color: #333333;
font-family: "Bit5x3"; max-width: 75vw;
color: rgb(245, 245, 245); /* max-height: 100vh; */
font-size: x-large; width: 80%;
} }
#div_game { #div_game {
@@ -359,15 +346,6 @@
color: rgb(245, 245, 245); color: rgb(245, 245, 245);
font-size: x-large; font-size: x-large;
} }
#error_notification {
text-align: center;
display: block;
font-family: "Bit5x3";
color: rgb(143, 19, 19);
font-size: x-large;
}
#div_game fieldset { #div_game fieldset {
max-width: 50vw; max-width: 50vw;
width: auto; width: auto;
@@ -383,12 +361,19 @@
font-size: x-large; font-size: x-large;
padding: 10px; padding: 10px;
} }
canvas {
/* background-color: #ff0000; */ #users_name { /* UNUSED */
background-color: #333333; text-align: center;
max-width: 75vw; font-family: "Bit5x3";
/* max-height: 100vh; */ color: rgb(245, 245, 245);
width: 80%; font-size: x-large;
}
#error_notification { /* UNUSED */
text-align: center;
display: block;
font-family: "Bit5x3";
color: rgb(143, 19, 19);
font-size: x-large;
} }
</style> </style>

View File

@@ -2,13 +2,13 @@
<script lang="ts"> <script lang="ts">
import { onMount, onDestroy } from "svelte"; import { onMount, onDestroy } from "svelte";
import Header from '../../pieces/Header.svelte'; import Header from '../../pieces/Header.svelte';
import MatchListElem from "../../pieces/MatchListElem.svelte";
import { fade, fly } from 'svelte/transition'; import { fade, fly } from 'svelte/transition';
import { Domain, Port } from "../../Constantes.svelte";
import * as pongSpectator from "./client/pongSpectator"; import * as pongSpectator from "./client/pongSpectator";
import { gameState } from "./client/ws";
// Pour Chérif: variables indiquant l'état du match import { gameSessionIdPLACEHOLDER } from "./shared_js/constants";
import { matchEnded, matchAbort } from "./client/ws";
//user's stuff //user's stuff
let user; let user;
@@ -16,30 +16,82 @@
//Game's stuff client side only //Game's stuff client side only
const gameAreaId = "game_area"; const gameAreaId = "game_area";
let sound = "off";
// const dummyMatchList = [
// {
// gameSessionId: gameSessionIdPLACEHOLDER,
// matchOptions: pongSpectator.MatchOptions.noOption,
// playerOneUsername: "toto",
// playerTwoUsername: "bruno",
// },
// {
// gameSessionId: gameSessionIdPLACEHOLDER,
// matchOptions: pongSpectator.MatchOptions.multiBalls,
// playerOneUsername: "pl1",
// playerTwoUsername: "pl2",
// },
// {
// gameSessionId: "id6543",
// matchOptions: pongSpectator.MatchOptions.movingWalls | pongSpectator.MatchOptions.multiBalls,
// playerOneUsername: "bertand",
// playerTwoUsername: "cassandre",
// },
// {
// gameSessionId: "id3452",
// matchOptions: pongSpectator.MatchOptions.multiBalls,
// playerOneUsername: "madeleine",
// playerTwoUsername: "jack",
// },
// ];
let matchList = [];
//html boolean for pages //html boolean for pages
let hiddenGame = true; let hiddenGame = true;
let hiddenMatchList = false;
onMount( async() => { onMount( async() => {
user = await fetch(`http://${Domain}:${Port}/api/v2/user`) user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
.then( x => x.json() ); .then( x => x.json() );
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/user/all`) allUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/all`)
.then( x => x.json() ); .then( x => x.json() );
// WIP: fetch for match list here
const responseForMatchList = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/match/all`)
const jsonForMatchList = await responseForMatchList.json();
matchList = jsonForMatchList;
console.log("matchList");
if (matchList.length <= 0)
hiddenMatchList = true;
console.log(matchList);
}) })
onDestroy( async() => { onDestroy( async() => {
pongSpectator.destroy(); pongSpectator.destroy();
}) })
const initGameSpectator = async() => { async function initGameSpectator(gameSessionId: string, matchOptions: pongSpectator.MatchOptions) {
let gameSessionId = "ID_PLACEHOLDER"; // PLACEHOLDER
let matchOptions = 0; // PLACEHOLDER
let sound = "off"; // PLACEHOLDER
pongSpectator.init(matchOptions, sound, gameAreaId, gameSessionId); pongSpectator.init(matchOptions, sound, gameAreaId, gameSessionId);
hiddenGame = false; hiddenGame = false;
}; };
function leaveMatch() {
resetPage();
};
async function resetPage() {
hiddenGame = true;
pongSpectator.destroy();
// WIP: fetch for match list here
matchList = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/match/all`)
.then( x => x.json() );
console.log("matchList");
if (matchList.length <= 0)
hiddenMatchList = true;
console.log(matchList);
};
</script> </script>
<!-- -->
<Header /> <Header />
<!-- <div id="game_page"> Replacement for <body>. <!-- <div id="game_page"> Replacement for <body>.
@@ -50,7 +102,92 @@
<canvas id={gameAreaId}/> <canvas id={gameAreaId}/>
</div> </div>
{#if hiddenGame}
<div id="div_game">
<div id="game_options">
<fieldset>
{#if hiddenMatchList}
<legend>no match available</legend>
{:else}
<legend>options</legend>
<div>
<p>sound :</p>
<input type="radio" id="sound_on" name="sound_selector" bind:group={sound} value="on">
<label for="sound_on">on</label>
<input type="radio" id="sound_off" name="sound_selector" bind:group={sound} value="off">
<label for="sound_off">off</label>
</div>
<menu id="match_list">
{#each matchList as match}
<MatchListElem match={match} on:click={(e) => initGameSpectator(match.gameServerIdOfTheMatch, match.gameOptions)} />
{/each}
</menu>
{/if}
</fieldset>
</div>
</div>
{:else}
<div id="div_game">
<button id="pong_button" on:click={leaveMatch}>leave match</button>
</div>
{/if}
</div> <!-- div "game_page" --> </div> <!-- div "game_page" -->
<!-- -->
<style> <style>
@font-face {
font-family: "Bit5x3";
src:
url("/fonts/Bit5x3.woff2") format("woff2"),
local("Bit5x3"),
url("/fonts/Bit5x3.woff") format("woff");
font-weight: normal;
font-style: normal;
font-display: swap;
}
#game_page {
margin: 0;
background-color: #222425;
position: relative;
width: 100%;
height: 100%;
}
#canvas_container {
margin-top: 20px;
text-align: center;
}
canvas {
background-color: #333333;
max-width: 75vw;
width: 80%;
}
#div_game {
margin-top: 20px;
text-align: center;
font-family: "Bit5x3";
color: rgb(245, 245, 245);
font-size: x-large;
}
#div_game fieldset {
max-width: 50vw;
width: auto;
margin: 0 auto;
}
#div_game fieldset div {
padding: 10px;
}
#match_list {
font-family: 'Courier New', Courier, monospace;
font-size: large;
}
#pong_button {
font-family: "Bit5x3";
color: rgb(245, 245, 245);
background-color: #333333;
font-size: x-large;
padding: 10px;
}
</style> </style>

View File

@@ -2,16 +2,16 @@
<script lang="ts"> <script lang="ts">
import { onMount, onDestroy } from "svelte"; import { onMount, onDestroy } from "svelte";
import Header from "../../pieces/Header.svelte"; import Header from "../../pieces/Header.svelte";
import { Domain, Port } from "../../Constantes.svelte";
//user's stuff //user's stuff
let currentUser; let currentUser;
let allUsers = []; let allUsers = [];
let idInterval; let idInterval;
onMount( async() => { onMount( async() => {
currentUser = await fetch(`http://${Domain}:${Port}/api/v2/user`) currentUser = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
.then( x => x.json() ); .then( x => x.json() );
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/game/ranking`) allUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/ranking`)
.then( x => x.json() ); .then( x => x.json() );
idInterval = setInterval(fetchScores, 10000); idInterval = setInterval(fetchScores, 10000);
}) })
@@ -21,7 +21,7 @@
}) })
function fetchScores() { function fetchScores() {
fetch(`http://${Domain}:${Port}/api/v2/game/ranking`) fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/game/ranking`)
.then( x => x.json() ) .then( x => x.json() )
.then( x => allUsers = x ); .then( x => allUsers = x );
} }

View File

@@ -1,21 +1,27 @@
import * as c from "./constants.js" import * as c from "./constants.js"
export const soundPongArr: HTMLAudioElement[] = []; // export const soundPongArr: HTMLAudioElement[] = [];
export const soundRoblox = new Audio("http://transcendance:8080/sound/roblox-oof.ogg"); export const soundPongArr: HTMLAudioElement[] = [
new Audio("http://" + process.env.WEBSITE_HOST + ":" + process.env.WEBSITE_PORT + "/sound/pong/"+1+".ogg"),
new Audio("http://" + process.env.WEBSITE_HOST + ":" + process.env.WEBSITE_PORT + "/sound/pong/"+2+".ogg")
];
export const soundRoblox = new Audio("http://" + process.env.WEBSITE_HOST + ":" + process.env.WEBSITE_PORT + "/sound/roblox-oof.ogg");
export function initAudio(sound: string) export function initAudio(sound: string)
{ {
let muteFlag = true; let muteFlag: boolean;
if (sound === "on") { if (sound === "on") {
muteFlag = false; muteFlag = false;
} }
else {
for (let i = 0; i <= 32; i++) { muteFlag = true;
soundPongArr.push(new Audio("http://transcendance:8080/sound/pong/"+i+".ogg"));
soundPongArr[i].volume = c.soundPongVolume;
soundPongArr[i].muted = muteFlag;
} }
soundPongArr.forEach((value) => {
value.volume = c.soundRobloxVolume;
value.muted = muteFlag;
});
soundRoblox.volume = c.soundRobloxVolume; soundRoblox.volume = c.soundRobloxVolume;
soundRoblox.muted = muteFlag; soundRoblox.muted = muteFlag;
} }

View File

@@ -7,4 +7,13 @@ export class InitOptions {
isInvitedPerson = false; isInvitedPerson = false;
playerOneUsername = ""; playerOneUsername = "";
playerTwoUsername = ""; playerTwoUsername = "";
reset() {
this.sound = "off";
this.multi_balls = false;
this.moving_walls = false;
this.isSomeoneIsInvited = false;
this.isInvitedPerson = false;
this.playerOneUsername = "";
this.playerTwoUsername = "";
}
} }

View File

@@ -1,7 +1,8 @@
import * as c from "./constants.js"; import * as c from "./constants.js";
import * as en from "../shared_js/enums.js" import * as en from "../shared_js/enums.js"
import { gc, matchOptions, clientInfo, clientInfoSpectator} from "./global.js"; import { gc, matchOptions } from "./global.js";
import { clientInfo, clientInfoSpectator} from "./ws.js";
import { wallsMovements } from "../shared_js/wallsMovement.js"; import { wallsMovements } from "../shared_js/wallsMovement.js";
import type { RacketClient } from "./class/RectangleClient.js"; import type { RacketClient } from "./class/RectangleClient.js";
import type { VectorInteger } from "../shared_js/class/Vector.js"; import type { VectorInteger } from "../shared_js/class/Vector.js";

View File

@@ -3,27 +3,24 @@ import * as en from "../shared_js/enums.js";
import type { GameArea } from "./class/GameArea.js"; import type { GameArea } from "./class/GameArea.js";
import type { GameComponentsClient } from "./class/GameComponentsClient.js"; import type { GameComponentsClient } from "./class/GameComponentsClient.js";
// export {pong, gc, matchOptions} from "./pong.js"
export {socket, clientInfo, clientInfoSpectator} from "./ws.js"
export let pong: GameArea; export let pong: GameArea;
export let gc: GameComponentsClient; export let gc: GameComponentsClient;
export let matchOptions: en.MatchOptions = en.MatchOptions.noOption; export let matchOptions: en.MatchOptions = en.MatchOptions.noOption;
export function initPong(value: GameArea) { export function setPong(value: GameArea) {
pong = value; pong = value;
} }
export function initGc(value: GameComponentsClient) { export function setGc(value: GameComponentsClient) {
gc = value; gc = value;
} }
export function initMatchOptions(value: en.MatchOptions) { export function setMatchOptions(value: en.MatchOptions) {
matchOptions = value; matchOptions = value;
} }
export let startFunction: () => void; export let startFunction: () => void;
export function initStartFunction(value: () => void) { export function setStartFunction(value: () => void) {
startFunction = value; startFunction = value;
} }

View File

@@ -1,10 +1,10 @@
import { pong, gc, socket, clientInfo } from "./global.js" import { pong, gc } from "./global.js"
import { socket, clientInfo, gameState } from "./ws.js"
import * as ev from "../shared_js/class/Event.js" import * as ev from "../shared_js/class/Event.js"
import * as en from "../shared_js/enums.js" import * as en from "../shared_js/enums.js"
import { InputHistory } from "./class/InputHistory.js" import { InputHistory } from "./class/InputHistory.js"
import * as c from "./constants.js"; import * as c from "./constants.js";
import { matchEnded } from "./ws.js";
export let gridDisplay = false; export let gridDisplay = false;
@@ -44,7 +44,7 @@ export function handleInput()
playerMovements(delta_time, keys); playerMovements(delta_time, keys);
} }
if (!matchEnded) { if (!gameState.matchEnded) {
socket.send(JSON.stringify(inputState)); socket.send(JSON.stringify(inputState));
} }
// setTimeout(testInputDelay, 100); // setTimeout(testInputDelay, 100);

View File

@@ -3,12 +3,12 @@ import * as c from "./constants.js"
import * as en from "../shared_js/enums.js" import * as en from "../shared_js/enums.js"
import { GameArea } from "./class/GameArea.js"; import { GameArea } from "./class/GameArea.js";
import { GameComponentsClient } from "./class/GameComponentsClient.js"; import { GameComponentsClient } from "./class/GameComponentsClient.js";
import { socket } from "./ws.js"; import { socket, resetGameState } from "./ws.js";
import { initAudio } from "./audio.js"; import { initAudio } from "./audio.js";
import type { InitOptions } from "./class/InitOptions.js"; import type { InitOptions } from "./class/InitOptions.js";
import { pong } from "./global.js" import { pong } from "./global.js"
import { initPong, initGc, initMatchOptions } from "./global.js" import { setPong, setGc, setMatchOptions } from "./global.js"
export function computeMatchOptions(options: InitOptions) export function computeMatchOptions(options: InitOptions)
{ {
@@ -26,10 +26,10 @@ export function computeMatchOptions(options: InitOptions)
export function initBase(matchOptions: en.MatchOptions, sound: string, gameAreaId: string) export function initBase(matchOptions: en.MatchOptions, sound: string, gameAreaId: string)
{ {
initMatchOptions(matchOptions);
initAudio(sound); initAudio(sound);
initPong(new GameArea(gameAreaId)); setMatchOptions(matchOptions);
initGc(new GameComponentsClient(matchOptions, pong.ctx)); setPong(new GameArea(gameAreaId));
setGc(new GameComponentsClient(matchOptions, pong.ctx));
} }
export function destroyBase() export function destroyBase()
@@ -39,9 +39,10 @@ export function destroyBase()
clearInterval(pong.handleInputInterval); clearInterval(pong.handleInputInterval);
clearInterval(pong.gameLoopInterval); clearInterval(pong.gameLoopInterval);
clearInterval(pong.drawLoopInterval); clearInterval(pong.drawLoopInterval);
initPong(null); setPong(null);
} }
if (socket && socket.OPEN) { if (socket && socket.OPEN) {
socket.close(); socket.close();
} }
resetGameState();
} }

View File

@@ -12,15 +12,17 @@ export { computeMatchOptions } from "./init.js";
/* TODO: A way to delay the init of variables, but still use "const" not "let" ? */ /* TODO: A way to delay the init of variables, but still use "const" not "let" ? */
import { pong, gc } from "./global.js" import { pong, gc } from "./global.js"
import { initStartFunction } from "./global.js" import { setStartFunction } from "./global.js"
let abortControllerKeydown: AbortController;
let abortControllerKeyup: AbortController;
export function init(options: InitOptions, gameAreaId: string, token: string) export function init(options: InitOptions, gameAreaId: string, token: string)
{ {
const matchOptions = computeMatchOptions(options); const matchOptions = computeMatchOptions(options);
initBase(matchOptions, options.sound, gameAreaId); initBase(matchOptions, options.sound, gameAreaId);
initStartFunction(start); setStartFunction(start);
if (options.isSomeoneIsInvited) { if (options.isSomeoneIsInvited) {
initWebSocket(matchOptions, token, options.playerOneUsername, true, options.playerTwoUsername, options.isInvitedPerson); initWebSocket(matchOptions, token, options.playerOneUsername, true, options.playerTwoUsername, options.isInvitedPerson);
} }
@@ -32,6 +34,14 @@ export function init(options: InitOptions, gameAreaId: string, token: string)
export function destroy() export function destroy()
{ {
destroyBase(); destroyBase();
if (abortControllerKeydown) {
abortControllerKeydown.abort();
abortControllerKeydown = null;
}
if (abortControllerKeyup) {
abortControllerKeyup.abort();
abortControllerKeyup = null;
}
} }
function start() function start()
@@ -41,20 +51,40 @@ function start()
gc.text1.clear(); gc.text1.clear();
gc.text1.text = `${count}`; gc.text1.text = `${count}`;
gc.text1.update(); gc.text1.update();
}, resume); }, start_after_countdown);
}
function start_after_countdown()
{
abortControllerKeydown = new AbortController();
window.addEventListener(
'keydown',
(e) => { pong.addKey(e.key); },
{signal: abortControllerKeydown.signal}
);
abortControllerKeyup = new AbortController();
window.addEventListener(
'keyup',
(e) => { pong.deleteKey(e.key);},
{signal: abortControllerKeyup.signal}
);
resume();
} }
function resume() function resume()
{ {
gc.text1.text = ""; gc.text1.text = "";
window.addEventListener('keydown', function (e) {
pong.addKey(e.key);
});
window.addEventListener('keyup', function (e) {
pong.deleteKey(e.key);
});
pong.handleInputInterval = window.setInterval(handleInput, c.handleInputIntervalMS); pong.handleInputInterval = window.setInterval(handleInput, c.handleInputIntervalMS);
// pong.handleInputInterval = window.setInterval(sendLoop, c.sendLoopIntervalMS); // pong.handleInputInterval = window.setInterval(sendLoop, c.sendLoopIntervalMS);
pong.gameLoopInterval = window.setInterval(gameLoop, c.gameLoopIntervalMS); pong.gameLoopInterval = window.setInterval(gameLoop, c.gameLoopIntervalMS);
pong.drawLoopInterval = window.setInterval(drawLoop, c.drawLoopIntervalMS); pong.drawLoopInterval = window.setInterval(drawLoop, c.drawLoopIntervalMS);
} }
function pause() // unused
{
clearInterval(pong.handleInputInterval);
clearInterval(pong.gameLoopInterval);
clearInterval(pong.drawLoopInterval);
}

View File

@@ -6,17 +6,18 @@ import { drawLoop } from "./draw.js";
import { initWebSocketSpectator } from "./ws.js"; import { initWebSocketSpectator } from "./ws.js";
import { initBase, destroyBase, computeMatchOptions } from "./init.js"; import { initBase, destroyBase, computeMatchOptions } from "./init.js";
export { computeMatchOptions } from "./init.js"; export { computeMatchOptions } from "./init.js";
export { MatchOptions } from "../shared_js/enums.js"
/* TODO: A way to delay the init of variables, but still use "const" not "let" ? */ /* TODO: A way to delay the init of variables, but still use "const" not "let" ? */
import { pong, gc } from "./global.js" import { pong, gc } from "./global.js"
import { initStartFunction } from "./global.js" import { setStartFunction } from "./global.js"
export function init(matchOptions: en.MatchOptions, sound: string, gameAreaId: string, gameSessionId: string) export function init(matchOptions: en.MatchOptions, sound: string, gameAreaId: string, gameSessionId: string)
{ {
initBase(matchOptions, sound, gameAreaId); initBase(matchOptions, sound, gameAreaId);
initStartFunction(start); setStartFunction(start);
initWebSocketSpectator(gameSessionId); initWebSocketSpectator(gameSessionId);
} }
@@ -35,3 +36,9 @@ function resume()
pong.gameLoopInterval = window.setInterval(gameLoopSpectator, c.gameLoopIntervalMS); pong.gameLoopInterval = window.setInterval(gameLoopSpectator, c.gameLoopIntervalMS);
pong.drawLoopInterval = window.setInterval(drawLoop, c.drawLoopIntervalMS); pong.drawLoopInterval = window.setInterval(drawLoop, c.drawLoopIntervalMS);
} }
function pause() // unused
{
clearInterval(pong.gameLoopInterval);
clearInterval(pong.drawLoopInterval);
}

View File

@@ -10,8 +10,15 @@ import { soundRoblox } from "./audio.js"
import { sleep } from "./utils.js"; import { sleep } from "./utils.js";
import { Vector, VectorInteger } from "../shared_js/class/Vector.js"; import { Vector, VectorInteger } from "../shared_js/class/Vector.js";
export let matchEnded = false; export const gameState = {
export let matchAbort = false; matchEnded: false,
matchAbort: false
}
export function resetGameState() {
gameState.matchEnded = false;
gameState.matchAbort = false;
}
class ClientInfo { class ClientInfo {
id = ""; id = "";
@@ -28,7 +35,7 @@ class ClientInfoSpectator {
playerRightNextPos: VectorInteger; playerRightNextPos: VectorInteger;
} }
const wsUrl = "ws://transcendance:8080/pong"; const wsUrl = "ws://" + process.env.WEBSITE_HOST + ":" + process.env.WEBSITE_PORT + "/pong";
export let socket: WebSocket; /* TODO: A way to still use "const" not "let" ? */ export let socket: WebSocket; /* TODO: A way to still use "const" not "let" ? */
export const clientInfo = new ClientInfo(); export const clientInfo = new ClientInfo();
export const clientInfoSpectator = new ClientInfoSpectator(); // WIP, could refactor this export const clientInfoSpectator = new ClientInfoSpectator(); // WIP, could refactor this
@@ -57,7 +64,6 @@ function logListener(this: WebSocket, event: MessageEvent) {
} }
function errorListener(this: WebSocket, event: MessageEvent) { function errorListener(this: WebSocket, event: MessageEvent) {
console.log("errorListener");
const data: ev.ServerEvent = JSON.parse(event.data); const data: ev.ServerEvent = JSON.parse(event.data);
if (data.type === en.EventTypes.error) { if (data.type === en.EventTypes.error) {
console.log("actual Error"); console.log("actual Error");
@@ -98,12 +104,9 @@ function preMatchListener(this: WebSocket, event: MessageEvent)
startFunction(); startFunction();
break; break;
case en.EventTypes.matchAbort: case en.EventTypes.matchAbort:
matchAbort = true; gameState.matchAbort = true;
socket.removeEventListener("message", preMatchListener); socket.removeEventListener("message", preMatchListener);
msg.matchAbort(); msg.matchAbort();
setTimeout(() => {
matchAbort = false;
}, 1000);
break; break;
} }
} }
@@ -204,7 +207,7 @@ function scoreUpdate(data: ev.EventScoreUpdate)
function matchEnd(data: ev.EventMatchEnd) function matchEnd(data: ev.EventMatchEnd)
{ {
matchEnded = true; gameState.matchEnded = true;
socket.close(); socket.close();
if (data.winner === clientInfo.side) { if (data.winner === clientInfo.side) {
msg.win(); msg.win();
@@ -215,9 +218,6 @@ function matchEnd(data: ev.EventMatchEnd)
else { else {
msg.lose(); msg.lose();
} }
setTimeout(() => {
matchEnded = false;
}, 1000);
} }
/* Spectator */ /* Spectator */
@@ -229,6 +229,7 @@ export function initWebSocketSpectator(gameSessionId: string)
socket.send(JSON.stringify( new ev.ClientAnnounceSpectator(gameSessionId) )); socket.send(JSON.stringify( new ev.ClientAnnounceSpectator(gameSessionId) ));
}); });
// socket.addEventListener("message", logListener); // for testing purpose // socket.addEventListener("message", logListener); // for testing purpose
socket.addEventListener("message", errorListener);
socket.addEventListener("message", preMatchListenerSpectator); socket.addEventListener("message", preMatchListenerSpectator);
clientInfoSpectator.playerLeftNextPos = new VectorInteger(gc.playerLeft.pos.x, gc.playerLeft.pos.y); clientInfoSpectator.playerLeftNextPos = new VectorInteger(gc.playerLeft.pos.x, gc.playerLeft.pos.y);
@@ -243,6 +244,7 @@ export function preMatchListenerSpectator(this: WebSocket, event: MessageEvent)
{ {
socket.removeEventListener("message", preMatchListenerSpectator); socket.removeEventListener("message", preMatchListenerSpectator);
socket.addEventListener("message", inGameListenerSpectator); socket.addEventListener("message", inGameListenerSpectator);
socket.send(JSON.stringify( new ev.ClientEvent(en.EventTypes.clientSpectatorReady) ));
startFunction(); startFunction();
} }
} }
@@ -318,7 +320,7 @@ function scoreUpdateSpectator(data: ev.EventScoreUpdate)
function matchEndSpectator(data: ev.EventMatchEnd) function matchEndSpectator(data: ev.EventMatchEnd)
{ {
console.log("matchEndSpectator"); console.log("matchEndSpectator");
matchEnded = true; gameState.matchEnded = true;
socket.close(); socket.close();
// WIP // WIP
/* msg.win(); /* msg.win();

View File

@@ -26,5 +26,5 @@ export const movingWallPosMax = Math.floor(w*0.12);
export const movingWallSpeed = Math.floor(w*0.08); export const movingWallSpeed = Math.floor(w*0.08);
export const gameSessionIdPLACEHOLDER = "42"; // TESTING SPECTATOR PLACEHOLDER export const gameSessionIdPLACEHOLDER = "match-id-test-42"; // TESTING SPECTATOR PLACEHOLDER
// for testing, force gameSession.id in wsServer.ts->matchmaking() // for testing, force gameSession.id in wsServer.ts->createGameSession()

View File

@@ -19,6 +19,7 @@ export enum EventTypes {
// Client // Client
clientAnnounce, clientAnnounce,
clientPlayerReady, clientPlayerReady,
clientSpectatorReady,
clientInput, clientInput,
} }

View File

@@ -2,7 +2,7 @@
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import GenerateUserDisplay from '../../pieces/GenerateUserDisplay.svelte'; import GenerateUserDisplay from '../../pieces/GenerateUserDisplay.svelte';
import { Domain, Port } from "../../Constantes.svelte";
import Chat from '../../pieces/chat/Chat.svelte'; import Chat from '../../pieces/chat/Chat.svelte';
@@ -10,7 +10,7 @@
onMount( async() => { onMount( async() => {
// console.log('mounting profile display') // console.log('mounting profile display')
user = await fetch(`http://${Domain}:${Port}/api/v2/user`) user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
.then( (x) => x.json() ); .then( (x) => x.json() );
}) })

View File

@@ -2,7 +2,7 @@
import { onMount } from "svelte"; import { onMount } from "svelte";
import { binding_callbacks } from "svelte/internal"; import { binding_callbacks } from "svelte/internal";
import { Domain, Port } from "../../Constantes.svelte";
import Button from "../../pieces/Button.svelte"; import Button from "../../pieces/Button.svelte";
import DisplayAUser from "../../pieces/DisplayAUser.svelte"; import DisplayAUser from "../../pieces/DisplayAUser.svelte";
@@ -39,7 +39,7 @@ could be a list of friends and if they're active but i can't see that yet
onMount( async() => { onMount( async() => {
// yea no idea what // yea no idea what
// i mean do i fetch user? i will for now // i mean do i fetch user? i will for now
user = await fetch(`http://${Domain}:${Port}/api/v2/user`) user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
.then( (x) => x.json() ); .then( (x) => x.json() );
// userBeingViewed = user; // userBeingViewed = user;
@@ -47,26 +47,26 @@ could be a list of friends and if they're active but i can't see that yet
// console.log(user) // console.log(user)
// console.log(user.username) // console.log(user.username)
myFriends = await fetch(`http://${Domain}:${Port}/api/v2/network/myfriends`) myFriends = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/myfriends`)
.then( (x) => x.json() ); .then( (x) => x.json() );
// console.log('my friends') // console.log('my friends')
// console.log(myFriends) // console.log(myFriends)
requestsMade = await fetch(`http://${Domain}:${Port}/api/v2/network/pending`) requestsMade = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/pending`)
.then( x => x.json() ); .then( x => x.json() );
// console.log('Requests pending '); // console.log('Requests pending ');
// console.log(requestsMade); // console.log(requestsMade);
requestsRecieved = await fetch(`http://${Domain}:${Port}/api/v2/network/received`) requestsRecieved = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/received`)
.then( x => x.json() ); .then( x => x.json() );
// console.log('Requests received '); // console.log('Requests received ');
// console.log(requestsRecieved); // console.log(requestsRecieved);
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/user/all`) allUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/all`)
.then( x => x.json() ); .then( x => x.json() );
// console.log('got all users ' + allUsers) // console.log('got all users ' + allUsers)
@@ -75,20 +75,20 @@ could be a list of friends and if they're active but i can't see that yet
const displayAllUsers = async() => { const displayAllUsers = async() => {
allUsers = await fetch(`http://${Domain}:${Port}/api/v2/user/all`) allUsers = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/all`)
.then( x => x.json() ); .then( x => x.json() );
// console.log('got all users ' + allUsers) // console.log('got all users ' + allUsers)
}; };
const displayAllFriends = async() => { const displayAllFriends = async() => {
myFriends = await fetch(`http://${Domain}:${Port}/api/v2/network/myfriends`) myFriends = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/myfriends`)
.then( x => x.json() ); .then( x => x.json() );
// console.log('got all friends ' + allFriends) // console.log('got all friends ' + allFriends)
}; };
const displayRequestsMade = async() => { const displayRequestsMade = async() => {
requestsMade = await fetch(`http://${Domain}:${Port}/api/v2/network/pending`) requestsMade = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/pending`)
.then( x => x.json() ); .then( x => x.json() );
// console.log('got requests made ' + requestsMade) // console.log('got requests made ' + requestsMade)
}; };
@@ -107,7 +107,7 @@ could be a list of friends and if they're active but i can't see that yet
} }
if (valid) { if (valid) {
sentFriendRequest = await fetch(`http://${Domain}:${Port}/api/v2/network/myfriends`, { sentFriendRequest = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/network/myfriends`, {
method : "POST", method : "POST",
headers: { 'Content-Type': 'application/json'}, headers: { 'Content-Type': 'application/json'},
body: JSON.stringify({ body: JSON.stringify({
@@ -125,7 +125,7 @@ could be a list of friends and if they're active but i can't see that yet
// sendUsername = userBeingViewed.username; // sendUsername = userBeingViewed.username;
// prolly like fetch if you're friends or not? // prolly like fetch if you're friends or not?
// GET `http://${Domain}:${Port}/api/v2/networks/myfriends?username=aUser` but i need to make that as long as Cherif // GET `http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/networks/myfriends?username=aUser` but i need to make that as long as Cherif
// doesn't have a better option // doesn't have a better option
// like i want this thing to return the Friendship ID ideally // like i want this thing to return the Friendship ID ideally
}; };

View File

@@ -3,7 +3,7 @@
import Card from '../../pieces/Card.svelte'; import Card from '../../pieces/Card.svelte';
import {onMount} from 'svelte'; import {onMount} from 'svelte';
import { push } from 'svelte-spa-router'; import { push } from 'svelte-spa-router';
import { Domain, Port } from "../../Constantes.svelte";
import Button from '../../pieces/Button.svelte'; import Button from '../../pieces/Button.svelte';
let user; let user;
@@ -17,7 +17,7 @@
let success = {username: '', avatar: '' }; let success = {username: '', avatar: '' };
onMount( async() => { onMount( async() => {
user = await fetch(`http://${Domain}:${Port}/api/v2/user`) user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`)
.then( (x) => x.json() ); .then( (x) => x.json() );
// do a .catch? // do a .catch?
@@ -34,7 +34,7 @@
// console.log('this is what is in the avatar before fetch') // console.log('this is what is in the avatar before fetch')
// console.log(avatar) // console.log(avatar)
await fetch(`http://${Domain}:${Port}/api/v2/user/avatar`, {method: "GET"}) await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar`, {method: "GET"})
.then(response => {return response.blob()}) .then(response => {return response.blob()})
.then(data => { .then(data => {
const url = URL.createObjectURL(data); const url = URL.createObjectURL(data);
@@ -64,7 +64,7 @@
else { else {
errors.username = ''; errors.username = '';
} }
await fetch(`http://${Domain}:${Port}/api/v2/user`, { await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user`, {
method: 'PATCH', method: 'PATCH',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@@ -101,15 +101,21 @@
// tmp // tmp
console.log(data); console.log(data);
await fetch(`http://${Domain}:${Port}/api/v2/user/avatar`, const responseWhenChangeAvatar = fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar`,
{ {
method : 'POST', method : 'POST',
body : data, body : data,
}) })
.then(() => uploadAvatarSuccess = true ) // for some reason it needs to be a function, i think a TS thing, not a promis otherwise const responseFromServer = await responseWhenChangeAvatar;
.then(() => success.avatar = 'Your changes have been saved') if (responseFromServer.ok === true) {
.catch(() => errors.avatar = 'Sorry failed to upload your new Avatar' ); uploadAvatarSuccess = true;
await fetch(`http://${Domain}:${Port}/api/v2/user/avatar`, {method: "GET"}) success.avatar = 'Your avatar has been updated';
}
else {
errors.avatar = responseFromServer.statusText;
}
await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar`, {method: "GET"})
.then(response => {return response.blob()}) .then(response => {return response.blob()})
.then(data => { .then(data => {
const url = URL.createObjectURL(data); const url = URL.createObjectURL(data);

View File

@@ -2,7 +2,7 @@
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import GenerateUserDisplay from './GenerateUserDisplay.svelte'; import GenerateUserDisplay from './GenerateUserDisplay.svelte';
import { Domain, Port } from "../Constantes.svelte";
// import {updateGeneratedUser} from './GenerateUserDisplay.svelte'; // import {updateGeneratedUser} from './GenerateUserDisplay.svelte';
export let aUsername; export let aUsername;
@@ -10,8 +10,8 @@
onMount( async() => { onMount( async() => {
console.log('Display aUser username: '+ aUsername) console.log('Display aUser username: '+ aUsername)
//`http://${Domain}:${Port}/api/v2/user?username=NomDuUserATrouve` //`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=NomDuUserATrouve`
user = await fetch(`http://${Domain}:${Port}/api/v2/user?username=${aUsername}`) user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=${aUsername}`)
.then( (x) => x.json() ); .then( (x) => x.json() );
// console.log('Display a user: ') // console.log('Display a user: ')
@@ -27,15 +27,15 @@
const updateUser = async(updatedUser) => { const updateUser = async(updatedUser) => {
console.log('Display Update aUser username: '+ updateUser) console.log('Display Update aUser username: '+ updateUser)
//`http://${Domain}:${Port}/api/v2/user?username=NomDuUserATrouve` //`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=NomDuUserATrouve`
user = await fetch(`http://${Domain}:${Port}/api/v2/user?username=${updateUser}`) user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=${updateUser}`)
.then( (x) => x.json() ); .then( (x) => x.json() );
}; };
// export const updateUser = async(updatedUser) => { // export const updateUser = async(updatedUser) => {
// console.log('Display Update aUser username: '+ updateUser) // console.log('Display Update aUser username: '+ updateUser)
// //`http://${Domain}:${Port}/api/v2/user?username=NomDuUserATrouve` // //`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=NomDuUserATrouve`
// user = await fetch(`http://${Domain}:${Port}/api/v2/user?username=${updateUser}`) // user = await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user?username=${updateUser}`)
// .then( (x) => x.json() ); // .then( (x) => x.json() );
// updateGeneratedUser(updateUser); // updateGeneratedUser(updateUser);

View File

@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { Domain, Port } from "../Constantes.svelte";
export let user; export let user;
export let primary; export let primary;
@@ -12,7 +12,7 @@
onMount( async() => { onMount( async() => {
// using this for now cuz for some reason there is yet to be a way to fet another person's avatar // using this for now cuz for some reason there is yet to be a way to fet another person's avatar
if (primary) { if (primary) {
await fetch(`http://${Domain}:${Port}/api/v2/user/avatar`, {method: "GET"}) await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/user/avatar`, {method: "GET"})
.then(response => {return response.blob()}) .then(response => {return response.blob()})
.then(data => { .then(data => {
const url = URL.createObjectURL(data); const url = URL.createObjectURL(data);

View File

@@ -1,14 +1,14 @@
<script lang="ts"> <script lang="ts">
import { push } from "svelte-spa-router"; import { push } from "svelte-spa-router";
import { location } from 'svelte-spa-router'; import { location } from 'svelte-spa-router';
import { Domain, Port } from "../Constantes.svelte";
import active from 'svelte-spa-router/active' import active from 'svelte-spa-router/active'
// or i could leave them all and not display if they're active? // or i could leave them all and not display if they're active?
let handleClickLogout = async () => { let handleClickLogout = async () => {
await fetch(`http://${Domain}:${Port}/api/v2/auth/logout`, { await fetch(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}/api/v2/auth/logout`, {
method: 'POST', method: 'POST',
}) })
// .then(resp => resp.json) // .then(resp => resp.json)
@@ -25,8 +25,8 @@
<img src="/img/potato_logo.png" alt="Potato Pong Logo" on:click={() => (push('/'))}> <img src="/img/potato_logo.png" alt="Potato Pong Logo" on:click={() => (push('/'))}>
<h1>Potato Pong</h1> <h1>Potato Pong</h1>
<nav> <nav>
<button on:click={() => (push('/game'))}>Game</button> <button on:click={() => (push('/game'))}>Play</button>
<button on:click={() => (push('/matchlist'))}>Match List</button> <button on:click={() => (push('/spectator'))}>Spectate</button>
<button on:click={() => (push('/ranking'))}>Ranking</button> <button on:click={() => (push('/ranking'))}>Ranking</button>
{#if $location !== '/profile'} {#if $location !== '/profile'}
<button on:click={() => (push('/profile'))}>My Profile</button> <button on:click={() => (push('/profile'))}>My Profile</button>

View File

@@ -1,15 +1,40 @@
<script lang="ts"> <script lang="ts">
import { onMount, onDestroy } from "svelte";
import { MatchOptions } from "../pages/game/client/pongSpectator";
export let match: { export let match: {
id: string, gameServerIdOfTheMatch: string,
gameOptions: MatchOptions,
playerOneUsername: string, playerOneUsername: string,
playerTwoUsername: string playerTwoUsername: string
}; };
let matchOptionsString = "";
onMount( async() => {
if (match.gameOptions === MatchOptions.noOption) {
matchOptionsString = "standard";
}
else {
if (match.gameOptions & MatchOptions.multiBalls) {
matchOptionsString += "multi balls";
}
if (match.gameOptions & MatchOptions.movingWalls) {
if (matchOptionsString) { matchOptionsString += ", "; }
matchOptionsString += "moving walls";
}
}
})
</script> </script>
<!-- --> <!-- -->
<li> <li>
{match.id} "{match.playerOneUsername}" VS "{match.playerTwoUsername}" <button on:click>
"{match.playerOneUsername}" VS "{match.playerTwoUsername}"
<br/> [{matchOptionsString}]
</button>
</li> </li>

View File

@@ -2,14 +2,13 @@
<script lang="ts"> <script lang="ts">
import Layouts from './Chat_layouts.svelte'; import Layouts from './Chat_layouts.svelte';
import { Domain, PortIo } from "../../Constantes.svelte";
export let color = "transparent"; export let color = "transparent";
/* web sockets with socket.io /* web sockets with socket.io
*/ */
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import io from 'socket.io-client'; import io from 'socket.io-client';
const socket = io(`http://${Domain}:${PortIo}`, { const socket = io(`http://${process.env.WEBSITE_HOST}:${process.env.WEBSITE_PORT}`, {
path: '/chat' path: '/chat'
}); });
onMount(async => { onMount(async => {

View File

@@ -1,8 +1,6 @@
<script lang="ts"> <script lang="ts">
import Debug from './tmp_debug.svelte';
import ChatBox from './Chat_box_css.svelte'; import ChatBox from './Chat_box_css.svelte';
import CloseLayout from './Layout_close.svelte'; import CloseLayout from './Layout_close.svelte';
@@ -79,8 +77,5 @@
</ChatBox> </ChatBox>
<!-- TMP DEBUG -->
<Debug bind:layout bind:layouts />
<style></style> <style></style>

View File

@@ -1,27 +0,0 @@
<script>
export let layout = "";
export let layouts = [];
</script>
<div style="display: flex; flex-direction: column; font-size: 12px; position: fixed; top: 20px; left: 20px; background-color: white;">
<p>temp, for testing :</p>
<button on:click={function(){layout = "close" }}>close</button>
<button on:click={function(){layout = "home" }}>home</button>
<button on:click={function(){layout = "room" }}>room</button>
<button on:click={function(){layout = "new" }}>new</button>
<button on:click={function(){layout = "settings" }}>settings</button>
<button on:click={function(){layout = "room_set" }}>room_set</button>
<button on:click={function(){layout = "protected"}}>protected</button>
<button on:click={function(){layout = "create" }}>create</button>
<button on:click={function(){layout = "mute" }}>mute</button>
<button on:click={function(){
layouts = ["settings", "settings"];
layout = "user";
}}>user from settings</button>
<button on:click={function(){
layouts = ["room_set", "room_set"];
layout = "user";
}}>user from room_set</button>
</div>

View File

@@ -7,7 +7,7 @@ import { wrap } from 'svelte-spa-router/wrap'
import TestPage from '../pages/TmpTestPage.svelte'; import TestPage from '../pages/TmpTestPage.svelte';
import Game from '../pages/game/Game.svelte'; import Game from '../pages/game/Game.svelte';
import Ranking from '../pages/game/Ranking.svelte'; import Ranking from '../pages/game/Ranking.svelte';
import SpectatorMatchList from '../pages/SpectatorMatchList.svelte'; import GameSpectator from '../pages/game/GameSpectator.svelte';
@@ -15,13 +15,13 @@ export const primaryRoutes = {
'/': SplashPage, '/': SplashPage,
'/2fa': TwoFactorAuthentication, '/2fa': TwoFactorAuthentication,
'/game': Game, '/game': Game,
'/matchlist': SpectatorMatchList, '/spectator': GameSpectator,
'/ranking' : Ranking, '/ranking' : Ranking,
'/profile': wrap({ '/profile': wrap({
component: ProfilePage, component: ProfilePage,
conditions: [ conditions: [
async(detail) => { async(detail) => {
const user = await fetch('http://transcendance:8080/api/v2/user') const user = await fetch('http://' + process.env.WEBSITE_HOST + ":" + process.env.WEBSITE_PORT + '/api/v2/user')
.then((resp) => resp.json()) .then((resp) => resp.json())
console.log('in /profile what is in user') console.log('in /profile what is in user')
@@ -38,7 +38,7 @@ export const primaryRoutes = {
component: ProfilePage, component: ProfilePage,
conditions: [ conditions: [
async(detail) => { async(detail) => {
const user = await fetch('http://transcendance:8080/api/v2/user') const user = await fetch('http://' + process.env.WEBSITE_HOST + ":" + process.env.WEBSITE_PORT + '/api/v2/user')
.then((resp) => resp.json()) .then((resp) => resp.json())
console.log('in /profile/* what is in user') console.log('in /profile/* what is in user')