Leaderboard sorting + level data size

SMJS updated his accurate leaderboard API to allow sorting by user coins or demons. What a nice guy!

Also, level analysis now shows the size of the level in MB or KB. Thanks to ItzSwirlz for suggesting this in a PR.

Packages were updated as well.
This commit is contained in:
GDColon 2020-03-21 18:45:49 -04:00
parent 6bc2d64bf8
commit cd600a1396
13 changed files with 58 additions and 26 deletions

View file

@ -3,14 +3,22 @@ const request = require('request')
module.exports = async (app, req, res) => {
if (app.endpoint != "http://boomlings.com/database/") return res.send([])
let type = req.query.type ? req.query.type.toLowerCase() : ''
if (type == "usercoins") type = "coins"
if (type == "demons" || type == "coins") type = `?${type}=1`
else type = ''
request.get(`https://gdleaderboards.com/incl/lbxml.php`, function (err, resp, topPlayers) {
request.get(`https://gdleaderboards.com/incl/lbxml.php${type}`, function (err, resp, topPlayers) {
if (err || !topPlayers) topPlayers = ""
let idArray = topPlayers.split(",")
let leaderboard = []
let total = idArray.length
if (!type.length) type = "stars"
if (type == "coins") type = "usercoins"
idArray.forEach((x, y) => {
request.post(app.endpoint + 'getGJUserInfo20.php', {
@ -34,7 +42,7 @@ module.exports = async (app, req, res) => {
leaderboard.push(accObj)
if (leaderboard.length == total) {
leaderboard = leaderboard.filter(x => x.stars).sort(function (a, b) {return parseInt(b.stars) - parseInt(a.stars)})
leaderboard = leaderboard.filter(x => x.stars).sort(function (a, b) {return parseInt(b[type]) - parseInt(a[type])})
leaderboard.forEach((a, b) => a.rank = b + 1)
return res.send(leaderboard)
}

BIN
assets/playbutton.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
assets/sort-coins-on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
assets/sort-coins.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
assets/sort-demons-on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
assets/sort-demons.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
assets/sort-stars-on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
assets/sort-stars.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

BIN
assets/stopbutton.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -26,6 +26,7 @@
<div id="analysisDiv" style="margin-top: 2%; display:none">
<h2 id="levelName"></h2>
<p></p>
<h3 id="objectCount"></h3>
<div id="highDetailDiv">
@ -52,7 +53,7 @@
<h1 class="topMargin2" id="orbText">Jump Rings</h1>
<div class="transparentBox analysis" id="orbs"></div>
<h1 class="topMargin2">Block Types</h1>
<div class="transparentBox analysis" id="blocks"></div>
@ -98,7 +99,7 @@ let mirrorPortals = ['mirrorOn', 'mirrorOff']
fetch(`../api${window.location.pathname}`).then(res => res.json()).then(res => {
if (!res.level) return window.location.href = window.location.href.replace("analyze", "search")
$('#levelName').text(res.level.name)
$('#objectCount').text(res.objects + " objects")
$('#objectCount').text(commafy(res.objects) + " objects")
document.title = "Analysis of " + res.level.name
$('#meta-title').attr('content', "Analysis of " + res.level.name)
@ -111,7 +112,7 @@ if (res.highDetail == 0 || res.hdPercent == 0) $('#highDetailDiv').hide()
else {
let offset = hdPercent < 20 ? 1 : hdPercent < 40 ? 2 : hdPercent < 60 ? 3 : hdPercent < 80 ? 4 : 5
$('#highdetail').append(`<div class="inline" style="width:${hdPercent + offset}%; height: 100%; background-color: lime; margin-left: -2.25%"></div>`)
$('#hdText').text(`${res.highDetail}/${res.objects} marked high detail • ${+hdPercent.toFixed(1)}% optimized`)
$('#hdText').text(`${commafy(res.highDetail)}/${commafy(res.objects)} marked high detail • ${+hdPercent.toFixed(1)}% optimized`)
}
let triggerList = Object.keys(res.triggers)
@ -123,6 +124,8 @@ let colorList = Object.keys(res.colors)
let portals = res.portals.split(", ").map(x => x.split(" "))
function commafy(num) { return (+num || 0).toString().replace(/(\d)(?=(\d\d\d)+$)/g, "$1,") }
function appendPortals() {
$('#portals').html("")
if (res.settings.gamemode && res.settings.gamemode != "cube" && !disabledPortals.includes('form')) $('#portals').append(`<div class="inline portalDiv"><img class="portalImage" src='../objects/portal-${res.settings.gamemode}.png'><h3>Start</h3></div><img class="divider portalImage" src="../assets/divider.png" style="margin: 1.3% 0.8%">`)
@ -146,27 +149,27 @@ function appendPortals() {
appendPortals()
triggerList.forEach(x => {
if (x == "total") $('#triggerText').text(`Triggers (${res.triggers[x]})`)
else $('#triggers').append(`<div class="inline triggerDiv"><img height="50%" src='../objects/trigger-${x}.png'><h3 style="padding-top: 7%">x${res.triggers[x]}</h3></div>`)
if (x == "total") $('#triggerText').text(`Triggers (${commafy(res.triggers[x])})`)
else $('#triggers').append(`<div class="inline triggerDiv"><img height="50%" src='../objects/trigger-${x}.png'><h3 style="padding-top: 7%">x${commafy(res.triggers[x])}</h3></div>`)
})
orbList.forEach(x => {
if (x == "total") $('#orbText').text(`Jump Rings (${res.orbs[x]})`)
else $('#orbs').append(`<div class="inline orbDiv"><img height="50%" src='../objects/orb-${x}.png'><h3 style="padding-top: 7%">x${res.orbs[x]}</h3></div>`)
if (x == "total") $('#orbText').text(`Jump Rings (${commafy(res.orbs[x])})`)
else $('#orbs').append(`<div class="inline orbDiv"><img height="50%" src='../objects/orb-${x}.png'><h3 style="padding-top: 7%">x${commafy(res.orbs[x])}</h3></div>`)
})
blockList.forEach(x => {
$('#blocks').append(`<div class="inline blockDiv"><img height="45%" src='../blocks/${x}.png'><h3 style="padding-top: 15%">x${res.blocks[x]}</h3></div>`)
$('#blocks').append(`<div class="inline blockDiv"><img height="45%" src='../blocks/${x}.png'><h3 style="padding-top: 15%">x${commafy(res.blocks[x])}</h3></div>`)
})
miscList.forEach(x => {
if (x == "objects") return;
else $('#misc').append(`<div class="inline miscDiv"><img height="40%" src='../objects/obj-${x.slice(0, -1)}.png'><h3 style="padding-top: 15%">x${res.misc[x][0]}<br>${res.misc[x][1]}</h3></div>`)
else $('#misc').append(`<div class="inline miscDiv"><img height="40%" src='../objects/obj-${x.slice(0, -1)}.png'><h3 style="padding-top: 15%">x${commafy(res.misc[x][0])}<br>${res.misc[x][1]}</h3></div>`)
})
groupList.forEach(x => {
if (x == "total") $('#grouptext').text(`Trigger Groups (${res.triggerGroups[x]})`)
else $('#groups').append(`<div class="inline groupDiv"><h1 class="groupID">${x.slice(6)}</h1><h3 style="padding-top: 7%">x${res.triggerGroups[x]}</h3></div>`)
if (x == "total") $('#grouptext').text(`Trigger Groups (${commafy(res.triggerGroups[x])})`)
else $('#groups').append(`<div class="inline groupDiv"><h1 class="groupID">${x.slice(6)}</h1><h3 style="padding-top: 7%">x${commafy(res.triggerGroups[x])}</h3></div>`)
})
let bgCol = res.colors.find(x => x.channel == "BG")
@ -188,7 +191,7 @@ appendPortals()
let c = res.colors[x]
$('#colorDiv').append(`${y % 8 == 0 ? "<brr>" : ""}<div class="inline aColor"><div class="color" channel="${c.channel}" style="background-color: rgba(${c.cr || c.r}, ${c.cg || c.g}, ${c.cb || c.b}, ${c.opacity}); border: 0.4vh solid rgb(${c.r}, ${c.g}, ${c.b})">
${c.copiedChannel ? `<h3 class='copiedColor'>C:${c.copiedChannel}</h3>` : c.pColor ? `<h3 class='copiedColor'>P${c.pColor}</h3>` : c.blending ? "<h3 class='blendingDot'></h3>" : ""}
${c.copiedChannel ? `<h3 class='copiedColor'>C:${c.copiedChannel}</h3>` : c.pColor ? `<h3 class='copiedColor'>P${c.pColor}</h3>` : c.blending ? "<h3 class='blendingDot'></h3>" : ""}
${c.copiedChannel && c.copiedHSV ? `<h3 class='copiedColor copiedHSV'> +HSV</h3>` : ""}
${c.opacity != "1" ? `<h3 class='copiedColor'>${c.opacity}%</h3>` : ""}
</div><h3 style="padding-top: 7%">${c.channel > 0 ? "Col " + c.channel : c.channel}</h3></div>`)
@ -199,7 +202,7 @@ appendPortals()
$(".portalToggle").click(function() {
if ($(this).prop('checked')) disabledPortals = disabledPortals.filter(x => x != $(this).attr('portal'))
else disabledPortals.push($(this).attr('portal'))
portals = res.portals.split(", ").map(x => x.split(" "))
if (disabledPortals.includes('form')) portals = portals.filter(x => !formPortals.includes(x[0]))
if (disabledPortals.includes('speed')) portals = portals.filter(x => !speedPortals.includes(x[0]))
@ -215,7 +218,10 @@ appendPortals()
appendPortals()
})
$('#codeLength').html(`(${res.dataLength} characters)`)
let dataSize = [Number((res.dataLength / 1024 / 1024).toFixed(1)), "MB"]
if (dataSize[0] < 1) dataSize = [Number((res.dataLength / 1024).toFixed(1)), "KB"]
$('#codeLength').html(`${commafy(res.dataLength)} characters (${dataSize.join(" ")})`)
$('#revealCode').click(function() {
$('#levelCode').html('<p>Loading...</p>')
@ -284,4 +290,4 @@ appendPortals()
});
</script>
</script>

View file

@ -324,11 +324,12 @@
<p>Simply returns the top player leaderboard</p>
<br>
<p class="reveal" onclick="$('#params-leaderboard').slideToggle(100)"><b>Parameters (3)</b></p>
<p class="reveal" onclick="$('#params-leaderboard').slideToggle(100)"><b>Parameters (4)</b></p>
<div class="subdiv" id="params-leaderboard">
<p>count: The amount of players to list (default is 100, max is 5000, does not work with accurate leaderboard)</p>
<p>creator: Fetches the creator leaderboard</p>
<p>accurate: Fetches the accurate leaderboard</p>
<p>type: Accurate leaderboard only - the type of stat to sort by (stars, coins, or demons)</p>
</div>
<br>

View file

@ -44,7 +44,13 @@
<div style="height: 4.5%"></div>
</div>
<div class="leaderboardBox supercenter gs" style="width: 120vh; height: 80%; pointer-events: none"></div>
<div class="leaderboardBox supercenter gs" style="width: 120vh; height: 80%; pointer-events: none">
<div id="sortDiv" style="position: relative; right: 10.5%; top: 10.5%; width: 0.1%">
<img class="gdButton sortButton" style="margin-bottom: 1vh" sort="stars" src="../assets/sort-stars-on.png" height="11%">
<img class="gdButton sortButton" style="margin-bottom: 1vh" sort="coins" src="../assets/sort-coins.png" height="11%">
<img class="gdButton sortButton" style="margin-bottom: 1vh" sort="demons" src="../assets/sort-demons.png" height="11%">
</div>
</div>
<div style="position:absolute; top: 2%; left: 1.5%; width: 10%; height: 25%; pointer-events: none">
<img class="gdButton yesClick" id="backButton" src="../assets/back.png" height="30%" onclick="backButton()">
@ -68,7 +74,7 @@
<script type="text/javascript" src="../assets/dragscroll.js"></script>
<script>
let loading = false;
let sort = "stars"
let top250Text =
`The <g>Top 250<> leaderboard contains the <g>top 250 players<>, sorted by <y>star<> value. However, due to <o>hackers<> flooding the leaderboard, this leaderboard has been <b>frozen<> for well over 2 years and displays <o>very outdated information<>.`
@ -97,7 +103,7 @@ function leaderboard(val) {
$('#searchBox').html(`<div style="height: 4.5%"></div>`)
$('#loading').show()
fetch(`../api/leaderboard?count=250&${val}`).then(res => res.json()).then(res => {
fetch(`../api/leaderboard?count=250&${val}&type=${sort}`).then(res => res.json()).then(res => {
if (val != type) return;
@ -134,12 +140,20 @@ function leaderboard(val) {
appendScroll: '#searchBox'
});
})
}
let type = "accurate"
leaderboard(type)
$(document).on('click', '.sortButton', function () {
if ($('#loading').is(":visible")) return
sort = $(this).attr('sort')
$('.sortButton').each(function() {
$(this).attr('src', $(this).attr('src').replace('-on', '').replace('.png', '') + ($(this).attr('sort') == sort ? "-on" : "") + ".png")
})
return leaderboard("accurate")
})
$('#topTabOff').click(function() {
if (type == "top") return;
type = "top"
@ -149,6 +163,7 @@ function leaderboard(val) {
$('#accurateTabOff').show()
$('#creatorTabOff').show()
infoText(top250Text)
$('#sortDiv').hide()
})
$('#accurateTabOff').click(function() {
@ -160,6 +175,7 @@ function leaderboard(val) {
$('#accurateTabOn').show()
$('#creatorTabOff').show()
infoText(accurateText)
$('#sortDiv').show()
})
$('#creatorTabOff').click(function() {
@ -171,6 +187,7 @@ function leaderboard(val) {
$('#accurateTabOff').show()
$('#creatorTabOn').show()
infoText(creatorText)
$('#sortDiv').hide()
});

View file

@ -5,12 +5,12 @@
"license": "MIT",
"private": true,
"dependencies": {
"canvas": "^2.6.0",
"canvas": "^2.6.1",
"compression": "^1.7.4",
"connect-timeout": "^1.9.0",
"express": "^4.17.1",
"jimp": "^0.8.4",
"jimp": "^0.8.5",
"plist": "^3.0.1",
"request": "^2.88.0"
"request": "^2.88.2"
}
}