GDBrowser/html/analyze.html
GDColon 8fd80d7147 Fixed comment username bug
Clicking on a username with a space in it (e.g. "le doge") would redirect you to the profile of the first word only (e.g. "le")

also shut up i'm not writng "fix comment bug" that whole present tense thing is stupid
2019-12-08 17:07:55 -05:00

287 lines
No EOL
15 KiB
HTML

<head>
<title>Level Analysis</title>
<meta charset="utf-8">
<meta property="og:type" content="website">
<meta id="meta-title" property="og:title" content="Level Analysis">
<meta id="meta-desc" property="og:description" content="Analyze a Geometry Dash level and view it's objects, portals, color channels, code, and more!">
<meta id="meta-image" name="og:image" itemprop="image" content="https://gdbrowser.com/assets/cp.png">
<link href="../css/browser.css" type="text/css" rel="stylesheet">
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135255146-3"></script><script>window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);}gtag('js', new Date());gtag('config', 'UA-135255146-3');</script>
<link rel="icon" href="../assets/cp.png">
</head>
<body class="levelBG" style="overflow-y:auto;" onbeforeunload="saveUrl()">
<div id="everything" class="center">
<div class="supercenter" id="loadingDiv" style="height:50%">
<h1 style="transform:scale(1.2)">Analyzing level...</h1>
<img class="spin noSelect" src="../assets/loading.png" height="25%" style="margin-top: 7%">
</div>
<div class="popup" id="colorInfo">
<div id="colorStuff" class="brownbox bounce center supercenter" style="height: 60%; width: 90vh">
</div>
</div>
<div id="analysisDiv" style="margin-top: 2%; display:none">
<h2 id="levelName"></h2>
<h3 id="objectCount"></h3>
<div id="highDetailDiv">
<h1 class="topMargin">Low Detail Mode</h1>
<div class="transparentBox analysis roundBottom" id="highdetail" style="height: 10%; text-align: left; overflow: hidden; background-color: darkblue;"></div>
<h3 style="margin-top: -0.25%" id="hdText"></h3>
</div>
<h1 class="topMargin">Portal order</h1>
<div class="transparentBox analysis" id="portals" style="height: 23%"></div>
<div>
<div class="portalSetting"><h3><input checked type="checkbox" class="portalToggle" id="box1" portal="form"> <label for="box1" class="gdcheckbox gdButton portalButton"></label>Form Portals</h3></div>
<div class="portalSetting"><h3><input checked type="checkbox" class="portalToggle" id="box2" portal="size"> <label for="box2" class="gdcheckbox gdButton portalButton"></label>Size Portals</h3></div>
<div class="portalSetting"><h3><input checked type="checkbox" class="portalToggle" id="box3" portal="speed"><label for="box3" class="gdcheckbox gdButton portalButton"></label>Speed Portals</h3></div>
<br><div style="height: 1.5%"></div>
<div class="portalSetting"><h3><input checked type="checkbox" class="portalToggle" id="box4" portal="mirror"><label for="box4" class="gdcheckbox gdButton portalButton"></label>Mirror Portals</h3></div>
<div class="portalSetting"><h3><input checked type="checkbox" class="portalToggle" id="box5" portal="dual"> <label for="box5" class="gdcheckbox gdButton portalButton"></label>Dual Portals</h3></div>
<div class="portalSetting"><h3><input checked type="checkbox" class="portalToggle" id="box6" portal="dupe"> <label for="box6" class="gdcheckbox gdButton portalButton"></label>Duplicates</h3></div>
</div>
<h1 class="topMargin2" id="triggerText">Triggers</h1>
<div class="transparentBox analysis" id="triggers"></div>
<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>
<h1 class="topMargin2">Misc Objects</h1>
<div class="transparentBox analysis" id="misc" style="height: 25%"></div>
<h1 class="topMargin2">Level Style</h1>
<div class="transparentBox analysis" id="style" style="height: 20%"></div>
<h1 class="topMargin2" id="grouptext">Trigger Groups</h1>
<div class="transparentBox analysis" id="groups" style="height: 18%"></div>
<h1 class="topMargin2">Color Channels</h1>
<div class="transparentBox analysis" id="colorDiv"></div>
<h1 class="topMargin2">Level Data</h1>
<div class="transparentBox levelCode" id="levelCode">
<p class="menuLink" id="revealCode">Reveal level data</p>
<p id="codeLength"></p>
</div>
<div style="height: 7%"></div>
</div>
<div style="position:absolute; top: 2%; left: -1.95%; width: 10%; height: 25%; pointer-events: none">
<img class="gdButton yesClick" id="backButton" src="../assets/back.png" height="30%" onclick="backButton()">
</div>
</div>
</body>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script async type="text/javascript" src="../assets/sizecheck.js"></script>
<script>
let disabledPortals = []
let formPortals = ['cube', 'ship', 'ball', 'ufo', 'wave', 'robot', 'spider']
let speedPortals = ['-1x', '1x', '2x', '3x', '4x']
let sizePortals = ['mini', 'big']
let dualPortals = ['dual', 'single']
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")
document.title = "Analysis of " + res.level.name
$('#meta-title').attr('content', "Analysis of " + res.level.name)
$('#meta-desc').attr('content', `${res.portals.split(",").length}x portals, ${res.orbs.total || 0}x orbs, ${res.triggers.total || 0}x triggers, ${res.misc.glow || 0}x glow...`)
let hdPercent = (res.highDetail / res.objects) * 100
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`)
}
let triggerList = Object.keys(res.triggers)
let groupList = Object.keys(res.triggerGroups)
let orbList = Object.keys(res.orbs)
let miscList = Object.keys(res.misc)
let blockList = Object.keys(res.blocks)
let colorList = Object.keys(res.colors)
let portals = res.portals.split(", ").map(x => x.split(" "))
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%">`)
if (res.settings.startMini && !disabledPortals.includes('size')) $('#portals').append(`<div class="inline portalDiv"><img class="portalImage" src='../objects/portal-mini.png'><h3>Start</h3></div><img class="divider portalImage" src="../assets/divider.png" style="margin: 1.3% 0.8%">`)
if (res.settings.speed && res.settings.speed != "1x" && !disabledPortals.includes('speed')) $('#portals').append(`<div class="inline portalDiv"><img class="portalImage speedPortal" src='../objects/portal-${res.settings.speed}.png'><h3>Start</h3></div><img class="divider portalImage" src="../assets/divider.png" style="margin: 1.3% 0.8%">`)
if (res.settings.startDual && !disabledPortals.includes('dual')) $('#portals').append(`<div class="inline portalDiv"><img class="portalImage" src='../objects/portal-dual.png'><h3>Start</h3></div><img class="divider portalImage" src="../assets/divider.png" style="margin: 1.3% 0.8%">`)
let dividerCount = $('.divider').length - 1
$('.divider').each(function(y) {
if (y != dividerCount) $(this).remove()
})
portals.forEach(x => {
if (!x || x[0] == "") return;
$('#portals').append(`<div class="inline portalDiv"><img class="portalImage ${x[0].match(/[0-9]x/) ? "speedPortal" : ""}" src='../objects/portal-${x[0]}.png'><h3>${x[1]}</h3></div>`)
}
)}
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>`)
})
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>`)
})
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>`)
})
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>`)
})
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>`)
})
let bgCol = res.colors.find(x => x.channel == "BG")
let grCol = res.colors.find(x => x.channel == "G")
if (!bgCol) bgCol = {r: 40, g: 125, b: 255}
else if (bgCol.r < 35 && bgCol.g < 35 && bgCol.b < 35) bgCol = {r: 75, g: 75, b: 75}
if (!grCol) grCol = {r: 0, g: 102, b: 255}
else if (grCol.r < 35 && grCol.g < 35 && grCol.b < 35) grCol = {r: 75, g: 75, b: 75}
$('#style').append(`<div class="inline styleDiv styleBG" style='background-color: rgb(${bgCol.r}, ${bgCol.g}, ${bgCol.b})'><img height="60%" src='../levelstyle/bg-${res.settings.background}.png'></div>`)
$('#style').append(`<div class="inline styleDiv styleBG" style='background-color: rgb(${grCol.r}, ${grCol.g}, ${grCol.b})'><img height="60%" src='../levelstyle/gr-${res.settings.ground}.png'></div>`)
$('#style').append(`<div class="inline styleDiv"><img height="55%" src='../levelstyle/font-${res.settings.font}.png'></div>`)
$('#style').append(`<div class="inline styleDiv"><img height="60%" src='../levelstyle/line-${res.settings.alternateLine ? 2 : 1}.png'></div>`)
if (res.settings.twoPlayer) $('#style').append(`<div class="inline styleDiv"><img height="60%" src='../levelstyle/mode-2p.png'></div>`)
colorList.forEach((x, y) => {
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 && 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>`)
})
if (colorList.length == 0) $('#colorDiv').append('<h3 style="margin-top: 7vh">Could not get color info!</h3>')
$(".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]))
if (disabledPortals.includes('size')) portals = portals.filter(x => !sizePortals.includes(x[0]))
if (disabledPortals.includes('dual')) portals = portals.filter(x => !dualPortals.includes(x[0]))
if (disabledPortals.includes('mirror')) portals = portals.filter(x => !mirrorPortals.includes(x[0]))
if (disabledPortals.includes('dupe')) {
portals.reverse().forEach((x, y) => {if (portals[y+1] && portals[y+1][0] == x[0]) portals[y][0] = null;})
portals = portals.reverse().filter(x => x[0] != null)
}
appendPortals()
})
$('#codeLength').html(`(${res.dataLength} characters)`)
$('#revealCode').click(function() {
$('#levelCode').html('<p>Loading...</p>')
window.setTimeout(function () { //small delay so "loading" message appears
$('#levelCode').html(`<p class="codeFont">${res.data}</p>`)}, 50);
$('#levelCode').focus().select()
})
$(document).on('click', '.color', function() {
let col = res.colors.find(x => x.channel == $(this).attr('channel'))
let hsv = col.copiedHSV
if (hsv) {
hsv.s = Number(hsv.s).toFixed(2)
hsv.v = Number(hsv.v).toFixed(2)
}
let hex = "#" + ((1 << 24) + (+col.r << 16) + (+col.g << 8) + +col.b).toString(16).slice(1)
$('#colorStuff').html(`
<h2 class="slightlySmaller">${isNaN(col.channel) ? col.channel : "Color " + col.channel}</h2>
<div class="colorSection">
<h3>Hex Code</h3>
<p>${hex}</p>
</div>
<div class="colorSection">
<h3>RGB</h3>
<p>${col.r}, ${col.g}, ${col.b}</p>
</div>
<div class="colorSection">
<h3>Opacity</h3>
<p>${Number(col.opacity).toFixed(2)}</p>
</div>
<br>
<div class="colorSection2" style="width: 40%; ${col.copiedChannel ? "" : "margin-right:55.4%"}">
<div class="colorCheckbox"><h3><input ${col.pColor == 1 ? "checked" : ""} type="checkbox"> <label class="gdcheckbox gdButton"></label>Player 1</h3></div>
<div class="colorCheckbox"><h3><input ${col.pColor == 2 ? "checked" : ""} type="checkbox"> <label class="gdcheckbox gdButton"></label>Player 2</h3></div>
<div class="colorCheckbox"><h3><input ${col.blending ? "checked" : ""} type="checkbox"> <label class="gdcheckbox gdButton"></label>Blending</h3></div>
<div class="colorCheckbox"><h3><input ${col.copiedChannel ? "checked" : ""} type="checkbox"> <label class="gdcheckbox gdButton"></label>Copy Color</h3></div>
<div class="colorCheckbox"><h3><input ${col.copyOpacity ? "checked" : ""} type="checkbox"> <label class="gdcheckbox gdButton"></label>Copy Opacity</h3></div>
</div>
${col.copiedChannel ? `
<div class="colorSection2">
<div class="colorSection copyDetails">
<h3>Copied</h3>
<p>${isNaN(col.copiedChannel) ? col.copiedChannel : "Col " + col.copiedChannel}</p>
</div>
<div class="colorSection copyDetails">
<h3>Hue</h3>
<p>${!hsv ? 0 : hsv.h > 0 ? "+" + hsv.h : hsv.h}</p>
</div>
<div class="colorSection copyDetails">
<h3>Saturation</h3>
<p>${!hsv ? "x1.00" : !hsv['s-checked'] ? "x" + hsv.s : hsv.s > 0 ? "+" + hsv.s : hsv.s}</p>
</div>
<div class="colorSection copyDetails">
<h3>Brightness</h3>
<p>${!hsv ? "x1.00" : !hsv['v-checked'] ? "x" + hsv.v : hsv.v > 0 ? "+" + hsv.v : hsv.v}</p>
</div>
</div>`
: `<div class="colorBox" style="background-color: rgba(${col.r}, ${col.g}, ${col.b}, ${col.opacity}); border-color: ${hex}"></div>`}
<br><img src="../assets/ok.png" width=14%; style="margin-top: 4%" class="gdButton center" onclick="$('.popup').hide()">`)
$('#colorInfo').show()
})
$('#loadingDiv').hide()
$('#analysisDiv').show()
});
</script>