From 29ffa2adf1f0d8a9aa428501aaef6e8e3b9be1dc Mon Sep 17 00:00:00 2001 From: Galexion Date: Sat, 18 Feb 2023 05:19:30 -0500 Subject: [PATCH] Play Log Partically Complete 1 / 3 --- public/javascript/user.js | 209 +++++++++++++++++++++++++++++++----- public/stylesheets/user.css | 122 +++++++++++++++++++-- readme.md | 6 +- routes/api.js | 20 ++++ routes/index.js | 4 + views/error.ejs | 33 +++++- views/user.ejs | 50 ++++++--- 7 files changed, 391 insertions(+), 53 deletions(-) diff --git a/public/javascript/user.js b/public/javascript/user.js index e1b7998..36ecba2 100644 --- a/public/javascript/user.js +++ b/public/javascript/user.js @@ -30,7 +30,7 @@ const cookieString = document.cookie; // Parse the cookie string and extract the values const cookies = cookieString.split(';'); -let ext_id, luid; +let ext_id, luid, aime_card_id; for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); @@ -43,6 +43,10 @@ for (let i = 0; i < cookies.length; i++) { if (cookieParts[0] === 'luid') { luid = cookieParts[1]; } + + if (cookieParts[0] === 'aime_card_id') { + aime_card_id = cookieParts[1]; + } } // Send the user to the sign in page if they aren't already signed in to the website. @@ -55,8 +59,49 @@ if (ext_id && luid) { } const userdata = JSON.parse(document.currentScript.getAttribute('data-userdata')); +//===================================================================== +// Now Exiting: Cookie Data ///////////////// Now Entering: User Data +//===================================================================== + +// general functions + +function padNumber(num, size) { + let s = num + ""; + while (s.length < size) { + s = "0" + s; + } + return s; +} + +async function getSongInformation(id) { + const musicData = await musicMetadata(); + const songMatch = musicData[id]; + if (!songMatch) { + return null; + } + return songMatch; + } + + +// Ban Check lmao + +if (userdata.ban_state !== 0) { + //nice + const parent = document.getElementById("User"); + const wrapperDiv = document.createElement("div"); + wrapperDiv.id = 'wrapper'; + const newDiv = document.createElement("div"); + newDiv.classList.add('error') + newDiv.innerHTML = `

Heya! It looks like you've been banned from playing on this profile, but don't worry - you can still enjoy the game in guest mode and view this profile. However, your account won't be able to play on it anymore. If you have any questions about your ban, please contact your Network Administrator.

`; // or set the HTML content with newDiv.innerHTML = "

This is some HTML content

; + parent.insertBefore(wrapperDiv, parent.firstChild); + wrapperDiv.appendChild(newDiv); +} + + // Check if the user image element exists -if(userdata.icon_id === 10) { +if (userdata.icon_id === 10) { const userImage = document.getElementById('user-image'); userImage.src = "images/" + ext_id + '-up.jpg'; } else if (document.currentScript.getAttribute('data-userdata')) { @@ -64,13 +109,6 @@ if(userdata.icon_id === 10) { const UI_Icon = userdata.icon_id; // Pad the number because game weird - function padNumber(num, size) { - let s = num + ""; - while (s.length < size) { - s = "0" + s; - } - return s; - } // Set the user image source userImage.src = "assets/icon/UI_Icon_" + padNumber(Number(UI_Icon), 6) + '.png'; @@ -80,26 +118,147 @@ if(userdata.icon_id === 10) { const request = new XMLHttpRequest(); request.open('GET', '/assets/metadata/titleMetadata.json', true); -request.onload = function() { - if (this.status >= 200 && this.status < 400) { - const data = JSON.parse(this.response); - const userTitle = document.getElementById('user-title-text'); - var userTitleText = "" - for (title of data) { - if(userdata.title_id === title.titleId) { - userTitleText = title.name - break +request.onload = function () { + if (this.status >= 200 && this.status < 400) { + const data = JSON.parse(this.response); + const userTitle = document.getElementById('user-title-text'); + var userTitleText = "" + for (title of data) { + if (userdata.title_id === title.titleId) { + userTitleText = title.name + break + } + continue } - continue + userTitle.textContent = userTitleText + } else { + // handle the error } - userTitle.textContent = userTitleText - } else { - // handle the error - } }; -request.onerror = function() { - // handle the error +request.onerror = function () { + // handle the error }; request.send(); + +// User Play Log + +async function userPlayLogFormatter(div) { + const UserPlayLogData = await UserPlayLog(aime_card_id); + const musicIds = UserPlayLogData.map(score => score.music_id); + const songs = await Promise.all(musicIds.map(getSongInformation)); + + let myDiv = document.getElementById("scoreWrapper"); + if (myDiv === null) { + const scoresWrapperDiv = document.createElement('div'); + scoresWrapperDiv.id = "scoreWrapper"; + + for (let i = UserPlayLogData.length - 1; i >= 0; i--) { + const newDiv = document.createElement('div'); + let score = JSON.parse(JSON.stringify(UserPlayLogData[i])); + let song = JSON.parse(JSON.stringify(songs[i])); + + if (!song || !song.name) { + console.log(song) + console.log(score.music_id) + console.log("Song or title is undefined"); + continue; + } + + newDiv.innerHTML = ` +

