Geoguessr Average Score Display

Shows your average score over a set number of rounds. Displays past rounds with links to their results page.

  1. // ==UserScript==
  2. // @name Geoguessr Average Score Display
  3. // @namespace https://gf.qytechs.cn/en/users/1080671
  4. // @version 0.2.1
  5. // @description Shows your average score over a set number of rounds. Displays past rounds with links to their results page.
  6. // @author Lemson
  7. // @match https://www.geoguessr.com/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=geoguessr.com
  9. // @grant GM_setValue
  10. // @grant GM_getValue
  11. // @run-at document-idle
  12. // @license MIT
  13. // ==/UserScript==
  14.  
  15.  
  16.  
  17. /***********************************************************************************/
  18. /****************YOU NEED TO TURN OFF ANIMATION INGAME FOR THIS TO WORK*************/
  19. /***********************************************************************************/
  20. /**************IF YOU DO NOT TURN OFF ANIMATIONS THE SCRIPT WILL NOT WORK***********/
  21. /***********************************************************************************/
  22.  
  23.  
  24. (function () {
  25. "use strict";
  26.  
  27. // Edit maxEntries to change the number of past games to include.
  28. const maxEntries = 4;
  29.  
  30. //let userId = JSON.parse(document.getElementById('__NEXT_DATA__').innerText).props.accountProps.account.user.userId;
  31.  
  32. const savedData = GM_getValue("savedData", { scores: [], urls: [] }) || { scores: [], urls: [] };
  33. let elementDetected = false;
  34.  
  35. const observer = new MutationObserver((mutations) => {
  36. mutations.forEach((mutation) => {
  37. const targetElements = document.querySelectorAll('[data-qa="final-result-score"] > div');
  38.  
  39. if (targetElements.length > 0) {
  40. if (!elementDetected) {
  41. const childText = targetElements[0].innerText;
  42. const scoreValue = parseInt(childText, 10);
  43. const currentUrl = window.location.href;
  44.  
  45. const urlAlreadySaved = savedData.urls.includes(currentUrl);
  46.  
  47. if (!urlAlreadySaved) {
  48. savedData.scores.push(scoreValue);
  49. savedData.urls.push(currentUrl);
  50.  
  51. if (savedData.scores.length > maxEntries) {
  52. savedData.scores = savedData.scores.slice(savedData.scores.length - maxEntries);
  53. savedData.urls = savedData.urls.slice(savedData.urls.length - maxEntries);
  54. }
  55.  
  56. GM_setValue("savedData", savedData);
  57. }
  58.  
  59. const averageScore = savedData.scores.reduce((sum, value) => sum + value, 0) / savedData.scores.length;
  60.  
  61. displayAverageScore(averageScore);
  62. displayScoresDropdown(savedData);
  63.  
  64. elementDetected = true;
  65. }
  66. } else {
  67. elementDetected = false;
  68. }
  69. });
  70. });
  71.  
  72. //createElement function to make code better look
  73. function createElement(tag, attributes = {}, textContent = "") {
  74. const element = document.createElement(tag);
  75. Object.entries(attributes).forEach(([key, value]) => element.setAttribute(key, value));
  76. element.textContent = textContent;
  77. return element;
  78. }
  79.  
  80. // Show the average score on the screen
  81. function displayAverageScore(averageScore) {
  82. const resultContainer = document.querySelector('div[class^="result-overlay_overlayContent__"]');
  83. const averageScoreDiv = createElement("div", { style: "text-align: center; font-weight: bold;" });
  84. averageScoreDiv.innerHTML = `Average Score: ${averageScore.toFixed(2)} <br> (over ${maxEntries} rounds)`;
  85. resultContainer.appendChild(averageScoreDiv);
  86. }
  87.  
  88. function displayScoresDropdown(data) {
  89. const resultContainer = document.querySelector('div[class^="result-overlay_overlayContent__"]');
  90. const dropdownContainer = createElement("div", { style: "text-align: center;" });
  91. const dropdown = createElement("select", { id: "scoreDropdown" });
  92. dropdown.style.cssText =
  93. "font-weight: bold; background-color: rgba(0,0,0,0.2); color: white; border: 1px black solid; width: 8rem; height: 1rem;text-align: center; border-radius: 2rem";
  94.  
  95. //Put the score sin the dropdown thing.
  96. data.scores.forEach((score, index) => {
  97. const option = createElement("option", { value: index }, `Round ${index + 1}: ${score}`);
  98. option.style = "background-color: black; border:none;";
  99. dropdown.appendChild(option);
  100. });
  101.  
  102. //When user click old round this takes them there.
  103. dropdown.addEventListener("change", (event) => {
  104. const selectedIndex = event.target.value;
  105. const selectedUrl = data.urls[selectedIndex];
  106. window.location.href = selectedUrl;
  107. });
  108.  
  109. dropdownContainer.appendChild(dropdown);
  110. resultContainer.appendChild(dropdownContainer);
  111. }
  112. observer.observe(document.body, { childList: true, subtree: true });
  113. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址