I made a simple chrome extension that shows game card like:dislike percentage values with 2 decimal points, rather than rounded to the nearest 0.
It works on the Games, Group, and Home pages.
Why did I make this?
I wanted this because whenever I release large updates to my games, I like to know if it is shifting the over-all response from users, and in what direction. I have other mediums to collect user input however the majority of users will never contact me directly and will simply like/dislike the game. This saves me the hassle of manually calculating the more precise percentage whenever I want to know it. As games gather more and more total votes, the whole number % value rarely changes, and we must rely on a few decimal points to see actual changes. More popular games would benefit from more decimals, and I will add settings for that in the future if I get around to it.
Get it
You can install the extension here (external chrome web store link)
Disclaimer:
I’ve never attempted to make a chrome extension before, and have very limited knowledge when it comes to JavaScript. The extension uses Roblox web API endpoints to gather +/- votes and I cannot guarantee it’s accurate any further than those said API endpoints can. I’m not aware of any issues running the extension may or may not cause. If Roblox updates their HTML formatting for the game cards, the extension may fail and/or cause issues.
script source if you want to run it unpacked
var CONTAINER_CLASS = '.game-card-container'
var LINK_CLASS = ".game-card-link"
var DECIMAL_POINTS = 2;
var updated = [];
var parser = new DOMParser();
function MakeHttpObject() {
try {return new XMLHttpRequest();}
catch (error) {}
try {return new ActiveXObject("Msxml2.XMLHTTP");}
catch (error) {}
try {return new ActiveXObject("Microsoft.XMLHTTP");}
catch (error) {}
throw new Error("Could not create HTTP request object.");
}
function Update(containerElement) {
var linkElement = containerElement.querySelectorAll(LINK_CLASS)
if (linkElement != null && linkElement[0] != null) {
var linkReference = linkElement[0].href;
if (linkReference != null) {
var placeString = linkReference.match(/PlaceId=\d+/);
if (placeString != null) {
if (updated.includes(placeId) == false) {
var placeId = placeString[0].match(/\d+/)[0];
var request = MakeHttpObject();
if (request != null) {
request.open("GET", 'https://www.roblox.com/places/api-get-details?assetId=' + placeId, true);
request.send(null);
request.onreadystatechange = function() {
if (request.readyState == 4) {
var responseHtml = request.responseText;
var upVotes = parseInt(responseHtml.match(/"TotalUpVotes":\d+/)[0].replace(/"TotalUpVotes":/, ""), 10);
var downVotes = parseInt(responseHtml.match(/"TotalDownVotes":\d+/)[0].replace(/"TotalDownVotes":/, ""), 10);
var total = upVotes + downVotes;
var percent = ((upVotes / total) * 100).toFixed(DECIMAL_POINTS)
var percentElement = containerElement.querySelector(".vote-percentage-label")
if (percentElement != null) {
percentElement.textContent = percent+"%"
}
updated.push(placeId);
}
}
}
}
}
}
}
}
function Run(){
var divs = document.querySelectorAll(CONTAINER_CLASS);
if (divs.length == 0) {
setTimeout(Run, 3);
} else {
for (var i=0; i < divs.length; i++) {
try {
Update(divs[i]);
}
catch(err) {
console.log("ERROR:", err);
}
}
}
}
document.addEventListener("click", function() {
Run();
})
Run();