${song.name.str || ""} ||

+ `; + + let jacket = document.createElement('img'); + jacket.addEventListener("error", function () { + this.src = "assets/icon/UI_Icon_000000.png"; + }); + jacket.classList.add('score-jacket'); + jacket.src = "assets/jacket/UI_Jacket_" + padNumber(Number(score.music_id), 6) + '.png'; + newDiv.append(jacket) + + newDiv.setAttribute("id", "score-grid"); + newDiv.setAttribute("class", "item"); + + scoresWrapperDiv.appendChild(newDiv); + } + + div.appendChild(scoresWrapperDiv); + } +} + + + + +//===================================================================== +// Now Exiting: User Data ////////////// Now Entering: Nested Div Hell +//===================================================================== + +const showContent = (contentNumber) => { + // Select the content div with the data-content attribute equal to the contentNumber + const contentDiv = document.querySelector(`[data-content="content-${contentNumber}"]`); + + // Hide all content divs except the selected one + const contentDivs = document.querySelectorAll('[data-content]'); + contentDivs.forEach((div) => { + if (div === contentDiv) { + if (contentNumber === 2) { // If the ContentNumber is set to the PlayLog, Go to the userPlayLogFormatter Function + userPlayLogFormatter(div) + } + div.classList.remove('hidden'); + } else { + div.classList.add('hidden'); + } + }); +}; + +//===================================================================== +// Now Exiting: Nested Div Hell ///////////// Now Entering: Fetch Land +//===================================================================== + +function UserPlayLog(aime_card_id) { + const input = aime_card_id; + const url = "/api/getUserScores/"; + + // Return the fetch promise so that it can be handled within userPlayLogFormatter + return fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({ + input: aime_card_id + }) + }) + .then(response => response.json()) + .then(data => data.data) + .catch(error => console.error(error)); +} + +async function musicMetadata() { + const url = "/assets/metadata/musicMetadata.json"; + + try { + const response = await fetch(url, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + + const data = await response.json(); + + const mapping = {}; + data.forEach((song) => { + mapping[song.name.id] = song; + }); + + return mapping; + } catch (error) { + console.error(error); + } + } + + + diff --git a/public/stylesheets/user.css b/public/stylesheets/user.css index 6a74026..69ada43 100644 --- a/public/stylesheets/user.css +++ b/public/stylesheets/user.css @@ -28,22 +28,24 @@ "profile-image user-class awakens"; gap: 10px; border: 2px solid black; - border-radius: 10px; + border-radius: 15px; justify-items: center; align-items: center; width: fit-content; margin: 0 auto; + font-size: 2em; } @media screen and (max-width: 768px) { #user-profile-wrapper { display: inline-block; margin: 0; - padding: 20px; border: 2px solid black; - border-radius: 10px; + border-radius: 15px; align-items: center; justify-content: center; + font-size: 1.5em; + } } @@ -73,7 +75,7 @@ grid-area: awakens; } -h4 { +h4.profile { font-size: 2em; } @@ -83,8 +85,110 @@ h4 { } } -@media (max-width: 480px) { - h4 { - font-size: 1.2em; - } -} \ No newline at end of file +.error { + display: inline-block; + margin: 1em; + border: 2px dashed red; + border-radius: 10px; + align-items: center; + justify-content: center; +} + +.buttons { + margin-bottom: 2em; + display: grid; + grid-template-areas: + "1a 2b 3c 4d" + "5e 6f 7g 8h"; + grid-gap: 10px; + } + + .btn1 { + grid-area: "1a"; + } + + .btn2 { + grid-area: "2b"; + } + + .btn3 { + grid-area: "3c"; + } + + .btn4 { + grid-area: "4d"; + } + + .btn5 { + grid-area: "5e"; + } + + .btn6 { + grid-area: "6f"; + } + + .btn7 { + grid-area: "7g"; + } + + .btn8 { + grid-area: "8h"; + } + + .hidden { + display:none !important; + } + +/* Jacket Grid */ + + .score-grid { + display: grid; + + grid-template-rows: 1fr 1fr 1fr; + grid-template-columns: 1fr 1fr 1fr 1fr; + + grid-template-areas: + 'label0 label0 label0 label0' + 'label1 label1 label2 label3' + 'label1 label1 label4 label4'; + + gap: 0px; + height: 100%; + + } + + .score-title { + + background-color: #D5BBCA; + grid-area: label0; + + } + .score-jacket { + + background-color: #9EF6B5; + grid-area: label1; + display: block; + margin-left: auto; + margin-right: auto; + max-width: 25%; + width: 25%; + + } + .score-achivement { + + background-color: #ED69FD; + grid-area: label2; + + } + .score-grade { + + background-color: #9B5999; + grid-area: label3; + + } + .score-info { + + background-color: #58B669; + grid-area: label4; + + } \ No newline at end of file diff --git a/readme.md b/readme.md index 97c02cb..2cdf5a7 100644 --- a/readme.md +++ b/readme.md @@ -37,6 +37,10 @@ Create a `config.json` file and paste this in, with paths to your instance. ToDo: - Create Play Data Tab + - Get User Playlog Data (Done) + - Sort From Most Recent (Done) + - Assign Song Names to Each Score (done) + - Create Detailed Look Into Score - Create Photos Tab - Create Area Tab - Create Collection Tab @@ -46,5 +50,5 @@ ToDo: Complete: - Sign In Page -- Make User Profile on User Page (almost done) +- Make User Profile on User Page (done) - Fuck you css go kill yourself \ No newline at end of file diff --git a/routes/api.js b/routes/api.js index 05b8346..b0112b6 100644 --- a/routes/api.js +++ b/routes/api.js @@ -49,6 +49,26 @@ let db = new sqlite3.Database('A:\\db.sqlite'); }); }) + router.post('/getUserScores/', function (req,res,next) { + db.all('SELECT * FROM maimai2_user_playlog', (err, rows) => { + if (err) { + console.error(err); + // Return a Failed Message. + res.status(500).json({ error: err.message, status: "Failed" }); + } else { + // Make the Request easier to get to. + var request = req.body; + var mUser = new Array(); // Leave the Matched User's Scores undefined until the user is found. + for (score of rows) { // For Each Score in Rows + if (request.input == score.user_id) { // If the inputed User ID and Score's User ID Matches, + mUser.push(score) // add that score into the array. + } + } + // Return a Response with all the Scores listed under that user. + res.status(200).json({ data: mUser, status: "Complete" }); + } + }); + }); module.exports = router; \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index 2302ca0..0d3dd62 100644 --- a/routes/index.js +++ b/routes/index.js @@ -35,6 +35,10 @@ router.get('/user', async function (req, res, next) { } }); +router.get('/error/test/db', function (req,res,next) { + res.render('error', { error: "Error: SQLITE_BUSY: database is locked"}) +}) + async function getUserData(req) { return new Promise((resolve, reject) => { const cookies = req.cookies diff --git a/views/error.ejs b/views/error.ejs index 2a8f40a..9119c29 100644 --- a/views/error.ejs +++ b/views/error.ejs @@ -1,6 +1,33 @@ <% var rootPath='../' ; %> <%- include(rootPath + 'templates/header.ejs' ); %> -

Fuck. Something Went Wrong or you got 404'd.

- <%=error%> - +
+
+ <% if(error == "Error: SQLITE_BUSY: database is locked") { + %> +

It appears that the database is currently unavailable. Please try again later.

+

If you accidentally disconnect from the server, this error typically resolves itself. However, if you continue to encounter the error, try restarting the server. If you're playing on a Private Server with other users, you should ask a Network Admin to restart it for you.

+ <%} else {%> + +

Fuck. Something Went Wrong or you got 404'd.

+ <%}%> +<%=error%> +
+
+ + + \ No newline at end of file diff --git a/views/user.ejs b/views/user.ejs index af9bbfa..e66e19f 100644 --- a/views/user.ejs +++ b/views/user.ejs @@ -5,24 +5,44 @@

Yo! Welcome Back <%= normalizeText(userdata.user_name) %>!

+
-
-
User Image
-
-

-
-
-

<%= normalizeText(userdata.user_name) %>

-
-
-

<%= userdata.music_rating%>

-
-
-
-

★ ☓<%= userdata.total_awake%>

+ +
+ + + + + + + +
-
+
+
+
User Image
+
+

+
+
+

<%= normalizeText(userdata.user_name) %>

+
+
+

<%= userdata.music_rating%>

+
+
+
+

★ ☓<%= userdata.total_awake%>

+
+
+ +
+ + +
Developer Only Information For Development purposes only, send statistics found in this menu when encontering UI