From b52b43b250746e6bb5195d8b14dab62712665b53 Mon Sep 17 00:00:00 2001 From: y-syo Date: Tue, 21 Oct 2025 14:05:02 +0200 Subject: [PATCH] =?UTF-8?q?=E3=80=8C=E2=9C=A8=E3=80=8D=20feat(front):=20fr?= =?UTF-8?q?ont=20mainly=20done,=20waiting=20for=20image=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/front/index.html | 7 +- src/front/static/ts/main.ts | 14 +- src/front/static/ts/views/MainMenu.ts | 1 + .../static/ts/views/{Game.ts => Pong.ts} | 8 +- src/front/static/ts/views/Profile.ts | 105 ++++++++++++--- src/front/static/ts/views/ProfileMenu.ts | 1 + src/front/static/ts/views/Settings.ts | 4 +- src/front/static/ts/views/Tetris.ts | 37 ++++-- src/front/static/ts/views/TetrisVersus.ts | 121 ++++++++++++++---- 9 files changed, 235 insertions(+), 63 deletions(-) rename src/front/static/ts/views/{Game.ts => Pong.ts} (96%) diff --git a/src/front/index.html b/src/front/index.html index de47004..8532da2 100644 --- a/src/front/index.html +++ b/src/front/index.html @@ -26,10 +26,10 @@ tetris_game.ts - +
@@ -46,8 +46,7 @@ rusty tetris-guideline.pdf
-
- +
12:37
diff --git a/src/front/static/ts/main.ts b/src/front/static/ts/main.ts index 6abfa27..831d203 100644 --- a/src/front/static/ts/main.ts +++ b/src/front/static/ts/main.ts @@ -12,11 +12,21 @@ export async function isLogged(): Promise { if (uuid_req.status === 200) { let uuid = await uuid_req.json(); document.cookie = `uuid=${uuid.user};max-age=${60 * 60 * 24 * 7}`; + if (!document.getElementById("friends-btn")) + { + const btn: HTMLButtonElement = document.createElement("button") as HTMLButtonElement; + btn.id = "friends-btn"; + btn?.classList.add("taskbar-button"); + btn.innerText = "friends"; + document.getElementById("taskbar-trail")?.prepend(btn); + } return true; } else // 401 { document.cookie = `uuid=;max-age=0`; + const btn = document.getElementById("friends-btn") as HTMLButtonElement; + if (btn) btn.remove(); return false; } } @@ -32,7 +42,7 @@ const routes = [ { path: "/", view: () => import("./views/MainMenu.ts") }, { path: "/pong", view: () => import("./views/PongMenu.ts") }, - { path: "/pong/local", view: () => import("./views/Game.ts") }, + { path: "/pong/local", view: () => import("./views/Pong.ts") }, { path: "/pong/tournament", view: () => import("./views/TournamentMenu.ts") }, { path: "/tetris", view: () => import("./views/TetrisMenu.ts") }, @@ -102,8 +112,6 @@ document.addEventListener("DOMContentLoaded", () => { router(); }); -oneko(); - function updateClock() { const days = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']; diff --git a/src/front/static/ts/views/MainMenu.ts b/src/front/static/ts/views/MainMenu.ts index 6451c2d..8639808 100644 --- a/src/front/static/ts/views/MainMenu.ts +++ b/src/front/static/ts/views/MainMenu.ts @@ -1,4 +1,5 @@ import Aview from "./Aview.ts" +import { isLogged} from "../main.ts" import { setOnekoState } from "../oneko.ts" export default class extends Aview { diff --git a/src/front/static/ts/views/Game.ts b/src/front/static/ts/views/Pong.ts similarity index 96% rename from src/front/static/ts/views/Game.ts rename to src/front/static/ts/views/Pong.ts index 07d72b8..f103684 100644 --- a/src/front/static/ts/views/Game.ts +++ b/src/front/static/ts/views/Pong.ts @@ -28,8 +28,9 @@ export default class extends Aview {
-
+
+

enter the users ids/names

@@ -265,8 +266,8 @@ export default class extends Aview { countdown = 3; countdownTimer = performance.now(); }); - let p1_input = document.getElementById("player1"); - let p2_input = document.getElementById("player2"); + let p1_input: HTMLInputElement = document.getElementById("player1") as HTMLInputElement; + let p2_input: HTMLInputElement = document.getElementById("player2") as HTMLInputElement; p2_input.value = "Player 2"; if (await isLogged()) @@ -283,6 +284,7 @@ export default class extends Aview { } let userdata = await userdata_req.json(); p1_input.value = userdata.displayName; + p1_input.readOnly = true; } else p1_input.value = "Player 1"; diff --git a/src/front/static/ts/views/Profile.ts b/src/front/static/ts/views/Profile.ts index 2f2f899..b80bd0b 100644 --- a/src/front/static/ts/views/Profile.ts +++ b/src/front/static/ts/views/Profile.ts @@ -28,11 +28,11 @@ export default class extends Aview {
-
-
    +
    +
      +
    +
    -
    -
@@ -58,33 +58,108 @@ export default class extends Aview { } let userdata = await userdata_req.json(); - const matchCount_req = await fetch(`http://localhost:3002/users/${uuid}/matchHistory/count?game=tetris`, { + let matchCount_req = await fetch(`http://localhost:3002/users/${uuid}/matchHistory/count?game=pong`, { method: "GET", credentials: "include", }); - const matchCount = await matchCount_req.json(); + let matchCount = await matchCount_req.json(); - const matches_req = await fetch(`http://localhost:3002/users/${uuid}/matchHistory?game=tetris&iStart=0&iEnd=${matchCount.n_matches}`, { + let matches_req = await fetch(`http://localhost:3002/users/${uuid}/matchHistory?game=pong&iStart=0&iEnd=${matchCount.n_matches}`, { method: "GET", credentials: "include", }); - const matches = await matches_req.json(); + let matches = await matches_req.json(); - const main = document.getElementById("profile-scorelist"); + let main = document.getElementById("profile-pong-scorelist"); if (!main) return console.error("what"); if (matches.matchHistory) { for (let match of matches.matchHistory) { const newEntry = document.createElement("li"); - newEntry.classList.add("m-2", "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`; main.insertBefore(newEntry, main.firstChild); - // ########################################################################################################################################### - // - // ADD TX LINK : https://testnet.snowscan.xyz/tx/${match.tx} - // - // ########################################################################################################################################### + + const popup: HTMLDivElement = document.createElement("div"); + const id: number = Math.floor(Math.random() * 100000000000); + popup.id = `${id}`; + popup.classList.add("z-10", "absolute", "default-border"); + const header = popup.appendChild(document.createElement("div")); + header.classList.add("bg-linear-to-r", "from-orange-200", "to-orange-300", "flex", "flex-row", "min-w-35", "justify-between", "px-2"); + header.id = `${id}-header`; + header.appendChild(document.createElement("span")).innerText = "score.ts"; + const btn = header.appendChild(document.createElement("button")); + btn.innerText = " × "; + btn.onclick = () => { document.getElementById(`${id}`).remove(); }; + + const popup_content: HTMLSpanElement = popup.appendChild(document.createElement("div")); + popup_content.classList.add("flex", "flex-col", "bg-neutral-200", "dark:bg-neutral-800", "p-6", "pt-4", "text-neutral-900", "dark:text-white", "space-y-4"); + const date = new Date(match.score.date); + popup_content.appendChild(document.createElement("span")).innerText = `${date.toDateString()} ${date.getHours()}:${date.getMinutes().toString().padStart(2, '0')}`; + const score = popup_content.appendChild(document.createElement("span")); + score.classList.add(); + score.innerText = `${match.score.p1} : ${match.score.p1Score} - ${match.score.p2Score} : ${match.score.p2}`; + const tx = popup_content.appendChild(document.createElement("a")); + tx.href = `https://testnet.snowscan.xyz/tx/${match.tx}`; + tx.innerText = "transaction proof"; + tx.target = "_blank"; + tx.classList.add("default-button", "items-center", "justify-center", "text-center"); + + newEntry.onclick = () => { document.getElementById("app")?.appendChild(popup); dragElement(document.getElementById(`${id}`)); }; + console.log(match.tx); + } + } + + matchCount_req = await fetch(`http://localhost:3002/users/${uuid}/matchHistory/count?game=tetris`, { + method: "GET", + credentials: "include", + }); + matchCount = await matchCount_req.json(); + + matches_req = await fetch(`http://localhost:3002/users/${uuid}/matchHistory?game=tetris&iStart=0&iEnd=${matchCount.n_matches}`, { + method: "GET", + credentials: "include", + }); + matches = await matches_req.json(); + + main = document.getElementById("profile-tetris-scorelist"); + if (!main) + return console.error("what"); + + if (matches.matchHistory) { + for (let match of matches.matchHistory) { + 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.innerHTML = match.score.p1Score > match.score.p2Score ? `${match.score.p1} - winner` : `${match.score.p2} - winner`; + main.insertBefore(newEntry, main.firstChild); + + const popup: HTMLDivElement = document.createElement("div"); + const id: number = Math.floor(Math.random() * 100000000000); + popup.id = `${id}`; + popup.classList.add("z-10", "absolute", "default-border"); + const header = popup.appendChild(document.createElement("div")); + header.classList.add("bg-linear-to-r", "from-orange-200", "to-orange-300", "flex", "flex-row", "min-w-35", "justify-between", "px-2"); + header.id = `${id}-header`; + header.appendChild(document.createElement("span")).innerText = "score.ts"; + const btn = header.appendChild(document.createElement("button")); + btn.innerText = " × "; + btn.onclick = () => { document.getElementById(`${id}`).remove(); }; + + const popup_content: HTMLSpanElement = popup.appendChild(document.createElement("div")); + popup_content.classList.add("flex", "flex-col", "bg-neutral-200", "dark:bg-neutral-800", "p-6", "pt-4", "text-neutral-900", "dark:text-white", "space-y-4"); + const date = new Date(match.score.date); + popup_content.appendChild(document.createElement("span")).innerText = `${date.toDateString()} ${date.getHours()}:${date.getMinutes().toString().padStart(2, '0')}`; + const score = popup_content.appendChild(document.createElement("span")); + score.classList.add(); + score.innerText = `${match.score.p1} : ${match.score.p1Score} - ${match.score.p2Score} : ${match.score.p2}`; + const tx = popup_content.appendChild(document.createElement("a")); + tx.href = `https://testnet.snowscan.xyz/tx/${match.tx}`; + tx.innerText = "transaction proof"; + tx.target = "_blank"; + tx.classList.add("default-button", "items-center", "justify-center", "text-center"); + + newEntry.onclick = () => { document.getElementById("app")?.appendChild(popup); dragElement(document.getElementById(`${id}`)); }; console.log(match.tx); } } diff --git a/src/front/static/ts/views/ProfileMenu.ts b/src/front/static/ts/views/ProfileMenu.ts index c2937d5..68317c0 100644 --- a/src/front/static/ts/views/ProfileMenu.ts +++ b/src/front/static/ts/views/ProfileMenu.ts @@ -77,6 +77,7 @@ export default class extends Aview { method: "GET", credentials: "include", }); + isLogged(); if (req.status === 200) this.run(); else diff --git a/src/front/static/ts/views/Settings.ts b/src/front/static/ts/views/Settings.ts index fb5fbc6..5c70167 100644 --- a/src/front/static/ts/views/Settings.ts +++ b/src/front/static/ts/views/Settings.ts @@ -70,7 +70,7 @@ export default class extends Aview { }); document.getElementById("deleteAccount-button")?.addEventListener("click", async () => { - const delete_req = await fetch(`http://localhost:3002/users/${uuid}`, { + const delete_req = await fetch(`http://localhost:3001/`, { method: "DELETE", credentials: "include", }); @@ -78,7 +78,7 @@ export default class extends Aview { if (delete_req.status == 200) navigationManager("/"); else - console.error("xd"); // should never happen, wtf + console.error("xd"); // xd????????????? }); } } diff --git a/src/front/static/ts/views/Tetris.ts b/src/front/static/ts/views/Tetris.ts index bdf9ede..61c309a 100644 --- a/src/front/static/ts/views/Tetris.ts +++ b/src/front/static/ts/views/Tetris.ts @@ -47,6 +47,8 @@ export default class extends Aview { const ROWS = 20; const BLOCK = 30; // pixels per block + const view = this; + type Cell = number; // 0 empty, >0 occupied (color index) // Tetromino definitions: each piece is an array of rotations, each rotation is a 2D matrix @@ -542,10 +544,13 @@ export default class extends Aview { } else if (e.key === "Shift" || e.key === "c" || e.key === "C") { e.preventDefault(); this.hold(); - } else if (e.key === "x" || e.key === "X" || e.key === "ArrowUp") + } else if (e.key === "x" || e.key === "X" || e.key === "ArrowUp") { + e.preventDefault(); this.rotatePiece("cw"); - else if (e.key === "z" || e.key === "Z" || e.key === "Control") + } else if (e.key === "z" || e.key === "Z" || e.key === "Control") { + e.preventDefault(); this.rotatePiece("ccw"); + } }); document.addEventListener("keyup", (e) => { @@ -554,6 +559,7 @@ export default class extends Aview { } async loop(timestamp: number) { + if (!view.running) return; if (!this.lastDrop) this.lastDrop = timestamp; if (!this.isPaused) { @@ -608,7 +614,7 @@ export default class extends Aview { if (!ctx || !this.canvas) return; ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); - ctx.strokeStyle = "#222"; + ctx.strokeStyle = window.matchMedia('(prefers-color-scheme: dark)').matches ? "oklch(14.5% 0 0)" : "oklch(55.6% 0 0)"; for (let r = 0; r <= ROWS; r++) { // horizontal lines ctx.beginPath(); @@ -625,6 +631,7 @@ export default class extends Aview { } drawBoard() { + this.drawGrid(); for (let r = 0; r < ROWS; r++) { for (let c = 0; c < COLS; c++) { const val = this.board[r][c]; @@ -647,15 +654,18 @@ export default class extends Aview { } drawHold() { - if (!this.holdPiece || !this.holdCtx) return; + if (!this.holdCtx || !this.holdCanvas) return; - this.holdCtx.clearRect(0, 0, 200, 200); + this.holdCtx.fillStyle = window.matchMedia('(prefers-color-scheme: dark)').matches ? "oklch(20.5% 0 0)" : "oklch(70.8% 0 0)"; + this.holdCtx.fillRect(0, 0, this.holdCanvas.width, this.holdCanvas.height); + + if (!this.holdPiece) return; let y: number = 0; for (const row of this.holdPiece.rotations[0]) { let x: number = 0; for (const val of row) { if (val) - this.fillBlock(x + (4 - this.holdPiece.rotations[0].length)/ 2 + 0.35, y + 0.5, this.canHold ? COLORS[this.holdPiece.findColorIndex()] : ["#8c8c84", "#393934"], this.holdCtx); + this.fillBlock(x + (4 - this.holdPiece.rotations[0].length)/ 2 + 0.35, y + 0.65, this.canHold ? COLORS[this.holdPiece.findColorIndex()] : ["#8c8c84", "#393934"], this.holdCtx); x++; } y++; @@ -663,8 +673,10 @@ export default class extends Aview { } drawQueue() { - if (!this.queueCtx) return ; - this.queueCtx.clearRect(0, 0, 500, 500); + if (!this.queueCtx || !this.queueCanvas) return ; + + this.queueCtx.fillStyle = window.matchMedia('(prefers-color-scheme: dark)').matches ? "oklch(20.5% 0 0)" : "oklch(70.8% 0 0)"; + this.queueCtx.fillRect(0, 0, this.queueCanvas.width, this.queueCanvas.height); let placement: number = 0; for (const nextPiece of this.nextQueue.slice(0, 5)) { let y: number = 0; @@ -755,7 +767,8 @@ export default class extends Aview { clearBlock(x: number, y: number) { if (!this.ctx) return; const ctx = this.ctx; - ctx.clearRect(x * BLOCK + 1, y * BLOCK + 1, BLOCK - 2, BLOCK - 2); + ctx.fillStyle = window.matchMedia('(prefers-color-scheme: dark)').matches ? "oklch(20.5% 0 0)" : "oklch(70.8% 0 0)"; + ctx.fillRect(x * BLOCK + 1, y * BLOCK + 1, BLOCK - 2, BLOCK - 2); } drawHUD() { @@ -765,9 +778,9 @@ export default class extends Aview { ctx.fillRect(4, 4, 120, 60); ctx.fillStyle = "#fff"; ctx.font = "12px Kubasta"; - ctx.fillText(`Score: ${this.score}`, 8, 20); - ctx.fillText(`Lines: ${this.lines}`, 8, 36); - ctx.fillText(`Level: ${this.level}`, 8, 52); + ctx.fillText(`score: ${this.score}`, 8, 20); + ctx.fillText(`lines: ${this.lines}`, 8, 36); + ctx.fillText(`level: ${this.level}`, 8, 52); if (this.isPaused) { ctx.fillStyle = "rgba(0,0,0,0.7)"; diff --git a/src/front/static/ts/views/TetrisVersus.ts b/src/front/static/ts/views/TetrisVersus.ts index bdc4426..efa045d 100644 --- a/src/front/static/ts/views/TetrisVersus.ts +++ b/src/front/static/ts/views/TetrisVersus.ts @@ -26,8 +26,16 @@ export default class extends Aview {
-
-
+
+
+

enter the users ids/names

+
+ + +
+ +
+