mirror of
https://github.com/KeyZox71/knl_meowscendence.git
synced 2025-12-31 21:56:41 +01:00
Merge branch 'front' into shitty-improvement
This commit is contained in:
10
.env.example
10
.env.example
@ -26,6 +26,10 @@ SMTP_AUTH_USERNAME=<smtp-user>
|
|||||||
SMTP_AUTH_PASSWORD=<smtp pass>
|
SMTP_AUTH_PASSWORD=<smtp pass>
|
||||||
EMAIL_TO=<mail to send to>
|
EMAIL_TO=<mail to send to>
|
||||||
|
|
||||||
USER_URL=<the url to the user api>
|
USER_URL=<the internal url to the user api>
|
||||||
AUTH_URL=<the url to the auth api>
|
AUTH_URL=<the internal url to the auth api>
|
||||||
CORS_ORIGIN=<the url of origin for cors>
|
SCORE_URL=<the internal url to the score store api>
|
||||||
|
|
||||||
|
CORS_ORIGIN=<the external url of origin for cors>
|
||||||
|
VITE_USER_API=<the external url of the user api>
|
||||||
|
VITE_AUTH_API=<the external url of the auth api>
|
||||||
|
|||||||
@ -5,8 +5,8 @@ services:
|
|||||||
dockerfile: docker/front/Dockerfile
|
dockerfile: docker/front/Dockerfile
|
||||||
context: ../../
|
context: ../../
|
||||||
args:
|
args:
|
||||||
- VITE_USER_URL=${USER_URL}
|
- VITE_USER_URL=${VITE_USER_URL}
|
||||||
- VITE_AUTH_URL=${AUTH_URL}
|
- VITE_AUTH_URL=${VITE_AUTH_URL}
|
||||||
environment:
|
environment:
|
||||||
- TZ=Europe/Paris
|
- TZ=Europe/Paris
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
@ -4,8 +4,11 @@ import FriendsMenu from "./views/Friends.ts";
|
|||||||
let profile_view = new ProfileMenu;
|
let profile_view = new ProfileMenu;
|
||||||
let friends_view = new FriendsMenu;
|
let friends_view = new FriendsMenu;
|
||||||
|
|
||||||
|
export const user_api = import.meta.env.VITE_USER_API as String;
|
||||||
|
export const auth_api = import.meta.env.VITE_AUTH_API as String;
|
||||||
|
|
||||||
export async function isLogged(): Promise<boolean> {
|
export async function isLogged(): Promise<boolean> {
|
||||||
let uuid_req = await fetch("http://localhost:3001/me", {
|
let uuid_req = await fetch(auth_api + "/me", {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
});
|
});
|
||||||
@ -129,7 +132,7 @@ function updateClock()
|
|||||||
|
|
||||||
async function pingClock() {
|
async function pingClock() {
|
||||||
if (await isLogged()) {
|
if (await isLogged()) {
|
||||||
fetch(`http://localhost:3002/ping`, {
|
fetch(user_api + "/ping", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
credentials: "include"
|
credentials: "include"
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import Aview from "./Aview.ts"
|
import Aview from "./Aview.ts"
|
||||||
import { setOnekoState } from "../oneko.ts"
|
|
||||||
import { dragElement } from "./drag.ts";
|
import { dragElement } from "./drag.ts";
|
||||||
import { isLogged, navigationManager } from "../main.ts"
|
import { setOnekoState } from "../oneko.ts"
|
||||||
|
import { isLogged, navigationManager, user_api, auth_api } from "../main.ts"
|
||||||
|
|
||||||
export default class extends Aview {
|
export default class extends Aview {
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ export default class extends Aview {
|
|||||||
const add_friend_msg = (document.getElementById("add-friend-msg") as HTMLParagraphElement);
|
const add_friend_msg = (document.getElementById("add-friend-msg") as HTMLParagraphElement);
|
||||||
|
|
||||||
async function removeFriend(name: String) {
|
async function removeFriend(name: String) {
|
||||||
const data_req = await fetch("http://localhost:3002/users/" + uuid + "/friends/" + name, {
|
const data_req = await fetch(user_api + "/users/" + uuid + "/friends/" + name, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
});
|
});
|
||||||
@ -76,7 +76,7 @@ export default class extends Aview {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function isFriendLogged(name: string): Promise<Boolean> {
|
async function isFriendLogged(name: string): Promise<Boolean> {
|
||||||
const data_req = await fetch("http://localhost:3002/ping/" + name, {
|
const data_req = await fetch(user_api + "/ping/" + name, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
});
|
});
|
||||||
@ -88,7 +88,7 @@ export default class extends Aview {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const list_friends = async () => {
|
const list_friends = async () => {
|
||||||
const data_req = await fetch("http://localhost:3002/users/" + uuid + "/friends/count", {
|
const data_req = await fetch(user_api + "/users/" + uuid + "/friends/count", {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@ -103,7 +103,7 @@ export default class extends Aview {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data.n_friends > 0) {
|
if (data.n_friends > 0) {
|
||||||
const list_req = await fetch("http://localhost:3002/users/" + uuid + "/friends?iStart=0&iEnd=2147483647", {
|
const list_req = await fetch(user_api + "/users/" + uuid + "/friends?iStart=0&iEnd=2147483647", {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@ -156,7 +156,7 @@ export default class extends Aview {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const add_friend = async () => {
|
const add_friend = async () => {
|
||||||
const data_req = await fetch("http://localhost:3002/users/" + uuid + "/friends/" + new_friend.value, {
|
const data_req = await fetch(user_api + "/users/" + uuid + "/friends/" + new_friend.value, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
});
|
});
|
||||||
@ -179,7 +179,7 @@ export default class extends Aview {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data_req = await fetch("http://localhost:3002/users/" + uuid + "/friends/count", {
|
const data_req = await fetch(user_api + "/users/" + uuid + "/friends/count", {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import Aview from "./Aview.ts"
|
import Aview from "./Aview.ts"
|
||||||
import { dragElement } from "./drag.ts"
|
import { dragElement } from "./drag.ts"
|
||||||
import { setOnekoState } from "../oneko.ts"
|
import { setOnekoState } from "../oneko.ts"
|
||||||
import { isLogged, navigationManager } from "../main.ts"
|
import { isLogged, navigationManager, user_api, auth_api } from "../main.ts"
|
||||||
|
|
||||||
export default class extends Aview {
|
export default class extends Aview {
|
||||||
|
|
||||||
@ -27,8 +27,10 @@ export default class extends Aview {
|
|||||||
<div class="bg-neutral-200 dark:bg-neutral-800 text-center pb-10 pt-5 px-10 reverse-border flex flex-col items-center">
|
<div class="bg-neutral-200 dark:bg-neutral-800 text-center pb-10 pt-5 px-10 reverse-border flex flex-col items-center">
|
||||||
<form method="dialog" class="space-y-4">
|
<form method="dialog" class="space-y-4">
|
||||||
<h1 class="text-gray-900 dark:text-white text-lg pt-0 pb-4">welcome back ! please login.</h1>
|
<h1 class="text-gray-900 dark:text-white text-lg pt-0 pb-4">welcome back ! please login.</h1>
|
||||||
<input type="text" id="username" placeholder="username" class="bg-white text-neutral-900 px-4 py-2 input-border" required></input>
|
<div class="flex flex-row justify-between space-x-4">
|
||||||
<input type="password" id="password" placeholder="password" class="bg-white text-neutral-900 px-4 py-2 input-border" required></input>
|
<input type="text" id="username" placeholder="username" class="bg-white text-neutral-900 px-4 py-2 input-border" required></input>
|
||||||
|
<input type="password" id="password" placeholder="password" class="bg-white text-neutral-900 px-4 py-2 input-border" required></input>
|
||||||
|
</div>
|
||||||
<button id="login-button" type="submit" class="default-button w-full">login</button>
|
<button id="login-button" type="submit" class="default-button w-full">login</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
@ -37,13 +39,13 @@ export default class extends Aview {
|
|||||||
<hr class="my-4 w-64 reverse-border">
|
<hr class="my-4 w-64 reverse-border">
|
||||||
|
|
||||||
<div class="flex flex-col space-y-4 w-full">
|
<div class="flex flex-col space-y-4 w-full">
|
||||||
<a target="_blank" href="http://localhost:3001/login/google" class="default-button inline-flex items-center justify-center w-full">
|
<a target="_blank" id="login-google" class="default-button inline-flex items-center justify-center w-full">
|
||||||
<img src="https://upload.wikimedia.org/wikipedia/commons/c/c1/Google_%22G%22_logo.svg" height=20 width=20 class="mr-2 justify-self-start" />
|
<img src="https://upload.wikimedia.org/wikipedia/commons/c/c1/Google_%22G%22_logo.svg" height=20 width=20 class="mr-2 justify-self-start" />
|
||||||
login with John Google
|
login with google
|
||||||
</a>
|
</a>
|
||||||
<a target="_blank" href="https://rusty.42angouleme.fr/issues/all" class="default-button inline-flex items-center justify-center w-full">
|
<a target="_blank" href="https://rusty.42angouleme.fr/issues/all" class="default-button inline-flex items-center justify-center w-full">
|
||||||
<img src="https://rusty.42angouleme.fr/assets/favicon-bb06adc80c8495db.ico" height=20 width=20 class="mr-2 justify-self-start" />
|
<img src="https://rusty.42angouleme.fr/assets/favicon-bb06adc80c8495db.ico" height=20 width=20 class="mr-2 justify-self-start" />
|
||||||
login with Rusty
|
login with rusty
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -53,6 +55,7 @@ export default class extends Aview {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async run() {
|
async run() {
|
||||||
|
document.getElementById("login-google").href = `${auth_api}/login/google`;
|
||||||
dragElement(document.getElementById("window"));
|
dragElement(document.getElementById("window"));
|
||||||
|
|
||||||
const totpVerify = async () => {
|
const totpVerify = async () => {
|
||||||
@ -61,7 +64,7 @@ export default class extends Aview {
|
|||||||
const totpPin = (document.getElementById('totpPin') as HTMLInputElement).value;
|
const totpPin = (document.getElementById('totpPin') as HTMLInputElement).value;
|
||||||
const idWindow = (document.getElementById('2fa-popup-content') as HTMLInputElement);
|
const idWindow = (document.getElementById('2fa-popup-content') as HTMLInputElement);
|
||||||
try {
|
try {
|
||||||
const data_req = await fetch("http://localhost:3001/login", {
|
const data_req = await fetch(auth_api + "/login", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json", },
|
headers: { "Content-Type": "application/json", },
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
@ -99,7 +102,7 @@ export default class extends Aview {
|
|||||||
const password = (document.getElementById("password") as HTMLInputElement).value;
|
const password = (document.getElementById("password") as HTMLInputElement).value;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data_req = await fetch("http://localhost:3001/login", {
|
const data_req = await fetch(auth_api + "/login", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json", },
|
headers: { "Content-Type": "application/json", },
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
@ -163,9 +166,9 @@ export default class extends Aview {
|
|||||||
uu.disabled = true;
|
uu.disabled = true;
|
||||||
pass.disabled = true;
|
pass.disabled = true;
|
||||||
|
|
||||||
document.getElementById("app")?.appendChild(popup);
|
document.getElementById("app")?.appendChild(popup);
|
||||||
tokenInput.focus();
|
tokenInput.focus();
|
||||||
dragElement(document.getElementById("2fa-popup"));
|
dragElement(document.getElementById("2fa-popup"));
|
||||||
|
|
||||||
document.getElementById("totp-submit")?.addEventListener("click", totpVerify);
|
document.getElementById("totp-submit")?.addEventListener("click", totpVerify);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import Aview from "./Aview.ts"
|
import Aview from "./Aview.ts"
|
||||||
import { isLogged } from "../main.js"
|
import { isLogged, user_api, auth_api } from "../main.js"
|
||||||
import { dragElement } from "./drag.js"
|
import { dragElement } from "./drag.js"
|
||||||
import { setOnekoState, setBallPos, setOnekoOffset } from "../oneko.ts"
|
import { setOnekoState, setBallPos, setOnekoOffset } from "../oneko.ts"
|
||||||
|
|
||||||
@ -59,6 +59,9 @@ export default class extends Aview {
|
|||||||
let p1_name: string;
|
let p1_name: string;
|
||||||
let p2_name: string;
|
let p2_name: string;
|
||||||
|
|
||||||
|
let p1_displayName: string;
|
||||||
|
let p2_displayName: string;
|
||||||
|
|
||||||
let countdown: number = 3;
|
let countdown: number = 3;
|
||||||
let countdownTimer: number = 0;
|
let countdownTimer: number = 0;
|
||||||
|
|
||||||
@ -148,7 +151,7 @@ export default class extends Aview {
|
|||||||
if (await isLogged())
|
if (await isLogged())
|
||||||
{
|
{
|
||||||
let uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
let uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
||||||
fetch(`http://localhost:3002/users/${uuid}/matchHistory?game=pong`, {
|
fetch(user_api + "/users/" + uuid + "/matchHistory?game=pong", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json", },
|
headers: { "Content-Type": "application/json", },
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
@ -203,8 +206,8 @@ export default class extends Aview {
|
|||||||
ctx.font = "24px Kubasta";
|
ctx.font = "24px Kubasta";
|
||||||
let text_score = `${p1_score} - ${p2_score}`;
|
let text_score = `${p1_score} - ${p2_score}`;
|
||||||
ctx.fillText(text_score, canvas.width / 2 - (ctx.measureText(text_score).width / 2), 25);
|
ctx.fillText(text_score, canvas.width / 2 - (ctx.measureText(text_score).width / 2), 25);
|
||||||
ctx.fillText(p1_name, canvas.width / 4 - (ctx.measureText(p1_name).width / 2), 45);
|
ctx.fillText(p1_displayName, canvas.width / 4 - (ctx.measureText(p1_name).width / 2), 45);
|
||||||
ctx.fillText(p2_name, (canvas.width / 4 * 3) - (ctx.measureText(p2_name).width / 2), 45);
|
ctx.fillText(p2_displayName, (canvas.width / 4 * 3) - (ctx.measureText(p2_name).width / 2), 45);
|
||||||
|
|
||||||
if (match_over)
|
if (match_over)
|
||||||
{
|
{
|
||||||
@ -273,23 +276,46 @@ export default class extends Aview {
|
|||||||
if (await isLogged())
|
if (await isLogged())
|
||||||
{
|
{
|
||||||
uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
||||||
const userdata_req = await fetch(`http://localhost:3002/users/${uuid}`, {
|
|
||||||
method: "GET",
|
p1_input.value = uuid;
|
||||||
credentials: "include",
|
|
||||||
});
|
|
||||||
if (userdata_req.status == 404)
|
|
||||||
{
|
|
||||||
console.error("invalid user");
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
let userdata = await userdata_req.json();
|
|
||||||
p1_input.value = userdata.displayName;
|
|
||||||
p1_input.readOnly = true;
|
p1_input.readOnly = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
p1_input.value = "player 1";
|
p1_input.value = "player 1";
|
||||||
|
|
||||||
document.getElementById("game-start")?.addEventListener("click", () => {
|
document.getElementById("game-start")?.addEventListener("click", async () => {
|
||||||
|
let p1_isvalid = true;
|
||||||
|
let p2_isvalid = true;
|
||||||
|
if (await isLogged()) {
|
||||||
|
const p1_req = await fetch(`${user_api}/users/${p1_input.value}`, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
const p2_req = await fetch(`${user_api}/users/${p2_input.value}`, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
if (p1_req.status != 200)
|
||||||
|
p1_isvalid = false;
|
||||||
|
else
|
||||||
|
p1_displayName = (await p1_req.json()).displayName;
|
||||||
|
|
||||||
|
if (p2_req.status != 200)
|
||||||
|
p2_isvalid = false;
|
||||||
|
else
|
||||||
|
p2_displayName = (await p2_req.json()).displayName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p1_isvalid = p2_isvalid = false;
|
||||||
|
p1_name = p1_input.value;
|
||||||
|
p2_name = p2_input.value;
|
||||||
|
if (!p1_isvalid)
|
||||||
|
p1_displayName = p1_name;
|
||||||
|
if (!p2_isvalid)
|
||||||
|
p2_displayName = p2_name;
|
||||||
|
|
||||||
|
p1_displayName = p1_displayName.length > 16 ? p1_displayName.substring(0, 16) + "." : p1_displayName;
|
||||||
|
p2_displayName = p2_displayName.length > 16 ? p2_displayName.substring(0, 16) + "." : p2_displayName;
|
||||||
p1_name = p1_input.value.length > 16 ? p1_input.value.substring(0, 16) + "." : p1_input.value;
|
p1_name = p1_input.value.length > 16 ? p1_input.value.substring(0, 16) + "." : p1_input.value;
|
||||||
p2_name = p2_input.value.length > 16 ? p2_input.value.substring(0, 16) + "." : p2_input.value;
|
p2_name = p2_input.value.length > 16 ? p2_input.value.substring(0, 16) + "." : p2_input.value;
|
||||||
document.getElementById("player-inputs").remove();
|
document.getElementById("player-inputs").remove();
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import Aview from "./Aview.ts"
|
import Aview from "./Aview.ts"
|
||||||
import { dragElement } from "./drag.ts";
|
import { dragElement } from "./drag.ts";
|
||||||
import { setOnekoState } from "../oneko.ts"
|
import { setOnekoState } from "../oneko.ts"
|
||||||
import { isLogged, navigationManager } from "../main.ts"
|
import { isLogged, navigationManager, user_api, auth_api } from "../main.ts"
|
||||||
|
|
||||||
|
|
||||||
export default class extends Aview {
|
export default class extends Aview {
|
||||||
@ -49,7 +49,7 @@ export default class extends Aview {
|
|||||||
let uuid: String;
|
let uuid: String;
|
||||||
uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
||||||
|
|
||||||
const userdata_req = await fetch(`http://localhost:3002/users/${uuid}`, {
|
const userdata_req = await fetch(`${user_api}/users/${uuid}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
});
|
});
|
||||||
@ -59,14 +59,14 @@ export default class extends Aview {
|
|||||||
}
|
}
|
||||||
let userdata = await userdata_req.json();
|
let userdata = await userdata_req.json();
|
||||||
|
|
||||||
let matchCount_req = await fetch(`http://localhost:3002/users/${uuid}/matchHistory/count?game=pong`, {
|
let matchCount_req = await fetch(`${user_api}/users/${uuid}/matchHistory/count?game=pong`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
});
|
});
|
||||||
let matchCount = await matchCount_req.json();
|
let matchCount = await matchCount_req.json();
|
||||||
pc += matchCount.n_matches;
|
pc += matchCount.n_matches;
|
||||||
|
|
||||||
let matches_req = await fetch(`http://localhost:3002/users/${uuid}/matchHistory?game=pong&iStart=0&iEnd=${matchCount.n_matches}`, {
|
let matches_req = await fetch(`${user_api}/users/${uuid}/matchHistory?game=pong&iStart=0&iEnd=${matchCount.n_matches}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
});
|
});
|
||||||
@ -78,6 +78,12 @@ export default class extends Aview {
|
|||||||
|
|
||||||
if (matches.matchHistory) {
|
if (matches.matchHistory) {
|
||||||
for (let match of matches.matchHistory) {
|
for (let match of matches.matchHistory) {
|
||||||
|
const p2_req = await fetch(`${user_api}/users/${match.score.p2}`, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
match.score.p1 = userdata.displayName;
|
||||||
|
match.score.p2 = (await p2_req.json()).displayName;
|
||||||
const newEntry = document.createElement("li");
|
const newEntry = document.createElement("li");
|
||||||
newEntry.classList.add("m-1", "default-button", "bg-neutral-200", "dark:bg-neutral-800", "text-neutral-900", "dark:text-white");
|
newEntry.classList.add("m-1", "default-button", "bg-neutral-200", "dark:bg-neutral-800", "text-neutral-900", "dark:text-white");
|
||||||
newEntry.innerHTML = match.score.p1Score > match.score.p2Score ? `${match.score.p1} - winner` : `${match.score.p2} - winner`;
|
newEntry.innerHTML = match.score.p1Score > match.score.p2Score ? `${match.score.p1} - winner` : `${match.score.p2} - winner`;
|
||||||
@ -115,14 +121,14 @@ export default class extends Aview {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
matchCount_req = await fetch(`http://localhost:3002/users/${uuid}/matchHistory/count?game=tetris`, {
|
matchCount_req = await fetch(`${user_api}/users/${uuid}/matchHistory/count?game=tetris`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
});
|
});
|
||||||
matchCount = await matchCount_req.json();
|
matchCount = await matchCount_req.json();
|
||||||
pc += matchCount.n_matches;
|
pc += matchCount.n_matches;
|
||||||
|
|
||||||
matches_req = await fetch(`http://localhost:3002/users/${uuid}/matchHistory?game=tetris&iStart=0&iEnd=${matchCount.n_matches}`, {
|
matches_req = await fetch(`${user_api}/users/${uuid}/matchHistory?game=tetris&iStart=0&iEnd=${matchCount.n_matches}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
});
|
});
|
||||||
@ -135,6 +141,15 @@ export default class extends Aview {
|
|||||||
// don't read this shit for you mental health
|
// don't read this shit for you mental health
|
||||||
if (matches.matchHistory) {
|
if (matches.matchHistory) {
|
||||||
for (let match of matches.matchHistory) {
|
for (let match of matches.matchHistory) {
|
||||||
|
if (match.score.p2 != undefined)
|
||||||
|
{
|
||||||
|
const p2_req = await fetch(`${user_api}/users/${match.score.p2}`, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
match.score.p2 = (await p2_req.json()).displayName;
|
||||||
|
}
|
||||||
|
match.score.p1 = userdata.displayName;
|
||||||
const newEntry = document.createElement("li");
|
const newEntry = document.createElement("li");
|
||||||
newEntry.classList.add("m-1", "default-button", "bg-neutral-200", "dark:bg-neutral-800", "text-neutral-900", "dark:text-white");
|
newEntry.classList.add("m-1", "default-button", "bg-neutral-200", "dark:bg-neutral-800", "text-neutral-900", "dark:text-white");
|
||||||
newEntry.innerHTML = match.score.p2 != undefined ?
|
newEntry.innerHTML = match.score.p2 != undefined ?
|
||||||
@ -184,12 +199,12 @@ export default class extends Aview {
|
|||||||
if (!profile) return;
|
if (!profile) return;
|
||||||
|
|
||||||
const picture = profile.appendChild(document.createElement("img"));
|
const picture = profile.appendChild(document.createElement("img"));
|
||||||
const a = await fetch(`http://localhost:3002/users/${uuid}/avatar`, {
|
const a = await fetch(`${user_api}/users/${uuid}/avatar`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
});
|
});
|
||||||
picture.src = a.status === 200
|
picture.src = a.status === 200
|
||||||
? `http://localhost:3002/users/${uuid}/avatar?t=${Date.now()}`
|
? `${user_api}/users/${uuid}/avatar?t=${Date.now()}`
|
||||||
: "https://api.kanel.ovh/pp";
|
: "https://api.kanel.ovh/pp";
|
||||||
picture.classList.add("text-neutral-900", "dark:text-white", "center", "h-18", "w-18", "mx-3", "reverse-border");
|
picture.classList.add("text-neutral-900", "dark:text-white", "center", "h-18", "w-18", "mx-3", "reverse-border");
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import Aview from "./Aview.ts"
|
import Aview from "./Aview.ts"
|
||||||
import { isLogged, navigationManager } from "../main.ts"
|
import { isLogged, user_api, auth_api } from "../main.ts"
|
||||||
|
|
||||||
export default class extends Aview {
|
export default class extends Aview {
|
||||||
async getHTML() {
|
async getHTML() {
|
||||||
@ -7,8 +7,7 @@ export default class extends Aview {
|
|||||||
<div id="main-window" class="default-border shadow-2x1 bg-neutral-200 dark:bg-neutral-800">
|
<div id="main-window" class="default-border shadow-2x1 bg-neutral-200 dark:bg-neutral-800">
|
||||||
<div class="flex flex-row items-stretch">
|
<div class="flex flex-row items-stretch">
|
||||||
<div class="inline-block bg-linear-to-b from-orange-200 to-orange-300 min-h-84 w-6 relative">
|
<div class="inline-block bg-linear-to-b from-orange-200 to-orange-300 min-h-84 w-6 relative">
|
||||||
<!--div class="absolute bottom-1 left-full whitespace-nowrap origin-bottom-left -rotate-90 font-bold">knl_meowscendence</div-->
|
<div class="absolute bottom-1 left-full whitespace-nowrap origin-bottom-left -rotate-90 font-bold">knl_meowscendence</div>
|
||||||
<div class="absolute bottom-1 left-full whitespace-nowrap origin-bottom-left -rotate-90 font-bold">girls kissing :3</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
@ -49,7 +48,7 @@ export default class extends Aview {
|
|||||||
document.getElementById("menu-bottom-div")?.classList.remove("hidden");
|
document.getElementById("menu-bottom-div")?.classList.remove("hidden");
|
||||||
|
|
||||||
uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
||||||
const userdata_req = await fetch(`http://localhost:3002/users/${uuid}`, {
|
const userdata_req = await fetch(`${user_api}/users/${uuid}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
});
|
});
|
||||||
@ -68,19 +67,21 @@ export default class extends Aview {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
document.getElementById("profile-items").innerHTML = await getMainHTML();
|
document.getElementById("profile-items").innerHTML = await getMainHTML();
|
||||||
|
requestAnimationFrame(() => {
|
||||||
document.getElementById("menu-logout")?.addEventListener("click", async () => {
|
document.getElementById("menu-logout").addEventListener("click", async () => {
|
||||||
let req = await fetch("http://localhost:3001/logout", {
|
let req = fetch(`${auth_api}/logout`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
|
});
|
||||||
|
req.then((res) => {
|
||||||
|
isLogged();
|
||||||
|
if (res.status === 200)
|
||||||
|
this.run();
|
||||||
|
else
|
||||||
|
console.error("logout failed");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
isLogged();
|
|
||||||
if (req.status === 200)
|
|
||||||
this.run();
|
|
||||||
else
|
|
||||||
console.error("logout failed");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import Aview from "./Aview.ts"
|
import Aview from "./Aview.ts"
|
||||||
import { dragElement } from "./drag.ts";
|
import { dragElement } from "./drag.ts";
|
||||||
import { setOnekoState } from "../oneko.ts"
|
import { setOnekoState } from "../oneko.ts"
|
||||||
import { isLogged, navigationManager } from "../main.ts"
|
import { isLogged, navigationManager, user_api, auth_api } from "../main.ts"
|
||||||
|
|
||||||
export default class extends Aview {
|
export default class extends Aview {
|
||||||
|
|
||||||
@ -26,8 +26,10 @@ export default class extends Aview {
|
|||||||
<div class="bg-neutral-200 dark:bg-neutral-800 text-center pb-10 pt-5 px-10 reverse-border flex flex-col items-center">
|
<div class="bg-neutral-200 dark:bg-neutral-800 text-center pb-10 pt-5 px-10 reverse-border flex flex-col items-center">
|
||||||
<form method="dialog" class="space-y-4">
|
<form method="dialog" class="space-y-4">
|
||||||
<h1 class="text-gray-900 dark:text-white text-lg pt-0 pb-4">welcome ! please register.</h1>
|
<h1 class="text-gray-900 dark:text-white text-lg pt-0 pb-4">welcome ! please register.</h1>
|
||||||
<input type="text" id="username" placeholder="username" class="bg-white text-neutral-900 px-4 py-2 input-border" required></input>
|
<div class="flex flex-row justify-between space-x-4">
|
||||||
<input type="password" id="password" placeholder="password" class="bg-white text-neutral-900 px-4 py-2 input-border" required></input>
|
<input type="text" id="username" placeholder="username" class="bg-white text-neutral-900 px-4 py-2 input-border" required></input>
|
||||||
|
<input type="password" id="password" placeholder="password" class="bg-white text-neutral-900 px-4 py-2 input-border" required></input>
|
||||||
|
</div>
|
||||||
<button id="register-button" type="submit" class="default-button w-full">register</button>
|
<button id="register-button" type="submit" class="default-button w-full">register</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
@ -36,13 +38,13 @@ export default class extends Aview {
|
|||||||
<hr class="my-4 w-64 reverse-border">
|
<hr class="my-4 w-64 reverse-border">
|
||||||
|
|
||||||
<div class="flex flex-col space-y-4 w-full">
|
<div class="flex flex-col space-y-4 w-full">
|
||||||
<a target="_blank" href="http://localhost:3001/register/google" class="default-button inline-flex items-center justify-center w-full">
|
<a target="_blank" id="register-google" class="default-button inline-flex items-center justify-center w-full">
|
||||||
<img src="https://upload.wikimedia.org/wikipedia/commons/c/c1/Google_%22G%22_logo.svg" height=20 width=20 class="mr-2 justify-self-start" />
|
<img src="https://upload.wikimedia.org/wikipedia/commons/c/c1/Google_%22G%22_logo.svg" height=20 width=20 class="mr-2 justify-self-start" />
|
||||||
register with John Google
|
register with google
|
||||||
</a>
|
</a>
|
||||||
<a target="_blank" href="https://rusty.42angouleme.fr/issues/all" class="default-button inline-flex items-center justify-center w-full">
|
<a target="_blank" href="https://rusty.42angouleme.fr/issues/all" class="default-button inline-flex items-center justify-center w-full">
|
||||||
<img src="https://rusty.42angouleme.fr/assets/favicon-bb06adc80c8495db.ico" height=20 width=20 class="mr-2 justify-self-start" />
|
<img src="https://rusty.42angouleme.fr/assets/favicon-bb06adc80c8495db.ico" height=20 width=20 class="mr-2 justify-self-start" />
|
||||||
register with Rusty
|
register with rusty
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -52,13 +54,14 @@ export default class extends Aview {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async run() {
|
async run() {
|
||||||
|
document.getElementById("register-google").href = `${auth_api}/register/google`;
|
||||||
dragElement(document.getElementById("window"));
|
dragElement(document.getElementById("window"));
|
||||||
const login = async () => {
|
const login = async () => {
|
||||||
const username = (document.getElementById("username") as HTMLInputElement).value;
|
const username = (document.getElementById("username") as HTMLInputElement).value;
|
||||||
const password = (document.getElementById("password") as HTMLInputElement).value;
|
const password = (document.getElementById("password") as HTMLInputElement).value;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data_req = await fetch("http://localhost:3001/register", {
|
const data_req = await fetch(auth_api + "/register", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json", },
|
headers: { "Content-Type": "application/json", },
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
@ -67,13 +70,12 @@ export default class extends Aview {
|
|||||||
const data = await data_req.json();
|
const data = await data_req.json();
|
||||||
|
|
||||||
if (data_req.status === 200) {
|
if (data_req.status === 200) {
|
||||||
let uuid_req = await fetch("http://localhost:3001/me", {
|
let uuid_req = await fetch(auth_api + "/me", {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
});
|
});
|
||||||
let uuid = await uuid_req.json();
|
let uuid = await uuid_req.json();
|
||||||
document.cookie = `uuid=${uuid.user};max-ages=${60 * 60 * 24 * 7}`;
|
document.cookie = `uuid=${uuid.user};max-ages=${60 * 60 * 24 * 7}`;
|
||||||
console.log(document.cookie);
|
|
||||||
isLogged();
|
isLogged();
|
||||||
navigationManager("/");
|
navigationManager("/");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import Aview from "./Aview.ts"
|
import Aview from "./Aview.ts"
|
||||||
import { dragElement } from "./drag.ts";
|
import { dragElement } from "./drag.ts";
|
||||||
import { setOnekoState } from "../oneko.ts"
|
import { setOnekoState } from "../oneko.ts"
|
||||||
import { isLogged, navigationManager } from "../main.ts"
|
|
||||||
import { totpEnablePopup } from "./TotpEnable.ts";
|
import { totpEnablePopup } from "./TotpEnable.ts";
|
||||||
import { totpVerify } from "../../../../api/auth/totpVerify.js";
|
import { totpVerify } from "../../../../api/auth/totpVerify.js";
|
||||||
|
import { isLogged, navigationManager, user_api, auth_api } from "../main.ts"
|
||||||
|
|
||||||
export default class extends Aview {
|
export default class extends Aview {
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ export default class extends Aview {
|
|||||||
dragElement(document.getElementById("window"));
|
dragElement(document.getElementById("window"));
|
||||||
|
|
||||||
const isTOTPEnabled = async () => {
|
const isTOTPEnabled = async () => {
|
||||||
const totpVerify_req = await fetch('http://localhost:3001/2fa', {
|
const totpVerify_req = await fetch(auth_api + '/2fa', {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
credentials: "include"
|
credentials: "include"
|
||||||
})
|
})
|
||||||
@ -66,10 +66,10 @@ export default class extends Aview {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
let uuid: String;
|
let uuid: String;
|
||||||
uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
||||||
const userdata_req = await fetch(`http://localhost:3002/users/${uuid}`, {
|
const userdata_req = await fetch(`${user_api}/users/${uuid}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
});
|
});
|
||||||
@ -83,7 +83,7 @@ export default class extends Aview {
|
|||||||
(document.getElementById("displayName-input") as HTMLInputElement).value = userdata.displayName;
|
(document.getElementById("displayName-input") as HTMLInputElement).value = userdata.displayName;
|
||||||
|
|
||||||
document.getElementById("displayName-button")?.addEventListener("click", async () => {
|
document.getElementById("displayName-button")?.addEventListener("click", async () => {
|
||||||
const changeDisplayName_req = await fetch(`http://localhost:3002/users/${uuid}/displayName`, {
|
const changeDisplayName_req = await fetch(`${user_api}/users/${uuid}/displayName`, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers: { "Content-Type": "application/json", },
|
headers: { "Content-Type": "application/json", },
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
@ -98,7 +98,7 @@ export default class extends Aview {
|
|||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById("deleteAccount-button")?.addEventListener("click", async () => {
|
document.getElementById("deleteAccount-button")?.addEventListener("click", async () => {
|
||||||
const delete_req = await fetch(`http://localhost:3001/`, {
|
const delete_req = await fetch(auth_api + "/", {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
});
|
});
|
||||||
@ -134,7 +134,7 @@ export default class extends Aview {
|
|||||||
});
|
});
|
||||||
|
|
||||||
(document.getElementById("upload-submit") as HTMLButtonElement).onclick = async () => {
|
(document.getElementById("upload-submit") as HTMLButtonElement).onclick = async () => {
|
||||||
const up_req = await fetch(`http://localhost:3002/users/${uuid}/avatar`, {
|
const up_req = await fetch(`${user_api}/users/${uuid}/avatar`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": upload.files[0].type } ,
|
headers: { "Content-Type": upload.files[0].type } ,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
@ -142,14 +142,14 @@ export default class extends Aview {
|
|||||||
});
|
});
|
||||||
console.log(up_req.status);
|
console.log(up_req.status);
|
||||||
};
|
};
|
||||||
|
|
||||||
const totpButton = document.getElementById("2fa-button") as HTMLButtonElement;
|
const totpButton = document.getElementById("2fa-button") as HTMLButtonElement;
|
||||||
|
|
||||||
if ((await isTOTPEnabled()) === true) {
|
if ((await isTOTPEnabled()) === true) {
|
||||||
totpButton.innerHTML = "disable 2fa";
|
totpButton.innerHTML = "disable 2fa";
|
||||||
|
|
||||||
document.getElementById("2fa-button")?.addEventListener("click", async () => {
|
document.getElementById("2fa-button")?.addEventListener("click", async () => {
|
||||||
const totp_req = await fetch(`http://localhost:3001/2fa`, {
|
const totp_req = await fetch(`${user_api}/2fa`, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
credentials: "include"
|
credentials: "include"
|
||||||
})
|
})
|
||||||
@ -162,9 +162,9 @@ export default class extends Aview {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
totpButton.innerHTML = "enable 2fa";
|
totpButton.innerHTML = "enable 2fa";
|
||||||
|
|
||||||
document.getElementById("2fa-button")?.addEventListener("click", async () => {
|
document.getElementById("2fa-button")?.addEventListener("click", async () => {
|
||||||
const totp_req = await fetch(`http://localhost:3001/2fa`, {
|
const totp_req = await fetch(`${user_api}/2fa`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
credentials: "include"
|
credentials: "include"
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import Aview from "./Aview.ts";
|
import Aview from "./Aview.ts";
|
||||||
import { isLogged } from "../main.js";
|
|
||||||
import { dragElement } from "./drag.js";
|
import { dragElement } from "./drag.js";
|
||||||
import { setOnekoState, setBallPos, setOnekoOffset, setSleepPos } from "../oneko.ts";
|
import { setOnekoState, setBallPos, setOnekoOffset, setSleepPos } from "../oneko.ts";
|
||||||
|
import { isLogged , user_api, auth_api } from "../main.js";
|
||||||
|
|
||||||
export default class extends Aview {
|
export default class extends Aview {
|
||||||
running: boolean;
|
running: boolean;
|
||||||
@ -630,7 +630,7 @@ export default class extends Aview {
|
|||||||
if (await isLogged())
|
if (await isLogged())
|
||||||
{
|
{
|
||||||
let uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
let uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
||||||
fetch(`http://localhost:3002/users/${uuid}/matchHistory?game=tetris`, {
|
fetch(`${user_api}/users/${uuid}/matchHistory?game=tetris`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json", },
|
headers: { "Content-Type": "application/json", },
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import Aview from "./Aview.ts";
|
import Aview from "./Aview.ts";
|
||||||
import { isLogged } from "../main.js";
|
import { isLogged, user_api, auth_api } from "../main.js";
|
||||||
import { dragElement } from "./drag.js";
|
import { dragElement } from "./drag.js";
|
||||||
import { setOnekoState, setBallPos, setOnekoOffset, setSleepPos } from "../oneko.ts";
|
import { setOnekoState, setBallPos, setOnekoOffset, setSleepPos } from "../oneko.ts";
|
||||||
|
|
||||||
@ -66,6 +66,8 @@ export default class extends Aview {
|
|||||||
let p2_score: number = 0;
|
let p2_score: number = 0;
|
||||||
let p1_name: string;
|
let p1_name: string;
|
||||||
let p2_name: string;
|
let p2_name: string;
|
||||||
|
let p1_displayName: string;
|
||||||
|
let p2_displayName: string;
|
||||||
|
|
||||||
const view = this;
|
const view = this;
|
||||||
|
|
||||||
@ -667,7 +669,7 @@ export default class extends Aview {
|
|||||||
if (await isLogged() && this.id == 0)
|
if (await isLogged() && this.id == 0)
|
||||||
{
|
{
|
||||||
let uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
let uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
||||||
fetch(`http://localhost:3002/users/${uuid}/matchHistory?game=tetris`, {
|
fetch(`${user_api}/users/${uuid}/matchHistory?game=tetris`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json", },
|
headers: { "Content-Type": "application/json", },
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
@ -862,7 +864,7 @@ export default class extends Aview {
|
|||||||
ctx.fillRect(4, 4, 120, 60);
|
ctx.fillRect(4, 4, 120, 60);
|
||||||
ctx.fillStyle = "#fff";
|
ctx.fillStyle = "#fff";
|
||||||
ctx.font = "12px Kubasta";
|
ctx.font = "12px Kubasta";
|
||||||
ctx.fillText(`${this.id == 0 ? p1_name : p2_name}: ${this.id == 0 ? p1_score : p2_score}`, 8, 20);
|
ctx.fillText(`${this.id == 0 ? p1_displayName : p2_displayName}: ${this.id == 0 ? p1_score : p2_score}`, 8, 20);
|
||||||
ctx.fillText(`score: ${this.score}`, 8, 36);
|
ctx.fillText(`score: ${this.score}`, 8, 36);
|
||||||
ctx.fillText(`lines: ${this.lines}`, 8, 52);
|
ctx.fillText(`lines: ${this.lines}`, 8, 52);
|
||||||
|
|
||||||
@ -933,26 +935,48 @@ export default class extends Aview {
|
|||||||
p2_input.value = "player 2";
|
p2_input.value = "player 2";
|
||||||
if (await isLogged())
|
if (await isLogged())
|
||||||
{
|
{
|
||||||
uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
||||||
const userdata_req = await fetch(`http://localhost:3002/users/${uuid}`, {
|
p1_input.value = uuid;
|
||||||
method: "GET",
|
|
||||||
credentials: "include",
|
|
||||||
});
|
|
||||||
if (userdata_req.status == 404)
|
|
||||||
{
|
|
||||||
console.error("invalid user");
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
let userdata = await userdata_req.json();
|
|
||||||
p1_input.value = userdata.displayName;
|
|
||||||
p1_input.readOnly = true;
|
p1_input.readOnly = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
p1_input.value = "player 1";
|
p1_input.value = "player 1";
|
||||||
|
|
||||||
document.getElementById("game-start")?.addEventListener("click", () => {
|
document.getElementById("game-start")?.addEventListener("click", async () => {
|
||||||
p1_name = p1_input.value.length > 16 ? p1_input.value.substring(0, 16) + "." : p1_input.value;
|
let p1_isvalid = true;
|
||||||
p2_name = p2_input.value.length > 16 ? p2_input.value.substring(0, 16) + "." : p2_input.value;
|
let p2_isvalid = true;
|
||||||
|
if (await isLogged()) {
|
||||||
|
const p1_req = await fetch(`${user_api}/users/${p1_input.value}`, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
const p2_req = await fetch(`${user_api}/users/${p2_input.value}`, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
if (p1_req.status != 200)
|
||||||
|
p1_isvalid = false;
|
||||||
|
else
|
||||||
|
p1_displayName = (await p1_req.json()).displayName;
|
||||||
|
|
||||||
|
if (p2_req.status != 200)
|
||||||
|
p2_isvalid = false;
|
||||||
|
else
|
||||||
|
p2_displayName = (await p2_req.json()).displayName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p1_isvalid = p2_isvalid = false;
|
||||||
|
|
||||||
|
p1_name = p1_input.value;
|
||||||
|
p2_name = p2_input.value;
|
||||||
|
if (!p1_isvalid)
|
||||||
|
p1_displayName = p1_name;
|
||||||
|
if (!p2_isvalid)
|
||||||
|
p2_displayName = p2_name;
|
||||||
|
|
||||||
|
p1_displayName = p1_displayName.length > 16 ? p1_displayName.substring(0, 16) + "." : p1_displayName;
|
||||||
|
p2_displayName = p2_displayName.length > 16 ? p2_displayName.substring(0, 16) + "." : p2_displayName;
|
||||||
|
|
||||||
document.getElementById("player-inputs").remove();
|
document.getElementById("player-inputs").remove();
|
||||||
document.getElementById("game-boards").classList.remove("hidden");
|
document.getElementById("game-boards").classList.remove("hidden");
|
||||||
game1 = new Game("board1", 0);
|
game1 = new Game("board1", 0);
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import { navigationManager } from "../main.ts";
|
import { navigationManager, user_api, auth_api } from "../main.ts";
|
||||||
import { dragElement } from "./drag.ts";
|
import { dragElement } from "./drag.ts";
|
||||||
|
|
||||||
async function totpVerify() {
|
async function totpVerify() {
|
||||||
const code = (document.getElementById("totpPin") as HTMLInputElement).value;
|
const code = (document.getElementById("totpPin") as HTMLInputElement).value;
|
||||||
const data_req = await fetch('http://localhost:3001/2fa/verify', {
|
const data_req = await fetch(auth_api + '/2fa/verify', {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@ -1,14 +1,17 @@
|
|||||||
import Aview from "./Aview.ts"
|
import Aview from "./Aview.ts"
|
||||||
|
import { isLogged, user_api } from "../main.js"
|
||||||
import { dragElement } from "./drag.ts";
|
import { dragElement } from "./drag.ts";
|
||||||
import { setOnekoState, setBallPos } from "../oneko.ts"
|
import { setOnekoState, setBallPos, setOnekoOffset } from "../oneko.ts"
|
||||||
|
|
||||||
export default class extends Aview {
|
export default class extends Aview {
|
||||||
|
running: boolean;
|
||||||
|
|
||||||
constructor()
|
constructor()
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
this.setTitle("Tournament");
|
this.setTitle("Tournament");
|
||||||
setOnekoState("default");
|
setOnekoState("default");
|
||||||
|
this.running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getHTML() {
|
async getHTML() {
|
||||||
@ -23,7 +26,8 @@ export default class extends Aview {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg-neutral-200 dark:bg-neutral-800 text-center p-10 pt-5 space-y-4 reverse-border">
|
<div id="main-div" class="bg-neutral-200 dark:bg-neutral-800 text-center p-10 pt-5 space-y-4 reverse-border">
|
||||||
|
<div id="tournament-id">
|
||||||
<p class="text-neutral-900 dark:text-white text-lg font-bold pb-4">how many players ?</p>
|
<p class="text-neutral-900 dark:text-white text-lg font-bold pb-4">how many players ?</p>
|
||||||
<div class="flex flex-col space-y-4">
|
<div class="flex flex-col space-y-4">
|
||||||
<select id="playerNumber" class="bg-white text-shadow-neutral-900 p-2 input-border">
|
<select id="playerNumber" class="bg-white text-shadow-neutral-900 p-2 input-border">
|
||||||
@ -37,28 +41,371 @@ export default class extends Aview {
|
|||||||
<button type="submit" id="bracket-generate" class="default-button">create the bracket</button>
|
<button type="submit" id="bracket-generate" class="default-button">create the bracket</button>
|
||||||
<div id="bracket" class="flex flex-col space-y-6 items-center"></div>
|
<div id="bracket" class="flex flex-col space-y-6 items-center"></div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="announcement" class="hidden flex flex-col space-y-8">
|
||||||
|
<div id="bracket-announcement" class="flex flex-col space-y-6 items-center">
|
||||||
|
</div>
|
||||||
|
<span id="announcement-text" class="text-lg font-bold text-neutral-900 dark:text-white"></span>
|
||||||
|
<button type="submit" id="tournament-continue" class="default-button">let's go</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="winner-div" class="hidden flex flex-col items-center space-y-8">
|
||||||
|
<img src="https://api.kanel.ovh/pp?id=3" class="w-25 h-25 default-border" \>
|
||||||
|
<span id="winner-text" class="text-2x1 text-neutral-900 dark:text-white"></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async runGame(p1_id: number, p2_id: number, players: string[]): Promise<number> {
|
||||||
|
return new Promise<number>(async (resolve) => {
|
||||||
|
//console.log(p1_id, p2_id, players, players[p1_id], players[p2_id]);
|
||||||
|
let p1_name = players[p1_id];
|
||||||
|
let p2_name = players[p2_id];
|
||||||
|
|
||||||
|
let uuid: string;
|
||||||
|
let start: number = 0;
|
||||||
|
let elapsed: number;
|
||||||
|
|
||||||
|
let game_playing: boolean = false;
|
||||||
|
let match_over: boolean = false;
|
||||||
|
let p1_score: number = 0;
|
||||||
|
let p2_score: number = 0;
|
||||||
|
|
||||||
|
let p1_displayName: string;
|
||||||
|
let p2_displayName: string;
|
||||||
|
|
||||||
|
let countdown: number = 3;
|
||||||
|
let countdownTimer: number = 0;
|
||||||
|
|
||||||
|
let canvas: HTMLCanvasElement;
|
||||||
|
let ctx: CanvasRenderingContext2D;
|
||||||
|
|
||||||
|
const paddleOffset: number = 15;
|
||||||
|
const paddleHeight: number = 100;
|
||||||
|
const paddleWidth: number = 10;
|
||||||
|
const ballSize: number = 10;
|
||||||
|
|
||||||
|
const paddleSpeed: number = 727 * 0.69;
|
||||||
|
let leftPaddleY: number;
|
||||||
|
let rightPaddleY: number;
|
||||||
|
let ballX: number;
|
||||||
|
let ballY: number;
|
||||||
|
let ballSpeed: number = 200;
|
||||||
|
let ballSpeedX: number = 300;
|
||||||
|
let ballSpeedY: number = 10;
|
||||||
|
|
||||||
|
const keys: Record<string, boolean> = {};
|
||||||
|
|
||||||
|
document.addEventListener("keydown", e => { keys[e.key] = true; });
|
||||||
|
document.addEventListener("keyup", e => { keys[e.key] = false; });
|
||||||
|
|
||||||
|
function movePaddles() {
|
||||||
|
if ((keys["w"] || keys["W"]) && leftPaddleY > 0)
|
||||||
|
leftPaddleY -= paddleSpeed * elapsed;
|
||||||
|
if ((keys["s"] || keys["S"]) && leftPaddleY < canvas.height - paddleHeight)
|
||||||
|
leftPaddleY += paddleSpeed * elapsed;
|
||||||
|
if (keys["ArrowUp"] && rightPaddleY > 0)
|
||||||
|
rightPaddleY -= paddleSpeed * elapsed;
|
||||||
|
if (keys["ArrowDown"] && rightPaddleY < canvas.height - paddleHeight)
|
||||||
|
rightPaddleY += paddleSpeed * elapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBounceVelocity(paddleY: number) {
|
||||||
|
const paddleCenterY = paddleY + paddleHeight / 2;
|
||||||
|
|
||||||
|
let n = (ballY - paddleCenterY) / (paddleHeight / 2);
|
||||||
|
n = Math.max(-1, Math.min(1, n));
|
||||||
|
let theta = n * ((75 * Math.PI) / 180);
|
||||||
|
ballSpeedY = ballSpeed * Math.sin(theta);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function moveBall() {
|
||||||
|
let length = Math.sqrt(ballSpeedX * ballSpeedX + ballSpeedY * ballSpeedY);
|
||||||
|
let scale = ballSpeed / length;
|
||||||
|
ballX += (ballSpeedX * scale) * elapsed;
|
||||||
|
ballY += (ballSpeedY * scale) * elapsed;
|
||||||
|
|
||||||
|
if (ballY <= 0 || ballY >= canvas.height - ballSize)
|
||||||
|
ballSpeedY *= -1;
|
||||||
|
|
||||||
|
if (ballX <= paddleWidth + paddleOffset && ballX >= paddleOffset &&
|
||||||
|
ballY > leftPaddleY && ballY < leftPaddleY + paddleHeight) {
|
||||||
|
ballSpeedX *= -1;
|
||||||
|
ballX = paddleWidth + paddleOffset;
|
||||||
|
getBounceVelocity(leftPaddleY);
|
||||||
|
ballSpeed += 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ballX >= canvas.width - paddleWidth - ballSize - paddleOffset && ballX <= canvas.width - ballSize - paddleOffset &&
|
||||||
|
ballY > rightPaddleY && ballY < rightPaddleY + paddleHeight) {
|
||||||
|
ballSpeedX *= -1;
|
||||||
|
ballX = canvas.width - paddleWidth - ballSize - paddleOffset;
|
||||||
|
getBounceVelocity(rightPaddleY);
|
||||||
|
ballSpeed += 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// scoring
|
||||||
|
if (ballX < 0 || ballX > canvas.width - ballSize) {
|
||||||
|
setOnekoState("default");
|
||||||
|
game_playing = false;
|
||||||
|
if (ballX < 0)
|
||||||
|
p2_score++;
|
||||||
|
else
|
||||||
|
p1_score++;
|
||||||
|
|
||||||
|
if (p1_score === 3 || p2_score === 3) {
|
||||||
|
if (await isLogged()) {
|
||||||
|
let uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
||||||
|
fetch(`${user_api}/users/${uuid}/matchHistory?game=pong`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json", },
|
||||||
|
credentials: "include",
|
||||||
|
body: JSON.stringify({
|
||||||
|
"game": "pong",
|
||||||
|
"opponent": p2_name,
|
||||||
|
"myScore": p1_score,
|
||||||
|
"opponentScore": p2_score,
|
||||||
|
"date": Date.now(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
match_over = true;
|
||||||
|
resolve(p1_score == 3 ? p1_id : p2_id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
countdown = 3;
|
||||||
|
countdownTimer = performance.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
ballX = canvas.width / 2;
|
||||||
|
ballY = canvas.height / 2;
|
||||||
|
ballSpeed = 200;
|
||||||
|
ballSpeedX = 300 * ((ballSpeedX > 0) ? 1 : -1);
|
||||||
|
ballSpeedY = 10;
|
||||||
|
ballSpeedX = -ballSpeedX;
|
||||||
|
leftPaddleY = canvas.height / 2 - paddleHeight / 2;
|
||||||
|
rightPaddleY = canvas.height / 2 - paddleHeight / 2;
|
||||||
|
}
|
||||||
|
setBallPos(ballX, ballY);
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw() {
|
||||||
|
ctx.fillStyle = "black";
|
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
ctx.strokeStyle = "white";
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.setLineDash([5, 10]);
|
||||||
|
ctx.moveTo(canvas.width / 2, 0);
|
||||||
|
ctx.lineTo(canvas.width / 2, canvas.height);
|
||||||
|
ctx.stroke();
|
||||||
|
|
||||||
|
ctx.fillStyle = "white";
|
||||||
|
ctx.fillRect(paddleOffset, leftPaddleY, paddleWidth, paddleHeight);
|
||||||
|
ctx.fillRect(canvas.width - paddleWidth - paddleOffset, rightPaddleY, paddleWidth, paddleHeight);
|
||||||
|
|
||||||
|
ctx.fillStyle = "white";
|
||||||
|
if (game_playing)
|
||||||
|
ctx.fillRect(ballX, ballY, ballSize, ballSize);
|
||||||
|
|
||||||
|
ctx.font = "24px Kubasta";
|
||||||
|
let text_score = `${p1_score} - ${p2_score}`;
|
||||||
|
ctx.fillText(text_score, canvas.width / 2 - (ctx.measureText(text_score).width / 2), 25);
|
||||||
|
ctx.fillText(p1_displayName, canvas.width / 4 - (ctx.measureText(p1_name).width / 2), 45);
|
||||||
|
ctx.fillText(p2_displayName, (canvas.width / 4 * 3) - (ctx.measureText(p2_name).width / 2), 45);
|
||||||
|
|
||||||
|
if (match_over) {
|
||||||
|
ctx.font = "32px Kubasta";
|
||||||
|
const winner = `${p1_score > p2_score ? p1_name : p2_name} won :D`;
|
||||||
|
ctx.fillText(winner, canvas.width / 2 - (ctx.measureText(winner).width / 2), canvas.height / 2 + 16);
|
||||||
|
document.getElementById("game-buttons")?.classList.remove("hidden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function startCountdown() {
|
||||||
|
const now = performance.now();
|
||||||
|
if (countdown > 0) {
|
||||||
|
if (now - countdownTimer >= 500) {
|
||||||
|
countdown--;
|
||||||
|
countdownTimer = now;
|
||||||
|
}
|
||||||
|
ctx.font = "48px Kubasta";
|
||||||
|
ctx.fillText(countdown.toString(), canvas.width / 2 - 10, canvas.height / 2 + 24);
|
||||||
|
}
|
||||||
|
else if (countdown === 0) {
|
||||||
|
ctx.font = "48px Kubasta";
|
||||||
|
ctx.fillText("Go!", canvas.width / 2 - 30, canvas.height / 2 + 24);
|
||||||
|
setTimeout(() => {
|
||||||
|
game_playing = true;
|
||||||
|
countdown = -1;
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const gameLoop = async (timestamp: number) => {
|
||||||
|
elapsed = (timestamp - start) / 1000;
|
||||||
|
start = timestamp;
|
||||||
|
if (game_playing) {
|
||||||
|
movePaddles();
|
||||||
|
await moveBall();
|
||||||
|
}
|
||||||
|
draw();
|
||||||
|
if (!game_playing)
|
||||||
|
startCountdown();
|
||||||
|
if (this.running)
|
||||||
|
requestAnimationFrame(gameLoop);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
document.getElementById("game-retry")?.addEventListener("click", () => {
|
||||||
|
setOnekoState("pong");
|
||||||
|
document.getElementById("game-buttons")?.classList.add("hidden");
|
||||||
|
game_playing = false;
|
||||||
|
match_over = false;
|
||||||
|
p1_score = 0;
|
||||||
|
p2_score = 0;
|
||||||
|
|
||||||
|
countdown = 3;
|
||||||
|
countdownTimer = performance.now();
|
||||||
|
});
|
||||||
|
|
||||||
|
let p1_isvalid = true;
|
||||||
|
let p2_isvalid = true;
|
||||||
|
if (await isLogged()) {
|
||||||
|
const p1_req = await fetch(`${user_api}/users/${p1_name}`, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
const p2_req = await fetch(`${user_api}/users/${p2_name}`, {
|
||||||
|
method: "GET",
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (p1_req.status == 200)
|
||||||
|
p1_displayName = (await p1_req.json()).displayName;
|
||||||
|
else
|
||||||
|
p1_displayName = p1_name;
|
||||||
|
|
||||||
|
if (p2_req.status == 200)
|
||||||
|
p2_displayName = (await p2_req.json()).displayName;
|
||||||
|
else
|
||||||
|
p2_displayName = p2_name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p1_displayName = p1_name;
|
||||||
|
p2_displayName = p2_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
p1_displayName = p1_displayName.length > 16 ? p1_displayName.substring(0, 16) + "." : p1_displayName;
|
||||||
|
p2_displayName = p2_displayName.length > 16 ? p2_displayName.substring(0, 16) + "." : p2_displayName;
|
||||||
|
p1_name = p1_name.length > 16 ? p1_name.substring(0, 16) + "." : p1_name;
|
||||||
|
p2_name = p2_name.length > 16 ? p2_name.substring(0, 16) + "." : p2_name;
|
||||||
|
document.getElementById("tournament-ui")?.classList.add("hidden");
|
||||||
|
|
||||||
|
canvas = document.createElement("canvas");
|
||||||
|
canvas.id = "gameCanvas";
|
||||||
|
canvas.classList.add("reverse-border");
|
||||||
|
|
||||||
|
document.getElementById("main-div")?.prepend(canvas);
|
||||||
|
|
||||||
|
ctx = canvas.getContext("2d", { alpha: false }) as CanvasRenderingContext2D;
|
||||||
|
ctx.canvas.width = 600;
|
||||||
|
ctx.canvas.height = 600;
|
||||||
|
|
||||||
|
leftPaddleY = canvas.height / 2 - paddleHeight / 2;
|
||||||
|
rightPaddleY = canvas.height / 2 - paddleHeight / 2;
|
||||||
|
ballX = canvas.width / 2;
|
||||||
|
ballY = canvas.height / 2;
|
||||||
|
|
||||||
|
setOnekoState("pong");
|
||||||
|
setOnekoOffset();
|
||||||
|
requestAnimationFrame(gameLoop);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForUserClick(buttonId: string): Promise<void> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const button = document.getElementById(buttonId);
|
||||||
|
if (!button) return resolve(); // failsafe if no button
|
||||||
|
|
||||||
|
const handler = () => {
|
||||||
|
button.removeEventListener("click", handler);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
button.addEventListener("click", handler);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
tournament_state: number[][];
|
||||||
|
i: number = 0;
|
||||||
|
space: number;
|
||||||
|
|
||||||
|
updateBracketDisplay(tournament: number[][], players: string[]) {
|
||||||
|
for (let i of Array(tournament[0].length).keys())
|
||||||
|
this.tournament_state[this.i][i] = tournament[0][i];
|
||||||
|
for (let i of Array(tournament[1].length).keys())
|
||||||
|
{
|
||||||
|
console.log(this.tournament_state, this.i, i);
|
||||||
|
this.tournament_state[this.i + 1][i] = tournament[1][i];
|
||||||
|
}
|
||||||
|
this.i++;
|
||||||
|
const container = document.getElementById("bracket-announcement");
|
||||||
|
if (!container) return;
|
||||||
|
container.innerHTML = ""; // clear old bracket
|
||||||
|
|
||||||
|
const bracketWrapper = document.createElement("div");
|
||||||
|
bracketWrapper.className = "flex space-x-8 overflow-x-auto";
|
||||||
|
|
||||||
|
// replicate generateBracket() spacing logic
|
||||||
|
let previousPadding = 4;
|
||||||
|
|
||||||
|
for (let round = 0; round < this.tournament_state.length; round++) {
|
||||||
|
const roundColumn = document.createElement("div");
|
||||||
|
|
||||||
|
if (round === 0) {
|
||||||
|
roundColumn.className = `flex flex-col mt-${this.space} space-y-4`;
|
||||||
|
} else {
|
||||||
|
previousPadding = previousPadding * 2 + 10;
|
||||||
|
roundColumn.className = `flex flex-col justify-center space-y-${previousPadding}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// each player slot or winner
|
||||||
|
for (let i = 0; i < this.tournament_state[round].length; i++) {
|
||||||
|
const playerIndex = this.tournament_state[round][i];
|
||||||
|
const name =
|
||||||
|
playerIndex !== undefined && playerIndex !== null
|
||||||
|
? players[playerIndex]
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const cell = document.createElement("div");
|
||||||
|
cell.className =
|
||||||
|
"w-32 h-10 flex items-center justify-center bg-white text-center text-sm input-border";
|
||||||
|
cell.textContent = name || "";
|
||||||
|
roundColumn.appendChild(cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
bracketWrapper.appendChild(roundColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
container.appendChild(bracketWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
async run() {
|
async run() {
|
||||||
dragElement(document.getElementById("window"));
|
dragElement(document.getElementById("window"));
|
||||||
const generateBracket = async (playerCount: number) => {
|
const generateBracket = async (playerCount: number) => {
|
||||||
|
this.tournament_state = [];
|
||||||
|
let initPlayerCount = playerCount;
|
||||||
document.getElementById("bracket").innerHTML = "";
|
document.getElementById("bracket").innerHTML = "";
|
||||||
|
|
||||||
const rounds = Math.ceil(Math.log2(playerCount));
|
const rounds: number = Math.ceil(Math.log2(playerCount));
|
||||||
const totalSlots = 2 ** rounds;
|
const totalSlots: number = 2 ** rounds;
|
||||||
const byes = totalSlots - playerCount;
|
let odd: number = 0;
|
||||||
|
let notPowPlayersCount: number = 0;
|
||||||
let odd = 0;
|
let tournament: number[][] = [];
|
||||||
if (playerCount > 9 || (playerCount != 3 && playerCount % 2 != 0))
|
|
||||||
{
|
|
||||||
console.error("odd numbers are temporarily invalids");
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let notPowPlayersCount = 0;
|
|
||||||
|
|
||||||
if ((playerCount & (playerCount - 1)) != 0)
|
if ((playerCount & (playerCount - 1)) != 0)
|
||||||
notPowPlayersCount = playerCount - (2 ** Math.floor(Math.log2(playerCount)));
|
notPowPlayersCount = playerCount - (2 ** Math.floor(Math.log2(playerCount)));
|
||||||
@ -72,58 +419,59 @@ export default class extends Aview {
|
|||||||
|
|
||||||
// Round 0: Player input column
|
// Round 0: Player input column
|
||||||
const playerInputColumn = document.createElement("div");
|
const playerInputColumn = document.createElement("div");
|
||||||
|
this.space = (notPowPlayersCount + odd) * 28;
|
||||||
playerInputColumn.className = `flex flex-col mt-${(notPowPlayersCount + odd) * 28} space-y-4`;
|
playerInputColumn.className = `flex flex-col mt-${(notPowPlayersCount + odd) * 28} space-y-4`;
|
||||||
|
|
||||||
|
tournament.push([]);
|
||||||
|
this.tournament_state.push([]);
|
||||||
initialPlayers.forEach((name, i) => {
|
initialPlayers.forEach((name, i) => {
|
||||||
const input = document.createElement("input");
|
const input = document.createElement("input");
|
||||||
input.type = "text";
|
input.type = "text";
|
||||||
input.id = `playerName${i}`;
|
input.id = `playerName${i}`;
|
||||||
input.value = "";
|
input.value = name;
|
||||||
input.placeholder = name;
|
input.placeholder = name;
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
isLogged().then((value) => {
|
||||||
|
if (value) {
|
||||||
|
let uuid = document.cookie.match(new RegExp('(^| )' + "uuid" + '=([^;]+)'))[2];
|
||||||
|
input.value = uuid;
|
||||||
|
input.readOnly = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
input.className = "w-32 h-10 p-2 text-sm bg-white disabled:bg-gray-200 input-border";
|
input.className = "w-32 h-10 p-2 text-sm bg-white disabled:bg-gray-200 input-border";
|
||||||
playerInputColumn.appendChild(input);
|
playerInputColumn.appendChild(input);
|
||||||
|
tournament[0].push(i);
|
||||||
|
this.tournament_state[0].push(-1);
|
||||||
});
|
});
|
||||||
|
|
||||||
bracketWrapper.appendChild(playerInputColumn);
|
bracketWrapper.appendChild(playerInputColumn);
|
||||||
|
|
||||||
let currentRound = initialPlayers;
|
let currentRound = initialPlayers;
|
||||||
let previousPadding = 4;
|
let previousPadding = 4;
|
||||||
|
tournament.push([]);
|
||||||
for (let round = 1; round <= rounds; round++)
|
for (let round = 1; round <= rounds; round++)
|
||||||
{
|
{
|
||||||
|
this.tournament_state.push([]);
|
||||||
const roundColumn = document.createElement("div");
|
const roundColumn = document.createElement("div");
|
||||||
previousPadding = previousPadding * 2 + 10
|
previousPadding = previousPadding * 2 + 10
|
||||||
roundColumn.className = `flex flex-col justify-center space-y-${previousPadding}`;
|
roundColumn.className = `flex flex-col justify-center space-y-${previousPadding}`;
|
||||||
|
|
||||||
const nextRound: string[] = [];
|
const nextRound: string[] = [];
|
||||||
|
|
||||||
if (!notPowPlayersCount)
|
while (notPowPlayersCount) {
|
||||||
{
|
tournament[1].push(playerCount);
|
||||||
if (odd)
|
this.tournament_state[1].push(-1);
|
||||||
{
|
const input = document.createElement("input");
|
||||||
const input = document.createElement("input");
|
input.type = "text";
|
||||||
input.type = "text";
|
input.id = `playerName${playerCount}`;
|
||||||
input.id = `playerName${playerCount}`;
|
input.value = `player ${playerCount + 1}`;
|
||||||
input.value = `player ${++playerCount}`;
|
input.placeholder = `player ${++playerCount}`;
|
||||||
input.placeholder = `player ${++playerCount}`;
|
input.className =
|
||||||
input.className =
|
"w-32 h-10 p-2 text-sm bg-white disabled:bg-gray-200 input-border";
|
||||||
"w-32 h-10 p-2 text-sm bg-white disabled:bg-gray-200 input-border";
|
roundColumn.appendChild(input);
|
||||||
roundColumn.appendChild(input);
|
--notPowPlayersCount;
|
||||||
odd--;
|
|
||||||
nextRound.push("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (notPowPlayersCount)
|
|
||||||
{
|
|
||||||
const input = document.createElement("input");
|
|
||||||
input.type = "text";
|
|
||||||
input.id = `playerName${playerCount}`;
|
|
||||||
input.value = "";
|
|
||||||
input.placeholder = `player ${++playerCount}`;
|
|
||||||
input.className =
|
|
||||||
"w-32 h-10 p-2 text-sm bg-white disabled:bg-gray-200 input-border";
|
|
||||||
roundColumn.appendChild(input);
|
|
||||||
--notPowPlayersCount;
|
|
||||||
nextRound.push("");
|
nextRound.push("");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,19 +488,47 @@ export default class extends Aview {
|
|||||||
nextRound.push("");
|
nextRound.push("");
|
||||||
|
|
||||||
roundColumn.appendChild(matchDiv);
|
roundColumn.appendChild(matchDiv);
|
||||||
|
this.tournament_state[round].push(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bracketWrapper.appendChild(roundColumn);
|
bracketWrapper.appendChild(roundColumn);
|
||||||
currentRound = nextRound;
|
currentRound = nextRound;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById("bracket").appendChild(document.createElement("hr")).classList.add("my-4", "mb-8", "w-64", "reverse-border");
|
document.getElementById("bracket")?.appendChild(document.createElement("hr")).classList.add("my-4", "mb-8", "w-64", "reverse-border");
|
||||||
document.getElementById("bracket").appendChild(bracketWrapper);
|
document.getElementById("bracket")?.appendChild(bracketWrapper);
|
||||||
const btn = document.getElementById("bracket").appendChild(document.createElement("button"));
|
const btn = document.getElementById("bracket")?.appendChild(document.createElement("button"));
|
||||||
|
if (!btn) return;
|
||||||
btn.classList.add("default-button", "w-full");
|
btn.classList.add("default-button", "w-full");
|
||||||
btn.id = "tournament-play";
|
btn.id = "tournament-play";
|
||||||
btn.onclick = () => {
|
btn.onclick = async () => {
|
||||||
console.log("ok");
|
document.getElementById("tournament-id")?.classList.add("hidden");
|
||||||
|
let players: string[] = [];
|
||||||
|
for (let i of Array(initPlayerCount).keys()) {
|
||||||
|
players.push((document.getElementById(`playerName${i}`) as HTMLInputElement).value);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (tournament[0].length > 1)
|
||||||
|
{
|
||||||
|
this.updateBracketDisplay(tournament, players);
|
||||||
|
while(tournament[0].length > 0)
|
||||||
|
{
|
||||||
|
const p1 = tournament[0].shift() as number;
|
||||||
|
const p2 = tournament[0].shift() as number;
|
||||||
|
|
||||||
|
document.getElementById("announcement-text").innerText = `${players[p1]} vs ${players[p2]}`;
|
||||||
|
document.getElementById("announcement")?.classList.remove("hidden");
|
||||||
|
await this.waitForUserClick("tournament-continue");
|
||||||
|
document.getElementById("announcement")?.classList.add("hidden");
|
||||||
|
const result = await this.runGame(p1, p2, players);
|
||||||
|
document.getElementById("gameCanvas")?.remove();
|
||||||
|
tournament[1].push(result);
|
||||||
|
}
|
||||||
|
tournament[0] = tournament[1];
|
||||||
|
tournament[1] = [];
|
||||||
|
}
|
||||||
|
document.getElementById("winner-div")?.classList.remove("hidden");
|
||||||
|
document.getElementById("winner-text").innerText = `${players[tournament[0][0]]} won the tournament !! ggs :D`;
|
||||||
};
|
};
|
||||||
btn.innerText = "start tournament !!";
|
btn.innerText = "start tournament !!";
|
||||||
|
|
||||||
@ -164,7 +540,5 @@ export default class extends Aview {
|
|||||||
return;
|
return;
|
||||||
generateBracket(+input.value);
|
generateBracket(+input.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user