1
0
mirror of https://dev.s-ul.net/Galexion/MaiMaiDXNet.git synced 2024-11-27 23:20:50 +01:00

Play Log Partically Complete 1 / 3

This commit is contained in:
Galexion 2023-02-18 05:19:30 -05:00
parent 93a9e0ee64
commit 29ffa2adf1
7 changed files with 391 additions and 53 deletions

View File

@ -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,6 +59,47 @@ 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 = `<h3 style='
word-wrap: break-word;
max-width:800px;'>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.</h3>`; // or set the HTML content with newDiv.innerHTML = "<p>This is some HTML content</p>;
parent.insertBefore(wrapperDiv, parent.firstChild);
wrapperDiv.appendChild(newDiv);
}
// Check if the user image element exists
if (userdata.icon_id === 10) {
const userImage = document.getElementById('user-image');
@ -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';
@ -103,3 +141,124 @@ request.onerror = function() {
};
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 = `
<h4>${song.name.str || ""} || </h4>
`;
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);
}
}

View File

@ -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;
.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;
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -1,6 +1,33 @@
<% var rootPath='../' ; %>
<%- include(rootPath + 'templates/header.ejs' ); %>
<div class="wrapper">
<div class="error">
<% if(error == "Error: SQLITE_BUSY: database is locked") {
%>
<h1 style="word-wrap: break-word; max-width:800px;">It appears that the database is currently unavailable. Please try again later.</h1>
<p style="word-wrap: break-word; max-width:800px;">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.</p>
<%} else {%>
<h1>Fuck. Something Went Wrong or you got 404'd.</h1>
<%}%>
<%=error%>
</div>
</div>
<style>
.error {
display: inline-block;
margin: 1em;
border: 2px dashed red;
border-radius: 10px;
align-items: center;
justify-content: center;
}
.wrapper {
display: flex;
justify-content: center;
align-items: center;
}
</style>
</body>
</html>

View File

@ -5,8 +5,22 @@
<link href="/stylesheets/user.css" rel="stylesheet" type="text/css">
<div id="User">
<h1>Yo! Welcome Back <%= normalizeText(userdata.user_name) %>!</h1>
<div id="wrapper">
<div id="user-profile-wrapper">
<!-- Calm before the storm -->
<div class="buttons">
<button class="btn1" onclick="showContent(1)">Home</button>
<button class="btn2" onclick="showContent(2)">Play Data</button>
<button class="btn3" onclick="showContent(3)">Friends</button>
<button class="btn4" onclick="showContent(4)">Photos</button>
<button class="btn5" onclick="showContent(5)">Records</button>
<button class="btn6" onclick="showContent(6)">Area</button>
<button class="btn7" onclick="showContent(7)">Collection</button>
<button class="btn8" onclick="showContent(8)">Ranking</button>
</div>
</div>
<div id="wrapper">
<div data-content="content-1" id="user-profile-wrapper">
<div class="profile-image"><img id="user-image" src="" alt="User Image" onerror="this.src='assets/icon/UI_Icon_000000.png'"></div>
<div class="user-title">
<h4 id="user-title-text"></h4>
@ -21,8 +35,14 @@
<div class="awakens">
<h4>★ ☓<%= userdata.total_awake%></h4>
</div>
</div><!-- This is just one nested div, Trmazi it's going to get a lot worse from here on. -->
<div data-content="content-2" id="user-play-data" class="hidden"> <!-- User Play-Log is generated at run time when the user clicks the button, so they get up to date data. -->
<h4>Please Wait, Obtaining Scores...</h4>
</div>
</div>
<details>
<summary>Developer Only Information</summary>
For Development purposes only, send statistics found in this menu when encontering UI